!******************************************************************************
!******************************************************************************

  module ni3_module

    use vtype_module
    use netcdf

    implicit none

    private


    public ::            &
         ni3_handle_err, &
         ni3_open      , &
         ni3_close     , &
         ni3_redef     , &
         ni3_enddef    , &
         ni3_inq

    public ::              &
         ni3_inq_dimlen   , &
         ni3_inq_dimnames , &
         ni3_inq_varname  , &
         ni3_inq_var      , &
         ni3_inq_varndims , &
         ni3_inq_vardimnames, &
         ni3_chk_var      , &
         ni3_set_ga       , &
         ni3_def_dim      , &
         ni3_set_dim      , &
         ni3_def_dim_bnds , &
         ni3_set_dim_bnds , &
         ni3_def_var      , &
         ni3_put_var      , &
         ni3_put_varss    , &
         ni3_get_var      , &
         ni3_get_varss    , &
         ni3_get_att      , &
         ni3_put_att      , &
         ni3_cp_atts


    interface ni3_set_dim
       module procedure         &
            ni3_set_dim_int   , &
            ni3_set_dim_real  , &
            ni3_set_dim_double
    end interface

    interface ni3_set_dim_bnds
       module procedure              &
            ni3_set_dim_bnds_int   , &
            ni3_set_dim_bnds_real  , &
            ni3_set_dim_bnds_double
    end interface

    interface ni3_def_var
       module procedure           &
            ni3_def_var_nofv    , &
            ni3_def_var_intfv   , &
            ni3_def_var_realfv  , &
            ni3_def_var_doublefv
    end interface

    interface ni3_put_var
       module procedure            &
            ni3_put_var_sc_int   , &
            ni3_put_var_sc_real  , &
            ni3_put_var_sc_double, &
            ni3_put_var_1d_int   , &
            ni3_put_var_1d_real  , &
            ni3_put_var_1d_double, &
            ni3_put_var_2d_int   , &
            ni3_put_var_2d_real  , &
            ni3_put_var_2d_double, &
            ni3_put_var_3d_int   , &
            ni3_put_var_3d_real  , &
            ni3_put_var_3d_double, &
            ni3_put_var_4d_double
    end interface

    interface ni3_put_varss
       module procedure              &
            ni3_put_varss_sc_int   , &
            ni3_put_varss_sc_real  , &
            ni3_put_varss_sc_double, &
            ni3_put_varss_1d_int   , &
            ni3_put_varss_1d_real  , &
            ni3_put_varss_1d_double, &
            ni3_put_varss_2d_int   , &
            ni3_put_varss_2d_real  , &
            ni3_put_varss_2d_double, &
            ni3_put_varss_3d_int   , &
            ni3_put_varss_3d_real  , &
            ni3_put_varss_3d_double
    end interface

    interface ni3_get_var
       module procedure            &
            ni3_get_var_sc_int   , &
            ni3_get_var_sc_real  , &
            ni3_get_var_sc_double, &
            ni3_get_var_1d_int   , &
            ni3_get_var_1d_real  , &
            ni3_get_var_1d_double, &
            ni3_get_var_2d_int   , &
            ni3_get_var_2d_real  , &
            ni3_get_var_2d_double, &
            ni3_get_var_3d_int   , &
            ni3_get_var_3d_real  , &
            ni3_get_var_3d_double, &
            ni3_get_var_4d_double
    end interface

    interface ni3_get_varss
       module procedure              &
            ni3_get_varss_sc_int   , &
            ni3_get_varss_sc_real  , &
            ni3_get_varss_sc_double, &
            ni3_get_varss_1d_int   , &
            ni3_get_varss_1d_real  , &
            ni3_get_varss_1d_double, &
            ni3_get_varss_2d_int   , &
            ni3_get_varss_2d_real  , &
            ni3_get_varss_2d_double, &
            ni3_get_varss_3d_int   , &
            ni3_get_varss_3d_real  , &
            ni3_get_varss_3d_double
    end interface

    interface ni3_get_att
       module procedure         &
            ni3_get_att_text  , &
            ni3_get_att_int   , &
            ni3_get_att_real  , &
            ni3_get_att_double
    end interface

    interface ni3_put_att
       module procedure         &
            ni3_put_att_text  , &
            ni3_put_att_int   , &
            ni3_put_att_real  , &
            ni3_put_att_double
    end interface


    integer, parameter, public :: NI3_INT    = NF90_INT
    integer, parameter, public :: NI3_REAL   = NF90_FLOAT
    integer, parameter, public :: NI3_DOUBLE = NF90_DOUBLE
    !
    ! Internal variables and routines
    !
    type, private :: ni3_fileinfo_type
       integer(i4b)          :: ncid
       character(len=extstr) :: ncfn, mode
       integer(i4b)          :: seq
    end type ni3_fileinfo_type

    integer(i4b)             , save        :: ni3_finum
    data                                      ni3_finum  /0/
    type( ni3_fileinfo_type ), allocatable :: ni3_fi( : )



!    interface ni_judge_xtype
!       module procedure ni_judge_xtype_int, &
!            ni_judge_xtype_real, ni_judge_xtype_double
!    end interface


    !**************************************************************************

  contains

    !**************************************************************************
    ! subroutine ni3_handle_err
    !
    ! Usage:
    !
    ! if( status .ne. nf90_noerr ) call ni3_handle_err( status, line )
    !
    !**************************************************************************

    subroutine ni3_handle_err( status, err_mes )

      integer(i4b)    , intent(in)           :: status
      character(len=*), intent(in), optional :: err_mes


      if( status .ne. nf90_noerr ) then
         if( present( err_mes ) ) print *, trim( err_mes )
         print *, trim( nf90_strerror( status ) )
         stop "STOP"
      end if


    end subroutine ni3_handle_err

    !**************************************************************************
    ! subroutine ni3_open
    !**************************************************************************
    ! path     : Path to NetCDF file
    ! mode     : new (NEW), read (READ), write (WRITE)
    ! ncid     : NetCDF file ID
    !**************************************************************************

    subroutine ni3_open( path, mode, ncid )

      character(len=*), intent(in ) :: path, mode
      integer(i4b)    , intent(out) :: ncid


      ! Local variables
      !
      integer(i4b)          :: cmode, omode
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_open"
      err_mes = trim( err_mes ) // ', path: ' // trim( path ) &
           // ', mode: ' // trim( mode )


      if( ( mode .eq. "new" ) .or. ( mode .eq. "NEW" ) ) then

         cmode = NF90_CLOBBER
         status = nf90_create( path, cmode, ncid )
         call ni3_handle_err( status, err_mes )

      else 

         if( ( mode .eq. "read" ) .or. ( mode .eq. "READ" ) ) then
            omode = NF90_NOWRITE
         else if( ( mode .eq. "write" ) .or. ( mode .eq. "WRITE" ) ) then
            omode = NF90_WRITE
         else
            write( 6, * ) "Inproper argument, mode"
            write( 6, * ) "Argument mode should be either of words below."
            write( 6, * ) " 'new', 'NEW', 'read', 'READ', 'write', or 'WRITE'"
            stop
         end if

         status = nf90_open( path, omode, ncid )
         call ni3_handle_err( status, err_mes )

      end if


!      call ni3__addfi( ncid, path, mode )


    end subroutine ni3_open

    !**************************************************************************
    ! subroutine ni3_close
    !**************************************************************************
    ! ncid     : NetCDF file ID
    !**************************************************************************

    subroutine ni3_close( ncid )

      integer(i4b), intent(in) :: ncid


      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_close"


      status = nf90_close( ncid )
      call ni3_handle_err( status, err_mes )

!      call ni3__delfi( ncid )

    end subroutine ni3_close

    !**************************************************************************
    ! subroutine ni3_redef
    !**************************************************************************
    ! ncid     : NetCDF file ID
    !**************************************************************************

    subroutine ni3_redef( ncid )

      integer(i4b), intent(in) :: ncid


      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_redef"


      status = nf90_redef( ncid )
      if( ( status .ne. nf90_noerr ) .and. ( status .ne. nf90_eindefine ) ) &
           call ni3_handle_err( status, err_mes )


    end subroutine ni3_redef

    !**************************************************************************
    ! subroutine ni3_enddef
    !**************************************************************************
    ! ncid     : NetCDF file ID
    !**************************************************************************

    subroutine ni3_enddef( ncid )

      integer(i4b), intent(in) :: ncid


      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_enddef"


      status = nf90_enddef( ncid )
      if( ( status .ne. nf90_noerr ) &
           .and. ( status .ne. nf90_enotindefine ) ) &
           call ni3_handle_err( status, err_mes )


    end subroutine ni3_enddef

    !**************************************************************************
    ! subroutine ni3_inq
    !**************************************************************************
    ! ncid      : NetCDF file ID
    !**************************************************************************

    subroutine ni3_inq( ncid, ndims, nvars, natts )

      integer(i4b), intent(in )           :: ncid
      integer(i4b), intent(out), optional :: ndims, nvars, natts


      !
      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq"


      status = NF90_Inquire( ncid, ndims, nvars, natts )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_inq

    !**************************************************************************
    ! subroutine ni3_inq_dimlen
    !**************************************************************************
    ! ncid      : NetCDF file ID
    !**************************************************************************

    subroutine ni3_inq_dimlen( ncid, name, len )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: len


      !
      ! Local variables
      !
      integer(i4b)          :: dimid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq_dimlen"


      status = NF90_inq_dimid( ncid, name, dimid )
      call ni3_handle_err( status, err_mes )

      status = NF90_Inquire_Dimension( ncid, dimid, len = len )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_inq_dimlen

    !**************************************************************************

    subroutine ni3_inq_dimnames( ncid, ndims, dimnames )

      integer(i4b)    , intent(in ) :: ncid
      integer(i4b)    , intent(in ) :: ndims
      character(len=*), intent(out) :: dimnames(ndims)


      !
      ! Local variables
      !
      integer(i4b)          :: dimid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq_dimnames"


      do dimid = 1, ndims
        status = NF90_inquire_dimension( ncid, dimid, dimnames(dimid) )
        call ni3_handle_err( status, err_mes )
      end do


    end subroutine ni3_inq_dimnames

    !**************************************************************************
    ! subroutine ni3_inq_var
    !**************************************************************************
    ! ncid      : NetCDF file ID
    !**************************************************************************

    subroutine ni3_inq_var( ncid, name, varid, ndims, xtype )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(out), optional :: varid, ndims, xtype


      !
      ! Local variables
      !
      integer(i4b)          :: l_varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq_var"

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, l_varid )
      call ni3_handle_err( status, err_mes )

      if ( present( ndims ) ) then
        status = nf90_inquire_variable( ncid, l_varid, ndims = ndims )
        call ni3_handle_err( status, err_mes )
      end if

      if ( present( xtype ) ) then
        status = nf90_inquire_variable( ncid, l_varid, xtype = xtype )
        call ni3_handle_err( status, err_mes )
      end if

      if( present( varid ) ) varid = l_varid


    end subroutine ni3_inq_var

    !**************************************************************************

    logical function ni3_chk_var( ncid, name )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name


      !
      ! Local variables
      !
      integer(i4b)          :: nvars
      integer(i4b)          :: l
      character(len=extstr) :: varname
!!$      character(len=extstr) :: err_mes


!!$      err_mes = "In ni3_chk_var"

      call ni3_enddef( ncid )

      call ni3_inq( ncid, nvars = nvars )

      ni3_chk_var = .false.
      do l = 1, nvars
        call ni3_inq_varname( ncid, l, varname )
        if ( varname == name ) ni3_chk_var = .true.
      end do


    end function ni3_chk_var

    !**************************************************************************

    subroutine ni3_inq_vardimnames( ncid, varname, ndims, dimnames )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: varname
      integer(i4b)    , intent(in ) :: ndims
      character(len=*), intent(out) :: dimnames(ndims)


      !
      ! Local variables
      !
      integer(i4b)          :: l_varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes
      integer(i4b)          :: dimids(ndims)
      integer(i4b)          :: n


      err_mes = "In ni3_inq_vardimnames"

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, varname, l_varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_inquire_variable( ncid, l_varid, dimids = dimids )
      call ni3_handle_err( status, err_mes )

      do n = 1, ndims
        status = nf90_inquire_dimension( ncid, dimids(n), dimnames(n) )
        call ni3_handle_err( status, err_mes )
      end do


    end subroutine ni3_inq_vardimnames

    !**************************************************************************
    ! subroutine ni3_inq_varname
    !**************************************************************************
    ! ncid      : NetCDF file ID
    !**************************************************************************

    subroutine ni3_inq_varname( ncid, varid, name )

      integer(i4b)    , intent(in ) :: ncid, varid
      character(len=*), intent(out) :: name


      !
      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq_varname"


      status = nf90_inquire_variable( ncid, varid, name = name )
      call ni3_handle_err( status, err_mes )


     end subroutine ni3_inq_varname

    !**************************************************************************
    ! subroutine ni3_inq_ndims
    !**************************************************************************
    ! ncid      : NetCDF file ID
    !**************************************************************************

    subroutine ni3_inq_varndims( ncid, name, ndims )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: ndims


      !
      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_inq_varndims"


      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_inquire_variable( ncid, varid, ndims = ndims )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_inq_varndims

    !**************************************************************************
    ! subroutine ni3_set_ga
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! conv      : Conventions
    ! title     : title
    ! hist      : history
    ! inst      : institution
    ! src       : source
    ! com       : comment
    ! ref       : reference
    !**************************************************************************

    subroutine ni3_set_ga( ncid, conv, title, hist, inst, src, com, ref )

      integer(i4b)    , intent(in)           :: ncid
      character(len=*), intent(in), optional :: conv, title, hist, inst, &
           src, com, ref


      ! Local variables
      !
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_set_ga"


      call ni3_redef( ncid )

      !
      ! Put "Conventions"
      !
      if( present( conv ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "Conventions", conv )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "title"
      !
      if( present( title ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "title", title )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "history"
      !
      if( present( hist ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "history", hist )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "institution"
      !
      if( present( inst ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "institution", inst )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "source"
      !
      if( present( src ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "source", src )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "com"
      !
      if( present( com ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "comment", com )
         call ni3_handle_err( status, err_mes )
      end if
      !
      ! Put "reference"
      !
      if( present( ref ) ) then
         status = nf90_put_att( ncid, NF90_GLOBAL, "reference", ref )
         call ni3_handle_err( status, err_mes )
      end if


    end subroutine ni3_set_ga

    !**************************************************************************
    ! subroutine ni3_def_dim
    !**************************************************************************
    ! Input:
    !     ncid, name, xtype len
    ! Output:
    !     
    !**************************************************************************
    ! ncid       : NetCDF file ID
    ! name       : Dimension name
    ! xtype      : Variable type
    ! len        : Length of dimension
    ! di         : Structure including dimension information
    !**************************************************************************

    subroutine ni3_def_dim( ncid, name, xtype, len, stdname, longname, units )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype, len
      character(len=*), intent(in ), optional :: stdname, longname, units


      !
      ! Local variables
      !
      integer(i4b)                     :: status
      integer(i4b)                     :: dimid
      integer(i4b)         , parameter :: ndims = 1
      character(len=extstr)            :: dimname( ndims )
      character(len=extstr)            :: err_mes


      err_mes = "In ni3_def_dim"


      call ni3_redef( ncid )

      !
      ! Definition of dimension
      !
      status = nf90_def_dim( ncid, name, len, dimid )
      call ni3_handle_err( status, err_mes )
      !
      ! Definition of variable for dimension
      !
      dimname( 1 ) = name
      call ni3_def_var( ncid, name, xtype, ndims, dimname )
      !
      ! Set standard_name
      !
      if( present( stdname ) ) then
         call ni3_put_att( ncid, name, "standard_name", stdname )
      end if
      !
      ! Set long_name
      !
      if( present( longname ) ) then
         call ni3_put_att( ncid, name, "long_name", longname )
      end if
      !
      ! Set unit
      !
      if( present( units ) ) then
         call ni3_put_att( ncid, name, "units", units )
      end if


    end subroutine ni3_def_dim

    !**************************************************************************
    ! subroutine ni3_set_dim_<type>
    !**************************************************************************
    ! Input:
    !     ncid, name, units, len, var
    ! Output:
    !     di
    !**************************************************************************
    ! ncid       : NetCDF file ID
    ! name       : Dimension name
    ! array size : Array size of dimension variable
    ! var        : Dimension variable ( integer, real(sp), real(dp) )
    ! di         : Structure including dimension information
    ! len        : Length of dimension
    !            : If the length of dimension is not equal to the array size, 
    !            : "len" can be used to specify the length of dimension. 
    !**************************************************************************

    subroutine ni3_set_dim_int( ncid, name, xtype, var, &
         stdname, longname, units )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: var( : )
      character(len=*), intent(in ), optional :: stdname, longname, units


      !
      ! Local variables
      !
      integer(i4b)          :: len
!      integer(i4b)          :: status
!!$      character(len=extstr) :: err_mes


!!$      err_mes = "In ni3_set_dim_int"


      len = size( var )
      call ni3_def_dim( ncid, name, xtype, len, stdname, longname, units )

      call ni3_put_var( ncid, name, var )


    end subroutine ni3_set_dim_int

    !**************************************************************************

    subroutine ni3_set_dim_real( ncid, name, xtype, var, &
         stdname, longname, units )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      real(sp)        , intent(in )           :: var( : )
      character(len=*), intent(in ), optional :: stdname, longname, units


      !
      ! Local variables
      !
      integer(i4b)          :: len
!      integer(i4b)          :: status
!!$      character(len=extstr) :: err_mes


!!$      err_mes = "In ni3_set_dim_real"


      len = size( var )
      call ni3_def_dim( ncid, name, xtype, len, stdname, longname, units )

      call ni3_put_var( ncid, name, var )


    end subroutine ni3_set_dim_real

    !**************************************************************************

    subroutine ni3_set_dim_double( ncid, name, xtype, var, &
         stdname, longname, units )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      real(dp)        , intent(in )           :: var( : )
      character(len=*), intent(in ), optional :: stdname, longname, units


      !
      ! Local variables
      !
      integer(i4b)          :: len
!      integer(i4b)          :: status
!!$      character(len=extstr) :: err_mes


!!$      err_mes = "In ni3_set_dim_double"


      len = size( var )
      call ni3_def_dim( ncid, name, xtype, len, stdname, longname, units )

      call ni3_put_var( ncid, name, var )


    end subroutine ni3_set_dim_double

    !**************************************************************************
    ! subroutine ni3_def_dim_bnds
    !**************************************************************************
    ! Input:
    !     ncid, name, xtype, longname
    ! Output:
    !
    !**************************************************************************
    ! ncid       : NetCDF file ID
    ! name       : Dimension name
    ! xtype      : Variable type
    ! longname   : long name
    !**************************************************************************

    subroutine ni3_def_dim_bnds( ncid, name, xtype, longname )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      character(len=*), intent(in ), optional :: longname


      ! Local variables
      !
      integer(i4b)                     :: varid, dimid
      character(len=extstr)            :: bnds_name
      integer(i4b)         , parameter :: ndims = 2
      character(len=extstr)            :: dimname( ndims )
      integer(i4b)                     :: status
      character(len=extstr)            :: err_mes


      err_mes = "In ni3_def_dim_bnds"

      bnds_name = " "


      call ni3_redef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      !
      ! Definition of dimension for dimension bounds
      !
      status = nf90_inq_dimid( ncid, "bnd", dimid )
      if( status .eq. nf90_ebaddim ) then
         status = nf90_def_dim( ncid, "bnd", 2, dimid )
         call ni3_handle_err( status, err_mes )
      else
         call ni3_handle_err( status, err_mes )
      end if

      bnds_name = trim( name ) // "_bnds"
      call ni3_put_att( ncid, name, "bounds", bnds_name )

      !
      ! Definition of variable
      !
      dimname( 1 ) = "bnd"
      dimname( 2 ) = name
      call ni3_def_var( ncid, bnds_name, xtype, ndims, dimname, &
           longname = longname )


    end subroutine ni3_def_dim_bnds

    !**************************************************************************

    subroutine ni3_set_dim_bnds_int( ncid, name, xtype, var, longname )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: var( :, : )
      character(len=*), intent(in ), optional :: longname


      ! Local variables
      !
      integer(i4b)                     :: varid
      character(len=extstr)            :: bnds_name
      integer(i4b)                     :: status
      character(len=extstr)            :: err_mes


      err_mes = "In ni3_def_dim_bnds_int"

      bnds_name = " "


      call ni3_def_dim_bnds( ncid, name, xtype, longname )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )
      status = nf90_get_att( ncid, varid, "bounds", bnds_name )
      call ni3_handle_err( status, err_mes )

      call ni3_put_var( ncid, bnds_name, var )


    end subroutine ni3_set_dim_bnds_int

    !**************************************************************************

    subroutine ni3_set_dim_bnds_real( ncid, name, xtype, var, longname )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      real(sp)        , intent(in )           :: var( :, : )
      character(len=*), intent(in ), optional :: longname


      ! Local variables
      !
      integer(i4b)                     :: varid
      character(len=extstr)            :: bnds_name
      integer(i4b)                     :: status
      character(len=extstr)            :: err_mes


      err_mes = "In ni3_def_dim_bnds_real"

      bnds_name = " "


      call ni3_def_dim_bnds( ncid, name, xtype, longname )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )
      status = nf90_get_att( ncid, varid, "bounds", bnds_name )
      call ni3_handle_err( status, err_mes )

      call ni3_put_var( ncid, bnds_name, var )


    end subroutine ni3_set_dim_bnds_real

    !**************************************************************************

    subroutine ni3_set_dim_bnds_double( ncid, name, xtype, var, longname )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      real(dp)        , intent(in )           :: var( :, : )
      character(len=*), intent(in ), optional :: longname


      ! Local variables
      !
      integer(i4b)                     :: varid
      character(len=extstr)            :: bnds_name
      integer(i4b)                     :: status
      character(len=extstr)            :: err_mes


      err_mes = "In ni3_def_dim_bnds_double"

      bnds_name = " "


      call ni3_def_dim_bnds( ncid, name, xtype, longname )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )
      status = nf90_get_att( ncid, varid, "bounds", bnds_name )
      call ni3_handle_err( status, err_mes )

      call ni3_put_var( ncid, bnds_name, var )


    end subroutine ni3_set_dim_bnds_double

    !**************************************************************************
    ! subroutine ni3_def_var
    !**************************************************************************
    ! Input:
    !     ncid, name, units, nvdim, vdims
    ! Output:
    !     varid
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! units     : Unit of variable
    ! xtype     : Variable type
    ! nvdim     : Number of dimensions
    ! vdims     : Array for dimension IDs
    ! varid     : Variable ID
    ! fillvalue : Fill value (missing data)
    !**************************************************************************

    subroutine ni3_def_var_nofv( ncid, name, xtype, ndims, dimname, &
         stdname, longname, units )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: ndims
      character(len=*), intent(in )           :: dimname( : )
      character(len=*), intent(in ), optional :: stdname, longname, units


      !
      ! Local variables
      !
      integer(i4b)          :: dimid, dimids( ndims )
      integer(i4b)          :: varid
      integer(i4b)          :: i
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_def_var_nofv"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_redef( ncid )

      !
      ! Definition of variable
      !
      do i = 1, ndims
         status = nf90_inq_dimid( ncid, dimname( i ), dimid )
         dimids( i ) = dimid
      end do
      status = nf90_def_var( ncid, name, xtype, dimids, varid )
      call ni3_handle_err( status, err_mes )
      !
      ! Set standard_name
      !
      if( present( stdname ) ) then
         call ni3_put_att( ncid, name, "standard_name", stdname )
      end if
      !
      ! Set long_name
      !
      if( present( longname ) ) then
         call ni3_put_att( ncid, name, "long_name", longname )
      end if
      !
      ! Set units
      !
      if( present( units ) ) then
         call ni3_put_att( ncid, name, "units", units )
      end if


    end subroutine ni3_def_var_nofv

    !**************************************************************************

    subroutine ni3_def_var_intfv( ncid, name, xtype, ndims, dimname, &
         stdname, longname, units, fillvalue )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: ndims
      character(len=*), intent(in )           :: dimname( : )
      character(len=*), intent(in ), optional :: stdname, longname, units
      integer(i4b)    , intent(in )           :: fillvalue


      !
      ! local variables
      !
!      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_def_var_intfv"


      call ni3_def_var_nofv( ncid, name, xtype, ndims, dimname, &
           stdname, longname, units )

      !
      ! Set fill value
      !
      select case( xtype )
      case( NF90_INT    )
         call ni3_put_att( ncid, name, "_FillValue", int ( fillvalue ) )
      case( NF90_REAL   )
         call ni3_put_att( ncid, name, "_FillValue", real( fillvalue ) )
      case( NF90_DOUBLE )
         call ni3_put_att( ncid, name, "_FillValue", dble( fillvalue ) )
      case default
         write( 6, * ) "Unexpected type, in ", trim( err_mes ), "."
         stop
      end select
         

    end subroutine ni3_def_var_intfv

    !**************************************************************************

    subroutine ni3_def_var_realfv( ncid, name, xtype, ndims, dimname, &
         stdname, longname, units, fillvalue )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: ndims
      character(len=*), intent(in )           :: dimname( : )
      character(len=*), intent(in ), optional :: stdname, longname, units
      real(sp)        , intent(in )           :: fillvalue


      !
      ! local variables
      !
!      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_def_var_realfv"


      call ni3_def_var_nofv( ncid, name, xtype, ndims, dimname, &
           stdname, longname, units )

      !
      ! Set fill value
      !
      select case( xtype )
      case( NF90_INT    )
         call ni3_put_att( ncid, name, "_FillValue", int ( fillvalue ) )
      case( NF90_REAL   )
         call ni3_put_att( ncid, name, "_FillValue", real( fillvalue ) )
      case( NF90_DOUBLE )
         call ni3_put_att( ncid, name, "_FillValue", dble( fillvalue ) )
      case default
         write( 6, * ) "Unexpected type, in ", trim( err_mes ), "."
         stop
      end select


    end subroutine ni3_def_var_realfv

    !**************************************************************************

    subroutine ni3_def_var_doublefv( ncid, name, xtype, ndims, dimname, &
         stdname, longname, units, fillvalue )

      integer(i4b)    , intent(in )           :: ncid
      character(len=*), intent(in )           :: name
      integer(i4b)    , intent(in )           :: xtype
      integer(i4b)    , intent(in )           :: ndims
      character(len=*), intent(in )           :: dimname( : )
      character(len=*), intent(in ), optional :: stdname, longname, units
      real(dp)        , intent(in )           :: fillvalue


      !
      ! local variables
      !
!      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_def_var_doublefv"


      call ni3_def_var_nofv( ncid, name, xtype, ndims, dimname, &
           stdname, longname, units )

      !
      ! Set fill value
      !
      select case( xtype )
      case( NF90_INT    )
         call ni3_put_att( ncid, name, "_FillValue", int ( fillvalue ) )
      case( NF90_REAL   )
         call ni3_put_att( ncid, name, "_FillValue", real( fillvalue ) )
      case( NF90_DOUBLE )
         call ni3_put_att( ncid, name, "_FillValue", dble( fillvalue ) )
      case default
         write( 6, * ) "Unexpected type, in ", trim( err_mes ), "."
         stop
      end select


    end subroutine ni3_def_var_doublefv

    !**************************************************************************
    ! subroutine ni3_put_var_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name, units, nvdim, vdims
    ! Output:
    !     varid
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! arr       : variable
    !**************************************************************************

    subroutine ni3_put_var_sc_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_sc_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_sc_int

    !**************************************************************************

    subroutine ni3_put_var_sc_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(in ) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_sc_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_sc_real

    !**************************************************************************

    subroutine ni3_put_var_sc_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(in ) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_sc_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_sc_double

    !**************************************************************************

    subroutine ni3_put_var_1d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_1d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_1d_int

    !**************************************************************************

    subroutine ni3_put_var_1d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_1d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_1d_real

    !**************************************************************************

    subroutine ni3_put_var_1d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_1d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_1d_double

    !**************************************************************************

    subroutine ni3_put_var_2d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_2d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_2d_int

    !**************************************************************************

    subroutine ni3_put_var_2d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_2d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_2d_real

    !**************************************************************************

    subroutine ni3_put_var_2d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_2d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_2d_double

    !**************************************************************************

    subroutine ni3_put_var_3d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_3d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_3d_int

    !**************************************************************************

    subroutine ni3_put_var_3d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_3d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_3d_real

    !**************************************************************************

    subroutine ni3_put_var_3d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_3d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_3d_double

    !**************************************************************************

    subroutine ni3_put_var_4d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(in ) :: arr( :, :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_put_var_4d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_put_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )


    end subroutine ni3_put_var_4d_double

    !**************************************************************************



    !**************************************************************************
    ! subroutine ni3_put_varss_<???>_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name, t, arr
    ! Output:
    !     
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! t         : time level
    ! arr       : 2D variable
    !**************************************************************************

    subroutine ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(in ) :: ndims
      integer(i4b)    , intent(out) :: st( ndims ), co( ndims )
      integer(i4b)    , intent(out) :: varid


      ! Local variables
      !
      integer(i4b)          :: l_ndims
      integer(i4b)          :: dimids( ndims ), len, i
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3__putget_var_ss_common"
      err_mes = trim( err_mes )  // ', Var: ' // trim( name )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_inquire_variable( ncid, varid, ndims = l_ndims )
      call ni3_handle_err( status, err_mes )
      if( l_ndims .ne. ndims ) then
         write( 6, * ) trim( err_mes )
         write( 6, * ) 'Number of dimensions is not appropriate for ', &
              trim( name )
         stop
      end if

      status = nf90_inquire_variable( ncid, varid, dimids = dimids )
      call ni3_handle_err( status, err_mes )
      st( : ) = 1
      do i = 1, ndims
         status = nf90_inquire_dimension( ncid, dimids( i ), len = len )
         co( i ) = len
      end do
      st( ndims ) = t
      co( ndims ) = 1


    end subroutine ni3__putget_varss_common

    !**************************************************************************

    subroutine ni3_put_varss_sc_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(in ) :: arr


      !
      ! local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_sc_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )
      arr2( 1 ) = arr

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_sc_int

    !**************************************************************************

    subroutine ni3_put_varss_sc_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(in ) :: arr


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_sc_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )
      arr2( 1 ) = arr

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_sc_real

    !**************************************************************************

    subroutine ni3_put_varss_sc_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(in ) :: arr


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_sc_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )
      arr2( 1 ) = arr

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_sc_double

    !**************************************************************************

    subroutine ni3_put_varss_1d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_1d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )
      arr2( :, 1 ) = arr( : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_1d_int

    !**************************************************************************

    subroutine ni3_put_varss_1d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_1d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )
      arr2( :, 1 ) = arr( : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_1d_real

    !**************************************************************************

    subroutine ni3_put_varss_1d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(in ) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_1d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )
      arr2( :, 1 ) = arr( : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_1d_double

    !**************************************************************************

    subroutine ni3_put_varss_2d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_2d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )
      arr2( :, :, 1 ) = arr( :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_2d_int

    !**************************************************************************

    subroutine ni3_put_varss_2d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_2d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )
      arr2( :, :, 1 ) = arr( :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_2d_real

    !**************************************************************************

    subroutine ni3_put_varss_2d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(in ) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_2d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )
      arr2( :, :, 1 ) = arr( :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_2d_double

    !**************************************************************************

    subroutine ni3_put_varss_3d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_3d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )
      arr2( :, :, :, 1 ) = arr( :, :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_3d_int

    !**************************************************************************

    subroutine ni3_put_varss_3d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_3d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )
      arr2( :, :, :, 1 ) = arr( :, :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_3d_real

    !**************************************************************************

    subroutine ni3_put_varss_3d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(in ) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_varss_3d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )
      arr2( :, :, :, 1 ) = arr( :, :, : )

      status = nf90_put_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      deallocate( arr2 )

      call ni3_redef( ncid )


    end subroutine ni3_put_varss_3d_double

    !**************************************************************************
    ! subroutine ni3_get_var_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name
    ! Output:
    !     arr
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! arr       : variable
    !**************************************************************************

    subroutine ni3_get_var_sc_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_sc_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_sc_int

    !**************************************************************************

    subroutine ni3_get_var_sc_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_sc_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_sc_real

    !**************************************************************************

    subroutine ni3_get_var_sc_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_sc_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_sc_double

    !**************************************************************************

    subroutine ni3_get_var_1d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_1d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_1d_int

    !**************************************************************************

    subroutine ni3_get_var_1d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_1d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_1d_real

    !**************************************************************************

    subroutine ni3_get_var_1d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_1d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_1d_double

    !**************************************************************************

    subroutine ni3_get_var_2d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_2d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_2d_int

    !**************************************************************************

    subroutine ni3_get_var_2d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_2d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_2d_real

    !**************************************************************************

    subroutine ni3_get_var_2d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_2d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_2d_double

    !**************************************************************************

    subroutine ni3_get_var_3d_int( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_3d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_3d_int

    !**************************************************************************

    subroutine ni3_get_var_3d_real( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(sp)        , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_3d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_3d_real

    !**************************************************************************

    subroutine ni3_get_var_3d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_3d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_3d_double

    !**************************************************************************

    subroutine ni3_get_var_4d_double( ncid, name, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      real(dp)        , intent(out) :: arr( :, :, :, : )


      ! Local variables
      !
      integer(i4b)          :: varid
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_get_var_4d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )

      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_var( ncid, varid, arr )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_var_4d_double

    !**************************************************************************
    ! subroutine ni3_get_varss_<???>_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name, units, nvdim, vdims
    ! Output:
    !     varid
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! t         : time level
    ! arr       : 2D variable
    !**************************************************************************

    subroutine ni3_get_varss_sc_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_sc_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr = arr2( 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_sc_int

    !**************************************************************************

    subroutine ni3_get_varss_sc_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_1d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr = arr2( 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_sc_real

    !**************************************************************************

    subroutine ni3_get_varss_sc_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(out) :: arr


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 0 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
!      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_sc_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )

      allocate( arr2( co( 1 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr = arr2( 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_sc_double

    !**************************************************************************

    subroutine ni3_get_varss_1d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_1d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( : ) = arr2( :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_1d_int

    !**************************************************************************

    subroutine ni3_get_varss_1d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_1d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( : ) = arr2( :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_1d_real

    !**************************************************************************

    subroutine ni3_get_varss_1d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(out) :: arr( : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 1 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_1d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( : ) = arr2( :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_1d_double

    !**************************************************************************

    subroutine ni3_get_varss_2d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_2d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, : ) = arr2( :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_2d_int

    !**************************************************************************

    subroutine ni3_get_varss_2d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_2d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, : ) = arr2( :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_2d_real

    !**************************************************************************

    subroutine ni3_get_varss_2d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(out) :: arr( :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 2 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_2d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, : ) = arr2( :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_2d_double

    !**************************************************************************

    subroutine ni3_get_varss_3d_int( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      integer(i4b)    , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      integer(i4b)         , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_3d_int"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, :, : ) = arr2( :, :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_3d_int

    !**************************************************************************

    subroutine ni3_get_varss_3d_real( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(sp)        , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(sp)             , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_3d_real"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, :, : ) = arr2( :, :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_3d_real

    !**************************************************************************

    subroutine ni3_get_varss_3d_double( ncid, name, t, arr )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name
      integer(i4b)    , intent(in ) :: t
      real(dp)        , intent(out) :: arr( :, :, : )


      ! Local variables
      !
      integer(i4b)         , parameter   :: ndims = 3 + 1
      integer(i4b)                       :: varid, st( ndims ), co( ndims )
      integer(i4b)                       :: i
      real(dp)             , allocatable :: arr2( :, :, :, : )
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_varss_3d_double"
      err_mes = trim( err_mes ) // ', Var: ' // trim( name )


      call ni3__putget_varss_common( ncid, name, t, ndims, st, co, varid )
      do i = 1, ndims - 1
         if( size( arr, i ) .ne. co( i ) ) then
            write( 6, * ) trim( err_mes )
            write( 6, * ) "Inappropriate array size: ", &
                 trim( name ), i, size( arr, i ), co( i ), "."
            stop
         end if
      end do

      allocate( arr2( co( 1 ), co( 2 ), co( 3 ), co( 4 ) ) )

      status = nf90_get_var( ncid, varid, arr2, start = st, count = co )
      call ni3_handle_err( status, err_mes )

      arr( :, :, : ) = arr2( :, :, :, 1 )
      deallocate( arr2 )


    end subroutine ni3_get_varss_3d_double

    !**************************************************************************
    ! subroutine ni3_get_att_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name, attname
    ! Output:
    !     att
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! attname   : time level
    ! att       :
    !**************************************************************************

    subroutine ni3_get_att_text( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      character(len=*), intent(out) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_att_text"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_att_text

    !**************************************************************************

    subroutine ni3_get_att_int( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      integer(i4b)    , intent(out) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_att_int"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_att_int

    !**************************************************************************

    subroutine ni3_get_att_real( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      real(sp)        , intent(out) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_att_real"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_att_real

    !**************************************************************************

    subroutine ni3_get_att_double( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      real(dp)        , intent(out) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_get_att_real"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      status = nf90_get_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_get_att_double

    !**************************************************************************
    ! subroutine ni3_put_att_<???>
    !**************************************************************************
    ! Input:
    !     ncid, name, attname, att
    ! Output:
    !     
    !**************************************************************************
    ! ncid      : NetCDF file ID
    ! name      : Variable name
    ! attname   : time level
    ! att       :
    !**************************************************************************

    subroutine ni3_put_att_text( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      character(len=*), intent(in ) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_att_text"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )

      status = nf90_put_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_put_att_text

    !**************************************************************************

    subroutine ni3_put_att_int( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      integer(i4b)    , intent(in ) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_att_int"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )

      status = nf90_put_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_put_att_int

    !**************************************************************************

    subroutine ni3_put_att_real( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      real(sp)        , intent(in ) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_att_real"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )

      status = nf90_put_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_put_att_real

    !**************************************************************************

    subroutine ni3_put_att_double( ncid, name, attname, att )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(in ) :: name, attname
      real(dp)        , intent(in ) :: att


      ! Local variables
      !
      integer(i4b)                       :: varid
      integer(i4b)                       :: status
      character(len=extstr)              :: err_mes


      err_mes = "In ni3_put_att_double"
      err_mes = trim( err_mes ) &
           // ', Var: ' // trim( name ) // ', Att: ' // trim( attname )


      call ni3_enddef( ncid )

      status = nf90_inq_varid( ncid, name, varid )
      call ni3_handle_err( status, err_mes )

      call ni3_redef( ncid )

      status = nf90_put_att( ncid, varid, attname, att )
      call ni3_handle_err( status, err_mes )


    end subroutine ni3_put_att_double

    !**************************************************************************
    ! copy attributes from one NetCDF file to another
    !**************************************************************************

    subroutine ni3_cp_atts( ncid_in, ncid_out, varname )

      integer(i4b)    , intent(in)           :: ncid_in, ncid_out
      character(len=*), intent(in), optional :: varname

      !
      ! local variables
      !
      integer(i4b)                       :: natts, attnum, varid_in, varid_out
      character(len=extstr)              :: attname
      integer(i4b)                       :: status
      character(len=extstr)              :: &
           err_mes = "In ni3_cp_atts"


      call ni3_redef( ncid_out )

      if( present( varname ) ) then
         if( ( varname .eq. "GLOBAL" ) &
              .or. ( varname .eq. "global" ) &
              .or. ( varname .eq. "Global" ) ) then
            varid_in  = NF90_GLOBAL
            varid_out = NF90_GLOBAL
         else
            status = nf90_inq_varid( ncid_in , varname, varid_in  )
            call ni3_handle_err( status, err_mes )
            status = nf90_inq_varid( ncid_out, varname, varid_out )
            call ni3_handle_err( status, err_mes )
         end if
      else
         varid_in  = NF90_GLOBAL
         varid_out = NF90_GLOBAL
      end if

      if( varid_in .eq. NF90_GLOBAL ) then
         status = nf90_Inquire( ncid_in, nAttributes = natts )
         call ni3_handle_err( status, err_mes )
      else
         status = nf90_Inquire_Variable( ncid_in, varid_in, nAtts = natts )
         call ni3_handle_err( status, err_mes )
      end if

      do attnum = 1, natts
         status = nf90_inq_attname( ncid_in, varid_in, attnum, attname )
         call ni3_handle_err( status, err_mes )
         status = nf90_copy_att( ncid_in, varid_in, attname, &
              ncid_out, varid_out )
         call ni3_handle_err( status, err_mes )
      end do


    end subroutine ni3_cp_atts

    !**************************************************************************





    !**************************************************************************
    ! Internal routines
    !
    !**************************************************************************

    !**************************************************************************
    ! subroutine ni3__nextfile
    !**************************************************************************
    ! ncid     : NetCDF file ID
    !**************************************************************************

    subroutine ni3__nextfile( ncid )

      integer(i4b), intent(inout) :: ncid


      !
      ! Local variables
      !
      character(len=extstr) :: path, mode
      integer(i4b)          :: seq, index
      character(len=2)      :: achar
      integer(i4b)          :: i
      integer(i4b)          :: status
      character(len=extstr) :: err_mes


      err_mes = "In ni3_nextfile"


      call ni3__inqfi( ncid, path, mode, seq, index )

!      status = nf90_get_att_text( ncid, NF90_GLOBAL, "file_name", path )
!      call ni3_handle_err( status, err_mes )

      seq = seq + 1

      if( ( mode .eq. "new" ) .or. ( mode .eq. "NEW" ) ) then
         if( path( len_trim( path )-2 : len_trim( path ) ) .ne. ".nc" ) &
              stop "Unexpected file name."

         find_a : do i = 1, 1000
            write( achar, '(a1)' ) i
            if( achar( 1 : 1 ) .eq. "a" ) exit find_a
         end do find_a
         if( i .gt. 1000 ) stop "Unable to find 'a'."

         i = i + seq - 1
         write( path, '(a,a1,a)' ) path( 1 : len_trim( path )-3 ), i, ".nc"

         status = nf90_put_att( ncid, NF90_GLOBAL, "next_file_name", path )
         call ni3_handle_err( status, err_mes )
      else
         status = nf90_get_att( ncid, NF90_GLOBAL, "next_file_name", path )
         call ni3_handle_err( status, err_mes )
      end if


      call ni3_close( ncid )

      mode = "new"
      call ni3_open( path, mode, ncid )

      call ni3__inqfi( ncid, path, mode, seq, index )
      ni3_fi( index ) % seq = seq


    end subroutine ni3__nextfile

    !**************************************************************************

    subroutine ni3__addfi( ncid, ncfn, mode )

      integer(i4b)    , intent(in) :: ncid
      character(len=*), intent(in) :: ncfn, mode


      !
      ! Local variables
      !
      type( ni3_fileinfo_type ), allocatable :: ni3_fi_tmp( : )
      integer(i4b)                           :: i


      if( ni3_finum .eq. 0 ) then
         allocate( ni3_fi( 1 ) )
      else
         allocate( ni3_fi_tmp( ni3_finum ) )
         do i = 1, ni3_finum
            ni3_fi_tmp( i ) % ncid = ni3_fi( i ) % ncid
            ni3_fi_tmp( i ) % ncfn = ni3_fi( i ) % ncfn
            ni3_fi_tmp( i ) % mode = ni3_fi( i ) % mode
            ni3_fi_tmp( i ) % seq  = ni3_fi( i ) % seq
         end do
         deallocate( ni3_fi )
         allocate  ( ni3_fi( ni3_finum + 1 ) )
         do i = 1, ni3_finum
            ni3_fi( i ) % ncid = ni3_fi_tmp( i ) % ncid
            ni3_fi( i ) % ncfn = ni3_fi_tmp( i ) % ncfn
            ni3_fi( i ) % mode = ni3_fi_tmp( i ) % mode
            ni3_fi( i ) % seq  = ni3_fi_tmp( i ) % seq
         end do
         deallocate( ni3_fi_tmp )
      end if

      ni3_finum = ni3_finum + 1

      ni3_fi( ni3_finum ) % ncid = ncid
      ni3_fi( ni3_finum ) % ncfn = ncfn
      ni3_fi( ni3_finum ) % mode = mode
      ni3_fi( ni3_finum ) % seq  = 1


    end subroutine ni3__addfi

    !**************************************************************************

    subroutine ni3__delfi( ncid )

      integer(i4b)    , intent(in) :: ncid


      !
      ! Local variables
      !
      type( ni3_fileinfo_type ), allocatable :: ni3_fi_tmp( : )
      integer(i4b)                           :: i, j


      allocate( ni3_fi_tmp( ni3_finum - 1 ) )
      j = 1
      do i = 1, ni3_finum
         if( ni3_fi( i ) % ncid .ne. ncid ) then
            ni3_fi_tmp( j ) % ncid = ni3_fi( i ) % ncid
            ni3_fi_tmp( j ) % ncfn = ni3_fi( i ) % ncfn
            ni3_fi_tmp( j ) % mode = ni3_fi( i ) % mode
            ni3_fi_tmp( j ) % seq  = ni3_fi( i ) % seq
            j = j + 1
         end if
      end do
      deallocate( ni3_fi )

      ni3_finum = ni3_finum - 1

      if( ni3_finum .ge. 1 ) then
         allocate( ni3_fi( ni3_finum ) )
         do i = 1, ni3_finum
            ni3_fi( i ) % ncid = ni3_fi_tmp( i ) % ncid
            ni3_fi( i ) % ncfn = ni3_fi_tmp( i ) % ncfn
            ni3_fi( i ) % mode = ni3_fi_tmp( i ) % mode
            ni3_fi( i ) % seq  = ni3_fi_tmp( i ) % seq
         end do
      end if

      deallocate( ni3_fi_tmp )


    end subroutine ni3__delfi

    !**************************************************************************

    subroutine ni3__inqfi( ncid, ncfn, mode, seq, index )

      integer(i4b)    , intent(in ) :: ncid
      character(len=*), intent(out) :: ncfn, mode
      integer(i4b)    , intent(out) :: seq, index


      !
      ! Local variables
      !
      integer(i4b) :: i


      search_loop : do i = 1, ni3_finum
         if( ni3_fi( i ) % ncid .eq. ncid ) exit search_loop
      end do search_loop
      if( i .gt. ni3_finum ) stop "Unable to find proper ncid."

      ncfn = ni3_fi( i ) % ncfn
      mode = ni3_fi( i ) % mode
      seq  = ni3_fi( i ) % seq

      index = i


    end subroutine ni3__inqfi

    !**************************************************************************
!
!    function ni_judge_xtype_int( value )
!
!      integer(i4b), intent(in) :: value
!
!      integer(i4b) :: ni_judge_xtype_int
!
!      ni_judge_xtype_int = NF90_INT
!
!    end function ni_judge_xtype_int
!
!
    !**************************************************************************
!
!    function ni_judge_xtype_real( value )
!
!      real(sp), intent(in) :: value
!
!      integer(i4b) :: ni_judge_xtype_real
!
!      ni_judge_xtype_real = NF90_FLOAT
!
!    end function ni_judge_xtype_real
!
!
    !**************************************************************************
!
!    function ni_judge_xtype_double( value )
!
!      real(dp), intent(in) :: value
!
!      integer(i4b) :: ni_judge_xtype_double
!
!      ni_judge_xtype_double = NF90_DOUBLE
!
!    end function ni_judge_xtype_double
!
!
    !**************************************************************************
    ! Internal routines
    !
    !**************************************************************************

    !**************************************************************************

    subroutine cf_dim_atts( name, stdname, units )

      character(len=*), intent(in ) :: name
      character(len=*), intent(out) :: stdname, units


      ! Local variables
      !
      integer(i4b), parameter :: listn = 8
      character(len=extstr) :: cf_dim_atts_list( 3, listn )

      !    "name"     , "std name" , "units"
      !
      data cf_dim_atts_list &
           / &
           "longitude", "longitude"                  , &
                        "degrees_east"               , &  !  1
           "lon"      , "longitude"                  , &
                        "degrees_east"               , &  !  2
           "latitude" , "latitude"                   , &
                        "degrees_north"              , &  !  3
           "lat"      , "latitude"                   , &
                        "degrees_north"              , &  !  4
           "lev"      , "lev"                        , &
                        "Sigma_level"                , &  !  5
           "plev"     , "plev"                       , &
                        "Pa"                         , &  !  6
           "time"     , "time"                       , &
                        "days since 0000-01-01"      , &  !  7
           "ls"       , "areocentric_solar_longitude", &
                        "degrees"                      &  !  8
           /

      integer(i4b) :: i



      search_loop: do i = 1, listn
         if( trim( name ) .eq. trim( cf_dim_atts_list( 1, i ) ) ) &
              exit search_loop
      enddo search_loop

      if( i .gt. listn ) then
         stdname = ""
         units   = ""

         call other_dim_atts( name, stdname, units )
      else
         stdname = cf_dim_atts_list( 2, i )
         units   = cf_dim_atts_list( 3, i )
      endif


    end subroutine cf_dim_atts

    !**************************************************************************

    subroutine other_dim_atts( name, stdname, units )

      character(len=*), intent(in ) :: name
      character(len=*), intent(out) :: stdname, units


      ! Local variables
      !
      integer(i4b), parameter :: listn = 2
      character(len=extstr) :: cf_dim_atts_list( 3, listn )

      !    "name"     , "std name" , "units"
      !
      data cf_dim_atts_list &
           / &
           "Ls"       , "areocentric_solar_longitude", "degrees", &  !  1
           "ls"       , "areocentric_solar_longitude", "degrees"  &  !  2
           /

      integer(i4b) :: i


      search_loop: do i = 1, listn
         if( trim( name ) .eq. trim( cf_dim_atts_list( 1, i ) ) ) &
              exit search_loop
      enddo search_loop

      if( i .gt. listn ) then
         stdname = ""
         units   = ""
      else
         stdname = cf_dim_atts_list( 2, i )
         units   = cf_dim_atts_list( 3, i )
      endif


    end subroutine other_dim_atts

    !**************************************************************************


  end module ni3_module
