PROGRAM ARPSCALCTRAJC     ,105
!
!##################################################################
!##################################################################
!######                                                      ######
!######                   PROGRAM ARPSTRAJC                  ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue 
!  (4/08/2004)
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  REAL, allocatable :: x (:),y (:),z (:)
  REAL, allocatable :: xs (:), ys (:), zs1d(:) ! x,y coord for scalar points
  REAL, allocatable :: zp(:,:,:), ptbar(:,:,:), pbar(:,:,:),qvbar(:,:,:),rhobar(:,:,:)
  REAL, allocatable :: tem1 (:,:,:), tem2(:,:,:), tem3(:,:,:), tem4(:,:,:)
  INTEGER (KIND=selected_int_kind(4)), ALLOCATABLE :: itmp(:,:,:) ! Temporary array
  INTEGER :: nx,ny,nz,nzsoil   ! Grid dimensions.
  INTEGER :: nstyps            ! Maximum number of soil types.
  INTEGER :: hinfmt,nhisfile_max,nhisfile,lengbf
  CHARACTER (LEN=256) :: grdbasfn,hisfile
  INTEGER :: hdmpinopt, nf
  CHARACTER (LEN=256) :: hdmpftrailer
  CHARACTER (LEN=256) :: hdmpfheader
  INTEGER :: ntimes
  INTEGER, PARAMETER :: nmax_times=20
  REAL :: tzero, tend, tstart_calc, tend_calc, tinc_calc, reftime(nmax_times)
  CHARACTER(LEN=256) :: trajc_fn_in(nmax_times), trajc_fn_out
  NAMELIST /input/ hdmpfheader,hdmpftrailer,tstart_calc,tend_calc,tinc_calc,reftime,trajc_fn_in,ntimes
  INTEGER :: ntrajc0,ntrajcs, npoints, npoints_in
 
  REAL, allocatable :: xtrajc(:,:,:),ytrajc(:,:,:),ztrajc(:,:,:),ttrajc(:)
  REAL, allocatable :: xtrajc1(:,:),ytrajc1(:,:),ztrajc1(:,:)
  REAL, allocatable :: utrajc(:,:),vtrajc(:,:),wtrajc(:,:)
  REAL, allocatable :: pt_trajc(:,:),p_trajc(:,:),qv_trajc(:,:),q_trajc(:,:),ptprt_trajc(:,:)
  REAL, allocatable :: xweight(:,:),yweight(:,:),zweight(:,:)
  INTEGER, allocatable :: itrajc(:,:),jtrajc(:,:),ktrajc(:,:)
  REAL, allocatable :: vortx_trajc(:,:),vorty_trajc(:,:),vortz_trajc(:,:), &
                       vorts_trajc(:,:),vortc_trajc(:,:)
  REAL, allocatable :: buoy_trajc(:,:),buoyq_trajc(:,:),frcs_trajc(:,:),pprt_trajc(:,:)
  REAL, allocatable :: upgrad_trajc(:,:),vpgrad_trajc(:,:),wpgrad_trajc(:,:)
  REAL, allocatable :: vorts_gen_trajc(:,:),vortc_gen_trajc(:,:)
  REAL, allocatable :: vortz_tilt_trajc(:,:),vortz_stch_trajc(:,:)
  INTEGER :: istatus, cur_level
  REAL :: xlow, xhigh, ylow, yhigh, zlow, zhigh, pttem
  INTEGER :: nstart, nend, npnt, ntrj, ninc
!
!-----------------------------------------------------------------------
!  Include files:
!-----------------------------------------------------------------------
!
  INCLUDE 'globcst.inc'
  INCLUDE 'grid.inc'
  INCLUDE 'phycst.inc'
  INTEGER :: i,j,k,ireturn
  REAL :: time, time1, time2, amin, amax, degree, degree2radian, theta
  LOGICAL :: iexist
  REAL :: u1_changed, utem,vtem,wtem, factor
  INTEGER :: nfile, do_diagnostics
  REAL :: ttrajc0_in
  INTEGER :: ntrajcs_in, ntrajcs_each_j
  CHARACTER (LEN=80) :: timsnd
  INTEGER :: tmstrln, nunit(nmax_times),ltrajc_fn,istat,tmstrln3
  INTEGER :: kl, counter
  REAL missing_value, pi
  INTEGER :: tmstrln0,tmstrln1,tmstrln2, idot
  CHARACTER (LEN=6) :: timsnd0,timsnd1,timsnd2
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  missing_value = -99999.0
  hinfmt = 3
  reftime = 0.0
  READ(5,input,ERR=100)
  WRITE(6,'(a)')'Namelist input was successfully read.'
  write(6,input)
  DO k=1,ntimes
  CALL getunit
 (nunit(k))
!-----------------------------------------------------------------------
! Read trajectory data 
!-----------------------------------------------------------------------
  OPEN(UNIT=nunit(k),FILE=trim(trajc_fn_in(k)),STATUS='old',   &
        FORM='formatted',IOSTAT= istat )
  READ(nunit(k),'(a)') runname
  READ(nunit(k),'(6e17.6)') xlow, xhigh, ylow, yhigh, zlow, zhigh
  write(6,'(6e17.6)') xlow, xhigh, ylow, yhigh, zlow, zhigh
  READ(nunit(k),'(3e17.6)') dx, dy, dz
  write(6,'(3e17.6)') dx, dy, dz
  READ(nunit(k),'(3e17.6)') tstart, tzero, tend
  READ(nunit(k),'(i10)') npoints
  READ(nunit(k),'(i10)') ntrajcs
  ENDDO
  allocate(xtrajc(npoints,ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:xtrajc")
  allocate(ytrajc(npoints,ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ytrajc")
  allocate(ztrajc(npoints,ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ztrajc")
  allocate(ttrajc(npoints),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ttrajc")
  allocate(xtrajc1(ntrajcs,ntimes),stat=istatus)
  allocate(ytrajc1(ntrajcs,ntimes),stat=istatus)
  allocate(ztrajc1(ntrajcs,ntimes),stat=istatus)
  DO k=1,ntimes
  DO j=1,npoints
    READ(nunit(k),'(4e17.6)',err=115,end=115) ttrajc(j)
    READ(nunit(k),'(i10)',err=115,end=115) ntrajcs_in
    IF( ntrajcs_in /= ntrajcs ) then
      print*,'ntrajcs read in .ne. ntrajcs in program.'
      print*,'Job stopped'
      STOP
    ENDIF
    READ(nunit(k),'(6e17.6)',err=115,end=115) ((xtrajc(j,i,k),ytrajc(j,i,k),ztrajc(j,i,k)),i=1,ntrajcs)
  ENDDO
  CLOSE(UNIT=nunit(k))
  CALL retunit(nunit(k))
  ENDDO
  npoints_in = npoints
  GOTO 125
115 continue
  npoints_in = max(1,j-1)
125 continue
  print*,'done reading trajectory data'
! IF( tstart_calc /= tend_calc ) then
    nstart = npoints_in
    DO j=1,npoints_in
      IF( ttrajc(j) >= tstart_calc ) then
        nstart = j
        exit
      ENDIF
    ENDDO
    nend   = 1
    DO j=npoints_in,1,-1
      IF( ttrajc(j) <= tend_calc ) then
        nend = j
        exit
      ENDIF
    ENDDO
! ELSE
!   nstart = 1
!   nend   = npoints
! ENDIF
  print*,'ttrajc(nstart),ttrajc(nend), tinc_calc=', ttrajc(nstart),ttrajc(nend), tinc_calc
  ninc = max(1, nint( tinc_calc/(ttrajc(nstart+1)-ttrajc(nstart)) ))
  print*,'tstart_calc, tend_calc, nstart, nend =', tstart_calc, tend_calc, nstart, nend
  grdbasfn = trim(hdmpfheader)//'.hdfgrdbas'//trim(hdmpftrailer)
  CALL get_dims_from_data
(hinfmt,trim(grdbasfn),                    &
       nx,ny,nz,nzsoil,nstyps, ireturn)
  Print*,'nx,ny,nz of input data were ', nx,ny,nz
  allocate(x(nx ),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:x")
  x = 0.0
  allocate(y(ny ),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:y")
  y = 0.0
  allocate(z(nz ),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:z")
  z = 0.0
  allocate(xs(nx),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:xs")
  xs = 0.0
  allocate(ys(ny),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ys")
  ys = 0.0
  allocate(zs1d(nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:zs")
  zs1d = 0.0
  allocate(zp(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:zp")
  zp=0.0
  allocate(ptbar(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ptbar")
  ptbar=0.0
  allocate(pbar(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:pbar")
  pbar=0.0
  allocate(qvbar(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:qvbar")
  qvbar=0.0
  allocate(rhobar(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:rhobar")
  rhobar=0.0
  allocate(tem1 (nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:tem1 ")
  tem1 =0.0
  allocate(tem2 (nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:tem2 ")
  tem2 =0.0
  allocate(tem3 (nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:tem3 ")
  tem3 =0.0
  allocate(tem4 (nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:tem4 ")
  tem4 =0.0
  allocate(itmp(nx,ny,nz),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:itmp")
  itmp=0
  allocate(vortx_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortx_trajc")
  vortx_trajc = missing_value
  allocate(vorty_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vorty_trajc")
  vorty_trajc = missing_value
  allocate(vortz_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortz_trajc")
  vortz_trajc = missing_value
  allocate(vorts_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vorts_trajc")
  vorts_trajc= missing_value
  allocate(vortc_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortc_trajc")
  vortc_trajc= missing_value
  allocate(buoy_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:buoy_trajc")
  buoy_trajc = missing_value
  allocate(buoyq_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:buoya_trajc")
  buoyq_trajc= missing_value
  allocate(vorts_gen_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vorts_gen_trajc")
  vorts_gen_trajc= missing_value
  allocate(vortc_gen_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortc_gen_trajc")
  vortc_gen_trajc= missing_value
  allocate(vortz_tilt_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortz_tilt_trajc")
  vortz_tilt_trajc= missing_value
  allocate(vortz_stch_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vortz_stch_trajc")
  vortz_stch_trajc= missing_value
  allocate(frcs_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:frcs_trajc")
  frcs_trajc = missing_value
  allocate(pprt_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:pprt_trajc")
  pprt_trajc = missing_value
  allocate(ptprt_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:ptprt_trajc")
  ptprt_trajc = missing_value
  allocate(pt_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:pt_trajc")
  pt_trajc = missing_value
  allocate(qv_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:qv_trajc")
  qv_trajc = missing_value
  allocate(p_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:p_trajc")
  p_trajc = missing_value
  allocate(q_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:q_trajc")
  q_trajc = missing_value
  allocate(upgrad_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:upgrad_trajc")
  upgrad_trajc = missing_value
  allocate(vpgrad_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vpgrad_trajc")
  vpgrad_trajc = missing_value
  allocate(wpgrad_trajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:wpgrad_trajc")
  wpgrad_trajc = missing_value
  allocate(utrajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:utrajc")
  allocate(vtrajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:vtrajc")
  allocate(wtrajc(ntrajcs,ntimes),stat=istatus)
  CALL check_alloc_status
(istatus, "arpstrajc:wtrajc")
! allocate(xweight(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:xweight")
! allocate(yweight(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:yweight")
! allocate(zweight(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:zweight")
! allocate(itrajc(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:itrajc")
! allocate(jtrajc(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:jtrajc")
! allocate(ktrajc(ntrajcs,ntimes),stat=istatus)
! CALL check_alloc_status(istatus, "arpstrajc:ktrajc")
!-----------------------------------------------------------------------
! Read x,y,z
!-----------------------------------------------------------------------
  CALL hdfreadxyz
(nx,ny,nz,x,y,z, trim(grdbasfn), time)
  Print*,'x,y,z of input data read in.'
  print*,'x(1 )=',x(1)
  print*,'x(nx)=',x(nx)
  print*,'y(1 )=',y(1)
  print*,'y(ny)=',y(ny)
  dx = x(2) - x(1)
  dy = y(2) - y(1)
  IF( ireturn /= 0 ) THEN
    PRINT*,'Problem occured when trying to get dimensions from data.'
    PRINT*,'Program stopped.'
    STOP
  END IF
  WRITE(6,'(4(a,i5))') 'nx =',nx,', ny=',ny,', nz=',nz ,'nzsoil=',nzsoil  
!-----------------------------------------------------------------------
!  First re-read data at starting (reference) time if necessary.
!-----------------------------------------------------------------------
   CALL hdfreadvar
(nx,ny,nz,trim(grdbasfn),time,'zp', tem1, itmp )
! print*,'mark 1'
   zp(:,:,:) = tem1(:,:,:)
   CALL hdfreadvar
(nx,ny,nz,trim(grdbasfn),time,'ptbar', tem1, itmp )
   ptbar(:,:,:) = tem1(:,:,:)
! print*,'mark 2'
   CALL hdfreadvar
(nx,ny,nz,trim(grdbasfn),time,'pbar', tem1, itmp )
   pbar(:,:,:) = tem1(:,:,:)
   CALL hdfreadvar
(nx,ny,nz,trim(grdbasfn),time,'qvbar', tem1, itmp )
   qvbar(:,:,:) = tem1(:,:,:)
! print*,'mark 3'
   DO i=1,nx-1
     xs(i) = 0.5*(x(i)+x(i+1))
   ENDDO
   DO j=1,ny-1
     ys(j) = 0.5*(y(j)+y(j+1))
   ENDDO
!   DO k=1,nz-1
!     zs1d(k) = 0.5*(zp1d(k)+zp1d(k+1))
!   ENDDO
! print*,'mark 4'
  print*,'nstart, nend, ninc =', nstart, nend, ninc
!-----------------------------------------------------------------------
!  Write out data along trajectories
!-----------------------------------------------------------------------
   DO k=1,ntimes
   idot = index( trim(trajc_fn_in(k)) , '.')
   CALL cvttsnd
( ttrajc(nstart)  ,timsnd0, tmstrln0 )
   CALL cvttsnd
( ttrajc(nend)    ,timsnd1, tmstrln1 )
   CALL cvttsnd
( reftime(k),      timsnd2, tmstrln2 )
   trajc_fn_out = trajc_fn_in(k)(1:idot-1)//'.trajc_'//trim(timsnd0)//'-'//trim(timsnd1)//'_'//trim(timsnd2)//'.data'
   CALL getunit
(nunit(k))
   ltrajc_fn = len_trim(trajc_fn_out) 
   CALL fnversn
( trajc_fn_out, ltrajc_fn )
   OPEN(UNIT=nunit(k),FILE=trim(trajc_fn_out),STATUS='unknown',   &
        FORM='formatted',IOSTAT= istat )
   counter = 0 
   DO j = nstart, nend, ninc
    counter = counter + 1
   ENDDO
   WRITE(nunit(k),'(a)') trim(runname)
   WRITE(nunit(k),'(6e17.6)') xs(1),xs(nx-1),ys(1),ys(ny-1),zp(1,1,1),zp(1,1,nz-1)
   WRITE(nunit(k),'(3e17.6)') dx, dy, z(2)-z(1) 
   WRITE(nunit(k),'(3e17.6)') ttrajc(nstart),ttrajc(nstart),ttrajc(nend) 
   WRITE(nunit(k),'(i10)') counter
   WRITE(nunit(k),'(i10)') ntrajcs
   write(nunit(k),'(a,a,a,a,a,a)')   &
   '    t,      x,        y,        z,           ',  &
   'u,        v,          w,        pt,            ', &
   'p,        qv,         ptprt,    pprt,          ', &
   'vortx,        vorty,        vortz,         vorts,       vortc,        ', &
   'buoy,         buoyq,        frcs,        upgrad,        vpgrad,      ', &
   '  wpgrad,   vorts_gen,    vortc_gen,     vortz_tilt,  vortz_stch '
   ENDDO
!-----------------------------------------------------------------------
!  Start calculations along trajectories
!-----------------------------------------------------------------------
   DO npnt = nstart, nend, ninc
     DO k=1,ntimes
     DO j=1,ntrajcs
       xtrajc1(j,k)=xtrajc(npnt,j,k)
       ytrajc1(j,k)=ytrajc(npnt,j,k)
       ztrajc1(j,k)=ztrajc(npnt,j,k)
     ENDDO
     ENDDO
     time=ttrajc(npnt)
! print*,'Inside npnt loop, npnt = ', npnt
! May have ninc and hdmpfheader, hdmpftrailer depends on time
     CALL cvttsnd
( ttrajc(npnt), timsnd, tmstrln )
     hisfile = trim(hdmpfheader)//'.hdf'//timsnd(1:tmstrln)//trim(hdmpftrailer)
     WRITE(6,'(/a,a,a)') ' Data set ', trim(hisfile),' to be read.'
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'u', tem1, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'v', tem2, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'w', tem3, itmp )
     CALL a3dmax0
(tem1,1,nx,1,nx,1,ny,1,ny-1,1,nz,1,nz-1, amax,amin)
     WRITE(6,'(1x,2(a,e13.6))') 'umin    = ', amin,',  umax    =',amax
     CALL a3dmax0
(tem2,1,nx,1,nx-1,1,ny,1,ny,1,nz,1,nz-1, amax,amin)
     WRITE(6,'(1x,2(a,e13.6))') 'vmin    = ', amin,',  vmax    =',amax
     CALL a3dmax0
(tem3,1,nx,1,nx-1,1,ny,1,ny-1,1,nz,1,nz, amax,amin)
     WRITE(6,'(1x,2(a,e13.6))') 'wmin    = ', amin,',  wmax    =',amax
!-----------------------------------------------------------------------
!  Do diagnostics 
!-----------------------------------------------------------------------
 
   do_diagnostics = 10
   IF( do_diagnostics == 1 .or. do_diagnostics == 10 ) then
     !CALL cal_xvort(tem2,tem3,y,zp,nx,ny,nz, tem4)
     CALL cal_xvort_flat
(tem2,tem3,y,zp,nx,ny,nz, tem4)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortx_trajc )
! Tilting of vortx into vertical
     DO k=1,nz-1
     DO j=1,ny-1
     DO i=2,nx-2
       tem4(i,j,k) = tem4(i,j,k)*(tem3(i+1,j,k)+tem3(i+1,j,k+1)  &
                                 -tem3(i-1,j,k)-tem3(i-1,j,k+1))/(4*dx)
     ENDDO
     ENDDO
     ENDDO
     CALL edgfill
(tem4,1,nx,2,nx-2, 1,ny,1,ny-1, 1,nz,1,nz-1)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortz_trajc ) ! vortz_trajc is used as work array
     !CALL cal_yvort(tem1,tem3,x,zp,nx,ny,nz, tem4)
     CALL cal_yvort_flat
(tem1,tem3,x,zp,nx,ny,nz, tem4)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vorty_trajc )
! Tilting of vorty into vertical
     DO k=1,nz-1
     DO j=2,ny-2
     DO i=1,nx-1 
       tem4(i,j,k) = tem4(i,j,k)*(tem3(i,j+1,k)+tem3(i,j+1,k+1)  &
                                 -tem3(i,j-1,k)-tem3(i,j-1,k+1))/(4*dy)
     ENDDO
     ENDDO
     ENDDO 
     CALL edgfill
(tem4,1,nx,1,nx-1, 1,ny,2,ny-2, 1,nz,1,nz-1)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortz_tilt_trajc )
     vortz_tilt_trajc(:,:) = vortz_tilt_trajc(:,:) + vortz_trajc(:,:)
! vertical vorticity
     !CALL cal_zvort(tem1,tem2,x,y ,nx,ny,nz, tem4,zp)
     CALL cal_zvort_flat
(tem1,tem2,x,y ,nx,ny,nz, tem4)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortz_trajc )
! Vertical stretching for vertical vorticity
     DO k=1,nz-1
     DO j=1,ny-1
     DO i=1,nx-1
       tem4(i,j,k) = tem4(i,j,k)*(tem3(i,j,k+1)-tem3(i,j,k))/(zp(i,j,k+1)-zp(i,j,k))
     ENDDO
     ENDDO
     ENDDO
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortz_stch_trajc )
     CALL avgx
(tem1,0, nx,ny,nz,1,nx-1,1,ny-1,1,nz-1, tem4 )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, utrajc )
     tem1 = tem4
     CALL avgy
(tem2,0, nx,ny,nz,1,nx-1,1,ny-1,1,nz-1, tem4 )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vtrajc )
     tem2 = tem4
     CALL avgz
(tem3,0, nx,ny,nz,1,nx-1,1,ny-1,1,nz-1, tem4 )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                      &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, wtrajc )
     tem3 = tem4
     IF( .false. ) then
! angle/direction of horizontal wind
     pi = 4.0 * atan(1.0)
     DO k=1,nz-1
     DO j=1,ny-1
     DO i=1,nx-1
       IF (tem1(i,j,k).eq.0.0 .and. tem2(i,j,k).gt.0.0) THEN
         tem4 (i,j,k) = (pi/2.0)
       ELSE IF (tem1(i,j,k).eq.0.0 .and. tem2(i,j,k).lt.0.0) THEN
         tem4 (i,j,k) = 3.0*pi/2.0
       ELSE IF (tem1(i,j,k).gt.0.0 .and. tem2(i,j,k).eq.0.0) THEN
         tem4 (i,j,k) = 0.0
       ELSE IF (tem1(i,j,k).lt.0.0 .and. tem2(i,j,k).eq.0.0) THEN
         tem4 (i,j,k) = pi
       ELSE IF (tem1(i,j,k).gt.0.0 .and. tem2(i,j,k).gt.0.0) THEN
         tem4 (i,j,k) = atan(tem2(i,j,k)/tem1(i,j,k))
       ELSE IF (tem1(i,j,k).gt.0.0 .and. tem2(i,j,k).lt.0.0) THEN
         tem4 (i,j,k) = atan(tem2(i,j,k)/tem1(i,j,k)) + (2.0*pi)
       ELSE IF (tem1(i,j,k).lt.0.0 .and. tem2(i,j,k).lt.0.0) THEN
         tem4 (i,j,k) = atan(tem2(i,j,k)/tem1(i,j,k)) + (pi)
       ELSE IF (tem1(i,j,k).lt.0.0 .and. tem2(i,j,k).gt.0.0) THEN
         tem4 (i,j,k) = atan(tem2(i,j,k)/tem1(i,j,k)) + (pi)
       ENDIF
     ENDDO
     ENDDO
     ENDDO
!
! horizontal wind speed
!
     DO k=1,nz-1
     DO j=1,ny-1
     DO i=1,nx-1
       tem4(i,j,k) = sqrt( (tem1(i,j,k))**2 + (tem2(i,j,k))**2 )
     ENDDO
     ENDDO
     ENDDO
 
     ENDIF
!-----------------------------------------------------------------------
! Horizontal streamwise and cross-stream vorticity
!-----------------------------------------------------------------------
     DO k=1,ntimes
     DO ntrj=1,ntrajcs
       utem = utrajc(ntrj,k)
       vtem = vtrajc(ntrj,k)
       wtem = wtrajc(ntrj,k)
       vorts_trajc(ntrj,k)=( vortx_trajc(ntrj,k)*utem  &
                            +vorty_trajc(ntrj,k)*vtem)  &
           /(1.0e-10+sqrt(utem**2+vtem**2))
       vortc_trajc(ntrj,k)=(-vortx_trajc(ntrj,k)*vtem  &
                            +vorty_trajc(ntrj,k)*utem)  &
           /(1.0e-10+sqrt(utem**2+vtem**2))
     ENDDO
     ENDDO
   ENDIF
   IF( do_diagnostics == 2 .or. do_diagnostics == 10 ) then
!-----------------------------------------------------------------------
! Buoyancy term
!-----------------------------------------------------------------------
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'qc', tem1, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'qr', tem2, itmp )
     tem4 = tem1 + tem2
     DO k=1,nz-1
     DO j=1,ny-1
       DO i=1,nx-1
         tem4(i,j,k) = -g*tem4(i,j,k)/(1+qvbar(i,j,k))
       END DO
     END DO
     END DO
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, buoyq_trajc )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'pt', tem1, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'p',  tem2, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'qv', tem3, itmp )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem1,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, pt_trajc )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem2,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, p_trajc )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem3,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, qv_trajc )
     DO k=1,nz
     DO j=1,ny
     DO i=1,nx
       tem1(i,j,k) = tem1(i,j,k)-ptbar(i,j,k)
       tem2(i,j,k) = tem2(i,j,k)- pbar(i,j,k)
       tem3(i,j,k) = tem3(i,j,k)-qvbar(i,j,k)
     ENDDO
     ENDDO
     ENDDO
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem1,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, ptprt_trajc )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem2,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, pprt_trajc )
!
!-----------------------------------------------------------------------
!  wbuoy = g ( ptprt/ptbar-pprt/(rddrv*pbar)+
!          qvprt/(rddrv+qvbar)-(qvprt+qc+qr+qs+qi+qh)/(1+qvbar)
!          -(ptprt*ptprt)/(ptbar*ptbar)                        !2nd-order
!          +0.5*(ptprt*pprt)/(cpdcv*ptbar*pbar))               !2nd-order
!-----------------------------------------------------------------------
     DO k=1,nz-1
     DO j=1,ny-1
       DO i=1,nx-1
         pttem = tem1(i,j,k)/ptbar(i,j,k)
         tem1(i,j,k) = g*(   &
             pttem - tem2(i,j,k)/(rddrv*pbar(i,j,k))     &
            -pttem*pttem+0.5*pttem*tem2(i,j,k)/(cpdcv*pbar(i,j,k))       &
            + tem3(i,j,k)/(rddrv+qvbar(i,j,k)))         &
            + tem4(i,j,k)
       END DO 
     END DO
     END DO
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem1,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, buoy_trajc )
!-----------------------------------------------------------------------
! Baroclinic vorticity generation in streamwise direction
!-----------------------------------------------------------------------
 
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'u', tem2, itmp )
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'v', tem3, itmp )
     do k=1,nz-1
     do j=2,ny-2
     do i=2,nx-2
       utem = 0.5*(tem2(i+1,j,k)+tem2(i,j,k))
       vtem = 0.5*(tem3(i,j+1,k)+tem3(i,j,k))
       tem4(i,j,k)=( -vtem*(tem1(i+1,j,k)-tem1(i-1,j,k))/(x(i+1)-x(i))    &
                     +utem*(tem1(i,j+1,k)-tem1(i,j-1,k))/(y(j+1)-y(j)) )/ &
                   ( 2.0 * (1.0e-10+sqrt( utem*utem + vtem*vtem)) )
     enddo
     enddo
     enddo
     CALL edgfill
(tem4,1,nx,2,nx-2, 1,ny,2,ny-2, 1,nz,1,nz-1)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vorts_gen_trajc )
 
!-----------------------------------------------------------------------
! Baroclinic vorticity generation in cross-wise direction 
!-----------------------------------------------------------------------
     do k=1,nz-1
     do j=2,ny-2
     do i=2,nx-2
       utem = 0.5*(tem2(i+1,j,k)+tem2(i,j,k))
       vtem = 0.5*(tem3(i,j+1,k)+tem3(i,j,k))
       tem4(i,j,k)=(  utem*(tem1(i+1,j,k)-tem1(i-1,j,k))/(x(i+1)-x(i))    &
                     +vtem*(tem1(i,j+1,k)-tem1(i,j-1,k))/(y(j+1)-y(j)) )/ &
                   ( 2.0 * (1.0e-10+sqrt( utem*utem + vtem*vtem)) )
     enddo
     enddo
     enddo
     CALL edgfill
(tem4,1,nx,2,nx-2, 1,ny,2,ny-2, 1,nz,1,nz-1)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vortc_gen_trajc )
   ENDIF
   IF( do_diagnostics == 3 .or. do_diagnostics == 10 ) then
!-----------------------------------------------------------------------
! Vertical pressure gradient force
!-----------------------------------------------------------------------
     CALL hdfreadvar
(nx,ny,nz,trim(hisfile),time,'p',  tem2, itmp )
     DO k=1,nz
     DO j=1,ny
     DO i=1,nx
       tem2(i,j,k) = tem2(i,j,k)- pbar(i,j,k)
     ENDDO
     ENDDO
     ENDDO
     DO k=2,nz-2
       if( k == 2 ) then
         kl = 2
         factor = 1.0
       else
         kl = k-1
         factor = 2.0
       endif
       DO j=1,ny-1
         DO i=1,nx-1
           rhobar(i,j,k) = pbar(i,j,k)/(rd*ptbar(i,j,k)*(pbar(i,j,k)/p0)**rddcp)
           tem1(i,j,k)=-(tem2(i,j,k+1)-tem2(i,j,kl))/  &
               (factor*rhobar(i,j,k)*(zp(i,j,k+1)-zp(i,j,kl)))
         END DO
       END DO
       DO j=1,ny-1
         DO i=2,nx-2
           tem3(i,j,k)=-(tem2(i+1,j,k)-tem2(i-1,j,k))/(2*dx*rhobar(i,j,k))
         END DO
       END DO
       DO j=2,ny-2
         DO i=1,nx-1
           tem4(i,j,k)=-(tem2(i,j,k+1)-tem2(i,j,kl))/(2*dy*rhobar(i,j,k))
         END DO
       END DO
     END DO
     CALL edgfill
(tem1,1,nx,1,nx-1, 1,ny,1,ny-1, 1,nz,2,nz-2)
     CALL edgfill
(tem3,1,nx,2,nx-2, 1,ny,1,ny-1, 1,nz,2,nz-2)
     CALL edgfill
(tem4,1,nx,1,nx-1, 1,ny,2,ny-2, 1,nz,2,nz-2)
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem1,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, wpgrad_trajc )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem3,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, upgrad_trajc )
     CALL intrp_trajc
(nx,ny,nz,xs,ys,zp, tem4,                   &
          xtrajc1,ytrajc1,ztrajc1, ntrajcs, ntimes, vpgrad_trajc )
     DO k=1,ntimes
     DO ntrj=1,ntrajcs
       utem = utrajc(ntrj,k)
       vtem = vtrajc(ntrj,k)
       wtem = wtrajc(ntrj,k)
       frcs_trajc(ntrj,k)=(upgrad_trajc(ntrj,k)*utem             &
                          +vpgrad_trajc(ntrj,k)*vtem+            &
           (wpgrad_trajc(ntrj,k)+buoy_trajc(ntrj,k))*wtem)     &
           /(1.0e-10+sqrt(utem**2+vtem**2+wtem**2))
     ENDDO
     ENDDO
 
     ENDIF
!-----------------------------------------------------------------------
!  Write out data long trajectories
!-----------------------------------------------------------------------
     j = npnt
     DO k=1,ntimes
     write(nunit(k),'(f8.1)') ttrajc(j)
     DO i = 1,ntrajcs
       write(nunit(k),'(f8.1,6f10.2,32e14.6)') ttrajc(j),  &
             xtrajc(j,i,k),ytrajc(j,i,k),ztrajc(j,i,k), & 
             utrajc(i,k),vtrajc(i,k),wtrajc(i,k),    &
             pt_trajc(i,k),p_trajc(i,k),qv_trajc(i,k), &
             ptprt_trajc(i,k),pprt_trajc(i,k), &
             vortx_trajc(i,k),vorty_trajc(i,k),vortz_trajc(i,k),   &
             vorts_trajc(i,k), vortc_trajc(i,k), &
             buoy_trajc(i,k),buoyq_trajc(i,k),frcs_trajc(i,k),     &
             upgrad_trajc(i,k),vpgrad_trajc(i,k),wpgrad_trajc(i,k),  &
             vorts_gen_trajc(i,k),vortc_gen_trajc(i,k) ,             &
             vortz_tilt_trajc(i,k),vortz_stch_trajc(i,k)  
     ENDDO
     ENDDO
   ENDDO
!-----------------------------------------------------------------------
!  Close the trajectory file
!-----------------------------------------------------------------------
   DO k=1,ntimes
   CALL flush(nunit(k))
   CLOSE(UNIT=nunit(k))
   CALL retunit( nunit(k))
   ENDDO
   print*,'done writing trajectory data'
  STOP
100 WRITE(6,'(a)') 'Error reading NAMELIST file. Program ARPSTRAJC stopped.'
  STOP
END PROGRAM ARPSCALCTRAJC
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE DTAREADWIND                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
SUBROUTINE dtareadwind(nx,ny,nz,x,y,z,zp1d, grdbasfn,datafn, time,u,v,w, itmp, tem1) 5,16
!
!-----------------------------------------------------------------------
!  Variable Declarations.
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  INTEGER :: nx,ny,nz          ! Number of grid points in 3 directions
  INTEGER :: hinfmt            ! The format of the history data dump
  CHARACTER(LEN=*) :: grdbasfn ! Name of the grid/base state array file
  CHARACTER(LEN=*) :: datafn   ! Name of the other time dependent data file
  REAL :: x(nx),y(ny),z(nz)
  REAL :: time
  REAL :: u(nx,ny,nz) 
  REAL :: v(nx,ny,nz) 
  REAL :: w(nx,ny,nz) 
  REAL :: zp1d(nz) 
  REAL :: tem1(nx,ny,nz) 
  INTEGER (KIND=selected_int_kind(4)) :: itmp(nx,ny,nz) ! Temporary array
  INTEGER :: grdread,iread
  SAVE grdread
  INTEGER :: istat
  INTEGER :: ireturn           ! Return status indicator
  INTEGER :: grdbas            ! Wether this is a grid/base state
                               ! array dump
  INTEGER :: i,j,k
  LOGICAL :: fexist
  INTEGER :: is
!
!-----------------------------------------------------------------------
!
!  Include files:
!
!-----------------------------------------------------------------------
!
  INCLUDE 'indtflg.inc'
  INCLUDE 'globcst.inc'
  INCLUDE 'grid.inc'          ! Grid & map parameters.
  INCLUDE 'mp.inc'            ! mpi parameters.
  INCLUDE 'exbc.inc'
  INCLUDE 'phycst.inc'
  DATA grdread /0/
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ireturn = 0
  hinfmt = 3
!
!-----------------------------------------------------------------------
!
!  Open and read grid and base state data file depending on the
!  values of parameters grdin and basin, which are read in from the
!  time dependent data set. If grdin or basin is zero, the grid and
!  base state arrays have to be read in from a separate file.
!
!-----------------------------------------------------------------------
!
  IF( grdread == 0 ) THEN
!   print*,'grdread inside if block=', grdread
    grdbas = 1
    INQUIRE(FILE=grdbasfn, EXIST = fexist )
    IF( fexist ) GO TO 200
    INQUIRE(FILE=grdbasfn//'.Z', EXIST = fexist )
    IF( fexist ) THEN
      CALL uncmprs
( grdbasfn//'.Z' )
      GO TO 200
    END IF
    INQUIRE(FILE=grdbasfn//'.gz', EXIST = fexist )
    IF( fexist ) THEN
      CALL uncmprs
( grdbasfn//'.gz' )
      GO TO 200
    END IF
    WRITE(6,'(/1x,a,/1x,a/)')                                           &
        'File '//grdbasfn//                             &
        ' or its compressed version not found.',                        &
        'Program stopped in DTAREAD.'
    CALL arpsstop
('arpsstop called from dtareadwind during base state read',1)
200 CONTINUE
!
!-----------------------------------------------------------------------
!  Read grid and base state fields.
!-----------------------------------------------------------------------
!
    CALL hdfreadwind
(nx,ny,nz,x,y,z,zp1d,grdbas,trim(grdbasfn), &
         time,u,v,w, itmp,tem1)
    grdread = 1
  END IF
!
!-----------------------------------------------------------------------
!  Read data fields.
!-----------------------------------------------------------------------
!
  grdbas = 0
    INQUIRE(FILE=trim(datafn), EXIST = fexist )
    IF( fexist ) GO TO 100
    INQUIRE(FILE=trim(datafn)//'.Z', EXIST = fexist )
    IF( fexist ) THEN
      CALL uncmprs
( trim(datafn)//'.Z' )
      GO TO 100
    END IF
    INQUIRE(FILE=trim(datafn)//'.gz', EXIST = fexist )
    IF( fexist ) THEN
      CALL uncmprs
( trim(datafn)//'.gz' )
      GO TO 100
    END IF
    WRITE(6,'(/1x,a,/1x,a/)')                                        &
       'File '//trim(datafn)                               &
       //' or its compressed version not found.',                    &
       'Program stopped in DTAREADWIND.'
    CALL arpsstop
('arpsstop called from dtareadwind during base read-2',1)
100 CONTINUE
    CALL hdfreadwind
(nx,ny,nz,x,y,z,zp1d,grdbas,trim(datafn), &
         time,u,v,w, itmp,tem1)
  RETURN
END SUBROUTINE dtareadwind
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE HDFREAD                    ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
SUBROUTINE hdfreadwind(nx,ny,nz,x,y,z,zp1d,grdbas,filename,   & 4,122
           time,u,v,w, itmp, tem1)
!-----------------------------------------------------------------------
!  PURPOSE:
!  Read in history data in the NCSA HDF4 format.
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  2000/04/15
!
!  MODIFICATION HISTORY:
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!    grdbas   Data read flag.
!             =1, only grid and base state arrays will be read
!             =0, all arrays will be read based on data
!                 parameter setting.
!    filename  Character variable nhming the input HDF file
!-----------------------------------------------------------------------
!  Variable Declarations.
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  INTEGER :: grdbas
  CHARACTER (LEN=*) :: filename
  REAL :: x     (nx)           ! x coord.
  REAL :: y     (ny)           ! y coord.
  REAL :: z     (nz)           ! z coord.
  REAL :: time
  REAL :: u(nx,ny,nz) 
  REAL :: v(nx,ny,nz)
  REAL :: w(nx,ny,nz)
  REAL :: zp1d(nz)
  REAL :: tem1(nx,ny,nz)
  INTEGER (KIND=selected_int_kind(4)) :: itmp(nx,ny,nz) ! Temporary array
  REAL :: hmax(nz), hmin(nz) ! Temporary array
  INTEGER :: ireturn
!-----------------------------------------------------------------------
!  Parameters describing routine that wrote the gridded data
!-----------------------------------------------------------------------
!
! 06/28/2002 Zuwen He
!
! fmtver??: to label each data a version.
! intver??: an integer to allow faster comparison than fmtver??,
!           which are strings.
!
! Verion 5.00: significant change in soil variables since version 4.10.
! 
!-----------------------------------------------------------------------
  CHARACTER (LEN=40) :: fmtver410,fmtver500
  INTEGER  :: intver,intver410,intver500
  PARAMETER (fmtver410='004.10 HDF4 Coded Data',intver410=410)
  PARAMETER (fmtver500='005.00 HDF4 Coded Data',intver500=500)
  CHARACTER (LEN=40) :: fmtverin
  CHARACTER (LEN=10) :: tmunit
!-----------------------------------------------------------------------
!  Misc. local variables
!-----------------------------------------------------------------------
  INTEGER :: lchanl
  PARAMETER (lchanl=6)      ! Channel number for formatted printing.
  INTEGER :: i,j,k,is
  INTEGER :: nxin,nyin,nzin
  INTEGER :: bgrdin,bbasin,bvarin,bicein,btrbin,btkein
  INTEGER :: istat, sd_id
  INTEGER :: varflg, istatus
!-----------------------------------------------------------------------
!
!  Include files:
!
!-----------------------------------------------------------------------
  INCLUDE 'globcst.inc'
  INCLUDE 'grid.inc'        ! Grid parameters
  INCLUDE 'indtflg.inc'
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!  Beginning of executable code...
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  WRITE(*,*) 'HDFREAD: Reading HDF file: ', trim(filename)
!-----------------------------------------------------------------------
! Open file for reading 
!-----------------------------------------------------------------------
  CALL hdfopen
(filename,1,sd_id)
  IF (sd_id < 0) THEN
    WRITE (6,*) "HDFREAD: ERROR opening ", trim(filename)," for reading."
    GO TO 110
  END IF
  fmtverin = fmtver500
  WRITE(6,'(/1x,a,a/)') 'Incoming data format, fmtverin=',fmtverin
  CALL hdfrdc
(sd_id,40,"runname",runname,istat)
  CALL hdfrdi
(sd_id,"nocmnt",nocmnt,istat)
  IF( nocmnt > 0 ) THEN
    CALL hdfrdc
(sd_id,80*nocmnt,"cmnt",cmnt,istat)
  END IF
  WRITE(6,'(//''  THE NAME OF THIS RUN IS:  '',A//)') trim(runname)
  WRITE (6,*) "Comments:"
  IF( nocmnt > 0 ) THEN
    DO i=1,nocmnt
      WRITE(6,'(1x,a)') cmnt(i)
    END DO
  END IF
  WRITE (6,*) " "
  CALL hdfrdc
(sd_id,10,"tmunit",tmunit,istat)
  CALL hdfrdr
(sd_id,"time",time,istat)
!-----------------------------------------------------------------------
!  Get dimensions of data in binary file and check against
!  the dimensions passed to HDFREAD
!-----------------------------------------------------------------------
  CALL hdfrdi
(sd_id,"nx",nxin,istat)
  CALL hdfrdi
(sd_id,"ny",nyin,istat)
  CALL hdfrdi
(sd_id,"nz",nzin,istat)
  IF ( nxin /= nx .OR. nyin /= ny .OR. nzin /= nz ) THEN
    WRITE(6,'(1x,a)') ' Dimensions in HDFREAD inconsistent with data.'
    WRITE(6,'(1x,a,3I15)') ' Read were: ', nxin, nyin, nzin
    WRITE(6,'(1x,a,3I15)') ' Expected:  ', nx, ny, nz
    WRITE(6,'(1x,a)') ' Program aborted in HDFREAD.'
    CALL arpsstop
('arpsstop called from HDFREAD due to nxin...',1)
  END IF
!-----------------------------------------------------------------------
!  Read in x,y and z at grid cell centers (scalar points).
!-----------------------------------------------------------------------
  IF( grdin == 1 .OR. grdbas == 1 ) THEN
    CALL hdfrd1d
(sd_id,"x",nx,x,istat)
    IF (istat /= 0) GO TO 110
    CALL hdfrd1d
(sd_id,"y",ny,y,istat)
    IF (istat /= 0) GO TO 110
    CALL hdfrd1d
(sd_id,"z",nz,z,istat)
    IF (istat /= 0) GO TO 110
  END IF  ! grdin
!-----------------------------------------------------------------------
!  Read in flags for different data groups
!-----------------------------------------------------------------------
  IF ( grdbas == 1 ) THEN   ! Read grid and base state arrays
    WRITE(lchanl,'(1x,a,f8.1,a,f8.3,a/)')                               &
         'To read grid and base state data at time ', time,             &
         ' secs = ',(time/60.),' mins.'
    CALL hdfrdi
(sd_id,"grdflg",bgrdin,istat)
    CALL hdfrdi
(sd_id,"basflg",bbasin,istat)
    CALL hdfrdi
(sd_id,"varflg",bvarin,istat)
    CALL hdfrdi
(sd_id,"mstflg",mstin,istat)
    CALL hdfrdi
(sd_id,"iceflg",bicein,istat)
    CALL hdfrdi
(sd_id,"trbflg",btrbin,istat)
    CALL hdfrdi
(sd_id,"landflg",landin,istat)
    CALL hdfrdi
(sd_id,"totflg",totin,istat)
    CALL hdfrdi
(sd_id,"tkeflg",btkein,istat)
  ELSE ! Normal data reading
    WRITE(lchanl,'(1x,a,f8.1,a,f8.3,a/)')'To read data for time:',      &
         time,' secs = ',(time/60.),' mins.'
    CALL hdfrdi
(sd_id,"grdflg",grdin,istat)
    CALL hdfrdi
(sd_id,"basflg",basin,istat)
    CALL hdfrdi
(sd_id,"varflg",varin,istat)
    CALL hdfrdi
(sd_id,"mstflg",mstin,istat)
    CALL hdfrdi
(sd_id,"iceflg",icein,istat)
    CALL hdfrdi
(sd_id,"trbflg",trbin,istat)
    CALL hdfrdi
(sd_id,"sfcflg",sfcin,istat)
    CALL hdfrdi
(sd_id,"rainflg",rainin,istat)
    CALL hdfrdi
(sd_id,"totflg",totin,istat)
    CALL hdfrdi
(sd_id,"tkeflg",tkein,istat)
    print*,'done reading parameters'
  END IF
  CALL hdfrdi
(sd_id,"prcflg",prcin,istat)
  CALL hdfrdi
(sd_id,"radflg",radin,istat)
  CALL hdfrdi
(sd_id,"flxflg",flxin,istat)
  CALL hdfrdi
(sd_id,"snowflg",snowin,istat)
  CALL hdfrdi
(sd_id,"month",month,istat)
  CALL hdfrdi
(sd_id,"day",day,istat)
  CALL hdfrdi
(sd_id,"year",year,istat)
  CALL hdfrdi
(sd_id,"hour",hour,istat)
  CALL hdfrdi
(sd_id,"minute",minute,istat)
  CALL hdfrdi
(sd_id,"second",second,istat)
  CALL hdfrdr
(sd_id,"umove",umove,istat)
  CALL hdfrdr
(sd_id,"vmove",vmove,istat)
  CALL hdfrdr
(sd_id,"xgrdorg",xgrdorg,istat)
  CALL hdfrdr
(sd_id,"ygrdorg",ygrdorg,istat)
  CALL hdfrdi
(sd_id,"mapproj",mapproj,istat)
  CALL hdfrdr
(sd_id,"trulat1",trulat1,istat)
  CALL hdfrdr
(sd_id,"trulat2",trulat2,istat)
  CALL hdfrdr
(sd_id,"trulon",trulon,istat)
  CALL hdfrdr
(sd_id,"sclfct",sclfct,istat)
  CALL hdfrdr
(sd_id,"tstop",tstop,istat)
  CALL hdfrdr
(sd_id,"thisdmp",thisdmp,istat)
  CALL hdfrdr
(sd_id,"latitud",latitud,istat)
  CALL hdfrdr
(sd_id,"ctrlat",ctrlat,istat)
  CALL hdfrdr
(sd_id,"ctrlon",ctrlon,istat)
  IF( grdin == 1 .OR. grdbas == 1 ) THEN
    CALL hdfrd3d
(sd_id,"zp",nx,ny,nz,tem1,istat,itmp,hmax,hmin)
    IF (istat /= 0) GO TO 110
    zp1d(:)=tem1(2,2,:) 
  ENDIF
!-----------------------------------------------------------------------
!  Read in base state fields
!-----------------------------------------------------------------------
! Print*,'start doing 3d arrays'
  IF( (basin == 1 .OR. grdbas == 1)  .and. hdmpfmt /= 0) THEN
!   CALL hdfrd3d(sd_id,"ubar",nx,ny,nz,ubar,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"vbar",nx,ny,nz,vbar,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"ptbar",nx,ny,nz,ptbar,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"pbar",nx,ny,nz,pbar,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   IF( mstin == 1 ) THEN
!     CALL hdfrd3d(sd_id,"qvbar",nx,ny,nz,qvbar,istat,itmp,hmax,hmin)
!     IF (istat /= 0) GO TO 110
!   ELSE
!     qvbar= 0.0
!   END IF
  ENDIF
  landout = 0 ! skipping landout for know
  IF( grdbas == 1 ) GO TO 930
  IF( varin == 1 ) then 
!-----------------------------------------------------------------------
!  Read in total values of variables from history dump
!-----------------------------------------------------------------------
    CALL hdfrd3d
(sd_id,"u",nx,ny,nz,u,istat,itmp,hmax,hmin)
    IF (istat /= 0) GO TO 110
    CALL hdfrd3d
(sd_id,"v",nx,ny,nz,v,istat,itmp,hmax,hmin)
    IF (istat /= 0) GO TO 110
    CALL hdfrd3d
(sd_id,"w",nx,ny,nz,w,istat,itmp,hmax,hmin)
    IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"pt",nx,ny,nz,pt,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"p",nx,ny,nz,p,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   IF( mstin == 1 ) THEN
!     CALL hdfrd3d(sd_id,"qv",nx,ny,nz,qv,istat,itmp,hmax,hmin)
!     IF (istat /= 0) GO TO 110
! 
!     CALL hdfrd3d(sd_id,"qc",nx,ny,nz,qc,istat,itmp,hmax,hmin)
!     IF (istat /= 0) GO TO 110
! 
!     CALL hdfrd3d(sd_id,"qr",nx,ny,nz,qr,istat,itmp,hmax,hmin)
!     IF (istat /= 0) GO TO 110
!     IF( icein == 1 ) THEN
!       CALL hdfrd3d(sd_id,"qi",nx,ny,nz,qi,istat,itmp,hmax,hmin)
!       IF (istat /= 0) GO TO 110
! 
!       CALL hdfrd3d(sd_id,"qs",nx,ny,nz,qs,istat,itmp,hmax,hmin)
!       IF (istat /= 0) GO TO 110
! 
!       CALL hdfrd3d(sd_id,"qh",nx,ny,nz,qh,istat,itmp,hmax,hmin)
!       IF (istat /= 0) GO TO 110
!     END IF
!   END IF
  END IF
! IF( tkein == 1 ) THEN
!   CALL hdfrd3d(sd_id,"tke",nx,ny,nz,tke,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
! END IF
! IF( trbin == 1 ) THEN
!   CALL hdfrd3d(sd_id,"kmh",nx,ny,nz,kmh,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
!   CALL hdfrd3d(sd_id,"kmv",nx,ny,nz,,istat,itmp,hmax,hmin)
!   IF (istat /= 0) GO TO 110
! END IF
!
! Surface arrays skipped
!
!-----------------------------------------------------------------------
!
!  Friendly exit message
!
!-----------------------------------------------------------------------
  930   CONTINUE
  WRITE(6,'(/a,F8.1,a/)')                                               &
  ' Data at time=', time/60,' (min) were successfully read.'
  ireturn = 0
  GO TO 130
!-----------------------------------------------------------------------
!
!  Error during read
!
!-----------------------------------------------------------------------
  110   CONTINUE
  WRITE(6,'(/a/)') ' Error reading data in HDFREAD'
  ireturn=1
  130   CONTINUE
  CALL hdfclose
(sd_id,istat)
  IF (ireturn == 0) THEN
    IF (istat == 0) THEN
      WRITE(6,'(/a/a)') &
      "HDFREADWIND: Successfully read ", trim(filename)
    ELSE
      WRITE(6,'(/a,i3,a/,a)') &
      "HDFREADWIND: ERROR (status=", istat, ") closing ", trim(filename)
    END IF
  END IF
  RETURN
END SUBROUTINE hdfreadwind
!##################################################################
!##################################################################
!######                                                      ######
!######             SUBROUTINE GET_GRIDINFO_FROM_HDF         ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
SUBROUTINE get_gridinfo_from_hdf(filename,nx,ny,nz,x,y,z,ireturn) 2,15
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Read in grid dimensions from base state/grid history data.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  7/17/2000.
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    filename Channel number for binary reading.
!
!  OUTPUT:
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER :: stat, sd_id
  CHARACTER (LEN=*) :: filename
  INTEGER :: nx,ny,nz          ! Number of grid points in 3 directions
  REAL :: x(nx),y(ny),z(nz)
  INTEGER :: ireturn           ! Return status indicator
  INTEGER istat
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  CALL hdfopen
(filename,1,sd_id)
  IF (sd_id < 0) THEN
    WRITE (6,*) "get_gridinfo_from_hdf: ERROR opening ",                 &
                 trim(filename)," for reading."
    GO TO 110
  ELSE
    WRITE(6,*) 'File ',filename,' openned.'
  END IF
! print*,'sd_id, nx =', sd_id, nx
  CALL hdfrd1d
(sd_id,"x",nx,x,istat)
! print*,'istat after reading x =', istat
  IF (istat /= 0) GO TO 110
  CALL hdfrd1d
(sd_id,"y",ny,y,istat)
  IF (istat /= 0) GO TO 110
  CALL hdfrd1d
(sd_id,"z",nz,z,istat)
  IF (istat /= 0) GO TO 110
  ireturn = 0
  GO TO 130
!-----------------------------------------------------------------------
!
!  Error during read
!
!-----------------------------------------------------------------------
  110   CONTINUE
  WRITE(6,'(/a/)') ' Error reading data in GET_GRIDINFO_FROM_HDF.'
  ireturn=1
130 CONTINUE
!tmp  stat = sfendacc(sd_id)   ! is this necessary?
  CALL hdfclose
(sd_id,stat)
  RETURN
END SUBROUTINE get_gridinfo_from_hdf
SUBROUTINE copyarray(arrayin,nx,ny,nz, arrayout, nx1,ny1,nz1, & 32
           nxbgn,nxend,nybgn,nyend,nzbgn,nzend)
INTEGER :: nx,ny,nz, nx1,ny1,nz1,nxbgn,nxend,nybgn,nyend,nzbgn,nzend
REAL :: arrayin(nx,ny,nz)
REAL :: arrayout(nx1,ny1,nz1)
  DO k=1,nz1
  DO j=1,ny1
  DO i=1,nx1
    arrayout(i,j,k)=arrayin(nxbgn+i-1,nybgn+j-1,nzbgn+k-1)
  ENDDO
  ENDDO
  ENDDO
return
END SUBROUTINE copyarray
SUBROUTINE intrpx3d(ain,nx,is,ie, ny,js,je, nz,ks,ke, wgtx,ix,          & 3
           aout,nx1,is1,ie1)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Perform interpolation in the first dimension
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  4/1/1999.
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER :: nx,is,ie, ny,js,je, nz,ks,ke
  INTEGER :: nx1,is1,ie1
  REAL :: ain (nx ,ny,nz)
  REAL :: aout(nx1,ny,nz)
  REAL :: wgtx(nx1)
  INTEGER :: ix(nx1)
  INTEGER :: i,j,k
    DO k=ks ,ke
      DO j=js ,je
        DO i=is1,ie1
          aout(i,j,k)=      wgtx(i) *ain(ix(i)  ,j,k)                 &
                      +(1.0-wgtx(i))*ain(ix(i)+1,j,k)
        END DO
      END DO
    END DO
  RETURN
END SUBROUTINE intrpx3d
SUBROUTINE intrpy3d(ain,nx,is,ie, ny,js,je, nz,ks,ke, wgty,jy,          & 3
           aout,ny1,js1,je1)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Perform interpolation in the second dimension
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  4/1/1999.
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  INTEGER :: nx,is,ie, ny,js,je, nz,ks,ke
  INTEGER :: ny1,js1,je1
  REAL :: ain (nx,ny ,nz)
  REAL :: aout(nx,ny1,nz)
  REAL :: wgty(ny1)
  INTEGER :: jy(ny1)
  INTEGER :: i,j,k
    DO k=ks ,ke
      DO j=js1,je1
        DO i=is ,ie
          aout(i,j,k)=      wgty(j) *ain(i,jy(j)  ,k)                 &
                      +(1.0-wgty(j))*ain(i,jy(j)+1,k)
        END DO
      END DO
    END DO
  RETURN
END SUBROUTINE intrpy3d
SUBROUTINE intrpxy3d(ain,nx,is,ie, ny,js,je, nz,ks,ke,                  & 53,8
           wgtx,ix,wgty,jy,                                             &
           aout,nx1,is1,ie1, ny1,js1,je1,                               &
           temx1yz)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Perform interpolation in the first and second dimensions
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  4/1/1999.
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  INTEGER :: nx,is,ie, ny,js,je, nz,ks,ke
  INTEGER :: nx1,is1,ie1, ny1,js1,je1
  REAL :: ain (nx ,ny ,nz)
  REAL :: aout(nx1,ny1,ks:ke)
  REAL :: wgtx(nx1),wgty(ny1)
  INTEGER :: ix(nx1),jy(ny1)
  INTEGER :: k
  REAL :: temx1yz(nx1,ny)
  DO k=ks,ke
  CALL intrpx3d
(ain(1,1,k),nx,is,ie, ny,js,je, 1,1,1,                &
                wgtx,ix,temx1yz,nx1,is1,ie1)
  CALL intrpy3d
(temx1yz,nx1,is1,ie1, ny,js,je, 1,1,1,                &
                wgty,jy,aout(1,1,k),ny1,js1,je1)
  ENDDO
  CALL edgfill
(aout,1,nx1,is1,ie1,1,ny1,js1,je1,ks,ke,ks,ke)
  RETURN
END SUBROUTINE intrpxy3d
INTEGER FUNCTION get_ktrajc(z, zs, nz)
  IMPLICIT NONE
  INTEGER :: nz, k
  REAL :: z, zs(nz)
  IF( z < zs(1) ) then
    get_ktrajc = 1
    RETURN
  ENDIF
  IF( z >= zs(nz) ) then
    get_ktrajc = nz-1
    RETURN
  ENDIF
  DO k=1,nz-1
    IF( z >= zs(k) .and. z < zs(k+1) ) then
      get_ktrajc = k
      EXIT
    endif
    
  ENDDO
  RETURN
END FUNCTION get_ktrajc
SUBROUTINE intrp_trajc(nx,ny,nz,xs,ys,zp, u,                & 21
           xtrajc,ytrajc,ztrajc, ntrajcs,ntimes, utrajc )
!
!-----------------------------------------------------------------------
!  PURPOSE:
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue 
!  (4/08/2004)
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!  Variable Declarations:
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: xs(nx),ys(ny),zp(nx,ny,nz)
  REAL :: u(nx,ny,nz) ! input - field to be interpolated to trajectory points
  INTEGER :: ntrajcs, ntimes
  REAL :: xtrajc(ntrajcs,ntimes),ytrajc(ntrajcs,ntimes),ztrajc(ntrajcs,ntimes)
  REAL :: utrajc(ntrajcs,ntimes)  ! output - u interpolated to trajectory points
  INTEGER :: get_ktrajc
  REAL :: dx, dy, utrajc1,vtrajc1,wtrajc1
  REAL :: uy1z1,uy2z1,uy1z2,uy2z2,vy1z1,vy2z1,vy1z2,vy2z2,wy1z1,wy2z1,wy1z2,wy2z2
  REAL :: uz1,uz2,vz1,vz2,wz1,wz2
  REAL :: missing_value
  INTEGER :: ntrajc,itrajc1,jtrajc1,ktrajc1
  REAL :: xweight1,yweight1,zweight1
!
  REAL :: zs1d(nz),zy1(nz),zy2(nz) ! automatic work array
  INTEGER :: i,k,l
  dx = xs(2)-xs(1)
  dy = ys(2)-ys(1)
  missing_value = -99999.0
  DO k=1,ntimes
  DO i= 1,ntrajcs
    IF( xtrajc(i,k) == missing_value .or.      &
        ytrajc(i,k) == missing_value .or.      &
        ztrajc(i,k) == missing_value ) then 
      utrajc(i,k) = missing_value
    ELSE
    itrajc1 = MAX(1, MIN(nx-2, INT((xtrajc(i,k)-xs(1))/dx)+1 ))
    jtrajc1 = MAX(1, MIN(ny-2, INT((ytrajc(i,k)-ys(1))/dy)+1 ))
!    ktrajc1 = get_ktrajc(ztrajc(i,k),zs,nz-1)
  
    xweight1 = (xtrajc(i,k)-xs(itrajc1))/dx
    yweight1 = (ytrajc(i,k)-ys(jtrajc1))/dy
    DO l=1,nz-1
      zy1(l) = (1.0-xweight1)*(zp(itrajc1  ,jtrajc1  ,l)+zp(itrajc1  ,jtrajc1  ,l+1))*0.5 &
                   +xweight1 *(zp(itrajc1+1,jtrajc1  ,l)+zp(itrajc1+1,jtrajc1  ,l+1))*0.5
      zy2(l) = (1.0-xweight1)*(zp(itrajc1  ,jtrajc1+1,l)+zp(itrajc1  ,jtrajc1+1,l+1))*0.5 &
                   +xweight1 *(zp(itrajc1+1,jtrajc1+1,l)+zp(itrajc1+1,jtrajc1+1,l+1))*0.5
      zs1d(l) = ( 1.0-yweight1 )*zy1(l) + yweight1*zy2(l)
    END DO
    ktrajc1 = get_ktrajc(ztrajc(i,k),zs1d,nz-1)
    uy1z1 = (1.0-xweight1)*u(itrajc1,jtrajc1  ,ktrajc1  )+xweight1*u(itrajc1+1,jtrajc1  ,ktrajc1  )
    uy2z1 = (1.0-xweight1)*u(itrajc1,jtrajc1+1,ktrajc1  )+xweight1*u(itrajc1+1,jtrajc1+1,ktrajc1  )
    uy1z2 = (1.0-xweight1)*u(itrajc1,jtrajc1  ,ktrajc1+1)+xweight1*u(itrajc1+1,jtrajc1  ,ktrajc1+1)
    uy2z2 = (1.0-xweight1)*u(itrajc1,jtrajc1+1,ktrajc1+1)+xweight1*u(itrajc1+1,jtrajc1+1,ktrajc1+1)
    uz1 = ( 1.0-yweight1 )*uy1z1 + yweight1*uy2z1
    uz2 = ( 1.0-yweight1 )*uy1z2 + yweight1*uy2z2
    zweight1 = (ztrajc(i,k)-zs1d(ktrajc1))/(zs1d(ktrajc1+1)-zs1d(ktrajc1))
    utrajc(i,k) = (1.0-zweight1)*uz1+zweight1*uz2
    ENDIF
  ENDDO
  ENDDO
  RETURN
END SUBROUTINE intrp_trajc
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE HDFREAD                    ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
SUBROUTINE hdfreadvar(nx,ny,nz,filename, time, varname, var, itmp ) 15,8
!-----------------------------------------------------------------------
!  PURPOSE:
!  Read in history data in the NCSA HDF4 format.
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  2000/04/15
!
!  MODIFICATION HISTORY:
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!    grdbas   Data read flag.
!             =1, only grid and base state arrays will be read
!             =0, all arrays will be read based on data
!                 parameter setting.
!    filename  Character variable nhming the input HDF file
!-----------------------------------------------------------------------
!  Variable Declarations.
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  CHARACTER (LEN=*) :: varname
  CHARACTER (LEN=*) :: filename
  REAL :: time
  REAL :: var(nx,ny,nz) 
  INTEGER (KIND=selected_int_kind(4)) :: itmp(nx,ny,nz) ! Temporary array
  REAL :: hmax(nz), hmin(nz) ! Temporary array
  INTEGER :: ireturn
  INTEGER :: i,j,k,is
  INTEGER :: nxin,nyin,nzin
  INTEGER :: istat, sd_id
  INTEGER :: varflg, istatus
  REAL :: timein
!-----------------------------------------------------------------------
!
!  Include files:
!
!-----------------------------------------------------------------------
  INCLUDE 'globcst.inc'
  INCLUDE 'grid.inc'        ! Grid parameters
  INCLUDE 'indtflg.inc'
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!  Beginning of executable code...
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  WRITE(*,*) 'HDFREAD: Reading HDF file: ', trim(filename)
!-----------------------------------------------------------------------
! Open file for reading 
!-----------------------------------------------------------------------
  CALL hdfopen
(filename,1,sd_id)
  IF (sd_id < 0) THEN
    WRITE (6,*) "HDFREAD: ERROR opening ", trim(filename)," for reading."
    GO TO 110
  END IF
  CALL hdfrdr
(sd_id,"time",timein,istat)
  IF( timein /= time ) then
    print*,'Warning: time in data does not match time passed into READHDFVAR.'
    Print*,'time in program =', time, ', time in data =', timein
    print*,'time in program reset to ', timein
    time = timein
  ENDIF
!-----------------------------------------------------------------------
!  Get dimensions of data in binary file and check against
!  the dimensions passed to HDFREAD
!-----------------------------------------------------------------------
  CALL hdfrdi
(sd_id,"nx",nxin,istat)
  CALL hdfrdi
(sd_id,"ny",nyin,istat)
  CALL hdfrdi
(sd_id,"nz",nzin,istat)
  IF ( nxin /= nx .OR. nyin /= ny .OR. nzin /= nz ) THEN
    WRITE(6,'(1x,a)') ' Dimensions in HDFREAD inconsistent with data.'
    WRITE(6,'(1x,a,3I15)') ' Read were: ', nxin, nyin, nzin
    WRITE(6,'(1x,a,3I15)') ' Expected:  ', nx, ny, nz
    WRITE(6,'(1x,a)') ' Program aborted in HDFREAD.'
    CALL arpsstop
('arpsstop called from HDFREAD due to nxin...',1)
  END IF
!-----------------------------------------------------------------------
!  Read in total values of variables from history dump
!-----------------------------------------------------------------------
    CALL hdfrd3d
(sd_id,varname,nx,ny,nz,var,istat,itmp,hmax,hmin)
    IF (istat /= 0) GO TO 110
!-----------------------------------------------------------------------
!  Friendly exit message
!-----------------------------------------------------------------------
  930   CONTINUE
  WRITE(6,'(/a,a,a,F8.1,a/)')                                               &
  ' Variable ', varname,' at time=', time/60,' (min) were successfully read.'
  ireturn = 0
  GO TO 130
!-----------------------------------------------------------------------
!  Error during read
!-----------------------------------------------------------------------
  110   CONTINUE
  WRITE(6,'(/a/)') ' Error reading data in HDFREADVAR'
  STOP
  ireturn=1
  130   CONTINUE
  CALL hdfclose
(sd_id,istat)
  IF (ireturn == 0) THEN
    IF (istat == 0) THEN
      WRITE(6,'(/a/a)') &
      "HDFREADVAR: Successfully read ", trim(filename)
    ELSE
      WRITE(6,'(/a,i3,a/,a)') &
      "HDFREADVAR: ERROR (status=", istat, ") closing ", trim(filename)
    END IF
  END IF
  RETURN
END SUBROUTINE hdfreadvar
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE HDFREADXYZ                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
SUBROUTINE hdfreadxyz(nx,ny,nz,x,y,z, filename, time) 1,10
!-----------------------------------------------------------------------
!  PURPOSE:
!  Read in history data in the NCSA HDF4 format.
!-----------------------------------------------------------------------
!
!  AUTHOR: Ming Xue
!  2000/04/15
!
!  MODIFICATION HISTORY:
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!    grdbas   Data read flag.
!             =1, only grid and base state arrays will be read
!             =0, all arrays will be read based on data
!                 parameter setting.
!-----------------------------------------------------------------------
!  Variable Declarations.
!-----------------------------------------------------------------------
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  CHARACTER (LEN=*) :: filename
  REAL :: x(nx)           ! x coord.
  REAL :: y(ny)           ! y coord.
  REAL :: z(nz)           ! z coord.
  REAL :: time
  INTEGER :: ireturn
  CHARACTER (LEN=40) :: fmtver410,fmtver500
  INTEGER  :: intver,intver410,intver500
  PARAMETER (fmtver410='004.10 HDF4 Coded Data',intver410=410)
  PARAMETER (fmtver500='005.00 HDF4 Coded Data',intver500=500)
  CHARACTER (LEN=40) :: fmtverin
  CHARACTER (LEN=10) :: tmunit
!-----------------------------------------------------------------------
!  Misc. local variables
!-----------------------------------------------------------------------
  INTEGER :: lchanl
  PARAMETER (lchanl=6)      ! Channel number for formatted printing.
  INTEGER :: i,j,k,is
  INTEGER :: nxin,nyin,nzin
  INTEGER :: istat, sd_id
  INTEGER :: varflg, istatus
!-----------------------------------------------------------------------
!  Include files:
!-----------------------------------------------------------------------
! INCLUDE 'globcst.inc'
! INCLUDE 'grid.inc'        ! Grid parameters
! INCLUDE 'indtflg.inc'
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!  Beginning of executable code...
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  WRITE(*,*) 'HDFREAD: Reading HDF file: ', trim(filename)
!-----------------------------------------------------------------------
! Open file for reading 
!-----------------------------------------------------------------------
  CALL hdfopen
(filename,1,sd_id)
  IF (sd_id < 0) THEN
    WRITE (6,*) "HDFREAD: ERROR opening ", trim(filename)," for reading."
    GO TO 110
  END IF
  CALL hdfrdr
(sd_id,"time",time,istat)
!-----------------------------------------------------------------------
!  Get dimensions of data in binary file and check against
!  the dimensions passed to HDFREAD
!-----------------------------------------------------------------------
  CALL hdfrdi
(sd_id,"nx",nxin,istat)
  CALL hdfrdi
(sd_id,"ny",nyin,istat)
  CALL hdfrdi
(sd_id,"nz",nzin,istat)
  IF ( nxin /= nx .OR. nyin /= ny .OR. nzin /= nz ) THEN
    WRITE(6,'(1x,a)') ' Dimensions in HDFREAD inconsistent with data.'
    WRITE(6,'(1x,a,3I15)') ' Read were: ', nxin, nyin, nzin
    WRITE(6,'(1x,a,3I15)') ' Expected:  ', nx, ny, nz
    WRITE(6,'(1x,a)') ' Program aborted in HDFREAD.'
    CALL arpsstop
('arpsstop called from HDFREAD due to nxin...',1)
  END IF
!-----------------------------------------------------------------------
!  Read in x,y and z at grid cell centers (scalar points).
!-----------------------------------------------------------------------
  CALL hdfrd1d
(sd_id,"x",nx,x,istat)
  IF (istat /= 0) GO TO 110
  CALL hdfrd1d
(sd_id,"y",ny,y,istat)
  IF (istat /= 0) GO TO 110
  CALL hdfrd1d
(sd_id,"z",nz,z,istat)
  IF (istat /= 0) GO TO 110
!-----------------------------------------------------------------------
!  Friendly exit message
!-----------------------------------------------------------------------
  930   CONTINUE
  WRITE(6,'(/a,F8.1,a/)')                                               &
  ' Data at time=', time/60,' (min) were successfully read.'
  ireturn = 0
  GO TO 130
!-----------------------------------------------------------------------
!  Error during read
!-----------------------------------------------------------------------
  110   CONTINUE
  WRITE(6,'(/a/)') ' Error reading data in HDFREAD'
  ireturn=1
  130   CONTINUE
  CALL hdfclose
(sd_id,istat)
  IF (ireturn == 0) THEN
    IF (istat == 0) THEN
      WRITE(6,'(/a/a)') &
      "HDFREADWIND: Successfully read ", trim(filename)
    ELSE
      WRITE(6,'(/a,i3,a/,a)') &
      "HDFREADWIND: ERROR (status=", istat, ") closing ", trim(filename)
    END IF
  END IF
  RETURN
END SUBROUTINE hdfreadxyz
SUBROUTINE cal_xvort(v,w,y,zp,nx,ny,nz, xvort)
!
! Rewritten (DTD 10-10-05) to include terrain-following case
!
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: xvort(nx,ny,nz)
  REAL :: v(nx,ny,nz), w(nx,ny,nz)
  REAL :: y(ny),zp(nx,ny,nz)
  REAL :: zweightl,zweightr,zs(nx,ny,nz)
  REAL :: ws(nx,ny,nz),wr,wl
  REAL :: dwdy, dvdz
 
  INTEGER :: i,j,k,kl,k1,k2
  REAL :: factor
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!  
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  DO j=2,ny-2
    DO i=1,nx-1
      DO k=2,nz-2
        ! Determine value of z and w at center scalar point
        zs(i,j,k)=0.5*(zp(i,j,k)+zp(i,j,k+1))
        ws(i,j,k)=0.5*(w(i,j,k)+w(i,j,k+1))
      END DO
    END DO
  END DO
  DO j=2,ny-2
    DO i=1,nx-1
      DO k=2,nz-2
        k1=k
        k2=k
        ! Determine k levels for vertical interpolation on either side of center point        
        IF(zs(i,j,k) < zp(i,j-1,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i,j-1,k1))
            k1=k1-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i,j-1,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i,j-1,k1+1))
            k1=k1+1
          END DO
        END IF
        
        IF(zs(i,j,k) < zp(i,j+1,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i,j+1,k2))
            k2=k2-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i,j+1,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i,j+1,k2+1))
            k2=k2+1
          END DO
        END IF
        ! Precalculate left-side and right-side interpolated w values
        IF(k1 >= 2 .and. k1 <= nz-2) THEN
          zweightl=(zs(i,j,k)-zp(i,j-1,k1))/(zp(i,j-1,k1+1)-zp(i,j-1,k1))
          wl=(1.0-zweightl)*zp(i,j-1,k1)+zweightl*zp(i,j-1,k1+1)
        END IF
        IF(k2 >= 2 .and. k2 <= nz-2) THEN
          zweightr=(zs(i,j,k)-zp(i,j+1,k2))/(zp(i,j+1,k2+1)-zp(i,j+1,k2))
          wr=(1.0-zweightr)*zp(i,j+1,k2)+zweightr*zp(i,j+1,k2+1)
        END IF
        
        if( k == 2 ) then
          kl = 2
          factor = 2.0
        else
          kl = k-1
          factor = 1.0
        endif
         
        ! Make sure the k levels are not below ground or above the model top
        IF((k1 < 2 .and. k2 < 2) .or. (k1 > nz-2 .and. k2 > nz-2)) THEN
          ! No calculation can be performed!  Set vorticity to zero at this point.
          xvort(i,j,k) = 0.0
        ELSE IF(k1 < 2) THEN       ! Do a right-sided difference
          dwdy=(wr-ws(i,j,k))/(y(j+1)-y(j))
        ELSE IF(k2 < 2) THEN       ! Do a left-sided difference
          dwdy=(ws(i,j,k)-wl)/(y(j)-y(j-1))
        ELSE                  ! Do a normal centered difference
          dwdy=(wr-wl)/(y(j+1)-y(j-1))
        END IF
        if( k == 2 ) then
          kl = 2
          factor = 2.0
        else
          kl = k-1
          factor = 1.0
        endif
        ! Calculate dvdz (there will be some error here due to assumption of uniform grid in the vertical)
        dvdz=0.25*factor*(v(i,j,k+1)+v(i,j+1,k+1)-v(i,j,kl )-v(i,j+1,kl ))/(zs(i,j,k+1)-zs(i,j,k))
        ! Calculate xvort
        xvort(i,j,k)=dwdy-dvdz
      END DO  
    END DO
  END DO 
  DO  k=2,nz-2
    DO i=1,nx-1
      xvort(i,   1,k)=xvort(i,   2,k)
      xvort(i,ny-1,k)=xvort(i,ny-2,k)
    END DO
  END DO
  DO j=1,ny-1
    DO i=1,nx-1
      xvort(i,j,   1)=xvort(i,j,   2)
      xvort(i,j,nz-1)=xvort(i,j,nz-2)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_xvort
SUBROUTINE cal_yvort(u,w,x,zp,nx,ny,nz, yvort)
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: yvort(nx,ny,nz)
  REAL :: zp(nx,ny,nz)
  REAL :: u(nx,ny,nz), w(nx,ny,nz)
  REAL :: x(ny),zs(nx,ny,nz)
  REAL :: wl,wr,ws(nx,ny,nz)
  REAL :: dwdx,dudz,zweightl,zweightr
  INTEGER :: k1,k2
  INTEGER :: i,j,k, kl
  REAL :: factor
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  DO j=1,ny-1
    DO i=2,nx-2
      DO k=2,nz-2
        ! Determine value of z and w at center scalar point
        zs(i,j,k)=0.5*(zp(i,j,k)+zp(i,j,k+1))
        ws(i,j,k)=0.5*(w(i,j,k)+w(i,j,k+1))
      END DO
    END DO
  END DO
  DO j=1,ny-1
    DO i=2,nx-2
      DO k=2,nz-2
        k1=k
        k2=k
        ! Determine k levels for vertical interpolation on either side of center point        
        IF(zs(i,j,k) < zp(i-1,j,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i-1,j,k1))
            k1=k1-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i-1,j,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i-1,j,k1+1))
            k1=k1+1
          END DO
        END IF
        IF(zs(i,j,k) < zp(i+1,j,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i+1,j,k2))
            k2=k2-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i+1,j,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i+1,j,k2+1))
            k2=k2+1
          END DO
        END IF
        ! Precalculate left-side and right-side interpolated w values
        IF(k1 >= 2 .and. k1 <= nz-2) THEN
          zweightl=(zs(i,j,k)-zp(i-1,j,k1))/(zp(i-1,j,k1+1)-zp(i-1,j,k1))
          wl=(1.0-zweightl)*zp(i-1,j,k1)+zweightl*zp(i-1,j,k1+1)
        END IF
        IF(k2 >= 2 .and. k2 <= nz-2) THEN
          zweightr=(zs(i,j,k)-zp(i+1,j,k2))/(zp(i+1,j,k2+1)-zp(i+1,j,k2))
          wr=(1.0-zweightr)*zp(i+1,j,k2)+zweightr*zp(i+1,j,k2+1)
        END IF
        if( k == 2 ) then
          kl = 2
          factor = 2.0
        else
          kl = k-1
          factor = 1.0
        endif
        ! Make sure the k levels are not below ground or above the model top
        IF((k1 < 2 .and. k2 < 2) .or. (k1 > nz-2 .and. k2 > nz-2)) THEN
          ! No calculation can be performed!  Set vorticity to zero at this point.
          yvort(i,j,k) = 0.0
        ELSE IF(k1 < 2) THEN       ! Do a right-sided difference
          dwdx=(wr-ws(i,j,k))/(x(i+1)-x(i))
        ELSE IF(k2 < 2) THEN       ! Do a left-sided difference
          dwdx=(ws(i,j,k)-wl)/(x(i)-x(i-1))
        ELSE                  ! Do a normal centered difference
          dwdx=(wr-wl)/(x(i+1)-x(i-1))
        END IF
        if( k == 2 ) then
          kl = 2
          factor = 2.0
        else
          kl = k-1
          factor = 1.0
        endif
        ! Calculate dudz
        dudz=0.25*factor*(u(i,j,k+1)+u(i+1,j,k+1)-u(i,j,kl)-u(i+1,j,kl))/(zs(i,j,k+1)-zs(i,j,k))
        ! Calculate xvort
        yvort(i,j,k)=dudz-dwdx
      END DO
    END DO
  END DO
  DO  k=2,nz-2
    DO j=1,ny-1
      yvort(   1,j,k)=yvort(   2,j,k)
      yvort(nx-1,j,k)=yvort(nx-2,j,k)
    END DO
  END DO
  DO j=1,ny-1
    DO i=1,nx-1
      yvort(i,j,   1)=yvort(i,j,   2)
      yvort(i,j,nz-1)=yvort(i,j,nz-2)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_yvort
!
!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROUTINES cal_zvort                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Calculate Vort*10^5 (1/s) value.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Min Zou
!  3/2/98
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
SUBROUTINE cal_zvort(u,v,x,y,nx,ny,nz,zvort,zp)
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: zvort(nx,ny,nz),zp(nx,ny,nz)
  REAL :: u(nx,ny,nz), v(nx,ny,nz)
  REAL :: x(nx), y(ny)
  INTEGER :: kw, ke, ks, kn
  REAL :: zs(nx,ny,nz)
  REAL :: us(nx,ny,nz),vs(nx,ny,nz)
  REAL :: viw,vie,uin,uis,zweightw,zweighte,zweightn,zweights
  REAL :: dudy,dvdx
 
  INTEGER :: i,j,k
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  ! Precalculate z, u, and v, at the scalar points
  DO j=2,ny-2
    DO i=2,nx-2
      DO k=2,nz-2
        zs(i,j,k)=0.5*(zp(i,j,k)+zp(i,j,k+1))
        us(i,j,k)=0.5*(u(i+1,j,k)+u(i,j,k))
        vs(i,j,k)=0.5*(v(i,j+1,k)+v(i,j,k))
      END DO
    END DO
  END DO
  DO j=2,ny-2
    DO i=2,nx-2
      DO k=2,nz-2
        kw=k
        ke=k
        ks=k
        kn=k
    
        ! Determine k levels for vertical interpolation of u and v on either side of center point        
        IF(zs(i,j,k) < zp(i-1,j,k)) THEN  
          DO WHILE (zs(i,j,k) < zp(i-1,j,kw))
            kw=kw-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i-1,j,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i-1,j,kw+1))
            kw=kw+1
          END DO
        END IF
        IF(zs(i,j,k) < zp(i+1,j,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i+1,j,ke))
            ke=ke-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i+1,j,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i+1,j,ke+1))
            ke=ke+1
          END DO
        END IF
        IF(zs(i,j,k) < zp(i,j-1,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i,j-1,ks))
            ks=ks-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i,j-1,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i,j-1,ks+1))
            ks=ks+1
          END DO
        END IF
        IF(zs(i,j,k) < zp(i,j+1,k)) THEN
          DO WHILE (zs(i,j,k) < zp(i,j+1,kn))
            kn=kn-1
          END DO
        ELSE IF(zs(i,j,k) > zp(i,j+1,k+1)) THEN
          DO WHILE (zs(i,j,k) > zp(i,j+1,kn+1))
            kn=kn+1
          END DO
        END IF
        ! Precalculate vertically-interpolated u and v values
        IF(kw >= 2 .and. kw <= nz-2) THEN
          zweightw=(zs(i,j,k)-zp(i-1,j,kw))/(zp(i-1,j,kw+1)-zp(i-1,j,kw))
          viw=(1.0-zweightw)*vs(i-1,j,kw)+zweightw*vs(i-1,j,kw+1)
        END IF
        IF(ke >= 2 .and. ke <= nz-2) THEN
          zweighte=(zs(i,j,k)-zp(i+1,j,ke))/(zp(i+1,j,ke+1)-zp(i+1,j,ke))
          vie=(1.0-zweighte)*vs(i+1,j,ke)+zweighte*vs(i,j,ke+1)
        END IF
        IF(ks >= 2 .and. ks <= nz-2) THEN
          zweights=(zs(i,j,k)-zp(i,j-1,ks))/(zp(i,j-1,ks+1)-zp(i,j-1,ks))
          uis=(1.0-zweights)*us(i,j-1,ks)+zweights*us(i,j-1,ks+1)
        END IF
        IF(kn >= 2 .and. kn <= nz-2) THEN
          zweightn=(zs(i,j,k)-zp(i,j+1,kn))/(zp(i,j+1,kn+1)-zp(i,j+1,kn))
          uin=(1.0-zweightn)*us(i,j+1,kn)+zweightn*us(i,j+1,kn+1)
        END IF
        ! Make sure the k levels are not below ground or above the model top and calculate dudy and dvdx
        IF((ks < 2 .and. kn < 2) .or. (ks > nz-2 .and. kn > nz-2)) THEN          
          dudy = 0.0
        ELSE IF(ks < 2) THEN       ! Do a right-sided difference
          dudy=(uin-us(i,j,k))/(y(j+1)-y(j))
        ELSE IF(kn < 2) THEN       ! Do a left-sided difference
          dudy=(us(i,j,k)-uis)/(y(j)-y(j-1))
        ELSE                  ! Do a normal centered difference
          dudy=(uin-uis)/(y(j+1)-y(j-1))
        END IF
        IF((kw < 2 .and. ke < 2) .or. (kw > nz-2 .and. ke > nz-2)) THEN
          dvdx = 0.0
        ELSE IF(kw < 2) THEN       ! Do a right-sided difference
          dvdx=(vie-vs(i,j,k))/(x(i+1)-x(i))
        ELSE IF(ke < 2) THEN       ! Do a left-sided difference
          dvdx=(vs(i,j,k)-viw)/(x(i)-x(i-1))
        ELSE                  ! Do a normal centered difference
          dvdx=(vie-viw)/(x(i+1)-x(i-1))
        END IF
        ! Finally, calculate the vorticity
        zvort(i,j,k)=dvdx-dudy
     END DO
   END DO
  END DO
  DO j=2,ny-2
    DO i=2,nx-2
      zvort(i,j,   1)=zvort(i,j,   2)
      zvort(i,j,nz-1)=zvort(i,j,nz-2)
    END DO
  END DO
  DO k=1,nz-1
    DO j=2,ny-2
      zvort(   1,j,k)=zvort(   2,j,k)
      zvort(nx-1,j,k)=zvort(nx-2,j,k)
    END DO
  END DO
  DO  k=1,nz-1
    DO i=1,nx-1
      zvort(i,   1,k)=zvort(i,   2,k)
      zvort(i,ny-1,k)=zvort(i,ny-2,k)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_zvort
SUBROUTINE cal_xvort_flat(v,w,y,zp,nx,ny,nz, xvort) 1
!
! Only valid for Cartesian grid, flat terrain case
!
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: xvort(nx,ny,nz)
  REAL :: v(nx,ny,nz), w(nx,ny,nz)
  REAL :: y(ny),zp(nx,ny,nz)
  INTEGER :: i,j,k,kl
  REAL :: factor
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  DO k=2,nz-2
    if( k == 2 ) then
      kl = 2
      factor = 2.0
    else
      kl = k-1
      factor = 1.0
    endif
    DO  j=2,ny-2
      DO  i=1,nx-1
        xvort(i,j,k)=0.25*(                                                &
         (w(i,j+1,k)+w(i,j+1,k+1)-w(i,j-1,k)-w(i,j-1,k+1))/(y(j+1)-y(j))   &
 -factor*(v(i,j,k+1)+v(i,j+1,k+1)-v(i,j,kl )-v(i,j+1,kl ))/(zp(i,j,k+1)-zp(i,j,k)) )
      END DO
    END DO
  END DO
  DO  k=2,nz-2
    DO i=1,nx-1
      xvort(i,   1,k)=xvort(i,   2,k)
      xvort(i,ny-1,k)=xvort(i,ny-2,k)
    END DO
  END DO
  DO j=1,ny-1
    DO i=1,nx-1
      xvort(i,j,   1)=xvort(i,j,   2)
      xvort(i,j,nz-1)=xvort(i,j,nz-2)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_xvort_flat
SUBROUTINE cal_yvort_flat(u,w,x,zp,nx,ny,nz, yvort) 1
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: yvort(nx,ny,nz)
  REAL :: u(nx,ny,nz), w(nx,ny,nz)
  REAL :: x(ny),zp(nx,ny,nz)
  INTEGER :: i,j,k, kl
  REAL :: factor
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  DO k=2,nz-2
    if( k == 2 ) then
      kl = 2
      factor = 2.0
    else
      kl = k-1
      factor = 1.0
    endif
    DO  j=1,ny-1
      DO  i=2,nx-2
        yvort(i,j,k)=0.25*(                                                &
        -(w(i+1,j,k)+w(i+1,j,k+1)-w(i-1,j,k)-w(i-1,j,k+1))/(x(i+1)-x(i))   &
 +factor*(u(i,j,k+1)+u(i+1,j,k+1)-u(i,j,kl )-u(i+1,j,kl ))   &
        /(zp(i,j,k+1)-zp(i,j,k)) )
      END DO
    END DO
  END DO
  DO  k=2,nz-2
    DO j=1,ny-1
      yvort(   1,j,k)=yvort(   2,j,k)
      yvort(nx-1,j,k)=yvort(nx-2,j,k)
    END DO
  END DO
  DO j=1,ny-1
    DO i=1,nx-1
      yvort(i,j,   1)=yvort(i,j,   2)
      yvort(i,j,nz-1)=yvort(i,j,nz-2)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_yvort_flat
!
!
!##################################################################
!##################################################################
!######                                                      ######
!######                 SUBROUTINES cal_zvort_flat           ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Calculate Vort*10^5 (1/s) value.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: Min Zou
!  3/2/98
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
SUBROUTINE cal_zvort_flat(u,v,x,y,nx,ny,nz,zvort) 1
  IMPLICIT NONE
  INTEGER :: nx,ny,nz
  REAL :: zvort(nx,ny,nz)
  REAL :: u(nx,ny,nz), v(nx,ny,nz)
  REAL :: x(nx), y(ny)
  INTEGER :: i,j,k
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  DO k=2,nz-2
    DO  j=2,ny-2
      DO  i=2,nx-2
        zvort(i,j,k)= (                                            &
               (v(i+1,j,k)-v(i-1,j,k)+v(i+1,j+1,k)-v(i-1,j+1,k))/       &
               (4*(x(i+1)-x(i)))-                                       &
               (u(i,j+1,k)-u(i,j-1,k)+u(i+1,j+1,k)-u(i+1,j-1,k))/       &
               (4*(y(j+1)-y(j))) )
      END DO
    END DO
  END DO
  DO j=2,ny-2
    DO i=2,nx-2
      zvort(i,j,   1)=zvort(i,j,   2)
      zvort(i,j,nz-1)=zvort(i,j,nz-2)
    END DO
  END DO
  DO k=1,nz-1
    DO j=2,ny-2
      zvort(   1,j,k)=zvort(   2,j,k)
      zvort(nx-1,j,k)=zvort(nx-2,j,k)
    END DO
  END DO
  DO  k=1,nz-1
    DO i=1,nx-1
      zvort(i,   1,k)=zvort(i,   2,k)
      zvort(i,ny-1,k)=zvort(i,ny-2,k)
    END DO
  END DO
  RETURN
END SUBROUTINE cal_zvort_flat
!