How to allocate size of Netcdf fortran array at run time?

时光怂恿深爱的人放手 提交于 2020-01-05 05:35:07

问题


I have a netCDF 4.4 file which has four dimensions- time, latitude,longitude, level. I want to be able to read the latitude and longitude values from this file and store them in a single dimensional array. However I do not know the size of the latitude array or longitude array and I so cannot allocate the size at the time of the declaration of the two arrays lat and lon. Each netCDF file that will be processed will have it's own lat and lon size and so it is not possible to declare this at compile time. So I did declare this using Fortran's allocate but this does not do what I want it to do. It prints 0 as the values of lats and lons. Where am I going wrong ?

  Variables for input Z file : height level
  character*80 in_cfn,varname
  integer      reason,i,in_ndim,ierr
  integer ndims_in, nvars_in, ngatts_in, unlimdimid_in
  integer lat_varid,lon_varid
  character*(*) LAT_NAME, LON_NAME
  parameter (LAT_NAME='lat', LON_NAME='lon')
  real,allocatable, dimension(:) :: lats
  real,allocatable, dimension(:) :: lons

  call system('ls hgt_*.nc > hgtFiles.txt')

  open(10,file='hgtFiles.txt',action="read")
  varname = "hgt"
  do
     read(10,*,IOSTAT=reason) in_cfn
     if (reason/=0) EXIT
     print *,in_cfn
     retval = nf_open(in_cfn,NF_NOWRITE,ncid)
     if (retval .ne. nf_noerr) call handle_err(retval)
     retval = nf_inq(ncid,ndims_in,nvars_in,ngatts_in,unlimdimid_in)
     retval = nf_inq_varid(ncid,LAT_NAME,lat_varid)
     if (retval .ne. nf_noerr) call handle_err(retval)
     retval = nf_inq_varid(ncid, LON_NAME, lon_varid)
     if (retval .ne. nf_noerr) call handle_err(retval)
     retval = nf_get_var_real(ncid, lat_varid, lats)
    if (retval .ne. nf_noerr) call handle_err(retval)
     retval = nf_get_var_real(ncid, lon_varid, lons)
     print *,size(lons)

  end do
  close(10)

  stop

  end

回答1:


I'm usually using Fortran 90 NetCDF Module. But the Fortran 77 interface works similar.

You can get the length of a dimension with a call to NF_INQ_DIMLEN

I've made a Fortran 77 compliant (hopefully) program to read in the latitude array and print it to the screen:

      PROGRAM READ_LAT
        IMPLICIT NONE
        INCLUDE 'netcdf.inc'
        INTEGER NCID, LATID, LATVARID, LATLEN
        REAL LATDATA[ALLOCATABLE](:)
        CHARACTER*(*) FILENAME
        CHARACTER*(*) LATNAME
        PARAMETER (FILENAME='data.nc', LATNAME='lat')

        CALL CHECK( NF_OPEN(FILENAME, NF_NOWRITE, NCID) )
        CALL CHECK( NF_INQ_DIMID(NCID, LATNAME, LATID) )
        CALL CHECK( NF_INQ_DIMLEN(NCID, LATID, LATLEN) )

        ALLOCATE(LATDATA(LATLEN))

        CALL CHECK( NF_INQ_VARID(NCID, LATNAME, LATVARID) )
        CALL CHECK( NF_GET_VAR_REAL(NCID, LATVARID, LATDATA) )

        WRITE(*, '(F10.4)') LATDATA

        CALL CHECK( NF_CLOSE(NCID) )

      CONTAINS

        SUBROUTINE CHECK( ERRORCODE )
            IMPLICIT NONE
            INTEGER ERRORCODE
            IF (ERRORCODE .ne. NF_NOERR) THEN
                PRINT *, "Encountered Error ", ERRORCODE
                STOP
            END IF
        END SUBROUTINE
      END PROGRAM

Same program as Fortran 90+:

program read_latitude
    use netcdf
    implicit none
    integer :: ncid, latid, latvarid, latlen
    real, allocatable :: latdata(:)
    character(len=*), parameter :: filename='data.nc'
    character(len=*), parameter :: latname = 'lat'

    call check( nf90_open(filename, NF90_NOWRITE, ncid) )
    call check( nf90_inq_dimid(ncid, latname, latid) )
    call check( nf90_inquire_dimension(ncid, latid, len=latlen) )

    allocate( latdata(latlen) )

    call check( nf90_inq_varid(ncid, latname, latvarid) )
    call check( nf90_get_var(ncid, latvarid, latdata) )

    write(*, '(F10.4)') latdata

    call check( nf90_close(ncid) )

    contains

        subroutine check(errorcode)
            implicit none
            integer, intent(in) :: errorcode
            if (errorcode /= NF90_NOERR) then
                write(*, '(A, I0)') "Encountered Error ", errorcode
                write(*, '(A)') nf90_strerror(errorcode)
                stop 1
            end if
        end subroutine check
end program read_latitude


来源:https://stackoverflow.com/questions/38324545/how-to-allocate-size-of-netcdf-fortran-array-at-run-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!