C**** QUSEM12 E001M12 SOMTQ QUSB261AM12
C**** QUSBM9=QUSB140M9 with correction to second order moment calc.
C**** Changes for constant pressure above LS1 + REAL*8
C**** QUS   is Russell quadratic upstream scheme for temperature
C**** and water vapor advection, with limits applied to water vapor.
C**** Changes for constant pressure above LS1
C**** FQU,FQV for additional diagnostics
C**** Routines included: AADVT, AADVTX, AADVTY, AADVTZ


      MODULE QUSCOM 13,1
!@sum  QUSCOM contains gcm-specific advection parameters/workspace
!@auth Maxwell Kelley
      USE QUSDEF
      IMPLICIT NONE
      SAVE
      INTEGER :: IM,JM,LM
      INTEGER :: XSTRIDE,YSTRIDE,ZSTRIDE
      REAL*8 :: BYIM
C**** AIR MASS FLUXES
      REAL*8, DIMENSION(:,:,:), ALLOCATABLE :: MFLX
C**** WORKSPACE FOR AADVTX
cc    REAL*8, DIMENSION(:), ALLOCATABLE :: AM,F_I
cc    REAL*8, DIMENSION(:,:), ALLOCATABLE :: FMOM_I
C**** WORKSPACE FOR AADVTY
cc    REAL*8, DIMENSION(:), ALLOCATABLE :: BM,F_J
cc    REAL*8, DIMENSION(:,:), ALLOCATABLE :: FMOM_J
C**** WORKSPACE FOR AADVTZ
cc    REAL*8, DIMENSION(:), ALLOCATABLE :: CM,F_L
cc    REAL*8, DIMENSION(:,:), ALLOCATABLE :: FMOM_L
      END MODULE QUSCOM


      SUBROUTINE init_QUS(grd_dum,IM_GCM,JM_GCM,LM_GCM) 1,5
!@sum  init_QUS sets gcm-specific advection parameters/workspace
!@auth Maxwell Kelley
      USE DOMAIN_DECOMP, only : DIST_GRID, GET
      use QUSCOM
      USE PARAM
      INTEGER, INTENT(IN) :: IM_GCM,JM_GCM,LM_GCM
      TYPE (DIST_GRID), INTENT(IN) :: grd_dum

C****
C**** Extract local domain parameters from "grd_dum"
C****
      INTEGER J_0,J_1,J_0H,J_1H
      CALL GET(grd_dum, J_STRT=J_0,       J_STOP=J_1,
     &                  J_STRT_HALO=J_0H, J_STOP_HALO=J_1H)

C**** SET RESOLUTION
      IM = IM_GCM
      JM = JM_GCM
      LM = LM_GCM
      BYIM = 1.D0/REAL(IM,KIND=8)
      XSTRIDE = 1
      YSTRIDE = IM
      ZSTRIDE = IM*(J_1H-J_0H+1)
C**** ALLOCATE SPACE FOR AIR MASS FLUXES
      ALLOCATE(MFLX(IM,J_0H:J_1H,LM))
C**** ALLOCATE WORKSPACE FOR AADVTX
cc    ALLOCATE(AM(IM),F_I(IM),FMOM_I(NMOM,IM))
C**** ALLOCATE WORKSPACE FOR AADVTY
cc    ALLOCATE(BM(JM),F_J(J_0H:J_1H),FMOM_J(NMOM,J_0H:J_1H))
C**** ALLOCATE WORKSPACE FOR AADVTZ
cc    ALLOCATE(CM(LM),F_L(LM),FMOM_L(NMOM,LM))

      call sync_param("prather_limits",prather_limits)

      RETURN
      END SUBROUTINE init_QUS


      SUBROUTINE AADVT (MA,RM,RMOM,SD,PU,PV,DT,QLIMIT,FQU,FQV) 1,9
!@sum  AADVT advection driver
!@auth G. Russell, modified by Maxwell Kelley
c****
c**** AADVT advects tracers using the Quadradic Upstream Scheme.
c****
c**** input:
c****  pu,pv,sd (kg/s) = east-west,north-south,vertical mass fluxes
c****      qlimit = whether moment limitations should be used
C****         DT (s) = time step
c****
c**** input/output:
c****     rm = tracer concentration
c****   rmom = moments of tracer concentration
c****     ma (kg) = fluid mass
c****
      USE DOMAIN_DECOMP, only: grid, get
      USE DOMAIN_DECOMP, only: HALO_UPDATE,NORTH,SOUTH
      USE QUSDEF
      USE QUSCOM, ONLY : IM,JM,LM, MFLX
      IMPLICIT NONE

      REAL*8, dimension(im,grid%J_STRT_HALO:grid%J_STOP_HALO,lm) :: 
     &                  rm,ma
      REAL*8, dimension(NMOM,IM,grid%J_STRT_HALO:grid%J_STOP_HALO,LM) 
     &               :: rmom

      REAL*8, INTENT(IN) :: DT
      REAL*8, dimension(im,grid%J_STRT_HALO:grid%J_STOP_HALO,lm), 
     &    intent(in) :: pu,pv
      REAL*8, dimension(im,grid%J_STRT_HALO:grid%J_STOP_HALO,lm-1),
     &    intent(in) :: sd
      LOGICAL, INTENT(IN) :: QLIMIT

      REAL*8, dimension(im,grid%J_STRT_HALO:grid%J_STOP_HALO), 
     & intent(inout) :: fqu,fqv

      INTEGER :: I,J,L,N
      REAL*8 :: BYMA
c**** Extract domain decomposition info
      INTEGER :: J_0, J_1, J_0S, J_1S
      LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
      CALL GET(grid, J_STRT = J_0, J_STOP = J_1,
     &               J_STRT_SKP  = J_0S,   J_STOP_SKP  = J_1S,
     &               HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
     &               HAVE_NORTH_POLE = HAVE_NORTH_POLE)

C**** Initialise diagnostics
      FQU=0.  ; FQV=0.

C**** Fill in values at the poles
C**** SOUTH POLE:
      if (HAVE_SOUTH_POLE) then
!$OMP  PARALLEL DO PRIVATE(I,L,N)
        DO L=1,LM
          DO I=2,IM
            RM(I,1 ,L) =   RM(1,1 ,L)
            DO N=1,NMOM
              RMOM(N,I,1 ,L) =  RMOM(N,1,1 ,L)
            enddo
          enddo
        enddo
!$OMP  END PARALLEL DO
      end if       !SOUTH POLE

c**** NORTH POLE:
      if (HAVE_NORTH_POLE) then
!$OMP  PARALLEL DO PRIVATE(I,L,N)
        DO L=1,LM
          DO I=2,IM
            RM(I,JM,L) =   RM(1,JM,L)
            DO N=1,NMOM
              RMOM(N,I,JM,L) =  RMOM(N,1,JM,L)
            enddo
          enddo
        enddo
!$OMP  END PARALLEL DO
      end if    ! NORTH POLE
C****
C**** convert from concentration to mass units
C****
!$OMP  PARALLEL DO PRIVATE(I,J,L)
      DO L=1,LM
      DO J=J_0,J_1
      DO I=1,IM
         RM(I,J,L)=RM(I,J,L)*MA(I,J,L)
         RMOM(:,I,J,L)=RMOM(:,I,J,L)*MA(I,J,L)
      enddo
      enddo
      enddo
!$OMP  END PARALLEL DO
C****
C**** Advect the tracer using the quadratic upstream scheme
C****
CC    mflx(:,:,:)=pu(:,:,:)*(.5*dt)
!$OMP  PARALLEL DO PRIVATE(L)
       DO L=1,LM
          mflx(:,:,l)=pu(:,:,l)*(.5*dt)
       ENDDO
!$OMP  END PARALLEL DO
      CALL AADVTX (RM,RMOM,MA,MFLX,QLIMIT,FQU)

CC    mflx(:,1:jm-1,:)=pv(:,2:jm,:)*dt
CC    mflx(:,jm,:)=0.
C**** Halo boxes for pv updated before call to AADVT.
!      call HALO_UPDATE(grid, pv, from=NORTH)
!$OMP  PARALLEL DO PRIVATE(L)
       DO L=1,LM
          mflx(:,J_0:J_1S,l)=pv(:,J_0+1:J_1S+1,l)*dt
       ENDDO
!$OMP  END PARALLEL DO
       if (HAVE_NORTH_POLE) mflx(:,jm,:)=0.

      CALL AADVTY (RM,RMOM,MA,MFLX,QLIMIT,FQV)
CC    mflx(:,:,1:lm-1)=sd(:,:,1:lm-1)*(-dt)
CC    mflx(:,:,lm)=0.
!$OMP  PARALLEL DO PRIVATE(L)
      DO L=1,LM
         IF(L.NE.LM)  THEN
            MFLX(:,:,L)=SD(:,:,L)*(-DT)
         ELSE
            MFLX(:,:,L)=0.
         END IF
      ENDDO
!$OMP  END PARALLEL DO
      CALL AADVTZ (RM,RMOM,MA,MFLX,QLIMIT)
CC    mflx(:,:,:)=pu(:,:,:)*(.5*dt)
!$OMP  PARALLEL DO PRIVATE(L)
       DO L=1,LM
          mflx(:,:,l)=pu(:,:,l)*(.5*dt)
       ENDDO
!$OMP  END PARALLEL DO
      CALL AADVTX (RM,RMOM,MA,MFLX,QLIMIT,FQU)
C****
C**** convert from mass to concentration units
C****
!$OMP  PARALLEL DO PRIVATE(I,J,L,BYMA)
      DO L=1,LM
      DO J=J_0,J_1
      DO I=1,IM
         BYMA = 1.D0/MA(I,J,L)
         RM(I,J,L)=RM(I,J,L)*BYMA
         RMOM(:,I,J,L)=RMOM(:,I,J,L)*BYMA
      enddo
      enddo
      enddo
!$OMP  END PARALLEL DO
      RETURN
      END


      subroutine aadvtx(rm,rmom,mass,mu,qlimit,fqu) 2,6
!@sum  AADVTX advection driver for x-direction
!@auth Maxwell Kelley
c****
c**** aadvtx advects tracers in the west to east direction using the
c**** quadratic upstream scheme.  if qlimit is true, the moments are
c**** limited to prevent the mean tracer from becoming negative.
c****
c**** input:
c****     mu (kg) = west-east mass flux, positive eastward
c****      qlimit = whether moment limitations should be used
c****
c**** input/output:
c****     rm (kg) = tracer mass
c****   rmom (kg) = moments of tracer mass
c****   mass (kg) = fluid mass
c****
      use DOMAIN_DECOMP, only : grid, GET
      use QUSDEF
ccc   use QUSCOM, only : im,jm,lm, xstride,am,f_i,fmom_i
      use QUSCOM, only : im,jm,lm, xstride
      implicit none
      REAL*8, dimension(im,grid%J_STRT_HALO:grid%J_STOP_HALO,lm) :: 
     &                  rm,mass,mu,hfqu
      REAL*8, dimension(NMOM,IM,grid%J_STRT_HALO:grid%J_STOP_HALO,LM) ::
     &                  rmom
      logical ::  qlimit
      REAL*8, INTENT(OUT), 
     &        DIMENSION(IM,grid%J_STRT_HALO:grid%J_STOP_HALO) :: FQU
      REAL*8  AM(IM), F_I(IM), FMOM_I(NMOM,IM)
     &     ,MASS_I(IM), COURMAX, BYNSTEP
      integer :: i,ip1,j,l,ierr,nerr,ICKERR,ns,nstep

c**** Get useful local parameters for domain decomposition
      integer :: J_0, J_1, J_0S, J_1S
      CALL GET(grid, J_STRT = J_0 , J_STOP=J_1,
     &             J_STRT_SKP=J_0S,J_STOP_SKP=J_1S )
c**** loop over layers and latitudes
      ICKERR=0
!$OMP  PARALLEL DO PRIVATE(J,L,AM,F_I,FMOM_I,IERR,NERR,
!$OMP*             I,IP1,NS,NSTEP,BYNSTEP,COURMAX,MASS_I)
!$OMP* SHARED(IM,QLIMIT,XSTRIDE)
!$OMP* REDUCTION(+:ICKERR)
      do l=1,lm
      do j=J_0S,J_1S
c****
c**** decide how many timesteps to take
c****
      nstep=0
      courmax = 2.
      do while(courmax.gt.1. .and. nstep.lt.20)
        nstep = nstep+1
        bynstep = 1d0/real(nstep,kind=8)
        am(:) = mu(:,j,l)*bynstep
        mass_i(:)  = mass(:,j,l)
        courmax = 0.
        do ns=1,nstep
          i = im
          do ip1=1,im
            if(am(i).gt.0.) then
               courmax = max(courmax,+am(i)/mass_i(i))
            else
               courmax = max(courmax,-am(i)/mass_i(ip1))
            endif
            i = ip1
          enddo
          if(ns.lt.nstep) then
             i = im
             do ip1=1,im
                mass_i(ip1) = mass_i(ip1) + (am(i)-am(ip1))
                i = ip1
             enddo
          endif
        enddo
      enddo
      if(courmax.gt.1.) then
         write(6,*) 'aadvtx: j,l,courmax=',j,l,courmax
         ICKERR=ICKERR+1
      endif

c      am(:) = mu(:,j,l)*bynstep ! am already set
      hfqu(:,j,l)  = 0.
c****
c**** loop over timesteps
c****
      do ns=1,nstep
c****
c**** call 1-d advection routine
c****
      call adv1d(rm(1,j,l),rmom(1,1,j,l), f_i,fmom_i, mass(1,j,l),
     &        am, im, qlimit,xstride,xdir,ierr,nerr)
      if (ierr.gt.0) then
        write(6,*) "Error in aadvtx: i,j,l=",nerr,j,l
        if (ierr.eq.2) then
          write(0,*) "Error in qlimit: abs(a) > 1"
CCC       call stop_model('Error in qlimit: abs(a) > 1',11)
          ICKERR=ICKERR+1
        end if
      end if
c****
c**** store tracer flux in fqu array
c****
CCC   fqu(:,j)  = fqu(:,j) + f_i(:)
      hfqu(:,j,l)  = hfqu(:,j,l) + f_i(:)
      enddo ! ns
      enddo ! j
      enddo ! l
!$OMP  END PARALLEL DO
c
c     now sum into fqu
c
!$OMP  PARALLEL DO PRIVATE(J,L)
      do j=J_0S,J_1S
      do l=1,lm
         fqu(:,j)  = fqu(:,j) + hfqu(:,j,l)
      enddo ! j
      enddo ! l
!$OMP  END PARALLEL DO
C
      IF(ICKERR.GT.0)  CALL stop_model('Stopped in aadvtx',11)
C
      return
c****
      end subroutine aadvtx


      subroutine aadvty(rm,rmom,mass,mv,qlimit,fqv) 1,8
!@sum  AADVTY advection driver for y-direction
!@auth Maxwell Kelley
c****
c**** aadvty advects tracers in the south to north direction using the
c**** quadratic upstream scheme.  if qlimit is true, the moments are
c**** limited to prevent the mean tracer from becoming negative.
c****
c**** input:
c****     mv (kg) = north-south mass flux, positive northward
c****      qlimit = whether moment limitations should be used
c****
c**** input/output:
c****     rm (kg) = tracer mass
c****   rmom (kg) = moments of tracer mass
c****   mass (kg) = fluid mass
c****
      use DOMAIN_DECOMP, only : grid, get, halo_update
      use DOMAIN_DECOMP, only : halo_update_column
      use DOMAIN_DECOMP, only : NORTH, SOUTH, AM_I_ROOT
      use QUSDEF
ccc   use QUSCOM, only : im,jm,lm, ystride,bm,f_j,fmom_j, byim
      use QUSCOM, only : im,jm,lm, ystride,               byim
      implicit none
      REAL*8, dimension(im,grid%j_strt_halo:grid%j_stop_halo,lm) :: 
     &                  rm,mass,mv
      REAL*8, dimension(NMOM,IM,grid%J_STRT_HALO:
     &                          grid%J_STOP_HALO,LM) :: rmom
      logical ::  qlimit
      REAL*8, intent(out), dimension(im,grid%J_STRT_HALO:
     &                                  grid%J_STOP_HALO) :: fqv
      REAL*8      BM(IM,grid%J_STRT_HALO:grid%J_STOP_HALO,LM),
     &                F_J(IM,grid%J_STRT_HALO:grid%J_STOP_HALO,LM),
     &        FMOM_J(NMOM,IM,grid%J_STRT_HALO:grid%J_STOP_HALO,LM)
      integer :: i,j,l,ierr,ICKERR, err_loc(3)
      REAL*8, DIMENSION(LM) ::
     &     m_sp,m_np,rm_sp,rm_np,rzm_sp,rzm_np,rzzm_sp,rzzm_np


c****Get relevant local distributed parameters
      INTEGER J_0,J_1,J_0H,J_1H
      LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
      CALL GET(grid, J_STRT = J_0,
     &               J_STOP = J_1,
     &               J_STRT_HALO = J_0H,
     &               J_STOP_HALO = J_1H,
     &               HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
     &               HAVE_NORTH_POLE = HAVE_NORTH_POLE)

c**** loop over layers
      ICKERR=0
      fqv = 0
!$OMP  PARALLEL DO PRIVATE(I,L)
!$OMP* SHARED(JM,QLIMIT,YSTRIDE)
!$OMP* REDUCTION(+:ICKERR)
      do l=1,lm

c**** scale polar boxes to their full extent
      if (HAVE_SOUTH_POLE) then
        mass(:,1,l)=mass(:,1,l)*im
        m_sp(l) = mass(1,1 ,l)
        rm(:,1,l)=rm(:,1,l)*im
        rm_sp(l) = rm(1,1 ,l)
        do i=1,im
           rmom(:,i,1 ,l)=rmom(:,i,1 ,l)*im
        enddo
        rzm_sp(l)  = rmom(mz ,1,1 ,l)
        rzzm_sp(l) = rmom(mzz,1,1 ,l)
      end if                       !SOUTH POLE

      if (HAVE_NORTH_POLE) then
        mass(:,jm,l)=mass(:,jm,l)*im
        m_np(l) = mass(1,jm,l)
        rm(:,jm,l)=rm(:,jm,l)*im
        rm_np(l) = rm(1,jm,l)
        do i=1,im
           rmom(:,i,jm,l)=rmom(:,i,jm,l)*im
        enddo
        rzm_np(l)  = rmom(mz ,1,jm,l)
        rzzm_np(l) = rmom(mzz,1,jm,l)
      end if                       !NORTH POLE

c***c**** loop over longitudes
c***      do i=1,im
c****
c**** load 1-dimensional arrays
c****
      bm   (:,:,l) = mv(:,:,l) !/nstep

c**** POLES
      IF (HAVE_SOUTH_POLE)  rmom(ihmoms,:,1,l ) = 0. ! horizontal moments are zero at pole
      IF (HAVE_NORTH_POLE) THEN
        bm(:,jm,l)= 0.
        rmom(ihmoms,:,jm,l) = 0.
      END IF
      end do
!$OMP END PARALLEL DO

c****
c**** call 1-d advection routine
c****
        call advection_1D_custom( rm(1,j_0h,1), rmom(1,1,j_0h,1), 
     &     f_j(1,j_0h,1),fmom_j(1,1,j_0h,1), mass(1,j_0h,1),
     &     bm(1,j_0h,1),j_1-j_0+1,LM,(/ (.true.,l=1,lm) /),
     &     qlimit,ystride,ydir,ierr,err_loc)

        if (ierr.gt.0) then
          write(6,*) "Error in aadvty: i,j,l=",err_loc
          if (ierr.eq.2) then
            write(0,*) "Error in qlimit: abs(b) > 1"
ccc         call stop_model('Error in qlimit: abs(b) > 1',11)
            ICKERR=ICKERR+1
          endif
        end if
! horizontal moments are zero at pole
        IF (HAVE_SOUTH_POLE) rmom(ihmoms,:,1, :) = 0
        IF (HAVE_NORTH_POLE) rmom(ihmoms,:,jm,:) = 0.


!$OMP  PARALLEL DO PRIVATE(I,L)
!$OMP* SHARED(JM,QLIMIT,YSTRIDE)
!$OMP* REDUCTION(+:ICKERR)
      do l=1,lm

c**** average and unscale polar boxes
      if (HAVE_SOUTH_POLE) then
        mass(:,1 ,l) = (m_sp(l) + sum(mass(:,1 ,l)-m_sp(l)))*byim
        rm(:,1 ,l) = (rm_sp(l) + sum(rm(:,1 ,l)-rm_sp(l)))*byim
        rmom(mz ,:,1 ,l) = (rzm_sp(l) + 
     *       sum(rmom(mz ,:,1 ,l)-rzm_sp(l) ))*byim
        rmom(mzz,:,1 ,l) = (rzzm_sp(l)+ 
     *       sum(rmom(mzz,:,1 ,l)-rzzm_sp(l)))*byim
      end if   !SOUTH POLE

      if (HAVE_NORTH_POLE) then
        mass(:,jm,l) = (m_np(l) + sum(mass(:,jm,l)-m_np(l)))*byim
        rm(:,jm,l) = (rm_np(l) + sum(rm(:,jm,l)-rm_np(l)))*byim
        rmom(mz ,:,jm,l) = (rzm_np(l) + 
     &       sum(rmom(mz ,:,jm,l)-rzm_np(l) ))*byim
        rmom(mzz,:,jm,l) = (rzzm_np(l)+ 
     &       sum(rmom(mzz,:,jm,l)-rzzm_np(l)))*byim
      end if  !NORTH POLE

      enddo ! end loop over levels
!$OMP  END PARALLEL DO
c
c     sum into fqv
c
!$OMP  PARALLEL DO PRIVATE(J,L)
      do j=J_0,J_1
        do l=1,lm
          fqv(:,j)  = fqv(:,j) + f_j(:,j,l)
        enddo                   ! l
      enddo                     ! j
!$OMP  END PARALLEL DO
      if (HAVE_NORTH_POLE) fqv(:,jm) = 0. ! not really needed
C
      IF(ICKERR.GT.0)  CALL stop_model('Stopped in aadvty',11)
C
      return
c****
      end subroutine aadvty



      subroutine aadvtz(rm,rmom,mass,mw,qlimit) 1,6
!@sum  AADVTZ advection driver for z-direction
!@auth Maxwell Kelley
c****
c**** aadvtz advects tracers in the upward vertical direction using the
c**** quadratic upstream scheme.  if qlimit is true, the moments are
c**** limited to prevent the mean tracer from becoming negative.
c****
c**** input:
c****     mw (kg) = vertical mass flux, positive upward
c****      qlimit = whether moment limitations should be used
c****
c**** input/output:
c****     rm (kg) = tracer mass
c****   rmom (kg) = moments of tracer mass
c****   mass (kg) = fluid mass
c****
      use DOMAIN_DECOMP, only : grid, GET
      use QUSDEF
ccc   use QUSCOM, only : im,jm,lm, zstride,cm,f_l,fmom_l
      use QUSCOM, only : im,jm,lm, zstride
      implicit none
      REAL*8, dimension(im,grid%j_strt_halo:grid%j_stop_halo,lm) 
     &        :: rm,mass,mw
      REAL*8, dimension(NMOM,IM,grid%j_strt_halo:grid%j_stop_halo,LM) 
     &        :: rmom
      logical ::  qlimit
      REAL*8  CM(LM),F_L(LM),FMOM_L(NMOM,LM),MASS_L(LM)
      real*8 bynstep,courmax
      integer :: i,j,l,ierr,nerr,ICKERR,ns,nstep
c**** Get useful local parameters for domain decomposition
      integer :: J_0, J_1
      CALL GET( grid, J_STRT=J_0 , J_STOP=J_1 )
c**** loop over latitudes and longitudes
      ICKERR=0
!$OMP  PARALLEL DO PRIVATE(I,J,CM,F_L,FMOM_L,IERR,NERR,
!$OMP* NSTEP,COURMAX,BYNSTEP,MASS_L,NS,L)
!$OMP* SHARED(LM,QLIMIT,ZSTRIDE)
!$OMP* REDUCTION(+:ICKERR)
      do j=J_0,J_1
      do i=1,im
c****
c**** decide how many timesteps to take
c****
      nstep=0
      courmax = 2.
      do while(courmax.gt.1. .and. nstep.lt.20)
        nstep = nstep+1
        bynstep = 1d0/real(nstep,kind=8)
        cm(:) = mw(i,j,:)*bynstep
        cm(lm) = 0.
        mass_l(:)  = mass(i,j,:)
        courmax = 0.
        do ns=1,nstep
          do l=1,lm-1
            if(cm(l).gt.0.) then
               courmax = max(courmax,+cm(l)/mass_l(l))
            else
               courmax = max(courmax,-cm(l)/mass_l(l+1))
            endif
          enddo
          if(ns.lt.nstep) then
            do l=1,lm-1
               mass_l(l  ) = mass_l(l  ) - cm(l)
               mass_l(l+1) = mass_l(l+1) + cm(l)
            enddo
          endif
        enddo
      enddo
      if(courmax.gt.1.) then
         write(6,*) 'aadvtz: i,j,courmax=',i,j,courmax
         ICKERR=ICKERR+1
      endif

c      cm(:) = mw(i,j,:)*bynstep ! cm already set
c      cm(lm)= 0.

c****
c**** loop over timesteps
c****
      do ns=1,nstep
c****
c**** call 1-d advection routine
c****
      call adv1d(rm(i,j,1),rmom(1,i,j,1),f_l,fmom_l,mass(i,j,1),
     &        cm,lm,qlimit,zstride,zdir,ierr,nerr)
      if (ierr.gt.0) then
        write(6,*) "Error in aadvtz: i,j,l=",i,j,nerr
        if (ierr.eq.2) then
          write(0,*) "Error in qlimit: abs(c) > 1"
ccc       call stop_model('Error in qlimit: abs(c) > 1',11)
          ICKERR=ICKERR+1
        endif
      end if
      enddo ! ns
      enddo ! i
      enddo ! j
!$OMP  END PARALLEL DO
C
      IF(ICKERR.GT.0) call stop_model('Stopped in aadvtz',11)
      return
c****
      end subroutine aadvtz