subroutine advc1d(kk,fld,z,dz,vrbos,errcon) 2
c
c --- ppm-based 1-dim transport routine, extracted from fct3d.f
c --- originator: rainer bleck^
c
c --- kk       - number of layers
c --- fld(kk)  - mixing ratio of dependent variable in each layer
c --- z(kk+1)  - interface depth; z(k+1)-z(k) = thickness of layer k
c --- dz(kk+1) - elements of -fld- travel from z(k)-dz(k) to z(k) during
c ---            present time step
c --- vrbos    - if .true., print diagnostic messages
c --- errcon   - set to .true. if error condition encountered
c
      implicit none
      integer, intent(IN) :: kk
      real,    intent(IN) :: z(kk+1),dz(kk+1)
      real, intent(INOUT) :: fld(kk)
      logical, intent(IN) :: vrbos
      logical,intent(OUT) :: errcon
c
      real thk(kk),flux(kk+1),div(kk)
      real a(kk),b(kk),c(kk),dx,fcdx,yl,yr
      real amount,bfore,after,scale,slab,dslab
      integer k,kp
      real, parameter :: athird=1./3.
      real, parameter :: small=1.e-11   !  (for z,dz given in meters)
c
cdiag if (vrbos) write (*,100)
cdiag. 'entering advc1d:  old loc''n  new loc''n   variable',
cdiag. (k,z(k),z(k)+dz(k),fld(k),k=1,kk),kk+1,z(kk+1),z(kk+1)+dz(kk+1)
 100  format (a/(i15,2f11.3,es12.3))
c
      bfore=0.
      scale=1.e-33
      do k=1,kk
        thk(k)=z(k+1)-z(k)
        bfore=bfore+fld(k)*thk(k)
        scale=max(scale,abs(fld(k)))
      end do
c
c --- exit if parcels overtake each other
      errcon=.false.
      do k=2,kk
        if (z(k)+dz(k).lt.z(k-1)+dz(k-1) .or.
     .      z(k)+dz(k).gt.z(k+1)+dz(k+1)) then
          write (*,'(a,i3)') 'error advc1d -- crossover at k =',k
          errcon=.true.
          return
          return
        end if
      end do
c
c --- start by filling massless cells with data from layer(s) above or below
c
      do 17 k=kk-1,1,-1
 17   fld(k)=(fld(k)*thk(k)+fld(k+1)*small)
     .      /(       thk(k)+         small)
      do 18 k=2,kk
 18   fld(k)=(fld(k)*thk(k)+fld(k-1)*small)
     .      /(       thk(k)+         small)
c
c --- fit 0th, 1st, or 2nd deg. polynomial to -fld- in each cell
      a(1 )=fld(1 )
      b(1 )=0.
      c(1 )=0.
      a(kk)=fld(kk)
      b(kk)=0.
      c(kk)=0.
c
      do 16 k=2,kk-1
c --- uncomment one of the following 3 options to activate pcm,plm,ppm resp.
c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
c --- piecewise constant method:
ccc      a(k)=fld(k)
ccc      b(k)=0.
ccc      c(k)=0.
c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
c --- piecewise linear method:
c --- fit linear function a+bx to tracer in each cell (-.5 < x < +.5)
ccc      a(k)=fld(k)
ccc      b(k)=0.
ccc      if (fld(k).le.min(fld(k-1),fld(k+1)) .or.
ccc     .    fld(k).ge.max(fld(k-1),fld(k+1))) then
ccc        b(k)=0.
ccc      else if ((fld(k+1)-fld(k-1))*(fld(k-1)+fld(k+1)
ccc     .  -2.*fld(k)).gt.0.) then
ccc        b(k)=fld(k)-fld(k-1)
ccc      else
ccc        b(k)=fld(k+1)-fld(k)
ccc      end if
ccc      c(k)=0.
c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
c --- piecewise parabolic method:
c --- fit parabola a+bx+cx^2 to tracer in each cell (-.5 < x < +.5)
      yl=.5*(fld(k-1)+fld(k))
      yr=.5*(fld(k+1)+fld(k))
      a(k)=1.5*fld(k)-.25*(yl+yr)
      b(k)=yr-yl
      c(k)=6.*(.5*(yl+yr)-fld(k))
      if (abs(yr-yl) .lt. 6.*abs(.5*(yl+yr)-fld(k))) then
c --- apex of parabola lies inside interval [-.5,+.5], implying an over-
c --- or undershoot situation. change curve to prevent over/undershoots.
        if (abs(yr-yl) .gt. 2.*abs(.5*(yl+yr)-fld(k))) then
c --- put apex of parabola on edge of interval [-.5,+.5]
          if ((yr-yl)*(.5*(yl+yr)-fld(k)) .gt. 0.) then
c --- apex at x=-.5
            a(k)=.25*(3.*fld(k)+yl)
            c(k)=3.*(fld(k)-yl)
            b(k)=c(k)
          else
c --- apex at x=+.5
            a(k)=.25*(3.*fld(k)+yr)
            c(k)=3.*(fld(k)-yr)
            b(k)=-c(k)
          end if
        else                    !  -1/6 < x < +1/6
c --- moving apex won't help. replace parabola by constant.
          a(k)=fld(k)
          b(k)=0.
          c(k)=0.
        end if
      end if
c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 16   continue
c
c --- get flux by summing -fld- over upstream slab of thickness -dz-
c
      do 23 k=1,kk+1
      slab=small
      if (dz(k).lt.0.) then                     ! -fld- moves up
        if (k.eq.kk+1) then
          amount=0.                             ! influx from outside domain
        else
          amount=slab*fld(k)
          kp=k-1
 24       kp=kp+1
          if (kp.le.kk) then
            if (thk(kp).gt.0.) then
              dslab=min(slab+thk(kp),-dz(k),z(kk+1)-z(k))
     .             -min(slab        ,-dz(k),z(kk+1)-z(k))
              dx=dslab/thk(kp)
              fcdx=a(kp)
     .          +b(kp)*.5*(dx-1.)               !  not needed in pcm
     .          +c(kp)*(.25-dx*(.5-dx*athird))  !  not needed in pcm,plm
              amount=amount+fcdx*dslab
              slab=slab+dslab
            end if
          else                                  ! reaching outside domain
            slab=-dz(k)
          end if
          if (slab.lt.-dz(k)) go to 24
        end if
      else if (dz(k).gt.0.) then                ! -fld- moves down
        if (k.eq.1) then
          amount=0.                             ! influx from outside domain
        else
          amount=slab*fld(k-1)
          kp=k
 25       kp=kp-1
          if (kp.ge.1) then
            if (thk(kp).gt.0.) then
              dslab=min(slab+thk(kp), dz(k),z(k)-z(1))
     .             -min(slab        , dz(k),z(k)-z(1))
              dx=dslab/thk(kp)
              fcdx=a(kp)
     .          +b(kp)*.5*(1.-dx)               !  not needed in pcm
     .          +c(kp)*(.25-dx*(.5-dx*athird))  !  not needed in pcm,plm
              amount=amount+fcdx*dslab
              slab=slab+dslab
            end if
          else                                  ! reaching outside domain
            slab=dz(k)
          end if
          if (slab.lt.dz(k)) go to 25
        end if
      else                                      !  dz = 0
        amount=0.
      end if
 23   flux(k)=dz(k)*amount/slab
c
      do 26 k=1,kk
 26   div(k)=flux(k+1)-flux(k)
c
      do 4 k=1,kk
      amount=fld(k)*thk(k)-div(k)
 4    fld(k)=(fld(k)*small+amount)/(small+thk(k))
c
      after=flux(kk+1)-flux(1)                  !  account for outflow loss
      do k=1,kk
        after=after+fld(k)*thk(k)
      end do
      if (abs(bfore-after)*kk.gt.1.e-9*scale*z(kk+1)) then
        write (*,104) '  advc1d - bad column intgl.:',bfore,after
        errcon=.true.
      end if
 104  format (a,2es15.7)
c
cdiag if (vrbos) write (*,100)
cdiag. 'exiting  advc1d:  old loc''n  new loc''n   variable',
cdiag. (k,z(k),z(k)+dz(k),fld(k),k=1,kk),kk+1,z(kk+1),z(kk+1)+dz(kk+1)
c
      return
      end
c
c
c> Revision history:
c>
c> May  2001 - added u/v regridding
c> June 2001 - added interlayer ("diapycnal") mass flux diagnostics
c> Aug. 2001 - added -kn- to list of private variables in loop 13
c> Aug. 2001 - various refinements, incl. multi-layer ingest
c> Dec. 2001 - softened enforcement of minimum layer thickness constraint
c> Feb. 2002 - restricted ingest of multiple layers from below
c> Mar. 2002 - added passive tracer
c> Apr. 2002 - fixed -diaflx- diagnostics by defining -dpold-
c> June 2002 - changed 'slak' logic - now based on gradual restoring
c> June 2002 - curtail downward growth of layers (esp. lowest hybrid layer)
c> May  2003 - introduced variable -dpsum- to make -p_hat- k-dependent
c> Aug. 2003 - added option to maintain 10 cm min.thickness throughout column
c> Sep. 2003 - added logical switch to enable/disable tracer redistribution
c> Sep. 2003 - provided choice between T/S and rho/S conservation
c> Nov. 2003 - replaced dp0 in cushn call by dp0 appropriate for layer k-1
c> Nov. 2003 - accelerated relaxation time for 1st interface (slak x 10)
c> Nov. 2004 - allowed -dplist- values to shrink near equator
c> Nov. 2004 - conversion to piecewise linear advection scheme (PLM)
c> Nov. 2004 - extended PLM advection to velocity field
c> Dec. 2004 - changed from PLM to PPM (piecewise parabolic)
c> Dec. 2004 - added code to update dpu/dpv(n) (loop 9 and dpudpv call)
c> Apr. 2005 - changed sigjmp to 10*sigjmp in formulae computing p_hat
c> May  2005 - ppmadv: bounded wdth by 1 (loop 4)
c> Mar. 2006 - changed pres(k) to pres(k+1) in p_hat calc'n after stmt label 6
c> June 2006 - if layer 1 touches sea floor, don't split it to restore target
c> July 2006 - introduced depth-dependent tapering function for 'slak'