! anvaropenbydimord.f90 - open(AN_VARIABLE, AN_VARIABLE, integer)
! Copyright (C) GFD Dennou Club, 2000.  All rights reserved
!
! open(dimvar, var, dimord, [count_compact], [err]) は
! 既に開かれた変数 var の ord 番目の次元にあたる変数を
! 開き dimvar に格納する。順序 ord は現在の入出力範囲が
! 幅１になっている (コンパクト化している）を飛ばした
! 順序であるが、count_compact に真を指定すると
! すべての次元のなかの順序になる。
!
! ord == 0 の場合は変数自体を再度開く。これは参照カウンタを
! 増加させる手段である。
!
subroutine ANVarOpenByDimOrd(dimvar, var, dimord, &
    count_compact, err)
    use an_types, only: AN_VARIABLE
    use an_file
    use netcdf_f77
    use dc_error
    implicit none
    type(AN_VARIABLE), intent(inout):: dimvar
    type(AN_VARIABLE), intent(in):: var
    integer, intent(in):: dimord
    logical, intent(in), optional:: count_compact
    logical, intent(out), optional:: err
    character(len = NF_MAX_NAME):: dimname
    logical:: scan_all
    integer:: idim, i, stat
continue
    ! オプショナル引数のデフォルト処理
    scan_all = .FALSE.
    if (present(count_compact)) scan_all = count_compact
    ! 開くファイルの検査
    if (.not. associated(var%dimids)) then  
        stat = NF_ENOTVAR
        goto 999
    endif
    !
    ! dimord == 0 の特別扱い
    !
    if (dimord == 0) then
        dimvar = var
        call ANFileReopen(dimvar%fileid, err)
        i = size(var%dimids)
        allocate(dimvar%dimids(i), dimvar%allcount(i), dimvar%start(i), &
            dimvar%count(i), dimvar%stride(i), stat=stat)
        dimvar%dimids(:) = var%dimids(:)
        dimvar%allcount(:) = var%allcount(:)
        dimvar%start(:) = var%start(:)
        dimvar%count(:) = var%count(:)
        dimvar%stride(:) = var%stride(:)
        dimvar%attrid = 0
        if (stat /= 0) stat = NF_ENOMEM
        goto 999
    endif
    !
    ! 次元 id の探索
    !
    stat = 0
    if (scan_all) then
        idim = dimord
        if (idim > size(var%count)) stat = GT_ENOMOREDIMS
    else
        idim = 0
        stat = dimord
        do, i = 1, size(var%count)
            if (var%count(i) <= 1) cycle
            stat = stat - 1
            if (stat == 0) then
                idim = i
                exit
            endif
        enddo
    endif
    if (stat /= 0) then
        stat = GT_ENOMOREDIMS
        goto 999
    endif
    dimvar%fileid = var%fileid
    dimvar%dimid = var%dimids(idim)
    !
    ! 決定された次元 id を使って変数 id の確定を試みる
    !
    stat = nf_inq_dimname(dimvar%fileid, dimvar%dimid, dimname)
    if (stat /= NF_NOERR) goto 999
    stat = nf_inq_varid(dimvar%fileid, dimname, dimvar%varid)
    if (stat == NF_NOERR) then
        ! 次元と同名の変数が自分自身を唯一の次元とすることを確認
        call ANVarTestDimvar(dimvar%fileid, dimvar%varid, dimvar%dimid, stat)
        if (stat /= NF_NOERR) goto 999
    else if (stat == NF_ENOTVAR) then
        ! 変数が対応しなければ処理は単純
        dimvar%varid = 0
        stat = NF_NOERR
    else 
        goto 999
    endif
    !
    ! その他の AN_VARIABLE の成分の初期化
    !
    call ANFileReopen(dimvar%fileid)
    allocate(dimvar%dimids(1), dimvar%allcount(1), dimvar%start(1), &
        dimvar%count(1), dimvar%stride(1))
    dimvar%dimids(1) = dimvar%dimid
    dimvar%allcount(1) = var%allcount(idim)
    dimvar%start(1) = var%start(idim)
    dimvar%count(1) = var%count(idim)
    dimvar%stride(1) = var%stride(idim)
    if (var%growable == idim) then
        dimvar%growable = 1
    else
        dimvar%growable = 0
    endif
    dimvar%attrid = 0
999 continue
    call StoreError(stat, 'ANVarOpenByDimOrd', err, cause_i=dimord)
    return
contains

    ! netCDF 変数 (ncid, varid) が次元 dimid を唯一の次元と
    ! する変数になっていることを確認する。そうなら stat = NF_NOERR
    subroutine ANVarTestDimvar(ncid, varid, dimid, stat)
        use netcdf_f77
        use dc_error
        integer, intent(in):: ncid, varid, dimid
        integer, intent(out):: stat
        integer:: ndims
        integer:: dimids(1)
    continue
        stat = nf_inq_varndims(ncid, varid, ndims)
        if (stat /= NF_NOERR) return
        if (ndims <= 0) stat = GT_EDIMNODIM
        if (ndims > 1) stat = GT_EDIMMULTIDIM
        if (stat /= NF_NOERR) return
        stat = nf_inq_vardimid(ncid, varid, dimids)
        if (stat /= NF_NOERR) return
        if (dimids(1) /= dimid) stat = GT_EDIMOTHERDIM        
    end subroutine
    
end subroutine
