subroutine horout(array,
     &                  artype,yrflag,time3,iexpt,lhycom,
     &                  name,namec,units, k,ltheta, frmt,io,
     &                  fdate, verfhour)
      use mod_plot ! HYCOM I/O interface
      use mod_xc   ! HYCOM communication API
      use mod_zb   ! HYCOM I/O interface for subregion
      use netcdf   ! NetCDF fortran 90 interface
      implicit none
      include  "grib_block.h"
      include  "locale.inc"
      include  "clib.inc"
      
c
      character*(*)    name,namec,units,frmt
      logical          lhycom,ltheta,lexist
      integer          artype,yrflag,iexpt,k,io,gridlabel
      integer	       ierr
      character*1      grib1
      integer  fdate(4)           ! yyyy, mm, dd, hh of forecast run
      integer  verfhour           ! verifying hour/lead
      INTEGER, save :: ibms = 1
      character*80 fname

      double precision time3(3)
      real             array(ii,jj),thetak
      CHARACTER *1 grib
      real, parameter :: flag = 2.0**100
c     real, parameter :: flag = -1.E30
c
c     write out array to unit io based on frmt.
c
c     array size and frmt        must be identical in all calls.
c     artype,yrflag,time3,lhycom must be identical in all calls.
c
c     the output filename is taken from environment variable FOR0xx,
c      where  xx = io, with default fort.xx.
c     the array  filename is taken from environment variable FORxxxA,
c      where xxx = io, with default fort.xxxa
c     the NetCDF filename is taken from environment variable CDFxxx,
c      where xxx = io, with no default.
c     the NetCDF title and institution are taken from environment
c      variables CDF_TITLE and CDF_INST.
c
c     Supported I/O types are:
c       frmt=='NetCDF'        for NetCDF I/O,
c       frmt=='netCDF'        for NetCDF I/O,
c       frmt=='HYCOM'         for HYCOM .[ab] I/O,
c       frmt=='BIN'           for unformatted sequential I/O,
c       frmt=='(...)'         for   formatted sequential I/O with format frmt.< c       frmt=='(2f10.4,...)'  for   formatted sequential I/O of the form
c                                   longitude latitude value (skipping land)
c       frmt=='GRIB1'         for GRIB1 format
c       frmt=='grib1'         for GRIB1 format
c
c     This version supports frmt=='netCDF' and needs 
c     version 3.5 of the NetCDF library, from: 
c     http://www.unidata.ucar.edu/packages/netcdf/
c
      integer          :: ncfileID, status, varID
      integer          :: pLatDimID,pLonDimID,pLatVarID,pLonVarID
      integer          :: pYDimID,pXDimID,pYVarID,pXVarID
      integer          :: MTDimID,MTVarID,datVarID
      character        :: ncfile*240,ncenv*240
      character        :: Ename*6
c
      logical          :: lopen
      integer          :: i,j,l,iyear,month,iday,ihour
      real             :: hmin,hmax
      double precision :: dt,dt0,year
c
      character*81,     save :: label   = ' '
      integer,          save :: iotype  = -1
      double precision, save :: date    = 0.d0
      double precision, save :: cell    = 0.d0
      logical,          save :: laxis
      real,        parameter :: fill_value = 2.0**100
c
      character cmonth(12)*3
      data      cmonth/'jan','feb','mar','apr','may','jun',
     &                 'jul','aug','sep','oct','nov','dec'/
c
      if     (iotype.eq.-1) then
c
c        initialization.
c
        l = len_trim(frmt)
        if     (frmt(1:l).eq.'HYCOM')  then
c
c         HYCOM .[ab] I/O.
c
          call zbiost(ii,jj)
          iotype = 1
          write(lp,'(/a/)') 'horout - HYCOM I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'BIN')    then
c
c         unformatted sequential I/O.
c
          iotype = 2
          write(lp,'(/a/)') 'horout - unformatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:8).eq.'(2f10.4,' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O (lon lat value).
c
          iotype = -3
          write(lp,'(/a,a/)') 'horout - formatted sequential I/O',
     &                        ' (longitude latitude value)'
          call flush(lp)
        elseif (frmt(1:1).eq.'(' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O.
c
          iotype = 3
          write(lp,'(/a/)') 'horout - formatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'netCDF' .or.
     &          frmt(1:l).eq.'NetCDF'     ) then
c
c         NetCDF I/O.
c
          laxis = .true.
          do i= 2,ii
            laxis = laxis .and. 
     &              maxval(abs(plat(1,:)-plat(i,:))).le.1.e-2
          enddo
          do j= 2,jj
            laxis = laxis .and. 
     &              maxval(abs(plon(:,1)-plon(:,j))).le.1.e-2
          enddo
c
          iotype = 4
          if     (laxis) then
            write(lp,'(/2a/)') 'horout - NetCDF I/O (lat/lon axes)'
          else
            write(lp,'(/2a/)') 'horout - NetCDF I/O (curvilinear)'
          endif
          call flush(lp)
        elseif (frmt(1:l).eq.'grib1' .or.
     &         frmt(1:l).eq.'GRIB1') then
c
c         grib-1 format
c
          iotype = 5
          laxis = .false.
          write(lp,'(/a,a/)') 'horout - grib-1 I/O'
          call flush(lp)

        else
c
c         unknown I/O type.
c
          write(lp,'(/a)')   'error in horout - unknown I/O type'
          write(lp,'(3a)')   'frmt   = "', frmt(1:len_trim( frmt)),'"'
          write(lp,'(a,i4)') 'io     = ',io
          call flush(lp)
          stop 9
        endif
c
c       initialize label.
c
        if     (yrflag.eq.0) then
          year  = 360.0d0
        elseif (yrflag.lt.3) then
          year  = 366.0d0
        else
          year  = 365.25d0
        endif
        call fordate(time3(3),yrflag, iyear,month,iday,ihour)
        date    = (iday + 100 * month + 10000 * iyear) +
     &            (time3(3)-int(time3(3)))
        if     (artype.eq.1) then
          if     (yrflag.lt.3) then
            write (label(51:72),112) time3(3)/year,cmonth(month),iday
          else
            write (label(51:72),113) cmonth(month),iday,iyear
          endif
        else  ! mean or sdev archive
          write(lp,*) 'time3 = ',time3
          dt = 0.5*(time3(2)-time3(1))/(nstep-1)
          if     (yrflag.eq.0) then
            dt0 = 15.0
          elseif (yrflag.eq.1) then
            dt0 = 15.25
          elseif (yrflag.eq.2) then
            dt0 = 0.0
          else
            dt0 = 0.0
          endif
          cell = (time3(2)+dt+dt0) - (time3(1)-dt+dt0)
          if     (artype.eq.2) then
            write(label(51:72),114) ' mean: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          else
            write(label(51:72),114) ' sdev: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          endif
        endif
        if (lhycom) then
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'H'
        else
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'M'
        endif
 112    format ('  year',f7.2,' (',a3,i3.2,')')
 113    format ('  date: ',a3,i3.2,',',i5,'  ')
 114    format (a7,f7.2,'-',f7.2)
 115    format (' [',i2.2,'.',i1.1,a1,']')
      endif  !initialization
c
c     complete the label
c
      if     (k.eq.0) then
        label(33:50)=name
      elseif (ltheta) then
        write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
      else
        write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
      endif
c
      if     (iotype.eq.1) then
c
c       HYCOM .[ab] I/O.
c
        call zbiopi(lopen, io)
        if     (.not.lopen) then
          call zbiopn('new', io)
          call zhopen(io, 'formatted', 'new', 0)
        endif
        call zbiowr(array, ip,.false., hmin,hmax, io, .false.)
        write(io,'(a,a,2g15.6)') label(33:81),':',hmin,hmax
        call flush(io)
        write(lp,'(a,a,2g15.6)') label(33:81),':',hmin,hmax
        call flush(lp)
      elseif (iotype.eq.2) then
c
c       unformatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'unformatted', 'new', 0)
        endif
        write(io) array
        call flush(io)
        write(lp,'(a)') label(33:81)
        call flush(lp)
      elseif (iotype.eq.-3) then
c
c       formatted sequential I/O (lon lat value)
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        do j= 1,jj
          do i= 1,ii
            if     (array(i,j).ne.fill_value) then
              write(io,frmt) plon(i,j),plat(i,j),array(i,j)
            endif
          enddo
        enddo
        call flush(io)
        write(lp,'(a)') label(33:81)
        call flush(lp)
      elseif (iotype.eq.3) then
c
c       formatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        write(io,frmt) array
        call flush(io)
        write(lp,'(a)') label(33:81)
        call flush(lp)
      elseif (iotype.eq.4) then
c
c       NetCDF I/O
c
        write(Ename,'(a3,i3.3)') 'CDF',io
        ncfile = ' '
        call getenv(Ename,ncfile)
        write(*,*) 'ncfile ',ncfile
        if     (ncfile.eq.' ') then
          write(lp,'(/3a/)') 'error in horout_nc- ',Ename,' not defined'
          call flush(lp)
          stop 9
        endif
c
        call ncrange(array,ii,jj,1, fill_value, hmin,hmax)
c
        inquire(file= ncfile, exist=lexist)
        if (.not.lexist) then
c
c          create a new NetCDF and write data to it
c
          call ncheck(nf90_create(trim(ncfile),nf90_noclobber,ncfileID))
          ! define the dimensions
          call ncheck(nf90_def_dim(ncfileID,
     &                             "MT", nf90_unlimited,MTDimID))
          if     (laxis) then
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Latitude",  jj,pLatDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Longitude", ii,pLonDimID))
          else
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Y",         jj,pYDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "X",         ii,pXDimID))
          endif
          ! create the global attributes
          call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                             "Conventions",
     &                             "CF-1.0"))
          if (lhycom) then
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "HYCOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            if     (artype.eq.1) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM archive file"))
            elseif (artype.eq.2) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM mean archive file"))
            else
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM std. archive file"))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archv2ncdf2d"))
          else
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "MICOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               "MICOM"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "source",
     &                               "MICOM archive file"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archm2ncdf2d"))
          endif
          ! create the variables and attributes
          call ncheck(nf90_def_var(ncfileID,"MT",  nf90_double,
     &                             MTDimID,MTVarID))
          if     (yrflag.eq.0) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-16 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "360_day"))
          elseif (yrflag.eq.1) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-16 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          elseif (yrflag.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-01 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          else
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 1900-12-31 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "standard"))
          endif
          call ncheck(nf90_def_var(ncfileID,"Date", nf90_double,
     &                             MTDimID,datVarID))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "long_name",
     &                             "date"))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "units",
     &                             "day as %Y%m%d.%f"))
          if     (artype.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          elseif (artype.eq.3) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          endif
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               pLatDimID,pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            if     (abs((plat(1,jj)-plat(1,1))-
     &                  (plat(1, 2)-plat(1,1))*(jj-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               pLonDimID,pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)-plon(1,1))-
     &                  (plon( 2,1)-plon(1,1))*(ii-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          else
            call ncheck(nf90_def_var(ncfileID,"Y", nf90_int,
     &                               pYDimID,pYVarID))
            call ncheck(nf90_put_att(ncfileID,pYVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"X", nf90_int,
     &                               pXDimID,pXVarID))
            call ncheck(nf90_put_att(ncfileID,pXVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               (/pXDimID, pYDimID/), pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               (/pXDimID, pYDimID/), pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          endif
          ! model 2d variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,   MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin, hmax/)))
          call ncheck(nf90_put_att(ncfileID,varID,"units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               label(33:50)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               label(33:55)//label(73:81)))
          endif
          ! leave def mode
          call ncheck(nf90_enddef(ncfileID))
          ! write data into coordinate variables
          call ncheck(nf90_put_var(ncfileID,MTVarID,time3(3)))
          call ncheck(nf90_put_var(ncfileID,datVarID,date   ))
          if     (laxis) then
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(1,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,1)))
          else
            call ncheck(nf90_put_var(ncfileID,pYVarID,
     &                               (/(j, j=1,jj)/)))
            call ncheck(nf90_put_var(ncfileID,pXVarID,
     &                               (/(i, i=1,ii)/)))
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(:,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,:)))
          endif
          ! write to model variable
          call ncheck(nf90_put_var(ncfileID,varID,array(:,:)))
          ! close NetCDF file
          call ncheck(nf90_close(ncfileID))
        else
c
c          Write data to existing NetCDF file
c
          ! open NetCDF file
          call ncheck(nf90_open(trim(ncfile), nf90_write, ncfileID))
          ! get dimension ID's
          call ncheck(nf90_inq_dimid(ncfileID,"MT",MTDimID))
          if     (laxis) then
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Latitude",pLatDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Longitude",pLonDimID))
          else
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Y",        pYDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "X",        pXDimID))
          endif
          ! switch to define mode
          call ncheck(nf90_redef(ncfileID))
          ! define new variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,   MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin, hmax/)))
          call ncheck(nf90_put_att(ncfileID,varID,"units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               label(33:50)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               label(33:55)//label(73:81)))
          endif
          ! leave define mode
          call ncheck(nf90_enddef(ncfileID))
          ! get varID and write to array
          call ncheck(nf90_inq_varid(ncfileID,trim(namec),varID))
          !write values into array
          call ncheck(nf90_put_var(ncfileID,varID,array(:,:)))
          ! close file 
          call ncheck(nf90_close(ncfileID))
        endif
        write(lp,'(a,a,2g15.6)') label(33:81),':',hmin,hmax
        call flush(lp)
      elseif (iotype.eq.5) then
c
c       grib-1 I/O
c
         call open_unit(io,frmt)

         read(22,*) gridlabel
         rewind(22)
         print *,'calling 1ab2grib for ',name, namec, k
         call ab2grib ( array, ii,jj,
     &        fdate(1),fdate(2),fdate(3),fdate(4),verfhour,
     &        flag,ibms,namec,k,0,0.0,gridlabel)


      else
c
c       should never get here.
c
        write(lp,'(/a)')   'error in horout - inconsistent call'
        write(lp,'(3a)')   'label  = "',label(33:len_trim(label)),'"'
        write(lp,'(3a)')   'frmt   = "', frmt( 1:len_trim( frmt)),'"'
        write(lp,'(a,i4)') 'io     = ',io
        write(lp,'(a,i4)') 'iotype = ',iotype
        call flush(lp)
        stop 9
      endif
      return
      end

      subroutine horout_3d(array,
     &                     artype,yrflag,time3,iexpt,lhycom,
     &                     name,namec,units, kf,kl,ltheta, frmt,io,
     &                     fdate,verfhour)
      use mod_plot ! HYCOM I/O interface
      use mod_xc   ! HYCOM communication API
      use mod_zb   ! HYCOM I/O interface for subregion
      use netcdf   ! NetCDF Interface
      
      implicit none
      include  "grib_block.h"
      include  "locale.inc"
      include  "clib.inc"
      integer  fdate(4)           ! yyyy, mm, dd, hh of forecast run
      integer  verfhour           ! verifying hour/lead
      INTEGER, save :: ibms = 1
      character*1 grib1
      integer	       ierr
      character*80 fname

c
      character*(*)    name,namec,units,frmt
      logical          lhycom,ltheta,lexist
      integer          artype,yrflag,iexpt,kf,kl,io,gridlabel
      double precision time3(3)
      real             array(ii,jj,kl),thetak
      real, parameter :: flag = 2.0**100
c
c     write out a 3-d layer array to unit io based on frmt.
c
c     2-d array size and frmt    must be identical in all calls.
c     artype,yrflag,time3,lhycom must be identical in all calls.
c
c     the output filename is taken from environment variable FOR0xx,
c      where  xx = io, with default fort.xx.
c     the array  filename is taken from environment variable FORxxxA,
c      where xxx = io, with default fort.xxxa
c     the NetCDF filename is taken from environment variable CDFxxx,
c      where xxx = io, with no default.
c     the NetCDF title and institution are taken from environment
c      variables CDF_TITLE and CDF_INST.
c
c     Supported I/O types are:
c       frmt=='NetCDF'        for NetCDF I/O,
c       frmt=='netCDF'        for NetCDF I/O,
c       frmt=='HYCOM'         for HYCOM .[ab] I/O,
c       frmt=='BIN'           for unformatted sequential I/O,
c       frmt=='(...)'         for   formatted sequential I/O with format frmt.< c       frmt=='(2f10.4,...)'  for   formatted sequential I/O of the form
c                                   longitude latitude value (skipping land)
c
c       frmt=='GRIB1'         for GRIB1 format
c       frmt=='grib1'         for GRIB1 format
c
c     This version supports frmt=='netCDF' and needs 
c     version 3.5 of the NetCDF library, from: 
c     http://www.unidata.ucar.edu/packages/netcdf/
c
      integer          :: ncfileID, status, varID
      integer          :: pLatDimID,pLonDimID,pLatVarID,pLonVarID,
     &                    lyrDimID,lyrVarID
      integer          :: pYDimID,pXDimID,pYVarID,pXVarID
      integer          :: MTDimID,MTVarID,datVarID
      character        :: ncfile*240,ncenv*240
      character        :: Ename*6
c
      logical          :: lopen
      integer          :: i,j,k,l,iyear,month,iday,ihour
      real             :: hmin(999),hmax(999)
      double precision :: dt,dt0,year
c
      character*81,     save :: label   = ' '
      integer,          save :: iotype  = -1
      double precision, save :: date    = 0.d0
      double precision, save :: cell    = 0.d0
      logical,          save :: laxis
      real,        parameter :: fill_value = 2.0**100
c
      character cmonth(12)*3
      data      cmonth/'jan','feb','mar','apr','may','jun',
     &                 'jul','aug','sep','oct','nov','dec'/
c
      if     (iotype.eq.-1) then
c
c        initialization.
c
        l = len_trim(frmt)
        if     (frmt(1:l).eq.'HYCOM')  then
c
c         HYCOM .[ab] I/O.
c
          call zbiost(ii,jj)
          iotype = 1
          write(lp,'(/a/)') 'horout_3d - HYCOM I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'BIN')    then
c
c         unformatted sequential I/O.
c
          iotype = 2
          write(lp,'(/a/)') 'horout_3d - unformatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:8).eq.'(2f10.4,' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O (lon lat value).
c
          iotype = -3
          write(lp,'(/a,a/)') 'horout - formatted sequential I/O',
     &                        ' (longitude latitude value)'
          call flush(lp)
        elseif (frmt(1:1).eq.'(' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O.
c
          iotype = 3
          write(lp,'(/a/)') 'horout_3d - formatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'netCDF' .or. 
     &          frmt(1:l).eq.'NetCDF'     ) then
c
c         NetCDF I/O.
c
          laxis = .true.
          do i= 2,ii
            laxis = laxis .and. 
     &              maxval(abs(plat(1,:)-plat(i,:))).le.1.e-2
          enddo
          do j= 2,jj
            laxis = laxis .and. 
     &              maxval(abs(plon(:,1)-plon(:,j))).le.1.e-2
          enddo
c
          iotype = 4
          if     (laxis) then
            write(lp,'(/2a/)') 'horout_3d - NetCDF I/O (lat/lon axes)'
          else
            write(lp,'(/2a/)') 'horout_3d - NetCDF I/O (curvilinear)'
          endif
          call flush(lp)
        elseif (frmt(1:l).eq.'grib1' .or.
     &          frmt(1:l).eq.'GRIB1') then
c
c         grib-1 format
c
          iotype = 5
          laxis = .false.
          write(lp,'(/a,a/)') 'horout - grib-1 I/O'
          call flush(lp)


        else
c
c         unknown I/O type.
c
          write(lp,'(/a)')   'error in horout_3d - unknown I/O type'
          write(lp,'(3a)')   'frmt   = "', frmt(1:len_trim( frmt)),'"'
          write(lp,'(a,i4)') 'io     = ',io
          call flush(lp)
          stop 9
        endif
c
c       initialize label.
c
        if     (yrflag.eq.0) then
          year  = 360.0d0
        elseif (yrflag.lt.3) then
          year  = 366.0d0
        else
          year  = 365.25d0
        endif
        call fordate(time3(3),yrflag, iyear,month,iday,ihour)
        date    = (iday + 100 * month + 10000 * iyear) +
     &            (time3(3)-int(time3(3)))
        if     (artype.eq.1) then
          if     (yrflag.lt.3) then
            write (label(51:72),112) time3(3)/year,cmonth(month),iday
          else
            write (label(51:72),113) cmonth(month),iday,iyear
          endif
        else  ! mean or sdev archive
          write(lp,*) 'time3 = ',time3
          dt = 0.5*(time3(2)-time3(1))/(nstep-1)
          if     (yrflag.eq.0) then
            dt0 = 15.0
          elseif (yrflag.eq.1) then
            dt0 = 15.25
          elseif (yrflag.eq.2) then
            dt0 = 0.0
          else
            dt0 = 0.0
          endif
          cell = (time3(2)+dt+dt0) - (time3(1)-dt+dt0)
          if     (artype.eq.2) then
            write(label(51:72),114) ' mean: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          else
            write(label(51:72),114) ' sdev: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          endif
        endif
        if (lhycom) then
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'H'
        else
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'M'
        endif
 112    format ('  year',f7.2,' (',a3,i3.2,')')
 113    format ('  date: ',a3,i3.2,',',i5,'  ')
 114    format (a7,f7.2,'-',f7.2)
 115    format (' [',i2.2,'.',i1.1,a1,']')
      endif  !initialization
c
      if     (iotype.eq.1) then
c
c       HYCOM .[ab] I/O.
c
        call zbiopi(lopen, io)
        if     (.not.lopen) then
          call zbiopn('new', io)
          call zhopen(io, 'formatted', 'new', 0)
        endif
        call zbiowr3(array(1,1,kf),kl-kf+1,
     +               ip,.false., hmin(kf),hmax(kf), io, .false.)
        do k= kf,kl
          if     (ltheta) then
            write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
          else
            write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
          endif
          write(io,'(a,a,2g15.6)') label(33:81),':',hmin(k),hmax(k)
          call flush(io)
          write(lp,'(a,a,2g15.6)') label(33:81),':',hmin(k),hmax(k)
          call flush(lp)
        enddo
      elseif (iotype.eq.2) then
c
c       unformatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'unformatted', 'new', 0)
        endif
        do k= kf,kl
          if     (ltheta) then
            write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
          else
            write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
          endif
          write(io) array(:,:,k)
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif (iotype.eq.-3) then
c
c       formatted sequential I/O (lon lat value).
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        do k= kf,kl
          if     (ltheta) then
            write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
          else
            write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
          endif
          do j= 1,jj
            do i= 1,ii
              if     (array(i,j,k).ne.fill_value) then
                write(io,frmt) plon(i,j),plat(i,j),array(i,j,k)
              endif
            enddo
          enddo
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif (iotype.eq.3) then
c
c       formatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        do k= kf,kl
          if     (ltheta) then
            write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
          else
            write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
          endif
          write(io,frmt) array(:,:,k)
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif(iotype.eq.4) then
        write(Ename,'(a3,i3.3)') 'CDF',io
        ncfile = ' '
        call getenv(Ename,ncfile)
        write(*,*) 'ncfile ',ncfile
        if     (ncfile.eq.' ') then
          write(lp,*) 'ncfile ',ncfile
          write(lp,'(/3a/)')'error in horout_nc- ',Ename,' not defined'
          call flush(lp)
          stop 9
        endif
c
        call ncrange(array(1,1,kf),ii,jj,kl-kf+1, fill_value, hmin,hmax)
c
        inquire(file= ncfile, exist=lexist)
        if (.not.lexist) then
c
c         create a new NetCDF and write data to it
c
          call ncheck(nf90_create(trim(ncfile),nf90_noclobber,ncfileID))
          ! define the dimensions
          call ncheck(nf90_def_dim(ncfileID,
     &                             "MT", nf90_unlimited,MTDimID))
          if     (laxis) then
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Latitude",  jj,pLatDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Longitude", ii,pLonDimID))
          else
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Y",         jj,pYDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "X",         ii,pXDimID))
          endif
          call ncheck(nf90_def_dim(ncfileID,"Layer",kl-kf+1,lyrDimID))
          ! create the global attributes
          call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                             "Conventions",
     &                             "CF-1.0"))
          if (lhycom) then
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "HYCOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            if     (artype.eq.1) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM archive file"))
            elseif (artype.eq.2) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM mean archive file"))
            else
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM std. archive file"))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archv2ncdf2d"))
          else
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "MICOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               "MICOM"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "source",
     &                               "MICOM archive file"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archm2ncdf2d"))
          endif
          ! create the variables and attributes
          call ncheck(nf90_def_var(ncfileID,"MT",  nf90_double,
     &                             MTDimID,MTVarID))
          if     (yrflag.eq.0) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-16 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "360_day"))
          elseif (yrflag.eq.1) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-16 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          elseif (yrflag.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-01 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          else
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 1900-12-31 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "standard"))
          endif
          call ncheck(nf90_def_var(ncfileID,"Date", nf90_double,
     &                             MTDimID,datVarID))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "long_name",
     &                             "date"))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "units",
     &                             "day as %Y%m%d.%f"))
          if     (artype.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          elseif (artype.eq.3) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          endif
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               pLatDimID,pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            if     (abs((plat(1,jj)-plat(1,1))-
     &                  (plat(1, 2)-plat(1,1))*(jj-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               pLonDimID,pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)-plon(1,1))-
     &                  (plon( 2,1)-plon(1,1))*(ii-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          else
            call ncheck(nf90_def_var(ncfileID,"Y", nf90_int,
     &                               pYDimID,pYVarID))
            call ncheck(nf90_put_att(ncfileID,pYVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"X", nf90_int,
     &                               pXDimID,pXVarID))
            call ncheck(nf90_put_att(ncfileID,pXVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               (/pXDimID, pYDimID/), pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               (/pXDimID, pYDimID/), pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          endif
          if     (ltheta) then
            call ncheck(nf90_def_var(ncfileID,"Layer", nf90_float,
     &                               lyrDimID,lyrVarID))
            call ncheck(nf90_put_att(ncfileID,lyrVarID,
     &                               "units","SigmaTheta"))     
          else
            call ncheck(nf90_def_var(ncfileID,"Layer", nf90_int,
     &                               lyrDimID,lyrVarID))
            call ncheck(nf90_put_att(ncfileID,lyrVarID,
     &                               "units","layer"))     
            call ncheck(nf90_put_att(ncfileID,lyrVarID,
     &                               "positive","down"))
          endif
          ! model 3d variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin(1), hmax(1)/)))
          call ncheck(nf90_put_att(ncfileID,varID,"units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               trim(name)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                 trim(name)//label(51:55)//label(73:81)))
          endif
          ! leave def mode
          call ncheck(nf90_enddef(ncfileID))
          ! write data into coordinate variables
          call ncheck(nf90_put_var(ncfileID,MTVarID,time3(3)))
          call ncheck(nf90_put_var(ncfileID,datVarID,date   ))
          if     (laxis) then
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(1,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,1)))
          else
            call ncheck(nf90_put_var(ncfileID,pYVarID,
     &                               (/(j, j=1,jj)/)))
            call ncheck(nf90_put_var(ncfileID,pXVarID,
     &                               (/(i, i=1,ii)/)))
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(:,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,:)))
          endif
          if     (ltheta) then
            call ncheck(nf90_put_var(ncfileID,lyrVarID,
     &                               theta(kf:kl)))
          else
            call ncheck(nf90_put_var(ncfileID,lyrVarID,
     &                               (/(k, k=kf,kl)/)))
          endif
          ! write to model variable
          call ncheck(nf90_put_var(ncfileID,varID,
     &                             array(1:ii,1:jj,kf:kl)))
          ! close NetCDF file
          call ncheck(nf90_close(ncfileID))
        else
c
c         Write data to existing NetCDF file
c
          ! open NetCDF file
          call ncheck(nf90_open(trim(ncfile), nf90_write, ncfileID))
          ! get dimension ID's
          call ncheck(nf90_inq_dimid(ncfileID,"MT",    MTDimID))
          call ncheck(nf90_inq_dimid(ncfileID,"Layer",lyrDimID))
          if     (laxis) then
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Latitude",pLatDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Longitude",pLonDimID))
          else
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Y",        pYDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "X",        pXDimID))
          endif
          !  switch to define mode
          call ncheck(nf90_redef(ncfileID))
          ! define new variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin(1), hmax(1)/)))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               trim(name)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                 trim(name)//label(51:55)//label(73:81)))
          endif
          ! leave define mode
          call ncheck(nf90_enddef(ncfileID))
          ! inquire variable ID
          call ncheck(nf90_inq_varid(ncfileID,trim(namec),varID))
          !write values into array
          call ncheck(nf90_put_var(ncfileID,varID,
     &                             array(1:ii,1:jj,kf:kl)))
          ! close file
          call ncheck(nf90_close(ncfileID))
        endif
        write(lp,'(a49,a,2g15.6)') 
     &    trim(name)//label(51:81),':',hmin(1),hmax(1)
        call flush(lp)

      elseif (iotype.eq.5) then
c
c       grib-1 I/O
c
        call open_unit(io,frmt)

        read(22,*) gridlabel
        rewind(22)
        do k= kf,kl
          if     (ltheta) then
            write(label(33:50),'(a,f5.2,   a)') 'sig=',theta(k),name
          else
            write(label(33:50),'(a,i2.2,1x,a)') 'layer=',k,name
          endif
          print *,'calling 2ab2grib for ',name, namec, k
          CALL ab2grib ( array(1:ii,1:jj,k), ii,jj,
     &         fdate(1),fdate(2),fdate(3),fdate(4),verfhour,
     &          flag,ibms,namec,k,0,-1.0,gridlabel)

          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo





      else
c
c       should never get here.
c
        write(lp,'(/a)')   'error in horout_3d - inconsistent call'
        write(lp,'(3a)')   'label  = "',label(33:len_trim(label)),'"'
        write(lp,'(3a)')   'frmt   = "', frmt( 1:len_trim( frmt)),'"'
        write(lp,'(a,i4)') 'io     = ',io
        write(lp,'(a,i4)') 'iotype = ',iotype
        call flush(lp)
        stop 9
      endif
      return
      end

      subroutine horout_3z(array,zz,
     &                     artype,yrflag,time3,iexpt,lhycom,
     &                     name,namec,units, kz, frmt,io,
     &                     fdate,verfhour)
      use mod_plot ! HYCOM I/O interface
      use mod_xc   ! HYCOM communication API
      use mod_zb   ! HYCOM I/O interface for subregion
      use netcdf   ! NetCDF Interface
      
      implicit none
      include  "grib_block.h"
      include  "locale.inc"
      include  "clib.inc"
      integer	       ierr
      character*1      grib1
      integer  fdate(4)           ! yyyy, mm, dd, hh of forecast run
      integer  verfhour           ! verifying hour/lead
      INTEGER, save :: ibms = 1
      character*80 fname
      real, parameter :: flag = 2.0**100
c
      character*(*)    name,namec,units,frmt
      logical          lhycom, lexist
      integer          artype,yrflag,iexpt,kz,io,gridlabel
      double precision time3(3)
      real             array(ii,jj,kz),zz(kz)
c
c     write out a 3-d z-level array to unit io based on frmt.
c
c     3-d array size and frmt    must be identical in all calls.
c     artype,yrflag,time3,lhycom must be identical in all calls.
c
c     the output filename is taken from environment variable FOR0xx,
c      where  xx = io, with default fort.xx.
c     the array  filename is taken from environment variable FORxxxA,
c      where xxx = io, with default fort.xxxa
c     the NetCDF filename is taken from environment variable CDFxxx,
c      where xxx = io, with no default.
c     the NetCDF title and institution are taken from environment
c      variables CDF_TITLE and CDF_INST.
c
c     Supported I/O types are:
c       frmt=='NetCDF'        for NetCDF I/O,
c       frmt=='netCDF'        for NetCDF I/O,
c       frmt=='HYCOM'         for HYCOM .[ab] I/O,
c       frmt=='BIN'           for unformatted sequential I/O,
c       frmt=='(...)'         for   formatted sequential I/O with format frmt.< c       frmt=='(2f10.4,...)'  for   formatted sequential I/O of the form
c                                   longitude latitude value (skipping land)
c       frmt=='NetCDF' for NetCDF I/O,
c       frmt=='NetCDF' for NetCDF I/O,
c       frmt=='netCDF' for NetCDF I/O,
c       frmt=='HYCOM'  for HYCOM .[ab] I/O,
c       frmt=='BIN'    for unformatted sequential I/O,
c       frmt=='(...)'  for   formatted sequential I/O with format frmt.
c
c     This version supports frmt=='netCDF' and needs 
c     version 3.5 of the NetCDF library, from: 
c     http://www.unidata.ucar.edu/packages/netcdf/
c
      integer          :: ncfileID, status, varID
      integer          :: pLatDimID,pLonDimID,pLatVarID,pLonVarID,
     &                    lyrDimID,lyrVarID
      integer          :: pYDimID,pXDimID,pYVarID,pXVarID
      integer          :: MTDimID,MTVarID,datVarID
      character        :: ncfile*240,ncenv*240
      character        :: Ename*6
c
      logical          :: lopen
      integer          :: i,j,k,l,iyear,month,iday,ihour
      real             :: hmin(999),hmax(999)
      double precision :: dt,dt0,year
c
      character*81,     save :: label   = ' '
      integer,          save :: iotype  = -1
      double precision, save :: date    = 0.d0
      double precision, save :: cell    = 0.d0
      logical,          save :: laxis
      real,        parameter :: fill_value = 2.0**100
c
      character cmonth(12)*3
      data      cmonth/'jan','feb','mar','apr','may','jun',
     &                 'jul','aug','sep','oct','nov','dec'/
c
      if     (iotype.eq.-1) then
c
c        initialization.
c
        l = len_trim(frmt)
        if     (frmt(1:l).eq.'HYCOM')  then
c
c         HYCOM .[ab] I/O.
c
          call zbiost(ii,jj)
          iotype = 1
          write(lp,'(/a/)') 'horout_3z - HYCOM I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'BIN')    then
c
c         unformatted sequential I/O.
c
          iotype = 2
          write(lp,'(/a/)') 'horout_3z - unformatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:8).eq.'(2f10.4,' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O (lon lat value).
c
          iotype = -3
          write(lp,'(/a,a/)') 'horout - formatted sequential I/O',
     &                        ' (longitude latitude value)'
          call flush(lp)
        elseif (frmt(1:1).eq.'(' .and. frmt(l:l).eq.')') then
c
c         formatted sequential I/O.
c
          iotype = 3
          write(lp,'(/a/)') 'horout_3z - formatted sequential I/O'
          call flush(lp)
        elseif (frmt(1:l).eq.'netCDF' .or.
     &          frmt(1:l).eq.'NetCDF'     ) then
c
c         NetCDF I/O.
c
          laxis = .true.
          do i= 2,ii
            laxis = laxis .and. 
     &              maxval(abs(plat(1,:)-plat(i,:))).le.1.e-2
          enddo
          do j= 2,jj
            laxis = laxis .and. 
     &              maxval(abs(plon(:,1)-plon(:,j))).le.1.e-2
          enddo
c
          iotype = 4
          if     (laxis) then
            write(lp,'(/2a/)') 'horout_3z - NetCDF I/O (lat/lon axes)'
          else
            write(lp,'(/2a/)') 'horout_3z - NetCDF I/O (curvilinear)'
          endif
          call flush(lp)
        elseif (frmt(1:l).eq.'grib1' .or.
     &          frmt(1:l).eq.'GRIB1') then
c
c         grib-1 format
c
          iotype = 5
          laxis = .false.
          write(lp,'(/a,a/)') 'horout - grib-1 I/O'
          call flush(lp)

        else
c
c         unknown I/O type.
c
          write(lp,'(/a)')   'error in horout_3z - unknown I/O type'
          write(lp,'(3a)')   'frmt   = "', frmt(1:len_trim( frmt)),'"'
          write(lp,'(a,i4)') 'io     = ',io
          call flush(lp)
          stop 9
        endif
c
c       initialize label.
c
        if     (yrflag.eq.0) then
          year  = 360.0d0
        elseif (yrflag.lt.3) then
          year  = 366.0d0
        else
          year  = 365.25d0
        endif
        call fordate(time3(3),yrflag, iyear,month,iday,ihour)
        date    = (iday + 100 * month + 10000 * iyear) +
     &            (time3(3)-int(time3(3)))
        if     (artype.eq.1) then
          if     (yrflag.lt.3) then
            write (label(51:72),112) time3(3)/year,cmonth(month),iday
          else
            write (label(51:72),113) cmonth(month),iday,iyear
          endif
        else  ! mean or sdev archive
          write(lp,*) 'time3 = ',time3
          dt = 0.5*(time3(2)-time3(1))/(nstep-1)
          if     (yrflag.eq.0) then
            dt0 = 15.0
          elseif (yrflag.eq.1) then
            dt0 = 15.25
          elseif (yrflag.eq.2) then
            dt0 = 0.0
          else
            dt0 = 0.0
          endif
          cell = (time3(2)+dt+dt0) - (time3(1)-dt+dt0)
          if     (artype.eq.2) then
            write(label(51:72),114) ' mean: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          else
            write(label(51:72),114) ' sdev: ',(time3(1)-dt+dt0)/year,
     &                                        (time3(2)+dt+dt0)/year
          endif
        endif
        if (lhycom) then
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'H'
        else
          write (label(73:81),115) iexpt/10,mod(iexpt,10),'M'
        endif
 112    format ('  year',f7.2,' (',a3,i3.2,')')
 113    format ('  date: ',a3,i3.2,',',i5,'  ')
 114    format (a7,f7.2,'-',f7.2)
 115    format (' [',i2.2,'.',i1.1,a1,']')
      endif  !initialization
c
      if     (iotype.eq.1) then
c
c       HYCOM .[ab] I/O.
c
        call zbiopi(lopen, io)
        if     (.not.lopen) then
          call zbiopn('new', io)
          call zhopen(io, 'formatted', 'new', 0)
        endif
        call zbiowr3(array,kz,
     +               ip,.false., hmin,hmax, io, .false.)
        do k= 1,kz
          if     (zz(k).le.9999.99) then
            write(label(33:50),'(a,f7.2,a)') 'z=',zz(k),name
          else
            write(label(33:50),'(a,f8.1,a)') 'z=',zz(k),name
          endif
          write(io,'(a,a,2g15.6)') label(33:81),':',hmin(k),hmax(k)
          call flush(io)
          write(lp,'(a,a,2g15.6)') label(33:81),':',hmin(k),hmax(k)
          call flush(lp)
        enddo
      elseif (iotype.eq.2) then
c
c       unformatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'unformatted', 'new', 0)
        endif
        do k= 1,kz
          if     (zz(k).le.9999.99) then
            write(label(33:50),'(a,f7.2,a)') 'z=',zz(k),name
          else
            write(label(33:50),'(a,f8.1,a)') 'z=',zz(k),name
          endif
          write(io) array(:,:,k)
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif (iotype.eq.-3) then
c
c       formatted sequential I/O (lon lat value).
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        do k= 1,kz
          if     (zz(k).le.9999.99) then
            write(label(33:50),'(a,f7.2,a)') 'z=',zz(k),name
          else
            write(label(33:50),'(a,f8.1,a)') 'z=',zz(k),name
          endif
          do j= 1,jj
            do i= 1,ii
              if     (array(i,j,k).ne.fill_value) then
                write(io,frmt) plon(i,j),plat(i,j),array(i,j,k)
              endif
            enddo
          enddo
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif (iotype.eq.3) then
c
c       formatted sequential I/O
c
        inquire(unit=io, opened=lopen)
        if     (.not.lopen) then
          call zhopen(io, 'formatted', 'new', 0)
        endif
        do k= 1,kz
          if     (zz(k).le.9999.99) then
            write(label(33:50),'(a,f7.2,a)') 'z=',zz(k),name
          else
            write(label(33:50),'(a,f8.1,a)') 'z=',zz(k),name
          endif
          write(io,frmt) array(:,:,k)
          call flush(io)
          write(lp,'(a)') label(33:81)
          call flush(lp)
        enddo
      elseif (iotype.eq.4) then
c
c       NetCDF I/O
c
        write(Ename,'(a3,i3.3)') 'CDF',io
        ncfile = ' '
        call getenv(Ename,ncfile)
        write(*,*) 'ncfile ',ncfile
        if     (ncfile.eq.' ') then
          write(lp,'(/3a/)')'error in horout_nc- ',Ename,' not defined'
          call flush(lp)
c          stop 9
        endif
c
        call ncrange(array,ii,jj,kz, fill_value, hmin,hmax)
c
        inquire(file= ncfile, exist=lexist)
        if (.not.lexist) then
          ! create a new NetCDF and write data to it
          call ncheck(nf90_create(trim(ncfile),nf90_noclobber,ncfileID))
          ! define the dimensions
          call ncheck(nf90_def_dim(ncfileID,
     &                             "MT", nf90_unlimited,MTDimID))
          if     (laxis) then
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Latitude",  jj,pLatDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Longitude", ii,pLonDimID))
          else
            call ncheck(nf90_def_dim(ncfileID,
     &                               "Y",         jj,pYDimID))
            call ncheck(nf90_def_dim(ncfileID,
     &                               "X",         ii,pXDimID))
          endif
          call ncheck(nf90_def_dim(ncfileID,"Z",kz,lyrDimID))
          ! create the global attributes
          call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                             "Conventions",
     &                             "CF-1.0"))
          if (lhycom) then
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "HYCOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            if     (artype.eq.1) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM archive file"))
            elseif (artype.eq.2) then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM mean archive file"))
            else
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "source",
     &                                 "HYCOM std. archive file"))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archv2ncdf3z"))
          else
            ncenv = ' '
            call getenv('CDF_TITLE',ncenv)
            if     (ncenv.eq.' ') then
              ncenv = "MICOM"
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               trim(ncenv)))
            ncenv = ' '
            call getenv('CDF_INST',ncenv)
            if     (ncenv.ne.' ') then
              call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                                 "institution",
     &                                 trim(ncenv)))
            endif
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "title",
     &                               "MICOM"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "source",
     &                               "MICOM archive file"))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "experiment",
     &                               label(75:78)))
            call ncheck(nf90_put_att(ncfileID,nf90_global,
     &                               "history",
     &                               "archm2ncdf3z"))
          endif
          ! create the variables and attributes
          call ncheck(nf90_def_var(ncfileID,"MT",  nf90_double,
     &                             MTDimID,MTVarID))
          if     (yrflag.eq.0) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-01 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "360_day"))
          elseif (yrflag.eq.1) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-16 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          elseif (yrflag.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "model time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 0001-01-01 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "366_day"))
          else
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "long_name",
     &                               "time"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "units",
     &                               "days since 1900-12-31 00:00:00"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "calendar",
     &                               "standard"))
          endif
          call ncheck(nf90_def_var(ncfileID,"Date", nf90_double,
     &                             MTDimID,datVarID))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "long_name",
     &                             "date"))
          call ncheck(nf90_put_att(ncfileID,datVarID,
     &                             "units",
     &                             "day as %Y%m%d.%f"))
          if     (artype.eq.2) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "mean"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          elseif (artype.eq.3) then
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,MTVarID,
     &                               "cell_extent",
     &                               cell))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_methods",
     &                               "standard_deviation"))
            call ncheck(nf90_put_att(ncfileID,datVarID,
     &                               "cell_extent",
     &                               cell))
          endif
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               pLatDimID,pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            if     (abs((plat(1,jj)-plat(1,1))-
     &                  (plat(1, 2)-plat(1,1))*(jj-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               pLonDimID,pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)-plon(1,1))-
     &                  (plon( 2,1)-plon(1,1))*(ii-1)).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "point_spacing","even"))  !ferret
            endif
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          else
            call ncheck(nf90_def_var(ncfileID,"Y", nf90_int,
     &                               pYDimID,pYVarID))
            call ncheck(nf90_put_att(ncfileID,pYVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"X", nf90_int,
     &                               pXDimID,pXVarID))
            call ncheck(nf90_put_att(ncfileID,pXVarID,
     &                               "point_spacing","even"))  !ferret
            call ncheck(nf90_def_var(ncfileID,"Latitude",  nf90_float,
     &                               (/pXDimID, pYDimID/), pLatVarID))
            call ncheck(nf90_put_att(ncfileID,pLatVarID,
     &                               "units","degrees_north"))
            call ncheck(nf90_def_var(ncfileID,"Longitude", nf90_float,
     &                               (/pXDimID, pYDimID/), pLonVarID))
            call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                               "units","degrees_east"))
            if     (abs((plon(ii,1)+(plon(2,1)-plon(1,1)))-
     &                  (plon( 1,1)+ 360.0) ).lt.1.e-2) then
              call ncheck(nf90_put_att(ncfileID,pLonVarID,
     &                                 "modulo","360 degrees"))  !ferret
            endif
          endif
          call ncheck(nf90_def_var(ncfileID,"Z", nf90_float,lyrDimID,
     &                             lyrVarID))
          call ncheck(nf90_put_att(ncfileID,lyrVarID,
     &                             "units","m"))
          call ncheck(nf90_put_att(ncfileID,lyrVarID,
     &                             "positive","down"))
          ! model 3Z variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin(1), hmax(1)/)))
          call ncheck(nf90_put_att(ncfileID,varID,"units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               trim(name)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                 trim(name)//label(51:55)//label(73:81)))
          endif
          ! leave def mode
          call ncheck(nf90_enddef(ncfileID))
          ! write data into coordinate variables
          call ncheck(nf90_put_var(ncfileID,MTVarID,time3(3)))
          call ncheck(nf90_put_var(ncfileID,datVarID,date   ))
          if     (laxis) then
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(1,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,1)))
          else
            call ncheck(nf90_put_var(ncfileID,pYVarID,
     &                               (/(j, j=1,jj)/)))
            call ncheck(nf90_put_var(ncfileID,pXVarID,
     &                               (/(i, i=1,ii)/)))
            call ncheck(nf90_put_var(ncfileID,pLatVarID,plat(:,:)))
            call ncheck(nf90_put_var(ncfileID,pLonVarID,plon(:,:)))
          endif
          call ncheck(nf90_put_var(ncfileID,lyrVarID,zz(:)))
          ! write to model variable
          call ncheck(nf90_put_var(ncfileID,varID,array(:,:,:)))
          ! close NetCDF file
          call ncheck(nf90_close(ncfileID))
        else
c
c        Write data to existing NetCDF file
c
          ! open NetCDF file
          call ncheck(nf90_open(trim(ncfile), nf90_write, ncfileID))
          ! get dimension ID's
          call ncheck(nf90_inq_dimid(ncfileID,"MT",MTDimID))
          call ncheck(nf90_inq_dimid(ncfileID,"Z",lyrDimID))
          if     (laxis) then
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Latitude",pLatDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Longitude",pLonDimID))
          else
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "Y",        pYDimID))
            call ncheck(nf90_inq_dimid(ncfileID,
     &                                 "X",        pXDimID))
          endif
          !  switch to define mode
          call ncheck(nf90_redef(ncfileID))
          ! define new variable
          if     (laxis) then
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pLonDimID, pLatDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Date"))
          else
            call ncheck(nf90_def_var(ncfileID,trim(namec),nf90_float,
     &                               (/pXDimID,   pYDimID,
     &                                 lyrDimID, MTDimID/),
     &                               varID))
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "coordinates",
     &                               "Longitude Latitude date"))
          endif
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "_FillValue",fill_value))
          call ncheck(nf90_put_att(ncfileID,varID,
     &                             "valid_range",
     &                             (/hmin(1), hmax(1)/)))
          call ncheck(nf90_put_att(ncfileID,varID,"units",trim(units)))
          if     (artype.eq.1) then
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                               trim(name)//label(73:81)))
          else
            call ncheck(nf90_put_att(ncfileID,varID,
     &                               "long_name",
     &                 trim(name)//label(51:55)//label(73:81)))
          endif
          ! leave define mode
          call ncheck(nf90_enddef(ncfileID))
          ! inquire variable ID
          call ncheck(nf90_inq_varid(ncfileID,trim(namec),varID))
          !write values into array
          call ncheck(nf90_put_var(ncfileID,varID,array(:,:,:)))
          ! close file
          call ncheck(nf90_close(ncfileID))
        endif
        write(lp,'(a49,a,2g15.6)') 
     &    trim(name)//label(51:81),':',hmin(1),hmax(1)
        call flush(lp)
      elseif (iotype.eq.5) then
c
c       grib-1 I/O
c
        call open_unit(io,frmt)

        read(22,*) gridlabel
        rewind(22)
        do k= 1,kz
          if     (zz(k).le.9999.99) then
            write(label(33:50),'(a,f7.2,a)') 'z=',zz(k),name
          else
            write(label(33:50),'(a,f8.1,a)') 'z=',zz(k),name
          endif
          print *,'calling 3ab2grib for ',name, namec, k
          CALL ab2grib ( array(1:ii,1:jj,k), ii,jj,
     &         fdate(1),fdate(2),fdate(3),fdate(4),verfhour,
     &          flag,ibms,namec,k,1,zz(k),gridlabel)
        enddo

      else
c
c       should never get here.
c
        write(lp,'(/a)')   'error in horout_3z - inconsistent call'
        write(lp,'(3a)')   'label  = "',label(33:len_trim(label)),'"'
        write(lp,'(3a)')   'frmt   = "', frmt( 1:len_trim( frmt)),'"'
        write(lp,'(a,i4)') 'io     = ',io
        write(lp,'(a,i4)') 'iotype = ',iotype
        call flush(lp)
        stop 9
      endif
      return
      end

      subroutine ncheck(status)
      use mod_xc   ! HYCOM communication API
      use netcdf   ! NetCDF fortran 90 interface
      implicit none
c
      integer, intent(in) :: status
c
c     subroutine to handle NetCDF errors
c
      if (status /= nf90_noerr) then
        write(lp,'(/a)')   'error in horout - from NetCDF library'
        write(lp,'(a/)')   trim(nf90_strerror(status))
        call flush(lp)
        stop 9
      end if
      end subroutine ncheck

      subroutine ncrange(h,ii,jj,kk, fill_value, hmin,hmax)
      implicit none
c
      integer, intent(in ) :: ii,jj,kk
      real,    intent(in ) :: h(ii,jj,kk),fill_value
      real,    intent(out) :: hmin,hmax
c
c     return range of array, ignoring fill_value
c
      integer i,j,k
      real    hhmin,hhmax
c
      hhmin =  abs(fill_value)
      hhmax = -abs(fill_value)
      do k= 1,kk
        do j= 1,jj
          do i= 1,ii
            if     (h(i,j,k).ne.fill_value) then
              hhmin = min(hhmin,h(i,j,k))
              hhmax = max(hhmax,h(i,j,k))
            endif
          enddo
        enddo
      enddo
      hmin = hhmin
      hmax = hhmax
      end subroutine ncrange