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

Legend:
Removed from v.76  
changed lines
  Added in v.81

  ViewVC Help
Powered by ViewVC 1.1.21