\input texinfo @c -*-texinfo-*- @comment $Id: netcdf-tutorial.texi,v 1.26 2009/09/30 13:36:44 ed Exp $ @c %**start of header @setfilename netcdf-tutorial.info @settitle The NetCDF Tutorial @setcontentsaftertitlepage @c Combine the variable, concept, and function indexes. @synindex vr cp @synindex fn cp @c %**end of header @c version-tutorial.texi is automatically generated by automake and @c contains defined variables VERSION, UPDATED, UPDATED-MONTH. @include version-tutorial.texi @c This file contains shared definitions of some vars. @include defines.texi @ifinfo @dircategory netCDF scientific data format @direntry * netcdf-tutorial: (netcdf-tutorial). @value{tut-man} @end direntry @end ifinfo @titlepage @title @value{tut-man} @subtitle NetCDF the Easy Way @subtitle NetCDF Version @value{VERSION} @subtitle Last Updated @value{UPDATED} @author Ed Hartnett @author Unidata Program Center @page @vskip 0pt plus 1filll @insertcopying @end titlepage @ifnottex @node Top, Intro, (dir), (dir) @top NetCDF Tutorial This tutorial aims to give a quick and painless introduction to netCDF. For the basic concepts of netCDF see @ref{Intro}. Read this to understand the netCDF data models and how to use netCDF. For sets of examples of increasing complexity see @ref{Examples}. The example programs are provided for each of four netCDF API languages, C, C++, F77, and F90. (No new netCDF-4 API extensions are used in these examples.) For a quick reference to the important functions in the netCDF-3 C, C++, Fortran 77, and Fortran 90 APIs, with hyper-links to the full documentation of each function, see @ref{Useful Functions}. To learn about the new features of netCDF-4, see @ref{API-Extensions}. For some examples see @ref{NetCDF-4 Examples}. NetCDF interface guides are available for C (@pxref{Top, @value{c-man},, netcdf-c, @value{c-man}}), C++ (@pxref{Top, @value{cxx-man},, netcdf-cxx, @value{cxx-man}}), Fortran 77 (@pxref{Top, @value{f77-man},, netcdf-f77, @value{f77-man}}), and Fortran 90 (@pxref{Top, @value{f90-man},, netcdf-f90, @value{f90-man}}). This document applies to netCDF version @value{VERSION}; it was last updated on @value{UPDATED}. @end ifnottex @menu * Intro:: What is NetCDF? * Examples:: Examples of increasing complexity. * Useful Functions:: Quick reference to useful netCDF functions. * API-Extensions:: New features added in netCDF-4. * NetCDF-4 Examples:: * Combined Index:: @detailmenu --- The Detailed Node Listing --- What is NetCDF? * Data Model:: How netCDF classic sees data. * Common Data Model:: The new, expanded data model. * Errors:: When things go tragically awry. * Unlimited Dimensions:: Arbitrarily extending a dimension. * Fill Values:: Handling missing data. * Tools:: Useful tools for netCDF files. * APIs:: Programming languages and netCDF. * Documentation:: Introducing the netCDF documentation! * Versions:: Different versions of netCDF. Example Programs * simple_xy:: A very simple netCDF file. * sfc_pres_temp:: A more complex file with more metadata. * pres_temp_4D:: A 4D file with an unlimited dimension. The simple_xy Example * simple_xy in C:: * simple_xy in F77:: * simple_xy in F90:: * simple_xy in C++:: simple_xy_wr.c and simple_xy_rd.c * simple_xy_wr.c:: * simple_xy_rd.c:: simple_xy_wr.f and simple_xy_rd.f * simple_xy_wr.f:: * simple_xy_rd.f:: simple_xy_wr.f90 and simple_xy_rd.f90 * simple_xy_wr.f90:: * simple_xy_rd.f90:: simple_xy_wr.cpp and simple_xy_rd.cpp * simple_xy_wr.cpp:: * simple_xy_rd.cpp:: The sfc_pres_temp Example * sfc_pres_temp in C:: * sfc_pres_temp in F77:: * sfc_pres_temp in F90:: * sfc_pres_temp in C++:: sfc_pres_temp_wr.c and sfc_pres_temp_rd.c * sfc_pres_temp_wr.c:: * sfc_pres_temp_rd.c:: sfc_pres_temp_wr.f and sfc_pres_temp_rd.f * sfc_pres_temp_wr.f:: * sfc_pres_temp_rd.f:: sfc_pres_temp_wr.f90 and sfc_pres_temp_rd.f90 * sfc_pres_temp_wr.f90:: * sfc_pres_temp_rd.f90:: sfc_pres_temp_wr.cpp and sfc_pres_temp_rd.cpp * sfc_pres_temp_wr.cpp:: * sfc_pres_temp_rd.cpp:: The pres_temp_4D Example * pres_temp_4D in C:: * pres_temp_4D in F77:: * pres_temp_4D in F90:: * pres_temp_4D in C++:: pres_temp_4D_wr.c and pres_temp_4D_rd.c * pres_temp_4D_wr.c:: * pres_temp_4D_rd.c:: pres_temp_4D_wr.f and pres_temp_4D_rd.f * pres_temp_4D_wr.f:: * pres_temp_4D_rd.f:: pres_temp_4D_wr.f90 and pres_temp_4D_rd.f90 * pres_temp_4D_wr.f90:: * pres_temp_4D_rd.f90:: pres_temp_4D_wr.cpp and pres_temp_4D_rd.cpp * pres_temp_4D_wr.cpp:: * pres_temp_4D_rd.cpp:: The Functions You Need in NetCDF-3 * Creation:: Creating netCDF files, adding metadata. * Reading:: Reading netCDF files of known structure. * Inquiry Functions:: Learning about an unknown netCDF file. * Subsets:: Reading and writing Subsets of data. Creating New Files and Metadata, an Overview * Creation in C:: * Creation in F77:: * Creation in F90:: * Creation in C++:: Numbering of NetCDF IDs * Reading in C:: * Reading in F77:: * Reading in F90:: * Reading in C++:: Reading NetCDF Files of Unknown Structure * Inquiry in C:: * Inquiry in F77:: * Inquiry in F90:: * Inquiry in C++:: Reading and Writing Subsets of Data * Subsetting in C:: * Subsetting in F77:: * Subsetting in F90:: * Subsetting in C++:: API Extensions Introduced with NetCDF-4 * Interoperability:: Reading and writing HDF5 files. * Multiple-Unlimited-Dimensions:: Use more than one unlimited dimension. * Groups:: Organizing data hierarchically. * Compound-Types:: Creating data type like C structs. * Opaque-Types:: Creating a data type of known size. * VLEN-Type:: Variable length arrays. * Strings:: Storing strings of data. * New-inq-Functions:: Functions to help explore a file. * Parallel:: How to get parallel I/O. * Future:: What's coming next! Collective/Independent Access * simple_xy_par in C:: simple_xy_par_wr.c and simple_xy_par_rd.c * simple_xy_par_wr.f90:: * simple_xy_par_rd.f90:: NetCDF-4 Examples * simple_nc4:: * simple_xy_nc4:: The simple_nc4 Example * simple_nc4 in C:: simple_nc4_wr.c and simple_nc4_rd.c * simple_nc4_wr.c:: * simple_nc4_rd.c:: The simple_xy_nc4 Example * simple_xy_nc4 in C:: * simple_xy_nc4 in F77:: * simple_xy_nc4 in F90:: simple_xy_nc4_wr.c and simple_xy_nc4_rd.c * simple_xy_nc4_wr.c:: * simple_xy_nc4_rd.c:: simple_xy_nc4_wr.f and simple_xy_nc4_rd.f * simple_xy_nc4_wr.f:: * simple_xy_nc4_rd.f:: simple_xy_nc4_wr.f90 and simple_xy_nc4_rd.f90 * simple_xy_nc4_wr.f90:: * simple_xy_nc4_rd.f90:: @end detailmenu @end menu @node Intro, Examples, Top, Top @chapter What is NetCDF? @cindex netCDF, definition @cindex Unidata @cindex UCAR NetCDF is a set of data formats, programming interfaces, and software libraries that help read and write scientific data files. NetCDF was developed and is maintained at Unidata, part of the University Corporation for Atmospheric Research (UCAR) Office of Programs (UOP). Unidata is funded primarily by the National Science Foundation. Unidata provides data and software tools for use in geoscience education and research. For more information see the web sites of Unidata (@uref{@value{unidata-url}}), UOP (@uref{@value{uop-url}}), and UCAR (@uref{@value{ucar-url}}). This tutorial may serve as an introduction to netCDF. Full netCDF documentation is available on-line (@pxref{Documentation}). @menu * Data Model:: How netCDF classic sees data. * Common Data Model:: The new, expanded data model. * Errors:: When things go tragically awry. * Unlimited Dimensions:: Arbitrarily extending a dimension. * Fill Values:: Handling missing data. * Tools:: Useful tools for netCDF files. * APIs:: Programming languages and netCDF. * Documentation:: Introducing the netCDF documentation! * Versions:: Different versions of netCDF. @end menu @node Data Model, Common Data Model, Intro, Intro @section The Classic NetCDF Data Model @cindex data model @cindex variable @cindex dimension @cindex attribute The classic netCDF data model consists of @dfn{variables}, @dfn{dimensions}, and @dfn{attributes}. This way of thinking about data was introduced with the very first netCDF release, and is still the core of all netCDF files. (In version 4.0, the netCDF data model has been expanded. @xref{Common Data Model}.) @table @code @item Variables N-dimensional arrays of data. Variables in netCDF files can be one of six types (char, byte, short, int, float, double). For more information see @ref{Variables,,, netcdf, @value{n-man}}. @item Dimensions describe the axes of the data arrays. A dimension has a name and a length. An unlimited dimension has a length that can be expanded at any time, as more data are written to it. NetCDF files can contain at most one unlimited dimension. For more information see @ref{Dimensions,,, netcdf, @value{n-man}}. @item Attributes annotate variables or files with small notes or supplementary metadata. Attributes are always scalar values or 1D arrays, which can be associated with either a variable or the file as a whole. Although there is no enforced limit, the user is expected to keep attributes small. For more information see @ref{Attributes,,, netcdf, @value{n-man}}. @end table For more information on the netCDF data model see @ref{The NetCDF Data Model,,, netcdf, @value{n-man}}. @subsection Meteorological Example NetCDF can be used to store many kinds of data, but it was originally developed for the Earth science community. NetCDF views the world of scientific data in the same way that an atmospheric scientist might: as sets of related arrays. There are various physical quantities (such as pressure and temperature) located at points at a particular latitude, longitude, vertical level, and time. A scientist might also like to store supporting information, such as the units, or some information about how the data were produced. The axis information (latitude, longitude, level, and time) would be stored as netCDF dimensions. Dimensions have a length and a name. The physical quantities (pressure, temperature) would be stored as netCDF variables. Variables are N-dimensional arrays of data, with a name and an associated set of netCDF dimensions. It is also customary to add one variable for each dimension, to hold the values along that axis. These variables are called ``coordinate variables.'' The latitude coordinate variable would be a one-dimensional variable (with latitude as its dimension), and it would hold the latitude values at each point along the axis. The additional bits of metadata would be stored as netCDF attributes. Attributes are always single values or one-dimensional arrays. (This works out well for a string, which is a one-dimensional array of ASCII characters.) The pres_temp_4D example in this tutorial shows how to write and read a file containing some four-dimensional pressure and temperature data, including all the metadata needed. @xref{pres_temp_4D}. @node Common Data Model, Errors, Data Model, Intro @section The Common Data Model and NetCDF-4 @cindex common data model @cindex groups @cindex compound types @cindex user-defined types @cindex netCDF-4 model extensions With netCDF-4, the netCDF data model has been extended, in a backwards compatible way. The new data model, which is known as the ``Common Data Model'' is part of an effort here at Unidata to find a common engineering language for the development of scientific data solutions. It contains the variables, dimensions, and attributes of the classic data model, but adds: @itemize @item groups A way of hierarchically organizing data, similar to directories in a Unix file system. @item user-defined types The user can now define compound types (like C structures), enumeration types, variable length arrays, and opaque types. @end itemize These features may only be used when working with a netCDF-4/HDF5 file. Files created in classic or 64-bit offset format cannot support groups or user-defined types. With netCDF-4/HDF5 files, the user may define groups, which may contain variables, dimensions, and attributes. In this way, a group acts as a container for the classic netCDF dataset. But netCDF-4/HDF5 files can have many groups, organized hierarchically. Each file begins with at least one group, the root group. The user may then add more groups, receiving a new ncid for each group created. Since each group functions as a complete netCDF classic dataset, it is possible to have variables with the same name in two or more different groups, within the same netCDF-4/HDF5 data file. Dimensions have a special scope: they may be seen by all variables in their group, and all descendant groups. This allows the user to define dimensions in a top-level group, and use them in many sub-groups. Since it may be necessary to write code which works with all types of netCDF data files, we also introduce the ability to create netCDF-4/HDF5 files which follow all the rules of the classic netCDF model. That is, these files are in HDF5, but will not support multiple unlimited dimensions, user-defined types, groups, etc. They act just like a classic netCDF file. @node Errors, Unlimited Dimensions, Common Data Model, Intro @section NetCDF Error Handling Each netCDF function in the C, Fortran 77, and Fortran 90 APIs returns 0 on success, in the tradition of C. (For C++, see below). When programming with netCDF in these languages, always check return values of every netCDF API call. The return code can be looked up in netcdf.h (for C programmers) or netcdf.inc (for Fortran programmers), or you can use the strerror function to print out an error message. (See @ref{nc_strerror,,, netcdf-c, @value{c-man}}/@ref{NF_STRERROR,,, netcdf-f77, @value{f77-man}}/@ref{NF90_STRERROR,,, netcdf-f90, @value{f90-man}}). In general, if a function returns an error code, you can assume it didn't do what you hoped it would. The exception is the NC_ERANGE error, which is returned by any of the reading or writing functions when one or more of the values read or written exceeded the range for the type. (For example if you were to try to read 1000 into an unsigned byte.) In the case of NC_ERANGE errors, the netCDF library completes the read/write operation, and then returns the error. The type conversion is handled like a C type conversion, whether or not it is within range. This may yield bad data, but the netCDF library just returns NC_ERANGE and leaves it up to the user to handle. (For more information about type conversion @pxref{Type Conversion,,, netcdf-c, @value{c-man}}). Error handling in C++ is different. For some objects, the is_valid() method should be called. Other error handling is controlled by the NcError class. For more information see @ref{Class NcError,,, netcdf-cxx, @value{cxx-man}}. For a complete list of netCDF error codes see @ref{Error Codes,,, netcdf-c, @value{c-man}}. @node Unlimited Dimensions, Fill Values, Errors, Intro @section Unlimited Dimensions Sometimes you don't know the size of all dimensions when you create a file, or you would like to arbitrarily extend the file along one of the dimensions. For example, model output usually has a time dimension. Rather than specifying that there will be forty-two output times when creating the file, you might like to create it with one time, and then add data for additional times, until you wanted to stop. For this purpose netCDF provides the unlimited dimension. By specifying a length of ``unlimited'' when defining a dimension, you indicate to netCDF that the dimension may be extended, and its length may increase. In netCDF classic files, there can only be one unlimited dimension, and it must be declared first in the list of dimensions for a variable. For programmers, the unlimited dimension will correspond with the slowest-varying dimension. In C this is the first dimension of an array, in Fortran, the last. The third example in this tutorial, pres_temp_4D, demonstrates how to write and read data one time step at a time along an unlimited dimension in a classic netCDF file. @xref{pres_temp_4D}. In netCDF-4/HDF5 files, any number of unlimited dimensions may be used, and there is no restriction as to where they appear in a variable's list of dimension IDs. For more detailed information about dimensions see @ref{Dimensions,,, netcdf, @value{n-man}}. @node Fill Values, Tools, Unlimited Dimensions, Intro @section Fill Values Sometimes there are missing values in the data, and some value is needed to represent them. For example, what value do you put in a sea-surface temperature variable for points over land? In netCDF, you can create an attribute for the variable (and of the same type as the variable) called ``_FillValue'' that contains a value that you have used for missing data. Applications that read the data file can use this to know how to represent these values. Using attributes it is possible to capture metadata that would otherwise be separated from the data. Various conventions have been established. By using a set of conventions, a data producer is more likely to produce files that can be easily shared within the research community, and that contain enough details to be useful as a long-term archive. Conventions also make it easier to develop software that interprets information represented in data, because a convention selects one conventional way to represent information when multiple equivalent representations are possible. For more information on _FillValue and other attribute conventions, see @ref{Attribute Conventions,,, netcdf, @value{n-man}}. Climate and meteorological users are urged to follow the Climate and Forecast (CF) metadata conventions when producing data files. For more information about the CF conventions, see @uref{@value{cf-url}}. For information about creating attributes, see @ref{Creation}. @node Tools, APIs, Fill Values, Intro @section Tools for Manipulating NetCDF Files @cindex ncdump @cindex ncgen @cindex third-party tools @cindex software for netCDF Many existing software applications can read and manipulate netCDF files. Before writing your own program, check to see if any existing programs meet your needs. Two utilities come with the netCDF distribution: ncdump and ncgen. The ncdump command reads a netCDF file and outputs text in a format called CDL. The ncgen command reads a text file in CDL format, and generates a netCDF data file. One common use for ncdump is to examine the metadata of a netCDF file, to see what it contains. At the beginning of each example in this tutorial, an ncdump of the resulting data file is shown. @xref{simple_xy}. For more information about ncdump and ncgen see @ref{NetCDF Utilities,,, netcdf, @value{n-man}}. The following general-purpose tools have been found to be useful in many situations. Some of the tools on this list are developed at Unidata. The others are developed elsewhere, and we can make no guarantees about their continued availability or success. All of these tools are open-source. @multitable @columnfractions .20 .40 .40 @item UDUNITS @tab Unidata library to help with scientific units. @tab @uref{@value{udunits-url}} @item IDV @tab Unidata's Integrated Data Viewer, a 3D visualization and analysis package (Java based). @tab @uref{@value{idv-url}} @item NCL @tab NCAR Command Language, a graphics and data manipulation package. @tab @uref{@value{ncl-url}} @item GrADS @tab The Grid Analysis and Display System package. @tab @uref{@value{grads-url}} @item NCO @tab NetCDF Command line Operators, tools to manipulate netCDF files. @tab @uref{@value{nco-url}} @end multitable For a list of netCDF tools that we know about see @uref{@value{netcdf-software-url}}. If you know of any that should be added to this list, send email to @value{netcdf-support-email}. @node APIs, Documentation, Tools, Intro @section The NetCDF Programming APIs @cindex tools for manipulating netCDF @cindex language APIs for netCDF @cindex perl, netCDF API @cindex ruby, netCDF API @cindex python, netCDF API @cindex C++, netCDF API @cindex C, netCDF API @cindex Fortran 77, netCDF API @cindex Fortran 90, netCDF API @cindex V2 API Unidata supports netCDF APIs in C, C++, Fortran 77, Fortran 90, and Java. The Java API is a complete implementation of netCDF in Java. It is distributed independently of the other APIs. For more information see the netCDF Java page: @uref{@value{netcdf-java-url}}. If you are writing web server software, you should certainly be doing so in Java. The C, C++, Fortran 77 and Fortran 90 APIs are distributed and installed when the netCDF C library is built, if compilers exist to build them, and if they are not turned off when configuring the netCDF build. The C++ and Fortran APIs depend on the C API. Due to the nature of C++ and Fortran 90, users of those languages can also use the C and Fortran 77 APIs (respectively) directly. In the netCDF-4.0 beta release, only the C API is well-tested. The Fortran APIs include support for netCDF-4 advanced features, but need more testing, which will be added in a future release of netCDF. The C++ API can handle netCDF-4.0/HDF5 files, but can not yet handle advanced netCDF-4 features. The successor to the current C++ API is under active development, and will include support for netCDF-4 advanced features. Full documentation exists for each API (@pxref{Documentation}). In addition, many other language APIs exist, including Perl, Python, and Ruby. Most of these APIs were written and supported by netCDF users. Some of them are listed on the netCDF software page, see @uref{@value{netcdf-software-url}}. Since these generally use the C API, they should work well with netCDF-4/HDF5 files, but the maintainers of the APIs must add support for netCDF-4 advanced features. In addition to the main netCDF-3 C API, there is an additional (older) C API, the netCDF-2 API. This API produces exactly the same files as the netCDF-3 API - only the API is different. (That is, users can create either classic format files, the default, or 64-bit offset files, or netCDF-4/HDF5 files.) The version 2 API was the API before netCDF-3.0 came out. It is still fully supported, however. Programs written to the version 2 API will continue to work. Users writing new programs should use the netCDF-3 API, which contains better type checking, better error handling, and better documentation. The netCDF-2 API is provided for backward compatibility. Documentation for the netCDF-2 API can be found on the netCDF website, see @uref{@value{v2-docs-url}}. @node Documentation, Versions, APIs, Intro @section NetCDF Documentation This tutorial is brief. A much more complete description of netCDF can be found in @value{n-man}. It fully describes the netCDF model and format. For more information see @ref{Top, @value{n-man},, netcdf, @value{n-man}}. The netCDF distribution, in various forms, can be obtained from the netCDF web site: @uref{@value{netcdf-url}}. A porting and installation guide for the C, C++, Fortran 77, and Fortran 90 APIs describes how to build these APIs on a variety of platforms. @xref{Top, @value{i-man},, netcdf-install, @value{i-man}}. Language specific programming guides are available for netCDF for the C, C++, Fortran 77, Fortran 90, and Java APIs: @table @code @item C @ref{Top, @value{c-man},, netcdf-c, @value{c-man}}. @item C++ @ref{Top, @value{cxx-man},, netcdf-cxx, @value{cxx-man}}. @item Fortran 77 @ref{Top, @value{f77-man},, netcdf-f77, @value{f77-man}}. @item Fortran 90 @ref{Top, @value{f90-man},, netcdf-f90, @value{f90-man}}. @item Java @uref{@value{netcdf-java-man-url}}. @end table Man pages for the C, F77, and F90 interfaces, and ncgen and ncdump, are available on the documentation page of the netCDF web site (@uref{@value{docs-url}}), and are installed with the netCDF distribution. The latest version of all netCDF documentation can always be found at the documentation page of the netCDF web site: @uref{@value{docs-url}} @node Versions, , Documentation, Intro @section A Note on NetCDF Versions and Formats @cindex classic format @cindex 64-bit offset format NetCDF has changed (and improved) over its lifetime. That means the user must have some understanding of netCDF versions. To add to the confusion, there are versions for the APIs, and also for the data files that they produce. The API version is the version number that appears in the tarball file that is downloaded from the netCDF website. For example this document applied to API version @value{VERSION}. The good news is that all netCDF files ever written can always be read by the latest netCDF release. That is, we guarantee backward data compatibility. @subsection Classic Format The default format is classic format. This is the original netCDF binary format - the format that the netCDF library has been using for almost 20 years, since its introduction with the first release of netCDF. No special flag is needed to create a file in classic format; it is the default. Classic format has some strict limitations for files larger than two gigabytes. (@pxref{NetCDF Classic Format Limitations,,, netcdf, @value{n-man}}). @subsection 64-bit Offset Format In December, 2004, version 3.6.0 of the netCDF library was released. It allows users to use a new version of the netCDF file format which greatly expands the sizes of variables and files which may be written. The format which was introduced in 3.6.0 is called ``64-bit Offset Format.'' Create files in this format by passing the 64-bit offset format flag to the create call (for example, in C, set the NC_64BIT_OFFSET flag when calling the function nc_create. (@pxref{nc_create,,, netcdf-c, @value{c-man}}). 64-bit offset is very useful for very large data files (over two gigabytes), however these files can only be shared with those who have upgraded to version 3.6.0 (or better) of netCDF. Earlier versions of netCDF will not be able to read these files. @subsection NetCDF-4/HDF5 Format With version 4.0 of netCDF, we introduce another new data format: netCDF-4/HDF5 format. This format is HDF5, with full use of the new dimension scales, creation ordering, and other features of HDF5 added in its version 1.8.0 release. As with 64-bit offset, this format is turned on when the file is created. (For example, with the nf_netcdf4 flag in the nf_create function. @pxref{nf_create,,, netcdf-f77, @value{f77-man}}). @subsection Sharing Data The classic format is the most portable. Classic format files can be read correctly by any version of netCDF. A netCDF-4 user can create a classic file, and share it with a user who has not upgraded netCDF since the version 2.3 in 1994. 64-bit offset format files can be read by any user who has at least version 3.6.0 of the netCDF API (released in Dec., 2004). Users must have netCDF 4.0 to read netCDF-4/HDF5 files. However, netCDF-4 does produce backward compatible classic and 64-bit offset format files. That is, a netCDF-4.0 user can create a classic format file, and share it with researchers who are still using a old version of netCDF. Similarly a netCDF-4.0 user can read any existing netCDF data file, whatever version of netCDF was used to create it. @subsection Classic Model The original netCDF API represents a data model as well as a programming API. That is, the idea of variables, attributes, and the six data types (char, byte, short, integer, float, and double), comprises a model of how data may be stored. The netCDF-4 release expands this model with groups, user-defined types, and new base types. New functions have been added to the APIs to accommodate these extensions, but once they are used, the file can no longer be output as a classic format file. That is, once you use groups in your code, you can only produce netCDF-4/HDF5 files. If you try to change the format to classic, you will get an error when you attempt to use any of the group functions. Since it is convenient to be able to produce files of all formats from the same code (restricting oneself to the classic data model), a flag has been added which, when used in the creation of a netCDF-4/HDF5 file, will instruct the library to disallow the use of any advanced features in the file. This is referred to as a ``classic model'' netCDF-4/HDF5 file. To get a classic model file, use the classic model flag when creating the file. For example, in Fortran 77, use the nf_classic_model flag when calling nf_create (@pxref{nf_create,,, netcdf-f77, @value{f77-man}}). For more information about format issues see @ref{Format, @value{n-man},, netcdf, @value{n-man}}. @node Examples, Useful Functions, Intro, Top @chapter Example Programs @cindex example programs @cindex simple_xy example @cindex sfc_pres_temp example @cindex pres_temp_4D example The netCDF example programs show how to use netCDF. In the netCDF distribution, the ``examples'' directory contains examples in C, Fortran 77, Fortran 90, C++, and CDL. There are three sets of netCDF-3 example programs in each language. Each language has its own subdirectory under the ``examples'' directory (for example, the Fortran 77 examples are in ``examples/F77''). There is also one example for netCDF-4, which is only provided in the C language. This example will only be run if the --enable-netcdf-4 option was used with configure. The examples are built and run with the ``make check'' command. (For more information on building netCDF, @pxref{Top, @value{i-man},, netcdf-install, @value{i-man}}). The examples create, and then read, example data files of increasing complexity. The corresponding examples in each language create identical netCDF data files. For example, the C program sfc_pres_temp_wr.c produces the same data file as the Fortran 77 program sfc_pres_temp_wr.f. For convenience, the complete source code in each language can be found in this tutorial, as well as in the netCDF distribution. @menu * simple_xy:: A very simple netCDF file. * sfc_pres_temp:: A more complex file with more metadata. * pres_temp_4D:: A 4D file with an unlimited dimension. @end menu @node simple_xy, sfc_pres_temp, Examples, Examples @section The simple_xy Example This example is an unrealistically simple netCDF file, to demonstrate the minimum operation of the netCDF APIs. Users should seek to make their netCDF files more self-describing than this primitive example. As in all the netCDF tutorial examples, this example file is created by C, Fortran 77, Fortran 90, and C++ programs, and by ncgen, which creates it from a CDL script. All examples create identical files, ``simple_xy.nc.'' The programs that create this sample file all have the base name ``simple_xy_wr'', with different extensions depending on the language. Therefore the example files that create simple_xy.nc can be found in: C/simple_xy_wr.c, F77/simple_xy_wr.f, F90/simple_xy_wr.f90, CXX/simple_xy_wr.cpp, and CDL/simple_xy_wr.cdl. Corresponding read programs (C/simple_xy_rd.c, etc.) read the simple_xy.nc data file, and ensure that it contains the correct values. The simple_xy.nc data file contains two dimensions, ``x'' and ``y'', and one netCDF variable, ``data.'' The utility ncdump can be used to show the contents of netCDF files. By default, ncdump shows the CDL description of the file. This CDL description can be fed into ncgen to create the data file. The CDL for this example is shown below. For more information on ncdump and ncgen see @ref{NetCDF Utilities,,, netcdf, @value{n-man}}. @example @include simple_xy.cdl @end example @menu * simple_xy in C:: * simple_xy in F77:: * simple_xy in F90:: * simple_xy in C++:: @end menu @node simple_xy in C, simple_xy in F77, simple_xy, simple_xy @subsection simple_xy_wr.c and simple_xy_rd.c These example programs can be found in the netCDF distribution, under examples/C. The example program simple_xy_wr.c creates the example data file simple_xy.nc. The example program simple_xy_rd.c reads the data file. @menu * simple_xy_wr.c:: * simple_xy_rd.c:: @end menu @node simple_xy_wr.c, simple_xy_rd.c, simple_xy in C, simple_xy in C @subsubsection simple_xy_wr.c @example @include simple_xy_wr.c @end example @node simple_xy_rd.c, , simple_xy_wr.c, simple_xy in C @subsubsection simple_xy_rd.c @example @include simple_xy_rd.c @end example @node simple_xy in F77, simple_xy in F90, simple_xy in C, simple_xy @subsection simple_xy_wr.f and simple_xy_rd.f These example programs can be found in the netCDF distribution, under examples/F77. The example program simple_xy_wr.f creates the example data file simple_xy.nc. The example program simple_xy_rd.f reads the data file. @menu * simple_xy_wr.f:: * simple_xy_rd.f:: @end menu @node simple_xy_wr.f, simple_xy_rd.f, simple_xy in F77, simple_xy in F77 @subsubsection simple_xy_wr.f @example @include simple_xy_wr.f @end example @node simple_xy_rd.f, , simple_xy_wr.f, simple_xy in F77 @subsubsection simple_xy_rd.f @example @include simple_xy_rd.f @end example @node simple_xy in F90, simple_xy in C++, simple_xy in F77, simple_xy @subsection simple_xy_wr.f90 and simple_xy_rd.f90 These example programs can be found in the netCDF distribution, under examples/F90. The example program simple_xy_wr.f90 creates the example data file simple_xy.nc. The example program simple_xy_rd.f90 reads the data file. @menu * simple_xy_wr.f90:: * simple_xy_rd.f90:: @end menu @node simple_xy_wr.f90, simple_xy_rd.f90, simple_xy in F90, simple_xy in F90 @subsubsection simple_xy_wr.f90 @example @include simple_xy_wr.f90 @end example @node simple_xy_rd.f90, , simple_xy_wr.f90, simple_xy in F90 @subsubsection simple_xy_rd.f90 @example @include simple_xy_rd.f90 @end example @node simple_xy in C++, , simple_xy in F90, simple_xy @subsection simple_xy_wr.cpp and simple_xy_rd.cpp These example programs can be found in the netCDF distribution, under examples/CXX. The example program simple_xy_wr.cpp creates the example data file simple_xy.nc. The example program simple_xy_rd.cpp reads the data file. @menu * simple_xy_wr.cpp:: * simple_xy_rd.cpp:: @end menu @node simple_xy_wr.cpp, simple_xy_rd.cpp, simple_xy in C++, simple_xy in C++ @subsubsection simple_xy_wr.cpp @example @include simple_xy_wr.cpp @end example @node simple_xy_rd.cpp, , simple_xy_wr.cpp, simple_xy in C++ @subsubsection simple_xy_rd.cpp @example @include simple_xy_rd.cpp @end example @node sfc_pres_temp, pres_temp_4D, simple_xy, Examples @section The sfc_pres_temp Example This example has been constructed for the meteorological mind. Suppose you have some data you want to write to a netCDF file. For example, you have one time step of surface temperature and surface pressure, on a 6 x 12 latitude longitude grid. To store this in netCDF, create a file, add two dimensions (latitude and longitude) and two variables (pressure and temperature). In this example we add some netCDF attributes, as is typical in scientific applications, to further describe the data. In this case we add a units attribute to every netCDF variable. In this example we also add additional netCDF variables to describe the coordinate system. These ``coordinate variables'' allow us to specify the latitudes and longitudes that describe the data grid. The CDL version of the data file, generated by ncdump, is shown below. For more information on ncdump and ncgen see @ref{NetCDF Utilities,,, netcdf, @value{n-man}}. @example @include sfc_pres_temp.cdl @end example @menu * sfc_pres_temp in C:: * sfc_pres_temp in F77:: * sfc_pres_temp in F90:: * sfc_pres_temp in C++:: @end menu @node sfc_pres_temp in C, sfc_pres_temp in F77, sfc_pres_temp, sfc_pres_temp @subsection sfc_pres_temp_wr.c and sfc_pres_temp_rd.c These example programs can be found in the netCDF distribution, under examples/C. The example program sfc_pres_temp_wr.c creates the example data file sfc_pres_temp.nc. The example program sfc_pres_temp_rd.c reads the data file. @menu * sfc_pres_temp_wr.c:: * sfc_pres_temp_rd.c:: @end menu @node sfc_pres_temp_wr.c, sfc_pres_temp_rd.c, sfc_pres_temp in C, sfc_pres_temp in C @subsubsection sfc_pres_temp_wr.c @example @include sfc_pres_temp_wr.c @end example @node sfc_pres_temp_rd.c, , sfc_pres_temp_wr.c, sfc_pres_temp in C @subsubsection sfc_pres_temp_rd.c @example @include sfc_pres_temp_rd.c @end example @node sfc_pres_temp in F77, sfc_pres_temp in F90, sfc_pres_temp in C, sfc_pres_temp @subsection sfc_pres_temp_wr.f and sfc_pres_temp_rd.f These example programs can be found in the netCDF distribution, under examples/F77. The example program sfc_pres_temp_wr.f creates the example data file sfc_pres_temp.nc. The example program sfc_pres_temp_rd.f reads the data file. @menu * sfc_pres_temp_wr.f:: * sfc_pres_temp_rd.f:: @end menu @node sfc_pres_temp_wr.f, sfc_pres_temp_rd.f, sfc_pres_temp in F77, sfc_pres_temp in F77 @subsubsection sfc_pres_temp_wr.f @example @include sfc_pres_temp_wr.f @end example @node sfc_pres_temp_rd.f, , sfc_pres_temp_wr.f, sfc_pres_temp in F77 @subsubsection sfc_pres_temp_rd.f @example @include sfc_pres_temp_rd.f @end example @node sfc_pres_temp in F90, sfc_pres_temp in C++, sfc_pres_temp in F77, sfc_pres_temp @subsection sfc_pres_temp_wr.f90 and sfc_pres_temp_rd.f90 These example programs can be found in the netCDF distribution, under examples/F90. The example program sfc_pres_temp_wr.f90 creates the example data file sfc_pres_temp.nc. The example program sfc_pres_temp_rd.f90 reads the data file. @menu * sfc_pres_temp_wr.f90:: * sfc_pres_temp_rd.f90:: @end menu @node sfc_pres_temp_wr.f90, sfc_pres_temp_rd.f90, sfc_pres_temp in F90, sfc_pres_temp in F90 @subsubsection sfc_pres_temp_wr.f90 @example @include sfc_pres_temp_wr.f90 @end example @node sfc_pres_temp_rd.f90, , sfc_pres_temp_wr.f90, sfc_pres_temp in F90 @subsubsection sfc_pres_temp_rd.f90 @example @include sfc_pres_temp_rd.f90 @end example @node sfc_pres_temp in C++, , sfc_pres_temp in F90, sfc_pres_temp @subsection sfc_pres_temp_wr.cpp and sfc_pres_temp_rd.cpp These example programs can be found in the netCDF distribution, under examples/CXX. The example program sfc_pres_temp_wr.cpp creates the example data file sfc_pres_temp.nc. The example program sfc_pres_temp_rd.cpp reads the data file. @menu * sfc_pres_temp_wr.cpp:: * sfc_pres_temp_rd.cpp:: @end menu @node sfc_pres_temp_wr.cpp, sfc_pres_temp_rd.cpp, sfc_pres_temp in C++, sfc_pres_temp in C++ @subsubsection sfc_pres_temp_wr.cpp @example @include sfc_pres_temp_wr.cpp @end example @node sfc_pres_temp_rd.cpp, , sfc_pres_temp_wr.cpp, sfc_pres_temp in C++ @subsubsection sfc_pres_temp_rd.cpp @example @include sfc_pres_temp_rd.cpp @end example @node pres_temp_4D, , sfc_pres_temp, Examples @section The pres_temp_4D Example This example expands on the previous example by making our two-dimensional data into four-dimensional data, adding a vertical level axis and an unlimited time step axis. Additionally, in this example the data are written and read one time step at a time, as is typical in scientific applications that use the unlimited dimension. The sample data file created by pres_temp_4D_wr can be examined with the utility ncdump. The output is shown below. For more information on ncdump see @ref{NetCDF Utilities,,, netcdf, @value{n-man}}. @example @include pres_temp_4D.cdl @end example @menu * pres_temp_4D in C:: * pres_temp_4D in F77:: * pres_temp_4D in F90:: * pres_temp_4D in C++:: @end menu @node pres_temp_4D in C, pres_temp_4D in F77, pres_temp_4D, pres_temp_4D @subsection pres_temp_4D_wr.c and pres_temp_4D_rd.c These example programs can be found in the netCDF distribution, under examples/C. The example program pres_temp_4D_wr.c creates the example data file pres_temp_4D.nc. The example program pres_temp_4D_rd.c reads the data file. @menu * pres_temp_4D_wr.c:: * pres_temp_4D_rd.c:: @end menu @node pres_temp_4D_wr.c, pres_temp_4D_rd.c, pres_temp_4D in C, pres_temp_4D in C @subsubsection pres_temp_4D_wr.c @example @include pres_temp_4D_wr.c @end example @node pres_temp_4D_rd.c, , pres_temp_4D_wr.c, pres_temp_4D in C @subsubsection pres_temp_4D_rd.c @example @include pres_temp_4D_rd.c @end example @node pres_temp_4D in F77, pres_temp_4D in F90, pres_temp_4D in C, pres_temp_4D @subsection pres_temp_4D_wr.f and pres_temp_4D_rd.f These example programs can be found in the netCDF distribution, under examples/F77. The example program pres_temp_4D_wr.f creates the example data file pres_temp_4D.nc. The example program pres_temp_4D_rd.f reads the data file. @menu * pres_temp_4D_wr.f:: * pres_temp_4D_rd.f:: @end menu @node pres_temp_4D_wr.f, pres_temp_4D_rd.f, pres_temp_4D in F77, pres_temp_4D in F77 @subsubsection pres_temp_4D_wr.f @example @include pres_temp_4D_wr.f @end example @node pres_temp_4D_rd.f, , pres_temp_4D_wr.f, pres_temp_4D in F77 @subsubsection pres_temp_4D_rd.f @example @include pres_temp_4D_rd.f @end example @node pres_temp_4D in F90, pres_temp_4D in C++, pres_temp_4D in F77, pres_temp_4D @subsection pres_temp_4D_wr.f90 and pres_temp_4D_rd.f90 These example programs can be found in the netCDF distribution, under examples/F90. The example program pres_temp_4D_wr.f90 creates the example data file pres_temp_4D.nc. The example program pres_temp_4D_rd.f90 reads the data file. @menu * pres_temp_4D_wr.f90:: * pres_temp_4D_rd.f90:: @end menu @node pres_temp_4D_wr.f90, pres_temp_4D_rd.f90, pres_temp_4D in F90, pres_temp_4D in F90 @subsubsection pres_temp_4D_wr.f90 @example @include pres_temp_4D_wr.f90 @end example @node pres_temp_4D_rd.f90, , pres_temp_4D_wr.f90, pres_temp_4D in F90 @subsubsection pres_temp_4D_rd.f90 @example @include pres_temp_4D_rd.f90 @end example @node pres_temp_4D in C++, , pres_temp_4D in F90, pres_temp_4D @subsection pres_temp_4D_wr.cpp and pres_temp_4D_rd.cpp These example programs can be found in the netCDF distribution, under examples/CXX. The example program pres_temp_4D_wr.cpp creates the example data file pres_temp_4D.nc. The example program pres_temp_4D_rd.cpp reads the data file. @menu * pres_temp_4D_wr.cpp:: * pres_temp_4D_rd.cpp:: @end menu @node pres_temp_4D_wr.cpp, pres_temp_4D_rd.cpp, pres_temp_4D in C++, pres_temp_4D in C++ @subsubsection pres_temp_4D_wr.cpp @example @include pres_temp_4D_wr.cpp @end example @node pres_temp_4D_rd.cpp, , pres_temp_4D_wr.cpp, pres_temp_4D in C++ @subsubsection pres_temp_4D_rd.cpp @example @include pres_temp_4D_rd.cpp @end example @node Useful Functions, API-Extensions, Examples, Top @chapter The Functions You Need in NetCDF-3 The netCDF-3 C and Fortran APIs each have over 100 functions, but most users need only a handful. Listed below are the essential netCDF functions for four important tasks in netCDF: creating new files, reading existing files, learning about a netCDF file of unknown structure, and reading and writing subsets of data. In each case the functions are presented for each of the four language APIs: C, Fortran 77, Fortran 90, and C++, with hyper-links to the detailed documentation of each function. @menu * Creation:: Creating netCDF files, adding metadata. * Reading:: Reading netCDF files of known structure. * Inquiry Functions:: Learning about an unknown netCDF file. * Subsets:: Reading and writing Subsets of data. @end menu @node Creation, Reading, Useful Functions, Useful Functions @section Creating New Files and Metadata, an Overview @cindex creating netCDF files To construct a netCDF file you need to: @table @code @item create the file Specify the name, optionally the format: classic (the default) or 64bit-offset. @item define metadata Specify the names and types of dimensions, data variables, and attributes. @item write data Write arrays of data from program variables to the netCDF file. Arrays of data may be written all at once, or in subsets. @item close the file Close the file to flush all buffers to the disk and free all resources allocated for this file. @end table @menu * Creation in C:: * Creation in F77:: * Creation in F90:: * Creation in C++:: @end menu @node Creation in C, Creation in F77, Creation, Creation @subsection Creating a NetCDF File in C @cindex creating files in C @findex nc_create @findex nc_def_dim @findex nc_def_var @findex nc_put_att @findex nc_enddef @findex nc_put_vara @findex nc_close Use nc_create to create a file. Then use nc_def_dim to define each shared dimension. The data variables are then specified with nc_def_var. Any attributes are added with nc_put_att. Finally, call nc_enddef to tell the library that you are done defining the metadata, and ready to start writing the data. After all data are written to the file, call nc_close to ensure that all buffers are flushed, and any resources associated with the open file are returned to the operating system. For a very simple example, @xref{simple_xy in C}. For a typical sequence of calls to the C versions of these functions, see @xref{Creating, Creating a NetCDF Dataset, Creating a NetCDF Dataset, netcdf-c, @value{c-man}}. @multitable @columnfractions .50 .50 @item @ref{nc_create,,, netcdf-c, @value{c-man}} @tab create a new netCDF file @item @ref{nc_def_dim,,, netcdf-c, @value{c-man}} @tab define a dimension @item @ref{nc_def_var,,, netcdf-c, @value{c-man}} @tab define a variable @item @ref{nc_put_att_ type,,, netcdf-c, @value{c-man}} @tab write attributes @item @ref{nc_enddef,,, netcdf-c, @value{c-man}} @tab leave define mode @item @ref{nc_put_vara_ type,,, netcdf-c, @value{c-man}} @tab write arrays of data @item @ref{nc_close,,, netcdf-c, @value{c-man}} @tab close a file @end multitable @node Creation in F77, Creation in F90, Creation in C, Creation @subsection Creating a NetCDF File in Fortran 77 @cindex creating files in Fortran @findex NF_CREATE @findex NF_DEF_DIM @findex NF_DEF_VAR @findex NF_PUT_ATT_ type @findex NF_ENDDEF @findex NF_PUT_VARA @findex NF_CLOSE Use NF_CREATE to create a file. Then use NF_DEF_DIM to define each shared dimension. The data variables are then specified with NF_DEF_VAR. Any attributes are added with NF_PUT_ATT. Finally, call NF_ENDDEF to tell the library that you are done defining the metadata, and ready to start writing the data. After all data are written to the file, call NF_CLOSE to ensure that all buffers are flushed, and any resources associated with the open file are returned to the operating system. For a typical sequence of calls see @ref{Creating, Creating a NetCDF Dataset, Creating a NetCDF Dataset, netcdf-f77, @value{f77-man}}. Fortran users take note: the netCDF Fortran 77 API consists of wrappers around the functions of the netCDF C library. There is no Fortran 77 code in netCDF except for these wrappers, and tests to ensure that the wrappers work. The name of each Fortran function shows the outline of the C function it wraps (for example, NF_CREATE is a wrapper around nc_create). @multitable @columnfractions .50 .50 @item @ref{NF_CREATE,,, netcdf-f77, @value{f77-man}} @tab create a new netCDF file @item @ref{NF_DEF_DIM,,, netcdf-f77, @value{f77-man}} @tab define a dimension @item @ref{NF_DEF_VAR,,, netcdf-f77, @value{f77-man}} @tab define a variable @item @ref{NF_PUT_ATT_ type,,, netcdf-f77, @value{f77-man}} @tab write an attribute @item @ref{NF_ENDDEF,,, netcdf-f77, @value{f77-man}} @tab end define mode @item @ref{NF_PUT_VARA_ type,,, netcdf-f77, @value{f77-man}} @tab write arrays of data @item @ref{NF_CLOSE,,, netcdf-f77, @value{f77-man}} @tab close the netCDF file @end multitable @node Creation in F90, Creation in C++, Creation in F77, Creation @subsection Creating a NetCDF File in Fortran 90 @cindex creating files in Fortran @findex NF90_CREATE @findex NF90_DEF_DIM @findex NF90_DEF_VAR @findex NF90_PUT_ATT_ type @findex NF90_ENDDEF @findex NF90_PUT_VARA @findex NF90_CLOSE Use NF90_CREATE to create a file. Then use NF90_DEF_DIM to define each shared dimension. The data variables are then specified with NF90_DEF_VAR. Any attributes are added with NF90_PUT_ATT. Finally, call NF90_ENDDEF to tell the library that you are done defining the metadata, and ready to start writing the data. After all data are written to the file, call NF90_CLOSE to ensure that all buffers are flushed, and any resources associated with the open file are returned to the operating system. For a typical sequence of calls see @ref{Creating, Creating a NetCDF Dataset, Creating a NetCDF Dataset, netcdf-f90, @value{f90-man}}. The netCDF Fortran 90 API calls the Fortran 77 API, which in turn calls the netCDF C library. The name of each Fortran function shows the outline of the F77 function it wraps (for example, NF90_CREATE is a wrapper around NF_CREATE). The F77 functions are, in turn, wrappers around the C functions. @multitable @columnfractions .50 .50 @item @ref{NF90_CREATE,,, netcdf-f90, @value{f90-man}} @tab create a netCDF file @item @ref{NF90_DEF_DIM,,, netcdf-f90, @value{f90-man}} @tab define a dimension @item @ref{NF90_DEF_VAR,,, netcdf-f90, @value{f90-man}} @tab define a variable @item @ref{NF90_PUT_ATT_ type,,, netcdf-f90, @value{f90-man}} @tab write an attribute @item @ref{NF90_ENDDEF,,, netcdf-f90, @value{f90-man}} @tab end define mode @item @ref{NF90_PUT_VARA_ type,,, netcdf-f90, @value{f90-man}} @tab write arrays of data @item @ref{NF90_CLOSE,,, netcdf-f90, @value{f90-man}} @tab close the netCDF file @end multitable @node Creation in C++, , Creation in F90, Creation @subsection Creating a NetCDF File in C++ @cindex creating files in C++ Create an instance of the NcFile class to create a netCDF file. Use its add_dim and add_var methods to add dimensions and variables. The add_att method is available for both NcFile and NcVar. Use the NcError class to specify error handling behavior. For an example creating a simple file see @ref{simple_xy_wr.cpp}. For a more complex example see @ref{pres_temp_4D_wr.cpp}. @multitable @columnfractions .50 .50 @item @ref{Class NcFile,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF files @item @ref{Class NcDim,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF dimensions @item @ref{Class NcVar,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF variables @item @ref{Class NcAtt,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF attributes @item @ref{Class NcError,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to control netCDF error handling @end multitable @node Reading, Inquiry Functions, Creation, Useful Functions @section Reading NetCDF Files of Known Structure @cindex reading netCDF files of known structure @cindex inquiry functions To read a netCDF file of known structure, you need to: @table @code @item open the file Specify the file name and whether you want read-write or read-only access. @item read variable or attribute data Read the data or attributes of interest. @item close the file Release all resources associated with this file. @end table Use ncdump to learn the structure of a file (use the -h option). For more information about ncdump see @ref{NetCDF Utilities,,, netcdf, @value{n-man}}. @subsection Numbering of NetCDF IDs In C, Fortran 77, and Fortran 90, netCDF objects are identified by an integer: the ID. NetCDF functions use this ID to identify the object. It's helpful for the programmer to understand these IDs. Open data files, dimensions, variables, and attributes are each numbered independently, and are always numbered in the order in which they were defined. (They also appear in this order in ncdump output.) Numbering starts with 0 in C, and 1 in Fortran 77/90. For example, the first variable defined in a file will have an ID of 0 in C programs, and 1 in Fortran programs, and functions that apply to a variable will need to know the ID of the variable you mean. (The numbering of files is an exception: file IDs are assigned by the operating system when a file is opened, and are not permanently associated with the file. IDs for netCDF dimensions and variables are persistent, but deleting an attribute changes subsequent attribute numbers.) Although netCDF refers to everything by an integer id (varid, dimid, attnum), there are inquiry functions which, given a name, will return an ID. For example, in the C API, nc_inq_varid will take a character string (the name), and give back the ID of the variable of that name. The variable ID is then used in subsequent calls (to read the data, for example). Other inquiry functions exist to further describe the file. (@pxref{Inquiry Functions}). @menu * Reading in C:: * Reading in F77:: * Reading in F90:: * Reading in C++:: @end menu @node Reading in C, Reading in F77, Reading, Reading @subsection Reading a Known NetCDF File in C @cindex reading netCDF files with C @findex nc_open @findex nc_get_att @findex nc_get_vara For a typical sequence of calls to these C functions see @ref{Reading Known, Reading a NetCDF Dataset with Known Names, Reading a NetCDF Dataset with Known Names, netcdf-c, @value{c-man}}. @multitable @columnfractions .17 .32 .51 @item @ref{nc_open,,, netcdf-c, @value{c-man}} @tab open a netCDF file @item @ref{nc_get_att,,, netcdf-c, @value{c-man}} @tab read an attribute @item @ref{nc_get_vara_ type,,, netcdf-c, @value{c-man}} @tab read arrays of data @item @ref{nc_close,,, netcdf-c, @value{c-man}} @tab close the file @end multitable @node Reading in F77, Reading in F90, Reading in C, Reading @subsection Reading a Known NetCDF File in Fortran 77 @cindex reading netCDF files with Fortran 77 @findex NF_OPEN @findex NF_GET_ATT @findex NF_GET_VARA For a typical sequence of calls to these functions see @ref{Reading Known, Reading a NetCDF Dataset with Known Names, Reading a NetCDF Dataset with Known Names, netcdf-f77, @value{f77-man}}. @multitable @columnfractions .50 .50 @item @ref{NF_OPEN,,, netcdf-f77, @value{f77-man}} @tab open a netCDF file @item @ref{NF_GET_ATT,,, netcdf-f77, @value{f77-man}} @tab read an attribute @item @ref{NF_GET_VARA_ type,,, netcdf-f77, @value{f77-man}} @tab read arrays of data @item @ref{NF_CLOSE,,, netcdf-f77, @value{f77-man}} @tab close the file @end multitable @node Reading in F90, Reading in C++, Reading in F77, Reading @subsection Reading a Known NetCDF File in Fortran 90 @cindex reading netCDF files with Fortran 90 @findex NF90_OPEN @findex NF90_GET_ATT @findex NF90_GET_VARA For a typical sequence of calls to these functions see @ref{Reading Known, Reading a NetCDF Dataset with Known Names, Reading a NetCDF Dataset with Known Names, netcdf-f90, @value{f90-man}}. @multitable @columnfractions .50 .50 @item @ref{NF90_OPEN,,, netcdf-f90, @value{f90-man}} @tab open a netCDF file @item @ref{NF90_GET_ATT,,, netcdf-f90, @value{f90-man}} @tab read an attribute @item @ref{NF90_GET_VARA,,, netcdf-f90, @value{f90-man}} @tab read arrays of data @item @ref{NF90_CLOSE,,, netcdf-f90, @value{f90-man}} @tab close the file @end multitable @node Reading in C++, , Reading in F90, Reading @subsection Reading a Known NetCDF File in C++ @cindex reading netCDF files with C++ @findex NcFile @multitable @columnfractions .17 .32 .51 @item @ref{Class NcFile,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF files @item @ref{Class NcDim,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF dimensions @item @ref{Class NcVar,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF variables @item @ref{Class NcAtt,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF attributes @end multitable @node Inquiry Functions, Subsets, Reading, Useful Functions @section Reading NetCDF Files of Unknown Structure Perhaps you would like to write your software to handle more general cases, so that you don't have to adjust your source every time the grid size changes, or a variable is added to the file. There are inquiry functions that let you find out everything you need to know about a file. These functions contain ``inq'' or ``INQ'' in their names. Using the inquiry functions, it is possible to write code that will read and understand any netCDF file, whatever its contents. (For example, ncdump does just that.) @menu * Inquiry in C:: * Inquiry in F77:: * Inquiry in F90:: * Inquiry in C++:: @end menu @node Inquiry in C, Inquiry in F77, Inquiry Functions, Inquiry Functions @subsection Inquiry in C First use nc_inq, which will tell you how many variables and global attributes there are in the file. Start with global attribute 0, and proceed to natts - 1, the number of global attributes minus one. The nc_inq_att function will tell you the name, type, and length of each global attribute. Then start with dimid 0, and proceed to dimid ndims - 1, calling nc_inq_dim. This will tell you the name and length of each dimension, and whether it is unlimited. Then start with varid 0, and proceed to varid nvars - 1, calling nc_inq_var. This will tell you the number of dimensions of this variable, and their associated IDs. It will also get the name and type of this variable, and whether there are any attributes attached. If there are attributes attached, use the nc_inq_att function to get their names, types, and lengths. (To read an attribute, use the appropriate nc_get_att_ function, like nc_get_att_int() to get the data from an attribute that is an array of integers.) There are also functions that return an item's ID, given its name. To find IDs from the names, use functions nc_inq_dimid, nc_inq_attnum, and nc_inq_varid. For a typical sequence of calls to these functions see @ref{Reading Unknown, Reading a netCDF Dataset with Unknown Names, Reading a netCDF Dataset with Unknown Names, netcdf-c, @value{c-man}}. @subsubsection NULL Parameters in Inquiry Functions With any of the C inquiry functions, a NULL pointer can be used to ignore a return parameter. Consider the nc_inq function: @example EXTERNL int nc_inq(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimidp); @end example If you call this with NULL for the last three parameters, you can learn the number of dimensions without bothering about the number of variables, number of global attributes, and the ID of the unlimited dimension. For further convenience, we provide functions like nc_inq_ndims, which only finds the number of dimensions, exactly as if you had called nc_inq, with NULLs in all parameters except ndimsp. (In fact, this is just what the nc_inq_ndims functions does). @multitable @columnfractions .17 .17 .25 .41 @item @ref{nc_inq,,, netcdf-c, @value{c-man}} @tab Find number of dimensions, variables, and global attributes, and the unlimited dimid. @item @ref{nc_inq_att,,, netcdf-c, @value{c-man}} @tab Find attribute name, type, and length. @item @ref{nc_inq_dim Family,,, netcdf-c, @value{c-man}} @tab Find dimension name and length. @item @ref{nc_inq_var,,, netcdf-c, @value{c-man}} @tab Find variable name, type, num dimensions, dim IDs, and num attributes. @item @ref{nc_inq_dimid,,, netcdf-c, @value{c-man}} @tab Find dimension ID from its name. @item @ref{nc_inq_varid,,, netcdf-c, @value{c-man}} @tab Find variable ID from its name. @item @ref{nc_inq_format,,, netcdf-c, @value{c-man}} @tab Find file format: classic or 64-bit offset @item @ref{nc_inq_libvers,,, netcdf-c, @value{c-man}} @tab Find the netCDF version. (Currently @value{VERSION}). @end multitable @node Inquiry in F77, Inquiry in F90, Inquiry in C, Inquiry Functions @subsection Inquiry in Fortran 77 First use NF_INQ, which will tell you how many variables and global attributes there are in the file. Then start with varid 1, and proceed to varid nvars, calling NF_INQ_VAR. For a typical sequence of calls to these functions see @ref{Reading Unknown, Reading a netCDF Dataset with Unknown Names, Reading a netCDF Dataset with Unknown Names, netcdf-f77, @value{f77-man}}. @multitable @columnfractions .27 .27 .45 @item @ref{NF_INQ,,, netcdf-f77, @value{f77-man}}. @tab Find number of dimensions, variables, and global attributes, and the unlimited dimid. @item @ref{NF_INQ_DIM,,, netcdf-f77, @value{f77-man}}. @tab Find dimension name and length. @item @ref{NF_INQ_VARID,,, netcdf-f77, @value{f77-man}}. @tab Find variable ID from its name. @item @ref{NF_INQ_VAR,,, netcdf-f77, @value{f77-man}}. @tab Find variable name, type, num dimensions, dim IDs, and num attributes. @item @ref{NF_INQ_DIMID,,, netcdf-f77, @value{f77-man}}. @tab Find dimension ID from its name. @item @ref{NF_INQ_DIM,,, netcdf-f77, @value{f77-man}}. @tab Find dimension name and length. @item @ref{NF_INQ_ATT,,, netcdf-f77, @value{f77-man}}. @tab Find attribute name, type, and length. @item @ref{NF_INQ_FORMAT,,, netcdf-f77, @value{f77-man}}. @tab Find file format: classic or 64-bit offset @item @ref{NF_INQ_LIBVERS,,, netcdf-f77, @value{f77-man}}. @tab Find the netCDF version. (Currently @value{VERSION}). @end multitable @node Inquiry in F90, Inquiry in C++, Inquiry in F77, Inquiry Functions @subsection Inquiry in Fortran 90 First use NF90_INQ, which will tell you how many variables and global attributes there are in the file. Then start with varid 1, and proceed to varid nvars, calling NF90_INQ_VAR. For a typical sequence of calls to these functions, see @xref{Reading Unknown, Reading a netCDF Dataset with Unknown Names, Reading a netCDF Dataset with Unknown Names, netcdf-f90, @value{f90-man}}. @multitable @columnfractions .27 .27 .45 @item @ref{NF90_INQ,,, netcdf-f90, @value{f90-man}}. @tab Find number of dimensions, variables, and global attributes, and the unlimited dimid. @item @ref{NF90_INQ_DIM,,, netcdf-f90, @value{f90-man}}. @tab Find dimension name and length. @item @ref{NF90_INQ_VARID,,, netcdf-f90, @value{f90-man}}. @tab Find variable ID from its name. @item @ref{NF90_INQ_VAR,,, netcdf-f90, @value{f90-man}}. @tab Find variable name, type, num dimensions, dim IDs, and num attributes. @item @ref{NF90_INQ_DIMID,,, netcdf-f90, @value{f90-man}}. @tab Find dimension ID from its name. @item @ref{NF90_INQ_DIM,,, netcdf-f90, @value{f90-man}}. @tab Find dimension name and length. @item @ref{NF90_INQ_ATT,,, netcdf-f90, @value{f90-man}}. @tab Find attribute name, type, and length. @item @ref{NF90_INQ_FORMAT,,, netcdf-f90, @value{f90-man}}. @tab Find file format: classic or 64-bit offset @item @ref{NF90_INQ_LIBVERS,,, netcdf-f90, @value{f90-man}}. @tab Find the netCDF version. (Currently @value{VERSION}). @end multitable @node Inquiry in C++, , Inquiry in F90, Inquiry Functions @subsection Inquiry Functions in the C++ API @multitable @columnfractions .17 .17 .25 .41 @item @ref{Class NcFile,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF files @item @ref{Class NcDim,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF dimensions @item @ref{Class NcVar,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF variables @item @ref{Class NcAtt,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF attributes @end multitable @node Subsets, , Inquiry Functions, Useful Functions @section Reading and Writing Subsets of Data Usually users are interested in reading or writing subsets of variables in a netCDF data file. The netCDF APIs provide a variety of functions for this purpose. In the simplest case, you will use the same type for both file and in-memory storage, but in some cases you may wish to use different types. For example, you might have a netCDF file that contains integer data, and you wish to read it into floating-point storage, converting the data as it is read. The same sort of type conversion can be done when writing the data. To convert to a type while reading data, use the appropriate nc_get_vara_ or NF_GET_VARA_ function. For example, the C function nc_get_vara_float(), and the Fortran function NF_GET_VARA_REAL will read netCDF data of any numeric type into a floating-point array, automatically converting each element to the desired type. To convert from a type while writing data, use the appropriate nc_put_vara_ or NF_PUT_VARA_ function. For example, the C function nc_put_vara_float(), and the Fortran function NC_PUT_VARA_REAL will write floating-point data into netCDF arrays, automatically converting each element of the array to the type of the netCDF variable. The in the function name refers to the type of the in-memory data, in both cases. They type of the file data is determined when the netCDF variable is defined. @menu * Subsetting in C:: * Subsetting in F77:: * Subsetting in F90:: * Subsetting in C++:: @end menu @node Subsetting in C, Subsetting in F77, Subsets, Subsets @subsection Reading and Writing Subsets of Data in C @findex nc_get_var1 @findex nc_get_vars @findex nc_get_varm @findex nc_put_var1 @findex nc_put_vars @findex nc_put_varm The type of the data may be automatically converted on read or write. For more information about type conversion see @ref{Type Conversion,,, netcdf-c, @value{c-man}}. @multitable @columnfractions .50 .25 .25 @item Read the entire variable at once @tab @ref{nc_get_var_ type,,, netcdf-c, @value{c-man}} @item Write the entire variable at once @tab @ref{nc_put_var_ type,,, netcdf-c, @value{c-man}} @item Read just one value @tab @ref{nc_get_var1_ type,,, netcdf-c, @value{c-man}} @item Write just one value @tab @ref{nc_put_var1_ type,,, netcdf-c, @value{c-man}} @item Read an array subset @tab @ref{nc_get_vara_ type,,, netcdf-c, @value{c-man}} @item Write an array subset @tab @ref{nc_put_vara_ type,,, netcdf-c, @value{c-man}} @item Read an array with strides @tab @ref{nc_get_vars_ type,,, netcdf-c, @value{c-man}} @item Write an array with strides @tab @ref{nc_put_vars_ type,,, netcdf-c, @value{c-man}} @c @item Read an array with strides and mapping @c @tab @ref{nc_get_varm_ type,,, netcdf-c, @value{c-man}} @c @item Write an array with strides and mapping @c @tab @ref{nc_put_varm_ type,,, netcdf-c, @value{c-man}} @end multitable @node Subsetting in F77, Subsetting in F90, Subsetting in C, Subsets @subsection Reading and Writing Subsets of Data in Fortran 77 @findex NF_GET_VAR1 @findex NF_GET_VARS @findex NF_GET_VARM @findex NF_PUT_VAR1 @findex NF_PUT_VARS @findex NF_PUT_VARM The type of the data may be automatically converted on read or write. For more information about type conversion see @ref{Type Conversion,,, netcdf-f77, @value{f77-man}}. @multitable @columnfractions .50 .25 .25 @item Read the entire variable at once @tab @ref{NF_GET_VAR_ type,,, netcdf-f77, @value{f77-man}} @item Write the entire variable at once @tab @ref{NF_PUT_VAR_ type,,, netcdf-f77, @value{f77-man}} @item Read just one value @tab @ref{NF_GET_VAR1_ type,,, netcdf-f77, @value{f77-man}} @item Write just one value @tab @ref{NF_PUT_VAR1_ type,,, netcdf-f77, @value{f77-man}} @item Read an array subset @tab @ref{NF_GET_VARA_ type,,, netcdf-f77, @value{f77-man}} @item Write an array subset @tab @ref{NF_PUT_VARA_ type,,, netcdf-f77, @value{f77-man}} @item Read an array with strides @tab @ref{NF_GET_VARS_ type,,, netcdf-f77, @value{f77-man}} @item Write an array with strides @tab @ref{NF_PUT_VARS_ type,,, netcdf-f77, @value{f77-man}} @c @item Read an array with strides and mapping @c @tab @ref{NF_GET_VARM_ type,,, netcdf-f77, @value{f77-man}} @c @item Write an array with strides and mapping @c @tab @ref{NF_PUT_VARM_ type,,, netcdf-f77, @value{f77-man}} @end multitable @node Subsetting in F90, Subsetting in C++, Subsetting in F77, Subsets @subsection Reading and Writing Subsets of Data in Fortran 90 @findex NF90_GET_VAR1 @findex NF90_GET_VARS @findex NF90_GET_VARM @findex NF90_PUT_VAR1 @findex NF90_PUT_VARS @findex NF90_PUT_VARM The type of the data may be automatically converted on read or write. For more information about type conversion see @ref{Type Conversion,,, netcdf-f90, @value{f90-man}}. @multitable @columnfractions .50 .25 .25 @item Read the entire variable at once @tab @ref{NF90_GET_VAR_ type,,, netcdf-f90, @value{f90-man}} @item Write the entire variable at once @tab @ref{NF90_PUT_VAR_ type,,, netcdf-f90, @value{f90-man}} @item Read just one value @tab @ref{NF90_GET_VAR1_ type,,, netcdf-f90, @value{f90-man}} @item Write just one value @tab @ref{NF90_PUT_VAR1_ type,,, netcdf-f90, @value{f90-man}} @item Read an array subset @tab @ref{NF90_GET_VARA_ type,,, netcdf-f90, @value{f90-man}} @item Write an array subset @tab @ref{NF90_PUT_VARA_ type,,, netcdf-f90, @value{f90-man}} @item Read an array with strides @tab @ref{NF90_GET_VARS_ type,,, netcdf-f90, @value{f90-man}} @item Write an array with strides @tab @ref{NF90_PUT_VARS_ type,,, netcdf-f90, @value{f90-man}} @c @item Read an array with strides and mapping @c @tab @ref{NF90_GET_VARM_ type,,, netcdf-f90, @value{f90-man}} @c @item Write an array with strides and mapping @c @tab @ref{NF90_PUT_VARM_ type,,, netcdf-f90, @value{f90-man}} @end multitable @node Subsetting in C++, , Subsetting in F90, Subsets @subsection Reading and Writing Subsets of Data in C++ To read a record of data at a time, use the set_cur method of the NcVar class to set the number of the record of interest, and then use the get method to read the record. @multitable @columnfractions .50 .25 .25 @item @ref{Class NcVar,,, netcdf-cxx, @value{cxx-man}} @tab a C++ class to manipulate netCDF variables, use the set_cur and get methods to read records from a file. @end multitable @node API-Extensions, NetCDF-4 Examples, Useful Functions, Top @chapter API Extensions Introduced with NetCDF-4 NetCDF-4 includes many advanced features. These features are only available when working with files created in the netCDF format. (That is, HDF5 files, created by netCDF, or simple-model HDF5 files). @menu * Interoperability:: Reading and writing HDF5 files. * Multiple-Unlimited-Dimensions:: Use more than one unlimited dimension. * Groups:: Organizing data hierarchically. * Compound-Types:: Creating data type like C structs. * Opaque-Types:: Creating a data type of known size. * VLEN-Type:: Variable length arrays. * Strings:: Storing strings of data. * New-inq-Functions:: Functions to help explore a file. * Parallel:: How to get parallel I/O. * Future:: What's coming next! @end menu @node Interoperability, Multiple-Unlimited-Dimensions, API-Extensions, API-Extensions @section Interoperability with HDF5 NetCDF-4 allows some interoperability with HDF5. @subsection Reading and Editing NetCDF-4 Files with HDF5 The HDF5 Files produced by netCDF-4 are perfectly respectable HDF5 files, and can be read by any HDF5 application. NetCDF-4 relies on several new features of HDF5, including dimension scales. The HDF5 dimension scales feature adds a bunch of attributes to the HDF5 file to keep track of the dimension information. It is not just wrong, but wrong-headed, to modify these attributes except with the HDF5 dimension scale API. If you do so, then you will deserve what you get, which will be a mess. Additionally, netCDF stores some extra information for dimensions without dimension scale information. (That is, a dimension without an associated coordinate variable). So HDF5 users should not write data to a netCDF-4 file which extends any unlimited dimension. Also there are some types allowed in HDF5, but not allowed in netCDF-4 (for example the time type). Using any such type in a netCDF-4 file will cause the file to become unreadable to netCDF-4. So don't do it. NetCDF-4 ignores all HDF5 references. Can't make head nor tail of them. Also netCDF-4 assumes a strictly hierarchical group structure. No looping, you weirdo! Attributes can be added (they must be one of the netCDF-4 types), modified, or even deleted, in HDF5. @subsection Reading and Editing HDF5 Files with NetCDF-4 Assuming a HDF5 file is written in accordance with the netCDF-4 rules (i.e. no strange types, no looping groups), and assuming that *every* dataset has a dimension scale attached to each dimension, the netCDF-4 API can be used to read and edit the file. In HDF5 (version 1.8.0 and later), dimension scales are (generally) 1D datasets, that hold dimension data. A multi-dimensional dataset can then attach a dimension scale to any or all of its dimensions. For example, a user might have 1D dimension scales for lat and lon, and a 2D dataset which has lat attached to the first dimension, and lon to the second. Dimension scales are vital to netCDF-4, which uses shared dimensions. If you want to read a HDF5 file with netCDF-4, it must use dimension scales, and one dimension scale must be attached to each dimension of every dataset in the file. @node Multiple-Unlimited-Dimensions, Groups, Interoperability, API-Extensions @section Multiple Unlimited Dimensions With classic and 64-bit offset netCDF files, each variable may use at most one unlimited dimension. With netCDF-4 format files, this restriction is lifted. Simply define as many unlimited dimensions as you wish, and use them in a variable. When data are written to that variable, the dimensions will be expanded as needed. @node Groups, Compound-Types, Multiple-Unlimited-Dimensions, API-Extensions @section Groups NetCDF-4 files can store attributes, variables, and dimensions in hierarchical groups. This allows the user to create a structure much like a Unix file system. In netCDF, each group gets an ncid. Opening or creating a file returns the ncid for the root group (which is named ``/''). Groups can be added with the nc_def_grp function. Get the number of groups, and their ncids, with the nc_inq_grps function. Dimensions are scoped such that they are visible to all child groups. For example, you can define a dimension in the root group, and use its dimension id when defining a variable in a sub-group. Attributes defined as NC_GLOBAL apply to the group, not the entire file. The degenerate case, in which only the root group is used, corresponds exactly with the classic data mode, before groups were introduced. @node Compound-Types, Opaque-Types, Groups, API-Extensions @section Compound Types In netCDF-4 files it's possible to create a data type which corresponds to a C struct. These are known as ``compound'' types (following HDF5 nomenclature). That is, a netCDF compound type is a data structure which contains an arbitrary collection of other data types, including other compound types. To define a new compound type, use nc_def_compound. Then call nc_insert_compound for each type within the compound type. Read and write arrays of compound data with the nc_get_vara and nc_put_vara functions. These functions were actually part of the netCDF-2 API, brought out of semi-retirement to handle user-defined types in netCDF-4. @node Opaque-Types, VLEN-Type, Compound-Types, API-Extensions @section Opaque Types Store blobs of bits in opaque types. Create an opaque type with nc_def_opaque. Read and write them with nc_get_vara/nc_put_vara. @node VLEN-Type, Strings, Opaque-Types, API-Extensions @section Variable Length Arrays (VLEN) Create a VLEN type to store variable length arrays of a known base type. Use nc_def_vlen to define a VLEN type, read and write them with nc_get_vara/nc_put_vara. @node Strings, New-inq-Functions, VLEN-Type, API-Extensions @section Strings Use the NC_STRING type to store arrays of strings. Read and write them with nc_get_vara/nc_put_vara. @node New-inq-Functions, Parallel, Strings, API-Extensions @section New Inquiry Functions There are many new inquiry functions to allow a program to navigate a completely unknown netCDF file. To find the number To find all the dimensions visible from a group, use nc_inq_dimids. @node Parallel, Future, New-inq-Functions, API-Extensions @section Parallel I/O with NetCDF Parallel I/O allows many processes to read/write netCDF data at the same time. Used properly, it allows users to overcome I/O bottlenecks in high performance computing environments. @subsection Parallel I/O Choices for NetCDF Users Parallel read-only access can be achieved netCDF files using the netCDF C/Fortran library. Each process can run a copy of the netCDF library and open and read any subsets of the data in the file. This sort of ``fseek parallelism'' will break down dramatically for any kind of writing. There are two methods available to users for read/write parallel I/O netCDF-4 or the parallel netCDF package from Argonne/Northwestern. Unfortunately the two methods involve different APIs, and different binary formats. For parallel read/write access to classic and 64-bit offset data users must use the PnetCDF library from Argonne/Northwestern University. This is not a Unidata software package, but was developed using the Unidata netCDF C library as a starting point. For more information see the parallel netcdf web site: @value{pnetcdf-url}. For parallel read/write access to netCDF-4/HDF5 files users must use the netCDF-4 API. The Argonne/Northwestern parallel netcdf package cannot read netCDF-4/HDF5 files. @subsection Parallel I/O with NetCDF-4 NetCDF-4 provides access to HDF5 parallel I/O features for netCDF-4/HDF5 files. NetCDF classic and 64-bit offset format may not be opened or created for use with parallel I/O. (They may be opened and created, but parallel I/O is not available.) A few functions have been added to the netCDF C API to handle parallel I/O. These functions are also available in the Fortran 90 and Fortran 77 APIs. @subsubsection Building NetCDF-4 for Parallel I/O You must build netCDF-4 properly to take advantage of parallel features. For parallel I/O HDF5 must be built with --enable-parallel. Typically the CC environment variable is set to mpicc. You must build HDF5 and netCDF-4 with the same compiler and compiler options. The netCDF configure script will detect the parallel capability of HDF5 and build the netCDF-4 parallel I/O features automatically. No configure options to the netcdf configure are required. If the Fortran APIs are desired set environmental variable FC to mpif90 (or some local variant.) @subsubsection Opening/Creating Files for Parallel I/O The nc_open_par and nc_create_par functions are used to create/open a netCDF file with the C API. (Or use nf_open_par/nf_create_par from Fortran 77). For Fortran 90 users the nf90_open and nf90_create calls have been modified to permit parallel I/O files to be opened/created using optional parameters comm and info. The parallel access associated with these functions is not a characteristic of the data file, but the way it was opened. @subsubsection Collective/Independent Access Parallel file access is either collective (all processors must participate) or independent (any processor may access the data without waiting for others). All netCDF metadata writing operations are collective. That is, all creation of groups, types, variables, dimensions, or attributes. Data reads and writes (ex. calls to nc_put_vara_int and nc_get_vara_int) may be independent (the default) or collective. To make writes to a variable collective, call the nc_var_par_access function (or nf_var_par_access for Fortran 77 users, or nf90_var_par_access for Fortran 90 users). The example program below demonstrates simple parallel writing and reading of a netCDF file. @menu * simple_xy_par in C:: @end menu @node simple_xy_par in C, , Parallel, Parallel @subsection simple_xy_par_wr.c and simple_xy_par_rd.c For this release, only a Fortran 90 language version of this example is provided. Other APIs will be demonstrated in examples in future releases. In the simple_xy_par_wr example program an num_procs x num_procs array is written to the disk, where num_proc is the number of processors on which this program is run. Each processor writes one row of length num_proc. In the simple_xy_par_rd program the file is read in, and each processor expects to read in a row with its own MPI rank stored. (The read program must be run on no more processors than were used to create the file.) @menu * simple_xy_par_wr.f90:: * simple_xy_par_rd.f90:: @end menu @node simple_xy_par_wr.f90, simple_xy_par_rd.f90, simple_xy_par in C, simple_xy_par in C @subsubsection simple_xy_par_wr.f90 @example @include simple_xy_par_wr.f90 @end example @node simple_xy_par_rd.f90, , simple_xy_par_wr.f90, simple_xy_par in C @subsubsection simple_xy_par_rd.f90 @example @include simple_xy_par_rd.f90 @end example @node Future, , Parallel, API-Extensions @section The Future of NetCDF @cindex netCDF-4 NetCDF continues under active development at Unidata (see @uref{@value{unidata-url}}). The next few releases of netCDF will include: @enumerate @item A new C++ API which has better error handling and handles netCDF-4 advanced features, such as groups and compound types. @item Remote access to files stored on a DAP server. @item Bundled packaging with udunits and other useful tools. @item More documentation, more examples, more tests, and more fun! @end enumerate @node NetCDF-4 Examples, Combined Index, API-Extensions, Top @chapter NetCDF-4 Examples Any existing netCDF applications can be converted to generate netCDF-4/HDF5 files. Simply change the file creation call to include the correct mode flag. For example, in one of the C examples which write a data file, change the nc_create call so that NC_NETCDF4 is one of the flags set on the create. The corresponding read example will work without modification; netCDF will notice that the file is a NetCDF-4/HDF5 file, and will read it automatically, just as if it were a netCDF classic format file. In the example in this section we show some of the advanced features of netCDF-4. More examples will be added in future releases. @menu * simple_nc4:: * simple_xy_nc4:: @end menu @node simple_nc4, simple_xy_nc4, NetCDF-4 Examples, NetCDF-4 Examples @section The simple_nc4 Example This example, like the simple_xy netCDF-3 example above, is an overly simplified example which demonstrates how to use groups in a netCDF-4 file. This example is only available in C for this version of netCDF-4. The example creates and then reads the file ``simple_nc4.nc.'' The simple_xy.nc data file contains two dimensions, ``x'' and ``y'', two groups, ``grp1'' and ``grp2'', and two data variables, one in each group, both named: ``data.'' One data variable is an unsigned 64-bit integer, the other a user-defined compound type. The example program simple_nc4_wr.c creates the example data file simple_nc4.nc. The example program simple_nc4_rd.c reads the data file. @menu * simple_nc4 in C:: @end menu @node simple_nc4 in C, , simple_nc4, simple_nc4 @subsection simple_nc4_wr.c and simple_nc4_rd.c For this release, only a C language version of this example is provided. Other APIs will be demonstrated in examples in future releases. @menu * simple_nc4_wr.c:: * simple_nc4_rd.c:: @end menu @node simple_nc4_wr.c, simple_nc4_rd.c, simple_nc4 in C, simple_nc4 in C @subsubsection simple_nc4_wr.c @example @include simple_nc4_wr.c @end example @node simple_nc4_rd.c, , simple_nc4_wr.c, simple_nc4 in C @subsubsection simple_nc4_rd.c @example @include simple_nc4_rd.c @end example @node simple_xy_nc4, , simple_nc4, NetCDF-4 Examples @section The simple_xy_nc4 Example This example, like the simple_xy netCDF-3 example above, is an overly simplified example. It is based on the simple_xy example, but used data chunking, compression, and the fletcher32 filter. (These are all HDF5 features. For more information see @value{hdf5-url}). This example is not yet available in C++. We hope to have the C++ example in a future release of netCDF. The example creates and then reads the file ``simple_xy_nc4.nc.'' The example program simple_xy_nc4_wr.c creates the example data file simple_xy_nc4.nc. The example program simple_xy_nc4_rd.c reads the data file. @menu * simple_xy_nc4 in C:: * simple_xy_nc4 in F77:: * simple_xy_nc4 in F90:: @end menu @node simple_xy_nc4 in C, simple_xy_nc4 in F77, simple_xy_nc4, simple_xy_nc4 @subsection simple_xy_nc4_wr.c and simple_xy_nc4_rd.c This is just like the simple_xy example, but with chunking and variable compression. @menu * simple_xy_nc4_wr.c:: * simple_xy_nc4_rd.c:: @end menu @node simple_xy_nc4_wr.c, simple_xy_nc4_rd.c, simple_xy_nc4 in C, simple_xy_nc4 in C @subsubsection simple_xy_nc4_wr.c @example @include simple_xy_nc4_wr.c @end example @node simple_xy_nc4_rd.c, , simple_xy_nc4_wr.c, simple_xy_nc4 in C @subsubsection simple_xy_nc4_rd.c @example @include simple_xy_nc4_rd.c @end example @node simple_xy_nc4 in F77, simple_xy_nc4 in F90, simple_xy_nc4 in C, simple_xy_nc4 @subsection simple_xy_nc4_wr.f and simple_xy_nc4_rd.f This is just like the simple_xy example, but with chunking and variable compression. @menu * simple_xy_nc4_wr.f:: * simple_xy_nc4_rd.f:: @end menu @node simple_xy_nc4_wr.f, simple_xy_nc4_rd.f, simple_xy_nc4 in F77, simple_xy_nc4 in F77 @subsubsection simple_xy_nc4_wr.f @example @include simple_xy_nc4_wr.f @end example @node simple_xy_nc4_rd.f, , simple_xy_nc4_wr.f, simple_xy_nc4 in F77 @subsubsection simple_xy_nc4_rd.f @example @include simple_xy_nc4_rd.f @end example @node simple_xy_nc4 in F90, , simple_xy_nc4 in F77, simple_xy_nc4 @subsection simple_xy_nc4_wr.f90 and simple_xy_nc4_rd.f90 This is just like the simple_xy example, but with chunking and variable compression. @menu * simple_xy_nc4_wr.f90:: * simple_xy_nc4_rd.f90:: @end menu @node simple_xy_nc4_wr.f90, simple_xy_nc4_rd.f90, simple_xy_nc4 in F90, simple_xy_nc4 in F90 @subsubsection simple_xy_nc4_wr.f90 @example @include simple_xy_nc4_wr.f90 @end example @node simple_xy_nc4_rd.f90, , simple_xy_nc4_wr.f90, simple_xy_nc4 in F90 @subsubsection simple_xy_nc4_rd.f90 @example @include simple_xy_nc4_rd.f90 @end example @node Combined Index, , NetCDF-4 Examples, Top @unnumbered Index @printindex cp @bye End: