Recipe: Fortran program as OPeNDAP client: Difference between revisions
Line 153: | Line 153: | ||
character(len=256) :: T_file | character(len=256) :: T_file | ||
! | ! 4D array: (lon,lat,lev,time) | ||
! ------------------------------------ | ! ------------------------------------ | ||
real, allocatable :: T(:,:,:,:) | real, allocatable :: T(:,:,:,:) ! global data | ||
real, allocatable :: Tsub(:,:,:,:) ! subset of global data | |||
! Miscellaneous | ! Miscellaneous | ||
Line 161: | Line 162: | ||
integer :: ierr | integer :: ierr | ||
integer :: im, jm, lm | integer :: im, jm, lm | ||
real :: minlat, minlon, maxlat, maxlon | |||
integer :: im_sub, jm_sub | |||
integer :: imin, imax, jmin, jmax | |||
integer :: ncid, varid | integer :: ncid, varid | ||
integer :: start(4), count(4) | integer :: start(4), count(4) | ||
Line 171: | Line 175: | ||
T_file = "http://opendap.nccs.nasa.gov:9090/dods/OSSE/GEOS-5.12/BETA9/0.5000_deg/inst/inst01hr_3d_T_Cv" | T_file = "http://opendap.nccs.nasa.gov:9090/dods/OSSE/GEOS-5.12/BETA9/0.5000_deg/inst/inst01hr_3d_T_Cv" | ||
! | ! Open file and get var id | ||
! ------------------------ | |||
! ------------------------ | |||
call check(nf90_open(T_file,NF90_NOWRITE,ncid), "opening T file") | call check(nf90_open(T_file,NF90_NOWRITE,ncid), "opening T file") | ||
call check(nf90_inq_varid(ncid,"t",varid), "getting T varid") | call check(nf90_inq_varid(ncid,"t",varid), "getting T varid") | ||
! Read global temperature data | |||
! ---------------------------- | |||
allocate(T(im,jm,lm,1)) ! global 4D array with 1 time level | |||
start = [1, 1, 1, 11772] ! time level 11772 corresponds to 2006/09/18, 9z | |||
count = [im, jm, lm, 1] ! 1 time level, 3D (lon,lat,lev) array | |||
write(*,*) 'Reading global T...' | |||
call check(nf90_get_var(ncid,varid,T,start=start,count=count), "reading T") | call check(nf90_get_var(ncid,varid,T,start=start,count=count), "reading T") | ||
write(*,*)'T: ', maxval(T),minval(T) | |||
! | ! Read temperature over US | ||
! ----------------------- | ! lons = -180:0.5:179.5 | ||
write(*,*)'T: ', maxval( | ! lats = -90:0.5:90 | ||
! ------------------------ | |||
write(*,*) 'Reading T over US' | |||
minlon = -130. | |||
maxlon = -65. | |||
minlat = 25. | |||
maxlat = 50. | |||
imin = nint((minlon + 180.)/0.5) | |||
imax = nint((maxlon + 180.)/0.5) | |||
jmin = nint((minlat + 90.)/0.5) | |||
jmax = nint((maxlat + 90.)/0.5) | |||
im_sub = imax-imin+1 | |||
jm_sub = jmax-jmin+1 | |||
allocate(Tsub(im_sub,jm_sub,lm,1)) ! global 4D array with 1 time level | |||
start = [1, 1, 1, 11772] ! time level 11772 corresponds to 2006/09/18, 9z | |||
count = [im_sub, jm_sub, lm, 1] ! 1 time level, 3D (lon,lat,lev) array | |||
call check(nf90_get_var(ncid,varid,Tsub,start=start,count=count), "reading Tsub") | |||
write(*,*)'Tsub: ', maxval(Tsub),minval(Tsub) | |||
! close file, release memory | |||
call check(nf90_close(ncid), "closing T file") | |||
deallocate(T) | deallocate(T) | ||
deallocate(Tsub) | |||
! All done | ! All done |
Revision as of 13:09, 27 October 2014
Back to G5NR Data Access Guide.
First, we ensure that out NetCDF-4 library has been built with Fortran, HDF5 and OPeNDAP support. All three queries
> nc-config --has-f90 > nc-config --has-hdf5 > nc-config --has-dap
should return yes.
Read downloaded nc4 file
We first download the collection inst01hr_3d_T_Cv for 2006-Sep-18/0900z as described here. The downloaded file is c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4
. The code below does the following
- reads global temperature data and computes its max/min
- reads a subset of the data and computes the subset's max/min
Code
program g5nr_reader
use netcdf ! for reading the NR files
implicit none
! File name
! ---------
character(len=256) :: T_file
! 4D array: (lon,lat,lev,time)
! ------------------------------------
real, allocatable :: T(:,:,:,:) ! global data
real, allocatable :: Tsub(:,:,:,:) ! subset of global data
! Miscellaneous
! -------------
integer :: ierr
integer :: im, jm, lm
real :: minlat, minlon, maxlat, maxlon
integer :: im_sub, jm_sub
integer :: imin, imax, jmin, jmax
integer :: ncid, varid
integer :: start(4), count(4)
! file name and dimensions
! ------------------------
im = 720
jm = 361
lm = 72
T_file = "c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4"
! Open file and get var id
! ------------------------
call check(nf90_open(T_file,NF90_NOWRITE,ncid), "opening T file")
call check(nf90_inq_varid(ncid,"T",varid), "getting T varid")
! Read global temperature data
! ----------------------------
allocate(T(im,jm,lm,1)) ! global 4D array with 1 time level
start = [1, 1, 1, 1]
count = [im, jm, lm, 1] ! 1 time level, 3D (lon,lat,lev) array
write(*,*) 'Reading global T...'
call check(nf90_get_var(ncid,varid,T,start=start,count=count), "reading T")
write(*,*)'T: ', maxval(T),minval(T)
! Read temperature over US
! lons = -180:0.5:179.5
! lats = -90:0.5:90
! ------------------------
write(*,*) 'Reading T over US'
minlon = -130.
maxlon = -65.
minlat = 25.
maxlat = 50.
imin = nint((minlon + 180.)/0.5)
imax = nint((maxlon + 180.)/0.5)
jmin = nint((minlat + 90.)/0.5)
jmax = nint((maxlat + 90.)/0.5)
im_sub = imax-imin+1
jm_sub = jmax-jmin+1
allocate(Tsub(im_sub,jm_sub,lm,1)) ! global 4D array with 1 time level
start = [1, 1, 1, 1]
count = [im_sub, jm_sub, lm, 1] ! 1 time level, 3D (lon,lat,lev) array
call check(nf90_get_var(ncid,varid,Tsub,start=start,count=count), "reading Tsub")
write(*,*)'Tsub: ', maxval(Tsub),minval(Tsub)
! close file, release memory
call check(nf90_close(ncid), "closing T file")
deallocate(T)
deallocate(Tsub)
! All done
! --------
contains
subroutine check(status, loc)
integer, intent(in) :: status
character(len=*), intent(in) :: loc
if(status /= NF90_NOERR) then
write (*,*) "Error at ", loc
write (*,*) NF90_STRERROR(status)
end if
end subroutine check
end program g5nr_reader
Compile and link
We use the utility nf-config
(included in the NetCDF-4 installation) to identify the linker rules
For a typical NetCDF-4 installation, the above code, g5nr_reader.f90
can be compiled and linked to the NetCDF-4 library via
gfortran -o g5nr_reader.x `nf-config --fflags` g5nr_reader.f90 `nf-config --flibs`
creating the executable g5nr_reader.x
.
NOTE:
- You can use your favorite Fortran compiler instead of
gfortran
. - If the NetCDF-4 library was built with parallel I/O support, you will need to use
mpif90
to link, even if your code does not use the MPI library.
Run
Running the executable,
./g5nr_reader.x
produces the output
Reading global T... T: 315.6512 180.3667 Reading T over US Tsub: 302.8958 183.1974
Access data via OPeNDAP server
Code
The code to read data from the OPeNDAP server is a minor modification (3 lines) of the above program and is reproduced below
program g5nr_reader_dap
use netcdf ! for reading the NR files
implicit none
! File name
! ---------
character(len=256) :: T_file
! 4D array: (lon,lat,lev,time)
! ------------------------------------
real, allocatable :: T(:,:,:,:) ! global data
real, allocatable :: Tsub(:,:,:,:) ! subset of global data
! Miscellaneous
! -------------
integer :: ierr
integer :: im, jm, lm
real :: minlat, minlon, maxlat, maxlon
integer :: im_sub, jm_sub
integer :: imin, imax, jmin, jmax
integer :: ncid, varid
integer :: start(4), count(4)
! file name and dimensions
! ------------------------
im = 720
jm = 361
lm = 72
T_file = "http://opendap.nccs.nasa.gov:9090/dods/OSSE/GEOS-5.12/BETA9/0.5000_deg/inst/inst01hr_3d_T_Cv"
! Open file and get var id
! ------------------------
call check(nf90_open(T_file,NF90_NOWRITE,ncid), "opening T file")
call check(nf90_inq_varid(ncid,"t",varid), "getting T varid")
! Read global temperature data
! ----------------------------
allocate(T(im,jm,lm,1)) ! global 4D array with 1 time level
start = [1, 1, 1, 11772] ! time level 11772 corresponds to 2006/09/18, 9z
count = [im, jm, lm, 1] ! 1 time level, 3D (lon,lat,lev) array
write(*,*) 'Reading global T...'
call check(nf90_get_var(ncid,varid,T,start=start,count=count), "reading T")
write(*,*)'T: ', maxval(T),minval(T)
! Read temperature over US
! lons = -180:0.5:179.5
! lats = -90:0.5:90
! ------------------------
write(*,*) 'Reading T over US'
minlon = -130.
maxlon = -65.
minlat = 25.
maxlat = 50.
imin = nint((minlon + 180.)/0.5)
imax = nint((maxlon + 180.)/0.5)
jmin = nint((minlat + 90.)/0.5)
jmax = nint((maxlat + 90.)/0.5)
im_sub = imax-imin+1
jm_sub = jmax-jmin+1
allocate(Tsub(im_sub,jm_sub,lm,1)) ! global 4D array with 1 time level
start = [1, 1, 1, 11772] ! time level 11772 corresponds to 2006/09/18, 9z
count = [im_sub, jm_sub, lm, 1] ! 1 time level, 3D (lon,lat,lev) array
call check(nf90_get_var(ncid,varid,Tsub,start=start,count=count), "reading Tsub")
write(*,*)'Tsub: ', maxval(Tsub),minval(Tsub)
! close file, release memory
call check(nf90_close(ncid), "closing T file")
deallocate(T)
deallocate(Tsub)
! All done
! --------
contains
subroutine check(status, loc)
integer, intent(in) :: status
character(len=*), intent(in) :: loc
if(status /= NF90_NOERR) then
write (*,*) "Error at ", loc
write (*,*) NF90_STRERROR(status)
end if
end subroutine check
end program g5nr_reader_dap
Discussion
The three (3) differences from the case where an individual downloaded file was being read are
T_file
: Instead of reading a downloaded NetCDF-4 file, we read an OPeNDAP URL.start
: Via the OPeNDAP URL, we can now access all time levels. The hourlyinst
files are available starting at 2005/15/15 2200z. Our desired time, 2006/09/18 0900z is then the 11772th file.nf90_inq_varid
: While in the downloaded file, the temperature variable appears in the uppercase (T), on the OPeNDAP server, this variable is in lowercase (see http://opendap.nccs.nasa.gov:9090/dods/OSSE/GEOS-5.12/BETA9/0.5000_deg/inst/inst01hr_3d_T_Cv). This is reflected in the call to nf90_inq_varid.
Compile and link
We use the utility nf-config (included in the NetCDF-4 installation) to identify the linker rules For a typical NetCDF-4 installation, the above code, g5nr_reader.f90 can be compiled and linked to the NetCDF-4 library via
gfortran -o g5nr_reader.x `nf-config --fflags` g5nr_reader.f90 `nf-config --flibs`
creating the executable g5nr_reader.x. NOTE: You can use your favorite Fortran compiler instead of gfortran. If the NetCDF-4 library was built with parallel I/O support, you will need to use mpif90 to link, even if your code does not use the MPI library.
Run
Running the executable,
./g5nr_reader.x
produces the output
Reading T T: 315.6512 180.3667