
 
 subroutine integrate(ierr)
!=======================================================================
!       solve prognostic equations for u,v and w
!       boundary exchange and apply roberts time filter
!=======================================================================
      use pyOM_module   
      implicit none
      integer, intent(out) :: ierr
      integer :: i,j,k,js,je,n
      real*8 :: bv0(nx,ny),bu0(nx,ny)
      ierr=0
      js=max(2,js_pe); je = min(je_pe,ny-1)
!---------------------------------------------------------------------------------
!      du/dt = F_u - p_x 
!---------------------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=2,nx-1
         u(i,j,k,taup1) = u(i,j,k,taum1) + maskU(i,j,k)*c2dt*(   &
           fu(i,j,k)-(p_full(i+1,j,k,tau)-p_full(i,j,k,tau))/dx)
        enddo
       enddo
      enddo
      if (enable_expl_free_surf) then
!---------------------------------------------------------------------------------
!      correct barotropic mode
!---------------------------------------------------------------------------------
        bu0(:,js_pe:je_pe)=0.
        do k=1,nz-1
         do j=js,je
          do i=2,nx-1
           bu0(i,j)=bu0(i,j)+u(i,j,k,taup1)*maskU(i,j,k)*dz
          enddo
         enddo
        enddo
        do k=1,nz-1
         do j=js,je
          do i=2,nx-1
           u(i,j,k,taup1)=u(i,j,k,taup1)+(bu(i,j,taup1)-bu0(i,j))/(1e-18+hu(i,j))*maskU(i,j,k)
          enddo
         enddo
        enddo
      endif
      call border_exchg3D(nx,ny,nz,u(:,:,:,taup1),2)
      call setcyclic3D(nx,ny,nz,u(:,:,:,taup1) )
!---------------------------------------------------------------------------------
!      dv/dt = F_v - p_y  
!---------------------------------------------------------------------------------
      do k=2,nz-1
       do j=js,je
        do i=2,nx-1
         v(i,j,k,taup1) = v(i,j,k,taum1) + maskV(i,j,k)*c2dt*(   &
           fv(i,j,k)-(p_full(i,j+1,k,tau)-p_full(i,j,k,tau))/dx)
        enddo
       enddo
      enddo
      if (enable_expl_free_surf) then
!---------------------------------------------------------------------------------
!      correct barotropic mode
!---------------------------------------------------------------------------------
        bv0(:,js_pe:je_pe)=0.
        do k=1,nz-1
         do j=js,je
          do i=2,nx-1
           bv0(i,j)=bv0(i,j)+v(i,j,k,taup1)*maskV(i,j,k)*dz
          enddo
         enddo
        enddo
        do k=1,nz-1
         do j=js,je
          do i=2,nx-1
           v(i,j,k,taup1)=v(i,j,k,taup1)+(bv(i,j,taup1)-bv0(i,j))/(1e-18+hv(i,j))*maskV(i,j,k)
          enddo
         enddo
        enddo
      endif
      call border_exchg3D(nx,ny,nz,v(:,:,:,taup1),2)
      call setcyclic3D(nx,ny,nz,v(:,:,:,taup1) )

      if (.not. enable_hydrostatic) then
!---------------------------------------------------------------------------------
!       dw/dt = F_w - psi_z 
!---------------------------------------------------------------------------------
       do k=2,nz-1
        do j=js,je
         do i=2,nx-1
          w(i,j,k,taup1) = w(i,j,k,taum1)+maskW(i,j,k)*c2dt*(fw(i,j,k)-(psi(i,j,k+1)-psi(i,j,k))/dz)
         enddo
        enddo
       enddo
       call border_exchg3D(nx,ny,nz,w(:,:,:,taup1),2)
       call setcyclic3D(nx,ny,nz,w(:,:,:,taup1) )
      endif
!---------------------------------------------------------------------------------
!      apply roberts time filter on time levels 
!---------------------------------------------------------------------------------
      do j=js,je
       u(:,j,:,tau) = u(:,j,:,tau) + gamma*(0.5*(u(:,j,:,taup1) + u(:,j,:,taum1)) - u(:,j,:,tau)) 
       v(:,j,:,tau) = v(:,j,:,tau) + gamma*(0.5*(v(:,j,:,taup1) + v(:,j,:,taum1)) - v(:,j,:,tau)) 
       if (.not. enable_hydrostatic) then
        w(:,j,:,tau) = w(:,j,:,tau) + gamma*(0.5*(w(:,j,:,taup1) + w(:,j,:,taum1)) - w(:,j,:,tau)) 
       endif
       b(:,j,:,tau) = b(:,j,:,tau) + gamma*(0.5*(b(:,j,:,taup1) + b(:,j,:,taum1)) - b(:,j,:,tau)) 
      enddo
      call border_exchg3D(nx,ny,nz,u(:,:,:,tau),2)
      call setcyclic3D(nx,ny,nz,u(:,:,:,tau) )
      call border_exchg3D(nx,ny,nz,v(:,:,:,tau),2)
      call setcyclic3D(nx,ny,nz,v(:,:,:,tau) )
      if (.not.enable_hydrostatic) then
       call border_exchg3D(nx,ny,nz,w(:,:,:,tau),2)
       call setcyclic3D(nx,ny,nz,w(:,:,:,tau) )
      endif
      call border_exchg3D(nx,ny,nz,b(:,:,:,tau),2)
      call setcyclic3D(nx,ny,nz,b(:,:,:,tau) )
      if (enable_diag_tracer) then
!---------------------------------------------------------------------------------
!        boundary exchange and apply roberts time filter on time levels 
!---------------------------------------------------------------------------------
      do n=1,nt
       call border_exchg3D(nx,ny,nz,tr(:,:,:,taup1,n),2)
       call setcyclic3D(nx,ny,nz,tr(:,:,:,taup1,n) )
       do j=js,je
       tr(:,j,:,tau,n) = tr(:,j,:,tau,n) + gamma*(0.5*(tr(:,j,:,taup1,n)+tr(:,j,:,taum1,n))-tr(:,j,:,tau,n)) 
       enddo
       call border_exchg3D(nx,ny,nz,tr(:,:,:,tau,n),2)
       call setcyclic3D(nx,ny,nz,tr(:,:,:,tau,n) )
      enddo
     endif

 end subroutine integrate


 
 subroutine vertical_velocity(ierr)
!=======================================================================
!       vertical velocity from continuity : 
!       \int_0^z w_z dz =w(z)-w(0) = - \int dz (u_x +v_y)  
!        w(z)=-int dz u_x + v_y
!=======================================================================
      use pyOM_module   
      implicit none
      integer, intent(out) :: ierr
      integer :: i,j,k,js,je
      ierr=0
      js=max(2,js_pe); je = min(je_pe,ny-1)
      w(:,js_pe:je_pe,1,tau) = 0.0
      do k=2,nz
       do j=js,je
        do i=2,nx-1
          w(i,j,k,tau) = w(i,j,k-1,tau)-maskW(i,j,k)*dz*(   &
            (u(i,j,k,tau)-u(i-1,j,k,tau))/dx +(v(i,j,k,tau)-v(i,j-1,k,tau))/dx)
        enddo
       enddo
      enddo
      do j=js,je
       w(:,j,:,tau) = w(:,j,:,tau)*maskW(:,j,:)
      enddo
      call border_exchg3D(nx,ny,nz,w(:,:,:,tau),2)
      call setcyclic3D(nx,ny,nz,w(:,:,:,tau) )
 end subroutine vertical_velocity






 subroutine read_restart(itt_,filename)
! ----------------------------------
!       read the restart file
! ----------------------------------
      use pyOM_module   
      implicit none
      integer, intent(out) :: itt_
      integer :: ierr
      integer :: j,io,nx_,ny_,nz_
      character*(*),intent(in) :: filename
      ierr=0

    if (my_pe==0) then
      print*,' reading 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_
      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
      read(io,err=10) itt_ !,restart_time_in
      print*,' itt        = ',itt_
      do j=1,ny
        read(io,err=10) u(:,j,:,tau),v(:,j,:,tau),w(:,j,:,tau), u(:,j,:,taum1),v(:,j,:,taum1),w(:,j,:,taum1)
        read(io,err=10) b(:,j,:,tau),   b(:,j,:,taum1)
        read(io,err=10) eta(:,j,tau),   eta(:,j,taum1), psi(:,j,:)
        read(io,err=10) p_full(:,j,:,tau), p_full(:,j,:,taum1) ! this is new
        if (enable_expl_free_surf) then
         read(io,err=10) bu(:,j,tau),bv(:,j,tau)
         read(io,err=10) bu(:,j,taum1),bv(:,j,taum1)
        endif
      enddo
      goto 20
      10 ierr=-1
      print*,' Warning: error reading restart file'
      20 close(io)
    endif

    call pe0_send_int(ierr)
    if (ierr/=0) return

      call pe0_send_int(itt_)
      call pe0_send_3D(nx,ny,nz,u(:,:,:,tau) )
      call pe0_send_3D(nx,ny,nz,v(:,:,:,tau) )
      call pe0_send_3D(nx,ny,nz,w(:,:,:,tau) )
      call pe0_send_3D(nx,ny,nz,u(:,:,:,taum1) )
      call pe0_send_3D(nx,ny,nz,v(:,:,:,taum1) )
      call pe0_send_3D(nx,ny,nz,w(:,:,:,taum1) )
      call pe0_send_3D(nx,ny,nz,b(:,:,:,tau) )
      call pe0_send_3D(nx,ny,nz,b(:,:,:,taum1) )
      call pe0_send_2D(nx,ny,eta(:,:,tau) )
      call pe0_send_2D(nx,ny,eta(:,:,taum1) )
      call pe0_send_3D(nx,ny,nz,psi)
      call pe0_send_3D(nx,ny,nz,p_full(:,:,:,tau) )
      call pe0_send_3D(nx,ny,nz,p_full(:,:,:,taum1) )
      if (enable_expl_free_surf) then
        call pe0_send_2D(nx,ny,bu(:,:,tau) )
        call pe0_send_2D(nx,ny,bv(:,:,tau) )
        call pe0_send_2D(nx,ny,bu(:,:,taum1) )
        call pe0_send_2D(nx,ny,bv(:,:,taum1) )
      endif

      call exchg_prog3Dfield_complete(nx,ny,nz,b)
      call exchg_prog3Dfield_complete(nx,ny,nz,u)
      call exchg_prog3Dfield_complete(nx,ny,nz,v)
      call exchg_prog3Dfield_complete(nx,ny,nz,w)
      call exchg_prog3Dfield_complete(nx,ny,nz,p_full)
      call exchg_prog2Dfield_complete(nx,ny,eta)
      call exchg_3Dfield_complete(nx,ny,nz,psi)
      if (enable_expl_free_surf) then
         call exchg_prog2Dfield_complete(nx,ny,bu)
         call exchg_prog2Dfield_complete(nx,ny,bv)
      endif

      if (my_pe==0) print*,' done reading restart'
 end subroutine read_restart


  subroutine write_restart(itt_,filename)
! ----------------------------------
!      write a restart file
! ----------------------------------
      use pyOM_module   
      implicit none
      integer :: ierr
      integer, intent(in) :: itt_
      character*(*),intent(in) :: filename
      integer :: j,io

      ierr=0
      if (my_pe==0) print*,' writing restart file ',filename(1:len_trim(filename)),' at itt=',itt_

      call pe0_recv_3D(nx,ny,nz,u(:,:,:,tau) )
      call pe0_recv_3D(nx,ny,nz,v(:,:,:,tau) )
      call pe0_recv_3D(nx,ny,nz,w(:,:,:,tau) )
      call pe0_recv_3D(nx,ny,nz,u(:,:,:,taum1) )
      call pe0_recv_3D(nx,ny,nz,v(:,:,:,taum1) )
      call pe0_recv_3D(nx,ny,nz,w(:,:,:,taum1) )
      call pe0_recv_3D(nx,ny,nz,b(:,:,:,tau) )
      call pe0_recv_3D(nx,ny,nz,b(:,:,:,taum1) )
      call pe0_recv_2D(nx,ny,eta(:,:,tau) )
      call pe0_recv_2D(nx,ny,eta(:,:,taum1) )
      call pe0_recv_3D(nx,ny,nz,psi)
      call pe0_recv_3D(nx,ny,nz,p_full(:,:,:,tau) )
      call pe0_recv_3D(nx,ny,nz,p_full(:,:,:,taum1) )
      if (enable_expl_free_surf) then
        call pe0_recv_2D(nx,ny,bu(:,:,tau) )
        call pe0_recv_2D(nx,ny,bv(:,:,tau) )
        call pe0_recv_2D(nx,ny,bu(:,:,taum1) )
        call pe0_recv_2D(nx,ny,bv(:,:,taum1) )
      endif

      if (my_pe==0) then
       call get_free_iounit(io,ierr)
       if (ierr/=0) goto 10
       open(io,file=filename,form='unformatted',status='unknown')
       write(io,err=10) nx,ny,nz
       write(io,err=10) itt_ !,current_time
       do j=1,ny
        write(io,err=10) u(:,j,:,tau),v(:,j,:,tau),w(:,j,:,tau), u(:,j,:,taum1),v(:,j,:,taum1),w(:,j,:,taum1)
        write(io,err=10) b(:,j,:,tau),   b(:,j,:,taum1)
        write(io,err=10) eta(:,j,tau),   eta(:,j,taum1), psi(:,j,:)
        write(io,err=10) p_full(:,j,:,tau), p_full(:,j,:,taum1) ! this is new
        if (enable_expl_free_surf) then
         write(io,err=10) bu(:,j,tau),  bv(:,j,tau)
         write(io,err=10) bu(:,j,taum1),  bv(:,j,taum1)
        endif
       enddo
       close(io)
!       open(io,file='ritt',form='formatted',status='unknown',err=10)
!       write(io,*,err=10) itt
!       close(io)
       goto 20
       10 ierr=-1
       print*,' Warning: error during writing restart file'
       20 continue
      endif
 end subroutine write_restart




 subroutine get_free_iounit (nu,ierr)
!-----------------------------------------------------------------------
!     returns the first free IO unit number in nu
!-----------------------------------------------------------------------
      implicit none
      integer nu,n,ierr
      logical in_use
      character (len=80) :: name
      ierr=0
      do n=7,99
        inquire (n, OPENED=in_use, NAME=name)
        if (.not. in_use) then
          nu = n
          go to 10
         endif
      enddo
      print *,'Error: exhausted available fortran unit numbers'
      print *,'             Are you forgetting to close units?'
      ierr=-1
10    continue
 end subroutine get_free_iounit

 subroutine replace_space_zero(name)
      implicit none
      character (len=*) :: name
      integer  :: i
      do i=1,len_trim(name)
          if (name(i:i)==' ')name(i:i)='0'
      enddo
 end subroutine replace_space_zero


