!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!-------------------------------------------------------------------------------------------------
!*Deckyinxq: netcdf_mod 2.2

  module netcdf_mod

!-------------------------------------------------------------------------------------------------
! ************************************************************************************************
!-------------------------------------------------------------------------------------------------
!                                                                 Copyright (C) 2005 Xunqiang Yin
!                                                                 MODULE NAME : netcdf_mod
!                                                                 History : netcdf_mod 2.2
!                                                                 History : netcdf_mod 2.1
!                                                                 History : netcdf_mod 2.0
!                                                                 History : NcFileData 1.x
!                                                                 Current VERSION : 2013/10/20
!
! --- USAGE : To output/input nc files in convenience.
! --- DEPEND: The package of netcdf for FORTRAN.
!
! --- NOTE for describing of subroutine / function :
!  A. The parameters bracketed with [], means optional parameter.
!  B. The describe for the parameters of subroutine / function, started with:
!   * It means input prameter;
!   $ It means output prameter;
!   @ It means input and output prameter(it will be changed inside).
!
!-------------------------------------------------------------------------------------------------
! ************************************************************************************************
! ***                                 INTERFACE DESCRIBE                                       ***
! ************************************************************************************************
!-------------------------------------------------------------------------------------------------
!
!  1. subroutine open_nc(ncid, FileName, act)
!     $ integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: FileName = the name of netcdf file.
!     * character :: act = 'create', 'define', 'write' or 'read'. One character is also
!                              accepted, i.e. 'c', 'd', 'w', 'r'.
!
!-------------------------------------------------------------------------------------------------
!
!  2. subroutine close_nc(ncid)
!     * integer :: ncid = unit number of opened netcdf file.
!
!-------------------------------------------------------------------------------------------------
!
!  3. subroutine end_define(ncid)
!     * integer :: ncid = unit number of opened netcdf file.
!
!-------------------------------------------------------------------------------------------------
!
!  4. subroutine dimension_define
!     - dimension_define(ncid, DimName, DimLen [, DimVarName, DimVarType, DimID, DimVarID])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character :: Dimname = the name of this dimension.
!     * integer :: DimLen = the size of this dimension.
!     * character :: DimVarName = the name of dimension variable name.
!     * integer :: DimVarType = the type of dimension variable (use integer).
!          ( nf_int1 = 1, nf_char = 2, nf_int2 = 3, nf_int = 4,
!            nf_real = 5, nf_double = 6 )
!     $ integer :: DimID = the record number of this dimension.
!     $ integer :: DimVarID = the record number of dimension variable.
!     ( Note: for the unlimited dimension, 'DimLen = 0 '.)
!     Change records: DimVarName, DimVarType are changed as optional parameters. It means the nc
!                     file is defined without dimension variables. Or it can be defined as normal
!                     variables.
!
!-------------------------------------------------------------------------------------------------
!
!  5. function get_dimension_len(ncid, DimName)
!     * integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: DimName = the name of dimension need to get length.
!     $ integer :: get_dimension_len = the needed dimension length.
!
!-------------------------------------------------------------------------------------------------
!
!  6. subroutine variable_define
!
!     --- 2 interfaces:
!
!    6.1 variable_define(ncid, VarName, VarType, VarDimsName [, VarID])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character :: VarName = the name of this variable.
!     * integer :: VarType = the type of variable (use integer).
!          ( nf_int1 = 1, nf_char = 2, nf_int2 = 3, nf_int = 4,
!            nf_real = 5, nf_double = 6 )
!     * character(len=*) :: VarDimsName = the name list to which this variable
!                           related.
!     $ integer :: VarID = the record number of this variable.
!
!    6.2 variable_define(ncid, VarName, VarType, VarDims [, VarID])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character :: VarName = the name of this variable.
!     * integer :: VarType = the type of variable (use integer).
!          ( nf_int1 = 1, nf_char = 2, nf_int2 = 3, nf_int = 4,
!            nf_real = 5, nf_double = 6 )
!     * integer :: VarDims = the related DimID of this variable.
!     $ integer :: VarID = the record number of this variable.
!
!-------------------------------------------------------------------------------------------------
!
!  7. subroutine set_attribute(ncid, AttName, Att [, VarName])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: AttName = the attribute name of netcdf file.
!     * character(len=*)/integer/integer*1/integer*2/real/double presion ::
!                           Att = attribute of opened netcdf file.
!     * character(len=*) :: VarName = the owner(variable) of attribute.
!     ( Note: for the globle attribute, VarName shouldn't be given.)
!
!-------------------------------------------------------------------------------------------------
!
!  8. subroutine get_attribute(ncid, AttName, Att [, VarName])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: AttName = the attribute name of netcdf file.
!     $ character(len=*)/integer/integer*1/integer*2/real/double presion ::
!                           Att = attribute of opened netcdf file.
!     * character(len=*) :: VarName = the owner(variable) of attribute.
!     ( Note: for the globle attribute, VarName shouldn't be given.)
!
!-------------------------------------------------------------------------------------------------
!
!  9. subroutine writenc(ncid, VarName, Var [, RecNum, locs])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: VarName = the name of variable in netcdf file.
!     * character(len=*)/char/integer/integer*1/integer*2/real/double presion ::
!                          Var = the variable needed to be output.
!     * integer :: RecNum = the record number at unlimited dimension.
!     * integer :: locs = the start locations for output.
!     ( Note: for the variable without unlimited dimension, RecNum shouldn't be given.)
!
!-------------------------------------------------------------------------------------------------
!
!  10. subroutine readnc(ncid, VarName, Var [, RecNum, locs])
!     * integer :: ncid = unit number of opened netcdf file.
!     * character(len=*) :: VarName = the name of variable in netcdf file.
!     $ character(len=*)/char/integer/integer*1/integer*2/real/double presion ::
!                         Var = the variable needed to be input.
!     * integer :: RecNum = the record number at unlimited dimension.
!     * integer :: locs   = the start locations for output.
!     ( Note: for the variable without unlimited dimension,
!             RecNum shouldn't be given.)
!
!-------------------------------------------------------------------------------------------------
!
!   Changes of current version 2.2
!
!     (1) real --> real(4) and double precision --> real(8)
!     (2) sub. dimension_define
!     - dimension_define(ncid, DimName, DimLen, DimVarName, DimVarType [, DimID, DimVarID])
!     Changed as:
!     - dimension_define(ncid, DimName, DimLen [, DimVarName, DimVarType, DimID, DimVarID])
!
!                                                                  --- Xunqiang Yin, 2007/10/20
!                                                                   E-Mail: XunqiangYin@gmail.com
!
!-------------------------------------------------------------------------------------------------
! ************************************************************************************************
!-------------------------------------------------------------------------------------------------

  implicit none

!-------------------------------------------------------------------------------------------------

  public :: nf_int1, nf_char, nf_int2, nf_int, nf_real, nf_double
  public :: nf_fill_byte, nf_fill_int1, nf_fill_char, nf_fill_short, nf_fill_int2
  public :: nf_fill_int, nf_fill_float, nf_fill_real, nf_fill_double

  public :: open_nc, close_nc, end_define, readnc, writenc, readncb, writencb
  public :: variable_define, set_attribute, get_attribute
  public :: dimension_define, get_dimension_len
  public :: check_dimension,check_variable,get_varndims

  private

!-------------------------------------------------------------------------------------------------

  interface variable_define
    module procedure variable_define1, variable_define2
  end interface variable_define

!-------------------------------------------------------------------------------------------------

  interface set_attribute
    module procedure set_attribute_character,               &
                     set_attribute_int1,                    &
                     set_attribute_int2,                    &
                     set_attribute_int ,                    &
                     set_attribute_real,                    &
                     set_attribute_double
  end interface set_attribute

!-------------------------------------------------------------------------------------------------

  interface get_attribute
    module procedure get_attribute_character,               &
                     get_attribute_int1,                    &
                     get_attribute_int2,                    &
                     get_attribute_int,                     &
                     get_attribute_real,                    &
                     get_attribute_double
  end interface get_attribute

!-------------------------------------------------------------------------------------------------

  interface writenc
    module procedure &
    writenc_0d_int1, writenc_0d_int2,   writenc_0d_int,      &
    writenc_0d_real, writenc_0d_double, writenc_0d_text,     &
    writenc_1d_int1, writenc_1d_int2,   writenc_1d_int,      &
    writenc_1d_real, writenc_1d_double, writenc_1d_text,     &
    writenc_2d_int1, writenc_2d_int2,   writenc_2d_int,      &
    writenc_2d_real, writenc_2d_double, writenc_2d_text,     &
    writenc_3d_int1, writenc_3d_int2,   writenc_3d_int,      &
    writenc_3d_real, writenc_3d_double, writenc_3d_text,     &
    writenc_4d_int1, writenc_4d_int2,   writenc_4d_int,      &
    writenc_4d_real, writenc_4d_double, writenc_4d_text
  end interface writenc

!-------------------------------------------------------------------------------------------------

  interface readnc
    module procedure &
    readnc_0d_int1, readnc_0d_int2,   readnc_0d_int,        &
    readnc_0d_real, readnc_0d_double, readnc_0d_text,       &
    readnc_1d_int1, readnc_1d_int2,   readnc_1d_int,        &
    readnc_1d_real, readnc_1d_double, readnc_1d_text,       &
    readnc_2d_int1, readnc_2d_int2,   readnc_2d_int,        &
    readnc_2d_real, readnc_2d_double, readnc_2d_text,       &
    readnc_3d_int1, readnc_3d_int2,   readnc_3d_int,        &
    readnc_3d_real, readnc_3d_double, readnc_3d_text,       &
    readnc_4d_int1, readnc_4d_int2,   readnc_4d_int,        &
    readnc_4d_real, readnc_4d_double, readnc_4d_text
  end interface readnc

!-------------------------------------------------------------------------------------------------

  interface readncb
    module procedure readncb_1d, readncb_2d, readncb_3d, readncb_4d
  end interface readncb

  interface writencb
    module procedure writencb_1d, writencb_2d, writencb_3d, writencb_4d
  end interface writencb

!-------------------------------------------------------------------------------------------------

  include 'netcdf.inc'
  integer :: mystat, VarID
  character(len=80) :: version = 'netcdf_mod 2.2,  by Xunqiang Yin, 2013-10-20 00:15.'

!-------------------------------------------------------------------------------------------------

  contains

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To handle errors for NCFile input or output.
!*DeckYinxq: check_err

  subroutine check_err(mystat)
    integer,intent(in) :: mystat
    if(mystat/=NF_NOERR)then
      write(*,*)nf_strerror(mystat);stop
    endif
  end subroutine check_err

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To open a NcFile. (By create, ifnew; By redefine, ifold.)
!*DeckYinxq: open_nc_def

  subroutine open_nc(ncid, FileName, act)
  character(len=*), intent(in) :: FileName, act
  integer, intent(in) :: ncid
  logical :: alive

  select case(act(1:1))
  case('c', 'C')
    !mystat=NF_CREATE(trim(FileName), NF_CLOBBER, ncid)
    mystat=NF_CREATE(trim(FileName),IOR(NF_CLOBBER,NF_64BIT_OFFSET), ncid)
    CALL check_err(mystat)
  case('d', 'D')
    inquire(file=trim(FileName), exist = alive)
    if(.not.alive)then
      write(*, *)trim(FileName), ' is not exist!'; stop
    endif
    mystat=NF_OPEN(trim(FileName), NF_WRITE, ncid)
    CALL check_err(mystat)
    mystat=NF_REDEF(ncid)
    CALL check_err(mystat)
  case('w', 'W')
    inquire(file=trim(FileName), exist = alive)
    if(.not.alive)then
      write(*, *)trim(FileName), ' is not exist!'; stop
    endif
    mystat=NF_OPEN(trim(FileName), NF_WRITE, ncid)
    CALL check_err(mystat)
  case('r', 'R')
    inquire(file=trim(FileName), exist = alive)
    if(.not.alive)then
      write(*, *)trim(FileName), ' is not exist!'; stop
    endif
    mystat=NF_OPEN(trim(FileName), NF_NOWRITE, ncid)
    CALL check_err(mystat)
  end select

  return
  end subroutine open_nc

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Close a openning NcFile.
!*DeckYinxq: WriteNC1DInt2

  subroutine close_nc(ncid)
  integer, intent(in) :: ncid

  mystat=NF_CLOSE(ncid)
  CALL check_err(mystat)

  return
  end subroutine close_nc

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To end define.
!*DeckYinxq: end_define

  subroutine end_define(ncid)
  integer, intent(in) :: ncid

  character(len=80) :: lib_version
  character(len=80) :: version = 'netcdf_mod 2.1, '    &
                               // 'by Xunqiang Yin, 2008-3-31 23:15.'
  character(len=10) :: dd, tt
  character(len=19) :: ts

  call date_and_time(dd,tt)
  ts = dd(1:4)//'/'//dd(5:6)//'/'//dd(7:8)// &
       'T'//tt(1:2)//':'//tt(3:4)//':'//tt(5:10)

! --- Output sorftware versions.

  call set_attribute_character(ncid, 'Creattime', ts)

  lib_version = 'netcdf '//nf_inq_libvers()
  call set_attribute_character(ncid, 'Sorftware1', lib_version)
  call set_attribute_character(ncid, 'Sorftware2', version)

! --- end of defination.

  mystat=NF_ENDDEF(ncid)
  CALL check_err(mystat)

  return
  end subroutine end_define

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define dimension for a NcFile.
!*DeckYinxq: dimension_define_notype

  subroutine dimension_define(ncid, DimName, DimLen, DimVarName, DimVarType, &
                               DimID, DimVarID)

  character(len=*), intent(in) :: DimName
  integer, intent(in) :: NcId, DimLen

  character(len=*), optional, intent(in) :: DimVarName
  integer, optional, intent(in) :: DimVarType
  integer, optional, intent(out) :: DimID, DimVarID

  integer :: DimID1, DimVarID1

  mystat=NF_DEF_DIM(ncid, DimName, DimLen, DimID1)
  CALL check_err(mystat)

  if(present(DimVarName))then
    mystat=nf_def_var(ncid, trim(DimVarName), DimVarType, 1, DimID1, DimVarID1)
    CALL check_err(mystat)
  endif

  if(present(DimID))DimID = DimID1
  if(present(DimVarID))DimVarID = DimVarID1

  return
  end subroutine dimension_define

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Get the dimension length,
!*DeckYinxq: get_dimension_len

  integer function get_dimension_len(ncid, DimName)
    integer, intent(in) :: ncid
    character(len=*), intent(in) :: DimName
    integer :: DimID
    mystat=NF_INQ_DIMID(ncid, trim(DimName), DimID)
    CALL check_err(mystat)
    mystat=NF_INQ_DIMLEN(ncid, DimID, get_dimension_len)
    CALL check_err(mystat)
  end function get_dimension_len

  logical function check_dimension(ncid,DimName)
    integer, intent(in) :: ncid
    character(len=*), intent(in) :: DimName
    integer :: DimID
    mystat=NF_INQ_DIMID(ncid,trim(DimName),DimID)
    if(mystat/=NF_NOERR)then
      check_dimension=.false.
    else
      check_dimension=.true.
    endif
  end function check_dimension

  logical function check_variable(ncid,VarName)
    integer, intent(in) :: ncid
    character(len=*), intent(in) :: VarName
    integer :: VarID
    mystat=NF_INQ_VarID(ncid,trim(VarName),VarID)
    if(mystat/=NF_NOERR)then
      check_variable=.false.
    else
      check_variable=.true.
    endif
  end function check_variable

  integer function get_varndims(ncid,vname)
    integer,intent(in) :: ncid
    character(len=*),intent(in) :: vname
    integer :: vid
    mystat=NF_INQ_VarID(ncid,vname,vid)
    mystat=NF_INQ_VARNDIMS(ncid,vid,get_varndims)
  end function get_varndims

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define variables.
!*DeckYinxq: variable_define1

  subroutine variable_define1(ncid, VarName, VarType, VarDims, VarID)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: VarType, VarDims(:)
  integer, optional, intent(out) :: VarID

  integer :: VarRank, VarID1

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID1)
  if(mystat.ne.NF_NOERR)then
    VarRank = size(VarDims)
    mystat=NF_DEF_VAR(ncid, trim(VarName), VarType, VarRank, VarDims, VarID1)
    CALL check_err(mystat)
  endif
  if(present(VarID))VarID = VarID1

  return
  end subroutine variable_define1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define variables.
!*DeckYinxq: variable_define2

  subroutine variable_define2(ncid, VarName, VarType, VarDimsName, VarID)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: VarType
  character(len=*), intent(in) :: VarDimsName(:)
  integer, optional, intent(out) :: VarID

  integer :: VarRank, VarID1, i
  integer, allocatable :: VarDims(:)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID1)
  if(mystat.ne.NF_NOERR)then
    VarRank = size(VarDimsName); allocate(VarDims(VarRank))
    do i = 1, VarRank
      mystat=NF_INQ_DIMID(ncid, trim(VarDimsName(i)), VarDims(i))
      CALL check_err(mystat)
    enddo
    mystat=NF_DEF_VAR(ncid, trim(VarName), VarType, VarRank, VarDims, VarID1)
    CALL check_err(mystat)
    deallocate(VarDims)
  endif
  if(present(VarID))VarID = VarID1

  return
  end subroutine variable_define2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: character
!*DeckYinxq: set_attribute_character

  Subroutine set_attribute_character(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName, attribute
  character(len=*), optional, intent(in) :: VarName

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_TEXT(ncid, VarID, AttName, len_trim(attribute), trim(attribute))
  CALL check_err(mystat)

  return
  end subroutine set_attribute_character

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int1
!*DeckYinxq: set_attribute_int1

  Subroutine set_attribute_int1(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer*1, intent(in) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_INT1(ncid, VarID, AttName, nf_int1, 1, attribute)
  CALL check_err(mystat)

  return
  end subroutine set_attribute_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int2
!*DeckYinxq: set_attribute_int2

  Subroutine set_attribute_int2(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer*2, intent(in) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_INT2(ncid, VarID, AttName, nf_int2, 1, attribute)
  CALL check_err(mystat)

  return
  end subroutine set_attribute_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int
!*DeckYinxq: set_attribute_int

  Subroutine set_attribute_int(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer, intent(in) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_INT(ncid, VarID, AttName, nf_int, 1, attribute)
  CALL check_err(mystat)

  return
  end subroutine set_attribute_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: real
!*DeckYinxq: set_attribute_real

  Subroutine set_attribute_real(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  real(4), intent(in) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_REAL(ncid, VarID, AttName, nf_real, 1, attribute)
  CALL check_err(mystat)

  return
  end subroutine set_attribute_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: double
!*DeckYinxq: set_attribute_double

  Subroutine set_attribute_double(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  real(8), intent(in) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_PUT_ATT_DOUBLE(ncid, VarID, AttName, nf_double, 1, attribute)
  CALL check_err(mystat)

  return
  end subroutine set_attribute_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: character
!*DeckYinxq: get_attribute_character

  Subroutine get_attribute_character(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), intent(out) :: attribute
  character(len=*), optional, intent(in) :: VarName

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_TEXT(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_character

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int1
!*DeckYinxq: get_attribute_int1

  Subroutine get_attribute_int1(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer*1, intent(out) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_INT1(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int2
!*DeckYinxq: get_attribute_int2

  Subroutine get_attribute_int2(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer*2, intent(out) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_INT2(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: int
!*DeckYinxq: get_attribute_int

  Subroutine get_attribute_int(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  integer, intent(out) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_INT(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: real
!*DeckYinxq: get_attribute_real

  Subroutine get_attribute_real(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  real(4), intent(out) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_REAL(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- To define attribute: double
!*DeckYinxq: get_attribute_double

  Subroutine get_attribute_double(ncid, AttName, attribute, VarName)
  integer, intent(in) :: ncid
  character(len=*), intent(in) :: AttName
  character(len=*), optional, intent(in) :: VarName
  real(8), intent(out) :: attribute

  VarID = 0
  if(present(VarName))then
    mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
    CALL check_err(mystat)
  endif
  mystat=NF_GET_ATT_DOUBLE(ncid, VarID, AttName, attribute)
  CALL check_err(mystat)

  return
  end subroutine get_attribute_double

!===================================== 0-d =====================================
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_int1

  subroutine writenc_0d_int1(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_int1(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_INT1(ncid, VarID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_int2

  subroutine writenc_0d_int2(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_int2(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_INT2(ncid, VarID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_int

  subroutine writenc_0d_int(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_int(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_INT(ncid, VarID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_real

  subroutine writenc_0d_real(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_real(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_REAL(ncid, VarID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_double

  subroutine writenc_0d_double(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_double(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_DOUBLE(ncid, VarID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write data of 0D or unlimite dims var into NC file.
!*DeckYinxq: writenc_0d_text

  subroutine writenc_0d_text(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(in) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_PUT_VAR_text(ncid, VarID, Var)
  else
    mystat=NF_PUT_VARA_text(ncid, VarID, [1, RecNum], [len_trim(var), 1], Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_0d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_int1

  subroutine readnc_0d_int1(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(out) :: Var
  integer, optional, intent(in) :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_int1(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_INT1(ncid, varID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_0d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_int2

  subroutine readnc_0d_int2(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(out) :: Var
  integer, optional, intent(in) :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)
  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_int2(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_INT2(ncid, varID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_0d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_int

  subroutine readnc_0d_int(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(out) :: Var
  integer, optional, intent(in) :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_int(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_INT(ncid, varID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_0d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_real

  subroutine readnc_0d_real(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(out) :: Var
  integer, optional, intent(in) :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)
  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_real(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_REAL(ncid, varID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_0d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_double

  subroutine readnc_0d_double(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(out) :: Var
  integer, optional, intent(in) :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)
  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_double(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_DOUBLE(ncid, varID, RecNum, 1, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_0d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read data of 0D or unlimite dims var from NC file.
!*DeckYinxq: readnc_0d_text

  subroutine readnc_0d_text(ncid, VarName, Var, RecNum)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(out) :: Var
  integer, intent(in), optional :: RecNum

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  IF(mystat /=NF_NOERR) CALL check_err(mystat)

  if(.not.present(RecNum))then
    mystat=NF_GET_VAR_text(ncid, varID, Var)
  else
    mystat=NF_GET_VARA_text(ncid, varID, [1, RecNum], [len(var), 1], Var)
  endif

  CALL check_err(mystat)

  return
  end subroutine readnc_0d_text

!===================================== 1-d =====================================
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: int1
!*DeckYinxq: writenc_1d_int1

  subroutine writenc_1d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT1(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: int2
!*DeckYinxq: writenc_1d_int2

  subroutine writenc_1d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT2(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: int
!*DeckYinxq: writenc_1d_int

  subroutine writenc_1d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: real
!*DeckYinxq: writenc_1d_real

  subroutine writenc_1d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_REAL(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: double
!*DeckYinxq: writenc_1d_double

  subroutine writenc_1d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_DOUBLE(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 1D data into NC file: double
!*DeckYinxq: writenc_1d_text

  subroutine writenc_1d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(in) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_text(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_1d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: int1
!*DeckYinxq: readnc_1d_int1

  subroutine readnc_1d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT1(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT1(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT1(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: int2
!*DeckYinxq: readnc_1d_int2

  subroutine readnc_1d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT2(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT2(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT2(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: int
!*DeckYinxq: readnc_1d_int

  subroutine readnc_1d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: real
!*DeckYinxq: readnc_1d_real

  subroutine readnc_1d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_REAL(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_REAL(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_REAL(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: double
!*DeckYinxq: readnc_1d_double

  subroutine readnc_1d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_DOUBLE(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_DOUBLE(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 1D data from NC file: double
!*DeckYinxq: readnc_1d_text

  subroutine readnc_1d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(out) :: Var(:)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 1
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_GET_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_GET_VARA_text(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_text(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_1d_text

!===================================== 2-d =====================================
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: int1
!*DeckYinxq: writenc_2d_int1

  subroutine writenc_2d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT1(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: int2
!*DeckYinxq: writenc_2d_int2

  subroutine writenc_2d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT2(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: int
!*DeckYinxq: writenc_2d_int

  subroutine writenc_2d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: real
!*DeckYinxq: writenc_2d_real

  subroutine writenc_2d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_REAL(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: double
!*DeckYinxq: writenc_2d_double

  subroutine writenc_2d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_DOUBLE(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 2D data into NC file: double
!*DeckYinxq: writenc_2d_text

  subroutine writenc_2d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(in) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_text(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_2d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: int1
!*DeckYinxq: readnc_2d_int1

  subroutine readnc_2d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT1(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT1(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT1(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: int2
!*DeckYinxq: readnc_2d_int2

  subroutine readnc_2d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT2(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT2(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT2(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: int
!*DeckYinxq: readnc_2d_int

  subroutine readnc_2d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: real
!*DeckYinxq: readnc_2d_real

  subroutine readnc_2d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_REAL(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_REAL(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_REAL(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: double
!*DeckYinxq: readnc_2d_double

  subroutine readnc_2d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_DOUBLE(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_DOUBLE(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 2D data from NC file: double
!*DeckYinxq: readnc_2d_text

  subroutine readnc_2d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(out) :: Var(:, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 2
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_GET_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_GET_VARA_text(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_text(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_2d_text

!===================================== 3-d =====================================
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: int1
!*DeckYinxq: writenc_3d_int1

  subroutine writenc_3d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT1(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: int2
!*DeckYinxq: writenc_3d_int2

  subroutine writenc_3d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT2(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: int
!*DeckYinxq: writenc_3d_int

  subroutine writenc_3d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: real
!*DeckYinxq: writenc_3d_real

  subroutine writenc_3d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_REAL(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: double
!*DeckYinxq: writenc_3d_double

  subroutine writenc_3d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_DOUBLE(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 3D data into NC file: double
!*DeckYinxq: writenc_3d_text

  subroutine writenc_3d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(in) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_text(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_3d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: int1
!*DeckYinxq: readnc_3d_int1

  subroutine readnc_3d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT1(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT1(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT1(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: int2
!*DeckYinxq: readnc_3d_int2

  subroutine readnc_3d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT2(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT2(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT2(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: int
!*DeckYinxq: readnc_3d_int

  subroutine readnc_3d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: real
!*DeckYinxq: readnc_3d_real

  subroutine readnc_3d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_REAL(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_REAL(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_REAL(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: double
!*DeckYinxq: readnc_3d_double

  subroutine readnc_3d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_DOUBLE(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_DOUBLE(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 3D data from NC file: double
!*DeckYinxq: readnc_3d_text

  subroutine readnc_3d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(out) :: Var(:, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 3
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_GET_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_GET_VARA_text(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_text(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_3d_text

!===================================== 4-d =====================================
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: int1
!*DeckYinxq: writenc_4d_int1

  subroutine writenc_4d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT1(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT1(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT1(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: int2
!*DeckYinxq: writenc_4d_int2

  subroutine writenc_4d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT2(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT2(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT2(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: int
!*DeckYinxq: writenc_4d_int

  subroutine writenc_4d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_INT(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_INT(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_INT(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: real
!*DeckYinxq: writenc_4d_real

  subroutine writenc_4d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_REAL(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_REAL(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_REAL(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: double
!*DeckYinxq: writenc_4d_double

  subroutine writenc_4d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var)
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts(1:DimNum),       &
                                counts(1:DimNum), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_PUT_VARA_DOUBLE(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_DOUBLE(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Write 4D data into NC file: double
!*DeckYinxq: writenc_4d_text

  subroutine writenc_4d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(in) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VARID(ncid, trim(VarName), varID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_PUT_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_PUT_VARA_text(ncid, varID, starts, counts, Var)
  else
    mystat=NF_PUT_VAR_text(ncid, varID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine writenc_4d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: int1
!*DeckYinxq: readnc_4d_int1

  subroutine readnc_4d_int1(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*1, intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT1(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT1(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT1(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT1(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_int1

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: int2
!*DeckYinxq: readnc_4d_int2

  subroutine readnc_4d_int2(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer*2, intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT2(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT2(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT2(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT2(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_int2

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: int
!*DeckYinxq: readnc_4d_int

  subroutine readnc_4d_int(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  integer, intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_INT(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_INT(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_INT(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_INT(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_int

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: real
!*DeckYinxq: readnc_4d_real

  subroutine readnc_4d_real(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(4), intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_REAL(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_REAL(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_REAL(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_REAL(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_real

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: double
!*DeckYinxq: readnc_4d_double

  subroutine readnc_4d_double(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  real(8), intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+1), counts(DimNum+1)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(1:DimNum) = shape(Var);
    starts(1:DimNum) = locs(1:DimNum)
    if(present(RecNum))then
      counts(DimNum+1) = 1; starts(DimNum+1) = RecNum
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_DOUBLE(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(1:DimNum) = shape(Var); counts(DimNum+1) = 1
    starts = 1; starts(DimNum+1) = RecNum
    mystat=NF_GET_VARA_DOUBLE(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_DOUBLE(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_double

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
! --- Read 4D data from NC file: double
!*DeckYinxq: readnc_4d_text

  subroutine readnc_4d_text(ncid, VarName, Var, RecNum, locs)

  integer, intent(in) :: ncid
  character(len=*), intent(in) :: VarName
  character(len=*), intent(out) :: Var(:, :, :, :)
  integer, optional, intent(in) :: RecNum
  integer, optional, intent(in) :: locs(:)

  integer, parameter :: DimNum = 4
  integer :: starts(DimNum+2), counts(DimNum+2)

  mystat=NF_INQ_VarID(ncid, trim(VarName), VarID)
  CALL check_err(mystat)

  if(present(locs))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var);
    starts(2:DimNum+1) = locs(1:DimNum); starts(1) = 1
    if(present(RecNum))then
      counts(DimNum+2) = 1; starts(DimNum+2) = RecNum
      mystat=NF_GET_VARA_text(ncid, varID, starts, counts, Var)
    else
      mystat=NF_GET_VARA_text(ncid, varID, starts(1:DimNum+1),       &
                                counts(1:DimNum+1), Var)
    endif
    CALL check_err(mystat)
    return
  endif

  if(present(RecNum))then
    counts(2:DimNum+1) = shape(Var); counts(1) = len(var); counts(DimNum+2) = 1
    starts = 1; starts(DimNum+2) = RecNum
    mystat=NF_GET_VARA_text(ncid, VarID, starts, counts, Var)
  else
    mystat=NF_GET_VAR_text(ncid, VarID, Var)
  endif
  CALL check_err(mystat)

  return
  end subroutine readnc_4d_text

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: writencb_1d

  subroutine writencb_1d(ncid, varname, var, myis, myie, myim)

  integer, intent(in) :: ncid, myis, myie, myim
  character(len=80) :: varname
  real(4), intent(in) :: var(myim)

  real(4), allocatable :: tmp(:)

  if(myis > myie)then

    allocate(tmp(myim-myie))
    tmp(1:myim-myie) = var(1:myim-myie)
    call writenc(ncid, trim(varname), tmp, locs=[myis])
    deallocate(tmp)

    allocate(tmp(myie))
    tmp(1:myie) = var(myim-myie+1:myim)
    call writenc(ncid, trim(varname), tmp, locs=[1])
    deallocate(tmp)

  else

    allocate(tmp(myim)); tmp = var
    call writenc(ncid, trim(varname), tmp, locs=[myis])
    deallocate(tmp)

  endif

  return

  end subroutine writencb_1d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: writencb_2d

  subroutine writencb_2d(ncid, varname, var, myis, myie, myim, myjs, myjm)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm
  character(len=80) :: varname
  real(4), intent(in) :: var(myim, myjm)

  real(4), allocatable :: tmp(:, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm))
    tmp(1:myim-myie, :) = var(1:myim-myie, :)
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs])
    deallocate(tmp)

    allocate(tmp(myie, myjm))
    tmp(1:myie, :) = var(myim-myie+1:myim, :)
    call writenc(ncid, trim(varname), tmp, locs=[1, myjs])
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm)); tmp = var
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs])
    deallocate(tmp)

  endif

  return

  end subroutine writencb_2d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: writencb_3d

  subroutine writencb_3d(ncid, varname, var, myis, myie, myim, myjs, myjm, kb)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm, kb
  character(len=80) :: varname
  real(4), intent(in) :: var(myim, myjm, kb)

  real(4), allocatable :: tmp(:, :, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm, kb))
    tmp(1:myim-myie, :, :) = var(1:myim-myie, :, :)
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs, 1])
    deallocate(tmp)

    allocate(tmp(myie, myjm, kb))
    tmp(1:myie, :, :) = var(myim-myie+1:myim, :, :)
    call writenc(ncid, trim(varname), tmp, locs=[1, myjs, 1])
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm, kb)); tmp = var
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs, 1])
    deallocate(tmp)

  endif

  return

  end subroutine writencb_3d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: writencb_4d

  subroutine writencb_4d(ncid, varname, var, myis, myie, myim, myjs, myjm, kb, lm)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm, kb, lm
  character(len=80) :: varname
  real(4), intent(in) :: var(myim, myjm, kb, lm)

  real(4), allocatable :: tmp(:, :, :, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm, kb, lm))
    tmp(1:myim-myie, :, :, :) = var(1:myim-myie, :, :, :)
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs, 1, 1])
    deallocate(tmp)

    allocate(tmp(myie, myjm, kb, lm))
    tmp(1:myie, :, :, :) = var(myim-myie+1:myim, :, :, :)
    call writenc(ncid, trim(varname), tmp, locs=[1, myjs, 1, 1])
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm, kb, lm)); tmp = var
    call writenc(ncid, trim(varname), tmp, locs=[myis, myjs, 1, 1])
    deallocate(tmp)

  endif

  return

  end subroutine writencb_4d
!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: readncb_1d

  subroutine readncb_1d(ncid, varname, var, myis, myie, myim)

  integer, intent(in) :: ncid, myis, myie, myim
  character(len=80) :: varname
  real(4), intent(out) :: var(myim)

  real(4), allocatable :: tmp(:)

  if(myis > myie)then

    allocate(tmp(myim-myie))
    call readnc(ncid, trim(varname), tmp, locs=[myis])
    var(1:myim-myie) = tmp(1:myim-myie)
    deallocate(tmp)

    allocate(tmp(myie))
    call readnc(ncid, trim(varname), tmp, locs=[1])
    var(myim-myie+1:myim) = tmp(1:myie)
    deallocate(tmp)

  else

    allocate(tmp(myim))
    call readnc(ncid, trim(varname), tmp, locs=[myis])
    var = tmp; deallocate(tmp)

  endif

  return

  end subroutine readncb_1d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: readncb_2d

  subroutine readncb_2d(ncid, varname, var, myis, myie, myim, myjs, myjm)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm
  character(len=80) :: varname
  real(4), intent(out) :: var(myim, myjm)

  real(4), allocatable :: tmp(:, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs])
    var(1:myim-myie, :) = tmp(1:myim-myie, :)
    deallocate(tmp)

    allocate(tmp(myie, myjm))
    call readnc(ncid, trim(varname), tmp, locs=[1, myjs])
    var(myim-myie+1:myim, :) = tmp(1:myie, :)
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs])
    var = tmp; deallocate(tmp)

  endif

  return

  end subroutine readncb_2d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: readncb_3d

  subroutine readncb_3d(ncid, varname, var, myis, myie, myim, myjs, myjm, kb)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm, kb
  character(len=80) :: varname
  real(4), intent(out) :: var(myim, myjm, kb)

  real(4), allocatable :: tmp(:, :, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm, kb))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs, 1])
    var(1:myim-myie, :, :) = tmp(1:myim-myie, :, :)
    deallocate(tmp)

    allocate(tmp(myie, myjm, kb))
    call readnc(ncid, trim(varname), tmp, locs=[1, myjs, 1])
    var(myim-myie+1:myim, :, :) = tmp(1:myie, :, :)
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm, kb))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs, 1])
    var = tmp; deallocate(tmp)

  endif

  return

  end subroutine readncb_3d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------
!*DeckYinxq: readncb_4d

  subroutine readncb_4d(ncid, varname, var, myis, myie, myim, myjs, myjm, kb, lm)

  integer, intent(in) :: ncid, myis, myie, myim, myjs, myjm, kb, lm
  character(len=80) :: varname
  real(4), intent(out) :: var(myim, myjm, kb, lm)

  real(4), allocatable :: tmp(:, :, :, :)

  if(myis > myie)then

    allocate(tmp(myim-myie, myjm, kb, lm))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs, 1, 1])
    var(1:myim-myie, :, :, :) = tmp(1:myim-myie, :, :, :)
    deallocate(tmp)

    allocate(tmp(myie, myjm, kb, lm))
    call readnc(ncid, trim(varname), tmp, locs=[1, myjs, 1, 1])
    var(myim-myie+1:myim, :, :, :) = tmp(1:myie, :, :, :)
    deallocate(tmp)

  else

    allocate(tmp(myim, myjm, kb, lm))
    call readnc(ncid, trim(varname), tmp, locs=[myis, myjs, 1, 1])
    var = tmp; deallocate(tmp)

  endif

  return

  end subroutine readncb_4d

!-------------------------------------------------------------------------------------------------
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!-------------------------------------------------------------------------------------------------

  end module netcdf_mod

!-------------------------------------------------------------------------------------------------
!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
