!
! $Header$
!
      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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "logic.h"
#include "comvert.h"
#include "comconst.h"
#include "comgeom.h"
#include "iniprint.h"

c
c   Arguments:
c   ----------
      integer mode
      real masse(ip1jmp1,llm)
      REAL 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

#ifdef CRAY
      real second
#endif

      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     ')

#ifdef CRAY
      if(testcpu) then
         ztemps1=second(0.)
         temps1=temps1+ztemps1-ztemps2
            print*,'VLSPLT X:',temps1,'   Y:',temps2,'   Z:',temps3
      endif
#endif
      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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "iniprint.h"
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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "iniprint.h"
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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "iniprint.h"
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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "logic.h"
#include "comvert.h"
#include "comconst.h"
#include "iniprint.h"
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

#ifdef CRAY
      data prec/1.e-24/
#else
      data prec/1.e-15/
#endif

      do l=1,llm
            do ij=iip2,ip1jm
               zdq=qd(ij,l)-qg(ij,l)
c              if((qd(ij,l)-q(ij,l))*(q(ij,l)-qg(ij,l)).lt.0.) then
c                 print*,'probleme au point ij=',ij,'  l=',l
c                 print*,qd(ij,l),q(ij,l),qg(ij,l)
c                 qd(ij,l)=q(ij,l)
c                 qg(ij,l)=q(ij,l)
c              endif
               if(abs(zdq).gt.prec) then
                  zsigd(ij,l)=(q(ij,l)-qg(ij,l))/zdq
                  zsigg(ij,l)=1.-zsigd(ij,l)
c                 if(.not.(zsigd(ij,l).ge.0..and.zsigd(ij,l).le.1. .and.
c    s               zsigg(ij,l).ge.0..or.zsigg(ij,l).le.1.) ) then
c                    print*,'probleme au point ij=',ij,'  l=',l
c                    print*,'sigg=',zsigg(ij,l),'  sigd=',zsigd(ij,l)
c                    print*,'q d,c,g ',qd(ij,l),q(ij,l),qg(ij,l),zdq
c                    stop
c                 endif
               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
c         if(zsig.lt.0.) then
c            print*,'au point ij=',ij,'  l=',l,'  sig=',zsig
c            stop
c         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) WRITE(lunout,*)
     & '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              print*,'niju,nl',niju,nl(l)

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
                     WRITE(lunout,*)'probleme2 au point ij=',ij,
     s               '  l=',l
                     WRITE(lunout,*)'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
                     WRITE(lunout,*)'probleme22 au point ij=',ij
     s               ,'  l=',l
                     WRITE(lunout,*)'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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "comgeom.h"
#include "iniprint.h"
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

#ifdef CRAY
      data prec/1.e-24/
#else
      data prec/1.e-15/
#endif
      do l=1,llm
            do ij=1,ip1jmp1
               zdq=qn(ij,l)-qs(ij,l)
c              if((qn(ij,l)-q(ij,l))*(q(ij,l)-qs(ij,l)).lt.0.) then
c                 print*,'probleme au point ij=',ij,'  l=',l,'  advnqx'
c                 print*,qn(ij,l),q(ij,l),qs(ij,l)
c                 qn(ij,l)=q(ij,l)
c                 qs(ij,l)=q(ij,l)
c              endif
               if(abs(zdq).gt.prec) then
                  zsign(ij)=(q(ij,l)-qs(ij,l))/zdq
                  zsigs(ij)=1.-zsign(ij)
c                 if(.not.(zsign(ij).ge.0..and.zsign(ij).le.1. .and.
c    s               zsigs(ij).ge.0..or.zsigs(ij).le.1.) ) then
c                    print*,'probleme au point ij=',ij,'  l=',l
c                    print*,'sigs=',zsigs(ij),'  sign=',zsign(ij)
c                    stop
c                 endif
               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   --------------------------------------------------------------------
      IMPLICIT NONE
c
#include "dimensions.h"
#include "paramet.h"
#include "comgeom.h"
#include "iniprint.h"
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

#ifdef CRAY
      data prec/1.e-24/
#else
      data prec/1.e-13/
#endif

      do l=1,llm
            do ij=1,ip1jmp1
               zdq=qb(ij,l)-qh(ij,l)
c              if((qh(ij,l)-q(ij,l))*(q(ij,l)-qb(ij,l)).lt.0.) then
c                 print*,'probleme au point ij=',ij,'  l=',l
c                 print*,qh(ij,l),q(ij,l),qb(ij,l)
c                 qh(ij,l)=q(ij,l)
c                 qb(ij,l)=q(ij,l)
c              endif

               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      print*,'ok1'
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
c     print*,'ok3'
      RETURN
      END
