!
!     $Id: pdyn2.F90,v 1.1 2005/10/18 20:10:17 mbhat Exp $
!

!---(pdyn2.f)-------generic CTM shell from UCIrvine (p-code 1.0,  1/31/95)
!---subroutines:  DYN2U, DYN2V, DYN2W, QXZON, QZONX, QLIMIT, QVECT, FLIMIT


      SUBROUTINE DYN2U(DTALFA) 4,3
!---WEST-EAST ADVECTION OF TRACE COMPOUNDS---V 10.0 (S.O.M.)
      REAL*8  DTALFA
      REAL*8  QM(99),       & ! air mass in box at start, !**=REDEFINED after flow
     &        QU(100),      & ! air mass to be moved (I-1) -> (I) in advective step
     &        QBC1, QBC2  ! tracer mixing ratio boundary conditions at (1)&(99)
      LOGICAL LCYCLE      ! .T. = cyclic b.c., .F. = mixing ratio b.c.
      REAL*8     QTT(99)  !** tracer mass in box (I)
      REAL*8  QXT(99),QXX(99),      & !** 1st & 2nd moments of tracer in X-direct
     &        QXY(99),QXZ(99),      & !** coupled 1st moments including X component
     &        QYZ(99),QYT(99),QYY(99),QZT(99),QZZ(99),   & !** other SOMs without X
     &        Q0F(99+1)            !** computed tracer flux from (I-1) to (I)
#        include "uci.h"
!xx$$
      save
!xx$$
!-----------------------------------------------------------------------
      DO 50 L=1,LM
      DO 40 J=1,JM
      IF(J+J0.EQ.1 .OR. J+J0.EQ.JMX) GOTO 40      !NO E-W advect @ Poles
        IMB = IMRSLV(J+J0)
        FIMB = IMB
        N1N2 = (IMB+1)*(IMB+2)
        NQ = IM/IMB
!---for each tracer calculate 'pipe-flow' in E-W direction
      DO 30 N=1,NTRACE
!---
      IF(IMB.EQ.1) THEN
!---transfer STT() & moments into local array for piped flow
       DO I=1,NQ
        QM(I) = MAX(AD(I,J,L),0.0)
        QU(I) = ALFA(I,J,L)*DTALFA
        QTT(I) = STT(I,J,L,N)
        QXT(I) = SUT(I,J,L,N)
        QYT(I) = SVT(I,J,L,N)
        QZT(I) = SWT(I,J,L,N)
        QXX(I) = SUU(I,J,L,N)
        QYY(I) = SVV(I,J,L,N)
        QZZ(I) = SWW(I,J,L,N)
        QXY(I) = SUV(I,J,L,N)
        QXZ(I) = SUW(I,J,L,N)
        QYZ(I) = SVW(I,J,L,N)
       ENDDO
      ELSE
!---create NQ-EXTENDED ZONES near poles, assume equal masses (i.e. same Psurf)
       DO IQ=1,NQ
        I = 1 + IMB*(IQ-1)
        QU(IQ) = ALFA(I,J,L)*DTALFA
!---combine IMB equal-mass boxes beginning at I:
        CALL QXZON( STT(I,J,L,N),SUT(I,J,L,N),SUU(I,J,L,N),SUV(I,J,L,N),  &
     &       SUW(I,J,L,N),SVT(I,J,L,N),SVV(I,J,L,N),SWT(I,J,L,N),  &
     &       SWW(I,J,L,N),SVW(I,J,L,N),  AD(I,J,L), IMB,  &
     &       QTT(IQ),QXT(IQ),QXX(IQ),QXY(IQ),QXZ(IQ),QYT(IQ),QYY(IQ),  &
     &       QZT(IQ),QZZ(IQ),QYZ(IQ),QM(IQ))
       ENDDO
      ENDIF
!---WINDOWS:  tracer in (IM+1,J,L) is eastern b.c,
!---          (IM+2,J,L) is western b.c, adjacent to (1,J,L)
      IF(IM.LT.IMX) THEN
        LCYCLE = .FALSE.
        QBC1 = STT(IM+2,J,L,N)/AD(IM+2,J,L)
        QBC2 = STT(IM+1,J,L,N)/AD(IM+1,J,L)
        QU(NQ+1) = ALFA(IM+1,J,L)*DTALFA
      ELSE
!---PERIODIC boundary conditions, (IM,J,L) connects to (1,J,L)
        LCYCLE = .TRUE.
        QBC1 = 0.0
        QBC2 = 0.0
        QU(NQ+1) = 0.0
      ENDIF
!------------------------------------------------------
      CALL QVECT(QM,QU,QBC1,QBC2,NQ,LCYCLE,  LMTSOM,  &
     &    QTT,QXT,QXX,QXY,QXZ,QYT,QYY,QZT,QZZ,QYZ, Q0F)
!------------------------------------------------------
      IF(IMB.EQ.1) THEN
!---transfer Q__() back to STT() & moments
       DO I=1,NQ
        STT(I,J,L,N) = QTT(I)
        SUT(I,J,L,N) = QXT(I)
        SVT(I,J,L,N) = QYT(I)
        SWT(I,J,L,N) = QZT(I)
        SUU(I,J,L,N) = QXX(I)
        SVV(I,J,L,N) = QYY(I)
        SWW(I,J,L,N) = QZZ(I)
        SUV(I,J,L,N) = QXY(I)
        SUW(I,J,L,N) = QXZ(I)
        SVW(I,J,L,N) = QYZ(I)
       ENDDO
      ELSE
!---remap EXTENDED ZONES near poles from Q__() back to STT():
       DO IQ=1,NQ
        I = 1 + IMB*(IQ-1)
        CALL QZONX( QTT(IQ),QXT(IQ),QXX(IQ),QXY(IQ),QXZ(IQ),  &
     &       QYT(IQ),QYY(IQ),QZT(IQ),QZZ(IQ),QYZ(IQ),QM(IQ),  &
     &       STT(I,J,L,N),SUT(I,J,L,N),SUU(I,J,L,N),SUV(I,J,L,N),  &
     &       SUW(I,J,L,N),SVT(I,J,L,N),SVV(I,J,L,N),SWT(I,J,L,N),  &
     &       SWW(I,J,L,N),SVW(I,J,L,N),  AD(I,J,L), IMB,LMTSOM)
!---simple fill for W->E flux across boundaries in extended zones
         DO II=I+1,I+IMB-1
          Q0F(II) = Q0F(I)
         ENDDO
       ENDDO
      ENDIF
!---DIAGNOSTICS:  flux across meridion, into (W->E) boxes ID18/ID19
         IF(ND18.GT.0) AJL(J,L,ND18+N) = AJL(J,L,ND18+N) + Q0F(ID18)
         IF(ND19.GT.0) AJL(J,L,ND19+N) = AJL(J,L,ND19+N) + Q0F(ID19)
   30 CONTINUE
!---can NOW reset dry air mass in boxes along E-W pipe, as calculated in QVECT
      IF(IMB.EQ.1) THEN
       DO I=1,NQ
        AD(I,J,L) = QM(I)
       ENDDO
      ELSE
       DO IQ=1,NQ
        QM(IQ) = QM(IQ)/REAL(IMB)
        I = 1 + IMB*(IQ-1)
         DO II=I,I+IMB-1
          AD(II,J,L) = QM(IQ)
         ENDDO
       ENDDO
      ENDIF
   40 CONTINUE
   50 CONTINUE
      RETURN
      END


      SUBROUTINE DYN2V(DTBETA) 3,3
!---SOUTH-NORTH ADVECTION OF TRACE COMPOUNDS---V 10.0 (S.O.M.)
!xx   DOUBLE PRECISION  STTPOL, STTNP,STTSP
      real*8 STTPOL, STTNP,STTSP
      REAL*8 SWTPOL,SWWPOL,ADDPOL,SWTNP,SWTSP,SWWNP,SWWSP,ADDNP,ADDSP
      REAL*8  DTBETA
      REAL*8  QM(99),       & ! air mass in box at start, !**=REDEFINED after flow
     &        QU(100),      & ! air mass to be moved (I-1) -> (I) in advective step
     &        QBC1, QBC2  ! tracer mixing ratio boundary conditions at (1)&(99)
      LOGICAL LCYCLE      ! .T. = cyclic b.c., .F. = mixing ratio b.c.
      REAL*8     QTT(99)  !** tracer mass in box (I)
      REAL*8  QXT(99),QXX(99),      & !** 1st & 2nd moments of tracer in X-direct
     &        QXY(99),QXZ(99),      & !** coupled 1st moments including X component
     &        QYZ(99),QYT(99),QYY(99),QZT(99),QZZ(99),   & !** other SOMs without X
     &        Q0F(99+1)            !** computed tracer flux from (I-1) to (I)
!xx   DOUBLE PRECISION   ETT      ! tracer mass in extended zone
      real*8 ETT      ! tracer mass in extended zone
      REAL*8  EXT,EXX,EXY,EXZ,EYZ,EYT,EYY,EZT,EZZ,    & ! moments in extended zone
     &        EM                  ! dry air mass in extended zone
#        include "uci.h"
!xx$$
      save
!xx$$
!-----------------------------------------------------------------------
!---1st DO N-S ADVECTION IN MERIDIONAL STRIPS, 2nd SMOOTH OVER EXT.ZONES
!---assume BETA(I,J,L) has been smoothed in setups
!---WINDOWS:  southern b.c is south pole if J+J0 begins at 1 (i.e., J0=0)
!---    northern b.c. is north pole if JM+J0 = JMX
!-----------------------------------------------------------------------
      DO 60 L=1,LM
!---SETUP for poles
!---collect POLAR BOXES (pie-wedges), sum over I, and put sum in each box
!---do N-S transport with full POLAR CIRCLE for each meridion I, fix later
         DO 20 J=1,JM,JM-1
         IF(J+J0.EQ.1 .OR. J+J0.EQ.JMX) THEN
!---check if doing polar boxes, put dry air mass total in each pie-wedge
           ADDPOL = 0.D0
           DO I=1,IM
           ADDPOL = ADDPOL + AD(I,J,L)
           ENDDO
           DO I=1,IM
           AD(I,J,L) = ADDPOL
           ENDDO
!---put tracer mass & moments total in each pie-wedge, zero all moments ex W
          DO N=1,NTRACE
           STTPOL = 0.0D0
           SWTPOL = 0.0
           SWWPOL = 0.0
           DO I=1,IM
           STTPOL = STTPOL + STT(I,J,L,N)
           SWTPOL = SWTPOL + SWT(I,J,L,N)
           SWWPOL = SWWPOL + SWW(I,J,L,N)
           ENDDO
           DO I=1,IM
           STT(I,J,L,N) = STTPOL
           SWT(I,J,L,N) = SWTPOL
           SWW(I,J,L,N) = SWWPOL
           SVT(I,J,L,N) = 0.0
           SVV(I,J,L,N) = 0.0
           SUT(I,J,L,N) = 0.0
           SUU(I,J,L,N) = 0.0
           SUV(I,J,L,N) = 0.0
           SVW(I,J,L,N) = 0.0
           SUW(I,J,L,N) = 0.0
           ENDDO
          ENDDO
         ENDIF
   20    CONTINUE
!---loop over each meridion:
      DO 40 I=1,IM
!---store polar boxes for readjustment later (only used if J0=0, J0+JM=JMX)
          ADDSP = AD(I,1,L)
          ADDNP = AD(I,JM,L)
!---for each tracer calculate 'pipe-flow' in N-S direction
      DO 30 N=1,NTRACE
          STTSP = STT(I,1,L,N)
          SWTSP = SWT(I,1,L,N)
          SWWSP = SWW(I,1,L,N)
          STTNP = STT(I,JM,L,N)
          SWTNP = SWT(I,JM,L,N)
          SWWNP = SWW(I,JM,L,N)
      DO J=1,JM
        QM(J) = MAX(AD(I,J,L),0.0)
        QU(J) = BETA(I,J,L)*DTBETA
        QTT(J) = STT(I,J,L,N)
        QXT(J) = SUT(I,J,L,N)
        QYT(J) = SVT(I,J,L,N)
        QZT(J) = SWT(I,J,L,N)
        QXX(J) = SUU(I,J,L,N)
        QYY(J) = SVV(I,J,L,N)
        QZZ(J) = SWW(I,J,L,N)
        QXY(J) = SUV(I,J,L,N)
        QXZ(J) = SUW(I,J,L,N)
        QYZ(J) = SVW(I,J,L,N)
      ENDDO
!----N-S flow is never periodic:
      LCYCLE = .FALSE.
      NQ = JM
!---WINDOWS:  tracer in (I,JM+1,L) is northern b.c.
      IF(J0+JM.EQ.JMX) THEN
        QBC2 = 0.0
        QU(NQ+1) = 0.0
      ELSE
        QBC2 = STT(I,JM+1,L,N)/AD(I,JM+1,L)
        QU(NQ+1) = BETA(I,JM+1,L)*DTBETA
      ENDIF
!---WNDOWS:  tracer in (I,JM+2,L) is southern b.c, adjacent to (I,1,L)
      IF(J0.EQ.0) THEN
        QBC1 = 0.0
        QU(1) = 0.0
      ELSE
        QBC1 = STT(I,JM+2,L,N)/AD(I,JM+2,L)
      ENDIF
!---
      CALL QVECT(QM,QU,QBC1,QBC2,NQ,LCYCLE,  LMTSOM,  &
     &    QTT,QYT,QYY,QYZ,QXY,QZT,QZZ,QXT,QXX,QXZ, Q0F)
!---
      DO J=1,NQ
        STT(I,J,L,N) = QTT(J)
        SUT(I,J,L,N) = QXT(J)
        SVT(I,J,L,N) = QYT(J)
        SWT(I,J,L,N) = QZT(J)
        SUU(I,J,L,N) = QXX(J)
        SVV(I,J,L,N) = QYY(J)
        SWW(I,J,L,N) = QZZ(J)
        SUV(I,J,L,N) = QXY(J)
        SUW(I,J,L,N) = QXZ(J)
        SVW(I,J,L,N) = QYZ(J)
      ENDDO
!---now fix POLAR BOXES by removing the (IM-1) pie wedges put in for transport
!---N.B. the remaining mass (STT & AD) may be negative, and must be left so
!---  they can be averaged later
        IF(J0.EQ.0) THEN
          STT(I,1,L,N) = STT(I,1,L,N) - STTSP*REAL(IM-1)/REAL(IM)
          SWT(I,1,L,N) = SWT(I,1,L,N) - SWTSP*REAL(IM-1)/REAL(IM)
          SWW(I,1,L,N) = SWW(I,1,L,N) - SWWSP*REAL(IM-1)/REAL(IM)
        ENDIF
        IF(J0+JM.EQ.JMX) THEN
          STT(I,JM,L,N) = STT(I,JM,L,N) - STTNP*REAL(IM-1)/REAL(IM)
          SWT(I,JM,L,N) = SWT(I,JM,L,N) - SWTNP*REAL(IM-1)/REAL(IM)
          SWW(I,JM,L,N) = SWW(I,JM,L,N) - SWWNP*REAL(IM-1)/REAL(IM)
        ENDIF
!---diagnostics of north_south flux
      IF(ND10.GT.0) THEN
        JMAX = MIN(JM+1,JMX)
        DO J=1,JMAX
          AJL(J,L,N+ND10) = AJL(J,L,N+ND10) + Q0F(J)
        ENDDO
      ENDIF
!---flux across latitude circle (north = +)
      IF(ND51.GT.0) AIL(I,L,N+ND51) = AIL(I,L,N+ND51) + Q0F(JD51)
      IF(ND52.GT.0) AIL(I,L,N+ND52) = AIL(I,L,N+ND52) + Q0F(JD52)
   30 CONTINUE
!---reset dry air mass
      DO J=1,NQ
        AD(I,J,L) = QM(J)
      ENDDO
        IF(J0.EQ.0) THEN
          AD(I,1,L) = AD(I,1,L) - ADDSP*REAL(IM-1)/REAL(IM)
        ENDIF
        IF(J0+JM.EQ.JMX) THEN
          AD(I,JM,L) = AD(I,JM,L) - ADDNP*REAL(IM-1)/REAL(IM)
        ENDIF
   40 CONTINUE
   60 CONTINUE
!-----------------------------------------------------------------------
!---now average both tracer & dry air mass over EXTENDED ZONES, incl POLES
      DO 72 J=1,JM
        IMB = IMRSLV(J+J0)
        IF(IMB.EQ.1) GOTO 72
        NQ = IM/IMB
      DO 70 L=1,LM
       DO N=1,NTRACE
        DO IQ=1,NQ
        I = 1 + IMB*(IQ-1)
!---put tracer into EXTENDED ZONES near poles (assumes equal-mass boxes)
!---    NQ-zones, each of size IMB
        CALL QXZON( STT(I,J,L,N),SUT(I,J,L,N),SUU(I,J,L,N),SUV(I,J,L,N),  &
     &       SUW(I,J,L,N),SVT(I,J,L,N),SVV(I,J,L,N),SWT(I,J,L,N),  &
     &       SWW(I,J,L,N),SVW(I,J,L,N),  AD(I,J,L), IMB,  &
     &       ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM)
!---if complete zone, then zero out E-W moments (e.g., poles)
        IF(IMB.EQ.IMX) THEN
          EXT = 0.0
          EXX = 0.0
          EXY = 0.0
          EXZ = 0.0
        ENDIF
!---if polar zone, ALSO zero out N-S moments (later fix for N-S moments)
        IF(J+J0.EQ.1 .OR. J+J0.EQ.JMX) THEN
          EYT = 0.0
          EYY = 0.0
          EYZ = 0.0
        ENDIF
!---remap EXTENDED ZONES to STT():  (includes redef of AD())
        CALL QZONX( ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM,  &
     &       STT(I,J,L,N),SUT(I,J,L,N),SUU(I,J,L,N),SUV(I,J,L,N),  &
     &       SUW(I,J,L,N),SVT(I,J,L,N),SVV(I,J,L,N),SWT(I,J,L,N),  &
     &       SWW(I,J,L,N),SVW(I,J,L,N),  AD(I,J,L), IMB,LMTSOM)
        ENDDO
       ENDDO
   70 CONTINUE
   72 CONTINUE
      RETURN
      END


      SUBROUTINE DYN2W(DTGAMA) 2,1
!---------VERTICAL ADVECTION OF TRACE COMPOUNDS---V 10.0 (S.O.M.)
      REAL*8  DTGAMA
      REAL*8  QM(99),       & ! air mass in box at start, !**=REDEFINED after flow
     &        QU(100),      & ! air mass to be moved (I-1) -> (I) in advective step
     &        QBC1, QBC2  ! tracer mixing ratio boundary conditions at (1)&(99)
      LOGICAL LCYCLE      ! .T. = cyclic b.c., .F. = mixing ratio b.c.
      REAL*8     QTT(99)  !** tracer mass in box (I)
      REAL*8  QXT(99),QXX(99),      & !** 1st & 2nd moments of tracer in X-direct
     &        QXY(99),QXZ(99),      & !** coupled 1st moments including X component
     &        QYZ(99),QYT(99),QYY(99),QZT(99),QZZ(99),   & !** other SOMs without X
     &        Q0F(99+1)            !** computed tracer flux from (I-1) to (I)
#        include "uci.h"
!xx$$
      save
!xx$$
!-----------------------------------------------------------------------
!-----CALCULATE VERTICAL TRANSPORTS SEPARATELY FOR BOXES IN EXTENDED ZONE
!-----****ASSUME THAT GAMA() HAS BEEN AVERAGED OVER ZONE.****
!-----DO all pie-wedges in polar boxes (for simplicity)
!-----------------------------------------------------------------------
      DO 50 J=1,JM
      DO 40 I=1,IM
!---for each tracer calculate 'pipe-flow' in UP-DOWN direction
      DO 30 N=1,NTRACE
!---
       DO L=1,LM
        QM(L) = MAX(AD(I,J,L),0.0)
        QU(L) = GAMA(I,J,L)*DTGAMA
        QTT(L) = STT(I,J,L,N)
        QXT(L) = SUT(I,J,L,N)
        QYT(L) = SVT(I,J,L,N)
        QZT(L) = SWT(I,J,L,N)
        QXX(L) = SUU(I,J,L,N)
        QYY(L) = SVV(I,J,L,N)
        QZZ(L) = SWW(I,J,L,N)
        QXY(L) = SUV(I,J,L,N)
        QXZ(L) = SUW(I,J,L,N)
        QYZ(L) = SVW(I,J,L,N)
       ENDDO
       NQ = LM
!----vertical transport always with rigid boundaries:
        LCYCLE = .FALSE.
        QBC1 = 0.0
        QBC2 = 0.0
        QU(1) = 0.0
        QU(NQ+1) = 0.0
!---
      CALL QVECT(QM,QU,QBC1,QBC2,NQ,LCYCLE,  LMTSOM,  &
     &    QTT,QZT,QZZ,QXZ,QYZ,QXT,QXX,QYT,QYY,QXY, Q0F)
!---
       DO L=1,LM
        STT(I,J,L,N) = QTT(L)
        SUT(I,J,L,N) = QXT(L)
        SVT(I,J,L,N) = QYT(L)
        SWT(I,J,L,N) = QZT(L)
        SUU(I,J,L,N) = QXX(L)
        SVV(I,J,L,N) = QYY(L)
        SWW(I,J,L,N) = QZZ(L)
        SUV(I,J,L,N) = QXY(L)
        SUW(I,J,L,N) = QXZ(L)
        SVW(I,J,L,N) = QYZ(L)
!---have dropped 'eddy' vertical flux. need better diagnostic
        IF(ND13.GT.0) AJL(J,L,N+ND13) = AJL(J,L,N+ND13) + Q0F(L+1)
       ENDDO
!---vertical transport thru TOP of layer (LD41/2) --> (LD41/2 + 1)
!---  need to fix vertical GAMA & DIAG's to mean: L=1 -> layer (1)
       IF(ND41.GT.0) AIJ(I,J,N+ND41) = AIJ(I,J,N+ND41) + Q0F(LD41+1)
       IF(ND42.GT.0) AIJ(I,J,N+ND42) = AIJ(I,J,N+ND42) + Q0F(LD42+1)
   30 CONTINUE
!---have finished all tracers, can now reset mass in column (I,J)
       DO L=1,LM
        AD(I,J,L) = QM(L)
       ENDDO
   40 CONTINUE
   50 CONTINUE
      RETURN
      END

!-----qxzon.f, qzonx.f

      SUBROUTINE QXZON(QTT,QXT,QXX,QXY,QXZ,QYT,QYY,QZT,QZZ,QYZ,QM, NQ,  & 2
     &                 ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM)
!---Combines NQ equal mass boxes (QTT,QXT,QXX,...,QYX) aligned in X-direction
!---        into 1 Extended zone (ETT,EXT,EXX,...,EYZ)
      IMPLICIT NONE
      INTEGER NQ          ! # of boxes in initial distribution to be combined
      Real*8  QTT(NQ)  ! tracer mass in box (I)
      Real*8  QXT(NQ),QXX(NQ),      & ! 1st & 2nd moments of tracer in X-direct
     &        QXY(NQ),QXZ(NQ),      & ! coupled 1st moments including X component
     &        QYZ(NQ),QYT(NQ),QYY(NQ),QZT(NQ),QZZ(NQ),   & ! other SOMs without X
     &        QM(NQ)              ! dry air mass in box (I)
      Real*8  ETT      ! tracer mass in extended zone
      Real*8  EXT,EXX,EXY,EXZ,EYZ,EYT,EYY,EZT,EZZ,    & ! moments in extended zone
     &        EM                  ! dry air mass in extended zone
!---local variables
      Real*8  SUMT,SUMF
      Real*8  FLTNQ,FLTIQ
      INTEGER N1N2,IQ
!xx$$
      save
!xx$$
!---since assume equal-mass boxes, rescale STT() so that no spurious moments
!---  from variations in AIRD() with constant STT/AD
        SUMT = 0.D0
        SUMF = 0.D0
       DO IQ=1,NQ
        SUMT = SUMT + QTT(IQ)
        IF (QM(IQ).GT.0.D0) QTT(IQ) = QTT(IQ)/QM(IQ)
        SUMF = SUMF + QTT(IQ)
       ENDDO
       IF (SUMF.GT.0.D0) SUMT = SUMT/SUMF
       DO IQ=1,NQ
        QTT(IQ) = QTT(IQ)*SUMT
       ENDDO
!---
      FLTNQ = NQ
      N1N2 = (NQ+1)*(NQ+2)
        ETT = 0.0D0
        EXT = 0.0
        EXX = 0.0
        EXY = 0.0
        EXZ = 0.0
        EYZ = 0.0
        EYT = 0.0
        EYY = 0.0
        EZT = 0.0
        EZZ = 0.0
        EM = 0.0
!---
      DO IQ=1,NQ
        FLTIQ = REAL(IQ+IQ-NQ-1)
        ETT = ETT + QTT(IQ)
        EXT = EXT + QXT(IQ) + QTT(IQ)*FLTIQ*3.
        EYT = EYT + QYT(IQ)
        EZT = EZT + QZT(IQ)
        EXX = EXX + QXX(IQ) + QXT(IQ)*FLTIQ*5. +  &
     &        QTT(IQ)*REAL(5*(6*IQ*(IQ-NQ-1)+N1N2))
        EYY = EYY + QYY(IQ)
        EZZ = EZZ + QZZ(IQ)
        EXY = EXY + QXY(IQ) + QYT(IQ)*FLTIQ*3.
        EXZ = EXZ + QXZ(IQ) + QZT(IQ)*FLTIQ*3.
        EYZ = EYZ + QYZ(IQ)
        EM  = EM + QM(IQ)
      ENDDO
      EXT = EXT/FLTNQ
      EXX = EXX/(FLTNQ*FLTNQ)
      EXY = EXY/FLTNQ
      EXZ = EXZ/FLTNQ
      RETURN
      END


      SUBROUTINE QZONX(ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM,  & 2,1
     &           QTT,QXT,QXX,QXY,QXZ,QYT,QYY,QZT,QZZ,QYZ,QM, NQ,LIMTR)
!---Divide one Extended zone (ETT,EXT,EXX,...,EYZ) into equal-mass
!---                   boxes (QTT,QXT,QXX,...,QYX) aligned in X-direction
      IMPLICIT NONE
      Integer NQ,LIMTR ! # of boxes in initial distribution to be combined & lim
      Real*8  QTT(NQ)  ! tracer mass in box (I)
      Real*8  QXT(NQ),QXX(NQ),      & ! 1st & 2nd moments of tracer in X-direct
     &        QXY(NQ),QXZ(NQ),      & ! coupled 1st moments including X component
     &        QYZ(NQ),QYT(NQ),QYY(NQ),QZT(NQ),QZZ(NQ),   & ! other SOMs without X
     &        QM(NQ)              ! dry air mass in box (I)
      Real*8  ETT      ! tracer mass in extended zone
      Real*8  EXT,EXX,EXY,EXZ,EYZ,EYT,EYY,EZT,EZZ,    & ! moments in extended zone
     &        EM                  ! dry air mass in extended zone
!---local variables
      Real*8  ETT0,EXT0,EXX0, FLTNQ8,FLTIQ,FLTIQ2
      Real*8  FLTNQ, EXY0,EXZ0,EYZ0,EYT0,EYY0,EZT0,EZZ0,EM0
      INTEGER N1N2,IQ
!xx$$
      save
!xx$$
!---
      FLTNQ = NQ
      FLTNQ8= NQ
      N1N2 = (NQ+1)*(NQ+2)
!---N.B. have not scaled Y,Z moments (EYT,...) to ETT, because not reversible
!---must call positive limiter to ensure So > 0 in sub-boxes
      CALL QLIMIT(ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM,LIMTR)
      ETT0 = ETT/FLTNQ8
      EXT0 = EXT/(FLTNQ*FLTNQ)
      EXX0 = EXX/(FLTNQ*FLTNQ*FLTNQ)
      EXY0 = EXY/(FLTNQ*FLTNQ)
      EXZ0 = EXZ/(FLTNQ*FLTNQ)
      EYT0 = EYT/FLTNQ
      EZT0 = EZT/FLTNQ
      EYY0 = EYY/FLTNQ
      EZZ0 = EZZ/FLTNQ
      EYZ0 = EYZ/FLTNQ
      EM0  = EM/FLTNQ
      DO IQ=1,NQ
         FLTIQ = (IQ+IQ-NQ-1)
         FLTIQ2 = (6*IQ*(IQ-NQ-1)+N1N2)
        QTT(IQ) = ETT0 + FLTIQ*EXT0 + FLTIQ2*EXX0
        QXT(IQ) = EXT0 + 3.*FLTIQ*EXX0
        QXX(IQ) = EXX0
        QYT(IQ) = EYT0 + FLTIQ*EXY0
        QZT(IQ) = EZT0 + FLTIQ*EXZ0
        QXY(IQ) = EXY0
        QXZ(IQ) = EXZ0
        QYY(IQ) = EYY0
        QZZ(IQ) = EZZ0
        QYZ(IQ) = EYZ0
        QM(IQ)  = EM0
      ENDDO
      RETURN
      END


      SUBROUTINE QLIMIT(ETT,EXT,EXX,EXY,EXZ,EYT,EYY,EZT,EZZ,EYZ,EM,LIM) 2
!---Place limits on moments in box to attain some properties:
!---  LIM=0   place no constraints, allow negative tracer
!---  LIM=1   require positive definite along X-axis (averaged over Y,Z)
!---          this is the standard limiter on the original CTM
!---  LIM=2   force positive, monotonic along X-axis (averaged over Y,Z)
      IMPLICIT NONE
      INTEGER LIM
      Real*8  ETT           ! tracer mass in extended zone
      Real*8  EXT,EXX,                   & ! 1st & 2nd moments of tracer in X-direct
     & EXY,EXZ,EYZ,EYT,EYY,EZT,EZZ,      & ! other moments
     &        EM                       ! dry air mass in extended zone
      Real*8  Q0N,Q1N,Q2N,Q3N
!xx$$
      save
!xx$$
!---
      IF (LIM.EQ.0) GOTO 99
      IF (LIM.EQ.1) THEN
!---positive definite, reset Sxx to allow maximum Sx (1.5*So)
       Q0N = 0.0
       IF(ETT.GT.1.0D-35) Q0N = ETT
       Q3N = 1.499*Q0N
       Q1N = MIN(+Q3N,MAX(-Q3N,EXT))
       Q2N = MIN((Q0N+Q0N-0.334*ABS(Q1N)),MAX(ABS(Q1N)-Q0N,EXX))
       EXY = MIN(+Q0N,MAX(-Q0N,EXY))
       EXZ = MIN(+Q0N,MAX(-Q0N,EXZ))
       EXT  = Q1N
       EXX = Q2N
!---NEW, restrict other moments to +-1.5*mass
!       EYZ = MIN(+Q3N,MAX(-Q3N,EYZ))
!       EYT = MIN(+Q3N,MAX(-Q3N,EYT))
!       EYY = MIN(+Q3N,MAX(-Q3N,EYY))
!       EZT = MIN(+Q3N,MAX(-Q3N,EZT))
!       EZZ = MIN(+Q3N,MAX(-Q3N,EZZ))
      ENDIF
!-----
      IF (LIM.GE.2) THEN
       Q0N = 0.0
       IF(ETT.GT.1.0D-35) Q0N = ETT
       Q3N = 1.50*Q0N
       Q1N = EXT
       Q2N = EXX
       IF(Q2N.GT.0.0) THEN
!----do not allow reversal of curvature: Q2N > 0
        Q2N = MIN(Q2N, ABS(Q1N)/3.0, 0.50*Q0N)
        IF (Q1N.LT.0.0) THEN
          Q1N = MAX(-(Q0N+Q2N), Q1N)
        ELSE
          Q1N = MIN(+(Q0N+Q2N), Q1N)
        ENDIF
       ELSE
!------Sxx < 0 = curved down at ends, allow if Sx < So
        Q1N = MIN(+Q0N ,MAX(-Q0N, Q1N))
        Q2N = MAX(Q2N, -Q0N+ABS(Q1N), -ABS(Q1N)/3.0)
       ENDIF
       EXY = MIN(+Q0N, MAX(-Q0N, EXY))
       EXZ = MIN(+Q0N, MAX(-Q0N, EXZ))
       EXT = Q1N
       EXX = Q2N
!---NEW, restrict other moments to +-1.5*mass
       EYZ = MIN(+Q3N,MAX(-Q3N,EYZ))
       EYT = MIN(+Q3N,MAX(-Q3N,EYT))
       EYY = MIN(+Q3N,MAX(-Q3N,EYY))
       EZT = MIN(+Q3N,MAX(-Q3N,EZT))
       EZZ = MIN(+Q3N,MAX(-Q3N,EZZ))
      ENDIF
   99 RETURN
      END

!-----qvect.f: hybrid version for ZRcode tests with LIMTR=4   (mjp 9/94)

      SUBROUTINE QVECT(QM,QU,QBC1,QBC2,NQ,LCYCLE,  LIMTR,  & 4,2
     &    QTT,QXT,QXX,QXY,QXZ,QYT,QYY,QZT,QZZ,QYZ, Q0F)
! Computes SOM advection for a single 'piped flow' of tracer in the X-direction
!-----LCYCLE=.T.= connect QM(NQ) to QM(1), assume QU cyclic: QU(NQ+1)=QU(1)
!-----  =QU(1)=> BOX(1) =QU(2)=> ... =QU(NQ)=> BOX(NQ) =QU(1)=> BOX(1) ...
!-----LCYCLE=.F.= use mixing ratio b.c. at (1) and (NQ), need QU(NQ+1)
!-----  (QBC1) =QU(1)=> BOX(1) =QU(2)=>... =QU(NQ)=> BOX(NQ) =QU(NQ+1)=> (QBC2)
!
!--- LIMTR=3 = monotonic internal, with min/max from connecting boxes,
!---              QXT, QXX adjusted only.
!---       =4 = bounds, min/max limits applied to ALL X-terms: QXY, QXZ
!---       ****not recommended, smooths out strat isolines too much***
!
      IMPLICIT NONE
      INTEGER NQ,LIMTR    ! # of boxes, does not include boundary conditions&LIM
      Real*8  QM(NQ),       & ! air mass in box at start, !**=REDEFINED after flow
     &        QU(NQ+1),     & ! air mass to be moved (I-1) -> (I) in advective step
     &        QBC1, QBC2  ! tracer mixing ratio boundary conditions at (1)&(NQ)
      LOGICAL LCYCLE      ! .T. = cyclic b.c., .F. = mixing ratio b.c.
      Real*8  QTT(NQ)  !** tracer mass in box (I)
      Real*8  QXT(NQ),QXX(NQ),      & !** 1st & 2nd moments of tracer in X-direct
     &        QXY(NQ),QXZ(NQ),      & !** coupled 1st moments including X component
     &        QYZ(NQ),QYT(NQ),QYY(NQ),QZT(NQ),QZZ(NQ),   & !** other SOMs without X
     &        Q0F(NQ+1)            !** computed tracer flux from (I-1) to (I)
!-----local variables:
      Real*8  FTT(99)                      !parallel to QTT
      Real*8  FXT(99),FXX(99),FYT(99),FZT(99),FXY(99),FXZ(99),FYY(99),  &
     &        FZZ(99),FYZ(99)                    !parallel to Q__s
      Real*8  EPS,EPSQ,EPS1,EPS1Q,EPS0,  QTT4
      REAL*8  FTTMX(99),FTTMN(99),FTTMX0(99),FTTMN0(99)
      REAL*8  FMAX,FMIN, F0,F1,F2,F0X,FSUM
      real*8  arg1,arg2
      INTEGER I           ! counter
!xx$$
      save
!xx$$
!
      IF(LIMTR.GT.0) THEN
      IF(LIMTR.LE.2) THEN
!----LIMTR = 1:2
!-----restrain moments (only positive tracer transport) BEFORE transport
        DO I=1,NQ
         CALL QLIMIT(QTT(I),QXT(I),QXX(I),  &
     &    QXY(I),QXZ(I),QYT(I),QYY(I),QZT(I),QZZ(I),QYZ(I),QM(I),LIMTR)
        ENDDO
      ELSE
!----LIMTR = 3:4
!---calculate initial MIN/MAX of tracer mix ratio in each box, limit x-terms
        DO I=1,NQ
          QTT4 = QTT(I)
          arg1=-1.5*QTT4
          arg2=QXY(I)
          arg2=MAX(arg1,arg2)
          QXY(I) = MIN(+1.5*QTT4,arg2)
          arg1=-1.5*QTT4
          arg2=QXZ(I)
          arg2=MAX(arg1,arg2)
          QXZ(I) = MIN(+1.5*QTT4,arg2)
! option   QYZ(I) = MIN(+1.5*QTT4,MAX(-1.5*QTT4, QYZ(I)))
!          QYT(I) = MIN(+1.5*QTT4,MAX(-1.5*QTT4, QYT(I)))
!          QYY(I) = MIN(+1.5*QTT4,MAX(-1.5*QTT4, QYY(I)))
!          QZT(I) = MIN(+1.5*QTT4,MAX(-1.5*QTT4, QZT(I)))
!          QZZ(I) = MIN(+1.5*QTT4,MAX(-1.5*QTT4, QZZ(I)))
          F0 = QTT(I)/QM(I)
          F1 =  ABS(QXT(I)) /QM(I)
          IF(LIMTR.EQ.4)  &
     &    F1 = ( ABS(QXT(I)) + ABS(QXY(I)) + ABS(QXZ(I)) )/QM(I)
          F2 = QXX(I)/QM(I)
          FTTMN0(I) = F0 - F1 + F2
          FTTMX0(I) = F0 + F1 + F2
!---NB this extra test, OR the write above, saves a zero divide that probably
!--- results from the optimization of the F0X calc before the IF test.
          IF(ABS(F2).GT.0.0) THEN
          IF(3.*ABS(F2).GT.F1) THEN     ! local extrema in interval
            F0X = F0 - F1*F1/(6.*F2) - 0.5*F2
            FTTMN0(I) = MIN(FTTMN0(I),F0X)
            FTTMX0(I) = MAX(FTTMX0(I),F0X)
          ENDIF
          ENDIF
          FTTMN(I) = FTTMN0(I)
          FTTMX(I) = FTTMX0(I)
        ENDDO
      ENDIF
      ENDIF

!---clear moments/fluxes between boxes (I-1) & (I):
        DO I=1,NQ+1
          Q0F(I) = 0.0
          FTT(I) = 0.0
          FXT(I) = 0.0
          FXX(I) = 0.0
          FYT(I) = 0.0
          FYY(I) = 0.0
          FZT(I) = 0.0
          FZZ(I) = 0.0
          FXY(I) = 0.0
          FXZ(I) = 0.0
          FYZ(I) = 0.0
        ENDDO
!---Calculate transport for all interior faces:  I = 2, NQ
!---QU(I) = mass FLUX across boundary:  BOX(I-1) <-> BOX(I)
      DO 24 I=2,NQ
      IF(QU(I).EQ.0.) GOTO 24
!---QU(I) = 0  ==>  do nothing if no mass flow across boundary
      IF(QU(I).LT.0.) GOTO 22
!---QU(I) > 0  ==>  FLUX FROM (I-1) -> (I)
!---FLUX limited by CURRENT mass in box (I-1) (cant get blood from a stone)
      IF(QM(I-1).LE.0.0) GOTO 24
        EPS = QU(I)/QM(I-1)
        arg1 = EPS
        EPS = MIN(arg1, 1.0)
        EPSQ = EPS*EPS
        EPS1 = 1.0 - EPS
        EPS1Q = EPS1*EPS1
!---COMPUTE moments of tracer in the parcel transferring from (I-1) to (I)
       FTT(I) = EPS*(QTT(I-1) + EPS1*(QXT(I-1) + (EPS1-EPS)*QXX(I-1)))
         IF(LIMTR.GT.0) FTT(I) = MIN(MAX(FTT(I), 0.D0), QTT(I-1))
       FXT(I) = EPSQ*(QXT(I-1)+3.0*EPS1*QXX(I-1))
       FXX(I) = EPS*EPSQ*QXX(I-1)
       FYT(I) = EPS*(QYT(I-1) + EPS1*QXY(I-1))
       FZT(I) = EPS*(QZT(I-1) + EPS1*QXZ(I-1))
       FXY(I) = EPSQ*QXY(I-1)
       FXZ(I) = EPSQ*QXZ(I-1)
       FYY(I) = EPS*QYY(I-1)
       FZZ(I) = EPS*QZZ(I-1)
       FYZ(I) = EPS*QYZ(I-1)
!---READJUST air mass and tracer moments remaining in box (I-1)
       QM(I-1) = QM(I-1) - QU(I)
       QTT(I-1) = QTT(I-1) - FTT(I)
       QXT(I-1) = EPS1Q*(QXT(I-1) - 3.0*EPS*QXX(I-1))
       QXX(I-1) = EPS1*EPS1Q*QXX(I-1)
       QYT(I-1) = QYT(I-1) - FYT(I)
       QYY(I-1) = QYY(I-1) - FYY(I)
       QZT(I-1) = QZT(I-1) - FZT(I)
       QZZ(I-1) = QZZ(I-1) - FZZ(I)
       QXY(I-1) = EPS1Q*QXY(I-1)
       QXZ(I-1) = EPS1Q*QXZ(I-1)
       QYZ(I-1) = QYZ(I-1) - FYZ(I)
!---diagnostic flux across boundary:
       Q0F(I) = +FTT(I)
      GOTO 24
   22 CONTINUE
!---QU(I) < 0  ==>  FLUX FROM (I) -> (I-1=I-1)
       IF(QM(I).LE.0.0) GOTO 24
        EPS = -QU(I)/QM(I)
        arg1=EPS
        EPS = MIN(arg1, 1.0)
        EPSQ = EPS*EPS
        EPS1 = 1.0 - EPS
        EPS1Q = EPS1*EPS1
!---COMPUTE moments of tracer in the parcel transferring from (I) to (I-1)
       FTT(I) = EPS*(QTT(I) - EPS1*(QXT(I) - (EPS1-EPS)*QXX(I)))
          IF(LIMTR.GT.0) FTT(I) = MIN(MAX(FTT(I), 0.D0), QTT(I))
       FXT(I) = EPSQ*(QXT(I)-3.0*EPS1*QXX(I))
       FXX(I) = EPS*EPSQ*QXX(I)
       FYT(I) = EPS*(QYT(I) - EPS1*QXY(I))
       FZT(I) = EPS*(QZT(I) - EPS1*QXZ(I))
       FXY(I) = EPSQ*QXY(I)
       FXZ(I) = EPSQ*QXZ(I)
       FYY(I) = EPS*QYY(I)
       FZZ(I) = EPS*QZZ(I)
       FYZ(I) = EPS*QYZ(I)
!---READJUST air mass and tracer moments remaining in box (I) if not b.c.
       QM(I) = QM(I) + QU(I)
       QTT(I) = QTT(I) - FTT(I)
       QXT(I) = EPS1Q*(QXT(I) + 3.0*EPS*QXX(I))
       QXX(I) = EPS1*EPS1Q*QXX(I)
       QYT(I) = QYT(I) - FYT(I)
       QYY(I) = QYY(I) - FYY(I)
       QZT(I) = QZT(I) - FZT(I)
       QZZ(I) = QZZ(I) - FZZ(I)
       QXY(I) = EPS1Q*QXY(I)
       QXZ(I) = EPS1Q*QXZ(I)
       QYZ(I) = QYZ(I) - FYZ(I)
!---diagnostic flux across boundary:
       Q0F(I) = -FTT(I)
   24 CONTINUE
!---end loop over internal faces

!---B.C. calculate transport for edge faces (boundary conditions):  1 & NQ+1
      IF (LCYCLE) THEN
        QU(NQ+1) = QU(1)
!---Connect (NQ) with (1) using air mass flux = QU(1), structure as above
       IF(QU(1).EQ.0.) GOTO 27
       IF(QU(1).LT.0.) GOTO 25
       IF(QM(NQ).LE.0.0) GOTO 27
!---QU(1)>0 flow from (NQ) to (1)
          EPS = QU(1)/QM(NQ)
          arg1=eps
           EPS = MIN(arg1, 1.0)
          EPSQ = EPS*EPS
          EPS1 = 1.0 - EPS
          EPS1Q = EPS1*EPS1
        FTT(1) = EPS*(QTT(NQ) + EPS1*(QXT(NQ) + (EPS1-EPS)*QXX(NQ)))
          IF(LIMTR.GT.0) FTT(1) = MIN(MAX(FTT(1), 0.D0), QTT(NQ))
        FXT(1) = EPSQ*(QXT(NQ)+3.0*EPS1*QXX(NQ))
        FXX(1) = EPS*EPSQ*QXX(NQ)
        FYT(1) = EPS*(QYT(NQ) + EPS1*QXY(NQ))
        FZT(1) = EPS*(QZT(NQ) + EPS1*QXZ(NQ))
        FXY(1) = EPSQ*QXY(NQ)
        FXZ(1) = EPSQ*QXZ(NQ)
        FYY(1) = EPS*QYY(NQ)
        FZZ(1) = EPS*QZZ(NQ)
        FYZ(1) = EPS*QYZ(NQ)
!---READJUST air mass and tracer moments remaining in box (NQ)
        QM(NQ) = QM(NQ) - QU(1)
        QTT(NQ) = QTT(NQ) - FTT(1)
        QXT(NQ) = EPS1Q*(QXT(NQ) - 3.0*EPS*QXX(NQ))
        QXX(NQ) = EPS1*EPS1Q*QXX(NQ)
        QYT(NQ) = QYT(NQ) - FYT(1)
        QYY(NQ) = QYY(NQ) - FYY(1)
        QZT(NQ) = QZT(NQ) - FZT(1)
        QZZ(NQ) = QZZ(NQ) - FZZ(1)
        QXY(NQ) = EPS1Q*QXY(NQ)
        QXZ(NQ) = EPS1Q*QXZ(NQ)
        QYZ(NQ) = QYZ(NQ) - FYZ(1)
!---flux diagnostic
        Q0F(1) = +FTT(1)
       GOTO 26
   25  CONTINUE
       IF(QM(1).LE.0.0) GOTO 26
!---flow from (1) to (NQ+1)
         EPS = -QU(1)/QM(1)
         arg1=eps
           EPS = MIN(arg1, 1.0)
         EPSQ = EPS*EPS
         EPS1 = 1.0 - EPS
         EPS1Q = EPS1*EPS1
        FTT(1) = EPS*(QTT(1) - EPS1*(QXT(1) - (EPS1-EPS)*QXX(1)))
          IF(LIMTR.GT.0) FTT(1) = MIN(MAX(FTT(1), 0.D0), QTT(1))
        FXT(1) = EPSQ*(QXT(1)-3.0*EPS1*QXX(1))
        FXX(1) = EPS*EPSQ*QXX(1)
        FYT(1) = EPS*(QYT(1) - EPS1*QXY(1))
        FZT(1) = EPS*(QZT(1) - EPS1*QXZ(1))
        FXY(1) = EPSQ*QXY(1)
        FXZ(1) = EPSQ*QXZ(1)
        FYY(1) = EPS*QYY(1)
        FZZ(1) = EPS*QZZ(1)
        FYZ(1) = EPS*QYZ(1)
!---READJUST air mass and tracer moments remaining in box (1)
        QM(1) = QM(1) + QU(1)
        QTT(1) = QTT(1) - FTT(1)
        QXT(1) = EPS1Q*(QXT(1) + 3.0*EPS*QXX(1))
        QXX(1) = EPS1*EPS1Q*QXX(1)
        QYT(1) = QYT(1) - FYT(1)
        QYY(1) = QYY(1) - FYY(1)
        QZT(1) = QZT(1) - FZT(1)
        QZZ(1) = QZZ(1) - FZZ(1)
        QXY(1) = EPS1Q*QXY(1)
        QXZ(1) = EPS1Q*QXZ(1)
        QYZ(1) = QYZ(1) - FYZ(1)
!---flux diagnostic
        Q0F(1) = -FTT(1)
!----equate (0)-(1) fluxes with (NQ)-(NQ+1) fluxes
   26  CONTINUE
        FTT(NQ+1) = FTT(1)
        FXT(NQ+1) = FXT(1)
        FXX(NQ+1) = FXX(1)
        FYT(NQ+1) = FYT(1)
        FYY(NQ+1) = FYY(1)
        FZT(NQ+1) = FZT(1)
        FZZ(NQ+1) = FZZ(1)
        FXY(NQ+1) = FXY(1)
        FXZ(NQ+1) = FXZ(1)
        FYZ(NQ+1) = FYZ(1)
        Q0F(NQ+1) = Q0F(1)
   27  CONTINUE
      ELSE
!---LCYCLE = .F.    connect QBC1 with (1) using air mass flux = QU(1)
!---    and QBC2 with (NQ) using air mass flux = QU(NQ+1)
       IF(QU(1).EQ.0.) GOTO 28
       IF(QU(1).GT.0.) THEN
!--- bring in air with QBC1 mixing ratio, no moments
        FTT(1) = QBC1*QU(1)
        FXT(1) = 0.0
        FXX(1) = 0.0
        FYT(1) = 0.0
        FZT(1) = 0.0
        FXY(1) = 0.0
        FXZ(1) = 0.0
        FYY(1) = 0.0
        FZZ(1) = 0.0
        FYZ(1) = 0.0
       ELSE
!--- take air out of (1) and throw away
        IF(QM(1).GT.0.0) THEN
         EPS = -QU(1)/QM(1)
           arg1=EPS
           EPS = MIN(arg1, 1.0)
         EPSQ = EPS*EPS
         EPS1 = 1.0 - EPS
         EPS1Q = EPS1*EPS1
        FTT(1) = EPS*(QTT(1) - EPS1*(QXT(1) - (EPS1-EPS)*QXX(1)))
          IF(LIMTR.GT.0) FTT(1) = MIN(MAX(FTT(1), 0.D0), QTT(1))
!       FXT(1) = EPSQ*(QXT(1)-3.0*EPS1*QXX(1))
!       FXX(1) = EPS*EPSQ*QXX(1)
        FYT(1) = EPS*(QYT(1) - EPS1*QXY(1))
        FZT(1) = EPS*(QZT(1) - EPS1*QXZ(1))
        FYY(1) = EPS*QYY(1)
        FZZ(1) = EPS*QZZ(1)
!       FXY(1) = EPSQ*QXY(1)
!       FXZ(1) = EPSQ*QXZ(1)
        FYZ(1) = EPS*QYZ(1)
        QM(1) = QM(1) + QU(1)
        QTT(1) = QTT(1) - FTT(1)
        QXT(1) = EPS1Q*(QXT(1) + 3.0*EPS*QXX(1))
        QXX(1) = EPS1*EPS1Q*QXX(1)
        QYT(1) = QYT(1) - FYT(1)
        QZT(1) = QZT(1) - FZT(1)
        QYY(1) = QYY(1) - FYY(1)
        QZZ(1) = QZZ(1) - FZZ(1)
        QXY(1) = EPS1Q*QXY(1)
        QXZ(1) = EPS1Q*QXZ(1)
        QYZ(1) = QYZ(1) - FYZ(1)
        ENDIF
       ENDIF
   28  CONTINUE
       IF(QU(NQ+1).EQ.0.) GOTO 29
       IF(QU(NQ+1).GT.0.) THEN
!--- take air out of (NQ) and throw away
        IF(QM(NQ).GT.0.0) THEN
          EPS = QU(NQ+1)/QM(NQ)
            arg1=EPS
            EPS = MIN(arg1, 1.0)
          EPSQ = EPS*EPS
          EPS1 = 1.0 - EPS
          EPS1Q = EPS1*EPS1
         FTT(NQ+1) = EPS*(QTT(NQ) + EPS1*(QXT(NQ) + (EPS1-EPS)*QXX(NQ)))
          IF(LIMTR.GT.0) FTT(NQ+1) = MIN(MAX(FTT(NQ+1), 0.D0), QTT(NQ))
!        FXT(NQ+1) = EPSQ*(QXT(NQ)+3.0*EPS1*QXX(NQ))
!        FXX(NQ+1) = EPS*EPSQ*QXX(NQ)
         FYT(NQ+1) = EPS*(QYT(NQ) + EPS1*QXY(NQ))
         FZT(NQ+1) = EPS*(QZT(NQ) + EPS1*QXZ(NQ))
         FYY(NQ+1) = EPS*QYY(NQ)
         FZZ(NQ+1) = EPS*QZZ(NQ)
!        FXY(NQ+1) = EPSQ*QXY(NQ)
!        FXZ(NQ+1) = EPSQ*QXZ(NQ)
         FYZ(NQ+1) = EPS*QYZ(NQ)
         QM(NQ) =  QM(NQ) - QU(NQ+1)
         QTT(NQ) = QTT(NQ) - FTT(NQ+1)
         QXT(NQ) = EPS1Q*(QXT(NQ) - 3.0*EPS*QXX(NQ))
         QXX(NQ) = EPS1*EPS1Q*QXX(NQ)
         QYT(NQ) = QYT(NQ) - FYT(NQ+1)
         QYY(NQ) = QYY(NQ) - FYY(NQ+1)
         QZT(NQ) = QZT(NQ) - FZT(NQ+1)
         QZZ(NQ) = QZZ(NQ) - FZZ(NQ+1)
         QXY(NQ) = EPS1Q*QXY(NQ)
         QXZ(NQ) = EPS1Q*QXZ(NQ)
         QYZ(NQ) = QYZ(NQ) - FYZ(NQ+1)
        ENDIF
       ELSE
!--- bring in air with QBC2 mixing ratio, no moments
         FTT(NQ+1) = -QBC2*QU(NQ+1)
         FXT(NQ+1) = 0.0
         FXX(NQ+1) = 0.0
         FYT(NQ+1) = 0.0
         FZT(NQ+1) = 0.0
         FXY(NQ+1) = 0.0
         FXZ(NQ+1) = 0.0
         FYY(NQ+1) = 0.0
         FZZ(NQ+1) = 0.0
         FYZ(NQ+1) = 0.0
       ENDIF
   29  CONTINUE
      ENDIF
!---end of separating pieces (LCYCLE if/then/else)

!---NOW can put back the intermediate 'zones' at the interfaces of the grid
      DO 44 I=2,NQ
      IF(QU(I).EQ.0.) GOTO 44
!---QU(I) = 0  ==>  do nothing if no mass flow across boundary
!---QU(I) > 0  ==>  intermediate transfer box (I) goes into (I)
      IF(QU(I).GT.0.) THEN
       QM(I) = QM(I) + QU(I)
         EPS = QU(I)/QM(I)
         EPS1 = 1.0 - EPS
         EPS0 = EPS*QTT(I) - EPS1*FTT(I)
!------N.B. Be careful about order of following statements:
       QXX(I) = EPS*EPS*FXX(I) + EPS1*EPS1*QXX(I)  &
     &   + 5.*(EPS*EPS1*(QXT(I)-FXT(I)) - (EPS1-EPS)*EPS0)
       QXT(I) = EPS*FXT(I) + EPS1*QXT(I) + 3.0*EPS0
       QTT(I) = QTT(I) + FTT(I)
       QXY(I) = EPS*FXY(I) + EPS1*QXY(I) + 3.*(-EPS1*FYT(I)+EPS*QYT(I))
       QXZ(I) = EPS*FXZ(I) + EPS1*QXZ(I) + 3.*(-EPS1*FZT(I)+EPS*QZT(I))
       QYT(I) = QYT(I) + FYT(I)
       QZT(I) = QZT(I) + FZT(I)
       QYY(I) = QYY(I) + FYY(I)
       QZZ(I) = QZZ(I) + FZZ(I)
       QYZ(I) = QYZ(I) + FYZ(I)
      ELSE
!---QU(I) < 0  ==>  intermediate transfer box (I) goes into (I-1)
       QM(I-1) = QM(I-1) - QU(I)
        EPS = -QU(I)/QM(I-1)
        EPS1 = 1.0 - EPS
        EPS0 = -EPS*QTT(I-1) + EPS1*FTT(I)
       QXX(I-1) = EPS*EPS*FXX(I) + EPS1*EPS1*QXX(I-1)  &
     &   + 5.*(EPS*EPS1*(-QXT(I-1)+FXT(I)) + (EPS1-EPS)*EPS0)
       QXT(I-1) = EPS*FXT(I) + EPS1*QXT(I-1) + 3.0*EPS0
       QTT(I-1) = QTT(I-1) + FTT(I)
       QXY(I-1)=EPS*FXY(I)+EPS1*QXY(I-1) + 3.*(EPS1*FYT(I)-EPS*QYT(I-1))
       QXZ(I-1)=EPS*FXZ(I)+EPS1*QXZ(I-1) + 3.*(EPS1*FZT(I)-EPS*QZT(I-1))
       QYT(I-1) = QYT(I-1) + FYT(I)
       QZT(I-1) = QZT(I-1) + FZT(I)
       QYY(I-1) = QYY(I-1) + FYY(I)
       QZZ(I-1) = QZZ(I-1) + FZZ(I)
       QYZ(I-1) = QYZ(I-1) + FYZ(I)
      ENDIF
   44 CONTINUE
!---end loop over internal faces, now fix b.c.
!-----do boundary at (1) if transport out of box (1)
      IF(QU(1).GT.0.0) THEN
        QM(1) = QM(1) + QU(1)
         EPS = QU(1)/QM(1)
         EPS1 = 1.0 - EPS
         EPS0 = EPS*QTT(1) - EPS1*FTT(1)
!---N.B. Be careful about order of following statements:
        QXX(1) = EPS*EPS*FXX(1) + EPS1*EPS1*QXX(1)  &
     &   + 5.*(EPS*EPS1*(QXT(1)-FXT(1)) - (EPS1-EPS)*EPS0)
        QXT(1) = EPS*FXT(1) + EPS1*QXT(1) + 3.0*EPS0
        QTT(1) = QTT(1) + FTT(1)
        QXY(1) = EPS*FXY(1) + EPS1*QXY(1) + 3.*(-EPS1*FYT(1)+EPS*QYT(1))
        QXZ(1) = EPS*FXZ(1) + EPS1*QXZ(1) + 3.*(-EPS1*FZT(1)+EPS*QZT(1))
        QYT(1) = QYT(1) + FYT(1)
        QZT(1) = QZT(1) + FZT(1)
        QYY(1) = QYY(1) + FYY(1)
        QZZ(1) = QZZ(1) + FZZ(1)
        QYZ(1) = QYZ(1) + FYZ(1)
      ENDIF
!-----do boundary at NQ+1 if transport out of box (NQ)
      IF(QU(NQ+1).LT.0.0) THEN
        QM(NQ) = QM(NQ) - QU(1)
         EPS = -QU(1)/QM(NQ)
         EPS1 = 1.0 - EPS
         EPS0 = -EPS*QTT(NQ) + EPS1*FTT(NQ+1)
!---N.B. Be careful about order of following statements:
        QXX(NQ) = EPS*EPS*FXX(NQ+1) + EPS1*EPS1*QXX(NQ)  &
     &   + 5.*(EPS*EPS1*(-QXT(NQ)+FXT(NQ+1)) + (EPS1-EPS)*EPS0)
        QXT(NQ) = EPS*FXT(NQ+1) + EPS1*QXT(NQ) + 3.0*EPS0
        QTT(NQ) = QTT(NQ) + FTT(NQ+1)
      QXY(NQ)=EPS*FXY(NQ+1)+EPS1*QXY(NQ)+3.*(EPS1*FYT(NQ+1)-EPS*QYT(NQ))
      QXZ(NQ)=EPS*FXZ(NQ+1)+EPS1*QXZ(NQ)+3.*(EPS1*FZT(NQ+1)-EPS*QZT(NQ))
        QYT(NQ) = QYT(NQ) + FYT(NQ+1)
        QZT(NQ) = QZT(NQ) + FZT(NQ+1)
        QYY(NQ) = QYY(NQ) + FYY(NQ+1)
        QZZ(NQ) = QZZ(NQ) + FZZ(NQ+1)
        QYZ(NQ) = QYZ(NQ) + FYZ(NQ+1)
      ENDIF

      IF(LIMTR.GE.3) THEN        !special section for LIMTR=3:4
!---NOW APPLY MIN/MAX TRANSPORT BOXES:
      DO 52 I=2,NQ
       IF(QU(I).EQ.0.) GOTO 52
       IF(QU(I).GT.0.) THEN
!---QU(I) > 0  ==>  (I-1) into (I)
         FTTMX(I) = MAX(FTTMX0(I-1),FTTMX(I))
         FTTMN(I) = MIN(FTTMN0(I-1),FTTMN(I))
       ELSE
!---QU(I) < 0  ==>  (I) goes into (I-1)
         FTTMX(I-1) = MAX(FTTMX(I-1),FTTMX0(I))
         FTTMN(I-1) = MIN(FTTMN(I-1),FTTMN0(I))
       ENDIF
   52 CONTINUE
!---B.C.
      IF (LCYCLE) THEN            !CYCLIC, connect (1) to (NQ)
       IF(QU(1).GT.0.) THEN
!---QU(1)>0 flow from (NQ) into (1)
         FTTMX(1) = MAX(FTTMX0(NQ),FTTMX(1))
         FTTMN(1) = MIN(FTTMN0(NQ),FTTMN(1))
        ELSE
!---flow from (1) into (NQ)
         FTTMX(NQ) = MAX(FTTMX0(1),FTTMX(NQ))
         FTTMN(NQ) = MIN(FTTMN0(1),FTTMN(NQ))
        ENDIF
      ELSE                        !connect QBC1 with (1), QBC2 with (NQ)
       IF(QU(1).GT.0.) THEN
         FTTMX(1) = MAX(QBC1,FTTMX(1))
         FTTMN(1) = MIN(QBC1,FTTMN(1))
       ENDIF
       IF(QU(NQ+1).LT.0.) THEN
         FTTMX(NQ) = MAX(QBC2,FTTMX(NQ))
         FTTMN(NQ) = MIN(QBC2,FTTMN(NQ))
       ENDIF
      ENDIF
!---now place limits on X-moments:  QXY & QXZ only changed if LIMTR=4
      DO I=1,NQ
        FMIN = FTTMN(I)*QM(I)
        FMAX = FTTMX(I)*QM(I)
        FSUM = QTT(I)
        CALL FLIMIT(FSUM,QXT(I),QXY(I),QXZ(I),QXX(I),FMIN,FMAX,LIMTR)
      ENDDO
      ENDIF           !end of LIMTR=3:4 section

      RETURN
      END


      SUBROUTINE FLIMIT(F0,F1,F1A,F1B,F2,FMIN,FMAX,LIM) 1
!---given moments/mass = mixing ratio moments: F0,F1,F2, and FMIN<FMAX
!---adjust the moments to be monotonic, within limits
!---the cross-moments (eg, F1A=x-y, F1B=x-z) are also limited!
      IMPLICIT NONE
      REAL*8 F0,F1,F1A,F1B,F2, FMIN,FMAX
      INTEGER LIM
      REAL*8 FFMAX,FFMIN,EXCESS,SLACK,FX,FX0
      real*8 arg1,arg2
!xx$$
      save
!xx$$
!---FX is positive slope (true in some direction), rescale F1,F1A,F1B later
      FX = ABS(F1)
      IF(LIM.EQ.4)  FX = ABS(F1) + ABS(F1A) + ABS(F1B)
!---check on reasonableness of limits:
      IF(FMAX.LT.F0 .OR. FMIN.GT.F0 .OR. FX.LE.0.0) THEN
        F1 = 0.0
        F1A= 0.0
        F1B= 0.0
        F2 = 0.0
        GOTO 99
      ENDIF
      FX0 = FX
!---limit slope by max-min range
      arg1=FX
      arg2=0.5*(FMAX-FMIN)
      FX = MIN(arg1,arg2)
!---force F2 to be monotonic within range (0,1), x(extrema) = 1/2 - 1/6*(b/c)
      IF(F2.GT.0.0) THEN
        arg1=F2
        arg2=FX/3.
        F2 = MIN(arg1,arg2)
      ELSE
        arg1=F2
        arg2=-FX/3.
        F2 = MAX(arg1,arg2)
      ENDIF
!---check if internal Max exceeds specified (FMAX)
      FFMAX = F0+FX+F2
      IF(FFMAX.GT.FMAX) THEN
!---EXCESS = amount beyond max allowed, SLACK = amount that can be taken
!---         from FX without violating monotonicity
        EXCESS = FFMAX - FMAX
        arg2=FX-3.*ABS(F2)
        arg1=EXCESS
        SLACK = MIN(arg1, arg2)
        IF(SLACK.GT.0.0) THEN
          FX = FX - SLACK
!---force F2 to be monotonic again
          IF(F2.GT.0.0) THEN
            arg1=F2
            arg2=FX/3.
            F2 = MIN(arg1,arg2)
          ELSE
            arg1=F2
            arg2=-FX/3.
            F2 = MAX(arg1,arg2)
          ENDIF
        ENDIF
!---now correct FX & F2 simultaneously for remaining excess:
        EXCESS = EXCESS - SLACK
        IF(EXCESS.GT.0.0) THEN
          IF(F2.GT.0.0) THEN
            F2 = F2 - 0.25*EXCESS
            FX = FX - 0.75*EXCESS
          ELSE
            F2 = F2 + 0.5*EXCESS
            FX = FX - 1.5*EXCESS
          ENDIF
        ENDIF
      ENDIF       ! end of fix if FFMAX>FMAX
!---now repeat for Min value:
      FFMIN = F0-FX+F2
      IF(FFMIN.LT.FMIN) THEN
        EXCESS = FMIN - FFMIN
        arg1=EXCESS
        arg2=FX-3.*ABS(F2)
        SLACK = MIN(arg1, arg2)
        IF(SLACK.GT.0.0) THEN
          FX = FX - SLACK
!---force F2 to be monotonic again
          IF(F2.GT.0.0) THEN
            arg1=F2
            arg2=FX/3.
            F2 = MIN(arg1,arg2)
          ELSE
            arg1=F2
            arg2=-FX/3.
            F2 = MAX(arg1,arg2)
          ENDIF
        ENDIF
!---now correct FX & F2 simultaneously for remaining excess:
        EXCESS = EXCESS - SLACK
        IF(EXCESS.GT.0.0) THEN
          IF(F2.GT.0.0) THEN
            F2 = F2 - 0.5*EXCESS
            FX = FX - 1.5*EXCESS
          ELSE
            F2 = F2 + 0.25*EXCESS
            FX = FX - 0.75*EXCESS
          ENDIF
        ENDIF
      ENDIF       ! end of fix if FFMAX>FMAX
!-----rescale the F1's
      F1  = F1  *(FX/FX0)
      IF(LIM.EQ.4) THEN
        F1A = F1A *(FX/FX0)
        F1B = F1B *(FX/FX0)
      ENDIF
   99 RETURN
      END