#if defined(ROW_LAND)
#define SEA_P .true.
#define SEA_U .true.
#define SEA_V .true.
#elif defined(ROW_ALLSEA)
#define SEA_P allip(j).or.ip(i,j).ne.0
#define SEA_U alliu(j).or.iu(i,j).ne.0
#define SEA_V alliv(j).or.iv(i,j).ne.0
#else
#define SEA_P ip(i,j).ne.0
#define SEA_U iu(i,j).ne.0
#define SEA_V iv(i,j).ne.0
#endif
      module mod_floats
      use mod_xc    ! HYCOM communication interface
      use mod_pipe  ! HYCOM debugging interface
#if defined(STOKES)
      use mod_stokes   !  Stokes Drift Velocity Module
#endif
!
      implicit none
!
! --- HYCOM synthetic floats, drifters and moorings
! --- See subroutine floats (below) for more information
!
      integer, parameter, public ::  nfldim=400  !maximum number of synthetic floats

      real, allocatable, dimension(:,:,:), save, public ::   &
         wveli,         & ! interface vertical velocity
         uold2, &
         vold2, &
         wold2u, &
         wold2d

      real, allocatable, dimension(:,:),   save, public :: &
         dlondx, &
         dlondy, &
         dlatdx, &
         dlatdy

      real, allocatable, dimension(:,:,:), save, private :: &
         wvelup, &
         wveldn

      real, allocatable, dimension(:,:),   save, private ::  &
        dpdxup, &
        dpdyup, &
        dpdxdn, &
        dpdydn

      real,    save :: flt(nfldim,13), &
                       deltfl,fldepm,tbvar,tdecri,dtturb,uturb0

      integer, save :: kfloat(nfldim),iflnum(nfldim),ifltyp(nfldim), &
                       nflsam,nfldta,fltflg,nfladv,intpfl,iturbv,ismpfl, &
                       nflout,nfl,nflt,nstepfl

      logical, save :: synflt,turbvel,samplfl,wvelfl,hadvfl,nonlatlon

      character(48), save :: flnmflti,flnmflto,flnmfltio

      contains

      subroutine floats_init(m,n,time0)
      use mod_cb_arrays  ! HYCOM saved arrays
      implicit none
      integer m,n
      real    time0
!
! --- read initial float data
! --- initialize parameters and arrays required for floats
!
      integer i,j,k,l,margin
      integer nbcday,nsmday,ityp
!
# include "stmt_fns.h"
!
! --- initialize flags
!
! --- wvelfl: calculate vertical velocity?
      wvelfl=.false.
!
! --- hadvfl: horizontally advect the float?
      hadvfl=.false.
!
! --- nonlatlon: does the model grid cross latitude/longitude lines anywhere
! --- in the domain?
      nonlatlon=.false.
!
! --- initialize file names
      flnmflti = 'floats.input'
      flnmflto = 'floats_out'
      flnmfltio= 'floats.input_out'
!
! -------------------------
! --- set timing parameters
! -------------------------
!
! --- must have an integer number of baroclinic time steps per day
      nbcday=nint(86400.0/baclin)
      if (real(nbcday).ne.86400.0/baclin) then
        if (mnproc.eq.1) then
        write(lp,'(/ a /)') &
          'error - need integer no. of bacl. time steps/day'
        call flush(lp)
        endif !1st tile
        call xcstop('(floats_init)')
               stop '(floats_init)'
      endif
!
! --- parameter nfladv is entered in blkdat.input as the number of
! --- baroclinic time steps between updates of float position. at model
! --- time nstep when the float is to be advected, velocity fields saved
! --- at times nstep, nstep-nfladv/2, and nstep-nfladv are used to perform
! --- the runga-kutta time interpolation.
!
! --- nfladv must be set so the float is advected every 2-4 hours, but
! --- also must be no smaller than 4. This ensures that the runga-
! --- kutta time interpolation is performed with a delta-time of 1-2 hours.
!
! --- if all floats are stationary (synthetic moorings), then nfladv
! --- must still be no smaller than 4, but the above time restrection
! --- is not necessary. this allows the user to sample at very high
! --- frequency. for example, if baclin is 360 seconds, then setting
! --- nfladv to 10 will allow water properties to be sampled once per hour
!
! --- set variable nfldta to nfladv/2 so that it equals the number of time
! --- steps separating the velocity fields input into the runga-kutta
! --- interpolation
!
      nfldta=nfladv/2
!
! --- make sure that the float will be advected at an integer number of
! --- temporal points per day
      nsmday=nbcday/nfladv
      if (int(real(nbcday)/real(2*nfldta)).ne.nsmday) then
        if (mnproc.eq.1) then
        write(lp,'(/ a /)') &
          'error - need integer no. of adv. times per day'
        call flush(lp)
        endif !1st tile
        call xcstop('(floats_init)')
               stop '(floats_init)'
      endif
!
! --- test to make sure that the advection time interval is between 2
! --- and 4 hours. only stop the program later if there are floats to
! --- be advected
      if (nfladv.ne.4 .and. (nsmday.gt.12  .or. nsmday.lt.6)) then
        nfladv=-nfladv
      endif
!
! --- initialize number of time steps between float output
      if (nflsam.gt.0) then
        nflsam=nflsam*nbcday
      elseif (nflsam.eq.0) then
        nflsam=abs(nfladv)
      endif
!
! --- calculate the time interval for the runga-kutta interpolation
! --- as 1/2 of the advection time interval
      deltfl=nfldta*baclin
!
! --- set minimum float depth (m)
      fldepm=1.0
!
! --- -------------------------------------------------------------
! --- initialize synthetic drifters, floats, and moored instruments
! --- -------------------------------------------------------------
!
      open(unit=uoff+99,file=trim(flnminp)//flnmflti,status='old') !on all nodes
!
! --- first line in float input file is the number of floats
      read(uoff+99,*) nflt
      if (nflt.gt.nfldim) then
        if (mnproc.eq.1) then
        write(lp,'(/ a /)') &
          'error - increase nfldim in mod_floats.F'
        call flush(lp)
        endif !1st tile
        call xcstop('(floats_init)')
               stop '(floats_init)'
      endif
      if (nflt.eq.0) then
        synflt=.false.
      endif
!
! --- second line in float input file is the initial float time step
! --- this number is set to zero for the first model run segment
      read(uoff+99,*) nstepfl
!
      do nfl=1,nflt
!
! --- read input file containing the following information for each float:
! ---
! ---   column 1 - initial sequential float number
! ---   column 2 - float type
! ---              1 = 3-d lagrangian (vertically advected by diagnosed w)
! ---              2 = isopycnic
! ---              3 = isobaric (surface drifter when released in sfc. layer)
! ---              4 = stationary (synthetic moored instrument)
! ---   column 3 - deployment time (days from model start, 0.0 = immediate)
! ---   column 4 - termination time (days from model start, 0.0 = forever)
! ---   column 5 - initial longitude (must be between minimum and maximum
! ---                                 longitudes defined in regional.grid.b)
! ---   column 6 - initial latitude  (must be between minimum and maximum
! ---                                 latitudes defined in regional.grid.b)
! ---   column 7 - initial depth (or reference sigma for isopycnic floats)
!
        read(uoff+99,*) iflnum(nfl),ifltyp(nfl),flt(nfl,8),flt(nfl,9), &
                        flt(nfl,1),flt(nfl,2),flt(nfl,3)
        if (ifltyp(nfl).eq.1 .or. ifltyp(nfl).eq.4) then
          wvelfl=.true.
        endif
        if (ifltyp(nfl).ne.4) then
          hadvfl=.true.
!
! --- since this float is to be advected, stop if the advection time interval
! --- is not between 2 and 4 hr
          if (nfladv.lt.0) then
            if (mnproc.eq.1) then
            write(lp,'(/ a /)') &
              'error - set nfladv to advect floats every 2-4 hr'
            call flush(lp)
            endif !1st tile
            call xcstop('(floats_init)')
                   stop '(floats_init)'
          endif
!
        endif
!
        flt(nfl,4)=0.0
        flt(nfl,5)=0.0
        flt(nfl,6)=0.0
        flt(nfl,7)=0.0
        if(ifltyp(nfl).eq.2) then
          flt(nfl,7)=flt(nfl,3)
          flt(nfl,3)=0.0
        endif
        flt(nfl,10)=0.0
        flt(nfl,11)=0.0
        flt(nfl,12)=0.0
        flt(nfl,13)=0.0
!
        kfloat(nfl)=-1
!
      enddo
!
      nfladv=abs(nfladv)
!
      close(unit=uoff+99) !file='float.input'
!
      if (mnproc.eq.1) then
      write(lp,955) nflt
      write(lp,956) nfladv
      write(lp,957) nflsam
      write(lp,958) min(nflt,10)
  955 format(' read initial data for',i6,' floats, time step',i9)
  956 format(' float advected every',i7,' baroclinic time steps')
  957 format(' float sampled every',i8,' baroclinic time steps'/)
  958 format(' input data for first',i3,' floats')
      do nfl=1,min(nflt,10)
        write(lp,959) nfl,(flt(nfl,i),i=1,9)
  959   format(3x,i2,1p,5e13.5/5x,4e13.5/)
      enddo
      call flush(lp)
      endif !1st tile
!
! ---------------------------------------------------------------------------
! --- allocate arrays for floats
! ---------------------------------------------------------------------------
!
      allocate( wvelup(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,kdm), &
                wveldn(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,kdm), &
                dpdxup(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy),  &
                dpdyup(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), &
                dpdxdn(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), &
                dpdydn(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) )
      allocate( wveli( 1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,  kdm+1), &
                uold2( 1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,2*kdm), &
                vold2( 1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,2*kdm), &
                wold2u(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,2*kdm), &
                wold2d(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy,2*kdm), &
                dlondx(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), &
                dlondy(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), &
                dlatdx(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy), &
                dlatdy(1-nbdy:idm+nbdy,1-nbdy:jdm+nbdy) )
      call mem_stat_add( 11*(idm+2*nbdy)*(jdm+2*nbdy)*kdm )
      call mem_stat_add(  9*(idm+2*nbdy)*(jdm+2*nbdy) )
!
      if (synflt) then
!$OMP   PARALLEL DO PRIVATE(j,i,k) &
!$OMP            SCHEDULE(STATIC,jblk)
        do j=1-nbdy,jj+nbdy
          do i=1-nbdy,ii+nbdy
            do k=1,kk
              uold2( i,j,k   )=hugel
              uold2( i,j,k+kk)=hugel
              vold2( i,j,k   )=hugel
              vold2( i,j,k+kk)=hugel
              wold2u(i,j,k   )=hugel
              wold2u(i,j,k+kk)=hugel
              wold2d(i,j,k   )=hugel
              wold2d(i,j,k+kk)=hugel
              wveli( i,j,k)   =hugel
            enddo !k
            wveli(i,j,kk+1)=hugel
          enddo
        enddo
!$OMP   END PARALLEL DO
      endif !synflt
!
! ---------------------------------------------------------------------------
! --- initialize old horizontal velocities for runga-kutta time interpolation
! --- calculate dlondx, dlondy, dlatdx, dlatdy required to convert u, v to
! --- longitude/time and latitude/time for float advection
! ---------------------------------------------------------------------------
!
      margin = nbdy - 1
!
      do j=1-margin,jj+margin
        do i=1-margin,ii+margin
          if (SEA_U) then
            do k=1,kk
              uold2(i,j,k   )=u(i,j,k,n)+ubavg(i,j,n)
              uold2(i,j,k+kk)=u(i,j,k,n)+ubavg(i,j,n)
#if defined(STOKES)                
              uold2(i,j,k   )=uold2(i,j,k   )+usd(i,j,k)
              uold2(i,j,k+kk)=uold2(i,j,k+kk)+usd(i,j,k)
#endif              
            enddo !k
            dlondx(i,j)=(plon(i  ,j)*scpy(i  ,j)-  &
                         plon(i-1,j)*scpy(i-1,j))/scu2(i,j)
            dlatdx(i,j)=(plat(i  ,j)*scpy(i  ,j)- &
                         plat(i-1,j)*scpy(i-1,j))/scu2(i,j)
            if (plat(i,j)-plat(i-1,j).ne.0.0) then
              nonlatlon=.true.
            endif
          endif !iu
          if (SEA_V) then
            do k=1,kk
              vold2(i,j,k   )=v(i,j,k,n)+vbavg(i,j,n)
              vold2(i,j,k+kk)=v(i,j,k,n)+vbavg(i,j,n)
#if defined(STOKES)                
              vold2(i,j,k   )=vold2(i,j,k   )+vsd(i,j,k)
              vold2(i,j,k+kk)=vold2(i,j,k+kk)+vsd(i,j,k)
#endif                  
            enddo !k
            dlondy(i,j)=(plon(i,j  )*scpx(i,j  )- &
                         plon(i,j-1)*scpx(i,j-1))/scv2(i,j)
            dlatdy(i,j)=(plat(i,j  )*scpx(i,j  )- &
                         plat(i,j-1)*scpx(i,j-1))/scv2(i,j)
            if (plon(i,j)-plon(i,j-1).ne.0.0) then
              nonlatlon=.true.
            endif
          endif !iv
          if (SEA_P) then
            do k=1,kk
              wold2u(i,j,k   )=0.0
              wold2d(i,j,k   )=0.0
              wold2u(i,j,k+kk)=0.0
              wold2d(i,j,k+kk)=0.0
              wveli (i,j,k   )=0.0
            enddo !k
            wveli(i,j,kk+1)=0.0
          endif !ip
        enddo !i
      enddo !j
!
! ----------------------------------------
! --- turbulent horizontal velocity option
! ----------------------------------------
!
! --- initialize turbulence constants
!
! --- tdecri is in inverse days and dtturb is the turbulent time step in days
!
! --- dtturb is set to the runga-kutta interpolation time step, which must
! --- be within 1 and 2 hours
!
      if (turbvel) then
        dtturb=deltfl/86400.0
        uturb0=sqrt(2.*tbvar*tdecri*dtturb)
      endif
!
      return
      end subroutine floats_init

      subroutine floats_restart
      implicit none
!
! -----------------------------
! --- output float restart file
! -----------------------------
!
      integer i,k,l
!
      if     (mnproc.eq.1) then
!
! ---   first remove floats that have run aground or left the domain
        i=0
        do l=1,nflt
          if (flt(l,1).gt.-999.0) then
            i=i+1
          endif
        enddo !1
!
        write(lp,*) 'writing new float input file for restart'
        call flush(lp)
!
        open(unit=uoff+802,file=flnmfltio, &
                           form='formatted',status='new')
        write(uoff+802,970) i
        write(uoff+802,970) nstepfl
        do l=1,nflt
          if (flt(l,1).gt.-999.0) then
            if (ifltyp(l).ne.2) then
            write(uoff+802,971) iflnum(l),ifltyp(l),flt(l,8),flt(l,9), &
                                (flt(l,k),k=1,3)
            else
            write(uoff+802,971) iflnum(l),ifltyp(l),flt(l,8),flt(l,9), &
                                (flt(l,k),k=1,2),flt(l,7)
            endif
          endif
        enddo !l
        close(uoff+802)
      endif !1st tile

  970 format(i9)
  971 format(i6,i2,2f9.2,3f15.9)

      return
      end subroutine floats_restart

      subroutine floats(m,n,timefl,ioflag)
      use mod_cb_arrays  ! HYCOM saved arrays
      implicit none 
!
      integer, parameter :: nfl_debug = -1  !no debugging
!     integer, parameter :: nfl_debug =  6  !debug float nfl_debug
!
      integer m,n,ioflag
      real    timefl
!
! --- local variables
      integer i,j,k,l,margin
      real    tflt,sflt,thlo,thhi,thflt, &
              uflt1,uflt2,uflt3,uflt4,uflt, &
              vflt1,vflt2,vflt3,vflt4,vflt, &
              wflt1,wflt2,wflt3,wflt4,wflt, &
              vkflt,tkflt,skflt,xpos0,xpos1,xpos2,xpos3, &
              ypos0,ypos1,ypos2,ypos3,depflt,plo,phi,q, &
              depiso,wvhi,wvlo,uvfctr,qisop,ufltm,vfltm, &
              alomin,alomax,alamin,alamax
      real    uturb,vturb,uturb1,vturb1,dlodx,dlody,dladx,dlady
      real*4  rtab(200,2)
      integer ifltll(3),jfltll(3),ngood(3)
      integer kflt,k1,k2,k3,ier,ngrid,kold1w,kold2w,kold1,kold2, &
              ntermn,i1,j1,ngoodi
      integer ied,iede,ifladv
!
      integer*4  seed,numran,inisee,iflag
      integer*4  iseed1,iseed2
      equivalence ( iseed1, iseed2, seed ) 
!
! --- local velocity component storage for synthetic moorings
      real fltloc(nflt,3)
!
! --- 2-d local arrays used for the 16-point box horizontal interpolation
      real    varb2d(4,4),ptlon(4,4,3),ptlat(4,4,3)
      logical maskpt(4,4,3),maskpi(4,4)
!
! --- arrays required for parallelization
      real    flt1(12*nflt),flt3(17*nflt)
      integer iproc
!
      real   timer1, timer2, totime
      real*8  wtime
!
# include "stmt_fns.h"
!
! -------------------------------------------------------------------------
! --- floats.f (hycom version 2.2)
! -------------------------------------------------------------------------
!
! --- synthetic floats, drifters, and mooring instruments
!
! --- optionally samples time series of dynamical/thermodynamical variables
! --- at the location of each float
!
! --- four float types are presently supported:
! ---    3-d lagrangian (vertically advected by diagnosed vertical velocity)
! ---    isopycnic      (remains on specified density surface)
! ---    isobaric       (remains at the pressure depth where it was released)
! ---    stationary     (synthetic instrument/mooring)
!
! --- horizontal advection, along with vertical advection of lagrangian floats,
! --- is performed using the MICOM runga-kutta-4 time interpolation algorithm
! --- developed by Zulema Garraffo
!
! --- works on any curvilinear grid
!
! --- float position is stored as longitude and latitude
!
! --- to horizontal advect the float, u and v are first converted to
! --- d(longitude)/dt and d(latitude)/dt as follows:
!
! ---   u_lon = u*dlondx + v*dlondy
! ---   v_lat = u*dlatdx + v*dlatdy
!
! --- to horizontally advect the float, terms u*dlondx and u*dlatdx are
! --- calculated on u grid points while terms v*dlondy and v*dlatdy are
! --- calculated on v grid ponts. these terms are then interpolated to
! --- the float locations from the surrounding u and v grid points,
! --- respectively
!
! --- since the terms v*dlondy and u*dlatdx are always zero when the model
! --- x,y axes are everywhere lines of constant latitude and longitude,
! --- respectively, logical variable 'nonlatlon' prevents horizontal
! --- interpolation of these terms in this case
!
! --- horizontal interpolation to the float location follows the MICOM
! --- procedure of Zulema Garraffo - second-order interpolation from the 16
! --- surrounding grid points is performed unless fewer than nptmin (presently
! --- set to 10 in subroutine intrph) water points are available, in which
! --- case nearest-neighbor interpolation is used.
!
! --- variables are horizontally interpolated from their native grid (p, u,
! --- or v)
!
! --- adapted for hycom by george halliwell
! --- code parallelized by remy baraille
!
! --- the second-order interpolation subroutine included here is the one
! --- included in the mariano and brown parameter matrix objective analysis
! --- algorithm to estimate the large scale trend surface - it is different
! --- from the algorithm used by Garraffo in MICOM
!
! --- float initialization is performed in floats_init - information
! --- about the input file containing initial float information is
! --- presented in that subroutine.
!
! --- variables in array flt(nfl,n) are:
!
! ---   n = 1  longitude
! ---   n = 2  latitude
! ---   n = 3  float depth 
! ---   n = 4  water depth
! ---   n = 5  temperature
! ---   n = 6  salinity
! ---   n = 7  water density
! ---   n = 8  float start time (in days from start of model run)
! ---   n = 9  float end   time (in days from start of model run)
!
! --- time series of several variables are interpolated to the location of each
! --- float and saved every nflsam time steps when ioflag is set to 1
!
! --- variables output onto file float.out for each float are:
!
! ---   1. initial sequential float number
! ---   2. time (in days from start of model run)
! ---   3. model layer number that contains the float
! ---   4. longitude   (u for synthetic moorings)
! ---   5. latitude    (v for synthetic moorings)
! ---   6. float depth (w for synthetic moorings)
! ---   7. water depth
! ---   8. temperature
! ---   9. salinity
! ---  10. water density (remains constant for isopycnic floats)
!
      call xctilr(dp(     1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_ps)
      call xctilr(dpu(    1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_vs)
      call xctilr(dpv(    1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_vs)
      call xctilr(u(      1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_uv)
      call xctilr(v(      1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_vv)
      call xctilr(ubavg(  1-nbdy,1-nbdy,  n),1, 1, 6,6, halo_uv)
      call xctilr(vbavg(  1-nbdy,1-nbdy,  n),1, 1, 6,6, halo_vv)
      call xctilr(temp(   1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_ps)
      call xctilr(saln(   1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_ps)
      call xctilr(th3d(   1-nbdy,1-nbdy,1,n),1,kk, 6,6, halo_ps)
!
! --- calculate vertical velocity at interfaces as the sum of the
! --- vertical interface velocity estimated in cnuity.f and the
! --- advective component due to flow parallel to interfaces.
! --- wvelup and wveldn represent velocity at the top and bottom of
! --- layer k
!
      margin = 6
!
! --- set pressure array at p points
      do j=1-margin,jj+margin
        do i=1-margin,ii+margin
          if (SEA_P) then
            do k=1,kk
              k1=k+1
              p(i,j,k+1)=p(i,j,k)+dp(i,j,k,n)
            enddo !k
          endif !ip
        enddo !i
      enddo !j
!
! --- set pressure array at u and v points
! --- calculate dpdx, dpdy at interfaces above and below layer k for
! --- estimating wvel within layer k
!
      do k=1,kk
!
        margin = 5
!
        do j=1-margin,jj+margin
          do i=1-margin,ii+margin
            if (SEA_U) then
              pu(i,j,k+1)=pu(i,j,k)+dpu(i,j,k,n)
              if (wvelfl) then
                dpdxup(i,j)= &
                  (p(i,j,k  )*scpy(i,j)-p(i-1,j,k  )*scpy(i-1,j)) &
                  /scu2(i,j)
                dpdxdn(i,j)= &
                  (p(i,j,k+1)*scpy(i,j)-p(i-1,j,k+1)*scpy(i-1,j)) &
                  /scu2(i,j)
              endif
            endif !iu
            if (SEA_V) then
              pv(i,j,k+1)=pv(i,j,k)+dpv(i,j,k,n)
              if (wvelfl) then
                dpdyup(i,j)= &
                  (p(i,j,k  )*scpx(i,j)-p(i,j-1,k  )*scpx(i,j-1)) &
                  /scv2(i,j)
                dpdydn(i,j)= &
                  (p(i,j,k+1)*scpx(i,j)-p(i,j-1,k+1)*scpx(i,j-1)) &
                  /scv2(i,j)
              endif
            endif !iv
          enddo !i
        enddo !j
!
! --- calculate the vertical velocity arrays
!
        margin = 4
!
        do j=1-margin,jj+margin
          do i=1-margin,ii+margin
            if (SEA_P) then
              if (wvelfl) then
                wveli(i,j,k+1)=deltfl*wveli(i,j,k+1)/delt1
                if (dp(i,j,k,n).gt.tencm) then
                    wvelup(i,j,k)=-0.5*deltfl* &
#if defined(STOKES)
               ((u(i  ,j  ,k,n)+usd(i  ,j  ,k)+ &
                 ubavg(i  ,j  ,n))*dpdxup(i  ,j  )+ &
                (u(i+1,j  ,k,n)+usd(i+1,j  ,k)+ &
                 ubavg(i+1,j  ,n))*dpdxup(i+1,j  )+ &
                (v(i  ,j  ,k,n)+vsd(i  ,j  ,k)+ &
                 vbavg(i  ,j  ,n))*dpdyup(i  ,j  )+ &
                (v(i  ,j+1,k,n)+vsd(i  ,j+1,k)+ &
                 vbavg(i  ,j+1,n))*dpdyup(i  ,j+1)) &
#else
                  ((u(i  ,j  ,k,n)+ubavg(i  ,j  ,n))*dpdxup(i  ,j  )+ &
                   (u(i+1,j  ,k,n)+ ubavg(i+1,j  ,n))*dpdxup(i+1,j  )+ &
                   (v(i  ,j  ,k,n)+vbavg(i  ,j  ,n) )*dpdyup(i  ,j  )+ &
                   (v(i  ,j+1,k,n)+vbavg(i  ,j+1,n))*dpdyup(i  ,j+1)) &
#endif
                   /onem+wveli(i,j,k  )
                  wveldn(i,j,k)=-0.5*deltfl* &
#if defined(STOKES)
            ((u(i  ,j  ,k,n)+usd(i  ,j  ,k)+ &
              ubavg(i  ,j  ,n))*dpdxdn(i  ,j  )+ &
             (u(i+1,j  ,k,n)+usd(i+1,j  ,k)+ &
              ubavg(i+1,j,n))*dpdxdn(i+1,j  )+ &
             (v(i  ,j  ,k,n)+vsd(i  ,j  ,k)+ &
              vbavg(i  ,j  ,n))*dpdydn(i  ,j  )+ &
             (v(i  ,j+1,k,n)+vsd(i  ,j+1,k)+ &
              vbavg(i  ,j+1,n))*dpdydn(i  ,j+1)) &
#else
                  ((u(i  ,j  ,k,n)+ubavg(i  ,j  ,n))*dpdxdn(i  ,j  )+ &
                   (u(i+1,j  ,k,n)+ubavg(i+1,j  ,n))*dpdxdn(i+1,j  )+ &
                   (v(i  ,j  ,k,n)+vbavg(i  ,j  ,n))*dpdydn(i  ,j  )+ &
                   (v(i  ,j+1,k,n)+vbavg(i  ,j+1,n))*dpdydn(i  ,j+1)) &
#endif
                   /onem+wveli(i,j,k+1)
                else
                  wvelup(i,j,k)=0.0
                  wveldn(i,j,k)=0.0
                endif
              endif
            endif !ip
          enddo !i
        enddo !j
!
      enddo !k
!
!     call xctilr(wvelup(1-nbdy,1-nbdy,1),1, kk, 4,4, halo_ps)
!     call xctilr(wveldn(1-nbdy,1-nbdy,1),1, kk, 4,4, halo_ps)
!
! --- set old velocity indices used for interpolation of float position
! --- perform full float update every two times this subroutine is called;
! --- at the intermediate times, just store old velocity fields for the next
! --- call
!
      if (mod(nstepfl,nfladv).eq.nfldta) then
        kold1 =kk
        kold1w=kk+1
        kold2 =0
        kold2w=0
        go to 10
      else
        kold1 =0
        kold1w=0
        kold2 =kk
        kold2w=kk+1
      endif
!
! --- turbulent horizontal velocity option
!
! --- to customize the parameter settings in blkdat.input that control
! --- the calculated turbulent velocity (tbvar, tdecri), refer to
! --- Griffa (1996), "Aplications of stochastic particles models to
! --- oceanographic problems" in "Stochatic Modelling in Physical
! --- Oceanography", pp. 114-140, Adler, Muller, and Rozovoskii, editors
!
      if (turbvel) then
!
! --- initialize random seeds and create random number table
! --- if iflag=1 (iflag=0), then time() is (is not) used to generate seeds
!
        iflag=1
        call system_clock(inisee)
        seed = 414957000-inisee
        iede = iseed1
        ied  = iseed2
        if (iede .lt. 0) iede = abs(iede)
        if (ied  .lt. 0) ied  = abs(ied)
!
        call rantab_ini(rtab,iseed1,iseed2,iflag)
      endif
!
! --- get particle locations from processor 1
      if     (mnproc.eq.1) then
        do nfl=1,nflt
          do i=1,9
            flt1( i+12*(nfl-1)) = flt(nfl,i)
          enddo
          flt1(10+12*(nfl-1)) = kfloat(nfl)
          flt1(11+12*(nfl-1)) = iflnum(nfl)
          flt1(12+12*(nfl-1)) = ifltyp(nfl)
        enddo
      endif !1st tile
      call xcastr(flt1(1:12*nflt), 1)
      if     (mnproc.ne.1) then
        do nfl=1,nflt
          do i=1,9
            flt(nfl,i) = flt1( i+12*(nfl-1))
          enddo
          kfloat(nfl) = flt1(10+12*(nfl-1))
          iflnum(nfl) = flt1(11+12*(nfl-1))
          ifltyp(nfl) = flt1(12+12*(nfl-1))
        enddo
      endif !1st tile
!
! ----------------------
! --- begin float loop
! ----------------------
!
      do nfl=1,nflt
!
! --- skip if float has previously run aground or exceeded termination time
        if(flt(nfl,1).le.-999.) then
          go to 22
        endif
!
! --- ier    = error flag for horizontal interpolation
! --- ntermn = float termination flag
! ---             -10 => reached termination time
! ---              -5 => exited domain
! ---              >0 => ran aground
! --- ifladv = float horizontal advection flag
        ier=0
        ntermn=0
        ifladv=1
!
! --- suppress float advection if this is the first time step so that
! --- the initial position on the output file is exactly the position
! --- specified on the input file
        if (nstepfl.eq.1) then
          ifladv=0
        endif
!
! --- check if model time has reached float deployment time
! --- when it does, again suppress float advection during first pass
        if (timefl-flt(nfl,8).lt.-0.001) then
          go to 22
        endif
        if (kfloat(nfl).lt.0) then
          ifladv=0
        endif
!
! --- check if model time has reached float termination time
        if (       flt(nfl,9).gt.0.0 .and. &
            timefl-flt(nfl,9).gt.0.001    ) then
          ntermn=-10
        endif
!
! ---------------------------------------------------------------------------
! --- search for the processor controlling the tile containing the grid point
! --- search for the surrounding 16 grid points on the p, u, and v grids
! ---------------------------------------------------------------------------
!
! --- processeur sur lequel va se derouler le calcul
!
        iproc=0
!
        margin = 0
!
        do j=1-margin,jj+margin
          do i=1-margin,ii+margin
            if (SEA_P) then
!
! --- search for the surrounding p-grid points
              if (i+i0.lt.itdm .and. j+j0.lt.jtdm) then
                alomin=min(plon(i  ,j),plon(i  ,j+1), &
                           plon(i+1,j),plon(i+1,j+1))
                alomax=max(plon(i  ,j),plon(i  ,j+1), &
                           plon(i+1,j),plon(i+1,j+1))
                alamin=min(plat(i  ,j),plat(i  ,j+1), &
                           plat(i+1,j),plat(i+1,j+1))
                alamax=max(plat(i  ,j),plat(i  ,j+1), &
                           plat(i+1,j),plat(i+1,j+1))
                if (flt(nfl,1).ge.alomin.and.flt(nfl,1).lt.alomax.and. &
                    flt(nfl,2).ge.alamin.and.flt(nfl,2).lt.alamax) then
                  ifltll(1)=i
                  jfltll(1)=j
!
! --- determine if float has exited domain
                  if (i+i0.lt.2 .or. i+i0.gt.itdm-1 .or. &
                      j+j0.lt.2 .or. j+j0.gt.jtdm-1) then
                    ntermn=-5
                  endif
!
! --- search for the surrounding u-grid points
                  do i1=i-1,i+1
                    do j1=j-1,j+1
                      if (i1+i0.lt.itdm .and. j1+j0.lt.jtdm) then
                        alomin=min(ulon(i1  ,j1),ulon(i1  ,j1+1), &
                                   ulon(i1+1,j1),ulon(i1+1,j1+1))
                        alomax=max(ulon(i1  ,j1),ulon(i1  ,j1+1), &
                                   ulon(i1+1,j1),ulon(i1+1,j1+1))
                        alamin=min(ulat(i1  ,j1),ulat(i1  ,j1+1), &
                                   ulat(i1+1,j1),ulat(i1+1,j1+1))
                        alamax=max(ulat(i1  ,j1),ulat(i1  ,j1+1), &
                                  ulat(i1+1,j1),ulat(i1+1,j1+1))
                        if (flt(nfl,1).ge.alomin .and. &
                            flt(nfl,1).lt.alomax .and. &
                            flt(nfl,2).ge.alamin .and. &
                            flt(nfl,2).lt.alamax) then  
                          ifltll(2)=i1
                          jfltll(2)=j1
!
! --- determine if float has exited domain
                          if (i1+i0.lt.2 .or. i1+i0.gt.itdm-1 .or. &
                             j1+j0.lt.2 .or. j1+j0.gt.jtdm-1) then
                            ntermn=-5
                          endif
                          go to 11
                        endif
                      endif
                    enddo !j1
                  enddo !i1
 11               continue
!
! --- search for the surrounding v-grid points
                  do i1=i-1,i+1
                    do j1=j-1,j+1
                      if (i1+i0.lt.itdm .and. j1+j0.lt.jtdm) then
                        alomin=min(vlon(i1  ,j1),vlon(i1  ,j1+1), &
                                   vlon(i1+1,j1),vlon(i1+1,j1+1))
                        alomax=max(vlon(i1  ,j1),vlon(i1  ,j1+1), &
                                   vlon(i1+1,j1),vlon(i1+1,j1+1))
                        alamin=min(vlat(i1  ,j1),vlat(i1  ,j1+1), &
                                   vlat(i1+1,j1),vlat(i1+1,j1+1))
                        alamax=max(vlat(i1  ,j1),vlat(i1  ,j1+1), &
                                   vlat(i1+1,j1),vlat(i1+1,j1+1))
                        if (flt(nfl,1).ge.alomin .and. &
                            flt(nfl,1).lt.alomax .and. &
                            flt(nfl,2).ge.alamin .and. &
                            flt(nfl,2).lt.alamax) then      
                          ifltll(3)=i1
                          jfltll(3)=j1
!
! --- determine if float has exited domain
                          if (i1+i0.lt.2 .or. i1+i0.gt.itdm-1 .or. &
                              j1+j0.lt.2 .or. j1+j0.gt.jtdm-1) then
                            ntermn=-5
                          endif
                          go to 12
                        endif
                      endif
                    enddo !j1
                  enddo !i1
 12               continue
!
! --- set processor number for the tile containing the float and exit grid
! --- point search
                  iproc=mnproc
                  go to 13
                endif
              endif
            endif !ip
          enddo !i
        enddo !j
!
 13     continue
!
! --- float nfl is now updated by the processor running the tile containing
! --- the float
!
        if (iproc.gt.0) then
!
          if     (nfl.eq.nfl_debug) then
            write(lp,100) nfl,nflt,nstep,nstepfl
            write(lp,101) nfl,ntermn,flt(nfl,1),flt(nfl,2), &
                         (ifltll(i)+i0,jfltll(i)+j0,i=1,3), &
                          mnproc, &
                          plon(ifltll(1),jfltll(1)), &
                          plat(ifltll(1),jfltll(1))
 100        format(/'diagnostics for float',i6,' of',i6,', time step', &
                    i9/'float time step',i9)
 101        format('float',i6,' ntermn:',i6,' position:',2(1pe12.4)/ &
                   'lower left points, p,u,v:',3(2i5,2x)/ &
                   'mnproc =',i4,'  plon,plat =',1pe12.4,1pe12.4)
            call flush(lp)
          endif !nfl_debug
!
! --- if float has exited domain or run aground as determined previously,
! --- jump ahead to the float termination code bloci
          if (ntermn.eq.-5 .or. ntermn.eq.1) then
            go to 30
          endif
!
! --- set ptlon, ptlat for all horizontal interpolations from each grid
          ngrid=1
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              ptlon(i1,j1,ngrid)=plon(i,j)
              ptlat(i1,j1,ngrid)=plat(i,j)
            enddo
          enddo
!
          ngrid=2
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              ptlon(i1,j1,ngrid)=ulon(i,j)
              ptlat(i1,j1,ngrid)=ulat(i,j)
            enddo
          enddo
!
          ngrid=3
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              ptlon(i1,j1,ngrid)=vlon(i,j)
              ptlat(i1,j1,ngrid)=vlat(i,j)
            enddo
          enddo
!
! --- the float is assumed to remain within the same layer that it was in
! --- during the previous update unless it is the first advection time step
! --- for the float, in which case it is initially assumed to be in layer 1
!
          k=max(1,kfloat(nfl))
!
! --- mask p grid points that are on land or where the layer containing the
! --- float is a zero or nearly-zero thickness layer at the bottom
          ngrid=1
          ngood(ngrid)=0
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              if (depths(i,j).lt.0.01 .or. depths(i,j).eq.hugel .or. &
                  depths(i,j)*onem-p(i,j,k).lt.tencm) then
                maskpt(i1,j1,ngrid)=.true.
              else
                maskpt(i1,j1,ngrid)=.false.
                ngood(ngrid)=ngood(ngrid)+1
              endif
            enddo
          enddo
!
          if     (nfl.eq.nfl_debug) then
            write(lp,102) ngood(1)
 102        format('initial masking: no. of good p points',i4)
          endif !nfl_debug
!
! --------------------------------------------------
! --- determine the model layer containing the float
! --------------------------------------------------
!
! --- if this is not the first advection time step for the float, determine
! --- if the float has transited to another model layer
!
          if (kfloat(nfl).ge.1) then
!
! --- check if the float is deeper than the interpolated bottom
! --- depth - if so, reset the depth to 0.1 m above the bottom - this
! --- prevents from running aground too frequently in coastal regions
            if (ifltyp(nfl).ne.4) then
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=p(i,j,kk+1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,plo,ier)
              flt(nfl,3)=max(fldepm,min(flt(nfl,3),(plo-tencm)/onem))
            endif
!
! --- has the float remained in the same layer?
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=p(i,j,k)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,phi,ier)
!
! --- terminate float because it has run aground
            if (ier.eq.999) then
              ntermn=2
              go to 30
            endif
!
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=p(i,j,k+1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,plo,ier)
            phi=phi/onem
            plo=plo/onem
!
! --- if the float is in the same model layer, skip ahead
            if (flt(nfl,3).gt.phi .and. flt(nfl,3).le.plo) then
              kflt=kfloat(nfl)
              go to 40
            endif
!
! --- determine the new model layer containing the float
!
! --- did the float move up one layer?
            if (flt(nfl,3).le.phi .and. kfloat(nfl).gt.1) then
              k=kfloat(nfl)-1
              plo=phi
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=p(i,j,k)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,phi,ier)
              phi=phi/onem
              if (flt(nfl,3).gt.phi .and. flt(nfl,3).le.plo) then
                kflt=k
                go to 40
              endif
            endif
!
! --- did the float move down one layer?
            if (flt(nfl,3).gt.plo .and. kfloat(nfl).lt.kk) then
              k=kfloat(nfl)+1
              phi=plo
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=p(i,j,k)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,plo,ier)
              plo=plo/onem
              if (flt(nfl,3).gt.phi .and. flt(nfl,3).le.plo) then
                kflt=k
                go to 40
              endif
            endif
!
          endif
!
! --- if the float did not move up or down one layer, or if this is the
! --- first time step after float initialization, search for the layer
! --- containg the float from top to bottom
          ngrid=1
          plo=0.
          k2=0
          k3=0
          do k=1,kk
            k1=min(k+3,kk+1)
!
! --- if the depth of interface k1 is not deeper than the float at any
! --- surrounding grid points, skip to end of k-loop
            if (k2.eq.0) then
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  if (.not.maskpt(i1,j1,ngrid) .and. &
                      p(i,j,k1)/onem.gt.flt(nfl,3)) then
                    k2=1
                  endif
                enddo
              enddo
            endif
            if (k2.eq.0) then
              go to 42
            endif
!
! --- mask points where the layer being tested rests on the bottom
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                if (k2.eq.1) then
                  maskpi(i1,j1)=maskpt(i1,j1,ngrid)
                endif
                if (.not.maskpi(i1,j1) .and. &
                    depths(i,j)*onem-p(i,j,k).lt.tencm) then
                  maskpi(i1,j1)=.true.
                  ngood(ngrid)=ngood(ngrid)-1
                endif
              enddo
            enddo
            k2=2
!
! --- if too few good points remain, float has run aground
            if (ngood(ngrid).le.2) then
              ntermn=3
              go to 30
            endif
!
! --- interpolate to find plo
            phi=plo
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=p(i,j,k+1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,plo,ier)
            plo=plo/onem
            if(plo-phi.gt.0.1) then
              k3=k
            else
              kflt=k3
              do i1=1,4
                do j1=1,4
                  maskpt(i1,j1,ngrid)=maskpi(i1,j1)
                enddo
              enddo
              go to 40
            endif
            if (flt(nfl,3).lt.plo) then
              kflt=k
              do i1=1,4
                do j1=1,4
                  maskpt(i1,j1,ngrid)=maskpi(i1,j1)
                enddo
              enddo
              go to 40
            endif
 42         continue
          enddo
!
! --- if layer selection fails, assume float has run aground
          print *,'warning - selection of float layer failed'
          ntermn=4
          go to 30
!
! --- we now know the model layer containing the float
 40       kfloat(nfl)=kflt
!
! ------------------------------------------
! --- set grid masks for u and v grid points
! ------------------------------------------
!
          k=kflt
          ngrid=2
          ngood(ngrid)=0
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              if (depthu(i,j).lt.onecm .or. depthu(i,j).eq.hugel .or. &
                  depthu(i,j)-pu(i,j,k).lt.tencm) then
                maskpt(i1,j1,ngrid)=.true.
              else
                maskpt(i1,j1,ngrid)=.false.
                ngood(ngrid)=ngood(ngrid)+1
              endif
            enddo
          enddo
!
          ngrid=3
          ngood(ngrid)=0
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              if (depthv(i,j).lt.onecm .or. depthv(i,j).eq.hugel .or. &
                  depthv(i,j)-pv(i,j,k).lt.tencm) then
                maskpt(i1,j1,ngrid)=.true.
              else
                maskpt(i1,j1,ngrid)=.false.
                ngood(ngrid)=ngood(ngrid)+1
              endif
            enddo
          enddo
!
! --- if too few good p, u, v grid points, assume float has run aground
          if (ngood(1).le.2 .or. ngood(2).le.2 .or. ngood(3).le.2) then
            ntermn=5
            go to 30
          endif
!
          if     (nfl.eq.nfl_debug) then
            write(lp,103) nfl,k,phi,flt(nfl,3),plo,q
            write(lp,104) ngood
 103        format('nfl,k,phi,pflt,plo,q',i6,i3,1p,4e12.4)
 104        format('number of good points, p,u,v',3i4)
          endif !nfl_debug
!
! --- set vertical indices, and also set q for vertical interpolation
          k=kfloat(nfl)
          k1=max(1,k-1)
          k2=min(kk,k+1)
          q=(plo-flt(nfl,3))/max(0.001,plo-phi)
!
! ----------------------------------------------------------
! --- advect the float horizontally, then move it vertically
! --- do not move float if it is a mooring instrument
! ----------------------------------------------------------
!
! ----------------------------------
! --- horizontal advection of floats
! ----------------------------------
!
          if (ifltyp(nfl).ne.4) then
!
! --- interpolate u,v to float location - velocities at the new time and
! --- at two earlier times are used for the runga-kutta time interpolation
!
            xpos0=flt(nfl,1)
            ypos0=flt(nfl,2)
!
            ngrid=2
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlondx(i,j)*uold2(i,j,k+kold2)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos0,ypos0,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,uflt1,ier)
!
! --- terminate float because it has run aground
            if (ier.eq.999) then
              ntermn=6
              go to 30
            endif
!
            if (nonlatlon) then
              ngrid=3
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlondy(i,j)*vold2(i,j,k+kold2)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,ufltm,ier)
              uflt1=uflt1+ufltm
!
! --- terminate float because it has run aground
              if (ier.eq.999) then
                ntermn=7
                go to 30
              endif
            endif
!
            ngrid=3
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlatdy(i,j)*vold2(i,j,k+kold2)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos0,ypos0,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,vflt1,ier)
!
! --- terminate float because it has run aground
            if (ier.eq.999) then
              ntermn=8
              go to 30
            endif
!
            if (nonlatlon) then
              ngrid=2
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlatdx(i,j)*uold2(i,j,k+kold2)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,vfltm,ier)
              vflt1=vflt1+vfltm
!
! --- terminate float because it has run aground
              if (ier.eq.999) then
                ntermn=9
                go to 30
              endif
            endif
!
            xpos1=flt(nfl,1)+uflt1
            ypos1=flt(nfl,2)+vflt1
!
            ngrid=2
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlondx(i,j)*uold2(i,j,k+kold1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos1,ypos1,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,uflt2,ier)
!
            if (nonlatlon) then
              ngrid=3
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlondy(i,j)*vold2(i,j,k+kold1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,ufltm,ier)
              uflt2=uflt2+ufltm
            endif
!
            ngrid=3
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlatdy(i,j)*vold2(i,j,k+kold1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos1,ypos1,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,vflt2,ier)
!
            if (nonlatlon) then
              ngrid=2
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlatdx(i,j)*uold2(i,j,k+kold1)
                enddo
              enddo
             call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                         xpos0,ypos0,maskpt(1,1,ngrid), &
                         ngood(ngrid),ngrid,intpfl,radian,vfltm,ier)
              vflt2=vflt2+vfltm
            endif
!
            xpos2=flt(nfl,1)+uflt2
            ypos2=flt(nfl,2)+vflt2
            ngrid=2
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlondx(i,j)*uold2(i,j,k+kold1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos2,ypos2,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,uflt3,ier)
!
            if (nonlatlon) then
              ngrid=3
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlondy(i,j)*vold2(i,j,k+kold1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,ufltm,ier)
              uflt3=uflt3+ufltm
            endif
!
            ngrid=3
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                varb2d(i1,j1)=dlatdy(i,j)*vold2(i,j,k+kold1)
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos2,ypos2,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,vflt3,ier)
!
            if (nonlatlon) then
              ngrid=2
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlatdx(i,j)*uold2(i,j,k+kold1)
                enddo
              enddo
             call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                         xpos0,ypos0,maskpt(1,1,ngrid), &
                         ngood(ngrid),ngrid,intpfl,radian,vfltm,ier)
              vflt3=vflt3+vfltm
            endif
!
          endif
!
          if (ifltyp(nfl).ne.4) then
            xpos3=flt(nfl,1)+2.0*uflt3
            ypos3=flt(nfl,2)+2.0*vflt3
          else
            xpos3=flt(nfl,1)
            ypos3=flt(nfl,2)
          endif
!
          ngrid=2
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              if (ifltyp(nfl).ne.4) then
#if defined(STOKES)
                 varb2d(i1,j1)=dlondx(i,j)*(u(i,j,k,n)+usd(i,j,k)+ &
                    ubavg(i,j,n))
              else
      varb2d(i1,j1)=u(i,j,k,n)+usd(i,j,k)+ubavg(i,j,n)
#else
                varb2d(i1,j1)=dlondx(i,j)*(u(i,j,k,n)+ubavg(i,j,n))
              else
                varb2d(i1,j1)=u(i,j,k,n)+ubavg(i,j,n)
#endif                
                
              endif
            enddo
          enddo
         call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                     xpos3,ypos3,maskpt(1,1,ngrid), &
                     ngood(ngrid),ngrid,intpfl,radian,uflt4,ier)
!
          if (nonlatlon .and. ifltyp(nfl).ne.4) then
            ngrid=3
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                
#if defined(STOKES)
                varb2d(i1,j1)=dlondy(i,j)*(v(i,j,k,n)+vsd(i,j,k)+ &
                        vbavg(i,j,n))
#else                
                varb2d(i1,j1)=dlondy(i,j)*(v(i,j,k,n)+vbavg(i,j,n))
#endif                          
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos0,ypos0,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,ufltm,ier)
            uflt4=uflt4+ufltm
          endif
!
          ngrid=3
          do i1=1,4
            i=i1+ifltll(ngrid)-2
            do j1=1,4
              j=j1+jfltll(ngrid)-2
              if (ifltyp(nfl).ne.4) then
                  
#if defined(STOKES)
               varb2d(i1,j1)=dlatdy(i,j)*(v(i,j,k,n)+vsd(i,j,k)+ &
                   vbavg(i,j,n))
              else
       varb2d(i1,j1)=v(i,j,k,n)+vsd(i,j,k)+vbavg(i,j,n)
#else
                varb2d(i1,j1)=dlatdy(i,j)*(v(i,j,k,n)+vbavg(i,j,n))
              else
                varb2d(i1,j1)=v(i,j,k,n)+vbavg(i,j,n)
#endif                      
              endif
            enddo
          enddo
          call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                      xpos3,ypos3,maskpt(1,1,ngrid), &
                      ngood(ngrid),ngrid,intpfl,radian,vflt4,ier)
!
          if (nonlatlon .and. ifltyp(nfl).ne.4) then
            ngrid=2
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                
#if defined(STOKES)
                varb2d(i1,j1)=dlatdx(i,j)*(u(i,j,k,n)+usd(i,j,k)+ &
                         ubavg(i,j,n))
#else           
                varb2d(i1,j1)=dlatdx(i,j)*(u(i,j,k,n)+ubavg(i,j,n))
#endif                
                
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos0,ypos0,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,vfltm,ier)
            vflt4=vflt4+vfltm
          endif
!
          if (ifltyp(nfl).ne.4) then
            uflt=(uflt1+2.0*uflt2+2.0*uflt3+uflt4)/6.0
            vflt=(vflt1+2.0*vflt2+2.0*vflt3+vflt4)/6.0
!
! --- add turbulent velocity to u and v if requested
!
            if (turbvel) then
              call rantab(rtab,iseed1,iseed2,numran)
              uturb=uturb0*rtab(numran, 2)
              call rantab(rtab,iseed1,iseed2,numran)
              vturb=uturb0*rtab(numran, 2)
!
! --- convert uturb, vturb to d(longitude)/dt, d(latitude)/dt
! --- interpolate dlondx, dlondy, dlatdx, dlatdy to the float location
!
              ngrid=2
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlondx(i,j)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,dlodx,ier)
              if (nonlatlon) then
                do i1=1,4
                  i=i1+ifltll(ngrid)-2
                  do j1=1,4
                    j=j1+jfltll(ngrid)-2
                    varb2d(i1,j1)=dlatdx(i,j)
                  enddo
                enddo
               call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                           xpos0,ypos0,maskpt(1,1,ngrid), &
                           ngood(ngrid),ngrid,intpfl,radian,dladx,ier)
                ngrid=3
                do i1=1,4
                  i=i1+ifltll(ngrid)-2
                  do j1=1,4
                    j=j1+jfltll(ngrid)-2
                    varb2d(i1,j1)=dlondy(i,j)
                  enddo
                enddo
                call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                            xpos0,ypos0,maskpt(1,1,ngrid), &
                            ngood(ngrid),ngrid,intpfl,radian,dlody,ier)
              else
                dladx=0.0
                dlody=0.0
              endif
              ngrid=3
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=dlatdy(i,j)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          xpos0,ypos0,maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,dlady,ier)
!
! --- add turbulent velocity to uflt, vflt
!
              uturb1=uturb*dlodx+vturb*dlody
              vturb1=uturb*dladx+vturb*dlady
!
      if     (nfl.eq.nfl_debug) then
        write(lp,105) nfl,uflt,uturb1,vflt,vturb1
 105    format('nfl,uflt,uturb1,vflt,vturb1',i5,1p,4e12.4)
      endif !nfl_debug
!
              uflt=(1.0-dtturb*tdecri)*uflt+uturb1
              vflt=(1.0-dtturb*tdecri)*vflt+vturb1
!
            endif
!
! --- update float horizontal position
!
            if (ifladv.eq.1) then
              flt(nfl,1)=flt(nfl,1)+2.0*deltfl*uflt
              flt(nfl,2)=flt(nfl,2)+2.0*deltfl*vflt
            endif
!
      if     (nfl.eq.nfl_debug) then
        write(lp,106) nfl,flt(nfl,1),xpos1,xpos2,xpos3, &
                      uflt1,uflt2,uflt3,uflt4,2.0*deltfl*uflt
        write(lp,107) nfl,flt(nfl,2),ypos1,ypos2,ypos3, &
                      vflt1,vflt2,vflt3,vflt4,2.0*deltfl*vflt
        write(lp,108) nfl,uflt,vflt,flt(nfl,1),flt(nfl,2)
 106    format('nfl,x-position',i6,1p,4e12.4/'    u-velocity',6x,5e12.4)
 107    format('nfl,y-position',i6,1p,4e12.4/'    v-velocity',6x,5e12.4)
 108    format('nfl,udeg,vdeg',i6,1p,2e13.5/'new position',2e13.5)
      endif !nfl_debug
!
          endif
!
! -----------------------------------------------
! --- vertical advection of 3-d lagrangian floats
! -----------------------------------------------
!
! --- horizontally interpolate diagnosed vertical velocity to the float
! --- location at the new time and at two earlier times to execute the
! --- runga-kutta time interpolation
!
          if (wvelfl .and. ifltyp(nfl).eq.1) then
!
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                wvhi=wold2u(i,j,k+kold2)
                wvlo=wold2d(i,j,k+kold2)
                varb2d(i1,j1)=q*wvhi+(1.0-q)*wvlo
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos0,ypos0,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,wflt1,ier)
!
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                wvhi=wold2u(i,j,k+kold1)
                wvlo=wold2d(i,j,k+kold1)
                varb2d(i1,j1)=q*wvhi+(1.0-q)*wvlo
              enddo
            enddo
           call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                       xpos1,ypos1,maskpt(1,1,ngrid), &
                       ngood(ngrid),ngrid,intpfl,radian,wflt2,ier)
!
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos2,ypos2,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,wflt3,ier)
!
          endif
!
          if (wvelfl) then
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                wvhi=wvelup(i,j,k)
                wvlo=wveldn(i,j,k)
                varb2d(i1,j1)=q*wvhi+(1.0-q)*wvlo
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        xpos3,ypos3,maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,wflt4,ier)
          endif
!
          if (ifltyp(nfl).eq.1) then
!
! --- dividing by 3 gives total vertical displacement over interval 2*deltfl
            wflt=(wflt1+2.0*wflt2+2.0*wflt3+wflt4)/3.0
            if (ifladv.eq.1) then
              flt(nfl,3)=max(fldepm,flt(nfl,3)-wflt)
            endif
            if     (nfl.eq.nfl_debug) then
              write(lp,109) nfl,wflt,flt(nfl,3)
 109          format('nfl,w,new depth',i6,1p,2e13.5)
            endif !nfl_debug
!
          elseif (ifltyp(nfl).eq.2) then
!
! ---------------------------------------
! --- vertical motion of isopycnic floats
! ---------------------------------------
!
! --- set float depth to the vertically interpolated depth of the specified
! --- density interface
!
! --- assume float runs aground if no water denser than the specified density
! --- exists in the water column
!
! --- limit float depth to fldepm if no water lighter than the specified
! --- density exists in the water column
!
! --- find smallest k where float density is exceeded by the density in
! --- layer k at at least one of the good 16 surrounding grid points
            thflt=flt(nfl,7)-thbase
            ngrid=1
            ngoodi=ngood(ngrid)
            do k=1,kk
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  maskpi(i1,j1)=maskpt(i1,j1,ngrid)
                  if (.not.maskpi(i1,j1)) then
                    if (th3d(i,j,k,n).gt.thflt) then
                      kflt=k
                      go to 33
                    endif
                  endif
                enddo
              enddo
            enddo
   33       continue
!
! --- move downward from layer kflt to find the two layers with densities
! --- bracketing the assigned float density
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                if (.not.maskpi(i1,j1)) then
                  if (kflt.eq.1) then
                    phi=0.
                    plo=.5*dp(i,j,kflt,n)/onem
                    thflt=flt(nfl,7)-thbase
                    if(thflt.le.th3d(i,j,kflt,n)) then
                      varb2d(i1,j1)=max(fldepm,plo)
                      go to 50
                    endif
                  endif
                  do k=max(2,kflt),kk
                    phi=p(i,j,k-1)/onem
                    plo=p(i,j,k  )/onem
                    thhi=th3d(i,j,k-1,n)
                    thlo=th3d(i,j,k  ,n)
                    if(thflt.gt.thhi .and. thflt.le.thlo) then
                      qisop=max(0.0,min(1.0,(thlo-thflt)/ &
                            max(epsil,thlo-thhi)))
                      varb2d(i1,j1)=max(fldepm,qisop*phi+(1.-qisop)*plo)
                      if (depths(i,j)-varb2d(i1,j1).lt.0.1) then
                        maskpi(i1,j1)=.true.
                        ngoodi=ngoodi-1
                      endif
                      go to 50
                    endif
                  enddo
 50               continue
                endif
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        flt(nfl,1),flt(nfl,2),maskpi, &
                        ngoodi,ngrid,intpfl,radian,depiso,ier)
            flt(nfl,3)=max(fldepm,depiso)
            if     (nfl.eq.nfl_debug) then
              write(lp,110) nfl,flt(nfl,3)
 110          format('nfl,new isopycnic depth',i6,1p,e13.5)
            endif !nfl_debug
!
          elseif (ifltyp(nfl).eq.4) then
!
            wflt=wflt4/deltfl
!
          endif
!
! --------------------------------------------------------------
! --- interpolate water properties to the present float location
! --------------------------------------------------------------
!
          if (ioflag.eq.1 .and. samplfl) then          
!
! --- recalculate q. assume float does not leave the layer that it was
! --- originally diagnosed to be within.
!
            q=max(0.0,min(1.0,(plo-flt(nfl,3))/max(0.001,plo-phi)))
!
! ---   water depth interpolation
            if (ifltyp(nfl).ne.4 .or. flt(nfl,4).eq.0.0) then
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=depths(i,j)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          16,ngrid,intpfl,radian,depflt,ier)
              flt(nfl,4)=depflt
            endif
!
! --- temperature interpolation
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                if (ifltyp(nfl).eq.4) then
                  k1=max(1 ,k-1)
                  k2=min(kk,k+1)
                  varb2d(i1,j1)= &
                      0.5*(     q *(temp(i,j,k1,n)+temp(i,j,k,n))+ &
                           (1.0-q)*(temp(i,j,k2,n)+temp(i,j,k,n)))
                else
                  varb2d(i1,j1)=temp(i,j,k,n)
                endif
              enddo
            enddo
           call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                       flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                       ngood(ngrid),ngrid,intpfl,radian,tflt,ier)
            flt(nfl,5)=tflt
!
! --- salinity interpolation
            ngrid=1
            do i1=1,4
              i=i1+ifltll(ngrid)-2
              do j1=1,4
                j=j1+jfltll(ngrid)-2
                if (ifltyp(nfl).eq.4) then
                  k1=max(1 ,k-1)
                  k2=min(kk,k+1)
                  varb2d(i1,j1)= &
                      0.5*(     q *(saln(i,j,k1,n)+saln(i,j,k,n))+ &
                           (1.0-q)*(saln(i,j,k2,n)+saln(i,j,k,n)))
                else
                  varb2d(i1,j1)=saln(i,j,k,n)
                endif
              enddo
            enddo
            call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                        flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                        ngood(ngrid),ngrid,intpfl,radian,sflt,ier)
            flt(nfl,6)=sflt
!
! --- calculate density
            if (ifltyp(nfl).ne.2) then
              thflt=sig(tflt,sflt)
              flt(nfl,7)=thflt
            else
              tflt=tofsig(flt(nfl,7),sflt)
              flt(nfl,5)=tflt
            endif
!
! --- interpolate model fields for float type 4 (stationary)
            if (ifltyp(nfl).eq.4) then
!
! --- 3-d u and v interpolation
              ngrid=2
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  k1=max(1 ,k-1)
                  k2=min(kk,k+1)
                  
#if defined(STOKES)
                  varb2d(i1,j1)=ubavg(i,j,n)+ &
                      0.5*(     q *(u(i,j,k1,n)+u(i,j,k,n)+ &
                                  usd(i,j,k1)+usd(i,j,k))+ &
                           (1.0-q)*(u(i,j,k2,n)+u(i,j,k,n)+ &
                                  usd(i,j,k2)+usd(i,j,k)))
#else                 
                  varb2d(i1,j1)=ubavg(i,j,n)+ &
                      0.5*(     q *(u(i,j,k1,n)+u(i,j,k,n))+ &
                           (1.0-q)*(u(i,j,k2,n)+u(i,j,k,n)))
#endif                
                  
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,uflt,ier)
!
              ngrid=3
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  k1=max(1 ,k-1)
                  k2=min(kk,k+1)
                  
#if defined(STOKES)
                  varb2d(i1,j1)=vbavg(i,j,n)+ &
                      0.5*(     q *(v(i,j,k1,n)+v(i,j,k,n)+ &
                                  vsd(i,j,k1)+vsd(i,j,k))+ &
                           (1.0-q)*(v(i,j,k2,n)+v(i,j,k,n)+ &
                                  vsd(i,j,k2)+vsd(i,j,k)))
#else                 
                  varb2d(i1,j1)=vbavg(i,j,n)+ &
                      0.5*(     q *(v(i,j,k1,n)+v(i,j,k,n))+ &
                           (1.0-q)*(v(i,j,k2,n)+v(i,j,k,n)))
#endif                  
                  
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,vflt,ier)
!
! --- wveli interpolation 
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=q*wveli(i,j,k)+(1.0-q)*wveli(i,j,k+1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,wflt1,ier)
              flt(nfl,10)=wflt1/deltfl
!
! --- vertical viscosity coefficient interpolation
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=q*vcty(i,j,k)+(1.0-q)*vcty(i,j,k+1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,vkflt,ier)
              flt(nfl,11)=max(1.0e-4,vkflt)
!
! --- vertical temperature diffusivity coefficient interpolation
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=q*dift(i,j,k)+(1.0-q)*dift(i,j,k+1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,tkflt,ier)
              flt(nfl,12)=max(1.0e-5,tkflt)
!
! --- vertical scalar diffusivity coefficient interpolation
              ngrid=1
              do i1=1,4
                i=i1+ifltll(ngrid)-2
                do j1=1,4
                  j=j1+jfltll(ngrid)-2
                  varb2d(i1,j1)=q*difs(i,j,k)+(1.0-q)*difs(i,j,k+1)
                enddo
              enddo
              call intrph(varb2d,ptlon(1,1,ngrid),ptlat(1,1,ngrid), &
                          flt(nfl,1),flt(nfl,2),maskpt(1,1,ngrid), &
                          ngood(ngrid),ngrid,intpfl,radian,skflt,ier)
              flt(nfl,13)=max(1.0e-5,skflt)
!
            endif                        ! float type 4
!
            if     (nfl.eq.nfl_debug) then
              write(lp,111) nfl,tflt,sflt,thflt
 111          format('new t,s,th, float',i5,2x,3f9.3)
            endif !nfl_debug
!
          endif                          ! ioflag.eq.1
!
! ----------------------------------------------------
! --- flag floats that have run aground or left domain
! ----------------------------------------------------
!
! --- jump ahead if the float has not reached its termination time
          if (ntermn.gt.-10) go to 20
!
! --- the following code block is entered when the previous code has
! --- detected that the float needs to be terminated
 30       flt(nfl,1)=-999.
          flt(nfl,2)=-999.
          if (ntermn.gt.0) then
            write(lp,112) nfl,nstep,nstepfl,ier,ntermn,ngood
 112        format('float',i6,' aground, time step',i9, &
                   ' float time step',i9/'   ier ',i3,' exit point', &
                    i3,' ngood 1-4',4i3)
          elseif (ntermn.eq.-5) then
            write(lp,113) nfl
 113        format('float',i6,' exits domain')
          elseif (ntermn.eq.-10) then
            write(lp,114) nfl
 114        format('float',i6,' reaches termination time')
          endif
!
 20       continue
!
! ----------------------------------------------------
! --- store velocity components for synthetic moorings
! ----------------------------------------------------
!
          if (ifltyp(nfl).eq.4) then
            fltloc(nfl,1)=uflt
            fltloc(nfl,2)=vflt
            fltloc(nfl,3)=wflt
          else
            fltloc(nfl,1)=0.0
            fltloc(nfl,2)=0.0
            fltloc(nfl,3)=0.0
          endif
!
!--- store updated particle location
!
          do i=1,13
            flt3(   i+17*(nfl-1)) = flt(   nfl,i)
          enddo
          do i=1,3
            flt3(13+i+17*(nfl-1)) = fltloc(nfl,i)
          enddo
          flt3(17+17*(nfl-1)) = kfloat(nfl)
!
! --- else du premier if de la boucle
        else  !float is not on this tile, so disable flt3
          do i=1,17
            flt3(i+17*(nfl-1)) = hugel
          enddo
        endif
!
        go to 222
!
 22     continue
!
! ---   float is unchanged
        do i=1,17
          flt3(i+17*(nfl-1)) = hugel
        enddo
!
 222    continue
!
! ---------------------
! --- end of float loop
! ---------------------
!
      enddo !nfl
!
! --- copy floats back to 1st processor
      call xcminr(flt3(1:17*nflt), 1)
      if (mnproc.eq.1) then
        do nfl=1,nflt
          if     (flt3(1+17*(nfl-1)).ne.hugel) then
            do i=1,13
              flt(   nfl,i) = flt3(   i+17*(nfl-1))
            enddo
            do i=1,3
              fltloc(nfl,i) = flt3(13+i+17*(nfl-1))
            enddo
            kfloat(nfl) = flt3(17+17*(nfl-1))
         endif !updated float
        enddo !nfl
      endif !1st tile
!
! -----------------------------------
! --- output float array for analysis
! -----------------------------------
!
      if (ioflag.eq.1 .and. mnproc.eq.1) then
!
        write(lp,*) 'storing float parameters'
        open(unit=uoff+801,file=flnmflto,status='unknown', &
             form='formatted',position='append')
        do nfl=1,nflt
          if (       flt(nfl,1).gt.-999. .and. &
              timefl-flt(nfl,8).ge.-0.001     ) then
!
            if (samplfl) then
              if (ifltyp(nfl).ne.4) then
                write(uoff+801,901) iflnum(nfl),timefl,kfloat(nfl), &
                                   (flt(nfl,j),j=1,7)
 901            format(i6,f12.4,i3,2f10.4,f14.4,f8.2,3f7.3)
              else
                write(uoff+801,902) iflnum(nfl),timefl,kfloat(nfl), &
                                    fltloc(nfl,1),fltloc(nfl,2), &
                                    fltloc(nfl,3),flt(nfl,10), &
                                   (flt(nfl,j),j=4,7), &
                                   (flt(nfl,j),j=11,13)
 902            format(i6,f12.4,i3,2f10.6,2f14.10,f8.2,3f7.3,1p,3e12.4)
              endif
            else
              if (ifltyp(nfl).ne.4) then
                write(uoff+801,901) iflnum(nfl),timefl,kfloat(nfl), &
                                   (flt(nfl,j),j=1,3)
              else
                write(uoff+801,902) iflnum(nfl),timefl,kfloat(nfl), &
                                    fltloc(nfl,1),fltloc(nfl,2), &
                                    fltloc(nfl,3),flt(nfl,10)
              endif
            endif
          endif
        enddo
        close(uoff+801)
      endif
!
! ----------------------------------------------------
! --- store old velocities for next time interpolation
! ----------------------------------------------------
!
 10   continue
!
      if (hadvfl) then
!
        margin = 6
!
        do j=1-margin,jj+margin
          do i=1-margin,ii+margin
            if (SEA_U) then
              do k=1,kk
                uold2(i,j,k+kold2)=u(i,j,k,n)+ubavg(i,j,n)
              enddo !k
            endif !iu
            if (SEA_V) then
              do k=1,kk
                vold2(i,j,k+kold2)=v(i,j,k,n)+vbavg(i,j,n)
              enddo !k
            endif !iv
            if (SEA_P) then
              do k=1,kk
                wold2u(i,j,k+kold2)=wvelup(i,j,k)
                wold2d(i,j,k+kold2)=wveldn(i,j,k)
              enddo !k
            endif !ip
          enddo !i
        enddo !j
!
      endif
!
      return
      end subroutine floats

      subroutine intrph(varb2d,ptlon,ptlat,fllon,fllat,maskpt, &
                        ngood,ngrid,intpfl,radian,vrbint,ier)
!
! ----------------------------------------------------
! --- 2-d polynomial or nearest neighbor interpolation
! ----------------------------------------------------
!
! --- polynomial interpolation code is adapted from the parameter matrix
! --- objective analysis algorithm of mariano and brown (1994), specifically
! --- the code used to calculate the large scale 2-d trend surface
!
! --- nptmin is presently set to 9
!
      implicit none
      real, dimension(4,4)   ::  varb2d,ptlon,ptlat
      real fllon,fllat,fllon2,fllat2,vfbint
      real wghtx,wghty,vrbint,suma,wghts,xcen,ycen,xo,yo,xsd,ysd,var
      real dx,dy,dxflt,dyflt,det,denom,radian
      real, dimension(16)    :: at,xt,yt
      real, dimension(12)    :: parm
      real, dimension(10,10) :: rtr,rtri
      real, dimension(10)    :: rta
      integer iarea(200)
      integer ngood,ngrid,intpfl,ier,iflag,ict,nptmin
      integer i,j,nd,nds,np,na
      logical maskpt(4,4)
!
! --- nptmin is the minimum number of points required for 2-d interpolation
! --- to be performed - otherwise, nearest neighbor interpolation is used
!
      data nptmin /9/
!
! --- na is the row dimension of rtr
      data na /10/
!
! --- set the 1-d arrays of field values and horizontal position
! --- find and remove central latitude and longitude of the good points
! --- correct horizontal position for earth's curvature to lowest order
!
      ict=0
      xcen=0.0
      ycen=0.0
      do i=1,4
        do j=1,4
          if (.not.maskpt(i,j) .or. ngood.eq.16) then
            ict=ict+1
            at(ict)=varb2d(i,j)
            xt(ict)=ptlon(i,j)
            xcen=xcen+xt(ict)
            yt(ict)=ptlat(i,j)
            ycen=ycen+yt(ict)
          endif
        enddo
      enddo
!
      np=ict
!
      if(np.le.0) then
        vrbint=0.0
        ier=999
        return
      endif
!
! --- set interpolated value to zero if all input values are zero
      iflag=0
      do ict=1,np
        if(at(ict).ne.0.) iflag=1
      enddo
      if(iflag.eq.0) then
        vrbint=0.0
        return
      endif
!
      xcen=xcen/np
      ycen=ycen/np
      denom=cos(ycen*radian)
!
      do ict=1,np
        xt(ict)=(xt(ict)-xcen)*cos(yt(ict)*radian)/denom
        yt(ict)=(yt(ict)-ycen)*cos(0.5*(yt(ict)+ycen)*radian)/denom
!
!diag   write(6,101) ngrid,ngood,ict,at(ict),xt(ict),yt(ict)
 101    format('poly. - ngrid,ngood,ict,at,xt,yt:' &
             /10x,3i4,1p,3e13.5)
!
      enddo
!
      fllon2=(fllon-xcen)*cos(fllat*radian)/denom
      fllat2=(fllat-ycen)*cos(0.5*(fllat+ycen)*radian)/denom
!
! --- perform the interpolation
!
      ier=0
!
      if (intpfl.eq.0 .and. ngood.ge.nptmin) then
!
! --- 2-d, second order polynomial interpolation
!
! --- set parameters for quadratic polynomial and zero the parm array
        nds=2
        nd=6
        do i=1,12
          parm(i)=0.0
        enddo
!
! --- calculate xo, the mean of xt, and yo, the mean of yt and their
! --- standard deviations from np observations 
!
        call f_stat(xt,np,xo,var,xsd)
        call f_stat(yt,np,yo,var,ysd)
!   
        do i=1,nd
          rta(i)=0.0
          do j=1,nd
            rtr(i,j)=0.0
          enddo
        enddo
!
! --- the next part of the code is a little messy, but we save alot of
! --- disk space by doing it this way
!
        do 20 ict=1,np
          dx=xt(ict)-xo
          dy=yt(ict)-yo
          rtr(1,2)=rtr(1,2) + dx
          rtr(1,3)=rtr(1,3) + dy
          rtr(2,2)=rtr(2,2) + dx**2
          rtr(2,3)=rtr(2,3) + dx*dy
          rtr(3,3)=rtr(3,3) + dy**2
          rta(1)=rta(1) + at(ict)
          rta(2)=rta(2) + dx*at(ict)
          rta(3)=rta(3) + dy*at(ict)
          if(nds.eq.1) go to 20
          rtr(2,4)=rtr(2,4) + (dx**3)/2.
          rtr(3,5)=rtr(3,5) + (dy**3)/2.
          rtr(4,4)=rtr(4,4) + (dx**4)/4.
          rtr(5,5)=rtr(5,5) + (dy**4)/4.
          rtr(3,4)=rtr(3,4) + (dx**2)*dy/2.
          rtr(2,5)=rtr(2,5) + (dy**2)*dx/2.
          rtr(4,6)=rtr(4,6) + (dx**3)*dy/2.
          rtr(5,6)=rtr(5,6) + (dy**3)*dx/2.
          rtr(6,6)=rtr(6,6) + (dx**2)*(dy**2)
          rta(4)=rta(4) + (dx**2)*at(ict)/2.
          rta(5)=rta(5) + (dy**2)*at(ict)/2.
          rta(6)=rta(6) + dx*dy*at(ict)
          if(nds.ne.3) go to 20
          rtr(4,7)=rtr(4,7) + (dx**5)/12.
          rtr(4,8)=rtr(4,8) + (dx**2)*(dy**3)/12.
          rtr(4,9)=rtr(4,9) + (dx**4)*dy/4.
          rtr(4,10)=rtr(4,10) + (dx**3)*(dy**2)/4.
          rtr(5,8)=rtr(5,8) + (dy**5)/12.
          rtr(5,10)=rtr(5,10) + dx*(dy**4)/4.
          rtr(6,7)=rtr(6,7) + dy*(dx**4)/6.
          rtr(7,7)=rtr(7,7) + (dx**6)/36.
          rtr(7,8)=rtr(7,8) + (dx**3)*(dy**3)/36.
          rtr(7,9)=rtr(7,9) + (dx**5)*dy/12.
          rtr(7,10)=rtr(7,10) + (dx**4)*(dy**2)/12.
          rtr(8,8)=rtr(8,8) + (dy**6)/36.
          rtr(8,9)=rtr(8,9) + (dx**2)*(dy**4)/12.
          rtr(8,10)=rtr(8,10) + dx*(dy**5)/12.
          rta(7)=rta(7) + (dx**3)*at(ict)/6.
          rta(8)=rta(8) + (dy**3)*at(ict)/6.
          rta(9)=rta(9) + (dx**2)*dy*at(ict)/2.
          rta(10)=rta(10) + (dy**2)*dx*at(ict)/2.
 20     continue
        rtr(1,1)=real(np)
        rtr(2,1)=rtr(1,2)
        rtr(3,2)=rtr(2,3)
        rtr(3,1)=rtr(1,3)
        if(nds.eq.1) go to 21
        rtr(1,4)=rtr(2,2)/2.
        rtr(1,5)=rtr(3,3)/2.
        rtr(1,6)=rtr(2,3)
        rtr(2,6)=rtr(3,4)*2.
        rtr(3,6)=rtr(2,5)*2.
        rtr(4,5)=rtr(6,6)/4.
        rtr(4,1)=rtr(1,4)
        rtr(4,2)=rtr(2,4)
        rtr(4,3)=rtr(3,4)
        rtr(5,1)=rtr(1,5)
        rtr(5,2)=rtr(2,5)
        rtr(5,3)=rtr(3,5)
        rtr(5,4)=rtr(4,5)
        rtr(6,1)=rtr(1,6)
        rtr(6,2)=rtr(2,6)
        rtr(6,3)=rtr(3,6)
        rtr(6,4)=rtr(4,6)
        rtr(6,5)=rtr(5,6)
        if(nds.ne.3) go to 21
        rtr(1,7)=rtr(2,4)/3.
        rtr(1,8)=rtr(3,5)/3.
        rtr(1,9)=rtr(2,6)/2.
        rtr(1,10)=rtr(2,5)
        rtr(2,7)=2.*rtr(4,4)/3.
        rtr(2,8)=rtr(5,6)/3.
        rtr(2,9)=rtr(4,6)
        rtr(2,10)=2.*rtr(4,5)
        rtr(3,7)=rtr(4,6)/3.
        rtr(3,8)=2.*rtr(5,5)/3.
        rtr(3,9)=2.*rtr(4,5)
        rtr(3,10)=3.*rtr(2,8)
        rtr(5,7)=rtr(4,10)/3.
        rtr(5,9)=rtr(4,8)/3.
        rtr(6,8)=2.*rtr(5,10)/3.
        rtr(6,9)=2.*rtr(4,10)
        rtr(6,10)=2.*rtr(5,9)
        rtr(7,1)=rtr(1,7)
        rtr(7,2)=rtr(2,7)
        rtr(7,3)=rtr(3,7)
        rtr(7,4)=rtr(4,7)
        rtr(7,5)=rtr(5,7)
        rtr(7,6)=rtr(6,7)
        rtr(8,1)=rtr(1,8)
        rtr(8,2)=rtr(2,8)
        rtr(8,3)=rtr(3,8)
        rtr(8,4)=rtr(4,8)
        rtr(8,5)=rtr(5,8)
        rtr(8,6)=rtr(6,8)
        rtr(8,7)=rtr(7,8)
        rtr(9,1)=rtr(1,9)
        rtr(9,2)=rtr(2,9)
        rtr(9,3)=rtr(3,9)
        rtr(9,4)=rtr(4,9)
        rtr(9,5)=rtr(5,9)
        rtr(9,6)=rtr(6,9)
        rtr(9,7)=rtr(7,9)
        rtr(9,8)=rtr(8,9)
        rtr(9,9)=3.*rtr(7,10)
        rtr(9,10)=9.*rtr(7,8)
        rtr(10,1)=rtr(1,10)
        rtr(10,2)=rtr(2,10)
        rtr(10,3)=rtr(3,10)
        rtr(10,4)=rtr(4,10)
        rtr(10,5)=rtr(5,10)
        rtr(10,6)=rtr(6,10)
        rtr(10,7)=rtr(7,10)
        rtr(10,8)=rtr(8,10)
        rtr(10,9)=rtr(9,10)
        rtr(10,10)=3.*rtr(8,9)
 21     continue
! 
! --- invert rtr and store in rtri, na is the row dimension of rtr
! --- and rtri, det is the determinant, nd is the number of coeff.
! --- to be estimated, i.e. the number of independent variables in
! --- rtr, iarea is a work area and ier is an error code. if ier
! --- is greater than 0, there is an inversion error
!
        call f_invmtx(rtr,na,rtri,na,nd,det,iarea,ier)
        if(ier.gt.0) print *, 'WARNING: INVERSION ERROR, ier= ',ier
!
! --- calculate the regression coeff. - parm
!
        do i=1,nd
          do j=1,nd
            parm(i)=parm(i) + rtri(i,j)*rta(j)
          enddo
        enddo
!
        parm(11)=xo
        parm(12)=yo
 85     continue
!
! --- interpolate the field to the float location
        dxflt=fllon2-parm(11)
        dyflt=fllat2-parm(12)
        vrbint=parm(1)+parm(2)*dxflt+parm(3)*dyflt &
              +parm(4)*(dxflt**2)/2.+parm(5)*(dyflt**2)/2.+ &
               parm(6)*dxflt*dyflt
        return
!
      else
!
! --- 2-d nearest neighbor interpolation if the number of available water
! --- points is smaller than nptmin. variable xt is inverse distance
!
        wghts=0.
        do ict=1,np
          xt(ict)=1.0/sqrt(max(1.0e-20,(xt(ict)-fllon2)**2+ &
                                       (yt(ict)-fllat2)**2))
          wghts=wghts+xt(ict)
!diag     write(6,102) ngrid,ngood,i,j,ict,at(ict),xt(ict)
 102      format('nearest neighbor - ngrid,ngood,i,j,ict,at,xt:' &
                 /10x,5i4,1p,2e13.5)
        enddo
!
        suma=0.
        do ict=1,np
          suma=suma+at(ict)*xt(ict)
        enddo
        vrbint=suma/wghts
        return
      endif
!
      end subroutine intrph
!
!
      SUBROUTINE F_INVMTX (A,NA,V,NV,N,D,IP,IER)
      implicit none
!
! --- this matrix inversion code is used in the parameter matrix
! --- objective analysis algorithm of mariano and brown (1994), specifically
! --- in the code used to calculate the large scale 2-d trend surface
!
      INTEGER NA,NV,N,IP(2*N),IER
      REAL D
      REAL, DIMENSION(NA,N) ::  A
      REAL, DIMENSION(NV,N) ::  V
!     DATA IEXMAX/75/
      integer, parameter :: iexmax=75
      integer j,m,i,iex, k, l, npm
      real    vmax,ch, pvt,pvtmx, hold, vh
  115 FORMAT(28H0*MATRIX SINGULAR IN INVMTX*)
  116 FORMAT(34H0*DETERMINANT TOO LARGE IN INVMTX*)
      IER = IERINV_F(N,NA,NV)
      IF (IER .NE. 0) RETURN
      DO 102 J=1,N
         IP(J) = 0
         DO 101 I=1,N
            V(I,J) = A(I,J)
  101    CONTINUE
  102 CONTINUE
      D = 1.
      IEX = 0
      DO 110 M=1,N
         VMAX = 0.
         DO 104 J=1,N
            IF (IP(J) .NE. 0) GO TO 104
            DO 103 I=1,N
               IF (IP(I) .NE. 0) GO TO 103
               VH =ABS(V(I,J))
               IF (VMAX .GT. VH) GO TO 103
               VMAX = VH
               K = I
               L = J
  103       CONTINUE
  104    CONTINUE
         IP(L) = K
         NPM = N+M
         IP(NPM) = L
         D = D*V(K,L)
  105    IF (ABS(D) .LE. 1.0) GO TO 106
         D = D*0.1
         IEX = IEX+1
         GO TO 105
  106    CONTINUE
         PVT = V(K,L)
         IF (M .EQ. 1) PVTMX = ABS(PVT)
         IF (ABS(PVT/REAL(M))+PVTMX .EQ. PVTMX) GO TO 113
         V(K,L) = 1.
         DO 107 J=1,N
            HOLD = V(K,J)
            V(K,J) = V(L,J)
            V(L,J) = HOLD/PVT
  107    CONTINUE
         DO 109 I=1,N
            IF (I .EQ. L) GO TO 109
            HOLD = V(I,L)
            V(I,L) = 0.
            DO 108 J=1,N
               V(I,J) = V(I,J)-V(L,J)*HOLD
  108       CONTINUE
  109    CONTINUE
  110 CONTINUE
      M = N+N+1
      DO 112 J=1,N
         M = M-1
         L = IP(M)
         K = IP(L)
         IF (K .EQ. L) GO TO 112
         D = -D
         DO 111 I=1,N
            HOLD = V(I,L)
            V(I,L) = V(I,K)
            V(I,K) = HOLD
  111    CONTINUE
  112 CONTINUE
      IF (IEX .GT. IEXMAX) GO TO 114
      D = D*10.**IEX
      RETURN
  113 IER = 33
!      PRINT 115
      RETURN
  114 IER = 1
      D = REAL(IEX)
      PRINT 116
      RETURN
      END SUBROUTINE F_INVMTX
!
      INTEGER FUNCTION IERINV_F (N,NA,NV)
      implicit none
      INTEGER N, NA, NV
  103 FORMAT(23H0* N .LT. 1 IN INVMTX *)
  104 FORMAT(24H0* NA .LT. N IN INVMTX *)
  105 FORMAT(24H0* NV .LT. N IN INVMTX *)
      IERINV_F = 0
      IF (N .GE. 1) GO TO 101
      IERINV_F = 34
      PRINT 103
      RETURN
  101 IF (NA .GE. N) GO TO 102
      IERINV_F = 35
      PRINT 104
      RETURN
  102 IF (NV .GE. N) RETURN
      IERINV_F = 36
      PRINT 105
      RETURN
      END FUNCTION IERINV_F

      subroutine f_stat(ser,ls,amean,var,std)
      implicit none
!
! --- computes mean, variance, standard deviation of data sequence
      real, dimension(16) :: ser
      integer ls
      real amean,var,std
      real sum,value
      integer j
      sum=0.0
      do j=1,ls
        sum=sum+ser(j)
      enddo
      amean=sum/ls
      sum=0.0
      do j=1,ls
        value=ser(j)-amean
        sum=sum+value*value
      enddo
      var=sum/ls
      std=sqrt(var)
!
      return
      end subroutine f_stat
!
!
! --- following are subprograms provided by Geoff Samuels, and inserted
! --- by Nasseer Idrisi (10/5/01)

      subroutine rantab_ini(rtab,iseed1,iseed2,iflag)
      implicit none
!
      real*4     rtab(200,2)
      integer*4  iseed1,iseed2
      integer*4  iflag
      integer    ic, inisee, itime
!
! --- get the two seeds
! --- iseed1 is for the 'usual'    random number generator  (udev_rt)
! --- iseed2 is for the 'gaussian' random number generator (grand_rt)
!
      integer*4 seed
      integer*2 isd2(2)
#if defined(NAGFOR)
!
! --- NAG Fortran - this routine won't work without the equivalence
!*****equivalence (isd2,seed)
!
      call system_clock(inisee)
!
      if     (inisee.ne.-999) then  !always .true.
        call xcstop('(rantab_ini-NAG Fortran)')
               stop '(rantab_ini-NAG Fortran)'
      endif !.true.
#else
      equivalence (isd2,seed)
!
      call system_clock(inisee)
#endif
!
!diag write(*,*)'calc itime',time()
      itime = inisee
      seed = 123456789
      iseed1 = isd2(1)
      if (iseed1 .lt. 0) then
        iseed1 = abs(iseed1)
      endif
      iseed1 = iseed1 + itime*iflag
!diag write(*,*)'iseed1',iseed1
      seed = 987654321
      iseed2 = isd2(2)
      if (iseed2 .lt. 0) then
        iseed2 = abs(iseed1)
      endif
      iseed2 = iseed2 + itime*iflag
!diag write(*,*)'iseed2',iseed2
!
! --- set seeds to negative values if iflag=1
!
      if (iflag .eq. 1) then
        iseed1 = -iseed1
        iseed2 = -iseed2
      endif
!
! --- load the table with a sequence of 200 random numbers.
      do  ic = 1,200
        rtab(ic,1) =  udev_rt(iseed1)
        rtab(ic,2) = grand_rt(iseed2)
      enddo
!diag write(*,*)'rtabs',rtab(100,1),rtab(100,2)
!
      return
      end subroutine rantab_ini

      subroutine rantab (rtab,iseed1,iseed2,numran)
!
! --- each time this routine is called one of the 200 records in "rtab"
! --- is randomly selected and new random numbers are inserted
!
      real*4     rtab(200,2)
      integer*4  iseed1,iseed2,numran
!
! --- pick a number between 1 and 200
      numran = nint(1+199*udev_rt(iseed1))
      if (numran .gt. 200) then
        numran = 200
      endif
!
! --- get new random numbers
      rtab(numran,1) =  udev_rt(iseed1)
      rtab(numran,2) = grand_rt(iseed2)
!
      return
      end subroutine rantab
!
      real function grand_rt(idum)
      implicit none
!
! provides random number from gaussian distribution, mean 0, varaince 1,
! for finding random component of turbulent u
!
! from arthur mariano using routines from numerical recipes
!
      integer*4  idum
      integer*4  iset
      real*4     gset,v1,v2,r,fac
!      data iset/0/
!      save iset,gset
! 
      iset = 0
      gset=0.0
      if (iset.eq.0) then
 1      v1=2.*udev_rt(idum)-1.0
        v2=2.*udev_rt(idum)-1.0
        r=v1**2+v2**2
        if (r.ge.1.0)go to 1
        fac=sqrt(-2.*log(r)/r)
        gset=v1*fac
        grand_rt=v2*fac
        iset=1
      else
        grand_rt=gset
        iset=0
      endif
!
      return
      end function grand_rt
!
      real function udev_rt(iseed)
      
      integer*4  iseed
      integer, parameter :: m=714025,ia=1366,ic=150889
      real  rm
      integer, dimension(97) :: ir
      integer iy, iff,j
!
      iff = 0
      rm = 1./m
      if (iseed .lt. 0 .or. iff .eq. 0) then
        iff = 1
        iseed = mod(ic-iseed,m)
        do j=1,97
          iseed = mod(ia*iseed+ic,m)
          ir(j) = iseed
        enddo
        iseed = mod(ia*iseed+ic,m)
      else
        iseed = mod(iseed,m)
      endif
      iy=iseed
      j = min(97,1+(97*iy)/m)
      iy = ir(j)
      udev_rt = iy*rm
      iseed = mod(ia*iseed+ic,m)
      ir(j) = iseed
      return
      end function udev_rt
      end module mod_floats
!
!
!> Revision history:
!>
!> Nov  2006 - 1st module version
!> Nov  2012 - implicit none added by Till Andreas Rasmussen
!> May  2014 - use land/sea masks (e.g. ip) to skip land
!> Aug  2017 - Added macro to allow NAG Fortran to compile