Recipe: Fortran program as OPeNDAP client: Difference between revisions

From GEOS-5
Jump to navigation Jump to search
Pchakrab (talk | contribs)
Pchakrab (talk | contribs)
Line 13: Line 13:
== Read downloaded nc4 file ==
== Read downloaded nc4 file ==


Download the collection inst01hr_3d_T_Cv for 2006-Sep-18/0900z as described [[G5NR Data Access Guide#ftp (global data)|here]]. The downloaded file is <code>c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4</code>. The program to read this file is
We first download the collection inst01hr_3d_T_Cv for 2006-Sep-18/0900z as described [[G5NR Data Access Guide#ftp (global data)|here]]. The downloaded file is <code>c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4</code>. 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 ====
==== Code ====
Line 20: Line 22:
program g5nr_reader
program g5nr_reader


   use netcdf          ! for reading the NR files
   use netcdf          ! for reading the NR files


   implicit none
   implicit none


   ! File name                                                                                                                
   ! File name
   ! ---------                                                                                                                
   ! ---------
   character(len=256) :: T_file
   character(len=256) :: T_file


   ! Global, 4D array: (lon,lat,lev,time)                                                                                    
   ! 4D array: (lon,lat,lev,time)
   ! ------------------------------------  
   ! ------------------------------------
   real, allocatable :: T(:,:,:,:)
   real, allocatable :: T(:,:,:,:)   ! global data
  real, allocatable :: Tsub(:,:,:,:) ! subset of global data


   ! Miscellaneous                                                                                                            
   ! Miscellaneous
   ! -------------                                                                                                            
   ! -------------
   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)


   ! file name and dimensions                                                                              
   ! file name and dimensions
   ! ------------------------                                                                              
   ! ------------------------
   im = 720
   im = 720
   jm = 361
   jm = 361
Line 46: Line 52:
   T_file = "c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4"
   T_file = "c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4"


   ! Allocate the Global 4-D array with only 1 time level                                                                     
   ! Open file and get var id
   ! ----------------------------------------------------                                                                     
   ! ------------------------
   allocate(T(im,jm,lm,1))
   call check(nf90_open(T_file,NF90_NOWRITE,ncid), "opening T file")
  call check(nf90_inq_varid(ncid,"T",varid), "getting T varid")


   ! Hypercube for reading one 1 array
   ! Read global temperature data
   ! ---------------------------------
   ! ----------------------------
  allocate(T(im,jm,lm,1))        ! global 4D array with 1 time level
   start = (/  1,  1,  1, 1 /)
   start = (/  1,  1,  1, 1 /)
   count = (/ im, jm, lm, 1  /)  ! 1 time level, 3D (lon,lat,lev) array                                                        
   count = (/ im, jm, lm, 1  /)  ! 1 time level, 3D (lon,lat,lev) array
 
   write(*,*) 'Reading global T...'
  ! Read the data file                                                                                                       
  ! ------------------                                                                                                       
   write(*,*)'Reading T'
  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_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")
   call check(nf90_close(ncid), "closing T file")
   write(*,*)'T: ', maxval(T),minval(T)


   ! Print min/max of arrays                                                                                                   
   ! Read temperature over US
   ! -----------------------                                                                                                  
  ! lons = -180:0.5:179.5
   write(*,*)'T: ', maxval(T),minval(T)
  ! 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))
  start = (/      1,      1,  1, 1 /)
  count = (/ im_sub, jm_sub, lm, 1 /)
  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
   ! --------                                                                                                                  
   ! --------


contains
contains

Revision as of 12:51, 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))
  start = (/      1,      1,  1, 1 /)
  count = (/ im_sub, jm_sub, lm, 1 /)
  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:

  1. You can use your favorite Fortran compiler instead of gfortran.
  2. 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

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

  ! Global, 4D array: (lon,lat,lev,time)
  ! ------------------------------------
  real, allocatable :: T(:,:,:,:)

  ! Miscellaneous
  ! -------------
  integer :: ierr
  integer :: im, jm, lm
  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"

  ! Allocate the Global 4-D array with only 1 time level
  ! ----------------------------------------------------
  allocate(T(im,jm,lm,1))

  ! Hypercube for reading one 1 array
  ! ---------------------------------
  start = (/  1,  1,  1, 11772 /) ! time level 11748 corresponds to 2006/09/18, 9z
  count = (/ im, jm, lm, 1  /)    ! 1 time level, 3D (lon,lat,lev) array

  ! Read the data file
  ! ------------------
  write(*,*)'Reading T'
  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_get_var(ncid,varid,T,start=start,count=count), "reading T")
  call check(nf90_close(ncid), "closing T file")

  ! Print min/max of arrays
  ! -----------------------
  write(*,*)'T: ', maxval(T),minval(T)

  deallocate(T)

  ! 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

  1. T_file: Instead of reading a downloaded NetCDF-4 file, we read an OPeNDAP URL.
  2. start: Via the OPeNDAP URL, we can now access all time levels. The hourly inst files are available starting at 2005/15/15 2200z. Our desired time, 2006/09/18 0900z is then the 11772th file.
  3. 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