C $Header: /u/gcmpack/MITgcm/pkg/flt/flt_up.F,v 1.13 2012/03/30 18:25:03 jmc Exp $
C $Name:  $

#include "FLT_OPTIONS.h"

CBOP 0
C !ROUTINE: FLT_UP

C !INTERFACE:
      SUBROUTINE FLT_UP (
     I                    myTime, myIter, myThid )

C     !DESCRIPTION:
C     *==========================================================*
C     | SUBROUTINE FLT_UP
C     | o This routine moves particles vertical from the target
C     |   depth to the surface and samples the model state over
C     |   the full water column at horizontal float position
C     |   every flt_int_prof time steps and writes output.
C     *==========================================================*

C     !USES:
      IMPLICIT NONE
C     == global variables ==
#include "SIZE.h"
#include "EEPARAMS.h"
#include "PARAMS.h"
#include "DYNVARS.h"
#include "FLT_SIZE.h"
#include "FLT.h"
#include "FLT_BUFF.h"

C     !INPUT PARAMETERS:
C     myTime :: current time in simulation
C     myIter :: current iteration number
C     myThid :: my Thread Id number
      _RL myTime
      INTEGER myIter, myThid

C     !FUNCTIONS:
      _RL FLT_MAP_K2R
      EXTERNAL 

C     !LOCAL VARIABLES:
      INTEGER bi, bj, nFlds
      INTEGER ip, k, ii
      INTEGER imax
      PARAMETER (imax=(9+4*Nr))
      _RL tmp(imax)
      _RL ix, jy, i0x, j0y, xx, yy, zz
      _RL uu,vv,tt,ss, pp
      _RL npart_read, npart_times
      _RS dummyRS(1)
      INTEGER fp, ioUnit, irecord
      CHARACTER*(MAX_LEN_FNAM) fn
      CHARACTER*(MAX_LEN_MBUF) msgBuf
CEOP

C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|

C--   set number of fields to write
      nFlds = 0
      IF ( flt_selectProfOutp.GE.1 ) nFlds = nFlds + 8
      IF ( flt_selectProfOutp.GE.2 ) nFlds = nFlds + 1 + 4*Nr

C--   check buffer size
      IF ( nFlds.GT.fltBufDim ) THEN
         _BEGIN_MASTER(myThid)
         WRITE(msgBuf,'(3(A,I4))') ' FLT_UP: fltBufDim=', fltBufDim,
     &                             ' too small (<', nFlds, ' )'
         CALL PRINT_ERROR( msgBuf, myThid )
         WRITE(msgBuf,'(2A)')     ' FLT_UP: => increase fltBufDim',
     &                            ' in "FLT_SIZE.h" & recompile'
         CALL PRINT_ERROR( msgBuf, myThid )
         _END_MASTER(myThid)
         CALL ALL_PROC_DIE( myThid )
         STOP 'ABNORMAL END: S/R FLT_UP'
      ENDIF

      IF ( myIter.EQ.nIter0 ) RETURN

C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|
C--   Calculate position + other fields at float position and fill up IO-buffer

      DO bj=myByLo(myThid),myByHi(myThid)
       DO bi=myBxLo(myThid),myBxHi(myThid)

         i0x = DFLOAT( myXGlobalLo-1 + (bi-1)*sNx )
         j0y = DFLOAT( myYGlobalLo-1 + (bj-1)*sNy )
         DO ip=1,npart_tile(bi,bj)

C     Move float to the surface
           IF ( myTime.GE.tstart(ip,bi,bj) .AND.
     &         (tend(ip,bi,bj).EQ.-1..OR.myTime.LE.tend(ip,bi,bj))
     &         .AND.
     &          kpart(ip,bi,bj).EQ.kfloat(ip,bi,bj) .AND.
     &          iup(ip,bi,bj).GT.0.
     &        ) THEN

             IF ( MOD(myTime,iup(ip,bi,bj)).EQ.0.)
     &       kpart(ip,bi,bj) = flt_surf

           ENDIF

C     If float has died move to level 0
           IF ( tend(ip,bi,bj).NE.-1..AND.myTime.GT.tend(ip,bi,bj)
     &        ) THEN
             kpart(ip,bi,bj) = 0.
           ENDIF

           IF ( flt_selectProfOutp.GE.1 ) THEN
C     Convert to coordinates
             ix = ipart(ip,bi,bj)
             jy = jpart(ip,bi,bj)
             CALL FLT_MAP_IJLOCAL2XY( xx, yy,
     I                                ix, jy, bi,bj, myThid )
             zz = FLT_MAP_K2R( kpart(ip,bi,bj),bi,bj,myThid )

             tmp(1) = npart(ip,bi,bj)
             tmp(2) = myTime
             tmp(3) = xx
             tmp(4) = yy
             tmp(5) = zz
             tmp(6) = ix + i0x
             tmp(7) = jy + j0y
             tmp(8) = kpart(ip,bi,bj)
           ENDIF

           IF ( ( flt_selectProfOutp.GE.2 )    .AND.
     &          ( myTime.GE.tstart(ip,bi,bj) ) .AND.
     &          ( tend(ip,bi,bj).EQ.-1..OR.myTime.LE.tend(ip,bi,bj) )
     &        ) THEN
             CALL FLT_BILINEAR2D(ix,jy,pp,etaN,0,bi,bj,myThid)
             tmp(9) = pp
             DO k=1,Nr
               CALL FLT_BILINEAR  (ix,jy,uu,uVel,  k,1,bi,bj,myThid)
               CALL FLT_BILINEAR  (ix,jy,vv,vVel,  k,2,bi,bj,myThid)
               CALL FLT_BILINEAR  (ix,jy,tt,theta, k,0,bi,bj,myThid)
               CALL FLT_BILINEAR  (ix,jy,ss,salt,  k,0,bi,bj,myThid)
               tmp(9+k     ) = uu
               tmp(9+k+1*Nr) = vv
               tmp(9+k+2*Nr) = tt
               tmp(9+k+3*Nr) = ss
             ENDDO
           ELSEIF ( flt_selectProfOutp.GE.2 ) THEN
             DO ii=9,nFlds
               tmp(ii) = flt_nan
             ENDDO
           ENDIF

           DO ii=1,nFlds
             flt_io_buff(ii,ip,bi,bj) = tmp(ii)
           ENDDO

         ENDDO

       ENDDO
      ENDDO

      IF ( flt_selectProfOutp.LE.0 ) RETURN

C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----|

C--   Write shared buffer to file

      _BARRIER
      _BEGIN_MASTER(myThid)

      fn = 'float_profiles'
      fp = writeBinaryPrec

      DO bj=1,nSy
       DO bi=1,nSx

C (1) read actual number floats from file (if exists)
         ioUnit = -2
         CALL MDS_READVEC_LOC(  fn, fp, ioUnit, 'RL', nFlds,
     &                          tmp, dummyRS,
     &                          bi, bj, 1, myThid )
         IF ( ioUnit.GT. 0 ) THEN
            npart_read  = tmp(1)
            npart_times = tmp(5)
            ii = NINT(tmp(7))
C-       for backward compatibility with old profile files:
            IF ( ii.EQ.0 ) ii = 9+4*Nr
            IF ( ii.NE.nFlds ) THEN
              WRITE(msgBuf,'(A,I4,A)')
     &            'FLT_UP: nFlds=', nFlds,' different from'
              CALL PRINT_ERROR( msgBuf, myThid )
              WRITE(msgBuf,'(3A,I4,A)')
     &            'previous file (',fn(1:14),') value =',ii
              CALL PRINT_ERROR( msgBuf, myThid )
              CALL ALL_PROC_DIE( 0 )
              STOP 'ABNORMAL END: S/R FLT_UP'
            ENDIF
C-       close the read-unit (safer to use a different unit for writing)
            CLOSE( ioUnit )
         ELSE
            npart_read  = 0.
            npart_times = 0.
            tmp(2)      = myTime
         ENDIF

C (2) write new actual number floats and time into file
C-    the standard routine mds_writevec_loc can be used here

C     total number of records in this file
         tmp(1) = DBLE(npart_tile(bi,bj))+npart_read
C     first time of writing floats (do not change when written)
c        tmp(2) = tmp(2)
C     current time
         tmp(3) = myTime
C     timestep
         tmp(4) = flt_int_prof
C     total number of timesteps
         tmp(5) = npart_times + 1.
C     total number of floats
         tmp(6) = max_npart
C     total number of fields
         tmp(7) = nFlds
         DO ii=8,nFlds
           tmp(ii) = 0.
         ENDDO
         ioUnit = -1
         CALL MDS_WRITEVEC_LOC( fn, fp, ioUnit, 'RL', nFlds,
     &                          tmp, dummyRS,
     &                          bi, bj, -1, myIter, myThid )

         DO ip=1,npart_tile(bi,bj)
C (3) write float positions into file
           irecord = npart_read+ip+1
           IF ( ip.NE.npart_tile(bi,bj) ) irecord = -irecord
           CALL MDS_WRITEVEC_LOC( fn, fp, ioUnit, 'RL', nFlds,
     &                            flt_io_buff(1,ip,bi,bj), dummyRS,
     &                            bi, bj, irecord, myIter, myThid )
         ENDDO
         CLOSE( ioUnit )

       ENDDO
      ENDDO

      _END_MASTER(myThid)
      _BARRIER

      RETURN
      END