问题
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