/[lmdze]/trunk/dyn3d/advn.f
ViewVC logotype

Diff of /trunk/dyn3d/advn.f

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/libf/dyn3d/advn.f revision 66 by guez, Thu Sep 20 13:00:41 2012 UTC trunk/dyn3d/advn.f revision 265 by guez, Tue Mar 20 09:35:59 2018 UTC
# Line 1  Line 1 
 !  
 ! $Header: /home/cvsroot/LMDZ4/libf/dyn3d/advn.F,v 1.1.1.1 2004/05/19 12:53:06 lmdzadmin Exp $  
 !  
       SUBROUTINE advn(q,masse,w,pbaru,pbarv,pdt,mode)  
 c  
 c     Auteur : F. Hourdin  
 c  
 c    ********************************************************************  
 c     Shema  d'advection " pseudo amont " .  
 c    ********************************************************************  
 c     q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....  
 c  
 c   pbaru,pbarv,w flux de masse en u ,v ,w  
 c   pdt pas de temps  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use comconst  
       use disvert_m  
       use conf_gcm_m  
       use comgeom  
       IMPLICIT NONE  
 c  
   
 c  
 c   Arguments:  
 c   ----------  
       integer mode  
       real masse(ip1jmp1,llm)  
       REAL, intent(in):: pbaru( ip1jmp1,llm ),pbarv( ip1jm,llm)  
       REAL q(ip1jmp1,llm)  
       REAL w(ip1jmp1,llm),pdt  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER i,ij,l,j,ii  
       integer ijlqmin,iqmin,jqmin,lqmin  
       integer ismin  
 c  
       real zm(ip1jmp1,llm),newmasse  
       real mu(ip1jmp1,llm)  
       real mv(ip1jm,llm)  
       real mw(ip1jmp1,llm+1)  
       real zq(ip1jmp1,llm),zz,qpn,qps  
       real zqg(ip1jmp1,llm),zqd(ip1jmp1,llm)  
       real zqs(ip1jmp1,llm),zqn(ip1jmp1,llm)  
       real zqh(ip1jmp1,llm),zqb(ip1jmp1,llm)  
       real temps0,temps1,temps2,temps3  
       real ztemps1,ztemps2,ztemps3,ssum  
       logical testcpu  
       save testcpu  
       save temps1,temps2,temps3  
       real zzpbar,zzw  
   
       real qmin,qmax  
       data qmin,qmax/0.,1./  
       data testcpu/.false./  
       data temps1,temps2,temps3/0.,0.,0./  
   
       zzpbar = 0.5 * pdt  
       zzw    = pdt  
   
       DO l=1,llm  
         DO ij = iip2,ip1jm  
             mu(ij,l)=pbaru(ij,l) * zzpbar  
          ENDDO  
          DO ij=1,ip1jm  
             mv(ij,l)=pbarv(ij,l) * zzpbar  
          ENDDO  
          DO ij=1,ip1jmp1  
             mw(ij,l)=w(ij,l) * zzw  
          ENDDO  
       ENDDO  
   
       DO ij=1,ip1jmp1  
          mw(ij,llm+1)=0.  
       ENDDO  
   
       do l=1,llm  
          qpn=0.  
          qps=0.  
          do ij=1,iim  
             qpn=qpn+q(ij,l)*masse(ij,l)  
             qps=qps+q(ip1jm+ij,l)*masse(ip1jm+ij,l)  
          enddo  
          qpn=qpn/ssum(iim,masse(1,l),1)  
          qps=qps/ssum(iim,masse(ip1jm+1,l),1)  
          do ij=1,iip1  
             q(ij,l)=qpn  
             q(ip1jm+ij,l)=qps  
          enddo  
       enddo  
   
       do ij=1,ip1jmp1  
          mw(ij,llm+1)=0.  
       enddo  
       do l=1,llm  
          do ij=1,ip1jmp1  
             zq(ij,l)=q(ij,l)  
             zm(ij,l)=masse(ij,l)  
          enddo  
       enddo  
   
 c     call minmaxq(zq,qmin,qmax,'avant vlx     ')  
       call advnqx(zq,zqg,zqd)  
       call advnx(zq,zqg,zqd,zm,mu,mode)  
       call advnqy(zq,zqs,zqn)  
       call advny(zq,zqs,zqn,zm,mv)  
       call advnqz(zq,zqh,zqb)  
       call advnz(zq,zqh,zqb,zm,mw)  
 c     call vlz(zq,0.,zm,mw)  
       call advnqy(zq,zqs,zqn)  
       call advny(zq,zqs,zqn,zm,mv)  
       call advnqx(zq,zqg,zqd)  
       call advnx(zq,zqg,zqd,zm,mu,mode)  
 c     call minmaxq(zq,qmin,qmax,'apres vlx     ')  
   
       do l=1,llm  
          do ij=1,ip1jmp1  
            q(ij,l)=zq(ij,l)  
          enddo  
          do ij=1,ip1jm+1,iip1  
             q(ij+iim,l)=q(ij,l)  
          enddo  
       enddo  
   
       RETURN  
       END  
   
       SUBROUTINE advnqx(q,qg,qd)  
 c  
 c     Auteurs:   Calcul des valeurs de q aux point u.  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       real q(ip1jmp1,llm),qg(ip1jmp1,llm),qd(ip1jmp1,llm)  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER ij,l  
 c  
       real dxqu(ip1jmp1),zqu(ip1jmp1)  
       real zqmax(ip1jmp1),zqmin(ip1jmp1)  
       logical extremum(ip1jmp1)  
   
       integer mode  
       save mode  
       data mode/1/  
   
 c   calcul des pentes en u:  
 c   -----------------------  
       if (mode.eq.0) then  
          do l=1,llm  
             do ij=1,ip1jm  
                qd(ij,l)=q(ij,l)  
                qg(ij,l)=q(ij,l)  
             enddo  
          enddo  
       else  
       do l = 1, llm  
          do ij=iip2,ip1jm-1  
             dxqu(ij)=q(ij+1,l)-q(ij,l)  
             zqu(ij)=0.5*(q(ij+1,l)+q(ij,l))  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             dxqu(ij)=dxqu(ij-iim)  
             zqu(ij)=zqu(ij-iim)  
          enddo  
          do ij=iip2,ip1jm-1  
             zqu(ij)=zqu(ij)-dxqu(ij+1)/12.  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             zqu(ij)=zqu(ij-iim)  
          enddo  
          do ij=iip2+1,ip1jm  
             zqu(ij)=zqu(ij)+dxqu(ij-1)/12.  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             zqu(ij-iim)=zqu(ij)  
          enddo  
   
 c   calcul des valeurs max et min acceptees aux interfaces  
   
          do ij=iip2,ip1jm-1  
             zqmax(ij)=max(q(ij+1,l),q(ij,l))  
             zqmin(ij)=min(q(ij+1,l),q(ij,l))  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             zqmax(ij)=zqmax(ij-iim)  
             zqmin(ij)=zqmin(ij-iim)  
          enddo  
          do ij=iip2+1,ip1jm  
             extremum(ij)=dxqu(ij)*dxqu(ij-1).le.0.  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             extremum(ij-iim)=extremum(ij)  
          enddo  
          do ij=iip2,ip1jm  
             zqu(ij)=min(max(zqmin(ij),zqu(ij)),zqmax(ij))  
          enddo  
          do ij=iip2+1,ip1jm  
             if(extremum(ij)) then  
                qg(ij,l)=q(ij,l)  
                qd(ij,l)=q(ij,l)  
             else  
                qd(ij,l)=zqu(ij)  
                qg(ij,l)=zqu(ij-1)  
             endif  
          enddo  
          do ij=iip1+iip1,ip1jm,iip1  
             qd(ij-iim,l)=qd(ij,l)  
             qg(ij-iim,l)=qg(ij,l)  
          enddo  
   
          goto 8888  
   
          do ij=iip2+1,ip1jm  
             if(extremum(ij).and..not.extremum(ij-1))  
      s         qd(ij-1,l)=q(ij,l)  
          enddo  
   
          do ij=iip1+iip1,ip1jm,iip1  
             qd(ij-iim,l)=qd(ij,l)  
          enddo  
          do ij=iip2,ip1jm-1  
             if (extremum(ij).and..not.extremum(ij+1))  
      s         qg(ij+1,l)=q(ij,l)  
          enddo  
   
          do ij=iip1+iip1,ip1jm,iip1  
             qg(ij,l)=qg(ij-iim,l)  
          enddo  
 8888     continue  
       enddo  
       endif  
       RETURN  
       END  
       SUBROUTINE advnqy(q,qs,qn)  
 c  
 c     Auteurs:   Calcul des valeurs de q aux point v.  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       real q(ip1jmp1,llm),qs(ip1jmp1,llm),qn(ip1jmp1,llm)  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER ij,l  
 c  
       real dyqv(ip1jm),zqv(ip1jm,llm)  
       real zqmax(ip1jm),zqmin(ip1jm)  
       logical extremum(ip1jmp1)  
   
       integer mode  
       save mode  
       data mode/1/  
   
       if (mode.eq.0) then  
          do l=1,llm  
             do ij=1,ip1jmp1  
                qn(ij,l)=q(ij,l)  
                qs(ij,l)=q(ij,l)  
             enddo  
          enddo  
       else  
   
 c   calcul des pentes en u:  
 c   -----------------------  
       do l = 1, llm  
          do ij=1,ip1jm  
             dyqv(ij)=q(ij,l)-q(ij+iip1,l)  
          enddo  
   
          do ij=iip2,ip1jm-iip1  
             zqv(ij,l)=0.5*(q(ij+iip1,l)+q(ij,l))  
             zqv(ij,l)=zqv(ij,l)+(dyqv(ij+iip1)-dyqv(ij-iip1))/12.  
          enddo  
   
          do ij=iip2,ip1jm  
             extremum(ij)=dyqv(ij)*dyqv(ij-iip1).le.0.  
          enddo  
   
 c Pas de pentes aux poles  
          do ij=1,iip1  
             zqv(ij,l)=q(ij,l)  
             zqv(ip1jm-iip1+ij,l)=q(ip1jm+ij,l)  
             extremum(ij)=.true.  
             extremum(ip1jmp1-iip1+ij)=.true.  
          enddo  
   
 c   calcul des valeurs max et min acceptees aux interfaces  
          do ij=1,ip1jm  
             zqmax(ij)=max(q(ij+iip1,l),q(ij,l))  
             zqmin(ij)=min(q(ij+iip1,l),q(ij,l))  
          enddo  
   
          do ij=1,ip1jm  
             zqv(ij,l)=min(max(zqmin(ij),zqv(ij,l)),zqmax(ij))  
          enddo  
   
          do ij=iip2,ip1jm  
             if(extremum(ij)) then  
                qs(ij,l)=q(ij,l)  
                qn(ij,l)=q(ij,l)  
 c              if (.not.extremum(ij-iip1)) qs(ij-iip1,l)=q(ij,l)  
 c              if (.not.extremum(ij+iip1)) qn(ij+iip1,l)=q(ij,l)  
             else  
                qs(ij,l)=zqv(ij,l)  
                qn(ij,l)=zqv(ij-iip1,l)  
             endif  
          enddo  
   
          do ij=1,iip1  
             qs(ij,l)=q(ij,l)  
             qn(ij,l)=q(ij,l)  
             qs(ip1jm+ij,l)=q(ip1jm+ij,l)  
             qn(ip1jm+ij,l)=q(ip1jm+ij,l)  
          enddo  
   
       enddo  
       endif  
       RETURN  
       END  
   
       SUBROUTINE advnqz(q,qh,qb)  
 c  
 c     Auteurs:   Calcul des valeurs de q aux point v.  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       real q(ip1jmp1,llm),qh(ip1jmp1,llm),qb(ip1jmp1,llm)  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER ij,l  
 c  
       real dzqw(ip1jmp1,llm+1),zqw(ip1jmp1,llm+1)  
       real zqmax(ip1jmp1,llm),zqmin(ip1jmp1,llm)  
       logical extremum(ip1jmp1,llm)  
   
       integer mode  
       save mode  
   
       data mode/1/  
   
 c   calcul des pentes en u:  
 c   -----------------------  
   
       if (mode.eq.0) then  
          do l=1,llm  
             do ij=1,ip1jmp1  
                qb(ij,l)=q(ij,l)  
                qh(ij,l)=q(ij,l)  
             enddo  
          enddo  
       else  
       do l = 2, llm  
          do ij=1,ip1jmp1  
             dzqw(ij,l)=q(ij,l-1)-q(ij,l)  
             zqw(ij,l)=0.5*(q(ij,l-1)+q(ij,l))  
          enddo  
       enddo  
       do ij=1,ip1jmp1  
          dzqw(ij,1)=0.  
          dzqw(ij,llm+1)=0.  
       enddo  
       do l=2,llm  
          do ij=1,ip1jmp1  
             zqw(ij,l)=zqw(ij,l)+(dzqw(ij,l+1)-dzqw(ij,l-1))/12.  
          enddo  
       enddo  
       do l=2,llm-1  
          do ij=1,ip1jmp1  
             extremum(ij,l)=dzqw(ij,l)*dzqw(ij,l+1).le.0.  
          enddo  
       enddo  
   
 c Pas de pentes en bas et en haut  
          do ij=1,ip1jmp1  
             zqw(ij,2)=q(ij,1)  
             zqw(ij,llm)=q(ij,llm)  
             extremum(ij,1)=.true.  
             extremum(ij,llm)=.true.  
          enddo  
   
 c   calcul des valeurs max et min acceptees aux interfaces  
       do l=2,llm  
          do ij=1,ip1jmp1  
             zqmax(ij,l)=max(q(ij,l-1),q(ij,l))  
             zqmin(ij,l)=min(q(ij,l-1),q(ij,l))  
          enddo  
       enddo  
   
       do l=2,llm  
          do ij=1,ip1jmp1  
             zqw(ij,l)=min(max(zqmin(ij,l),zqw(ij,l)),zqmax(ij,l))  
          enddo  
       enddo  
   
       do l=2,llm-1  
          do ij=1,ip1jmp1  
             if(extremum(ij,l)) then  
                qh(ij,l)=q(ij,l)  
                qb(ij,l)=q(ij,l)  
             else  
                qh(ij,l)=zqw(ij,l+1)  
                qb(ij,l)=zqw(ij,l)  
             endif  
          enddo  
       enddo  
 c     do l=2,llm-1  
 c        do ij=1,ip1jmp1  
 c           if(extremum(ij,l)) then  
 c              if (.not.extremum(ij,l-1)) qh(ij,l-1)=q(ij,l)  
 c              if (.not.extremum(ij,l+1)) qb(ij,l+1)=q(ij,l)  
 c           endif  
 c        enddo  
 c     enddo  
   
       do ij=1,ip1jmp1  
          qb(ij,1)=q(ij,1)  
          qh(ij,1)=q(ij,1)  
          qb(ij,llm)=q(ij,llm)  
          qh(ij,llm)=q(ij,llm)  
       enddo  
   
       endif  
   
       RETURN  
       END  
   
       SUBROUTINE advnx(q,qg,qd,masse,u_m,mode)  
 c  
 c     Auteur : F. Hourdin  
 c  
 c    ********************************************************************  
 c     Shema  d'advection " pseudo amont " .  
 c    ********************************************************************  
 c     nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....  
 c  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use comconst  
       use disvert_m  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       integer mode  
       real masse(ip1jmp1,llm)  
       real u_m( ip1jmp1,llm )  
       real q(ip1jmp1,llm),qd(ip1jmp1,llm),qg(ip1jmp1,llm)  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER i,j,ij,l,indu(ip1jmp1),niju,iju,ijq  
       integer n0,nl(llm)  
 c  
       real new_m,zu_m,zdq,zz  
       real zsigg(ip1jmp1,llm),zsigd(ip1jmp1,llm),zsig  
       real u_mq(ip1jmp1,llm)  
   
       real zm,zq,zsigm,zsigp,zqm,zqp,zu  
   
       logical ladvplus(ip1jmp1,llm)  
   
       real prec  
       save prec  
   
       data prec/1.e-15/  
   
       do l=1,llm  
             do ij=iip2,ip1jm  
                zdq=qd(ij,l)-qg(ij,l)  
                if(abs(zdq).gt.prec) then  
                   zsigd(ij,l)=(q(ij,l)-qg(ij,l))/zdq  
                   zsigg(ij,l)=1.-zsigd(ij,l)  
                else  
                   zsigd(ij,l)=0.5  
                   zsigg(ij,l)=0.5  
                   qd(ij,l)=q(ij,l)  
                   qg(ij,l)=q(ij,l)  
                endif  
             enddo  
        enddo  
   
 c   calcul de la pente maximum dans la maille en valeur absolue  
   
        do l=1,llm  
        do ij=iip2,ip1jm-1  
           if (u_m(ij,l).ge.0.) then  
              zsigp=zsigd(ij,l)  
              zsigm=zsigg(ij,l)  
              zqp=qd(ij,l)  
              zqm=qg(ij,l)  
              zm=masse(ij,l)  
              zq=q(ij,l)  
           else  
              zsigm=zsigd(ij+1,l)  
              zsigp=zsigg(ij+1,l)  
              zqm=qd(ij+1,l)  
              zqp=qg(ij+1,l)  
              zm=masse(ij+1,l)  
              zq=q(ij+1,l)  
           endif  
           zu=abs(u_m(ij,l))  
           ladvplus(ij,l)=zu.gt.zm  
           zsig=zu/zm  
           if(zsig.eq.0.) zsigp=0.1  
           if (mode.eq.1) then  
              if (zsig.le.zsigp) then  
                  u_mq(ij,l)=u_m(ij,l)*zqp  
              else if (mode.eq.1) then  
                  u_mq(ij,l)=  
      s           sign(zm,u_m(ij,l))*(zsigp*zqp+(zsig-zsigp)*zqm)  
              endif  
           else  
              if (zsig.le.zsigp) then  
                  u_mq(ij,l)=u_m(ij,l)*(zqp-0.5*zsig/zsigp*(zqp-zq))  
              else  
                 zz=0.5*(zsig-zsigp)/zsigm  
                 u_mq(ij,l)=sign(zm,u_m(ij,l))*( 0.5*(zq+zqp)*zsigp  
      s          +(zsig-zsigp)*(zq+zz*(zqm-zq)) )  
              endif  
           endif  
       enddo  
       enddo  
   
       do l=1,llm  
        do ij=iip1+iip1,ip1jm,iip1  
           u_mq(ij,l)=u_mq(ij-iim,l)  
           ladvplus(ij,l)=ladvplus(ij-iim,l)  
        enddo  
       enddo  
   
 c=================================================================  
 C   SCHEMA SEMI-LAGRAGIEN EN X DANS LES REGIONS POLAIRES  
 c=================================================================  
 c   tris des regions a traiter  
       n0=0  
       do l=1,llm  
          nl(l)=0  
          do ij=iip2,ip1jm  
             if(ladvplus(ij,l)) then  
                nl(l)=nl(l)+1  
                u_mq(ij,l)=0.  
             endif  
          enddo  
          n0=n0+nl(l)  
       enddo  
   
       if(n0.gt.1) then  
       IF (prt_level > 9) print *,  
      & 'Nombre de points pour lesquels on advect plus que le'  
      &       ,'contenu de la maille : ',n0  
   
          do l=1,llm  
             if(nl(l).gt.0) then  
                iju=0  
 c   indicage des mailles concernees par le traitement special  
                do ij=iip2,ip1jm  
                   if(ladvplus(ij,l).and.mod(ij,iip1).ne.0) then  
                      iju=iju+1  
                      indu(iju)=ij  
                   endif  
                enddo  
                niju=iju  
   
 c  traitement des mailles  
                do iju=1,niju  
                   ij=indu(iju)  
                   j=(ij-1)/iip1+1  
                   zu_m=u_m(ij,l)  
                   u_mq(ij,l)=0.  
                   if(zu_m.gt.0.) then  
                      ijq=ij  
                      i=ijq-(j-1)*iip1  
 c   accumulation pour les mailles completements advectees  
                      do while(zu_m.gt.masse(ijq,l))  
                         u_mq(ij,l)=u_mq(ij,l)+q(ijq,l)*masse(ijq,l)  
                         zu_m=zu_m-masse(ijq,l)  
                         i=mod(i-2+iim,iim)+1  
                         ijq=(j-1)*iip1+i  
                      enddo  
 c   MODIFS SPECIFIQUES DU SCHEMA  
 c   ajout de la maille non completement advectee  
              zsig=zu_m/masse(ijq,l)  
              if(zsig.le.zsigd(ijq,l)) then  
                 u_mq(ij,l)=u_mq(ij,l)+zu_m*(qd(ijq,l)  
      s          -0.5*zsig/zsigd(ijq,l)*(qd(ijq,l)-q(ijq,l)))  
              else  
 c               u_mq(ij,l)=u_mq(ij,l)+zu_m*q(ijq,l)  
 c         goto 8888  
                 zz=0.5*(zsig-zsigd(ijq,l))/zsigg(ijq,l)  
                 if(.not.(zz.gt.0..and.zz.le.0.5)) then  
                      print *,'probleme2 au point ij=',ij,  
      s               '  l=',l  
                      print *,'zz=',zz  
                      stop  
                 endif  
                 u_mq(ij,l)=u_mq(ij,l)+masse(ijq,l)*(  
      s          0.5*(q(ijq,l)+qd(ijq,l))*zsigd(ijq,l)  
      s        +(zsig-zsigd(ijq,l))*(q(ijq,l)+zz*(qg(ijq,l)-q(ijq,l))) )  
              endif  
                   else  
                      ijq=ij+1  
                      i=ijq-(j-1)*iip1  
 c   accumulation pour les mailles completements advectees  
                      do while(-zu_m.gt.masse(ijq,l))  
                         u_mq(ij,l)=u_mq(ij,l)-q(ijq,l)*masse(ijq,l)  
                         zu_m=zu_m+masse(ijq,l)  
                         i=mod(i,iim)+1  
                         ijq=(j-1)*iip1+i  
                      enddo  
 c   ajout de la maille non completement advectee  
 c 2eme MODIF SPECIFIQUE  
              zsig=-zu_m/masse(ij+1,l)  
              if(zsig.le.zsigg(ijq,l)) then  
                 u_mq(ij,l)=u_mq(ij,l)+zu_m*(qg(ijq,l)  
      s          -0.5*zsig/zsigg(ijq,l)*(qg(ijq,l)-q(ijq,l)))  
              else  
 c               u_mq(ij,l)=u_mq(ij,l)+zu_m*q(ijq,l)  
 c           goto 9999  
                 zz=0.5*(zsig-zsigg(ijq,l))/zsigd(ijq,l)  
                 if(.not.(zz.gt.0..and.zz.le.0.5)) then  
                      print *,'probleme22 au point ij=',ij  
      s               ,'  l=',l  
                      print *,'zz=',zz  
                      stop  
                 endif  
                 u_mq(ij,l)=u_mq(ij,l)-masse(ijq,l)*(  
      s          0.5*(q(ijq,l)+qg(ijq,l))*zsigg(ijq,l)  
      s          +(zsig-zsigg(ijq,l))*  
      s           (q(ijq,l)+zz*(qd(ijq,l)-q(ijq,l))) )  
              endif  
 c   fin de la modif  
                   endif  
                enddo  
             endif  
          enddo  
       endif  ! n0.gt.0  
   
 c   bouclage en latitude  
       do l=1,llm  
         do ij=iip1+iip1,ip1jm,iip1  
            u_mq(ij,l)=u_mq(ij-iim,l)  
         enddo  
       enddo  
   
 c=================================================================  
 c   CALCUL DE LA CONVERGENCE DES FLUX  
 c=================================================================  
   
       do l=1,llm  
          do ij=iip2+1,ip1jm  
             new_m=masse(ij,l)+u_m(ij-1,l)-u_m(ij,l)  
             q(ij,l)=(q(ij,l)*masse(ij,l)+  
      &      u_mq(ij-1,l)-u_mq(ij,l))  
      &      /new_m  
             masse(ij,l)=new_m  
          enddo  
 c   Modif Fred 22 03 96 correction d'un bug (les scopy ci-dessous)  
          do ij=iip1+iip1,ip1jm,iip1  
             q(ij-iim,l)=q(ij,l)  
             masse(ij-iim,l)=masse(ij,l)  
          enddo  
       enddo  
   
       RETURN  
       END  
       SUBROUTINE advny(q,qs,qn,masse,v_m)  
 c  
 c     Auteur : F. Hourdin  
 c  
 c    ********************************************************************  
 c     Shema  d'advection " pseudo amont " .  
 c    ********************************************************************  
 c     nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....  
 c  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use comgeom  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       real masse(ip1jmp1,llm)  
       real v_m( ip1jm,llm )  
       real q(ip1jmp1,llm),qn(ip1jmp1,llm),qs(ip1jmp1,llm)  
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER ij,l  
 c  
       real new_m,zdq,zz  
       real zsigs(ip1jmp1),zsign(ip1jmp1),zsig  
       real v_mq(ip1jm,llm)  
       real convpn,convps,convmpn,convmps,massen,masses  
       real zm,zq,zsigm,zsigp,zqm,zqp  
       real ssum  
       real prec  
       save prec  
   
       data prec/1.e-15/  
       do l=1,llm  
             do ij=1,ip1jmp1  
                zdq=qn(ij,l)-qs(ij,l)  
                if(abs(zdq).gt.prec) then  
                   zsign(ij)=(q(ij,l)-qs(ij,l))/zdq  
                   zsigs(ij)=1.-zsign(ij)  
                else  
                   zsign(ij)=0.5  
                   zsigs(ij)=0.5  
                endif  
             enddo  
   
 c   calcul de la pente maximum dans la maille en valeur absolue  
   
        do ij=1,ip1jm  
           if (v_m(ij,l).ge.0.) then  
              zsigp=zsign(ij+iip1)  
              zsigm=zsigs(ij+iip1)  
              zqp=qn(ij+iip1,l)  
              zqm=qs(ij+iip1,l)  
              zm=masse(ij+iip1,l)  
              zq=q(ij+iip1,l)  
           else  
              zsigm=zsign(ij)  
              zsigp=zsigs(ij)  
              zqm=qn(ij,l)  
              zqp=qs(ij,l)  
              zm=masse(ij,l)  
              zq=q(ij,l)  
           endif  
           zsig=abs(v_m(ij,l))/zm  
           if(zsig.eq.0.) zsigp=0.1  
           if (zsig.le.zsigp) then  
               v_mq(ij,l)=v_m(ij,l)*(zqp-0.5*zsig/zsigp*(zqp-zq))  
           else  
               zz=0.5*(zsig-zsigp)/zsigm  
               v_mq(ij,l)=sign(zm,v_m(ij,l))*( 0.5*(zq+zqp)*zsigp  
      s        +(zsig-zsigp)*(zq+zz*(zqm-zq)) )  
           endif  
        enddo  
       enddo  
   
       do l=1,llm  
          do ij=iip2,ip1jm  
             new_m=masse(ij,l)  
      &      +v_m(ij,l)-v_m(ij-iip1,l)  
             q(ij,l)=(q(ij,l)*masse(ij,l)+v_mq(ij,l)-v_mq(ij-iip1,l))  
      &         /new_m  
             masse(ij,l)=new_m  
          enddo  
 c.-. ancienne version  
          convpn=SSUM(iim,v_mq(1,l),1)  
          convmpn=ssum(iim,v_m(1,l),1)  
          massen=ssum(iim,masse(1,l),1)  
          new_m=massen+convmpn  
          q(1,l)=(q(1,l)*massen+convpn)/new_m  
          do ij = 1,iip1  
             q(ij,l)=q(1,l)  
             masse(ij,l)=new_m*aire(ij)/apoln  
          enddo  
   
          convps=-SSUM(iim,v_mq(ip1jm-iim,l),1)  
          convmps=-ssum(iim,v_m(ip1jm-iim,l),1)  
          masses=ssum(iim,masse(ip1jm+1,l),1)  
          new_m=masses+convmps  
          q(ip1jm+1,l)=(q(ip1jm+1,l)*masses+convps)/new_m  
          do ij = ip1jm+1,ip1jmp1  
             q(ij,l)=q(ip1jm+1,l)  
             masse(ij,l)=new_m*aire(ij)/apols  
          enddo  
       enddo  
   
       RETURN  
       END  
       SUBROUTINE advnz(q,qh,qb,masse,w_m)  
 c  
 c     Auteurs:   F.Hourdin  
 c  
 c    ********************************************************************  
 c     Shema  d'advection " pseudo amont " .  
 c     b designe le bas et h le haut  
 c     il y a une correspondance entre le b en z et le d en x  
 c    ********************************************************************  
 c  
 c  
 c   --------------------------------------------------------------------  
       use dimens_m  
       use paramet_m  
       use comgeom  
       use conf_gcm_m  
       IMPLICIT NONE  
 c  
 c  
 c  
 c   Arguments:  
 c   ----------  
       real masse(ip1jmp1,llm)  
       real w_m( ip1jmp1,llm+1)  
       real q(ip1jmp1,llm),qb(ip1jmp1,llm),qh(ip1jmp1,llm)  
   
 c  
 c      Local  
 c   ---------  
 c  
       INTEGER ij,l  
 c  
       real new_m,zdq,zz  
       real zsigh(ip1jmp1,llm),zsigb(ip1jmp1,llm),zsig  
       real w_mq(ip1jmp1,llm+1)  
       real zm,zq,zsigm,zsigp,zqm,zqp  
       real prec  
       save prec  
   
       data prec/1.e-13/  
   
       do l=1,llm  
             do ij=1,ip1jmp1  
                zdq=qb(ij,l)-qh(ij,l)  
                if(abs(zdq).gt.prec) then  
                   zsigb(ij,l)=(q(ij,l)-qh(ij,l))/zdq  
                   zsigh(ij,l)=1.-zsigb(ij,l)  
                   zsigb(ij,l)=min(max(zsigb(ij,l),0.),1.)  
                else  
                   zsigb(ij,l)=0.5  
                   zsigh(ij,l)=0.5  
                endif  
             enddo  
        enddo  
   
 c   calcul de la pente maximum dans la maille en valeur absolue  
        do l=2,llm  
        do ij=1,ip1jmp1  
           if (w_m(ij,l).ge.0.) then  
              zsigp=zsigb(ij,l)  
              zsigm=zsigh(ij,l)  
              zqp=qb(ij,l)  
              zqm=qh(ij,l)  
              zm=masse(ij,l)  
              zq=q(ij,l)  
           else  
              zsigm=zsigb(ij,l-1)  
              zsigp=zsigh(ij,l-1)  
              zqm=qb(ij,l-1)  
              zqp=qh(ij,l-1)  
              zm=masse(ij,l-1)  
              zq=q(ij,l-1)  
           endif  
           zsig=abs(w_m(ij,l))/zm  
           if(zsig.eq.0.) zsigp=0.1  
           if (zsig.le.zsigp) then  
               w_mq(ij,l)=w_m(ij,l)*(zqp-0.5*zsig/zsigp*(zqp-zq))  
           else  
               zz=0.5*(zsig-zsigp)/zsigm  
               w_mq(ij,l)=sign(zm,w_m(ij,l))*( 0.5*(zq+zqp)*zsigp  
      s        +(zsig-zsigp)*(zq+zz*(zqm-zq)) )  
           endif  
       enddo  
       enddo  
   
        do ij=1,ip1jmp1  
           w_mq(ij,llm+1)=0.  
           w_mq(ij,1)=0.  
        enddo  
   
       do l=1,llm  
          do ij=1,ip1jmp1  
             new_m=masse(ij,l)+w_m(ij,l+1)-w_m(ij,l)  
             q(ij,l)=(q(ij,l)*masse(ij,l)+w_mq(ij,l+1)-w_mq(ij,l))  
      &         /new_m  
             masse(ij,l)=new_m  
          enddo  
       enddo  
1    
2        END  ! $Header: /home/cvsroot/LMDZ4/libf/dyn3d/advn.F,v 1.1.1.1 2004/05/19
3    ! 12:53:06 lmdzadmin Exp $
4    
5    SUBROUTINE advn(q, masse, w, pbaru, pbarv, pdt, mode)
6    
7      ! Auteur : F. Hourdin
8    
9      ! ********************************************************************
10      ! Shema  d'advection " pseudo amont " .
11      ! ********************************************************************
12      ! q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
13    
14      ! pbaru,pbarv,w flux de masse en u ,v ,w
15      ! pdt pas de temps
16    
17      ! --------------------------------------------------------------------
18      USE dimensions
19      USE paramet_m
20      USE comconst
21      USE disvert_m
22      USE conf_gcm_m
23      USE comgeom
24      IMPLICIT NONE
25    
26    
27    
28      ! Arguments:
29      ! ----------
30      INTEGER mode
31      REAL masse(ip1jmp1, llm)
32      REAL, INTENT (IN) :: pbaru(ip1jmp1, llm), pbarv(ip1jm, llm)
33      REAL q(ip1jmp1, llm)
34      REAL w(ip1jmp1, llm), pdt
35    
36      ! Local
37      ! ---------
38    
39      INTEGER ij, l
40      REAL zm(ip1jmp1, llm)
41      REAL mu(ip1jmp1, llm)
42      REAL mv(ip1jm, llm)
43      REAL mw(ip1jmp1, llm+1)
44      REAL zq(ip1jmp1, llm), qpn, qps
45      REAL zqg(ip1jmp1, llm), zqd(ip1jmp1, llm)
46      REAL zqs(ip1jmp1, llm), zqn(ip1jmp1, llm)
47      REAL zqh(ip1jmp1, llm), zqb(ip1jmp1, llm)
48      REAL ssum
49      REAL zzpbar, zzw
50    
51      zzpbar = 0.5*pdt
52      zzw = pdt
53    
54      DO l = 1, llm
55        DO ij = iip2, ip1jm
56          mu(ij, l) = pbaru(ij, l)*zzpbar
57        END DO
58        DO ij = 1, ip1jm
59          mv(ij, l) = pbarv(ij, l)*zzpbar
60        END DO
61        DO ij = 1, ip1jmp1
62          mw(ij, l) = w(ij, l)*zzw
63        END DO
64      END DO
65    
66      DO ij = 1, ip1jmp1
67        mw(ij, llm+1) = 0.
68      END DO
69    
70      DO l = 1, llm
71        qpn = 0.
72        qps = 0.
73        DO ij = 1, iim
74          qpn = qpn + q(ij, l)*masse(ij, l)
75          qps = qps + q(ip1jm+ij, l)*masse(ip1jm+ij, l)
76        END DO
77        qpn = qpn/ssum(iim, masse(1,l), 1)
78        qps = qps/ssum(iim, masse(ip1jm+1,l), 1)
79        DO ij = 1, iip1
80          q(ij, l) = qpn
81          q(ip1jm+ij, l) = qps
82        END DO
83      END DO
84    
85      DO ij = 1, ip1jmp1
86        mw(ij, llm+1) = 0.
87      END DO
88      DO l = 1, llm
89        DO ij = 1, ip1jmp1
90          zq(ij, l) = q(ij, l)
91          zm(ij, l) = masse(ij, l)
92        END DO
93      END DO
94    
95      ! call minmaxq(zq,qmin,qmax,'avant vlx     ')
96      CALL advnqx(zq, zqg, zqd)
97      CALL advnx(zq, zqg, zqd, zm, mu, mode)
98      CALL advnqy(zq, zqs, zqn)
99      CALL advny(zq, zqs, zqn, zm, mv)
100      CALL advnqz(zq, zqh, zqb)
101      CALL advnz(zq, zqh, zqb, zm, mw)
102      ! call vlz(zq,0.,zm,mw)
103      CALL advnqy(zq, zqs, zqn)
104      CALL advny(zq, zqs, zqn, zm, mv)
105      CALL advnqx(zq, zqg, zqd)
106      CALL advnx(zq, zqg, zqd, zm, mu, mode)
107      ! call minmaxq(zq,qmin,qmax,'apres vlx     ')
108    
109      DO l = 1, llm
110        DO ij = 1, ip1jmp1
111          q(ij, l) = zq(ij, l)
112        END DO
113        DO ij = 1, ip1jm + 1, iip1
114          q(ij+iim, l) = q(ij, l)
115        END DO
116      END DO
117    
118      RETURN
119    END SUBROUTINE advn
120    
121    SUBROUTINE advnqx(q, qg, qd)
122    
123      ! Auteurs:   Calcul des valeurs de q aux point u.
124    
125      ! --------------------------------------------------------------------
126      USE dimensions
127      USE paramet_m
128      USE conf_gcm_m
129      IMPLICIT NONE
130    
131    
132    
133      ! Arguments:
134      ! ----------
135      REAL q(ip1jmp1, llm), qg(ip1jmp1, llm), qd(ip1jmp1, llm)
136    
137      ! Local
138      ! ---------
139    
140      INTEGER ij, l
141    
142      REAL dxqu(ip1jmp1), zqu(ip1jmp1)
143      REAL zqmax(ip1jmp1), zqmin(ip1jmp1)
144      LOGICAL extremum(ip1jmp1)
145    
146      INTEGER mode
147      SAVE mode
148      DATA mode/1/
149    
150      ! calcul des pentes en u:
151      ! -----------------------
152      IF (mode==0) THEN
153        DO l = 1, llm
154          DO ij = 1, ip1jm
155            qd(ij, l) = q(ij, l)
156            qg(ij, l) = q(ij, l)
157          END DO
158        END DO
159      ELSE
160        DO l = 1, llm
161          DO ij = iip2, ip1jm - 1
162            dxqu(ij) = q(ij+1, l) - q(ij, l)
163            zqu(ij) = 0.5*(q(ij+1,l)+q(ij,l))
164          END DO
165          DO ij = iip1 + iip1, ip1jm, iip1
166            dxqu(ij) = dxqu(ij-iim)
167            zqu(ij) = zqu(ij-iim)
168          END DO
169          DO ij = iip2, ip1jm - 1
170            zqu(ij) = zqu(ij) - dxqu(ij+1)/12.
171          END DO
172          DO ij = iip1 + iip1, ip1jm, iip1
173            zqu(ij) = zqu(ij-iim)
174          END DO
175          DO ij = iip2 + 1, ip1jm
176            zqu(ij) = zqu(ij) + dxqu(ij-1)/12.
177          END DO
178          DO ij = iip1 + iip1, ip1jm, iip1
179            zqu(ij-iim) = zqu(ij)
180          END DO
181    
182          ! calcul des valeurs max et min acceptees aux interfaces
183    
184          DO ij = iip2, ip1jm - 1
185            zqmax(ij) = max(q(ij+1,l), q(ij,l))
186            zqmin(ij) = min(q(ij+1,l), q(ij,l))
187          END DO
188          DO ij = iip1 + iip1, ip1jm, iip1
189            zqmax(ij) = zqmax(ij-iim)
190            zqmin(ij) = zqmin(ij-iim)
191          END DO
192          DO ij = iip2 + 1, ip1jm
193            extremum(ij) = dxqu(ij)*dxqu(ij-1) <= 0.
194          END DO
195          DO ij = iip1 + iip1, ip1jm, iip1
196            extremum(ij-iim) = extremum(ij)
197          END DO
198          DO ij = iip2, ip1jm
199            zqu(ij) = min(max(zqmin(ij),zqu(ij)), zqmax(ij))
200          END DO
201          DO ij = iip2 + 1, ip1jm
202            IF (extremum(ij)) THEN
203              qg(ij, l) = q(ij, l)
204              qd(ij, l) = q(ij, l)
205            ELSE
206              qd(ij, l) = zqu(ij)
207              qg(ij, l) = zqu(ij-1)
208            END IF
209          END DO
210          DO ij = iip1 + iip1, ip1jm, iip1
211            qd(ij-iim, l) = qd(ij, l)
212            qg(ij-iim, l) = qg(ij, l)
213          END DO
214    
215          GO TO 8888
216    
217          DO ij = iip2 + 1, ip1jm
218            IF (extremum(ij) .AND. .NOT. extremum(ij-1)) qd(ij-1, l) = q(ij, l)
219          END DO
220    
221          DO ij = iip1 + iip1, ip1jm, iip1
222            qd(ij-iim, l) = qd(ij, l)
223          END DO
224          DO ij = iip2, ip1jm - 1
225            IF (extremum(ij) .AND. .NOT. extremum(ij+1)) qg(ij+1, l) = q(ij, l)
226          END DO
227    
228          DO ij = iip1 + iip1, ip1jm, iip1
229            qg(ij, l) = qg(ij-iim, l)
230          END DO
231    8888  CONTINUE
232        END DO
233      END IF
234      RETURN
235    END SUBROUTINE advnqx
236    SUBROUTINE advnqy(q, qs, qn)
237    
238      ! Auteurs:   Calcul des valeurs de q aux point v.
239    
240      ! --------------------------------------------------------------------
241      USE dimensions
242      USE paramet_m
243      USE conf_gcm_m
244      IMPLICIT NONE
245    
246    
247    
248      ! Arguments:
249      ! ----------
250      REAL q(ip1jmp1, llm), qs(ip1jmp1, llm), qn(ip1jmp1, llm)
251    
252      ! Local
253      ! ---------
254    
255      INTEGER ij, l
256    
257      REAL dyqv(ip1jm), zqv(ip1jm, llm)
258      REAL zqmax(ip1jm), zqmin(ip1jm)
259      LOGICAL extremum(ip1jmp1)
260    
261      INTEGER mode
262      SAVE mode
263      DATA mode/1/
264    
265      IF (mode==0) THEN
266        DO l = 1, llm
267          DO ij = 1, ip1jmp1
268            qn(ij, l) = q(ij, l)
269            qs(ij, l) = q(ij, l)
270          END DO
271        END DO
272      ELSE
273    
274        ! calcul des pentes en u:
275        ! -----------------------
276        DO l = 1, llm
277          DO ij = 1, ip1jm
278            dyqv(ij) = q(ij, l) - q(ij+iip1, l)
279          END DO
280    
281          DO ij = iip2, ip1jm - iip1
282            zqv(ij, l) = 0.5*(q(ij+iip1,l)+q(ij,l))
283            zqv(ij, l) = zqv(ij, l) + (dyqv(ij+iip1)-dyqv(ij-iip1))/12.
284          END DO
285    
286          DO ij = iip2, ip1jm
287            extremum(ij) = dyqv(ij)*dyqv(ij-iip1) <= 0.
288          END DO
289    
290          ! Pas de pentes aux poles
291          DO ij = 1, iip1
292            zqv(ij, l) = q(ij, l)
293            zqv(ip1jm-iip1+ij, l) = q(ip1jm+ij, l)
294            extremum(ij) = .TRUE.
295            extremum(ip1jmp1-iip1+ij) = .TRUE.
296          END DO
297    
298          ! calcul des valeurs max et min acceptees aux interfaces
299          DO ij = 1, ip1jm
300            zqmax(ij) = max(q(ij+iip1,l), q(ij,l))
301            zqmin(ij) = min(q(ij+iip1,l), q(ij,l))
302          END DO
303    
304          DO ij = 1, ip1jm
305            zqv(ij, l) = min(max(zqmin(ij),zqv(ij,l)), zqmax(ij))
306          END DO
307    
308          DO ij = iip2, ip1jm
309            IF (extremum(ij)) THEN
310              qs(ij, l) = q(ij, l)
311              qn(ij, l) = q(ij, l)
312              ! if (.not.extremum(ij-iip1)) qs(ij-iip1,l)=q(ij,l)
313              ! if (.not.extremum(ij+iip1)) qn(ij+iip1,l)=q(ij,l)
314            ELSE
315              qs(ij, l) = zqv(ij, l)
316              qn(ij, l) = zqv(ij-iip1, l)
317            END IF
318          END DO
319    
320          DO ij = 1, iip1
321            qs(ij, l) = q(ij, l)
322            qn(ij, l) = q(ij, l)
323            qs(ip1jm+ij, l) = q(ip1jm+ij, l)
324            qn(ip1jm+ij, l) = q(ip1jm+ij, l)
325          END DO
326    
327        END DO
328      END IF
329      RETURN
330    END SUBROUTINE advnqy
331    
332    SUBROUTINE advnqz(q, qh, qb)
333    
334      ! Auteurs:   Calcul des valeurs de q aux point v.
335    
336      ! --------------------------------------------------------------------
337      USE dimensions
338      USE paramet_m
339      USE conf_gcm_m
340      IMPLICIT NONE
341    
342    
343    
344      ! Arguments:
345      ! ----------
346      REAL q(ip1jmp1, llm), qh(ip1jmp1, llm), qb(ip1jmp1, llm)
347    
348      ! Local
349      ! ---------
350    
351      INTEGER ij, l
352    
353      REAL dzqw(ip1jmp1, llm+1), zqw(ip1jmp1, llm+1)
354      REAL zqmax(ip1jmp1, llm), zqmin(ip1jmp1, llm)
355      LOGICAL extremum(ip1jmp1, llm)
356    
357      INTEGER mode
358      SAVE mode
359    
360      DATA mode/1/
361    
362      ! calcul des pentes en u:
363      ! -----------------------
364    
365      IF (mode==0) THEN
366        DO l = 1, llm
367          DO ij = 1, ip1jmp1
368            qb(ij, l) = q(ij, l)
369            qh(ij, l) = q(ij, l)
370          END DO
371        END DO
372      ELSE
373        DO l = 2, llm
374          DO ij = 1, ip1jmp1
375            dzqw(ij, l) = q(ij, l-1) - q(ij, l)
376            zqw(ij, l) = 0.5*(q(ij,l-1)+q(ij,l))
377          END DO
378        END DO
379        DO ij = 1, ip1jmp1
380          dzqw(ij, 1) = 0.
381          dzqw(ij, llm+1) = 0.
382        END DO
383        DO l = 2, llm
384          DO ij = 1, ip1jmp1
385            zqw(ij, l) = zqw(ij, l) + (dzqw(ij,l+1)-dzqw(ij,l-1))/12.
386          END DO
387        END DO
388        DO l = 2, llm - 1
389          DO ij = 1, ip1jmp1
390            extremum(ij, l) = dzqw(ij, l)*dzqw(ij, l+1) <= 0.
391          END DO
392        END DO
393    
394        ! Pas de pentes en bas et en haut
395        DO ij = 1, ip1jmp1
396          zqw(ij, 2) = q(ij, 1)
397          zqw(ij, llm) = q(ij, llm)
398          extremum(ij, 1) = .TRUE.
399          extremum(ij, llm) = .TRUE.
400        END DO
401    
402        ! calcul des valeurs max et min acceptees aux interfaces
403        DO l = 2, llm
404          DO ij = 1, ip1jmp1
405            zqmax(ij, l) = max(q(ij,l-1), q(ij,l))
406            zqmin(ij, l) = min(q(ij,l-1), q(ij,l))
407          END DO
408        END DO
409    
410        DO l = 2, llm
411          DO ij = 1, ip1jmp1
412            zqw(ij, l) = min(max(zqmin(ij,l),zqw(ij,l)), zqmax(ij,l))
413          END DO
414        END DO
415    
416        DO l = 2, llm - 1
417          DO ij = 1, ip1jmp1
418            IF (extremum(ij,l)) THEN
419              qh(ij, l) = q(ij, l)
420              qb(ij, l) = q(ij, l)
421            ELSE
422              qh(ij, l) = zqw(ij, l+1)
423              qb(ij, l) = zqw(ij, l)
424            END IF
425          END DO
426        END DO
427        ! do l=2,llm-1
428        ! do ij=1,ip1jmp1
429        ! if(extremum(ij,l)) then
430        ! if (.not.extremum(ij,l-1)) qh(ij,l-1)=q(ij,l)
431        ! if (.not.extremum(ij,l+1)) qb(ij,l+1)=q(ij,l)
432        ! endif
433        ! enddo
434        ! enddo
435    
436        DO ij = 1, ip1jmp1
437          qb(ij, 1) = q(ij, 1)
438          qh(ij, 1) = q(ij, 1)
439          qb(ij, llm) = q(ij, llm)
440          qh(ij, llm) = q(ij, llm)
441        END DO
442    
443      END IF
444    
445      RETURN
446    END SUBROUTINE advnqz
447    
448    SUBROUTINE advnx(q, qg, qd, masse, u_m, mode)
449    
450      ! Auteur : F. Hourdin
451    
452      ! ********************************************************************
453      ! Shema  d'advection " pseudo amont " .
454      ! ********************************************************************
455      ! nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
456    
457    
458      ! --------------------------------------------------------------------
459      USE dimensions
460      USE paramet_m
461      USE comconst
462      USE disvert_m
463      USE conf_gcm_m
464      IMPLICIT NONE
465    
466    
467    
468      ! Arguments:
469      ! ----------
470      INTEGER mode
471      REAL masse(ip1jmp1, llm)
472      REAL u_m(ip1jmp1, llm)
473      REAL q(ip1jmp1, llm), qd(ip1jmp1, llm), qg(ip1jmp1, llm)
474    
475      ! Local
476      ! ---------
477    
478      INTEGER i, j, ij, l, indu(ip1jmp1), niju, iju, ijq
479      INTEGER n0, nl(llm)
480    
481      REAL new_m, zu_m, zdq, zz
482      REAL zsigg(ip1jmp1, llm), zsigd(ip1jmp1, llm), zsig
483      REAL u_mq(ip1jmp1, llm)
484    
485      REAL zm, zq, zsigm, zsigp, zqm, zqp, zu
486    
487      LOGICAL ladvplus(ip1jmp1, llm)
488    
489      REAL prec
490      SAVE prec
491    
492      DATA prec/1.E-15/
493    
494      DO l = 1, llm
495        DO ij = iip2, ip1jm
496          zdq = qd(ij, l) - qg(ij, l)
497          IF (abs(zdq)>prec) THEN
498            zsigd(ij, l) = (q(ij,l)-qg(ij,l))/zdq
499            zsigg(ij, l) = 1. - zsigd(ij, l)
500          ELSE
501            zsigd(ij, l) = 0.5
502            zsigg(ij, l) = 0.5
503            qd(ij, l) = q(ij, l)
504            qg(ij, l) = q(ij, l)
505          END IF
506        END DO
507      END DO
508    
509      ! calcul de la pente maximum dans la maille en valeur absolue
510    
511      DO l = 1, llm
512        DO ij = iip2, ip1jm - 1
513          IF (u_m(ij,l)>=0.) THEN
514            zsigp = zsigd(ij, l)
515            zsigm = zsigg(ij, l)
516            zqp = qd(ij, l)
517            zqm = qg(ij, l)
518            zm = masse(ij, l)
519            zq = q(ij, l)
520          ELSE
521            zsigm = zsigd(ij+1, l)
522            zsigp = zsigg(ij+1, l)
523            zqm = qd(ij+1, l)
524            zqp = qg(ij+1, l)
525            zm = masse(ij+1, l)
526            zq = q(ij+1, l)
527          END IF
528          zu = abs(u_m(ij,l))
529          ladvplus(ij, l) = zu > zm
530          zsig = zu/zm
531          IF (zsig==0.) zsigp = 0.1
532          IF (mode==1) THEN
533            IF (zsig<=zsigp) THEN
534              u_mq(ij, l) = u_m(ij, l)*zqp
535            ELSE IF (mode==1) THEN
536              u_mq(ij, l) = sign(zm, u_m(ij,l))*(zsigp*zqp+(zsig-zsigp)*zqm)
537            END IF
538          ELSE
539            IF (zsig<=zsigp) THEN
540              u_mq(ij, l) = u_m(ij, l)*(zqp-0.5*zsig/zsigp*(zqp-zq))
541            ELSE
542              zz = 0.5*(zsig-zsigp)/zsigm
543              u_mq(ij, l) = sign(zm, u_m(ij,l))*(0.5*(zq+zqp)*zsigp+(zsig-zsigp)* &
544                (zq+zz*(zqm-zq)))
545            END IF
546          END IF
547        END DO
548      END DO
549    
550      DO l = 1, llm
551        DO ij = iip1 + iip1, ip1jm, iip1
552          u_mq(ij, l) = u_mq(ij-iim, l)
553          ladvplus(ij, l) = ladvplus(ij-iim, l)
554        END DO
555      END DO
556    
557      ! =================================================================
558      ! SCHEMA SEMI-LAGRAGIEN EN X DANS LES REGIONS POLAIRES
559      ! =================================================================
560      ! tris des regions a traiter
561      n0 = 0
562      DO l = 1, llm
563        nl(l) = 0
564        DO ij = iip2, ip1jm
565          IF (ladvplus(ij,l)) THEN
566            nl(l) = nl(l) + 1
567            u_mq(ij, l) = 0.
568          END IF
569        END DO
570        n0 = n0 + nl(l)
571      END DO
572    
573      IF (n0>1) THEN
574        IF (prt_level>9) PRINT *, &
575          'Nombre de points pour lesquels on advect plus que le', &
576          'contenu de la maille : ', n0
577    
578        DO l = 1, llm
579          IF (nl(l)>0) THEN
580            iju = 0
581            ! indicage des mailles concernees par le traitement special
582            DO ij = iip2, ip1jm
583              IF (ladvplus(ij,l) .AND. mod(ij,iip1)/=0) THEN
584                iju = iju + 1
585                indu(iju) = ij
586              END IF
587            END DO
588            niju = iju
589    
590            ! traitement des mailles
591            DO iju = 1, niju
592              ij = indu(iju)
593              j = (ij-1)/iip1 + 1
594              zu_m = u_m(ij, l)
595              u_mq(ij, l) = 0.
596              IF (zu_m>0.) THEN
597                ijq = ij
598                i = ijq - (j-1)*iip1
599                ! accumulation pour les mailles completements advectees
600                DO WHILE (zu_m>masse(ijq,l))
601                  u_mq(ij, l) = u_mq(ij, l) + q(ijq, l)*masse(ijq, l)
602                  zu_m = zu_m - masse(ijq, l)
603                  i = mod(i-2+iim, iim) + 1
604                  ijq = (j-1)*iip1 + i
605                END DO
606                ! MODIFS SPECIFIQUES DU SCHEMA
607                ! ajout de la maille non completement advectee
608                zsig = zu_m/masse(ijq, l)
609                IF (zsig<=zsigd(ijq,l)) THEN
610                  u_mq(ij, l) = u_mq(ij, l) + zu_m*(qd(ijq,l)-0.5*zsig/zsigd(ijq, &
611                    l)*(qd(ijq,l)-q(ijq,l)))
612                ELSE
613                  ! u_mq(ij,l)=u_mq(ij,l)+zu_m*q(ijq,l)
614                  ! goto 8888
615                  zz = 0.5*(zsig-zsigd(ijq,l))/zsigg(ijq, l)
616                  IF (.NOT. (zz>0. .AND. zz<=0.5)) THEN
617                    PRINT *, 'probleme2 au point ij=', ij, '  l=', l
618                    PRINT *, 'zz=', zz
619                    STOP
620                  END IF
621                  u_mq(ij, l) = u_mq(ij, l) + masse(ijq, l)*(0.5*(q(ijq, &
622                    l)+qd(ijq,l))*zsigd(ijq,l)+(zsig-zsigd(ijq,l))*(q(ijq, &
623                    l)+zz*(qg(ijq,l)-q(ijq,l))))
624                END IF
625              ELSE
626                ijq = ij + 1
627                i = ijq - (j-1)*iip1
628                ! accumulation pour les mailles completements advectees
629                DO WHILE (-zu_m>masse(ijq,l))
630                  u_mq(ij, l) = u_mq(ij, l) - q(ijq, l)*masse(ijq, l)
631                  zu_m = zu_m + masse(ijq, l)
632                  i = mod(i, iim) + 1
633                  ijq = (j-1)*iip1 + i
634                END DO
635                ! ajout de la maille non completement advectee
636                ! 2eme MODIF SPECIFIQUE
637                zsig = -zu_m/masse(ij+1, l)
638                IF (zsig<=zsigg(ijq,l)) THEN
639                  u_mq(ij, l) = u_mq(ij, l) + zu_m*(qg(ijq,l)-0.5*zsig/zsigg(ijq, &
640                    l)*(qg(ijq,l)-q(ijq,l)))
641                ELSE
642                  ! u_mq(ij,l)=u_mq(ij,l)+zu_m*q(ijq,l)
643                  ! goto 9999
644                  zz = 0.5*(zsig-zsigg(ijq,l))/zsigd(ijq, l)
645                  IF (.NOT. (zz>0. .AND. zz<=0.5)) THEN
646                    PRINT *, 'probleme22 au point ij=', ij, '  l=', l
647                    PRINT *, 'zz=', zz
648                    STOP
649                  END IF
650                  u_mq(ij, l) = u_mq(ij, l) - masse(ijq, l)*(0.5*(q(ijq, &
651                    l)+qg(ijq,l))*zsigg(ijq,l)+(zsig-zsigg(ijq,l))*(q(ijq, &
652                    l)+zz*(qd(ijq,l)-q(ijq,l))))
653                END IF
654                ! fin de la modif
655              END IF
656            END DO
657          END IF
658        END DO
659      END IF ! n0.gt.0
660    
661      ! bouclage en latitude
662      DO l = 1, llm
663        DO ij = iip1 + iip1, ip1jm, iip1
664          u_mq(ij, l) = u_mq(ij-iim, l)
665        END DO
666      END DO
667    
668      ! =================================================================
669      ! CALCUL DE LA CONVERGENCE DES FLUX
670      ! =================================================================
671    
672      DO l = 1, llm
673        DO ij = iip2 + 1, ip1jm
674          new_m = masse(ij, l) + u_m(ij-1, l) - u_m(ij, l)
675          q(ij, l) = (q(ij,l)*masse(ij,l)+u_mq(ij-1,l)-u_mq(ij,l))/new_m
676          masse(ij, l) = new_m
677        END DO
678        ! Modif Fred 22 03 96 correction d'un bug (les scopy ci-dessous)
679        DO ij = iip1 + iip1, ip1jm, iip1
680          q(ij-iim, l) = q(ij, l)
681          masse(ij-iim, l) = masse(ij, l)
682        END DO
683      END DO
684    
685      RETURN
686    END SUBROUTINE advnx
687    SUBROUTINE advny(q, qs, qn, masse, v_m)
688    
689      ! Auteur : F. Hourdin
690    
691      ! ********************************************************************
692      ! Shema  d'advection " pseudo amont " .
693      ! ********************************************************************
694      ! nq,iq,q,pbaru,pbarv,w sont des arguments d'entree  pour le s-pg ....
695    
696    
697      ! --------------------------------------------------------------------
698      USE dimensions
699      USE paramet_m
700      USE comgeom
701      USE conf_gcm_m
702      IMPLICIT NONE
703    
704    
705    
706      ! Arguments:
707      ! ----------
708      REAL masse(ip1jmp1, llm)
709      REAL v_m(ip1jm, llm)
710      REAL q(ip1jmp1, llm), qn(ip1jmp1, llm), qs(ip1jmp1, llm)
711    
712      ! Local
713      ! ---------
714    
715      INTEGER ij, l
716    
717      REAL new_m, zdq, zz
718      REAL zsigs(ip1jmp1), zsign(ip1jmp1), zsig
719      REAL v_mq(ip1jm, llm)
720      REAL convpn, convps, convmpn, convmps, massen, masses
721      REAL zm, zq, zsigm, zsigp, zqm, zqp
722      REAL ssum
723      REAL prec
724      SAVE prec
725    
726      DATA prec/1.E-15/
727    
728      DO l = 1, llm
729        DO ij = 1, ip1jmp1
730          zdq = qn(ij, l) - qs(ij, l)
731          IF (abs(zdq)>prec) THEN
732            zsign(ij) = (q(ij,l)-qs(ij,l))/zdq
733            zsigs(ij) = 1. - zsign(ij)
734          ELSE
735            zsign(ij) = 0.5
736            zsigs(ij) = 0.5
737          END IF
738        END DO
739    
740        ! calcul de la pente maximum dans la maille en valeur absolue
741    
742        DO ij = 1, ip1jm
743          IF (v_m(ij,l)>=0.) THEN
744            zsigp = zsign(ij+iip1)
745            zsigm = zsigs(ij+iip1)
746            zqp = qn(ij+iip1, l)
747            zqm = qs(ij+iip1, l)
748            zm = masse(ij+iip1, l)
749            zq = q(ij+iip1, l)
750          ELSE
751            zsigm = zsign(ij)
752            zsigp = zsigs(ij)
753            zqm = qn(ij, l)
754            zqp = qs(ij, l)
755            zm = masse(ij, l)
756            zq = q(ij, l)
757          END IF
758          zsig = abs(v_m(ij,l))/zm
759          IF (zsig==0.) zsigp = 0.1
760          IF (zsig<=zsigp) THEN
761            v_mq(ij, l) = v_m(ij, l)*(zqp-0.5*zsig/zsigp*(zqp-zq))
762          ELSE
763            zz = 0.5*(zsig-zsigp)/zsigm
764            v_mq(ij, l) = sign(zm, v_m(ij,l))*(0.5*(zq+zqp)*zsigp+(zsig-zsigp)*( &
765              zq+zz*(zqm-zq)))
766          END IF
767        END DO
768      END DO
769    
770      DO l = 1, llm
771        DO ij = iip2, ip1jm
772          new_m = masse(ij, l) + v_m(ij, l) - v_m(ij-iip1, l)
773          q(ij, l) = (q(ij,l)*masse(ij,l)+v_mq(ij,l)-v_mq(ij-iip1,l))/new_m
774          masse(ij, l) = new_m
775        END DO
776        ! .-. ancienne version
777        convpn = ssum(iim, v_mq(1,l), 1)
778        convmpn = ssum(iim, v_m(1,l), 1)
779        massen = ssum(iim, masse(1,l), 1)
780        new_m = massen + convmpn
781        q(1, l) = (q(1,l)*massen+convpn)/new_m
782        DO ij = 1, iip1
783          q(ij, l) = q(1, l)
784          masse(ij, l) = new_m*aire(ij)/apoln
785        END DO
786    
787        convps = -ssum(iim, v_mq(ip1jm-iim,l), 1)
788        convmps = -ssum(iim, v_m(ip1jm-iim,l), 1)
789        masses = ssum(iim, masse(ip1jm+1,l), 1)
790        new_m = masses + convmps
791        q(ip1jm+1, l) = (q(ip1jm+1,l)*masses+convps)/new_m
792        DO ij = ip1jm + 1, ip1jmp1
793          q(ij, l) = q(ip1jm+1, l)
794          masse(ij, l) = new_m*aire(ij)/apols
795        END DO
796      END DO
797    
798      RETURN
799    END SUBROUTINE advny
800    SUBROUTINE advnz(q, qh, qb, masse, w_m)
801    
802      ! Auteurs:   F.Hourdin
803    
804      ! ********************************************************************
805      ! Shema  d'advection " pseudo amont " .
806      ! b designe le bas et h le haut
807      ! il y a une correspondance entre le b en z et le d en x
808      ! ********************************************************************
809    
810    
811      ! --------------------------------------------------------------------
812      USE dimensions
813      USE paramet_m
814      USE comgeom
815      USE conf_gcm_m
816      IMPLICIT NONE
817    
818    
819    
820      ! Arguments:
821      ! ----------
822      REAL masse(ip1jmp1, llm)
823      REAL w_m(ip1jmp1, llm+1)
824      REAL q(ip1jmp1, llm), qb(ip1jmp1, llm), qh(ip1jmp1, llm)
825    
826    
827      ! Local
828      ! ---------
829    
830      INTEGER ij, l
831    
832      REAL new_m, zdq, zz
833      REAL zsigh(ip1jmp1, llm), zsigb(ip1jmp1, llm), zsig
834      REAL w_mq(ip1jmp1, llm+1)
835      REAL zm, zq, zsigm, zsigp, zqm, zqp
836      REAL prec
837      SAVE prec
838    
839      DATA prec/1.E-13/
840    
841      DO l = 1, llm
842        DO ij = 1, ip1jmp1
843          zdq = qb(ij, l) - qh(ij, l)
844          IF (abs(zdq)>prec) THEN
845            zsigb(ij, l) = (q(ij,l)-qh(ij,l))/zdq
846            zsigh(ij, l) = 1. - zsigb(ij, l)
847            zsigb(ij, l) = min(max(zsigb(ij,l),0.), 1.)
848          ELSE
849            zsigb(ij, l) = 0.5
850            zsigh(ij, l) = 0.5
851          END IF
852        END DO
853      END DO
854    
855      ! calcul de la pente maximum dans la maille en valeur absolue
856      DO l = 2, llm
857        DO ij = 1, ip1jmp1
858          IF (w_m(ij,l)>=0.) THEN
859            zsigp = zsigb(ij, l)
860            zsigm = zsigh(ij, l)
861            zqp = qb(ij, l)
862            zqm = qh(ij, l)
863            zm = masse(ij, l)
864            zq = q(ij, l)
865          ELSE
866            zsigm = zsigb(ij, l-1)
867            zsigp = zsigh(ij, l-1)
868            zqm = qb(ij, l-1)
869            zqp = qh(ij, l-1)
870            zm = masse(ij, l-1)
871            zq = q(ij, l-1)
872          END IF
873          zsig = abs(w_m(ij,l))/zm
874          IF (zsig==0.) zsigp = 0.1
875          IF (zsig<=zsigp) THEN
876            w_mq(ij, l) = w_m(ij, l)*(zqp-0.5*zsig/zsigp*(zqp-zq))
877          ELSE
878            zz = 0.5*(zsig-zsigp)/zsigm
879            w_mq(ij, l) = sign(zm, w_m(ij,l))*(0.5*(zq+zqp)*zsigp+(zsig-zsigp)*( &
880              zq+zz*(zqm-zq)))
881          END IF
882        END DO
883      END DO
884    
885      DO ij = 1, ip1jmp1
886        w_mq(ij, llm+1) = 0.
887        w_mq(ij, 1) = 0.
888      END DO
889    
890      DO l = 1, llm
891        DO ij = 1, ip1jmp1
892          new_m = masse(ij, l) + w_m(ij, l+1) - w_m(ij, l)
893          q(ij, l) = (q(ij,l)*masse(ij,l)+w_mq(ij,l+1)-w_mq(ij,l))/new_m
894          masse(ij, l) = new_m
895        END DO
896      END DO
897    
898    END SUBROUTINE advnz

Legend:
Removed from v.66  
changed lines
  Added in v.265

  ViewVC Help
Powered by ViewVC 1.1.21