
!=======================================================================
!       integrate passive tracers
!=======================================================================



subroutine integrate_tracer(ierr)
!=======================================================================
!     solve prognostic equation for tracers
!=======================================================================
      use pyOM_module   
      implicit none
      integer, intent(out) :: ierr
      integer :: i,j,k,js,je,n
      real*8 :: adv_fe(nx,ny,nz), adv_ft(nx,ny,nz)
      real*8 :: adv_fn(nx,ny,nz), diff_fn(nx,ny,nz)
      real*8 :: diff_fe(nx,ny,nz),diff_ft(nx,ny,nz),fxa
      real*8 :: uback(nx,ny,nz),vback(nx,ny,nz),wback(nx,ny,nz)

      ierr=0
      js=max(2,js_pe); je = min(je_pe,ny-1)
      do n=1,nt
!---------------------------------------------------------------------------------
!        advection
!---------------------------------------------------------------------------------
       adv_fe(:,js_pe:je_pe,:)=0
       adv_fn(:,js_pe:je_pe,:)=0
       adv_ft(:,js_pe:je_pe,:)=0
       call adv_flux(nx,ny,nz,adv_fe,adv_fn,adv_ft,tr(:,:,:,:,n))
       call border_exchg3D(nx,ny,nz,adv_fn,1)
       call setcyclic3D(nx,ny,nz,adv_fe)
       call setcyclic3D(nx,ny,nz,adv_fn)
       if (delimit_tracer_fluxes) call delimit_adv_flux(nx,ny,nz,n,adv_fe,adv_fn,adv_ft)
!---------------------------------------------------------------------------------
!      horizontal diffusion
!---------------------------------------------------------------------------------
       diff_fe(:,js_pe:je_pe,:)=0
       diff_fn(:,js_pe:je_pe,:)=0
       diff_ft(:,js_pe:je_pe,:)=0
       do k=2,nz-1
        do j=js,je
         do i=1,nx-1
          fxa=K_h*maskU(i,j,k)
          diff_fe(i,j,k)=fxa*(tr(i+1,j,k,taum1,n)-tr(i,j,k,taum1,n))/dx
         enddo
        enddo
       enddo
       call setcyclic3D(nx,ny,nz,diff_fe)
       do k=2,nz-1
        do j=js,je 
         do i=2,nx-1
          fxa=K_h*maskV(i,j,k)
          diff_fn(i,j,k)=fxa*(tr(i,j+1,k,taum1,n)-tr(i,j,k,taum1,n))/dx
         enddo
        enddo
       enddo
       call border_exchg3D(nx,ny,nz,diff_fn,1)
       call setcyclic3D(nx,ny,nz,diff_fn)
!---------------------------------------------------------------------------------
!      vertical diffusion
!---------------------------------------------------------------------------------
       do k=1,nz-1
        do j=js,je
         do i=2,nx-1
          fxa=K_v*maskW(i,j,k)
          diff_ft(i,j,k)=fxa*(tr(i,j,k+1,taum1,n)-tr(i,j,k,taum1,n))/dz
         enddo
        enddo
       enddo
!---------------------------------------------------------------------------------
!       time tendency of b
!---------------------------------------------------------------------------------
       do k=2,nz-1
        do j=js,je
         do i=2,nx-1
          tr(i,j,k,taup1,n)=tr(i,j,k,taum1,n)+maskT(i,j,k)*c2dt*(    &
        -(adv_fe(i,j,k)-adv_fe(i-1,j,k))/dx   &
        -(adv_fn(i,j,k)-adv_fn(i,j-1,k))/dx   &
        -(adv_ft(i,j,k)-adv_ft(i,j,k-1))/dz   &
        +(diff_ft(i,j,k)-diff_ft(i,j,k-1))/dz   &
        +(diff_fe(i,j,k)-diff_fe(i-1,j,k))/dx   &
        +(diff_fn(i,j,k)-diff_fn(i,j-1,k))/dx  )
         enddo
        enddo
       enddo
!---------------------------------------------------------------------------------
!       Biharmonic diffusion (horizontal and vertical)
!---------------------------------------------------------------------------------
       if (enable_biharmonic_diffusion) call biha_mix(nx,ny,nz,diff_fe,diff_fn,diff_ft,tr(:,:,:,:,n))
!---------------------------------------------------------------------------------
!      effect of zonal background velocity on tracer
!---------------------------------------------------------------------------------
       if (enable_back_state .and. enable_back_zonal_flow) then  
       do j=js_pe,je_pe
        uback(:,j,:)=u(:,j,:,tau);
        vback(:,j,:)=v(:,j,:,tau);
        wback(:,j,:)=w(:,j,:,tau);
        u(:,j,:,tau)=u0(:,j,:); v(:,j,:,tau)=0.; w(:,j,:,tau)=0.
       enddo
       adv_fe(:,js_pe:je_pe,:)=0; adv_fn(:,js_pe:je_pe,:)=0; adv_ft(:,js_pe:je_pe,:)=0
       call adv_flux(nx,ny,nz,adv_fe,adv_fn,adv_ft,tr(:,:,:,:,n) )
       u(:,js_pe:je_pe,:,tau)=uback(:,js_pe:je_pe,:)
       v(:,js_pe:je_pe,:,tau)=vback(:,js_pe:je_pe,:)
       w(:,js_pe:je_pe,:,tau)=wback(:,js_pe:je_pe,:)
       call border_exchg3D(nx,ny,nz,adv_fn,1)
       call setcyclic3D(nx,ny,nz,adv_fe); 
       call setcyclic3D(nx,ny,nz,adv_fn)
       do k=2,nz-1
        do j=js,je
         do i=2,nx-1
          tr(i,j,k,taup1,n)=tr(i,j,k,taup1,n)+maskT(i,j,k)*c2dt*(   &
         -(adv_fe(i,j,k)-adv_fe(i-1,j,k))/dx  &
         -(adv_fn(i,j,k)-adv_fn(i,j-1,k))/dx  &
         -(adv_ft(i,j,k)-adv_ft(i,j,k-1))/dz )
         enddo
        enddo
       enddo
       endif
!---------------------------------------------------------------------------------
!      effect of meridional background velocity on tracer
!---------------------------------------------------------------------------------
       if (enable_back_state .and. enable_back_meridional_flow) then  
       do j=js_pe,je_pe
        uback(:,j,:)=u(:,j,:,tau);
        vback(:,j,:)=v(:,j,:,tau);
        wback(:,j,:)=w(:,j,:,tau);
        v(:,j,:,tau)=u0(:,j,:); u(:,j,:,tau)=0.;w(:,j,:,tau)=0.
       enddo
       adv_fe(:,js_pe:je_pe,:)=0; adv_fn(:,js_pe:je_pe,:)=0; adv_ft(:,js_pe:je_pe,:)=0
       call adv_flux(nx,ny,nz,adv_fe,adv_fn,adv_ft,tr(:,:,:,:,n) )
       u(:,js_pe:je_pe,:,tau)=uback(:,js_pe:je_pe,:)
       v(:,js_pe:je_pe,:,tau)=vback(:,js_pe:je_pe,:)
       w(:,js_pe:je_pe,:,tau)=wback(:,js_pe:je_pe,:)
       call border_exchg3D(nx,ny,nz,adv_fn,1)
       call setcyclic3D(nx,ny,nz,adv_fe); 
       call setcyclic3D(nx,ny,nz,adv_fn)
       do k=2,nz-1
        do j=js,je
         do i=2,nx-1
          tr(i,j,k,taup1,n)=tr(i,j,k,taup1,n)+maskT(i,j,k)*c2dt*(   &
         -(adv_fe(i,j,k)-adv_fe(i-1,j,k))/dx  &
         -(adv_fn(i,j,k)-adv_fn(i,j-1,k))/dx  &
         -(adv_ft(i,j,k)-adv_ft(i,j,k-1))/dz )
         enddo
        enddo
       enddo
       endif
!---------------------------------------------------------------------------------
!     account for convection
!---------------------------------------------------------------------------------
       if (enable_hydrostatic)  call implicit_tracer_mix(nx,ny,nz,tr(:,:,:,:,n),K_b)
      enddo
end subroutine integrate_tracer




subroutine isopycnal_diffusion(ierr)
!=======================================================================
!   Isopycnal diffusion for tracer
!=======================================================================
    use pyOM_module   
    implicit none
    integer, intent(out) :: ierr
    integer :: i,j,k,js,je,n
    real*8 :: diff_fn(nx ,ny ,nz),K_iso(nx ,ny ,nz)
    real*8 :: diff_fe(nx ,ny ,nz),diff_ft(nx ,ny ,nz)
    real*8 :: Tz(nx ,ny ,nz),bz(nx ,ny ,nz),sl,fxa
    real*8 :: Tx(nx ,ny ,nz),bx(nx ,ny ,nz)
    real*8 :: Ty(nx ,ny ,nz),by(nx ,ny ,nz)
    real*8, parameter :: epsln = 1.0d-20 ! a small parameter

    ierr=0
    js=max(2,js_pe); je = min(je_pe,ny -1)
!-----------------------------------------------------------------------
!   derivatives of buoyancy
!-----------------------------------------------------------------------
    bz(:,js_pe:je_pe,:)=0; bx(:,js_pe:je_pe,:)=0; by(:,js_pe:je_pe,:)=0
    do k=1,nz-1
       do j=js,je
        do i=1,nx -1
         bx(i,j,k)= (b(i+1,j,k,taum1)-b(i,j,k,taum1))/dx*maskU(i,j,k) 
         by(i,j,k)= (b(i,j+1,k,taum1)-b(i,j,k,taum1))/dx*maskV(i,j,k) 
         bz(i,j,k)= (b(i,j,k+1,taum1)-b(i,j,k,taum1))/dz*maskW(i,j,k) 
        enddo
       enddo
    enddo
    if (enable_back_state) then  
      do k=1,nz-1
       do j=js,je
        do i=1,nx -1
         bx(i,j,k)= bx(i,j,k)+(back(i+1,j,k,taum1)-back(i,j,k,taum1))/dx*maskU(i,j,k) 
         by(i,j,k)= by(i,j,k)+(back(i,j+1,k,taum1)-back(i,j,k,taum1))/dx*maskV(i,j,k) 
         bz(i,j,k)= bz(i,j,k)+(back(i,j,k+1,taum1)-back(i,j,k,taum1))/dz*maskW(i,j,k) 
        enddo
       enddo
      enddo
    endif
    call border_exchg3D(nx,ny,nz,bx,1); call setcyclic3D(nx,ny,nz,bx)
    call border_exchg3D(nx,ny,nz,by,1); call setcyclic3D(nx,ny,nz,by)
    call border_exchg3D(nx,ny,nz,bz,1); call setcyclic3D(nx,ny,nz,bz)

    diff_fe(:,js_pe:je_pe,:)=0; diff_fn(:,js_pe:je_pe,:)=0; diff_ft(:,js_pe:je_pe,:)=0
    K_iso(:,js_pe:je_pe,:)=0; 
    do n=1,nt
!-----------------------------------------------------------------------
!     derivatives of tracer
!-----------------------------------------------------------------------
      Tz(:,js_pe:je_pe,:)=0; Tx(:,js_pe:je_pe,:)=0; Ty(:,js_pe:je_pe,:)=0
      do k=1,nz-1
       do j=js,je
        do i=1,nx -1
         Tx(i,j,k)= (tr(i+1,j,k,taum1,n)-tr(i,j,k,taum1,n))/dx*maskU(i,j,k) 
         Ty(i,j,k)= (tr(i,j+1,k,taum1,n)-tr(i,j,k,taum1,n))/dx*maskV(i,j,k) 
         Tz(i,j,k)= (tr(i,j,k+1,taum1,n)-tr(i,j,k,taum1,n))/dz*maskW(i,j,k) 
        enddo
       enddo
      enddo
      call border_exchg3D(nx,ny,nz,Tx,1); call setcyclic3D(nx,ny,nz,Tx)
      call border_exchg3D(nx,ny,nz,Ty,1); call setcyclic3D(nx,ny,nz,Ty)
      call border_exchg3D(nx,ny,nz,Tz,1); call setcyclic3D(nx,ny,nz,Tz)

!-----------------------------------------------------------------------
!     diff_fe =  K (T_x - b_x/b_z T_z)
!-----------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=1,nx -1
         fxa=(bz(i,j,k)+bz(i,j,k-1)+bz(i+1,j,k)+bz(i+1,j,k-1))   &
                    /(maskW(i,j,k  )+maskW(i+1,j,k) +maskW(i,j,k-1)+maskW(i+1,j,k-1)+epsln)
         sl=bx(i,j,k)*sign(dble(1.),fxa)/(abs(fxa)+epsln)
         sl=sl*0.5*(1.+tanh((-abs(sl)+iso_slopec)/iso_dslope))   
         fxa=(Tz(i,j,k)+Tz(i,j,k-1)+Tz(i+1,j,k)+Tz(i+1,j,k-1))  &
               /(maskW(i,j,k  )+maskW(i+1,j,k) +maskW(i,j,k-1)+maskW(i+1,j,k-1)+epsln)
         diff_fe(i,j,k)=(Tx(i,j,k)-sl*fxa)    *maskU(i,j,k) *K_gm ! *ahthk(i,j,k)
        enddo
       enddo
      enddo
      call setcyclic3D(nx,ny,nz,diff_fe)
!-----------------------------------------------------------------------
!     diff_fn =  K (T_y - b_y/b_z T_z)
!-----------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=2,nx -1
         fxa=(bz(i,j,k)+bz(i,j,k-1)+bz(i,j+1,k)+bz(i,j+1,k-1))   &
          /(maskW(i,j,k  )+maskW(i,j+1,k) +maskW(i,j,k-1)+maskW(i,j+1,k-1)+epsln)
         sl=by(i,j,k)*sign(dble(1.),fxa)/(abs(fxa)+epsln)
         sl=sl*0.5*(1.+tanh((-abs(sl)+iso_slopec)/iso_dslope))   
         fxa=(Tz(i,j,k)+Tz(i,j,k-1)+Tz(i,j+1,k)+Tz(i,j+1,k-1))   &
          /(maskW(i,j,k  )+maskW(i,j+1,k)  +maskW(i,j,k-1)+maskW(i,j+1,k-1)+epsln)
         diff_fn(i,j,k)=(Ty(i,j,k)-sl*fxa)   *maskV(i,j,k)*K_gm ! *ahthk(i,j,k)
        enddo
       enddo
      enddo
      call border_exchg3D(nx,ny,nz,diff_fn,1); call setcyclic3D(nx,ny,nz,diff_fn)
!-----------------------------------------------------------------------
!     diff_fb =  - K(b_x/b_z T_x +b_y/b_z T_y) 
!                  + T_z K((bx/bz)**2+(by/bz))**2
!      second term is done implicitly
!-----------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=2,nx -1
         fxa=(bx(i,j,k)+bx(i-1,j,k)+bx(i,j,k+1)+bx(i-1,j,k+1))  &
          /(maskU(i,j,k  )+maskU(i-1,j,k  ) +maskU(i,j,k+1)+maskU(i-1,j,k+1)+epsln)
         sl=fxa*sign(dble(1.),bz(i,j,k))/(abs(bz(i,j,k))+epsln)
         sl=sl*0.5*(1.+tanh((-abs(sl)+iso_slopec)/iso_dslope))   
         fxa=(Tx(i,j,k)+Tx(i-1,j,k)+Tx(i,j,k+1)+Tx(i-1,j,k+1))  &
          /(maskU(i,j,k  )+maskU(i-1,j,k  )  +maskU(i,j,k+1)+maskU(i-1,j,k+1)+epsln)
         diff_ft(i,j,k)=(-sl*fxa)*maskW(i,j,k) *K_gm !*ahthk(i,j,k)
         K_iso(i,j,k)=sl**2*maskW(i,j,k) * K_gm !*ahthk(i,j,k)

         fxa=(by(i,j,k)+by(i,j-1,k  )+by(i,j,k+1)+by(i,j-1,k+1))   &
          /(maskV(i,j,k  )+maskV(i,j-1,k  ) +maskV(i,j,k+1)+maskV(i,j-1,k+1)+epsln)
         sl=fxa*sign(dble(1.),bz(i,j,k))/(abs(bz(i,j,k))+epsln)
         sl=sl*0.5*(1.+tanh((-abs(sl)+iso_slopec)/iso_dslope))   
         fxa=(Ty(i,j,k)+Ty(i,j-1,k)+Ty(i,j,k+1)+Ty(i,j-1,k+1))    &
          /(maskV(i,j,k  )+maskV(i,j-1,k  ) +maskV(i,j,k+1)+maskV(i,j-1,k+1)+epsln)
         diff_ft(i,j,k)=diff_ft(i,j,k)  +(-sl*fxa)*maskW(i,j,k) *K_gm !*ahthk(i,j,k)
         K_iso(i,j,k)=K_iso(i,j,k)+   sl**2*maskW(i,j,k) *K_gm !*ahthk(i,j,k)
        enddo
       enddo
      enddo

 if (delimit_tracer_fluxes) then
       diff_fe(:,js_pe:je_pe,:)=-diff_fe(:,js_pe:je_pe,:)
       diff_fn(:,js_pe:je_pe,:)=-diff_fn(:,js_pe:je_pe,:)
       diff_ft(:,js_pe:je_pe,:)=-diff_ft(:,js_pe:je_pe,:)
       call border_exchg3D(nx,ny,nz,diff_fn,1);
       call delimit_adv_flux_taup1(nx,ny,nz,n,diff_fe,diff_fn,diff_ft)
       diff_fe(:,js_pe:je_pe,:)=-diff_fe(:,js_pe:je_pe,:)
       diff_fn(:,js_pe:je_pe,:)=-diff_fn(:,js_pe:je_pe,:)
       diff_ft(:,js_pe:je_pe,:)=-diff_ft(:,js_pe:je_pe,:)
       call border_exchg3D(nx,ny,nz,diff_fn,1);
 endif
!---------------------------------------------------------------------------------
!     add explicit part 
!---------------------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=2,nx -1
          tr(i,j,k,taup1,n)=tr(i,j,k,taup1,n)+maskT(i,j,k)*c2dt*(   &
                +(diff_ft(i,j,k)-diff_ft(i,j,k-1))/dz  &
                +(diff_fe(i,j,k)-diff_fe(i-1,j,k))/dx  &
                +(diff_fn(i,j,k)-diff_fn(i,j-1,k))/dx      )  
        enddo
       enddo
      enddo
!---------------------------------------------------------------------------------
!     add implicit part 
!---------------------------------------------------------------------------------
      call implicit_tracer_mix(nx,ny,nz,tr(:,:,:,:,n) ,K_iso)
      call border_exchg3D(nx,ny,nz,tr(:,:,:,taup1,n),2)
      call setcyclic3D(nx,ny,nz,tr(:,:,:,taup1,n) )
    enddo ! n
end subroutine isopycnal_diffusion






subroutine delimit_adv_flux(nx_,ny_,nz_,n,adv_fe,adv_fn,adv_ft)
!-----------------------------------------------------------------------
!   delimit advective fluxes for passive tracers
!   using the multidimensional positive definite
!   advection scheme (MPDCD) by Lafore, et al 1998
!-----------------------------------------------------------------------
      use pyOM_module   
      implicit none
      integer, intent(in) :: n,nx_,ny_,nz_
      integer :: js,je,i,j,k
      real*8 :: adv_fe(nx_,ny_,nz_), adv_fn(nx_,ny_,nz_), adv_ft(nx_,ny_,nz_)
      real*8 :: betaf(nx,ny,nz), denom
      real*8, parameter :: small = 1.d-15

      js=max(2,js_pe); je=min(je_pe,ny -1)
!    compute delimiter for outgoing flux
      betaf(:,js_pe:je_pe,:)=2.
      do j=js,je
        do k=2,nz-1
          do i=2,nx -1
           denom =       max(0d0,adv_fe(i  ,j,k)/dx)
           denom = denom-min(0d0,adv_fe(i-1,j,k)/dx) 
           denom = denom+max(0d0,adv_fn(i,j,k  )/dx)
           denom = denom-min(0d0,adv_fn(i,j-1,k)/dx)
           denom = denom+max(0d0,adv_ft(i,j,k)/dz)
           denom = denom-min(0d0,adv_ft(i,j,k-1)/dz)
           denom=denom*c2dt
           denom = sign(dble(1.) ,denom)*max(small,abs(denom)) ! should be positive anyway
           betaf(i,j,k)=tr(i,j,k,taum1,n)/denom
          enddo
        enddo
      enddo
      call border_exchg3D(nx,ny,nz,betaf,1); call setcyclic3D(nx,ny,nz,betaf)
!   delimit zonal flux
      do j=js,je
        do k=2,nz-1
          do i=1,nx -1
           adv_fe(i,j,k)=min(1d0,betaf(i ,j ,k))*max(0d0,adv_fe(i,j,k)) &
                        +min(1d0,betaf(i+1,j,k))*min(0d0,adv_fe(i,j,k))
          enddo
        enddo
      enddo
!   delimit meridional flux
      do j=js-1,je
        do k=2,nz-1
          do i=2,nx -1
           adv_fn(i,j,k)=min(1d0,betaf(i,j,k  ))*max(0d0,adv_fn(i,j,k)) & 
                        +min(1d0,betaf(i,j+1,k))*min(0d0,adv_fn(i,j,k))
          enddo
        enddo
      enddo
!   delimit vertical flux
      do j=js,je
        do k=1,nz-1
          do i=2,nx -1
           adv_ft(i,j,k)=min(1d0,betaf(i,j,k))*max(0d0,adv_ft(i,j,k)) &
                        +min(1d0,betaf(i,j,k+1))*min(0d0,adv_ft(i,j,k))
          enddo
        enddo
      enddo
end subroutine delimit_adv_flux



 subroutine delimit_adv_flux_taup1(nx_,ny_,nz_,n,adv_fe,adv_fn,adv_ft)
!-----------------------------------------------------------------------
!   same as above but cares for tracer at taup1
!-----------------------------------------------------------------------
      use pyOM_module   
      implicit none
      integer, intent(in) :: n,nx_,ny_,nz_
      integer :: js,je,i,j,k
      real*8 :: adv_fe(nx_,ny_,nz_), adv_fn(nx_,ny_,nz_), adv_ft(nx_,ny_,nz_)
      real*8 :: betaf(nx,ny,nz), denom
      real*8, parameter :: small = 1.d-15

      js=max(2,js_pe); je=min(je_pe,ny-1)
!    compute delimiter for outgoing flux
      betaf(:,js_pe:je_pe,:)=2.
      do j=js,je
        do k=2,nz-1
          do i=2,nx-1
           denom =       max(0d0,adv_fe(i  ,j,k)/dx)
           denom = denom-min(0d0,adv_fe(i-1,j,k)/dx) 
           denom = denom+max(0d0,adv_fn(i,j,k  )/dx)
           denom = denom-min(0d0,adv_fn(i,j-1,k)/dx)
           denom = denom+max(0d0,adv_ft(i,j,k)/dz)
           denom = denom-min(0d0,adv_ft(i,j,k-1)/dz)
           denom=denom*c2dt
           denom = sign(dble(1.),denom)*max(small,abs(denom)) ! should be positive anyway
           betaf(i,j,k)=tr(i,j,k,taup1,n)/denom
          enddo
        enddo
      enddo
      call border_exchg3D(nx,ny,nz,betaf,1); call setcyclic3D(nx,ny,nz,betaf)
!   delimit zonal flux
      do j=js,je
        do k=2,nz-1
          do i=1,nx-1
           adv_fe(i,j,k)= min(1d0,betaf(i ,j ,k))*max(0d0,adv_fe(i,j,k)) &
                         +min(1d0,betaf(i+1,j,k))*min(0d0,adv_fe(i,j,k))
          enddo
        enddo
      enddo
!   delimit meridional flux
      do j=js-1,je
        do k=2,nz-1
          do i=2,nx-1
           adv_fn(i,j,k)=min(1d0,betaf(i,j,k  ))*max(0d0,adv_fn(i,j,k)) &
                        +min(1d0,betaf(i,j+1,k))*min(0d0,adv_fn(i,j,k))
          enddo
        enddo
      enddo
!   delimit vertical flux
      do j=js,je
        do k=1,nz-1
          do i=2,nx-1
           adv_ft(i,j,k)=min(1d0,betaf(i,j,k))*max(0d0,adv_ft(i,j,k)) &
                        +min(1d0,betaf(i,j,k+1))*min(0d0,adv_ft(i,j,k))
          enddo
        enddo
      enddo
 end subroutine delimit_adv_flux_taup1





subroutine tracer_read_restart(filename)
!=======================================================================
!     read tracer from restart file
!=======================================================================
      use pyOM_module   
      implicit none
      integer :: ierr
      integer :: j,io,n,nx_,ny_,nz_,nt_
      character*(*),intent(in) :: filename
      ierr=0
      if (my_pe==0) print*,' reading tracer from restart file ',filename(1:len_trim(filename))
      call get_free_iounit(io,ierr)
      if (ierr/=0) goto 10
      open(io,file=filename,form='unformatted',status='old',err=10)
      read(io,err=10) nx_,ny_,nz_,nt_
      if (nx/=nx_ .or. ny/=ny_ .or. nz/= nz_) then 
        print*,' read from restart dimensions: ',nx_,ny_,nz_
        print*,' does not match dimensions   : ',nx,ny,nz
        goto 10
      endif
      if (nt/=nt_ ) then 
        print*,' read number of tracer: ',nt_
        print*,' does not match nt= ',nt
        goto 10
      endif
      do n=1,nt
       do j=1,ny
        read(io,err=10) tr(:,j,:,tau,n),  tr(:,j,:,taum1,n)
       enddo
      enddo
      close(io)
      return
  10  ierr=-1
      close(io)
      if (my_pe==0) print*,' error reading tracer restart file'
end subroutine tracer_read_restart


subroutine tracer_write_restart(filename)
!=======================================================================
!     write restart to file
!=======================================================================
      use pyOM_module   
      implicit none
      integer :: ierr
      character*(*),intent(in) :: filename
      integer :: j,io,n
      ierr=0
      if (my_pe==0) print*,' writing tracer restart to file ',filename(1:len_trim(filename))
      do n=1,nt
       call pe0_recv_3D(nx,ny,nz,tr(:,:,:,tau  ,n) )
       call pe0_recv_3D(nx,ny,nz,tr(:,:,:,taum1,n) )
      enddo
      if (my_pe==0) then 
       call get_free_iounit(io,ierr)
       if (ierr/=0) goto 10
       open(io,file=filename,form='unformatted',status='unknown',err=10)
       write(io,err=10) nx,ny,nz,nt
       do n=1,nt
         do j=1,ny
          write(io,err=10) tr(:,j,:,tau,n), tr(:,j,:,taum1,n)
         enddo
       enddo
       close(io)
      endif
      return
  10  ierr=-1
      if (my_pe==0) print*,' error writing tracer restart file'
end subroutine tracer_write_restart

