      subroutine tracksout
c
c=======================================================================
c                                                                    ===
c  This routine writes out current trajectory data into output       ===
c  NetCDF Lagrangian trajectory file.                                ===
c                                                                    ===
c  Calls:  NCAPT, NCAPTC, NCCRE, NCDDEF, NCENDF, NCSNC, NCVDEF,      ===
c          NCVPT, NCVPTC    (NetCDF library)                         ===
c          EXITUS, LNBLK, XY2LL                                      ===
c                                                                    ===
c  WARNING:   Character argument to NetCDF routines NCAPT, NCAPTC,   ===
c             NCDDEF, and NCVDEF is (upper/lower) case sensitive.    ===
c                                                                    ===
c  Common blocks:                                                    ===
c                                                                    ===
c     /FULLWD/                                                       ===
c                                                                    ===
c     /NETCDF/                                                       ===
c                                                                    ===
c     /PE_NETCDF/                                                    ===
c                                                                    ===
c     /TRACKS/                                                       ===
c                                                                    ===
c     TRACK    descriptor of the drifter (real array; input)         ===
c     TSTART   release time (real array; input)                      ===
c     STATUS   trajectory status (integer array; input)              ===
c     NFLOATS  number of simulated drifters (integer; input)         ===
c                                                                    ===
c     /TRACKSC/                                                      ===
c                                                                    ===
c     TYPE     pointer for drifter type: surface or density floats   ===
c              (character array; input)                              ===
c     IDENT    drifter indentifier (character array; input)          ===
c                                                                    ===
c=======================================================================
c
c-----------------------------------------------------------------------
c  Define global data.
c-----------------------------------------------------------------------
c
#include <cdefs.h>
#include <param.h>
#include <pconst.h>
#include <fullwd.h>
#include <tracks.h>
#include <netcdf.inc>
#include <pe_netcdf.h>
#include <moddat.h>
#include <runid.h>
#include <iounits.h>
#include <version.h>
c
c-----------------------------------------------------------------------
c  Define local data.
c-----------------------------------------------------------------------
c
      logical first
      integer n,sbgn,sbm,sem,send,slen,slm,trkddim,trkldim,trkpdim,
     *        trktdim,trkvdim,vartyp
      integer count(3),start(3),trk2dc(2),trk3dp(3),trk3dv(3),
     *        ttrkindx(maxfloats)
      FLOAT
     *      day,pos(3)
      character*256 dummy
      save first
      data first /.true./
c
c=======================================================================
c  Begin executable code.
c=======================================================================
c
c-----------------------------------------------------------------------
c  On first call, create drifters output NetCDF file, its dimensions,
c  and global attributes.
c-----------------------------------------------------------------------
c
      if(first) then
        first=.false.
c
c  Create NetCDF file.
c
        call length (trkname,slen,sbgn,send)
        nctrkid=nccre(trkname(sbgn:send),ncclob,rcode)
        if(rcode.eq.0) then
           nctrkst = 1
          else
           write(stdout,900) trkname(sbgn:send)
           call exitus('TRACKSOUT')
        endif
c
c  Define dimensions.
c
        trkddim=ncddef(nctrkid,'drifter',nfloats,rcode)
        trkldim=ncddef(nctrkid,'lenid',lenid,rcode)
        trkpdim=ncddef(nctrkid,'axis',3,rcode)
        trkvdim=ncddef(nctrkid,'vector',3,rcode)
        trktdim=ncddef(nctrkid,'time',ncunlim,rcode)
c
c  Define dimension vectors.
c
        trk2dc(1)=trkldim
        trk2dc(2)=trkddim
c
        trk3dp(1)=trkpdim
        trk3dp(2)=trkddim
        trk3dp(3)=trktdim
c
        trk3dv(1)=trkvdim
        trk3dv(2)=trkddim
        trk3dv(3)=trktdim
c
c  Define type of floating-point variables: single or double precision.
c
#ifdef dblprec
      vartyp=ncdouble
#else
      vartyp=ncfloat
#endif
c
c  Define global attributes.
c
      call length (model,slm,sbm,sem)
      dummy=model(sbm:sem)//' simulated Lagrangian drifters'
      call length (dummy,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'title',ncchar,slen,dummy(sbgn:send)
     *            ,rcode)
      call length (outname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'out_file',ncchar,slen,
     *            outname(sbgn:send),rcode)
      call length (nrgname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'nrg_file',ncchar,slen,
     *            nrgname(sbgn:send),rcode)
#ifdef ldrifters
      call length (trkname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'trk_file',ncchar,slen,
     *            trkname(sbgn:send),rcode)
      call length (dposnam,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'trk_parm',ncchar,slen,
     *            dposnam(sbgn:send),rcode)
#endif
#ifndef analytical
      call length (inpname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'inp_file',ncchar,slen,
     *            inpname(sbgn:send),rcode)
#endif
#ifdef forcing
      call length (frcname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'frc_file',ncchar,slen,
     *            frcname(sbgn:send),rcode)
#endif
#ifdef oias
      call length (assname,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'ass_file',ncchar,slen,
     *            assname(sbgn:send),rcode)
      call length (aparnam,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'ass_parm',ncchar,slen,
     *            aparnam(sbgn:send),rcode)
#endif
#ifdef extraction
      call length (xparnam,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'xtr_parm',ncchar,slen,
     *            xparnam(sbgn:send),rcode)
#endif
#if defined bioAnder | defined bioFasham | defined bioMcGillic | defined bioDuse
      call length (bparnam,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'bio_parm',ncchar,slen,
     *            bparnam(sbgn:send),rcode)
#endif
      dummy=model(sbm:sem)//' DRIFTERS'
      call length (dummy,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'type',ncchar,slen,dummy(sbgn:send),
     *            rcode)
      call length (vnum,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'version',ncchar,slen,
     *            vnum(sbgn:send),rcode)
      call length (history,slen,sbgn,send)
      call ncaptc(nctrkid,ncglobal,'history',ncchar,slen,
     *            history(sbgn:send),rcode)
c
c-----------------------------------------------------------------------
c  Define NetCDF variables and their attributes.
c-----------------------------------------------------------------------
c
c  Define Lagrangian drifters identifiers.
c
        trkidid=ncvdef(nctrkid,'trk_id',ncchar,2,trk2dc,rcode)
        dummy = 'Lagrangian drifter identifier'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkidid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        trktypid=ncvdef(nctrkid,'trk_type',ncchar,1,trkddim,rcode)
        dummy = 'Lagrangian drifter type'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trktypid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 's: density (Swallow float), z: surface, x: extended '//
     &          'surface'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trktypid,'options',ncchar,slen,
     *               dummy(sbgn:send),rcode)
c
c  Define density at initial drifter position.  This information is
c  relevant when simulating density-following drifters.
c
        trkdenid = ncvdef (nctrkid,'trk_den',vartyp,1,trkddim,rcode)
        dummy = 'Density at initial Lagrangian drifter position'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkdenid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'kilogram meter-3'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkdenid,'units',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trkdenid,'_FillValue',vartyp,1,spval,rcode)
c
c  Define drifter diameter.  This information is
c  relevant when simulating extended surface drifters.
c
        trkdiaid = ncvdef (nctrkid,'trk_dia',vartyp,1,trkddim,rcode)
        dummy = 'Lagrangian drifter diameter'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkdiaid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'meter'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkdiaid,'units',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trkdiaid,'_FillValue',vartyp,1,spval,rcode)
c
c  Define time coordinate.
c
        trktimid=ncvdef(nctrkid,'trk_time',vartyp,2,trk3dp(2),rcode)
        dummy = 'time'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trktimid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'modified Julian day'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trktimid,'units',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trktimid,'add_offset',vartyp,1,jul_off,
     *              rcode)
        dummy = 'time, scalar, series'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trktimid,'field',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trktimid,'_FillValue',vartyp,1,spval,rcode)
c
c  Define Lagrangian drifter positions.
c
        trkposid=ncvdef(nctrkid,'trk_pos',vartyp,3,trk3dp,rcode)
        dummy = 'Lagrangian drifter trajectory positions'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkposid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = '1: longitude, 2: latitude, 3: depth'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkposid,'axis',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'degrees_east, degress_north, meter'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkposid,'units',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'drifter positions, vector, series'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkposid,'field',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trkposid,'_FillValue',vartyp,1,spval,rcode)
c
c  Define Lagrangian drifter velocity components.
c
        trkvelid=ncvdef(nctrkid,'trk_vel',vartyp,3,trk3dv,rcode)
        dummy = 'Lagrangian drifter velocity'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkvelid,'long_name',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = '1: zonal, 2: meridional, 3: vertical'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkvelid,'vector',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'centimeter second-1'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkvelid,'units',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'drifter velocity, vector, series'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkvelid,'field',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        dummy = 'trk_pos'
        call length (dummy,slen,sbgn,send)
        call ncaptc (nctrkid,trkvelid,'positions',ncchar,slen,
     *               dummy(sbgn:send),rcode)
        call ncapt (nctrkid,trkvelid,'_FillValue',vartyp,1,spval,rcode)
c
c-----------------------------------------------------------------------
c  Leave definition mode.
c-----------------------------------------------------------------------
c
        call ncendf(nctrkid,rcode)
        if(rcode.eq.0) then
           nctrkst = 2
          else
           call length (trkname,slen,sbgn,send)
           write(stdout,910) trkname(sbgn:send)
           call exitus('TRACKSOUT')
        endif
c
c-----------------------------------------------------------------------
c  Write out Lagrangian drifter identifiers and density at initial
c  position for density drifters.
c-----------------------------------------------------------------------
c
        do 10 n=1,nfloats
          start(1)=1
          count(1)=lenid
          start(2)=n
          count(2)=1
          call ncvptc(nctrkid,trkidid,start,count,ident(n),lenid,rcode)
          if(rcode.ne.0) then
            write(stdout,920) 'trk_id',n
            call exitus('TRACKSOUT')
          endif
          start(1)=n
          count(1)=1
          call ncvptc(nctrkid,trktypid,start,count,type(n),1,rcode)
          if (rcode.ne.0) then
            write(stdout,920) 'trk_type',n
            call exitus('TRACKSOUT')
          endif
          if (type(n).eq.'s') then
            start(1)=n
            count(1)=1
            call ncvptc(nctrkid,trkdenid,start,count,track(8,n),1,rcode)
            if (rcode.ne.0) then
              write(stdout,920) 'trk_den',n
              call exitus('TRACKSOUT')
            endif
           elseif (type(n).eq.'x') then
            start(1)=n
            count(1)=1
            call ncvptc (nctrkid,trkdiaid,start,count,track(8,n)*cm2m,1,
     &                   rcode)
            if (rcode.ne.0) then
              write(stdout,920) 'trk_dia',n
              call exitus('TRACKSOUT')
            endif
          endif
  10    continue
c
c-----------------------------------------------------------------------
c  Initialize time dimension counters.
c-----------------------------------------------------------------------
c
        do 15 n = 1, nfloats
           ttrkindx(n) = 0
  15    continue
      endif
c
c=======================================================================
c  End of introductory section.
c=======================================================================
c
c-----------------------------------------------------------------------
c  Write out Lagrangian drifter data into NetCDF.
c-----------------------------------------------------------------------
c
      do 20 n=1,nfloats
        if(status(n).eq.1) then
          ttrkindx(n)=ttrkindx(n)+1
c
          start(1)=1
          count(1)=3
          start(2)=n
          count(2)=1
          start(3)=ttrkindx(n)
          count(3)=1
c
c  Write out drifter position.
c
          call xy2ll(track(1,n),track(2,n),coord,imt,jmt,gridx,gridy,
     *               rlngd,rlatd,delx,dely,thetad,pos(1),pos(2))
          pos(3)=track(3,n)
          call ncvpt(nctrkid,trkposid,start,count,pos,rcode)
          if(rcode.ne.0) then
            write(stdout,920) 'trk_pos',n,ttrkindx(n)
            call exitus('TRACKSOUT')
          endif
c
c  Write out time coordinate.
c
          day=tstart(1,n)+track(4,n)
          call ncvpt(nctrkid,trktimid,start(2),count(2),day,rcode)
          if(rcode.ne.0) then
            write(stdout,920) 'trk_time',n,ttrkindx(n)
            call exitus('TRACKSOUT')
          endif
c
c  Write drifter velocity.
c
          call ncvpt(nctrkid,trkvelid,start,count,track(5,n),rcode)
          if(rcode.ne.0) then
            write(stdout,920) 'trk_vel',n,ttrkindx(n)
            call exitus('TRACKSOUT')
          endif
        endif
  20  continue
c
c  Synchronize trajectories NetCDF file to disk to allow other processes
c  to access data immediately after it is written. Do at the same output
c  data intervals.
c
      if(wrtts) then
        call ncsnc(nctrkid,rcode)
        if(rcode.ne.0) then
          write(stdout,930)
          call exitus('TRACKSOUT')
        endif
      endif
c
 900  format(/' TRACKSOUT - unable to create drifters NetCDF file: ',a)
 910  format(/' TRACKSOUT - unable to define drifters NetCDF file: ',a)
 920  format(/' TRACKSOUT - error while writing variable: ',a,2x,
     *        ' for DRIFTER = ',i3,2x,' at time INDEX = ',i6)
 930  format(/' TRACKSOUT - unable to synchronize trajectories NetCDF',
     *        ' to disk.')
      return
      end
