!= gtool å¤‰æ•°è¡¨ã«é–¢ã™ã‚‹å„ç¨®æ‰‹ç¶šã
!
! Authors::   Eizi TOYODA, Yasuhiro MORIKAWA
! Version::   $Id: gtdata_internal_map.f90,v 1.3 2010-04-11 14:13:50 morikawa Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!

module gtdata_internal_map
  !
  !== gtool å¤‰æ•°è¡¨
  !
  ! gtool å¤‰æ•°ã¨ã„ã†ã®ã¯å®Ÿã¯ãƒžãƒƒãƒ—è¡¨ã®ã‚ãƒ¼ã¨ãªã‚‹æ•´æ•°ãƒãƒ³ãƒ‰ãƒ«ã§ã‚ã‚‹ã€‚
  ! ãƒžãƒƒãƒ—è¡¨ maptab ã«ã¯å®Ÿä½“è¡¨ã®ã‚¨ãƒ³ãƒˆãƒªç•ªå·ã¨æ¬¡å…ƒæ›¸ãæ›ãˆï¼ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿
  ! ã®è¡¨ãŒè¼‰ã£ã¦ã„ã‚‹ã€‚
  ! ã“ã®ãƒ¬ãƒ™ãƒ«ã«ãŠã‘ã‚‹å‚ç…§ã‚«ã‚¦ãƒ³ãƒˆã¯ä½œã‚‰ãªã„ã“ã¨ã«ã™ã‚‹ã€‚ã¤ã¾ã‚Šã€
  ! ãƒžãƒƒãƒ—è¡¨ã¨å®Ÿä½“è¡¨ã¯ä¸€å¯¾ä¸€å¯¾å¿œã™ã‚‹ã—ã€
  ! ãƒ¦ãƒ¼ã‚¶ãŒãƒãƒ³ãƒ‰ãƒ«ã‚’ã‚³ãƒ”ãƒ¼ã™ã‚‹ã®ã¯å‹æ‰‹ã§ã‚ã‚‹ã€‚
  ! ã‚‚ã¡ã‚ã‚“ãƒ¦ãƒ¼ã‚¶ã«ã¯å¿…ãšãŸã ï¼‘å›ž
  ! å½“è©²ãƒãƒ³ãƒ‰ãƒ«ã‚’ close ã™ãªã‚ã¡ maptabdelete ã™ã‚‹ç¾©å‹™ãŒã‚ã‚‹ã€‚

  use dc_types, only: STRING
  use gtdata_internal_vartable, only: vid_invalid, &
    & VTB_CLASS_UNUSED, VTB_CLASS_MEMORY, VTB_CLASS_NETCDF
    ! ã“ã‚Œã‚‰ã¯, å¤–éƒ¨ã‹ã‚‰ gtdata_internal_vartable ã‚’ç›´æŽ¥å‘¼ã°ãªã„ã‚ˆã†ã«ã™ã‚‹ãŸã‚,
    ! gtdata_internal_map ã‚’ä»‹ã—ã¦å…¬é–‹ã™ã‚‹.

  implicit none

  type GT_DIMMAP
    ! æ¬¡å…ƒæ›¸ãæ›ãˆè¡¨
    integer:: dimno
          ! æ£ãªã‚‰ã°å®Ÿä½“å¤‰æ•°ã®æ¬¡å…ƒç•ªå·, ä»–å¤‰æ•°å‚ç…§æ™‚ã¯éžæ£å€¤
    character(len=STRING):: url
          ! æ¬¡å…ƒå¤‰æ•°ã® url
    integer:: offset
          !=== å®Ÿä½“ã¨ gtool ãƒ¦ãƒ¼ã‚¶ã®æ ¼åç•ªå·å¯¾å¿œ
          !
          ! ãƒ¦ãƒ¼ã‚¶ã‹ã‚‰ã¿ã¦ 1..allcount ãŒå®Ÿä½“ã®
          ! (1..allcount) * step + offset ã«å†™åƒã•ã‚Œã‚‹ã€‚
          ! ã“ã‚Œã‚‰ã®å€¤ã®å¤‰æ›´ã®éš›ã¯å®Ÿä½“å¤‰æ•°ã®è¨±å®¹æ·»å—ç¯„å›²ãŠã‚ˆã³
          ! æˆé•·å¯èƒ½æ€§ã‚’ç¢ºèªã™ã‚‹å¿…è¦ã‚ã‚Šã€‚
          ! start å€¤ã«å¯¾ã™ã‚‹ã‚ªãƒ•ã‚»ãƒƒãƒˆã€‚
    integer:: step
          ! 1 ã‹ -1 ã®å€¤ã‚’ã¨ã‚‹ã“ã¨ãŒæœŸå¾…ã•ã‚Œã‚‹ã€‚
    integer:: allcount
          ! è¦‹æŽ›ã‘ã®æ ¼åç•ªå·ä¸Šé™: start + count * stride <= allcount
    integer:: start
          !=== ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿æœ¬ä½“
          ! å…¥å‡ºåŠ›ç¯„å›²ã¯ (start:start+count*stride:stride) ã§ã‚ã‚‹ã€‚
          ! ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ start å€¤
    integer:: count
          ! ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ count å€¤
    integer:: stride
          ! ã‚¤ãƒ†ãƒ¬ãƒ¼ã‚¿ stride å€¤
    logical:: scalar
          ! ã‚¹ã‚«ãƒ©ãƒ¼å¤‰æ•°ã§ã‚ã‚‹å ´åˆ, .true.
  end type GT_DIMMAP

  type MAP_TABLE_ENTRY
    ! ãƒžãƒƒãƒ—è¡¨ã®åž‹
    integer:: vid
    integer:: ndims
    type(GT_DIMMAP), pointer:: map(:)
  end type MAP_TABLE_ENTRY

  type(MAP_TABLE_ENTRY), save, target, allocatable:: maptab(:)
  integer, parameter:: maptab_init_size = 16

  public:: MapTabAdd, MapTabDelete, map_lookup
  public:: var_class, map_create, map_to_internal_specs, dimrange
  public:: vid_invalid, &
    &      VTB_CLASS_UNUSED, VTB_CLASS_MEMORY, VTB_CLASS_NETCDF
  private:: maptab, maptab_init_size

  interface dimrange
    module procedure dimrange_by_dimno
  end interface

contains

  subroutine dimrange_by_dimno(var, dimno, dimlo, dimhi)
    ! å¤‰æ•°ã¨æ¬¡å…ƒç•ªå·ã‚’æŒ‡å®šã—ã¦ã€å½“è©²æ¬¡å…ƒã®å†…éƒ¨çš„æ·»å—ç•ªå·ç¯„å›²ã‚’å¾—ã‚‹
    use gtdata_types, only: gt_variable
    use gtdata_generic, only: open, close
    use gtdata_internal_vartable, only: dimrange
    type(gt_variable), intent(in):: var
    integer, intent(in):: dimno
    integer, intent(out):: dimlo, dimhi
    type(gt_variable):: dimvar
    integer:: vid
    call open(dimvar, var, dimno, count_compact=.true.)
    call map_lookup(dimvar, vid=vid)
    call dimrange(vid, dimlo, dimhi)
    call close(dimvar)
  end subroutine dimrange_by_dimno

  subroutine map_dup(var, source_var)
    ! å¤‰æ•° source_var ã®è¤‡å†™ var ã‚’ä½œæˆã™ã‚‹
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: VarTableAdd, VarTableLookup
    use dc_trace, only: DbgMessage
    type(gt_variable), intent(out):: var
    type(gt_variable), intent(in):: source_var
    integer:: vid, mid1, mid2, vid2, nd, class, cid
    call map_lookup(source_var, vid=vid)
    if (vid < 0) then
      var = gt_variable(-1)
      return
    endif
    if (vid == 0) then
      vid2 = 0
    else
      call VartableLookup(vid, class=class, cid=cid)
      call VarTableAdd(vid2, class, cid)
    endif
    call MapTabAdd(var%mapid, vid2)
    mid1 = source_var%mapid
    mid2 = var%mapid
    maptab(mid2)%ndims = maptab(mid1)%ndims
    if (associated(maptab(mid1)%map)) then
      nd = size(maptab(mid1)%map)
      allocate(maptab(mid2)%map(nd))
      maptab(mid2)%map(1:nd) = maptab(mid1)%map(1:nd)
    else
      nullify(maptab(mid2)%map)
    endif
    call DbgMessage('map_dup mapid(%d from %d) vid(%d from %d)', &
      & i=(/mid2, mid1, maptab(mid2)%vid, maptab(mid1)%vid/))
  end subroutine map_dup

  subroutine map_create(var, class, cid, ndims, allcount, stat)
    ! å¤‰æ•° var ã‚’ä½œæˆã™ã‚‹ã€‚å†…éƒ¨ç¨®åˆ¥ class, å†…éƒ¨è˜åˆ¥å cid,
    ! å¤–è¦‹çš„æ¬¡å…ƒæ•° ndims, å¤–è¦‹çš„æ¬¡å…ƒé•· allcount(:) ã‚’ä¸Žãˆã‚‹ã€‚
    ! ã‚ªãƒ•ã‚»ãƒƒãƒˆã‚¼ãƒã‚’ä»®å®šã—ã¦è«¸å…ƒã®åˆæœŸåŒ–ãŒè¡Œã‚ã‚Œã‚‹ã€‚
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: VarTableAdd
    use dc_error, only: NF90_ENOTVAR, GT_ENOMOREDIMS, DC_NOERR
    type(gt_variable), intent(out):: var
    integer, intent(in):: class, cid, ndims, allcount(:)
    integer, intent(out):: stat
    type(GT_DIMMAP), pointer:: map(:)
    integer:: vid, i
  continue

    stat = DC_NOERR
    if ( ndims < 0 ) then
      stat = GT_ENOMOREDIMS
      goto 999
    end if
    call VarTableAdd(vid, class, cid)
    call MapTabAdd(var%mapid, vid)
    if (ndims > 0) then
      call map_allocate(map, ndims)
      maptab(var%mapid)%ndims = ndims
      maptab(var%mapid)%map => map

      do, i = 1, ndims
        map(i)%dimno = i
        map(i)%allcount = allcount(i)
        map(i)%count = allcount(i)
        map(i)%offset = 0
        map(i)%start = 1
        map(i)%step = 1
        map(i)%stride = 1
        map(i)%scalar = .false.
      enddo
    else
      ! ã‚¹ã‚«ãƒ©ãƒ¼å¤‰æ•° (ndims = 0) ã®å ´åˆ
      call map_allocate(map, 1)
      maptab(var%mapid)%ndims = 0
      maptab(var%mapid)%map => map
      map(1)%dimno = 1
      map(1)%allcount = 1
      map(1)%count = 1
      map(1)%offset = 0
      map(1)%start = 1
      map(1)%step = 1
      map(1)%stride = 1
      map(1)%scalar = .true.
    end if

999 continue
    return
  end subroutine map_create

  subroutine MapTabAdd(mapid, vid)
    ! ã™ã§ã«å®Ÿä½“è¡¨ã«è¿½åŠ ã•ã‚ŒãŸã‚¨ãƒ³ãƒˆãƒªç•ªå· vid ã‚’æŒ‡å®šã—ã¦ã€
    ! ãƒžãƒƒãƒ—è¡¨ã«ã‚¨ãƒ³ãƒˆãƒªã‚’è¿½åŠ ã™ã‚‹ã€‚
    integer, intent(out):: mapid
    integer, intent(in):: vid
    type(MAP_TABLE_ENTRY), allocatable:: tmp_maptab(:)
    integer:: i, n
    ! å¿…è¦ãªã‚‰åˆæœŸç¢ºä¿
    if (.not. allocated(maptab)) then
      allocate(maptab(maptab_init_size))
      maptab(:)%vid = vid_invalid
      do, n = 1, maptab_init_size
        nullify(maptab(n)%map)
      enddo
    endif
    ! ç©ºãåœ°ãŒã‚ã‚Œã°ãã“ã«å‰²ã‚Šå½“ã¦
    do, i = 1, size(maptab)
      if (maptab(i)%vid == vid_invalid) then
        mapid = i
        maptab(mapid)%vid = vid
        return
      endif
    enddo
    ! ç©ºãåœ°ã¯ãªã‹ã£ãŸã®ã ã‹ã‚‰å€å¹…ç¢ºä¿
    n = size(maptab)
    allocate(tmp_maptab(n))
    tmp_maptab(:) = maptab(:)
    deallocate(maptab)
    allocate(maptab(n * 2))
    ! ç¢ºä¿ã—ãŸã¨ã“ã‚ã¯ã‚¯ãƒªã‚¢
    maptab(1:n) = tmp_maptab(1:n)
    do, i = n + 1, (2 * size(tmp_maptab))
      maptab(i)%vid = vid_invalid
      nullify(maptab(i)%map)
    enddo
    deallocate(tmp_maptab)
    mapid = n + 1
    maptab(mapid)%vid = vid
  end subroutine MapTabAdd

  subroutine MapTabDelete(var, err)
    ! å¤‰æ•° var ã‚’ãƒžãƒƒãƒ—è¡¨ã‹ã‚‰å‰Šé™¤ã™ã‚‹ã€‚
    ! å®Ÿä½“è¡¨ã«ã¯æ‰‹ã‚’ã¤ã‘ãªã„ã€‚
    use dc_error, only: NF90_ENOTVAR, STOREERROR, DC_NOERR
    use gtdata_types, only: gt_variable
    use dc_trace, only: DbgMessage
    implicit none
    type(gt_variable), intent(in):: var
    logical, intent(out), optional:: err
    integer:: mapid
    mapid = var%mapid
    if (.not. allocated(maptab)) goto 999
    if (mapid <= 0 .or. mapid > size(maptab)) goto 999
    if (maptab(mapid)%vid == vid_invalid) goto 999
    maptab(mapid)%vid = vid_invalid
    if (associated(maptab(mapid)%map)) deallocate(maptab(mapid)%map)
    call storeerror(DC_NOERR, 'maptabdelete', err)
    call DbgMessage('gtdata_internal_map table %d deleted', i=(/mapid/))
    return
999 continue
    call storeerror(NF90_ENOTVAR, 'maptabdelete', err)
  end subroutine MapTabDelete

  subroutine map_lookup(var, vid, map, ndims)
    ! åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ç•ªå·ã®å¤‰æ•°è¡¨ã®ä¸èº«ã‚’è¿”ã™
    use gtdata_types, only: gt_variable
    type(GT_VARIABLE), intent(in):: var
    integer, intent(out), optional:: vid
    type(GT_DIMMAP), intent(out), optional:: map(:)
    integer, intent(out), optional:: ndims
    if (.not. allocated(maptab)) goto 999
    if (var%mapid <= 0 .or. var%mapid > size(maptab)) goto 999
    if (maptab(var%mapid)%vid == vid_invalid) goto 999
    if (present(vid)) vid = maptab(var%mapid)%vid
    if (present(map)) map(:) = maptab(var%mapid)%map(1:size(map))
    if (present(ndims)) ndims = maptab(var%mapid)%ndims
    return
999 continue
    if (present(vid)) vid = vid_invalid
    if (present(map)) then
      map(:)%dimno = -1
      map(:)%url = " "
    endif
    if (present(ndims)) ndims = 0
  end subroutine map_lookup

  subroutine map_set(var, map, stat)
    ! åŒã˜ãƒ•ã‚¡ã‚¤ãƒ«ç•ªå·ã®å¤‰æ•°è¡¨ã®å€¤ã‚’è¨å®šã™ã‚‹
    use gtdata_types, only: gt_variable
    use dc_error, only: NF90_ENOTVAR, GT_ENOMOREDIMS, DC_NOERR
    type(gt_variable), intent(in):: var
    type(GT_DIMMAP), intent(in):: map(:)
    integer, intent(out):: stat
    if (.not. allocated(maptab)) goto 999
    if (var%mapid <= 0 .or. var%mapid > size(maptab)) goto 999
    if (maptab(var%mapid)%vid == vid_invalid) goto 999
    if (size(map) > size(maptab(var%mapid)%map)) then
      stat = GT_ENOMOREDIMS
      return
    endif
    maptab(var%mapid)%map(1:size(map)) = map(:)
    stat = DC_NOERR
    return
999 continue
    stat = NF90_ENOTVAR
  end subroutine map_set

  subroutine var_class(var, class, cid)
    ! å¤‰æ•° var ã‚’æŒ‡å®šã—ã¦ã€å†…éƒ¨ç¨®åˆ¥ class, å†…éƒ¨è˜åˆ¥å cid ã‚’å¾—ã‚‹ã€‚
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: vartablelookup
    type(gt_variable), intent(in):: var
    integer, intent(out), optional:: class, cid
    integer:: vid
    call map_lookup(var, vid=vid)
    call vartablelookup(vid, class=class, cid=cid)
  end subroutine var_class

  subroutine map_set_ndims(var, ndims, stat)
    ! å¤‰æ•° var ã®æ¬¡å…ƒæ•°ã‚’ ndims ã«å¤‰ãˆã‚‹ã€‚
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: vartablelookup
    use dc_error, only: NF90_ENOTVAR, GT_ENOMOREDIMS, DC_NOERR
    type(gt_variable), intent(in):: var
    integer, intent(in):: ndims
    integer, intent(out):: stat
    integer:: vid
    call map_lookup(var, vid=vid)
    if (vid == vid_invalid) then
      stat = NF90_ENOTVAR
      return
    endif
    if (.not. associated(maptab(var%mapid)%map)) then
      if (ndims == 0) then
        stat = DC_NOERR
        maptab(var%mapid)%ndims = 0
      else
        stat = GT_ENOMOREDIMS
      endif
    else
      if (ndims > size(maptab(var%mapid)%map)) then
        stat = GT_ENOMOREDIMS
      else
        stat = DC_NOERR
        maptab(var%mapid)%ndims = ndims
      endif
    endif
  end subroutine map_set_ndims

  subroutine map_set_rank(var, rank, stat)
    ! å¤‰æ•° var ã®ãƒ©ãƒ³ã‚¯(éžç¸®é€€æ¬¡å…ƒæ•°)ã‚’ rank ã«æ¸›ã‚‰ã™ã‚ˆã†ã«
    ! count å€¤ã‚’1ã«æ¸›ã‚‰ã™ã€‚ãƒ©ãƒ³ã‚¯ã‚’å¢—ã‚„ã™ã“ã¨ã‚„å¤–è¦‹æ¬¡å…ƒæ•°ã®æ“ä½œã¯ã—ãªã„ã€‚
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: vartablelookup
    use dc_error, only: NF90_ENOTVAR, GT_ENOMOREDIMS, DC_NOERR
    type(gt_variable), intent(in):: var
    integer, intent(in):: rank
    integer, intent(out):: stat
    type(GT_DIMMAP), pointer:: tmpmap(:)
    integer:: ndims
    integer:: vid, nd
    call map_lookup(var, vid, ndims=ndims)
    if (vid == vid_invalid) then
      stat = NF90_ENOTVAR
      return
    endif
    if (ndims < rank) then
      stat = GT_ENOMOREDIMS
      return
    endif
    tmpmap => maptab(var%mapid)%map
    do, nd = ndims, 1, -1
      if (count(tmpmap(1:ndims)%count > 1) <= rank) exit
      tmpmap(nd)%count = 1
    enddo
    stat = DC_NOERR
  end subroutine map_set_rank

  subroutine map_to_internal_specs(var, specs, ndims)
    ! ãƒžãƒƒãƒ—è¡¨ã‹ã‚‰ netCDF ã®å¼•æ•°ã«ãµã•ã‚ã—ã„ start, count, stride, imap
    ! ã‚’ä½œæˆã™ã‚‹ã€‚ãŸã ã—ã€stride ãŒè² ã«ãªã‚‹ã°ã‚ã„ã¯å¯¾ç–ã•ã‚Œã¦ã„ãªã„ã€‚
    ! (æš«å®šçš„ã« gdncvarget/gdncvarput ãŒå¯¾å¿œã—ã¦ã„ã‚‹)
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: num_dimensions => ndims
    type(gt_variable), intent(in):: var
    integer, pointer:: specs(:, :)
    integer, intent(out), optional:: ndims
    type(GT_DIMMAP), pointer:: it
    integer:: vid, i, j, imap, internal_ndims
    integer:: external_ndims
  continue
    call map_lookup(var, vid, ndims=external_ndims)
    internal_ndims = num_dimensions(vid)
    if (present(ndims)) ndims = internal_ndims
    allocate(specs(max(1, internal_ndims), 4))
    specs(:, 1) = 1
    specs(:, 2) = 1
    specs(:, 3) = 1
    specs(:, 4) = 0
    imap = 1
    do, i = 1, size(maptab(var%mapid)%map)
      it => maptab(var%mapid)%map(i)
      j = it%dimno
      if (j > 0 .and. j <= internal_ndims) then
        specs(j, 1) = it%start + it%offset
        specs(j, 2) = it%count
        if (i > external_ndims) specs(j, 2) = 1
        specs(j, 3) = it%stride * it%step
        specs(j, 4) = imap
      endif
      imap = imap * it%count
    enddo
  end subroutine map_to_internal_specs

  subroutine map_allocate(map, ndims)
    ! æ¬¡å…ƒè¡¨ã‚¨ãƒ³ãƒˆãƒªã« ndims å€‹ã®ã‚¨ãƒ³ãƒˆãƒªã‚’å‰²ã‚Šä»˜ã‘åˆæœŸåŒ–ã™ã‚‹ã€‚
    type(GT_DIMMAP), pointer:: map(:)
    integer, intent(in):: ndims
    if (ndims <= 0) then
      nullify(map)
      return
    endif
    allocate(map(1:ndims))
    map(1:ndims)%dimno = -1
    map(1:ndims)%url = ' '
    map(1:ndims)%allcount = 0
    map(1:ndims)%offset = 0
    map(1:ndims)%step = 1
    map(1:ndims)%start = 1
    map(1:ndims)%count = 0
    map(1:ndims)%stride = 1
    map(1:ndims)%scalar = .false.
  end subroutine map_allocate

  subroutine map_apply(var, map)
    ! å¤‰æ•° var ã«ãƒžãƒƒãƒ—è¡¨ map ã‚’çµ„ã¿åˆã‚ã›ã‚‹
    use gtdata_types, only: gt_variable
    type(GT_VARIABLE), intent(inout):: var
    type(GT_DIMMAP), pointer:: map(:)
    type(GT_DIMMAP), pointer:: tmpmap(:), varmap
    integer:: i, nd
    nd = size(map)
    allocate(tmpmap(nd))
    do, i = 1, nd
      tmpmap(i)%allcount = map(i)%allcount
      tmpmap(i)%count = map(i)%count
      if (map(i)%dimno > 0) then
        varmap => maptab(var%mapid)%map(map(i)%dimno)
        tmpmap(i)%url = varmap%url
        tmpmap(i)%dimno = varmap%dimno
        tmpmap(i)%offset = varmap%offset + map(i)%offset
        tmpmap(i)%step = varmap%step * map(i)%step
      else
        tmpmap(i)%url = map(i)%url
        tmpmap(i)%dimno = 0
        tmpmap(i)%offset = map(i)%offset
        tmpmap(i)%step = map(i)%step
      endif
    enddo
    deallocate(map)
    map => tmpmap
  end subroutine map_apply

  subroutine map_resize(var, ndims)
    ! å¤‰æ•° var ã®æ¬¡å…ƒè¡¨ã®å¤§ãã•ã‚’å¤‰ãˆã‚‹
    use gtdata_types, only: gt_variable
    type(GT_VARIABLE), intent(in):: var
    integer, intent(in):: ndims
    type(GT_DIMMAP), pointer:: newmap(:)
    type(GT_DIMMAP), pointer:: tmpmap(:)
    integer:: n
    if (associated(maptab(var%mapid)%map)) then
      tmpmap => maptab(var%mapid)%map
      call map_allocate(newmap, ndims)
      n = min(size(tmpmap), ndims)
      newmap(1:n) = tmpmap(1:n)
      deallocate(tmpmap)
      maptab(var%mapid)%map => newmap
      newmap(n+1:ndims)%dimno = -1
      newmap(n+1:ndims)%url = ' '
      newmap(n+1:ndims)%allcount = 0
      newmap(n+1:ndims)%offset = 0
      newmap(n+1:ndims)%step = 1
      newmap(n+1:ndims)%start = 1
      newmap(n+1:ndims)%count = 0
      newmap(n+1:ndims)%stride = 1
    else
      call map_allocate(maptab(var%mapid)%map, ndims)
      n = 1
    endif
  end subroutine map_resize

  subroutine gtvar_dump(var)
    ! å¤‰æ•°ã®ãƒ—ãƒãƒ‘ãƒ†ã‚£ã‚’å‡ºåŠ›
    use gtdata_types, only: gt_variable
    use gtdata_internal_vartable, only: vartable_dump
    use dc_trace, only: debug, DbgMessage
    type(gt_variable), intent(in):: var
    integer:: idim, imap
    logical:: dbg_mode
  continue
    call Debug( dbg_mode )
    if (.not. dbg_mode) return
    imap = var%mapid
    if (imap < 1 .or. imap > size(maptab)) then
      call DbgMessage('[gt_variable %d: invalid id]', i=(/imap/))
      return
    endif
    if (associated(maptab(imap)%map)) then
      call DbgMessage('[gt_variable %d: ndims=%d, map.size=%d]', &
        & i=(/imap, maptab(imap)%ndims, size(maptab(imap)%map)/))
      do, idim = 1, size(maptab(imap)%map)
        call DbgMessage('[dim%d dimno=%d ofs=%d step=%d' &
          &// ' all=%d start=%d count=%d stride=%d url=%c]', &
          & c1=trim(maptab(imap)%map(idim)%url), &
          & i=(/idim, maptab(imap)%map(idim)%dimno, &
          & maptab(imap)%map(idim)%offset, &
          & maptab(imap)%map(idim)%step, &
          & maptab(imap)%map(idim)%allcount, &
          & maptab(imap)%map(idim)%start, &
          & maptab(imap)%map(idim)%count, &
          & maptab(imap)%map(idim)%stride/))
      enddo
    else
      call DbgMessage('[gt_variable %d: ndims=%d, map=null]', &
        & i=(/imap, maptab(imap)%ndims/))
    endif
    call vartable_dump(maptab(imap)%vid)
  end subroutine gtvar_dump

  integer function dimord_skip_compact(dimord, map) result(result)
    ! æ¬¡å…ƒè¡¨ã®ä¸ã§éžç¸®é€€æ¬¡å…ƒã ã‘ã‚’æ•°ãˆãŸæ¬¡å…ƒç•ªå· dimord ã®æ¬¡å…ƒã‚’
    ! ç‰¹å®šã—ã€å¤–éƒ¨å‘ã‘ã®æ¬¡å…ƒç•ªå·ã‚’è¿”ã™ã€‚
    use dc_trace, only: DbgMessage
    integer, intent(in):: dimord
    type(GT_DIMMAP), intent(in):: map(:)
    integer:: nd, id
    result = -1
    nd = 0
    do, id = 1, size(map)
      if (map(id)%count < 2) cycle
      nd = nd + 1
      if (nd < dimord) cycle
      result = id
      call DbgMessage('compact dim skip: %d <= %d', i=(/result, dimord/))
      exit
    enddo
  end function dimord_skip_compact

end module gtdata_internal_map