Go to the previous, next section.

Use of the NetCDF Library

It is not necessary to know about the whole netCDF interface to make use of the netCDF library. If you are creating a netCDF file, only a handful of routines are required to define the necessary dimensions, variables, and attributes, and to write the data to the netCDF file. Similarly, if you are writing software to access data stored in a particular netCDF object, only a small subset of the netCDF library is required to open the netCDF file and access the data. Only authors of generic applications that access arbitrary netCDF files and write out transformed netCDF files need to be familiar with the whole netCDF library. In this chapter we provide templates of common sequences of netCDF subroutine calls needed for common uses. Full argument lists for the procedures and subroutines are described in later chapters.

Creating a NetCDF File

The typical sequences of C netCDF calls used to create a new netCDF file follows. For clarity we only present the name of the routines, omit all declarations, parameters and error checking, and use ... to represent arbitrary sequences of other statements:

    nccreate      /* create netCDF file: enter define mode */
         ...
       ncdimdef   /* dimension definitions: from name and size */
         ...
       ncvardef   /* variable definitions: from name, type, dimensions */
         ...
       ncattput   /* attribute put: assign attribute values */
         ...
    ncendef       /* end definitions: leave define mode */
         ...
    ncvarput      /* variable put: provide values for variables */
      ...
    ncattput      /* attribute put: change attribute values */
      ...
    ncclose       /* close: save new netCDF file */

In FORTRAN, the corresponding sequence looks like this:

    NCCRE              ! create netCDF file: enter define mode
         ...
       NCDDEF          ! define dimensions: from name and size
         ...
       NCVDEF          ! define variables: from name, type, dimensions
         ...
       NCAPT or NCAPTC ! attribute put: assign attribute values
         ...
    NCENDF             ! end definitions: leave define mode
         ...
    NCVPT or NCVPTC    ! variable put: provide values for variables
      ...
    NCAPT or NCAPTC    ! attribute put: change attribute values
      ...
    NCCLOS             ! close: save new netCDF file

The FORTRAN interface provides two subroutines for defining attributes and providing values for variables, depending on whether a numeric or character string value is used. The FORTRAN template indicates that either of these subroutines could be called.

Only one call is needed to begin creating a netCDF file, at which point you will be in the first of two netCDF modes. When accessing a netCDF, you are either in define mode or data mode. In define mode, you can create dimensions, variables, and new attributes, but you cannot read or write variable data. In data mode, you can access data and change existing attributes, but you are not permitted to create new dimensions, variables, or attributes.

One call to ncdimdef (or NCDDEF) is needed for each dimension created. Similarly, one call to ncvardef (or NCVDEF) is needed for each variable creation, and one call to ncattput (or NCAPT or NCAPTC) is needed for each attribute defined and assigned a value. The only way to leave define mode and enter data mode is by a call to ncendef (or NCENDF).

Once in data mode, you can add new data to variables, change old values, and change values of existing attributes (so long as the attribute changes do not require more storage space for the attribute). Single values are written to a variable with ncvarput1 (or NCVPT1 or NCVP1C); while arbitrary hyperslabs of data are written using ncvarput or ncvarputg (or NCVPT, NCVPTC, NCVPTG, or NCVPGC) instead. Multi-variable records of data may be written using multiple calls to ncvarput (or NCVPT) or with a single call to ncrecput.

Finally, you should explicitly close all open netCDF files on which you are writing by calling ncclose (or NCCLOS) before the program exits. If a program terminates abnormally with netCDF files open for writing, you may lose one or more records of the most recently written record variable data as well as any attribute changes since the last call to ncsync (or NCSNC). It is possible to reduce the chance of losing data due to abnormal termination by explicitly calling ncsync (NCSNC) after every write to netCDF variables or change to attribute values. This can be expensive in computer resources, so such calls should ordinarily be omitted unless they are really needed.

Reading a NetCDF File with Known Names

If you know the names of the dimensions, variables, and attributes in a netCDF file, you can write calls to read data from the file; you don't need to include the "inquire" calls that determine the dimensions, variables, and attributes. If you employ such knowledge about particular netCDF files, the program you write will lack generality. It will only work with files that have the assumed names and structure, so you will be losing some of the advantages of using the netCDF interface. However, you may be writing software that expects the user or some other program to supply variable or dimension names, perhaps as subroutine or command line arguments. In that case, the resulting program could be quite general.

When you know the names of some variables of interest and their dimensions, the order of typical C calls to read data from those variables in a netCDF file is:

    ncopen           /* open existing netCDF */
      ...
    ncdimid          /* get dimension IDs to use in accessing data */
      ...
    ncvarid          /* get variable IDs */
      ...
    ncattget         /* get attribute values, if needed */
      ...
    ncvarget         /* get values of variables */
      ...
    ncclose          /* close netCDF */

In FORTRAN, the corresponding sequence looks like this:

    NCOPN            !  open existing netCDF 
      ...
    NCDID            !  get dimension IDs to use in accessing data 
      ...
    NCVID            !  get variable IDs 
      ...
    NCAGT or NCAGTC  !  get attribute values, if needed 
      ...
    NCVGT or NCVGTC  !  get values of variables 
      ...
    NCCLOS           !  close netCDF 

First, a single call opens the netCDF file, given the file name, and returns a netCDF ID that is used to refer to the netCDF in all subsequent calls.

Next, a call to ncdimid (or NCDID) for each dimension of interest gets the dimension ID from the dimension name. Dimension IDs, like netCDF IDs, are small integers used to refer to dimensions in subsequent calls. Similarly, each required variable ID is determined from its name by a call to ncvarid (or NCVID). Once variable IDs are known, variable attribute values can be retrieved using the netCDF ID, the variable ID, and the desired attribute name as input to ncattget (or NCAGT or NCAGTC) for each desired attribute. Variable data values can be directly accessed from the netCDF file with ncvarget1 (or NCVGT1 or NCVG1C) for single values, ncvarget or ncvargetg (or NCVGT, NCVGTC, NCVGTG, or NCVGGC) for hyperslabs of values, or ncrecget for records of values. To minimize the number of disk accesses, you should remember that the last dimension in C (first dimension in FORTRAN) varies fastest when using hyperslab access.

Finally, the netCDF file can be closed with ncclose (or NCCLOS) when you are finished with it to free system resources. There is no harm in not closing a file open only for reading.

Reading a netCDF File with Unknown Names

If you want to write generic software (i.e., a program that transposes specified variables by interchanging specified dimensions) you should make no assumptions about the dimension and variable names that are not specified. In such cases, you must find out about all the dimensions, variables, and attributes in a netCDF file by calling the inquire functions. Four inquire functions get information about a whole netCDF file, a dimension, a variable, or an attribute. The following template illustrates how they are used:
    ncopen           /* open existing netCDF */
      ...
    ncinquire        /* find out what is in it */
         ...
       ncdiminq      /* get dimension names, sizes */
         ...
       ncvarinq      /* get variable names, types, shapes */
            ...
          ncattname  /* get attribute names */
            ...
          ncattinq   /* get attribute types and lengths */
            ...
          ncattget   /* get attribute values */
            ...
    ncvarget         /* get values of variables */
      ...
    ncclose          /* close netCDF */

In FORTRAN, the corresponding sequence looks like this:

    NCOPN                 !  open existing netCDF 
      ...
    NCINQ                 !  find out what is in it 
         ...
       NCDINQ             !  get dimension names, sizes 
         ...
       NCVINQ             !  get variable names, types, shapes 
            ...
          NCANAM          !  get attribute names 
            ...
          NCAINQ          !  get attribute values 
            ...
          NCAGT or NCAGTC !  get attribute values 
            ...
    NCVGT or NCVGTC       !  get values of variables 
      ...
    NCCLOS                !  close netCDF 

As in the previous example, a single call opens the existing netCDF file, returning a netCDF ID. This netCDF ID is given to the ncinquire (or NCINQ) routine, which returns the number of dimensions, the number of variables, the number of global attributes, and the ID of the unlimited dimension, if there is one.

Another inquire function, ncrecinq, is provided for convenience to return information about record variables, although the information is also obtainable by using the other inquire functions. The ncrecinq function returns the number of record variables, their variable IDs, and how much memory space is needed for a record's worth of data for each record variable.

All the inquire functions are quite inexpensive to use and require no I/O, since the information they provide is stored in a table in memory for each open netCDF file. In the C interface, the inquire functions also support getting a subset of information by providing NULL pointers instead of valid addresses for undesired information.

Dimension IDs are assigned by using consecutive integers (beginning at 0 in C, 1 in FORTRAN). Also dimensions, once created, cannot be deleted. Therefore, knowing the number of dimension IDs in a netCDF file means knowing all the dimension IDs: they are the integers 0, 1, 2, ..., (or 1, 2, 3, ... in FORTRAN). For each dimension ID, a call to the inquire function ncdiminq (or NCDINQ) returns the dimension name and size.

Like dimension IDs, variable IDs are also 0, 1, 2, ..., (or 1, 2, 3, ... in FORTRAN). These can be used in ncvarinq (or NCVINQ) calls to find out the names, types, shapes, and the number of attributes assigned to each variable.

Once the number of attributes for a variable is known, successive calls to ncattname (or NCANAM) return the name for each attribute given the netCDF ID, variable ID, and attribute number. Armed with the attribute name, a call to ncattinq (or NCAINQ) returns its type and length. Given the type and length, the generic application can allocate enough space to hold the attribute values. Then a call to ncattget (or NCAGT or NCAGTC) returns the attribute values.

Once the names, IDs, types, shapes, and lengths of all netCDF components are known, data values can be accessed by calling ncvarget1 (or NCVGT1 or NCVG1C) for single values, ncvarget or ncvargetg (or NCVGT, NCVGTC, NCVGTG, or NCVGGC) for aggregates of values using hyperslab access, or ncrecget for aggregates of values using record access.

Adding New Dimensions, Variables, Attributes

An existing netCDF file can be extensively altered. New dimensions, variables, and attributes can be added or existing ones renamed, and existing attributes can be deleted. Existing dimensions, variables, and attributes can be renamed. The following code template lists a typical sequence of calls to add new netCDF components to an existing file:

    ncopen           /* open existing netCDF file */
      ...
    ncredef          /* put it into define mode */
        ...
      ncdimdef       /* define additional dimensions (if any) */
        ...
      ncvardef       /* define additional variables (if any) */
        ...
      ncattput       /* define additional attributes (if any) */
        ...
    ncendef          /* check all definitions, leave define mode */
      ...
    ncvarput         /* provide values for new variables */
      ...
    ncclose          /* save netCDF file */

In FORTRAN, the corresponding sequence looks like this:

    NCOPN             !  open existing netCDF 
      ...
    NCREDF            !  put it into define mode 
        ...
      NCDDEF          !  define additional dimensions (if any) 
        ...
      NCVDEF          !  define additional variables (if any) 
        ...
      NCAPT or NCAPTC !  define additional attributes (if any) 
        ...
    NCENDF            !  check all definitions, leave define mode 
      ...
    NCVPT or NCVPTC   !  provide values for new variables 
      ...
    NCCLOS            !  save netCDF file 

A netCDF file is first opened by the ncopen (or NCOPN) call. This call puts you in data mode, which means existing data values can be accessed and changed, existing attributes can be changed (so long as they do not grow), but nothing can be added. To add new netCDF dimensions, variables, or attributes you must leave data mode and enter define mode, by calling ncredef (or NCREDF). In define mode, call ncdimdef (or NCDDEF) to define new dimensions, ncvardef (or NCVDEF) to define new variables (using the new dimensions), and ncattput (or NCAPT or NCAPTC) to assign new attributes to variables or enlarge old attributes.

You can leave define mode and reenter data mode, checking all the new definitions for consistency and committing the changes to disk, by calling ncendef (or NCENDF). If you do not wish to reenter data mode, just call ncclose (or NCCLOS), which will have the effect of first calling ncendef (or NCENDF).

Until the ncendef (or NCENDF) call, you may back out of all the redefinitions made in define mode and restore the previous state of the netCDF by calling ncabort (or NCABOR). You may also use the ncabort call to restore the netCDF to a consistent state if the call to ncendef (or NCENDF) fails. If you have called ncclose (or NCCLOS) from definition mode and the implied call to ncendef (or NCENDF) fails, ncabort (or NCABOR) will automatically be called to close the netCDF in its previous consistent state (before you entered define mode).

Error Handling

By default all netCDF library routines print an error message and exit when an error has occurred. If this error behavior is acceptable, you never need to check error returns, since any condition that would result in an error will print an explanatory message and exit. The examples in this guide assume the default error-handling behavior, so there is no checking of error returns.

Occasionally, low-level write errors may occur in the XDR library layer below the netCDF library. For example, if a write operation causes you to exceed disk quotas or to attempt to write to a device that is no longer available, you may get an error message from one of the XDR functions rather than from the netCDF library. If you get a message from the XDR layer, diagnose and correct whatever is causing the low-level write errors.

In the C interface, errors may be handled more flexibly by setting the external integer ncopts, declared in the file `netcdf.h'. Two aspects of the error-handling behavior can be modified independently: the suppression of error messages, and the fatality of errors. The default behavior is specified by the assignment

ncopts = NC_VERBOSE | NC_FATAL;
where NC_VERBOSE and NC_FATAL are predefined constants from the include file `netcdf.h'.

If you want error messages but do not wish errors to be fatal, turn off the fatal error flag with:

ncopts = NC_VERBOSE;
If you want neither error messages nor fatal errors, turn off both flags with:
ncopts = 0;
In either case, you should check the return value after each call to a netCDF function. The integer -1 is returned whenever an error occurs and NC_FATAL is off, so you can detect error returns and handle the errors appropriately. Another externally-defined integer, ncerr, contains a netCDF-specific error code that can be used after an error has occurred to determine what the nature of the error was. The names and descriptions of netCDF error codes are included in the file `netcdf.h'.

In the FORTRAN interface, the error options described above can be accessed by using the routines NCPOPT and NCGOPT. The default error- handling behavior is equivalent to the statement

      CALL NCPOPT(NCVERBOS+NCFATAL)
where the values of NCVERBOS and NCFATAL are pre-defined constants from the FORTRAN include file `netcdf.inc'. If you want error messages, but do not wish errors to be fatal, turn off the fatal error flag with:
      CALL NCPOPT(NCVERBOS)
If you want neither error messages nor fatal errors, turn off both flags with:
      CALL NCPOPT(0)
To get the current value of the error options, use:
      CALL NCGOPT(NCOPTS)

In either case, the integer return code (the last parameter in all of the FORTRAN subroutines and functions) contains the non-zero netCDF-specific error number that can be used to determine the nature of the error. Names and descriptions of netCDF error codes are included in the file `netcdf.inc'.

Go to the previous, next section.