Quick Guide to netCDF3

Ross Bannister, Dept. of Meteorology, University of Reading, UK

A. Operations to read-in netCDF data (no attributes)

1. Open the netCDF file (NF_OPEN).

2. Get dimension IDs (NF_INQ_DIMID) - one per dimension.

3. Get dimension lengths (NF_INQ_DIMLEN) - one per dimension.

4. Get variable IDs (NF_INQ_VARID) - one for each dimension present and per data variable required.

5. Define the 'shape' of the data to be input.

6. Read-in the data (NF_GET_VARA_REAL) - repeat steps 5 and 6 for each variable (including dimension variables).

7. Close the netCDF file (NF_CLOSE).

Example program to read-in netCDF data into an array


B. Operations to write netCDF data (no attributes)

1. Open the netCDF file (NF_CREATE).

2. Define the dimensions (NF_DEF_DIM) - one per dimension.

3. Define the variables (NF_DEF_VAR) - one for each dimension present and per data variable to be output.

4. Change the mode of netCDF operation (NF_ENDDEF).

5. Define the 'shape' of the data to be output.

6. Output the values of the variables (NF_PUT_VARA_REAL) - repeat steps 5 and 6 for each variable (including dimension variables).

7. Close the netCDF file (NF_CLOSE).

Example program to write-out netCDF data from an array


C. Compilation on the Sun system

include file: '/opt/local/include/netcdf.inc'

Compilation: f77 filename.f /opt/local/lib/libnetcdf.a




D. Selection of netCDF functions

All routines are integer functions in FORTRAN.

NF_OPEN - open a netCDF file for reading

NF_OPEN (path, mode, ncid)

path char. string input File name of netCDF file

mode integer input NF_WRITE or NF_NOWRITE

ncid integer output ID index of netCDF file

NF_CREATE - open a netCDF file for writing

NF_CREATE (path, cmode, ncid)

path char. string input File name of netCDF file

cmode integer input NF_SHARE or NF_NOCLOBBER

ncid integer output ID index of netCDF file

NF_INQ_DIMID - get dimension ID from an existing netCDF file

NF_INQ_DIMID (ncid, name, dimid)

ncid integer input ID index of netCDF file

name char. string input Name of dimension

dimid integer output ID index of dimension

NF_INQ_DIMLEN - get length of dimension

NF_INQ_DIMLEN (ncid, dimid, len)

ncid integer input ID index of netCDF file

dimid integer input ID index of dimension

len integer output Length of dimension

NF_INQ_VARID - get variable ID

NF_INQ_VARID (ncid, name, varid)

ncid integer input ID index of netCDF file

name char. string input Name of variable

varid integer output ID index of variable

NF_GET_VARA_REAL - read-in a data array

NF_GET_VARA_REAL (ncid, varid, start, count, rvals)

ncid integer input ID index of netCDF file

varid integer input ID index of variable

start integer(n) input index vector of position to start reading

count integer(n) input lengths of 'volume' to be retrieved

rvals real(x,y,...) output data structure to hold data

n=dimensionality of variable (this is 1 for simple dimension variables).

NF_DEF_DIM - define dimension for output

NF_DEF_DIM (ncid, name, len, dimid)

ncid integer input ID index of netCDF file

name char. string input Name of dimension

len integer input Length of dimension (units)

dimid integer output ID index of dimension

NF_DEF_VAR - define variable

NF_DEF_VAR (ncid, name, xtype, ndims, dimids, varid)

ncid integer input ID index of netCDF file

name char. string input Name of variable

xtype integer input NF_BYTE, NF_CHAR, NF_REAL, ...

ndims integer input Number of dimensions (1-4)

dimids integer(4) input List of dimension IDs (first ndims elements only)

varid integer output ID index of variable

NF_ENDDEF - end the 'define' mode in netCDF

NF_ENDDEF (ncid)

ncid integer input ID index of netCDF file

NF_PUT_VARA_REAL - output a data array

NF_PUT_VARA_REAL (ncid, varid, start, count, rvals)

ncid integer input ID index of netCDF file

varid integer input ID index of variable

start integer(n) input index vector of position to start writing

count integer(n) input lengths of 'volume' to be output

rvals real(x,y,...) input data structure holding data

n=dimensionality of variable (this is 1 for dimension variables).

NF_CLOSE - close the netCDF file

NF_CLOSE (ncid)

ncid integer input ID index of netCDF file


E. Example programs

Example FORTRAN-77 program to read-in netCDF data into an array

*     789012345678901234567890123456789012345678901234567890123456789012
*     ^  1         2         3         4         5         6         7 ^

*     ==================================================================
*     Attempt to read-in some netCDF data

      program ReadIn
      integer ncid,ierr,dimidx,dimidy,dimidz,dimidt,varid,varidx,varidy
      integer varidz,varidt,startA(1),countA(1),startB(4),countB(4)
      integer lenx,leny,lenz,lent
      real valsx(96),valsy(72),valsz(25),valst(1),vals(96,72,25,1)

*     Declare functions and variables associated with the netCDF library
      integer NF_OPEN,NF_NOWRITE,NF_INQ_DIMID,NF_INQ_VARID,NF_INQ_DIMLEN
      integer NF_GET_VARA_REAL,NF_CLOSE

      include '/opt/local/include/netcdf.inc'

*     1. Open the netCDF file
*     -----------------------
      ierr=NF_OPEN('/twix/AMIPII/amip2_mmean/amip2_mmean_jan79.nc',
     +             NF_NOWRITE,ncid)
      print*,1,ierr

*     2. Get dimension IDs
*     --------------------
      ierr=NF_INQ_DIMID(ncid,'longitude_72x96',dimidx)
      print*,2,ierr
      ierr=NF_INQ_DIMID(ncid,'latitude_72x96',dimidy)
      print*,3,ierr
      ierr=NF_INQ_DIMID(ncid,'dp25',dimidz)
      print*,4,ierr
      ierr=NF_INQ_DIMID(ncid,'time',dimidt)
      print*,5,ierr

*     3. Get dimension lengths
*     ------------------------
      ierr=NF_INQ_DIMLEN(ncid,dimidx,lenx)
      print*,6,ierr
      ierr=NF_INQ_DIMLEN(ncid,dimidy,leny)
      print*,7,ierr
      ierr=NF_INQ_DIMLEN(ncid,dimidz,lenz)
      print*,8,ierr
      ierr=NF_INQ_DIMLEN(ncid,dimidt,lent)
      print*,9,ierr
      print*,'Dimension lengths',lenx,leny,lenz,lent

*     4. Get variable IDs
*     -------------------
*     First the variables for the dimensions
      ierr=NF_INQ_VARID(ncid,'longitude_72x96',varidx)
      print*,6,ierr
      ierr=NF_INQ_VARID(ncid,'latitude_72x96',varidy)
      print*,7,ierr
      ierr=NF_INQ_VARID(ncid,'dp25',varidz)
      print*,8,ierr
      ierr=NF_INQ_VARID(ncid,'time',varidt)
      print*,9,ierr
*     ...and for the main data variable
      ierr=NF_INQ_VARID(ncid,'ta',varid)
      print*,10,ierr

*     5. Get contents of dimension variables
*     --------------------------------------
      startA(1)=1
      countA(1)=lenx
      ierr=NF_GET_VARA_REAL(ncid,varidx,startA,countA,valsx)
      print*,11,ierr
      startA(1)=1
      countA(1)=leny
      ierr=NF_GET_VARA_REAL(ncid,varidy,startA,countA,valsy)
      print*,12,ierr
      startA(1)=1
      countA(1)=lenz
      ierr=NF_GET_VARA_REAL(ncid,varidz,startA,countA,valsz)
      print*,13,ierr
      startA(1)=1
      countA(1)=lent
      ierr=NF_GET_VARA_REAL(ncid,varidt,startA,countA,valst)
      print*,14,ierr
      print*,'longitude values'
      print 100,(valsx(l),l=1,lenx)
      print*,'latitude values'
      print 100,(valsy(l),l=1,leny)
      print*,'pressure values'
      print 100,(valsz(l),l=1,lenz)
      print*,'time values'
      print 100,(valst(l),l=1,lent)

*     6. Get values of the main variable
*     ----------------------------------
      startB(1)=1
      startB(2)=1
      startB(3)=1
      startB(4)=1
      countB(1)=lenx
      countB(2)=leny
      countB(3)=lenz
      countB(4)=lent
      ierr=NF_GET_VARA_REAL(ncid,varid,startB,countB,vals)
      print*,15,ierr

*     7. Close the file up
*     --------------------
      err=NF_CLOSE(ncid)
      print*,16,ierr

*     8. Output a pressure level to gnuplot
*     -------------------------------------
      open (12,file='Gnu1')
      do l=1,lenx
        do m=1,leny
          write (12,101) vals(l,m,20,1)
        enddo
        if (l.lt.lenx) write (12,102)
      enddo
      close (12)
      print*,'Pressure level',valsz(20),' output for gnuplot'

100   format (100F8.2)
101   format (F12.6)
102   format ((A))
      end
  

Example FORTRAN-77 programs (i) to write-out netCDF data from an array and (ii) to read it back in again

(i) Write-out data (program (ii) below will read it back in again)
*     789012345678901234567890123456789012345678901234567890123456789012
*     ^  1         2         3         4         5         6         7 ^

*     ==================================================================
*     Attempt to write out some netCDF data
      program netcdf2

      integer err,fileid,dimidx,dimidy,dd(4),varidx,varidy,myvar
      integer startA(1),startB(2),countA(1),countB(2)
      real xvals(100),yvals(50),var(100,50)

*     netCDF functions
      integer NF_CREATE,NF_CLOBBER,NF_DEF_DIM,NF_REAL,NF_ENDDEF
      integer NF_PUT_VARA_REAL,NF_CLOSE

      include '/opt/local/include/netcdf.inc'



*     Open a netCDF file
      err=NF_CREATE('Test2.nc',NF_CLOBBER,fileid)

*     Define the dimensions
      err=NF_DEF_DIM(fileid,'xval',100,dimidx)
      err=NF_DEF_DIM(fileid,'yval',50,dimidy)

*     Define the variables (include 2 variables giving the dim. values)
      dd(1)=dimidx
      err=NF_DEF_VAR(fileid,'xval',NF_REAL,1,dd,varidx)
      dd(1)=dimidy
      err=NF_DEF_VAR(fileid,'yval',NF_REAL,1,dd,varidy)
      dd(1)=dimidx
      dd(2)=dimidy
      err=NF_DEF_VAR(fileid,'MyVar',NF_REAL,2,dd,myvar)

      print*,'x dim ID ',dimidx
      print*,'y dim ID ',dimidy
      print*,'x var ID ',varidx
      print*,'y var ID ',varidy
      print*,'main ID  ',myvar

*     Change mode of netCDF operation
      err=NF_ENDDEF(fileid)

*     Output the values of the variables (include dimension variables)
*     x dimension values
      startA(1)=1
      countA(1)=100
      do l=1,100
        xvals(l)=2.0*real(l)
      enddo
      err=NF_PUT_VARA_REAL(fileid,varidx,startA,countA,xvals)
*     y dimension values
      startA(1)=1
      countA(1)=50
      do l=1,50
        yvals(l)=real(l)/2.0
      enddo
      err=NF_PUT_VARA_REAL(fileid,varidy,startA,countA,yvals)
*     Main variables values
      startB(1)=1
      startB(2)=1
      countB(1)=100
      countb(2)=50
      do l1=1,100
        do l2=1,50
          var(l1,l2)=sin(0.1*real(l1)+0.3*real(l2))
        enddo
      enddo
      err=NF_PUT_VARA_REAL(fileid,myvar,startB,countB,var)

*     CLose the file up
      err=NF_CLOSE(fileid)

      end
  
(ii) Read-in the data written to netCDF in (i)
*     789012345678901234567890123456789012345678901234567890123456789012
*     ^  1         2         3         4         5         6         7 ^

*     ==================================================================
*     Attempt to read in the netCDF data written by netCDF2
      program netcdf3

      integer err,fileid,dimidx,dimidy,dd(4),varidx,varidy,myvar
      integer startA(1),startB(2),countA(1),countB(2),lenx,leny
      real xvals(100),yvals(50),var(100,50)

*     netCDF functions
      integer NF_CREATE,NF_CLOBBER,NF_DEF_DIM,NF_REAL,NF_ENDDEF
      integer NF_PUT_VARA_REAL,NF_CLOSE,NF_OPEN,NF_NOWRITE,NF_INQ_DIMID
      integer NF_INQ_DIMLEN,NF_INQ_VARID,NF_GET_VARA_REAL

      include '/opt/local/include/netcdf.inc'

*     Open the netCDF file for reading
      err=NF_OPEN('Test2.nc',NF_NOWRITE,fileid)

*     Get dimension IDs
      err=NF_INQ_DIMID (fileid,'xval',dimidx)
      err=NF_INQ_DIMID (fileid,'yval',dimidy)
*     Get dimension lengths
      err=NF_INQ_DIMLEN (fileid,dimidx,lenx)
      err=NF_INQ_DIMLEN (fileid,dimidy,leny)
      print*,'Length of x-dimension',lenx
      print*,'Length of y-dimension',leny

*     Get variable IDs
      err=NF_INQ_VARID (fileid,'xval',varidx)
      err=NF_INQ_VARID (fileid,'yval',varidy)
      err=NF_INQ_VARID (fileid,'MyVar',myvar)

*     Get contents of dimension variables
      startA(1)=1
      countA(1)=100
      err=NF_GET_VARA_REAL (fileid,varidx,startA,countA,xvals)
      startA(1)=1
      countA(1)=50
      err=NF_GET_VARA_REAL (fileid,varidy,startA,countA,yvals)
      print*,'Here are the x-values'
      print 100,(xvals(l),l=1,100)
      print*,'Here are the y-values'
      print 101,(yvals(l),l=1,50)

*     Get the main data (what all of this is actually for!!)
      startB(1)=1
      startB(2)=1
      countB(1)=100
      countb(2)=50
      err=NF_GET_VARA_REAL (fileid,myvar,startB,countB,var)

*     Close the netCDF file
      err=NF_CLOSE(fileid)

*     Output the data so that gnuplot can look at it
      open (12,file='gnudata')
      do l1=1,100
        do l2=1,50
          write (12,102) var(l1,l2)
        enddo
        if (l1.lt.100) write (12,103)
      enddo
      close (12)


100   format (100F8.2)
101   format (50F8.2)
102   format (F12.6)
103   format ((A))
      end