Recipe: Fortran program as OPeNDAP client: Difference between revisions

Pchakrab (talk | contribs)
Move from http to https
 
(53 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{rightTOC}}
Back to [[G5NR Data Access Guide]].


Back to [[G5NR Data Access Guide]].
== Problem ==
 
By accessing the collection <code>inst01hr_3d_T_Cv</code> via the OPeNDAP server
https://opendap.nccs.nasa.gov/dods/OSSE/G5NR/Ganymed/7km


First, we ensure that out NetCDF-4 library has been built with Fortran, HDF5 and OPeNDAP support. All three queries
we want to read the surface temperature data inside the box bound by latitudes 25<sup>o</sup>N, 50<sup>o</sup>N and longitudes -130<sup>o</sup>W, -65<sup>o</sup>W for 2006/Sep/18, 9z and compute its min/max.


== Solution ==
First, we ensure that our NetCDF-4 library has been built with Fortran and OPeNDAP support. If both the queries
  > nc-config --has-f90
  > nc-config --has-f90
> nc-config --has-hdf5
  > nc-config --has-dap
  > nc-config --has-dap


should return yes.
return "yes", we have a compatible NetCDF-4 library. Here <code>nc-config</code> is a utility bundled with NetCDF-4 package.


== Read downloaded nc4 file ==
The metadata for the collection <code>inst01hr_3d_T_Cv</code> is available at
https://opendap.nccs.nasa.gov/dods/OSSE/G5NR/Ganymed/7km/0.5000_deg/inst/inst01hr_3d_T_Cv.info


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
==== Code ====
This code accesses the collection <code>inst01hr_3d_T_Cv</code> from the OPeNDAP server, reads a subset of the temperature data (all levels inside the bounding box specified above) and computes its max/min.


==== Code ====
NOTE:
# Instead of reading a downloaded NetCDF-4 file, we read an OPeNDAP URL.
# While in the downloaded file, the temperature variable appears in the uppercase (T), on the OPeNDAP server, this variable is in lowercase. This is reflected in the call to <code>nf90_inq_varid</code>.
# Via the OPeNDAP URL, we now have access to all times for which data exists. The hourly <code>inst</code> files are available starting at 2005/15/15, 2200z. Our desired time, 2006/09/18, 0900z is then the 11772<sup>th</sup> step.


<syntaxhighlight lang="fortran" line>
<syntaxhighlight lang="fortran" line>
program g5nr_reader
program g5nr_reader_dap


   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(:,:,:,:)


   ! Miscellaneous                                                                                                            
   ! Miscellaneous
   ! -------------                                                                                                            
   ! -------------
   integer :: ierr
   integer :: ierr
   integer :: im, jm, lm
   integer :: im, jm, lm
   integer :: ncid, varid
   integer :: ncid, varid
   integer :: start(4), count(4)
   integer :: start(4), count(4)
  integer :: imin, imax, jmin, jmax
  real :: minlat, minlon, maxlat, maxlon


   ! file name and dimensions                                                                               
   ! We replace filename by opendal url
   ! ------------------------                                                                              
   ! ----------------------------------
  im = 720
   T_file = "https://opendap.nccs.nasa.gov:9090/dods/OSSE/G5NR/Ganymed/7km/0.5000_deg/inst/inst01hr_3d_T_Cv"
  jm = 361
  lm = 72
   T_file = "c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4"


   ! Allocate the Global 4-D array with only 1 time level                                                                     
   ! file name and (subset) dimensions
   ! ----------------------------------------------------                                                                     
  ! bounding box:
   allocate(T(im,jm,lm,1))
   !   lons = -130:0.5:-65
 
   !  lats =   25:0.5:50
   ! Hypercube for reading one 1 array
   ! ---------------------------------
   ! ---------------------------------
   start = (/  1, 1,  1, 1 /)
   ! array indices from the
   count = (/ im, jm, lm, 1 /)  ! 1 time level, 3D (lon,lat,lev) array                                                       
  ! bounding lat/lon values
  imin = nint((-130. + 180.)/0.5)
  imax = nint(( -65. + 180.)/0.5)
  jmin = nint(( 25 + 90.)/0.5)
   jmax = nint(50 +  90.)/0.5)
   ! array sizes
  im = imax-imin+1
  jm = jmax-jmin+1
  lm = 72


   ! Read the data file                                                                                                       
   ! Open url and get var id
   ! ------------------                                                                                                        
   ! -----------------------
  write(*,*)'Reading T'
   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 temperature data
  ! ---------------------
  allocate(T(im,jm,lm,1))            ! global 4D array with 1 time level
  start = [imin, jmin, 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 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")
  call check(nf90_close(ncid), "closing T file")
  ! Print min/max of arrays                                                                                                   
  ! -----------------------                                                                                                   
   write(*,*)'T: ', maxval(T),minval(T)
   write(*,*)'T: ', maxval(T),minval(T)


  ! close file, release memory
  call check(nf90_close(ncid), "closing T file")
   deallocate(T)
   deallocate(T)


   ! All done                                                                                                                  
   ! All done
   ! --------                                                                                                                  
   ! --------


contains
contains
Line 86: Line 105:
   end subroutine check
   end subroutine check


end program g5nr_reader
end program g5nr_reader_dap
</syntaxhighlight>
</syntaxhighlight>


==== Compile and link ====
==== Compile and link ====


We use the utility <code>nf-config</code> (included in the NetCDF-4 installation) to identify the linker rules
We use the utility <code>nf-config</code> (included in the NetCDF-4 installation) to identify the linking rules


For a typical NetCDF-4 installation, the above code, <code>g5nr_reader.f90</code> can be compiled and linked to the NetCDF-4 library via
For a typical NetCDF-4 installation, the above code, <code>g5nr_reader_dap.f90</code> can be compiled and linked to the NetCDF-4 library via
gfortran -o g5nr_reader_dap.x `nf-config --fflags` g5nr_reader_dap.f90 `nf-config --flibs`


<nowiki>
creating the executable <code>g5nr_reader_dap.x</code>.
gfortran -o g5nr_reader.x `nf-config --fflags` g5nr_reader.f90 `nf-config --flibs`
</nowiki>
 
creating the executable <code>g5nr_reader.x</code>.


NOTE:
NOTE:
Line 108: Line 124:
Running the executable,
Running the executable,


  ./g5nr_reader.x
  ./g5nr_reader_dap.x


produces the output
produces the output
  Reading T
  Reading T (subset)...
T:    315.6512      180.3667
  T (subset):   305.6048      191.6956
 
== 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
 
<syntaxhighlight lang="fortran" line>
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
== Discussion ==
  ! --------


contains
== See Also ==
 
  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
</syntaxhighlight>


===== Discussion =====
# File Spec: [[File:G5NR-Ganymed-7km FileSpec-ON6-V1.0.pdf]]
# [[Recipe: Fortran program to read data from downloaded file]]


The three (3) differences from the case where an individual downloaded file was being read are
== No Warranty ==
# <code>T_file</code>: Instead of reading a downloaded NetCDF-4 file, we read an OPeNDAP URL.
# <code>start</code>: Via the OPeNDAP URL, we can now access all time levels. The hourly <code>inst</code> files are available starting at 2005/15/15 2200z. Our desired time, 2006/09/18 0900z is then the 11772<sup>th</sup> file.
# <code>nf90_inq_varid</code>: On the OPeNDAP servers, the variables are typically lowercase (see http://opendap.nccs.nasa.gov:9090/dods/OSSE/GEOS-5.12/BETA9/0.5000_deg/inst/inst01hr_3d_T_Cv) as opposed to the file where the variables name is in uppercase. This is reflected in the call to nf90_inq_varid.


==== Compile and run ====
== Copyright ==