\input texinfo   @c -*-texinfo-*-

@c %**start of header
@setfilename netcdf.info
@settitle NetCDF User's Guide
@setchapternewpage odd
@c %**end of header

@c Combine the variable and function indices.
@synindex vr fn

@iftex
@finalout
@end iftex

@ifinfo
This file documents the Unidata netCDF interface, library, and
utilities.  

Copyright (C) 1993 University Corporation for Atmospheric Research.
Permission is granted to make and distribute verbatim copies of
this file provided the copyright notice and this permission notice
are preserved on all copies.
@end ifinfo

@titlepage
@title NetCDF User's Guide
@subtitle An Interface for Data Access
@subtitle Version 2.3, April 1993
@author Russ Rew, Glenn Davis, and Steve Emmerson
@author Unidata Program Center
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1993 University Corporation for Atmospheric Research

Permission is granted to make and distribute verbatim copies of this 
manual provided that the copyright notice and these paragraphs are 
preserved on all copies.  The software and any accompanying written 
materials are provided ``as is'' without warranty of any kind.  UCAR 
expressly disclaims all warranties of any kind, either expressed or 
implied, including but not limited to the implied warranties of 
merchantability and fitness for a particular purpose.  

The Unidata Program Center is managed by the University 
Corporation for Atmospheric Research and sponsored by the National 
Science Foundation.  Any opinions, findings, conclusions, or 
recommendations expressed in this publication are those of the 
author(s) and do not necessarily reflect the views of the National 
Science Foundation.

Mention of any commercial company or product in this document 
does not constitute an endorsement by the Unidata Program Center.  
Unidata does not authorize any use of information from this 
publication for advertising or publicity purposes.
@end titlepage

@node     Top, Foreword, (dir), (dir)
@ifinfo
@top NetCDF User's Guide

The Unidata netCDF library provides an application- and
machine-independent interface to self-describing, multidimensional
scientific data.  It supports an abstract view of scientific data as a
collection of named variables and their attributes, and provides
high-level access to data that is faithful to the abstraction.  This
on-line document describes the netCDF abstraction, applications programming
interfaces, and utilities.  It includes the following chapters:

@menu
* Foreword::                    What is Unidata?
* Summary::                     Brief purpose and description of netCDF.
* Introduction::                Overview and background of netCDF.
* Components::                  The components of a netCDF file.
* Data::                        The primitive netCDF data types and forms of data
                    access.
* Usage::                       How to use the netCDF library.
* File Operations::             The interface for handling netCDF files.
* Dimensions::                  The interface for handling netCDF dimensions.
* Variables::                   The interface for handling netCDF variables.
* Attributes::                  The interface for handling netCDF attributes.
* File Structure::              The netCDF format and performance considerations.
* Utilities::                   Higher-level netCDF operations implemented as separate
                    programs.
* FAQ::                         Answers to some frequently asked questions about netCDF.
* C Interface::                 A summary of the C interface.
* Fortran Interface::           A summary of the Fortran interface.
* Units::                       The recommended syntax for representing units.
* Name Index::                  Index of cross-references for names of netCDF functions
                    and variables.
* General Index::               Index of concepts.

 --- The Detailed Node Listing ---

The NetCDF Interface

* Not a DBMS::   NetCDF is not a database management system.
* Performance::  Some performance considerations.
* Archiving::    Is netCDF a good archive format?
* History::      Background and Evolution of the netCDF Interface.
* Recent Changes::  Changes since the last release
* Future Plans:: Future plans for netCDF.
* References::   References.

Components of a NetCDF File

* What Are Dimensions?::  The components of and operations on netCDF
                          dimensions.

* What Are Variables?::  The components of and operations on netCDF
                          variables.

* What Are Attributes?::  The components of and operations on netCDF
                          attributes.

Dimensions

* Specifying Variable Shapes::  Using Dimensions to Specify the Shapes
                                of Variables

* Relating Variables::          Using Dimensions to Relate Variables

* Defining Coordinates::        Using Dimensions to Define Coordinates

Attributes

* Attribute Conventions::    Conventions for Commonly Used Attributes

* Attributes and Variables:: Differences Between Attributes and Variables

Data

* Data Types::      The six basic netCDF data types.

* Data Access::     Direct access, hyperslab access, and record access.

* Data Structures:: Representing other structures with netCDF arrays.

Use of the NetCDF Library

* Creating a netCDF File::     How to create a new netCDF file.

* Reading with Known Names::   How to read a netCDF file with known names.

* Reading with Unknown Names:: How to read a generic netCDF.

* Adding Components::          How to add new dimensions, variables, and
                               attributes.

* Error Handling::             How to handle errors.

NetCDF Operations

* Interface Descriptions::   Conventions for netCDF library interface
                             descriptions.
* nccreate and NCCRE::       Create a netCDF file.
* ncopen and NCOPN::         Open a netCDF file for access.
* ncredef and NCREDF::       Put open netCDF file into define mode.
* ncendef and NCENDF::       Leave Define Mode.
* ncclose and NCCLOS::       Close an Open netCDF File.
* ncinquire and NCINQ::      Inquire about an Open netCDF File.
* ncsync and NCSNC::         Synchronize an Open netCDF File to Disk.
* ncabort and NCABOR::       Back Out of Recent Definitions.
* ncsetfill and NCSFIL::     Set fill mode for optimized writes.

Dimensions

* ncdimdef and NCDDEF::    Create a Dimension
* ncdimid and NCDID::      Get a Dimension ID from Its Name
* ncdiminq and NCDINQ::    Inquire about a Dimension
* ncdimrename and NCDREN:: Rename a Dimension

Variables

* ncvardef and NCVDEF::     Create a Variable
* ncvarid and NCVID::       Get a Variable ID from Its Name
* ncvarinq and NCVINQ::     Get Information about a Variable from Its ID
* ncvarput1 and NCVPT1::    Write a Single Data Value
* ncvarput and NCVPT::      Write a Hyperslab of Values
* ncvarputg NCVPTG and NCVPGC::    Write a Generalized Hyperslab of Values
* ncrecput::                Write a Record of Values
* ncvarget1 and NCVGT1::    Read a Single Data Value
* ncvarget and NCVGT(C)::   Read a Hyperslab of Values
* ncvargetg NCVGTG and NCVGGC::    Read a Generalized Hyperslab of Values
* ncrecget::                Read a Record of Values
* Character String I/O::    Reading and Writing Character String Values
* Missing Values::          Conventions for Missing Values
* ncvarrename and NCVREN::  Rename a Variable
* nctypelen and NCTLEN::    Get Number of Bytes for a Data Type
* ncrecinq::                Get Information about Record Variables

Attributes

* ncattput and NCAPT::      Create an Attribute
* ncattinq and NCAINQ::      Get Information about an Attribute
* ncattget and NCAGT(C)::      Get Attribute's Values
* ncattcopy and NCACPY::      Copy Attribute from One netCDF to Another
* ncattname and NCANAM::      Get Name of Attribute from Its Number
* ncattrename and NCAREN::      Rename an Attribute
* ncattdel and NCADEL::      Delete an Attribute

NetCDF File Structure and Performance

* File parts::  Parts of a netCDF File
* XDR layer::   The XDR Layer

Higher-Level netCDF Operations

* CDL Syntax::    The syntax of CDL, a tiny language for representing
                  netCDF files or their structure in ASCII.
* CDL Data Types::The data types of CDL.
* CDL Constants:: The CDL notation for data constants.
* ncgen::         Check CDL syntax or generate netCDF file (or C or Fortran)
                  from netCDF file.
* ncdump::        Generate CDL file (or a portion of a CDL file) from a netCDF
                  file.

Answers to Some Frequently Asked Questions

* What is netCDF?::       
* How to get it::         Availability of the netCDF software
* Platforms::             What platforms it runs on
* netCDF and CDF::        Connection with NASA's Common Data Format
* netCDF and HDF::        Connection with NCSA's Hierarchical Data Format
* pub/netcdf::            Some files with volatile netCDF information
* XDR error messages::    Why occasional error messages from XDR layer
* representing data::     Ways to represent data in netCDF
* data compression::      Data compression in netCDF
* Other utilities::             What netCDF utilities exist
* mailing list::          The netCDF mailing lists
* bug reports::           Where to send bug reports
* Popularity::            Is netCDF widely used?
* WAIS/gopher access::    WIAS or gopher access to netCDF information
@end menu

@end ifinfo

@node Foreword, Summary, Top, Top
@unnumbered Foreword
Unidata is a National Science Foundation-sponsored program empowering 
U.S. universities, through innovative applications of computers and 
networks, to make the best use of atmospheric and related data for 
enhancing education and research.  The Unidata Program Center currently 
offers universities several (supported) software packages for analyzing 
and displaying such data, some developed by Unidata and some by other 
organizations, including NASA, the University of Wisconsin, Purdue 
University, and MacDonald Dettwiler.  Underlying these is a Unidata-
developed system for acquiring and managing data in real time, making 
practical the Unidata principle that each university should acquire and 
manage its own data holdings as local requirements dictate.  (It is 
significant that the Unidata program has no data center -- the 
management of data is a ``distributed'' function.)

The Network Common Data Form (netCDF) software described in this guide 
was originally intended to provide a common data access method for the 
various Unidata applications.  These deal with a variety of data types 
that encompass single-point observations, time series, regularly-spaced 
grids, and satellite or radar images.  

The netCDF software functions as an I/O library, callable from C or 
FORTRAN, which stores and retrieves scientific data structures in self-
describing, machine-independent files.  Each netCDF file can contain an 
unlimited number of multi-dimensional, named variables (with differing 
types that include integers, reals, characters, bytes, etc.), and each 
variable may be accompanied by ancillary data, such as units of measure 
or descriptive text.  The interface includes a method for appending data 
to existing netCDF files in prescribed ways, functionality that is not 
unlike a (fixed length) record structure.  However, the netCDF library 
also allows direct-access storage and retrieval of data by variable name 
and index and therefore is useful only for disk-resident (or memory-
resident) files.

NetCDF access has been implemented in about half of Unidata's software, 
so far, and it is planned that such commonality will extend across all 
Unidata applications in order to:

@itemize @bullet
@item
Facilitate the use of common data files by distinct applications.

@item
Permit data files to be transported between or shared by dissimilar 
computers transparently, i.e., without translation.

@item
Reduce the programming effort usually spent interpreting formats in a 
way that is equally effective for FORTRAN and C programmers.

@item
Reduce errors arising from misinterpreting data and ancillary data.

@item
Facilitate using output from one application as input to another.

@item
Establish an interface standard which simplifies the inclusion of new 
software into the Unidata system.
@end itemize

A measure of success has been achieved.  The netCDF is now in use on 
computing platforms that range from CRAYs to Personal Computers and 
include many (UNIX- and VMS-based) workstations.  It can be used to 
create a complex data set on one computer (say in FORTRAN) and retrieve 
that same (self-describing) data set on another computer (say in C) 
without intermediate translations -- netCDF files can be transferred 
across a network, or they can be accessed remotely using a suitable 
network file system.

Because we believe that the use of netCDF access in non-Unidata software 
will benefit Unidata's primary constituency -- such use may result in 
more options for analyzing and displaying Unidata information -- the 
netCDF library is distributed without licensing or other significant 
restrictions, and current versions can be obtained via anonymous FTP.  
Apparently the software has been well received by a wide range of 
institutions beyond the atmospheric science community, and a substantial 
number of public domain and commercial data analysis systems can now 
accept netCDF files as input.  

Several organizations have adopted the netCDF as a data access standard, 
and there is an effort underway at the National Center for Supercomputer 
Applications (NCSA, which is associated with the University of Illinois 
at Urbana-Champaign) to support the netCDF programming interfaces as a 
means to store and retrieve data in ``HDF files,'' i.e., in the format 
used by the popular NCSA tools.  We have encouraged and cooperated with 
these efforts.

Questions occasionally arise about the level of support provided for the 
netCDF software.  Unidata's formal position, stated in the copyright 
notice which accompanies the netCDF library, is that the software is 
provided ``as is'' ...  In practice, the software is updated from time 
to time, and Unidata intends to continue making improvements for the 
foreseeable future.  Because Unidata's mission is to serve atmospheric 
scientists at U.S. universities, problems reported by that community 
necessarily receive the greatest attention.

We hope the reader will find the software useful and will give us 
feedback on its application as well as suggestions for its improvement.


@noindent
David Fulker@*
Unidata Program Center Director
University Corporation for Atmospheric Research

@node Summary, Introduction, Foreword, Top
@unnumbered Summary
@cindex self-describing
@cindex network-transparent
The purpose of the Network Common Data Form (netCDF) interface is to
allow you to create, access, and share scientific data in a form that is
self-describing and network-transparent.  ``Self-describing'' means that a
file includes information defining the data it contains.
``Network-transparent'' means that a file is represented in a form that
can be accessed by computers with different ways of storing integers,
characters, and floating-point numbers.  Using the netCDF interface for
creating new scientific data sets can improve the accessibility of the
data.  Using the netCDF interface in new software for scientific data
access, management, analysis, and display can improve the reusability of
the software for other data sets and by other users.

@cindex FORTRAN interface
@cindex C++ interface
@cindex C interface
The netCDF software provides common C and FORTRAN interfaces for
applications and data.  The C interface library is available for many
common computing platforms, including various versions of UNIX, VMS,
MSDOS and OS/2 environments.  The FORTRAN interface, implemented in C,
is available for many of the platforms on which the C interface is
available.  The form in which the FORTRAN interface is implemented makes
it easy to generate and test a new FORTRAN interface for a new platform
by specifying the conventions for calling C from FORTRAN.  An
experimental C++ prototype interface is currently under evaluation.

The netCDF software is being made freely available to encourage the
sharing of both scientific data and the software that makes the data
useful.

@node Introduction, Components, Summary, Top
@chapter Introduction
@section The NetCDF Interface

@cindex netCDF
The Network Common Data Form, or netCDF, is an interface to a library of
data access programs for storing and retrieving scientific data.  NetCDF
is an abstraction that supports a view of data as a collection of
self-describing, network-transparent objects that can be accessed
through a simple interface.  Collections of named multidimensional
variables can be randomly accessed, without knowing details of how the
data are stored.  Auxiliary information about the data, such as what
units are used, can be stored with the data.  Generic utilities and
application programs can be written that access arbitrary netCDF files
and transform, combine, analyze, or display specified fields of the
data.  The development of such applications may lead to improved
accessibility of data and improved reusability of software for
scientific data management, analysis, and display.

@cindex availability of netCDF software
@cindex languages supported
@cindex operating systems supported
@cindex portability
@cindex abstract data type
@cindex future changes planned
The netCDF software implements an @dfn{abstract data type}, which means
that all operations to access and manipulate data in a netCDF file must use
only the set of functions provided by the interface.  The actual
representation of the data is hidden from applications that use the
interface, so that how the data are stored could be changed without
affecting such programs.  The physical representation of netCDF data is
designed to be independent of the computer on which the data were
written.  Future changes to the netCDF interface will be compatible with
the interface described here, so that neither existing netCDF files nor
programs accessing them will require modification.

The netCDF interface is supported for both C and FORTRAN, and for UNIX,
VMS, OS/2 and MSDOS operating systems.  The netCDF software that
implements this interface is freely available via FTP and free of
licensing restrictions to encourage its wide use.

@menu
* Not a DBMS::   NetCDF is not a database management system.
* Performance::  Some performance considerations.
* Archiving::    Is netCDF a good archive format?
* History::      Background and Evolution of the netCDF Interface.
* Recent Changes::  Changes since the last release
* Future Plans:: Future plans for netCDF.
* References::   References.
@end menu

@node Not a DBMS, Performance, Introduction, Introduction
@section NetCDF is Not a Database Management System

@cindex database management systems
Why not use an existing database management system (DBMS) for storing
scientific data?  We looked at available database software, both
commercial and research-oriented, and concluded that existing
packages are currently inadequate for the kinds of scientific data
access supported by the netCDF interface.

@cindex relational database systems
First, most existing DBMSs have poor support for multidimensional
objects as the basic unit of data access.  An alternative data model of
comparable power and elegance to the relational model for databases is
needed for scientific data.  If such a model existed, programs that
shared that model could be used in flexible combinations to support
effective systems for building applications and visualizing data.
Representing multidimensional arrays as relations makes some useful
kinds of data access awkward and provides little support for the
abstractions of multidimensional data and coordinate systems.

Related to this is a second problem with general-purpose database
systems: their poor performance on large scientific data sets.
Collections of satellite images, scientific model outputs, climate
observations covering decades, high-resolution atmospheric profile data,
and other large data sets are beyond the capabilities of most DBMSs to
organize and index for efficient retrieval.

Finally, general-purpose database systems provide, at significant cost
in terms of both resources and access performance, many facilities that
are not needed in the analysis, management, and display of scientific
data.  For example, elaborate update facilities, concurrency control,
audit trails, report writers, and mechanisms designed for
transaction-processing are unnecessary for most scientific applications.

@node Performance, Archiving, Not a DBMS, Introduction
@section What about Performance?

@cindex efficiency
@cindex performance
@cindex external data representation (XDR)
@cindex XDR
To achieve network-transparency, the netCDF is implemented on top of a
layer of software for external data representation (XDR).  XDR,
developed by Sun Microsystems, Inc., is a nonproprietary standard for
describing and encoding data.  It supports encoding arbitrary C
data structures into machine-independent sequences of bits.
@cindex IEEE floating-point
The encoding used for floating-point numbers is the Institute for
Electrical and Electronics Engineers (IEEE) standard for normalized
floating-point numbers.  XDR has been implemented on a wide variety of
computers, including Suns, VAXs, Apple Macintoshes, IBM RS 6000s, IBM
PS/2s, IBM mainframes, and CRAYs.  It assumes only that eight-bit bytes can
be encoded and decoded in a consistent way.

Translating data into and out of XDR form adds overhead to data
transfers, but for many applications the extra CPU cycles used to
convert data to and from a machine-independent representation are not
significant.  The amount of XDR overhead depends on many factors,
including the data type, the type of computer, the granularity of data
access, and how well the implementation has been tuned to the computer
on which it is run.  For a large set of applications, the overhead of
the XDR layer is a reasonable price to pay for portable,
network-transparent data access.

@cindex performance
@cindex efficiency
Often when an abstraction layer is added to hide the details of an
underlying implementation, some computations that can be expressed
simply in terms of the abstraction may be computationally expensive.
Furthermore, it may not be obvious which of several ways of expressing a
computation through the abstract interface will make efficient use of
computing resources, without understanding something about the
implementation.  It is certainly possible to use the netCDF interface to
access data in inefficient ways: for example, by requesting a slice of
variable data that requires a single value out of each record.
@xref{File Structure, , NetCDF File Structure and Performance}, for a
discussion of performance characteristics of the implementation and how
to apply knowledge of the underlying implementation to use the interface
effectively when performance is an important concern.

@node Archiving, History, Performance, Introduction
@section Is NetCDF a Good Archive Format?

@cindex archive formats
NetCDF can be used as an archive format for storing data, but it may
take more space than a special-purpose archive format that exploits
knowledge of particular characteristics of a set of data.
Compression of data is possible with netCDF (e.g., using arrays of
eight-bit bytes to encode low-resolution floating-point numbers instead
of arrays of 32-bit numbers), but netCDF was not designed to achieve
optimal compression of scientific data.

The advantages of a special-purpose archive format for small archives
should be compared to the benefits of machine-independence and the
ability to store ancillary data (data about the data) that the netCDF
interface provides.  For large archives, only two programs need to be
provided for each archive format, one to translate archived data into
netCDF form and the other to translate back to the archive format.
Tools provided for manipulating netCDF data will then be available
without sacrificing the advantages of the archive format and without
requiring the wholesale conversion of large existing archives.

@node History, Recent Changes, Archiving, Introduction
@section Background and Evolution of the NetCDF Interface

@cindex history of the netCDF
@cindex netCDF, development of
The development of the netCDF interface began with a modest goal related to
Unidata's needs: to provide a common interface between Unidata
applications and ingested real-time meteorological data.  Since Unidata
software was intended to run on multiple hardware platforms with access
from both C and FORTRAN, achieving Unidata's goals had the
potential for providing a package that was useful in a broader context.
By making the package widely available and collaborating with other
organizations with similar needs, we hoped to improve the current
situation in which scientific software is only rarely reused by others
in the same discipline and almost never reused between disciplines
(Fulker, 1988).

@cindex NASA CDF
@cindex NSSDC CDF
Important concepts employed in the netCDF software originated in a paper
(Treinish and Gough, 1987) that described data-access software developed
at the NASA Goddard National Space Science Data Center (NSSDC).  The
interface provided by this software was called the Common Data Format
(CDF).  The NASA CDF was originally developed as a platform-specific
FORTRAN library to support an abstraction for storing multidimensional
scientific data.

The NASA CDF package had been used for many different kinds
of data in an extensive collection of applications.  It
had the virtues of simplicity (only 13 subroutines), independence from
storage format, generality, ability to support logical user views of
data, and support for generic applications.

@cindex Unidata CDF Workshops
Unidata held a workshop on CDF in Boulder in August 1987.  We proposed
exploring the possibility of collaborating with NASA to extend the CDF
FORTRAN interface, to define a C interface, and to permit the access of
data aggregates with a single call, while maintaining compatibility with
the existing NASA interface.

@cindex New Mexico Tech. CDF
@cindex CANDIS
Independently, Dave Raymond at the New Mexico Institute of Mining and
Technology had developed a package of C software for UNIX that supported
self-describing scientific data along with a ``pipes and filters''
approach to processing, analyzing, and displaying scientific data.
This package also used the ``Common Data Format'' name,
later changed to C-Based Analysis and Display System (CANDIS).
Unidata learned of Raymond's work (Raymond, 1988), and
incorporated some of his ideas, such as the use of named dimensions and
variables with differing shapes in a single data object, into the
Unidata netCDF interface.

@cindex XDR
In early 1988, Glenn Davis of Unidata developed a prototype netCDF
package in C that was layered on a nonproprietary external data
representation standard (XDR) developed by Sun Microsystems.  This
prototype proved that a single-file, network-transparent implementation
of the CDF interface could be achieved at acceptable cost and that the
resulting programs could be implemented on both UNIX and VMS systems.
However, it also demonstrated that providing a small, portable, and NASA
CDF-compatible FORTRAN interface with the desired generality was not
practical.  (NASA's CDF and Unidata's netCDF have since evolved
separately, but recent CDF versions share many characteristics with
netCDF.)

@cindex SeaSpace CDF
In early 1988, Joe Fahle of SeaSpace, Inc. (a commercial software
development firm in San Diego, California), a participant in the 1987
Unidata CDF workshop, independently developed a CDF package in C that
extended the NASA CDF interface in several important ways (Fahle, 1989).
Like Raymond's package, the SeaSpace CDF software permitted variables
with unrelated shapes to be included in the same data object and
permitted a general ``hyperslab'' form of access to multidimensional
arrays.  Fahle's implementation was used at SeaSpace as the intermediate
form of storage for a variety of steps in their image-processing system.

@cindex Unidata CDF Workshops
After studying Fahle's interface, we concluded that it solved many of
the problems we had identified in trying to stretch the NASA interface
to our purposes.  In August 1988, we convened a small workshop to agree
on a Unidata netCDF interface, and to resolve remaining open issues.
Attending were Joe Fahle of SeaSpace, Michael Gough of Apple (an author
of the NASA CDF software), Angel Li of the University of Miami (who had
implemented our prototype netCDF software on VMS and was a potential
user), and Unidata systems development staff.  Consensus was reached at
the workshop after some further simplifications were discovered.  A
document incorporating the results of the workshop into a proposed
Unidata netCDF interface specification was distributed widely for
comments before Glenn Davis implemented the software it described.
Comparison with other data-access interfaces and recent experience in
using netCDF are discussed in (Rew and Davis, 1990a) and (Rew and Davis,
1990b).

In October 1991, we announced version 2.0 of the netCDF software
distribution.  Slight modifications to the C interface (declaring
dimension sizes to be @code{long} rather than @code{int}) improved the
usability of netCDF on inexpensive platforms such as MSDOS computers,
without requiring recompilation on other platforms.  This change to the
interface required no changes to the associated file format.

@node Recent Changes, Future Plans, History, Introduction
@section What's New in this Release?

This Guide documents the March 1993 release of netCDF 2.3, which
preserves the same file format but adds a few new functions to the C and
Fortran interfaces.

The suggested extension for netCDF files has been changed from
@code{.cdf} to @code{.nc}, in order to avoid a clash with the NASA CDF
file extension.  Although the old extension is still supported in a
backward compatible way, new netCDF files should use the new filename
extension, where practical.

Subsampling along specified dimensions (using `strides') is one of the
commonly-asked-for features supported by the new @code{ncvarputg()} and
@code{ncvargetg()} interfaces for generalized hyperslab access.  In
addition, these interfaces permit accessing data that is not contiguous
in memory.  In a generalized hyperslab, an index mapping vector is used
to define the mapping between points in the generalized hyperslab and
the memory locations of the corresponding values.  (@xref{ncvarputg
NCVPTG and NCVPGC}.)

There are also some new interfaces that can be used to write, read, and
inquire about records, where a record may contain multiple variables of
different types and shapes.  Where before you had to access a record's
worth of data using multiple calls, now you may instead use a single
call.  (@xref{ncrecput}.)

New optimizations for the library have resulted in significant speedups
for accessing cross-sections involving non-contiguous data.  Many bugs
have been fixed, portability has been improved, and the installation has
been greatly simplified for most systems.

The ncdump utility now supports several new command-line options
including the ability to specify for which variables data values will be
output, to provide brief annotations in the form of CDL comments to
identify data values for large multidimensional variables, or to provide
full annotations in the form of trailing CDL comments for every data
value.

@node Future Plans, References, Recent Changes, Introduction
@section Future Plans for NetCDF

@cindex Future Plans
We continue to use netCDF for Unidata system software and applications.
We have begun to use netCDF interfaces for earth-referenced
image-analysis software, as well as for the output of decoders for a
wide variety of meteorological and oceanographic data.

We have recently released a preliminary set of netCDF operators that we
hope will eventually be completed to provide an algebra of useful
operations on generic scientific data stored in netCDF files.  The
complete set of operators includes selectors to extract subsets of
variables or reduce the dimensionality of a netCDF file; combiners to
merge netCDF files, combine variables, or increase dimensionality;
graphics generators to read netCDF files and produce graphical output;
mathematical operators; and specialized data converters to convert
units, convert to or from standard archive forms, or to convert to a
canonical form for comparison.  By composing these fundamental
operators, users would have a wide variety of capabilities.

We have submitted a proposal for resources to extend the netCDF library
in an upward-compatible way to support netCDF servers on a network.
With netCDF servers, clients could access cross-sections of data
efficiently, as if they were stored in a local file.  A netCDF server
would also have the ability to support virtual netCDF objects that
provide different views of large or remote data sets.  Servers might
also be capable of providing a transparent netCDF interface to
non-netCDF archives.

Other desirable extensions that we would like to see added to netCDF
include an interface for record access by key or coordinate value,
transparent data packing by use of three new reserved attributes
(@code{_Nbits}, @code{_Scale}, and @code{_Offset}), support for pointers
to data cross-sections in other files (what Joe Fahle calls
``assemblies''), better string support, and a well-tested C++ interface.
Some of these extensions may be included in future releases.

@node References,  , Future Plans, Introduction
@unnumberedsec References

@enumerate

@item
Fahle, J., @emph{TeraScan Applications Programming Interface}, SeaSpace,
San Diego, California, 1989.
@item
Fulker, D. W., ``The netCDF:  Self-Describing, Portable Files---a Basis
for `Plug-Compatible' Software Modules Connectable by Networks,'' ICSU
Workshop on Geophysical Informatics, Moscow, USSR, August 1988.
@item
Fulker, D. W., ``Unidata Strawman for Storing Earth-Referencing Data,''
@emph{Seventh International Conference on Interactive Information
and Processing Systems for Meteorology, Oceanography, and Hydrology}, New
Orleans, La., American Meteorology Society, January 1991.
@item
Gough, M. L., @emph{NSSDC CDF Implementer's Guide (DEC VAX/VMS) Version
1.1}, National Space Science Data Center, 88-17, NASA/Goddard Space
Flight Center, 1988.
@item
Jenter, H. L. and R. P. Signell, ``NetCDF: A Freely-Available
Software-Solution to Data-Access Problems for Numerical Modelers,''
Proceedings of the American Society of Civil Engineers Conference on
Estuarine and Coastal Modeling, Tampa, Florida, 1992.
@item
Raymond, D. J., ``A C Language-Based Modular System for Analyzing and
Displaying Gridded Numerical Data,'' Journal of Atmospheric and Oceanic
Technology, @strong{5}, 501-511, 1988.
@item
Rew, R. K. and G. P. Davis, ``The Unidata netCDF: Software for
Scientific Data Access,'' @emph{Sixth International Conference on Interactive
Information and Processing Systems for Meteorology, Oceanography, and
Hydrology}, Anaheim, California, American Meteorology Society, February 1990.
@item
Rew, R. K. and G. P. Davis, ``NetCDF: An Interface for
Scientific Data Access,'' @emph{Computer Graphics and Applications},
IEEE, pp. 76-82, July 1990.
@item
Treinish, L. A. and M. L. Gough, ``A Software Package for the Data
Independent Management of Multi-Dimensional Data,'' @emph{EOS
Transactions}, American Geophysical Union, @strong{68}, 633-635, 1987.
@item
Sun Microsystems, ``External Data Representation Standard: Protocol
Specification,'' RFC 1014; Information Sciences Institute, May 1988.
@end enumerate

@node Components, Data, Introduction, Top
@chapter Components of a NetCDF File
@cindex netCDF components
@cindex netCDF dimensions
@cindex netCDF variables
@cindex netCDF attributes
A netCDF file has @dfn{dimensions}, @dfn{variables}, and
@dfn{attributes}.  These components can be used together to capture the
meaning of data and relations among data fields in a scientific data set.

@cindex CDL
@cindex CDL example
@cindex network Common Data Form Language (CDL)
@vindex NC_UNLIMITED
We will use a small netCDF example to illustrate the concepts of netCDF
dimensions, variables, and attributes.  The notation used to describe
this simple netCDF object is called CDL (network Common Data form
Language).  It provides an easily comprehended text version of the
structure and contents of a binary netCDF file:
@example
@group
netcdf example_1 @{  // example of CDL notation for a netCDF file

dimensions:          // dimension names and sizes are declared first
        lat = 5, lon = 10, level = 4, time = unlimited;

variables:           // variable types, names, shapes, attributes
        float   temp(time,level,lat,lon);
                    temp:long_name     = "temperature";
                    temp:units         = "celsius";
        float   rh(time,lat,lon);
                    rh:long_name = "relative humidity";
                    rh:valid_range = 0.0, 1.0;      // min and max
        int     lat(lat), lon(lon), level(level);
                    lat:units       = "degrees_north";      
                    lon:units       = "degrees_east";
                    level:units     = "millibars";
        short   time(time);
                    time:units      = "hours since 1990-11-25 12:00 UTC";
        // global attributes
                    :source = "National Weather Service";

data:                // optional data assignments
        level   = 1000, 850, 700, 500;
        lat     = 20, 30, 40, 50, 60;
        lon     = -160,-140,-118,-96,-84,-52,-45,-35,-25,-15;
        time    = 12;
        rh      =.5,.2,.4,.2,.3,.2,.4,.5,.6,.7,
                 .1,.3,.1,.1,.1,.1,.5,.7,.8,.8,
                 .1,.2,.2,.2,.2,.5,.7,.8,.9,.9,
                 .1,.2,.3,.3,.3,.3,.7,.8,.9,.9,
                  0,.1,.2,.4,.4,.4,.4,.7,.9,.9;
@}
@end group
@end example

@findex ncdump
@findex ncgen
@sp 1
@cindex CDL notation
The CDL notation for a netCDF file can be generated automatically by
using @code{ncdump}, a utility program described later (@pxref{ncdump}).
Another netCDF utility, @code{ncgen}, generates a netCDF file (or
optionally C or FORTRAN source code containing calls needed to produce a
netCDF file) from CDL input (@pxref{ncgen}).  It is not necessary to
learn much about CDL notation to use the netCDF library; we use it in
this document as a concise way of presenting netCDF examples.

The CDL notation will be explained more fully as we describe the
components of a netCDF file.  For now, note that CDL statements are
terminated by a semicolon.  Spaces, tabs, and newlines can be used freely
for readability.  Comments in CDL follow the characters @samp{//} on any
line.  A CDL description of a netCDF file takes the form
@example
@group
  netCDF @var{name} @{
    dimensions: @dots{}
    variables: @dots{}
    data: @dots{}
  @}
@end group
@end example
@noindent
where the @var{name} is used only as a default in constructing the name
of the file generated by the @code{ncgen} utility.  The CDL description
consists of three optional parts, introduced by the keywords
@code{dimensions}, @code{variables}, and @code{data}.  NetCDF dimension
declarations appear after the @code{dimensions} keyword, netCDF
variables and attributes are defined after the @code{variables} keyword,
and variable data assignments appear after the @code{data} keyword.

@menu
* What Are Dimensions?::  The components of and operations on netCDF
                          dimensions.

* What Are Variables?::  The components of and operations on netCDF
                          variables.

* What Are Attributes?::  The components of and operations on netCDF
                          attributes.
@end menu

@node What Are Dimensions?, What Are Variables?,  , Components
@section Dimensions

@cindex dimensions
A netCDF dimension is a named integer used to specify the shape of one
or more of the multi-dimensional variables contained in a netCDF file.
A dimension may be used to represent a real physical dimension, for
example, time, latitude, longitude, or height.  A dimension might also be
used to index more abstract quantities, for example, color-table entry
number, instrument number, station-time pair, or model-run ID.

@cindex dimension names
@cindex dimension size
@cindex netCDF names
@cindex CDL names
@cindex unlimited dimension
@cindex record dimension
@cindex record variables
@cindex appending data
Every netCDF dimension has both a @dfn{name} and a @dfn{size}.  A
dimension name is an arbitrary sequence of alphanumeric characters
(as well as the underscore character, @samp{_}, and the hyphen character,
@samp{-}) beginning with a letter.  Case is distinguished in netCDF
names.  A dimension size is an arbitrary positive integer, except that
one dimension in a netCDF file can have the size @code{UNLIMITED}.  Such
a dimension is called the @dfn{unlimited dimension} or the @dfn{record
dimension}.  A variable with an unlimited dimension can grow to any
length along that dimension.  The unlimited dimension is like a record
number in conventional record-oriented files.

CDL dimension declarations may appear on one or more lines following the
CDL keyword @code{dimensions}.  Multiple dimension declarations on the
same line may be separated by commas.  Each declaration is of the form
@var{name} = @var{size}.

@cindex unlimited dimension
There are four dimensions in the example: @code{lat}, @code{lon},
@code{level}, and @code{time}.  The first three are assigned
fixed sizes; @code{time} is assigned the size @code{UNLIMITED}, which means
it is the @dfn{unlimited} dimension.  A netCDF file can have at most one
unlimited dimension, but need not have any.

There are several uses for netCDF dimensions:
@itemize @bullet
@item
Specifying the shapes and sizes of variables.
@item
Identifying and relating variables that are defined on a common grid.
@item
Providing a way to define coordinate systems.
@end itemize
We discuss each of these uses below.

@menu
* Specifying Variable Shapes::  Using Dimensions to Specify the Shapes
                                of Variables

* Relating Variables::          Using Dimensions to Relate Variables

* Defining Coordinates::        Using Dimensions to Define Coordinates
@end menu

@node Specifying Variable Shapes, Relating Variables,  , What Are Dimensions?
@subsection Using Dimensions to Specify Variable Shapes

@cindex specifying variable shapes
The basic unit of named data in a netCDF file is a @dfn{variable}.  In
general, a variable is a multidimensional object that has, among other
characteristics, a @dfn{shape}, which is defined by the number, order,
and sizes of its dimensions.  When a netCDF variable is defined, the
number and order of the dimensions that define its shape are specified.
Hence you must first create the necessary dimensions before creating a
netCDF variable that uses them.

It is possible to use the same dimension more than once in specifying a
variable shape, for example @code{var(dim, dim)}, but it does not make
much sense to do this; it is contrary to the intuitive meaning of a
physical dimension.  A variable that has two dimensions that happen to
be the same size is more accurately modeled by using two dimensions with
different names but the same size.

@node Relating Variables, Defining Coordinates, Specifying Variable Shapes, What Are Dimensions?
@subsection Using Dimensions to Relate Variables

@cindex relating variables
Two dimensions may have the same size, perhaps by coincidence, without
being related in any other way.  Dimension names provide a way to distinguish
dimensions regardless of size.

@cindex variables
Variables are related by the dimensions they share.  For example, if two
variables are defined with the same dimensions, they might represent
observations or model output for the same set of points.  In the example
netCDF file, variables @code{temp} and @code{rh} share the
@code{time}, @code{lat}, and @code{lon} dimensions.  The variable
@code{rh} does not have @code{level} as a dimension, perhaps because it is only
defined for a single level.

@node Defining Coordinates,  , Relating Variables, What Are Dimensions?
@subsection Using Dimensions to Define Coordinate Systems

@cindex defining coordinate systems
@cindex coordinates
@cindex coordinate variables
Besides serving as sizes for integer indexes to multidimensional
variables, dimensions may be used to define coordinate systems for
variable data.  To do this, create a variable with the same name as a
dimension and specify coordinate values for that variable.  A variable
should only be given the same name as a dimension in a netCDF file when it is
to be used as a @dfn{coordinate} variable.  Such variables are
indexed by the dimension for which they provide coordinate values, for
example, @code{lat(lat)}.

It is not necessary to provide a coordinate variable for each dimension;
if no such variable is defined, the coordinate values of the dimension
are assumed to be 0, 1, 2, @dots{} (for C programs) or 1, 2, 3, @dots{}
(for FORTRAN programs).  Although the C and FORTRAN interfaces support
different conventions for index numbering, there is no difference
between the actual netCDF files written by C and FORTRAN programs.
Programs written in either language can be used to access data written
by programs using the other interface.

In the CDL example, each dimension has an associated coordinate variable
with the same name as the dimension.  The four values of the
@code{level} index, 0, 1, 2, 3, (1, 2, 3, 4 in FORTRAN) are related in
coordinate-like fashion to the four values (1000, 850, 700, 500) of the
@code{level} variable.  Note that there is no requirement that
coordinates be equally spaced or increasing.  It would not make much
sense for two coordinate values to be the same, but the meaning of
coordinate variables is enforced only by conventions of application
packages and utilities, not by the netCDF interface.  The application
packages and utilities that make use netCDF coordinate variables assume
they are one-dimensional and monotonic (all values either increasing or
decreasing).

@node What Are Variables?, What Are Attributes?, What Are Dimensions?, Components
@section Variables
@cindex variables

@cindex data types
@cindex variable shape
@cindex shape of a netCDF variable
@cindex variable attributes
@cindex variable data values
A @dfn{variable} represents a multidimensional array of values of the
same type.  A variable has a name, a data type, and a shape described by
its list of dimensions, all of which are specified when the variable is
created.  Each variable may also have data values and associated
attributes, which may be added or changed after the variable is created.
Variables are used to store the bulk of the data in a netCDF file, and
are the primary component used by utilities to identify sub-parts of a
netCDF file.
@sp 1
@cindex variable name
Like a dimension name, a variable name is an arbitrary sequence of
alphanumeric characters (also including @samp{_} and @samp{-}) beginning
with a letter.  Case is distinguished in variable names.  Long names
help to make a netCDF file self-documenting, but ancillary information
about a variable is better stored in variable @dfn{attributes}
(discussed below) than encoded as part of the name.

@cindex data types
@cindex variable data types
@cindex NC_BYTE type specifier
@cindex NC_CHAR type specifier
@cindex NC_SHORT type specifier
@cindex NC_LONG type specifier
@cindex NC_FLOAT type specifier
@cindex NC_DOUBLE type specifier
@cindex byte CDL type
@cindex char CDL type
@cindex short CDL type
@cindex long CDL type
@cindex float CDL type
@cindex double CDL type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
A variable data type is one of a small set of netCDF @dfn{types} that
have the names @code{NC_BYTE}, @code{NC_CHAR}, @code{NC_SHORT},
@code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE} in the C interface
and the corresponding names @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT},
@code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE} in the
FORTRAN interface.  In the CDL notation, these types are given the
simpler names @code{byte}, @code{char}, @code{short}, @code{long},
@code{float}, and @code{double}.  @code{int} may be used as a synonym
for @code{long} and @code{real} may be used as a synonym for
@code{float} in the CDL notation.  We will postpone a discussion of the
exact meaning of each of the types until the discussion of @dfn{data},
below.  For now, it suffices to know that the choice of the type used to
represent variable data depends on the range of values it can have, the
precision to which values are known, and the number of bits required to
represent the variable in a netCDF file on disk.

@cindex unlimited dimension
@cindex scalar variables
The shape of a variable is specified by its list of dimensions.  If a
variable has an unlimited dimension, that dimension must appear
first in the list of dimensions in CDL.  It is possible to define variables
with no dimensions, also called @dfn{scalar} variables.  There are no
scalar variables in the example netCDF file.

@cindex CDL variable declarations
CDL variable declarations appear after the @code{variables} keyword in
a CDL unit.  They have the form
@display
     @i{type} @i{variable_name}  ( @i{dim_name_1, dim_name_2, @dots{}} ) ;
@end display
@noindent
for variables with dimensions, or
@display
     @i{type} @i{variable_name} ;
@end display
@noindent
for scalar variables.

@cindex record variables
@cindex variable size
In the CDL example there are six variables.  As discussed above, four of
these are coordinate variables for dimensions.  The remaining variables,
@code{temp} and @code{rh}, contain what is usually thought of as the
data.  Each of these variables has the unlimited dimension @code{time}
as its first dimension, so they are called @dfn{record variables}.  A
variable that is not a record variable has a fixed size (number of data
values) given by the product of its dimensions.  A record variable has a
current size, given by the product of the maximum record written so far
and the other dimensions of the variable.  Only record variables may
grow after they are defined.

@node What Are Attributes?,  , What Are Variables?, Components
@section Attributes

@cindex attributes
@cindex ancillary data
@cindex database management systems
A netCDF @dfn{attribute} is meant to contain information about a netCDF
variable or about an entire netCDF file.  This information is
@dfn{ancillary data}, or data about data, analogous to the information
stored in data dictionaries and schema in conventional database systems.
An attribute has an associated variable, a name, a data type, a length,
and a value.  Individual attributes are identified by specifying a
variable and an attribute name.

@cindex variable attributes
Each attribute is associated with a single variable when it is created.
Attributes for different variables may differ in data type, length, and
values even though they share the same name.  

@cindex global attributes
A @dfn{global} attribute is one that applies to the whole netCDF rather
than any particular variable.  Global attributes are defined and
accessed similarly to variable attributes; the details for defining
global attributes in the CDL notation and in the netCDF procedural
interface are presented later.

@cindex attribute names
@cindex conventional attributes
@cindex generic applications
@cindex units attribute
Attribute names follow the same rules as dimension and variable names.
Providing meaningful names for attributes is important, but using agreed
on conventional names is also required if generic applications and
utility programs will be used on a netCDF file.  For example, every
variable for which units make sense should have a @code{units} attribute
defined, so the units can be printed in labels.  Furthermore, if the
netCDF file is ever to be used as input to generic units-aware software,
the values of the @code{units} attributes should be expressed in a
conventional form as a character string that can be interpreted by that
software.

@cindex attribute type
The type of an attribute is specified when it is created.  The types
permitted for attributes are exactly the same as the netCDF data types
used in creating variables.  Attributes with the same name for different
variables should sometimes be of different types.  For example, the
attribute @code{valid_max} specifying the maximum valid data value for a
variable of type @code{long} should be of type @code{long}, whereas the
attribute @code{valid_max} for a variable of type @code{double} should
instead be of type @code{double}.

@cindex attribute length
@cindex attribute values
@cindex string-valued attributes
In addition to specifying the associated variable, attribute name, and
type, the length and value of an attribute must also be specified when it is
created.  The information in an attribute is represented by either a single
value (length 1) or a vector of values of the same type.  Since
``character string'' is not a basic netCDF data type, string-valued
attributes have a vector of characters as their value, with a length
equal to the length of the character string.

@cindex attributes
@cindex dimensions
@cindex variables
Attributes are more dynamic than variables or dimensions; they
can have their type, length, and values changed after they are created.
For example, an attribute @code{max_value} might store the 
maximum value seen so far for a record variable, and might 
be updated every time a new record is written.

@cindex CDL notation
@cindex variable attributes
@cindex global attributes
@cindex attribute type
@cindex attribute length
The CDL notation for defining an attribute is
@display
    @i{variable_name:attribute_name} = @i{list_of_values} ;
@end display
@noindent
for a variable attribute, or
@display
    @i{:attribute_name} = @i{list_of_values} ;
@end display
@noindent
for a global attribute.  The type and length of each attribute are not
explicitly declared in CDL; they are derived from the values assigned to
the attribute.  All values of an attribute must be of the same type.
The notation used for constant values of the various netCDF types is
discussed later (@pxref{CDL Constants}).

In the example netCDF (@pxref{Components, , CDL example}), @code{units}
is an attribute for the variable @code{lat} that has a
13 character array value @samp{degrees_north}. And @code{valid_range} is an
attribute for the variable @code{rh} that has length 2 and values
@samp{0.0} and @samp{1.0}.

@cindex global attributes
One global attribute---@code{source}---is defined
for the example netCDF file.  This is a character array intended for
documenting the data.  Real netCDF files typically have more global
attributes to document the origin, history, accuracy, and other
characteristics of the data.

@menu
* Attribute Conventions::    Conventions for Commonly Used Attributes

* Attributes and Variables:: Differences Between Attributes and Variables
@end menu

@node    Attribute Conventions, Attributes and Variables,  , What Are Attributes?
@comment  node-name,  next,  previous,  up
@subsection Attribute Conventions

@cindex attribute conventions
@cindex conventional attributes
@cindex generic applications
Generic applications that take netCDF files as input may by
convention expect certain variable and global attributes.  A few other
attributes are handled in special ways by the netCDF library (these
reserved attributes will have names that begin with a leading underscore
character @samp{_}).  If you want to be able to use generic
applications with your files, you should use the following conventional
names for these commonly used attributes:

@cindex units attribute
@table @code
@item units
A character array that specifies the units used for the variable's data.
A standard for conventional ways to name units in each specific
discipline should be used, if available.  Unidata has developed a
freely-available library of routines to convert between character string
and binary forms of unit specifications and to perform various useful
operations on the binary forms.  This library is used in some netCDF
applications.  Using the recommended units syntax permits data
represented in conformable units to be automatically converted to common
units for algebraic operations.  @xref{Units}, for more information.

@cindex long_name attribute
@cindex variable name
@item long_name
A long descriptive name.  This could be used for labelling plots, for
example.  If a variable has no @code{long_name} attribute assigned, the
variable name will be used as a default.
@cindex valid_range attribute
@item valid_range
An array of two numbers specifying the minimum and maximum valid values
for this variable.  The type of each @code{valid_range} attribute should
match the type of its variable.
@cindex valid_min attribute
@cindex valid_max attribute
@item valid_min
@itemx valid_max
One or both of these may be used instead of @code{valid_range}; this
handles the case where it only makes sense to bound the data below
or above.
@cindex scaling data
@cindex scale_factor attribute
@item scale_factor
If present for a variable, the data are to be multiplied by this factor
after the data are read by the application that accesses the data.
@cindex data packing
@cindex data compression
@cindex data resolution
@cindex add_offset attribute
@item add_offset
If present for a variable, this number is to be added to the data after
it is read by the application that accesses the data.  If
both @code{scale_factor} and @code{add_offset} attributes are present,
the data are first scaled before the offset is added.
The attributes @code{scale_factor} and @code{add_offset} can be used
together to provide simple data compression to store low-resolution
floating-point data as small integers in a netCDF file.  When scaled data
are written, the application should first subtract the offset and then
divide by the scale factor.

When @code{scale_factor} and @code{add_offset} are used for packing, the
associated variable (containing the packed data) is typically of type
byte or short, whereas the unpacked values are intended to be of type
float or double.  The attributes @code{scale_factor} and
@code{add_offset} should both be of the type intended for the unpacked
data, e.g. float or double.

@cindex missing values
@cindex fill values
@cindex FillValue attribute
@item _FillValue
If a scalar attribute with this name is defined for a variable and is of
the same type as the variable, it will be subsequently used as the
@emph{fill value} for that variable.  The purpose of this attribute is
to save the applications programmer the work of prefilling the data and
also to eliminate the duplicate writes that result from netCDF filling
in missing data with its default fill value, only to be immediately
overwritten by the programmer's preferred value.  This value is
considered to be a special value that indicates missing data, and is
returned when reading values that were not written.  The missing value
should be outside the range specified by @code{valid_range} for a
variable.  It is not necessary to define your own @code{_FillValue}
attribute for a variable if the default @dfn{fill value} for the type of
the variable is adequate.  Note that if you change the value of this
attribute, the changed value only applies to subsequent writes;
previously written data are not changed.  @xref{Missing Values}, for
more information.

@cindex missing_value
@item missing_value
@code{missing_value} is a conventional name for a missing value that
will not be treated in any special way be the library, as the
@code{_FillValue} attribute is.  It is also useful when it is necessary
to distinguish between two kinds of missing values.  For example,
@code{_FillValue} might be useful to indicate data that was expected but
did not appear, whereas @code{missing_value} might be used to indicate
grid regions that are not intended to contain data.  @xref{Missing
Values}, for more information.

@cindex signedness
@cindex signed
@cindex unsigned
@item signedness
Used to indicate a nondefault interpretation of the signedness of
integer values.  By default, applications that deal with values should
treat netCDF byte data as unsigned and netCDF short and long integer
data as signed.  If you declare a netCDF variable for storing bytes, and
you intend that the values represent signed quantities, you should
declare the variable attribute @code{signedness} with value
@code{"signed"}.  Similarly, if you define a variable for an array of
short or long integers and you intend that the values be interpreted as
unsigned, it would be appropriate to define the variable attribute
@code{signedness = "unsigned"}.  This attribute is ignored by the netCDF
library, but applications may use it.  Since there are no standard
FORTRAN types corresponding to unsigned integers, FORTRAN programs that
compute with or use the ordering of data values may need to handle this
attribute.

@cindex print formats
@cindex C_format attribute
@item C_format
A character array for the format that should be used to print values for
this variable by C applications.  For example, if you know a variable is
only accurate to three significant digits, it would be appropriate to
define the @code{C_format} attribute as @code{"%.3g"}.  The
@code{ncdump} utility program uses this attribute for variables for
which it is defined.

@cindex FORTRAN_format attribute
@item FORTRAN_format
A character array for the format that should be used to print values for
this variable by FORTRAN applications.

@cindex title attribute
@item title
A global attribute that is a character array providing a succinct
description of what is in the data set.

@cindex recording data history
@cindex generic applications
@cindex generic filters
@cindex history attribute
@item history
A global attribute that is a character array with a line for each
invocation of a program and arguments that were used to derive the file.
Well-behaved generic netCDF filters (programs that take netCDF files as
input and produce netCDF files as output) will automatically append
their name and the parameters with which they were invoked to the global
history attribute of an input netCDF file.
@end table
Attributes may be added to a netCDF file long after it is first defined,
so you don't have to anticipate all potentially useful attributes.
However adding new attributes to an existing file can incur the same
expense as copying the file.  @xref{File Structure, , NetCDF File
Structure and Performance}, for a more extensive discussion.

@node   Attributes and Variables,  , Attribute Conventions, What Are Attributes?
@subsection Differences between Attributes and Variables

@cindex variables
@cindex attributes
@cindex differences between attributes and variables
@cindex ancillary data
In contrast to variables, which are intended for bulk data, attributes
are intended for ancillary data, or information about the data.
Typically the data in variables of an open netCDF will reside on disk,
because the data are too large to fit in memory all at once.  In
contrast, the total amount of ancillary data associated with a netCDF
object and stored in its attributes is typically small enough to be
memory-resident.

Another difference between attributes and variables is that variables
may be multidimensional.  Attributes are all either scalars
(single-valued) or vectors (a single, fixed dimension).

@cindex variable values
@cindex attribute values
Variables are created with a name, type, and shape before they are assigned
data values, so a variable may exist with no values.  The value of an
attribute must be specified when it is created, so no attribute ever
exists without a value.

@cindex units attribute
A variable may have attributes, but an attribute cannot have attributes.
Attributes assigned to variables may have the same units as the variable
(for example, @code{valid_range}) or have no units (for example,
@code{scale_factor}).  If you want to store data in a netCDF file that
requires units different from those of the associated variable, it is
better to use a variable than an attribute.  More generally, if data
require ancillary data to describe them, are multidimensional, require
any of the defined netCDF dimensions to index their values, or require a
significant amount of storage, the data should be represented using
variables rather than attributes.

@node Data, Usage, Components, Top
@chapter Data

This chapter discusses the six primitive netCDF data types, the kinds of
data access supported by the netCDF interface, and how data structures other
than multidimensional arrays may be implemented in a netCDF file.

@menu
* Data Types::      The six basic netCDF data types.

* Data Access::     Direct access, hyperslab access, and record access.

* Data Structures:: Representing other structures with netCDF arrays.
@end menu

@node Data Types, Data Access,  , Data
@section NetCDF Data Types

@cindex netCDF data types
@cindex byte type
@cindex char type
@cindex short type
@cindex long type
@cindex float type
@cindex double type
@cindex primitive netCDF types
@cindex ASCII characters
@cindex IEEE floating-point
The current set of primitive types supported by the netCDF interface are:
@table @code
@item byte
Eight-bit data; especially good for saving space when
only a few values are possible or resolution is low.
@item character
Currently synonymous with @code{byte}; intended for
representing text strings as arrays of ASCII characters.
@item short
16-bit integers.
@item long
32-bit integers.
@item float
32-bit IEEE floating-point.
@item double
64-bit IEEE floating-point.
@end table

@cindex unsigned
@cindex CDL reserved words
Except for the added @code{byte} and the lack of
unsigned types, netCDF supports the same primitive data types as C.  The
names for the primitive data types are reserved words in CDL, so the
names of variables, dimensions, and attributes must not be type names.
Whether byte, short, or long data is interpreted as signed or unsigned
is not part of the netCDF interface; since no netCDF operations depend
on the sign or order of variable data, you are free to interpret a byte,
for example, as holding values between 0 and 255 or between -128 and
127.  For convenience, short and long constants are interpreted as
signed in the CDL notation.  @xref{Attribute Conventions} for more
information on representing signedness of values.

@cindex XDR
These types were chosen because they are familiar to C and FORTRAN
programmers, they have well-defined external representations independent
of any particular computers (using XDR), and they are sufficient for
providing a reasonably wide range of trade-offs between data precision
and number of bits required for each datum.

@cindex future changes planned
Additional primitive types may be added in the future, but only in a way
that is compatible with existing programs and files.  For example,
@code{hyperlong} for 64-bit integers will eventually be needed, along
with a new type for multibyte characters, but these can both be added
without affecting existing netCDF files or applications, and with
only minor changes required for generic applications that will support
them.

@node Data Access, Data Structures, Data Types, Data
@section Data Access

The netCDF interface supports several kinds of data access to data in an
open netCDF file:
@itemize @bullet
@item
direct (random) access to single data values,
@item
direct access to an arbitrary generalized cross-section of data
for a single variable,
@item
record-oriented access to data for a single variable, and
@item
record-oriented access to a subset of the variables in a record.
@end itemize

To directly access a single data value, you specify a netCDF file, a
variable, and a multidimensional index for the variable.  Files are not
specified by name every time you want to access data, but instead by a
small integer obtained when the file is first created or opened.
Similarly, variables are not specified by name for every data access
either, but by variable IDs, small integers used to identify variables
in a netCDF file.

@cindex hyperslabs
@cindex hyperslab corner
@cindex hyperslab edge lengths
@cindex subscript order
@cindex index order
@cindex data order
Data in a netCDF file can be accessed as single values or as
@dfn{hyperslabs}.  A hyperslab is a generalized piece of a
multidimensional variable that is specified by giving the indices of a
corner point and a list of edge lengths along each of the dimensions of
the variable.  The corner point specified must be the one with the
smallest indices, that is the one closest to the origin of the variable
index space.  The block of data values returned (or written) has the
last dimension of the variable varying fastest, and the first dimension
varying most slowly in the C interface.  For FORTRAN, the order is
reversed, with the first dimension of the variable varying fastest and
the last dimension varying most slowly.  These ordering conventions
correspond to the customary order in which multidimensional variables
are stored in C and FORTRAN.

@cindex hyperslab access example
As an example of hyperslab access, assume that in the example
netCDF file (@pxref{Components, , CDL example}), you wish to read all the
data for the @code{temp} variable at the second (850 millibar) level, and
assume that there are currently three records (@code{time} values) in
the netCDF file.  Recall that the dimensions are defined as
@example
        lat = 5, lon = 10, level = 4, time = unlimited;
@end example
@noindent
and the variable @code{temp} is declared as
@example
        float   temp(time, level, lat, lon);
@end example
@noindent
in the CDL notation.

A corresponding C variable that holds data for all four levels and all
three times might be declared as
@example
#define LATS  5
#define LONS 10
#define LEVELS 4
#define TIMES 3                 /* currently */
    @dots{}
float   temp[TIMES*LEVELS*LATS*LONS];
@end example
@noindent
to keep the data in a one-dimensional array, or
@example
    @dots{}
float   temp[TIMES][LEVELS][LATS][LONS];
@end example
@noindent
using a multidimensional array declaration.  To read in a hyperslab of
data for only one level at a time, for example, you could leave out the
LEVEL dimension or set it to 1.

In FORTRAN, the dimensions are reversed from the CDL declaration with the
first dimension varying fastest and the record dimension as the last
dimension of a record variable.  Thus a FORTRAN declaration for the
coresponding variable that holds all times and levels is
@example
@group
      PARAMETER (LATS=5, LONS=10, LEVELS=4, TIMES=3)
         @dots{}
      REAL TEMP(LONS, LATS, LEVELS, TIMES)
@end group
@end example

@cindex hyperslab corner
@cindex hyperslab edge lengths
@cindex subscript order
@cindex index order
@cindex data order
To specify the hyperslab of data that represents the second level, all
times, all latitudes, and all longitudes, we need to provide a corner
and some edge lengths.  The corner should be (0, 1, 0, 0) in C---or (1,
1, 2, 1) in FORTRAN---because you want to start at the beginning of each
of the @code{time}, @code{lon}, and @code{lat} dimensions, but you want
to begin at the second value of the @code{level} dimension.  The edge
lengths should be (3, 1, 5, 10) in C---or (10, 5, 1, 3) in
FORTRAN---since you want to get data for all three @code{time} values,
only one @code{level} value, all five @code{lat} values, and all 10
@code{lon} values.  You should expect to get a total of 150 float values
returned (3 * 1 * 5 * 10), and should provide enough space in your array
for this many.  The order in which the data will be returned is with the
last dimension, @code{lon}, varying fastest for C, or with the first
dimension, @code{LON}, varying fastest for FORTRAN:
@example
@group
              C                  FORTRAN

     temp[0][1][0][0]      TEMP(1, 1, 2, 1)
     temp[0][1][0][1]      TEMP(2, 1, 2, 1)
     temp[0][1][0][2]      TEMP(3, 1, 2, 1)
     temp[0][1][0][3]      TEMP(4, 1, 2, 1)

           @dots{}                 @dots{}

     temp[2][1][4][7]      TEMP( 8, 5, 2, 3)
     temp[2][1][4][8]      TEMP( 9, 5, 2, 3)
     temp[2][1][4][9]      TEMP(10, 5, 2, 3)
@end group
@end example

@cindex language interfaces
@cindex data order
@cindex order of data
Note that the different dimension orders for the C and FORTRAN
interfaces do not reflect a different order for values stored on the
disk, but merely different orders supported by the procedural interfaces
to the two languages.  In general, it does not matter whether a netCDF
file is written using the C or FORTRAN interface; netCDF files written
from either language may be read by programs written in the other
language.

@cindex generalized hyperslabs
@cindex hyperslab corner
@cindex hyperslab edge lengths
Besides the regular hyperslab access described above, the netCDF
abstraction also supports the reading and writing of @dfn{generalized
hyperslabs}.  A generalized hyperslab has the same corner point and edge
lengths attributes as a regular hyperslab.  It allows, however, more
general mappings between the points of the hyperslab and both the
disk-resident values of the netCDF variable and the locations for those
values in memory.

@cindex strides
In a regular hyperslab, the mapping between the points of the hyperslab and 
the values of a netCDF variable can be described as contiguous: along each
dimension, adjacent hyperslab points correspond to adjacent netCDF variable
values.
In a generalized hyperslab, however, this is not necessarily true;
in any dimension, adjacent generalized hyperslab points correspond to
netCDF variable values that are separated by a distance of @dfn{n} values.
@dfn{n} is the @dfn{stride} of the dimension and needn't be the same for all
dimensions.
Strides may reasonably vary from one (to access adjacent netCDF variable 
values) to the number of points in a netCDF dimension.
A regular hyperslab has unity strides in all dimensions.

@cindex index mapping vector
The other mapping allowed by generalized hyperslabs is between the
points of the hyperslab and the memory locations of the corresponding
values.  In a regular hyperslab, this mapping is trivial: the structure
of the in-memory values (i.e. the dimensional sizes and their order) is
identical to that of the hyperslab.  In a generalized hyperslab,
however, this is not necessarily true, instead an @dfn{index mapping
vector} is used to define the mapping between points in the generalized
hyperslab and the memory locations of the corresponding values.  The
offset, in bytes, from the origin of a memory-resident array to a
particular point is given by the
@cindex inner product
@dfn{inner product}
@footnote{
The @dfn{inner product} of two vectors 
[x0, x1, @dots{}, xn] and [y0, y1, @dots{}, yn] is just x0*y0 + x1*y1 + @dots{} + 
xn*yn.
}
of the index mapping vector with the point's 
@cindex coordinate offset vector
@dfn{coordinate offset vector}
@footnote{
A point's @dfn{coordinate offset vector} gives,
for each dimension, the offset from the origin of the containing array
to the point.
In C, a point's coordinate offset vector is the same as it's coordinate
vector.
In FORTRAN, however, the values of a point's coordinate offset vector
are one less than the corresponding values of the point's coordinate vector.
}
.
The index
mapping vector for a regular hyperslab would have -- in order from most
rapidly varying dimension to most slowly -- the byte size of a
memory-resident datum (e.g. 4 for a floating-point value), then the
product of that value with the edge length of the most rapidly varying
dimension of the hyperslab, then the product of that value with the edge
length of the next most rapidly varying dimension, and so on.  In a
generalized hyperslab, however, the correspondence between hyperslab
points and memory locations can be radically diferent.  For example, the
following C definitions
@example 
@group
struct vel @{
    int flags;
    float u;
    float v;
@} vel[NX][NY];
long imap[2] = @{
    sizeof(struct vel),
    sizeof(struct vel)*NY@};
@end group
@end example
where @code{imap} is the index mapping vector,
can be used to access the memory-resident values of the netCDF variable,
@code{vel[NY][NX]}, even
though the dimensions are transposed and the data is contained in a 2-D array
of structures rather than a 2-D array of floating-point values.

Note that, although the netCDF abstraction allows the use of generalized 
hyperslab access if warranted by the situation, it does not mandate it.
If you do not need generalized hyperslab access, you may ignore this
capability and use regular hyperslab access instead.

@cindex records
@cindex record-oriented access
@cindex record variables
@cindex appending data
To perform conventional record-oriented access, you specify a netCDF
file, a record variable (one defined with an unlimited dimension),
and for the record number use the value of the first dimension (last
dimension in FORTRAN), using hyperslab access to get the record of
values.

@cindex record I/O
You may read or write multiple record variables, even if the variables
are of different types, with a single call in the C interface.  In this
case you must write a whole record's-worth of data for each desired
variable.  This interface is supported as a convenience for C
programmers, but is not strictly necesary, since the same result may be
achieved with one read or write call for each variable.  An equivalent
portable FORTRAN interface that replaces multiple calls with a single
call is unfortunately not possible.  However, data written using the C
interface can still be read with the FORTRAN interface, using one call
per variable.

@cindex efficiency
@cindex performance
@cindex order of dimensions
@cindex data order
@cindex representation on disk
When efficiency is a concern, you should keep in mind the order in which
netCDF data are written on the disk, since the best I/O performance is
achieved by reading or writing contiguous data.  All variable data are
ordered with the last dimension for each variable varying fastest in the
C interface, or the slowest in the FORTRAN interface.  This means that
for record variables in particular, at least one disk access per record
will be required for reading a value from each record.  Hence reading a
hyperslab that takes one value out of each record will require as many
disk accesses as the number of values requested.  For writing, the
situation is even worse, since each record must first be read and then
rewritten to change a single value within a record.  If you have a
choice about the order in which data is accessed or the order of the
dimensions that define the shape of a variable, try to choose these two
orders in harmony to avoid needless inefficiency.

@node Data Structures,  , Data Access, Data
@section Data Structures
@cindex data structures
@cindex sparse matrices
@cindex trees
@cindex linked lists
@cindex pointers
@cindex XDR
The only kind of data structure directly supported by the netCDF
abstraction is a collection of named scalar and multidimensional
variables with attached vector attributes.  NetCDF is not particularly
well-suited for storing linked lists, trees, sparse matrices, or other
kinds of data structures requiring pointers.  The underlying XDR library
on which netCDF is implemented is quite suitable for storing and
retrieving arbitrary data structures in a network-transparent way, but
such structures will no longer be self-describing unless you encode
information about the structure with the data.
@cindex index variables
It is possible to build other kinds of data structures from sets of
multidimensional arrays by adopting various conventions regarding the
use of data in one array as pointers into another array.  The netCDF
library won't provide much help or hindrance with constructing such data
structures, but netCDF provides the mechanisms with which such
conventions can be designed.  

@cindex indexing values
For example, it is possible to use a variable attribute to name an
associated index variable: the variable attribute @samp{array_index_var
= "v_index"} might provide the name of another associated variable to be
used as an index for fast retrieval by value in the variable to which
the attribute is attached.

@cindex grouping variables
As another example, netCDF variables may be grouped within a netCDF file
by defining attributes that list the names of the variables in each
group, separated by a conventional delimiter such as a space or comma.
A convention can be adopted to use particular sorts of attribute names
for such groupings, so that an arbitrary number of named groups of
variables can be supported.  If needed, a particular conventional
attribute for each variable might list the names of the groups of which
it is a member.  Use of attributes or variables that refer to other
attributes or variables provides a flexible mechanism for representing
complex structures in netCDF files.

@node Usage, File Operations, Data, Top
@chapter Use of the NetCDF Library

@cindex netCDF library use
@cindex common netCDF calls
@cindex typical netCDF calls
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.

@menu
* Creating a netCDF File::     How to create a new netCDF file.

* Reading with Known Names::   How to read a netCDF file with known names.

* Reading with Unknown Names:: How to read a generic netCDF.

* Adding Components::          How to add new dimensions, variables, and
                               attributes.

* Error Handling::             How to handle errors.
@end menu

@node Creating a netCDF File, Reading with Known Names,  , Usage
@section Creating a NetCDF File

@cindex netCDF file creation
@cindex 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
@code{@dots{}} to represent arbitrary sequences of other statements:

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

In FORTRAN, the corresponding sequence looks like this:
@findex NCCRE
@findex NCDDEF
@findex NCVDEF
@findex NCAPT
@findex NCAPTC
@findex NCENDF
@findex NCVPT
@findex NCVPTC
@findex NCVPTG
@findex NCCLOS
@example
    NCCRE              ! create netCDF file: enter define mode
         @dots{}
       NCDDEF          ! define dimensions: from name and size
         @dots{}
       NCVDEF          ! define variables: from name, type, dimensions
         @dots{}
       NCAPT or NCAPTC ! attribute put: assign attribute values
         @dots{}
    NCENDF             ! end definitions: leave define mode
         @dots{}
    NCVPT or NCVPTC    ! variable put: provide values for variables
      @dots{}
    NCAPT or NCAPTC    ! attribute put: change attribute values
      @dots{}
    NCCLOS             ! close: save new netCDF file
@end example

@noindent
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.

@cindex define mode
@cindex data mode
@cindex dimensions
@cindex variables
@cindex attributes
Only one call is needed to begin creating a netCDF file, at which
point you will be in the first of two netCDF @dfn{modes}.  When
accessing a netCDF, you are either in @dfn{define mode} or @dfn{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.

@cindex attributes
@cindex variables
@cindex dimensions
@cindex define mode
@findex ncdimdef
@findex NCDDEF
@findex ncvardef
@findex NCVDEF
@findex ncattput
@findex NCAPT
@findex NCAPTC
@findex ncendef
@findex NCENDF
One call to @code{ncdimdef} (or @code{NCDDEF}) is needed for each
dimension created.  Similarly, one call to @code{ncvardef} (or
@code{NCVDEF}) is needed for each variable creation, and one call to
@code{ncattput} (or @code{NCAPT} or @code{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 @code{ncendef} (or
@code{NCENDF}).

@cindex data mode
@cindex attributes
@cindex variables
@findex ncvarput1
@findex NCVPT1
@findex NCVP1C
@findex ncvarput
@findex ncvarputg
@findex ncrecput
@findex NCVPT
@findex NCVPTC
@findex NCVPTG
@findex NCVPGC
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 @code{ncvarput1} (or @code{NCVPT1}
or @code{NCVP1C}); while arbitrary hyperslabs of data are written using
@code{ncvarput} or @code{ncvarputg} (or @code{NCVPT}, @code{NCVPTC},
@code{NCVPTG}, or @code{NCVPGC}) instead.  Multi-variable records of
data may be written using multiple calls to @code{ncvarput} (or @code{NCVPT})
or with a single call to @code{ncrecput}.

@cindex data loss
@cindex abnormal termination
@cindex closing files
@cindex attributes
@cindex variables
@cindex performance
@cindex efficiency
@findex ncclose
@findex NCCLOS
@findex ncsync
@findex NCSNC
Finally, you should explicitly close all open netCDF
files on which you are writing by calling @code{ncclose} (or
@code{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 @code{ncsync} (or
@code{NCSNC}).  It is possible to reduce the chance of losing data due
to abnormal termination by explicitly calling @code{ncsync}
(@code{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.

@node Reading with Known Names, Reading with Unknown Names, Creating a netCDF File, Usage
@section Reading a NetCDF File with Known Names

@cindex known names
@cindex reading a netCDF file
@cindex generic applications
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:

@findex ncopen
@findex ncdimid
@findex ncvarid
@findex ncattget
@findex ncvarget
@findex ncclose
@example
    ncopen           /* open existing netCDF */
      @dots{}
    ncdimid          /* get dimension IDs to use in accessing data */
      @dots{}
    ncvarid          /* get variable IDs */
      @dots{}
    ncattget         /* get attribute values, if needed */
      @dots{}
    ncvarget         /* get values of variables */
      @dots{}
    ncclose          /* close netCDF */
@end example
@sp 1
In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCDID
@findex NCVID
@findex NCAGT
@findex NCAGTC
@findex NCVGT
@findex NCVGTC
@findex NCVGTG
@findex NCCLOS
@example
    NCOPN            !  open existing netCDF 
      @dots{}
    NCDID            !  get dimension IDs to use in accessing data 
      @dots{}
    NCVID            !  get variable IDs 
      @dots{}
    NCAGT or NCAGTC  !  get attribute values, if needed 
      @dots{}
    NCVGT or NCVGTC  !  get values of variables 
      @dots{}
    NCCLOS           !  close netCDF 
@end example

@cindex opening a netCDF file
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.  

@cindex dimensions
@cindex dimension IDs
@cindex variables
@cindex variable IDs
@cindex variable data
@cindex efficiency
@cindex performance
@cindex hyperslab access
@findex ncopen
@findex NCOPN
@findex ncvarid
@findex NCVID
@findex ncattget
@findex NCAGT
@findex NCAGTC
@findex ncvarget1
@findex NCVGT1
@findex NCVG1C
@findex ncvarget
@findex ncvargetg
@findex NCVGT
@findex NCVGTC
@findex NCVGTG
@findex NCVGGC
Next, a call to @code{ncdimid} (or @code{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 @code{ncvarid} (or @code{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 @code{ncattget} (or @code{NCAGT} or @code{NCAGTC}) for each desired
attribute.  Variable data values can be directly accessed from the
netCDF file with @code{ncvarget1} (or @code{NCVGT1} or @code{NCVG1C})
for single values, @code{ncvarget} or @code{ncvargetg} (or @code{NCVGT},
@code{NCVGTC}, @code{NCVGTG}, or @code{NCVGGC}) for hyperslabs of
values, or @code{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.

@cindex closing a netCDF file
@findex ncclose
@findex NCCLOS
Finally, the netCDF file can be closed with @code{ncclose} (or
@code{NCCLOS}) when you are finished with it to free system
resources.  There is no harm in not closing a file open only for
reading.
@node Reading with Unknown Names, Adding Components, Reading with Known Names, Usage
@section Reading a netCDF File with Unknown Names
@cindex generic applications
@cindex inquire functions
@cindex dimensions
@cindex variables
@cindex attributes
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:
@findex ncopen
@findex ncinquire
@findex ncdiminq
@findex ncvarinq
@findex ncattname
@findex ncattinq
@findex ncattget
@findex ncvarget
@findex ncclose
@example
@group
    ncopen           /* open existing netCDF */
      @dots{}
    ncinquire        /* find out what is in it */
         @dots{}
       ncdiminq      /* get dimension names, sizes */
         @dots{}
       ncvarinq      /* get variable names, types, shapes */
            @dots{}
          ncattname  /* get attribute names */
            @dots{}
          ncattinq   /* get attribute types and lengths */
            @dots{}
          ncattget   /* get attribute values */
            @dots{}
    ncvarget         /* get values of variables */
      @dots{}
    ncclose          /* close netCDF */
@end group
@end example

In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCINQ
@findex NCDINQ
@findex NCVINQ
@findex NCAINQ
@findex NCAGT
@findex NCAGTC
@findex NCVGT
@findex NCVGTC
@findex NCVGTG
@findex NCCLOS
@example
@group
    NCOPN                 !  open existing netCDF 
      @dots{}
    NCINQ                 !  find out what is in it 
         @dots{}
       NCDINQ             !  get dimension names, sizes 
         @dots{}
       NCVINQ             !  get variable names, types, shapes 
            @dots{}
          NCANAM          !  get attribute names 
            @dots{}
          NCAINQ          !  get attribute values 
            @dots{}
          NCAGT or NCAGTC !  get attribute values 
            @dots{}
    NCVGT or NCVGTC       !  get values of variables 
      @dots{}
    NCCLOS                !  close netCDF 
@end group
@end example

@findex ncinquire
@findex NCINQ
As in the previous example, a single call opens the existing netCDF
file, returning a netCDF ID.  This netCDF ID is given to the
@code{ncinquire} (or @code{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.

@findex ncrecinq
@cindex record variables
Another inquire function, @code{ncrecinq}, is provided for convenience
to return information about record variables, although the information
is also obtainable by using the other inquire functions.  The
@code{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.

@cindex performance
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.

@cindex dimension IDs
@cindex dimensions
@findex ncdiminq
@findex NCDINQ
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, @dots{}, (or 1, 2,
3, @dots{} in FORTRAN).  For each dimension ID, a call to the inquire
function @code{ncdiminq} (or @code{NCDINQ}) returns the dimension name
and size.

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

@cindex attributes
@findex ncattname
@findex NCANAM
@findex ncattinq
@findex NCAINQ
@findex ncattget
@findex NCAGT
@findex NCAGTC
Once the number of attributes for a variable is known, successive calls
to @code{ncattname} (or @code{NCANAM}) return the name for
each attribute given the netCDF ID, variable ID, and attribute number.
Armed with the attribute name, a call to @code{ncattinq} (or
@code{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 @code{ncattget} (or @code{NCAGT}
or @code{NCAGTC}) returns the attribute values.

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

@node Adding Components, Error Handling, Reading with Unknown Names, Usage
@section Adding New Dimensions, Variables, Attributes

@cindex adding dimensions
@cindex adding variables
@cindex adding attributes
@cindex deleting attributes
@cindex renaming attributes
@cindex renaming dimensions
@cindex renaming variables
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:

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

In FORTRAN, the corresponding sequence looks like this:
@findex NCOPN
@findex NCREDF
@findex NCDDEF
@findex NCVDEF
@findex NCAPT
@findex NCAPTC
@findex NCENDF
@findex NCVPT
@findex NCVPTC
@findex NCVPTG
@findex NCVPGC
@findex NCCLOS
@example
    NCOPN             !  open existing netCDF 
      @dots{}
    NCREDF            !  put it into define mode 
        @dots{}
      NCDDEF          !  define additional dimensions (if any) 
        @dots{}
      NCVDEF          !  define additional variables (if any) 
        @dots{}
      NCAPT or NCAPTC !  define additional attributes (if any) 
        @dots{}
    NCENDF            !  check all definitions, leave define mode 
      @dots{}
    NCVPT or NCVPTC   !  provide values for new variables 
      @dots{}
    NCCLOS            !  save netCDF file 
@end example

@cindex data mode
@cindex define mode
@findex ncopen
@findex NCOPN
@findex ncredef
@findex NCREDF
@findex ncdimdef
@findex NCDDEF
@findex ncvardef
@findex NCVDEF
@findex ncattput
@findex NCAPT
@findex NCAPTC
A netCDF file is first opened by the @code{ncopen} (or @code{NCOPN})
call.  This call puts you in @dfn{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 @dfn{define mode}, by calling @code{ncredef} (or @code{NCREDF}).
In define mode, call @code{ncdimdef} (or @code{NCDDEF}) to define new
dimensions, @code{ncvardef} (or @code{NCVDEF}) to define new variables
(using the new dimensions), and @code{ncattput} (or @code{NCAPT} or
@code{NCAPTC}) to assign new attributes to variables or enlarge old
attributes.

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

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

@node Error Handling,  , Adding Components, Usage
@section Error Handling

@cindex error handling
@cindex error messages
@cindex suppressing error messages
@cindex error returns
@cindex default 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.

@cindex XDR errors
@cindex write errors
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.

@vindex ncopts
@vindex NC_VERBOSE
@vindex NC_FATAL
@cindex error options
@cindex fatal errors
@cindex error messages
In the C interface, errors may be handled more flexibly by setting the
external integer @code{ncopts}, declared in the file @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
@example
ncopts = NC_VERBOSE | NC_FATAL;
@end example
@noindent
where @code{NC_VERBOSE} and @code{NC_FATAL} are predefined constants
from the include file @file{netcdf.h}.

@vindex ncerr
@vindex error returns
If you want error messages but do not wish errors to be fatal, turn off
the fatal error flag with:
@example
ncopts = NC_VERBOSE;
@end example
@noindent
If you want neither error messages nor fatal errors, turn off both flags
with:
@example
ncopts = 0;
@end example
@noindent
In either case, you should check the return value after each call to a
netCDF function.  The integer @code{-1} is returned whenever an error
occurs and @code{NC_FATAL} is off, so you can detect error returns and
handle the errors appropriately.  Another externally-defined integer,
@code{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 @file{netcdf.h}.

@vindex NCPOPT
@vindex NCGOPT
@vindex NCVERBOS
@vindex NCFATAL
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
@example
      CALL NCPOPT(NCVERBOS+NCFATAL)
@end example
@noindent
where the values of NCVERBOS and NCFATAL are pre-defined constants from
the FORTRAN include file @file{netcdf.inc}.
@noindent
If you want error messages, but do not wish errors to be fatal, turn
off the fatal error flag with:
@example
      CALL NCPOPT(NCVERBOS)
@end example
@noindent
If you want neither error messages nor fatal errors, turn off both flags
with:
@example
      CALL NCPOPT(0)
@end example
@noindent
To get the current value of the error options, use:
@example
      CALL NCGOPT(NCOPTS)
@end example

@vindex rcode
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
@file{netcdf.inc}.

@node File Operations, Dimensions, Usage, Top
@chapter NetCDF Operations

This chapter presents the interfaces of the netCDF routines that deal
with a netCDF file as a whole.

@cindex netCDF file name
@cindex netCDF ID
@cindex netCDF handle
A netCDF file that has not yet been opened can only be referred to by
its file name.  Once a netCDF file is opened, it is referred to by an
ID, which is a small nonnegative integer returned when you create or
open the file.  A netCDF ID is a file @dfn{handle}, much like a file
descriptor in C or a logical unit number in FORTRAN.  In any single
program, the netCDF IDs of distinct open netCDFs are distinct.  A single
netCDF file may be opened multiple times and will then have multiple
distinct netCDF IDs; however at most one of the open instances of a
single netCDF file should permit writing.  When an open netCDF file is
closed, its ID no longer refers to it, and that ID may be subsequently
reassigned to refer to a different netCDF that is opened later.

@cindex netCDF operations
The operations supported on a netCDF file as a single object are:
@itemize @bullet

@item
Create, given file path and whether to overwrite or not.

@item
Open for access, given file path and read or write intent.

@item
Put into define mode, to add dimensions, variables, or attributes.

@item
Take out of define mode, checking consistency of additions.

@item
Close, writing to disk if required.

@item
Get number of dimensions, number of variables, number of global
attributes, and ID of the unlimited dimension if any.

@item
Synchronize to disk to make sure it is current.

@item
Set and unset @emph{nofill} mode for optimized sequential writes.

@end itemize
@noindent
After a summary of conventions used in describing the netCDF C and
FORTRAN interfaces, the rest of this chapter presents the interfaces for
these operations.

@menu
* Interface Descriptions::   Conventions for netCDF library interface
                             descriptions.
* nccreate and NCCRE::       Create a netCDF file.
* ncopen and NCOPN::         Open a netCDF file for access.
* ncredef and NCREDF::       Put open netCDF file into define mode.
* ncendef and NCENDF::       Leave Define Mode.
* ncclose and NCCLOS::       Close an Open netCDF File.
* ncinquire and NCINQ::      Inquire about an Open netCDF File.
* ncsync and NCSNC::         Synchronize an Open netCDF File to Disk.
* ncabort and NCABOR::       Back Out of Recent Definitions.
* ncsetfill and NCSFIL::     Set fill mode for optimized writes.
@end menu

@node Interface Descriptions, nccreate and NCCRE,  , File Operations
@section NetCDF Library Interface Descriptions

@cindex interface descriptions
@cindex example conventions
@cindex conventions in examples
@cindex error conditions
@cindex examples
@cindex function prototypes

Each interface description for a particular netCDF function in this and
later chapters contains:
@itemize @bullet

@item
A description of the purpose of the function;

@item
A list of possible error conditions;

@item
A C function prototype that presents the type and order of the formal
parameters to the function;

@item
A description of each formal parameter in the C interface;

@item
An example of a C program fragment calling the netCDF function and
perhaps other netCDF functions to do something useful;

@item
A FORTRAN function prototype that presents the type and order of the
formal parameters to the FORTRAN function or functions that provide the
same functionality as the C function;

@item
A description of each formal parameter in the FORTRAN interface; and

@item
An example of a FORTRAN program fragment that duplicates the function of
the example C fragment.
@end itemize

The C function prototypes specify the order and type of each formal
parameter and conform to the ANSI C standard.  FORTRAN does not have
function prototypes, but a similar syntax is used to concisely present
the order and types of FORTRAN formal parameters.  In the few cases in
which a single C function corresponds to two FORTRAN functions, the
FORTRAN functions prototypes are presented together.

The FORTRAN examples use two nonstandard notations: @code{INCLUDE}
statements and in-line comments.  In each case, we use the VMS FORTRAN
notation, as in the following example:
@example
      INCLUDE 'netcdf.inc'
      INTEGER NCID       ! this is an in-line comment
@end example
FORTRAN examples (and the FORTRAN interface) abide by the six-character
limitation on the length of FORTRAN names, except that
parameters names may be up to eight characters long.

@page
@node nccreate and NCCRE, ncopen and NCOPN, Interface Descriptions, File Operations
@section  Create a NetCDF file

@cindex netCDF file creation
@cindex creating a netCDF file
@findex nccreate
@findex NCCRE
The function @code{nccreate} (or @code{NCCRE} for FORTRAN) creates a
new netCDF file, returning a netCDF ID that can subsequently be used to
refer to the netCDF file.  The new netCDF file is placed in define mode.

In case of an error, @code{nccreate} returns -1; @code{NCCRE} returns a
nonzero value in @code{rcode}.  Possible causes of errors include::
@itemize @bullet

@item
Passing a file name that includes a directory that does not exist.

@vindex NC_NOCLOBBER
@vindex NCNOCLOB
@item
Specifying a file name of a file that exists and also specifying
@code{NC_NOCLOBBER} (or @code{NCNOCLOB}).

@item
Attempting to create a netCDF file in a directory where you don't have
permission to create files.
@end itemize

@findex nccreate
@unnumberedsubsec nccreate:  C Interface
@example
int nccreate (const char* path, int cmode);
@end example

@table @code

@item path
The file name of the new netCDF file.  This can be given as either an
absolute path name (from the root of the file system) or a relative
path name (from the current directory).

@vindex NC_CLOBBER
@vindex NC_NOCLOBBER
@item cmode
Should be specified as either @code{NC_CLOBBER} or @code{NC_NOCLOBBER}.  These
constants are defined in the include file named @file{netcdf.h}.
@code{NC_CLOBBER} means that even if the file already exists, you want to
create a new file with the same name, erasing the old file's contents.
@code{NC_NOCLOBBER} means you want to create a new netCDF file only if the
given file name does not refer to a file that already exists.
@end table

@findex nccreate
@vindex NC_NOCLOBBER
In this example we create a netCDF file named
@file{foo.nc}; we want the file to be created in the current
directory only if a file with that name does not already exist:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = nccreate("foo.nc", NC_NOCLOBBER);
@end group
@end example

@unnumberedsubsec NCCRE:  FORTRAN Interface

@findex NCCRE
@example
INTEGER FUNCTION NCCRE (CHARACTER*(*) PATH, INTEGER CMODE,
                        INTEGER RCODE)
@end example

@table @code

@item PATH
The file name of the new netCDF file.  This can be given as either an
absolute path name (from the root of the file system) or a relative
path name (from the current directory).

@vindex NCCLOB
@vindex NCNOCLOB
@item CMODE
Should be specified as either @code{NCCLOB} or @code{NCNOCLOB}.  These
constants are defined in the include file @file{netcdf.inc}.
@code{NCCLOB} means that even if the file already exists, you want to
create a new file with the same name, erasing the old file's contents.
@code{NCNOCLOB} means you want to create a new netCDF file only if the
given file name does not refer to a file that already exists.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCRE
In this example we create a netCDF file named
@file{foo.nc}, assuming we want the file to be created in the current
directory only if a file with that name does not already exist:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID
         @dots{}
      NCID = NCCRE('foo.nc', NCNOCLOB, RCODE)
@end group
@end example

@page
@node ncopen and NCOPN, ncredef and NCREDF, nccreate and NCCRE, File Operations
@section Open a NetCDF File for Access

@cindex opening a netCDF file
@findex ncopen
@findex NCOPN
The function @code{ncopen} (or @code{NCOPN} for FORTRAN) 
opens an existing netCDF file for access.

In case of an error, @code{ncopen} returns -1; @code{NCOPN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include::
@itemize @bullet

@item
The specified netCDF file does not exist.

@vindex NC_WRITE
@vindex NC_NOWRITE
@item
The mode specified is something other than @code{NC_WRITE} or
@code{NC_NOWRITE}.
@end itemize

@findex ncopen
@unnumberedsubsec ncopen:  C Interface
@example
int ncopen(const char* path,int mode);
@end example

@table @code

@item path
Absolute or relative file name for netCDF file to be opened.

@vindex NC_WRITE
@vindex NC_NOWRITE
@item mode
Either @code{NC_WRITE}, to open the file for writing, or @code{NC_NOWRITE}, to
open the file read-only.  ``Writing'' means any kind of change to the
file, including appending or changing data, adding or renaming dimensions,
variables, and attributes, or deleting attributes.
@end table

@findex ncopen
@vindex NC_NOWRITE
Here is an example using @code{ncopen} to open an existing netCDF file
named @file{foo.nc} for reading:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
@end group
@end example

@findex NCOPN
@unnumberedsubsec NCOPN:  FORTRAN Interface
@example
      INTEGER FUNCTION NCOPN(CHARACTER*(*) PATH,
     +                       INTEGER RWMODE,
     +                       INTEGER RCODE)
@end example

@table @code

@item PATH
Absolute or relative file name for netCDF file to be opened.

@vindex NCWRITE
@vindex NCNOWRIT
@item RWMODE
Either @code{NCWRITE}, to open the file for writing, or @code{NCNOWRIT}, to
open the file read-only.  ``Writing'' means any kind of change to the
file, including appending or changing data, adding or renaming dimensions,
variables, and attributes, or deleting attributes.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
Here is an example of using @code{NCOPN} to open an existing netCDF file
named @file{foo.nc} for reading:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID
         @dots{}
      NCID = NCOPN('foo.nc', NCNOWRIT, RCODE)
@end group
@end example

@page
@node ncredef and NCREDF, ncendef and NCENDF, ncopen and NCOPN, File Operations
@section Put Open NetCDF File into Define Mode

@cindex define mode
@cindex adding dimensions
@cindex adding variables
@cindex adding attributes
@cindex renaming dimensions
@cindex renaming variables
@cindex renaming attributes
@cindex deleting attributes
@findex ncredef
@findex NCREDF
The function @code{ncredef} (or @code{NCREDF} for FORTRAN) 
puts an open netCDF file into define mode, so dimensions, variables,
and attributes can be added or renamed and attributes can be deleted.

In case of an error, @code{ncredef} returns -1; @code{NCREDF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include::
@itemize @bullet

@item
The specified netCDF file is already in define mode.

@item
The specified netCDF file was opened for read-only.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncredef
@unnumberedsubsec ncredef:  C Interface
@example
int ncredef(int ncid);
@end example

@table @code

@item ncid
netCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncopen
@findex ncredef
@vindex NC_WRITE
Here is an example using @code{ncredef} to open an existing NetCDF file
named @file{foo.nc} and put it into define mode:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);    /* open file */
   @dots{}
ncredef(ncid);                        /* put in define mode */
@end group
@end example

@findex NCREDF
@unnumberedsubsec NCREDF:  FORTRAN Interface
@example
SUBROUTINE NCREDF(INTEGER NCID, INTEGER RCODE)
@end example

@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCREDF
@vindex NCWRITE
Here is an example of using @code{NCREDF} to open an existing netCDF file
named @file{foo.nc} and put it into define mode:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF(NCID, RCODE)
@end group
@end example

@page
@node ncendef and NCENDF, ncclose and NCCLOS, ncredef and NCREDF, File Operations
@section Leave Define Mode

@cindex define mode
@cindex data mode
@findex ncendef
@findex NCENDF
The function @code{ncendef} (or @code{NCENDF} for FORTRAN) takes an open
netCDF file out of define mode.  The changes made to the netCDF file
while it was in define mode are checked and committed to disk if no
problems occurred.  The netCDF file is then placed in data mode, so
variable data can be read or written.

This call can be expensive, since it involves initializing non-record
variables and copying data under some circumstances.  @xref{File
Structure, , NetCDF File Structure and Performance}, for a more
extensive discussion.

In case of an error, @code{ncendef} returns -1; @code{NCENDF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet

@item
The specified netCDF file is not in define mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncendef
@unnumberedsubsec ncendef:  C Interface
@example
int ncendef(int ncid);
@end example

@table @code

@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table
@findex nccreate
@findex ncendef
@vindex NC_NOCLOBBER
Here is an example using @code{ncendef} to finish the definitions of a
new netCDF file named @file{foo.nc} and put it into data mode:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = nccreate("foo.nc", NC_NOCLOBBER);

   @dots{}      /* create dimensions, variables, attributes */

ncendef(ncid);  /*leave define mode*/

@end group
@end example
@sp 1
@findex NCENDF
@unnumberedsubsec NCENDF:  FORTRAN Interface
@example
SUBROUTINE NCENDF(INTEGER NCID, INTEGER RCODE)
@end example

@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCENDF
@findex NCCRE
@vindex NCNOCLOB
Here is an example using @code{NCENDF} to finish the definitions of a
new netCDF file named @file{foo.nc} and put it into data mode:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID
         @dots{}
      NCID = NCCRE('foo.nc', NCNOCLOB, RCODE)

         @dots{}  !  create dimensions, variables, attributes

      CALL NCENDF(NCID, RCODE)
@end group
@end example

@page
@node ncclose and NCCLOS, ncinquire and NCINQ, ncendef and NCENDF, File Operations
@section Close an Open NetCDF File

@cindex closing a netCDF file
@findex ncclose
@findex NCCLOS
@findex ncendef
@findex NCENDF
@findex ncabort
@findex NCABOR
@cindex netCDF ID
The function @code{ncclose} (or @code{NCCLOS} for FORTRAN) closes an
open netCDF file.  If the file is in define mode, @code{ncendef} (or
@code{NCENDF}) will be called before closing.  (In this case, if
@code{ncendef} [or @code{NCENDF}] returns an error, @code{ncabort} [or
@code{NCABOR}] will automatically be called to restore the file to the
consistent state before define mode was last entered.)  After an open
netCDF file is closed, its netCDF ID will be reassigned to the next
netCDF file that is opened or created.

In case of an error, @code{ncclose} returns -1; @code{NCCLOS} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet

@findex ncendef
@findex NCENDF
@item
The netCDF was in define mode and the automatic call made to
@code{ncendef} (or @code{NCENDF}) failed.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncclose
@unnumberedsubsec ncclose:  C Interface
@example
int ncclose(int ncid);
@end example

@table @code

@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex nccreate
@findex ncclose
@vindex NC_NOCLOBBER
Here is an example using @code{ncclose} to finish the definitions of a
new netCDF file named @file{foo.nc} and release its netCDF ID:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = nccreate("foo.nc", NC_NOCLOBBER);

   @dots{}      /* create dimensions, variables, attributes */

ncclose(ncid);       /* close netCDF file */
@end group
@end example

@unnumberedsubsec NCCLOS:  FORTRAN Interface

@findex NCCLOS
@example
SUBROUTINE NCCLOS(INTEGER NCID, INTEGER RCODE)
@end example

@table @code

@item NCID
netCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCLOS
@findex NCCRE
@vindex NCNOCLOB
Here is an example using @code{NCCLOS} to finish the definitions of a
new netCDF file named @file{foo.nc} and release its netCDF ID:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE
         @dots{}
      NCID = NCCRE('foo.nc', NCNOCLOB, RCODE)

         @dots{}  ! create dimensions, variables, attributes

      CALL NCCLOS(NCID, RCODE)
@end group
@end example

@page
@node ncinquire and NCINQ, ncsync and NCSNC, ncclose and NCCLOS, File Operations
@section Inquire about an Open NetCDF File

@cindex inquire about a netCDF file
@findex ncinquire
@findex NCINQ
The function @code{ncinquire} (@code{NCINQ} for FORTRAN) returns
information about an open netCDF file, given its netCDF ID.  It can be
called from either define mode or data mode.  It returns values for the
number of dimensions, the number of variables, the number of global
attributes, and the dimension ID of the dimension defined with
unlimited size, if any.  No I/O is required when this or any other
`inquire' function in the netCDF interface is called, since the
functions merely return information that is stored in a table for each
open netCDF file.

In case of an error, @code{ncinquire} returns -1; @code{NCINQ} returns a
nonzero value in @code{rcode}.  Possible cause of errors includes:
@itemize @bullet
@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncinquire
@unnumberedsubsec ncinquire:  C Interface
@example
int ncinquire(int ncid, int* ndims, int* nvars, int* ngatts,
              int* recdim);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex number of dimensions
@item ndims
Returned number of dimensions defined for this netCDF file.  If this
parameter is given as @samp{(int *) 0}, the number of dimensions will not be
returned so no variable to hold this information needs to be declared.

@cindex number of variables
@item nvars
Returned number of variables defined for this netCDF file.  If this
parameter is given as @samp{(int *) 0}, the number of variables will not be
returned so no variable to hold this information needs to be declared.

@cindex number of global attributes
@cindex global attributes
@item ngatts
Returned number of global attributes defined for this netCDF file.  If
this parameter is given as @samp{(int *) 0}, the number of global attributes
will not be returned so no variable to hold this information needs to be
declared.

@cindex unlimited dimension ID
@item recdim
Returned ID of the unlimited dimension, if there is one for this netCDF
file.  If no unlimited size dimension has been defined, -1 is returned
for the value of @code{recdim}.  If this parameter is given as
@samp{(int *) 0}, the record dimension ID will not be returned so no
variable to hold this information needs to be declared.
@end table

@findex ncopen
@findex ncinquire
@vindex NC_NOWRITE
Here is an example using @code{ncinquire} to find out about a netCDF
file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid, ndims, nvars, ngatts, recdim;
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
ncinquire(ncid, &ndims, &nvars, &ngatts, &recdim);
@end group
@end example

@unnumberedsubsec NCINQ:  FORTRAN Interface

@findex NCINQ
@example
      SUBROUTINE NCINQ(INTEGER NCID, INTEGER NDIMS, INTEGER NVARS,
     *                 INTEGER NGATTS, INTEGER RECDIM, INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item NDIMS
Returned number of dimensions defined for this netCDF file.

@item NVARS
Returned number of variables defined for this netCDF file.

@item NGATTS
Returned number of global attributes defined for this netCDF file.

@cindex unlimited dimension ID
@item RECDIM
Returned ID of the unlimited dimension, if there is one for this netCDF
file.  If no unlimited size dimension has been defined, -1 is returned
for the value of @code{RECDIM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCINQ
@vindex NCNOWRIT
Here is an example using @code{NCINQ} to find out about a netCDF
file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, NDIMS, NVARS, NATTS, RECDIM, RCODE
         @dots{}
      NCID = NCOPN('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      CALL NCINQ(NCID, NDIMS, NVARS, NATTS, RECDIM, RCODE)
@end group
@end example

@page
@node ncsync and NCSNC, ncabort and NCABOR, ncinquire and NCINQ, File Operations
@section Synchronize an Open NetCDF File to Disk

@cindex synchronize a netCDF file
@cindex data mode
@cindex define mode
@cindex performance
@cindex efficiency
@findex ncsync
@findex NCSNC
@findex ncendef
@findex NCENDF
The function @code{ncsync} (or @code{NCSNC} for FORTRAN) makes sure that
the disk copy of a netCDF file open for writing is current.  The netCDF
file must be in data mode.  A netCDF file in define mode is synchronized
to disk only when @code{ncendef} (or @code{NCENDF}) is called.  A
process that is reading a netCDF file that another process is writing
can also call @code{ncsync} (or @code{NCSNC} for FORTRAN) to get updated
with the changes made by the writing process (e.g. the number of records
written), without having to close and reopen the file.

It can be expensive in computer resources to always synchronize to disk
after every write of variable data or change of an attribute value.
There are two reasons you might want to synchronize after writes:
@itemize @bullet
@item
To minimize data loss in case of abnormal termination, or

@cindex shared access
@item
To make data available to other processes for reading immediately after it
is written.  But note that a process that already had the file open for
reading would not see the number of records increase when the writing
process calls @code{ncsync}; to accomplish this, the reading process
must call @code{ncsync}.
@end itemize

@cindex closing a netCDF file
@cindex define mode
@cindex data mode
Data is automatically synchronized to disk when a netCDF file is closed,
or whenever you leave define mode.

In case of an error, @code{ncsync} returns -1; @code{NCSNC} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet

@item
The netCDF file is in define mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncsync
@unnumberedsubsec ncsync:  C Interface
@example
int ncsync(int ncid);
@end example

@table @code

@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncsync
@findex ncopen
@vindex NC_WRITE
Here is an example using @code{ncsync} to synchronize the disk writes of
a netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);  /* open for writing */

   @dots{}          /* write data or change attributes */

ncsync(ncid);      /* synchronize to disk */
@end group
@end example

@findex NCSNC
@unnumberedsubsec NCSNC:  FORTRAN Interface
@example
      SUBROUTINE NCSNC(INTEGER NCID, INTEGER RCODE)
@end example

@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCSNC
@findex NCOPN
@vindex NCNOWRIT
Here is an example using @code{NCSNC} to synchronize the disk writes of
a netCDF file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
         @dots{}
* write data or change attributes
         @dots{}
      CALL NCSNC(NCID, RCODE)
@end group
@end example

@page
@node ncabort and NCABOR, ncsetfill and NCSFIL, ncsync and NCSNC, File Operations
@section Back Out of Recent Definitions

@cindex canceling definitions
@cindex backing out of definitions
@cindex aborting definitions
@findex ncabort
@findex NCABOR
@cindex define mode
@cindex data mode
@cindex closing a netCDF file
@cindex creating a netCDF file
@cindex deleting a netCDF file
@findex ncredef
@findex NCREDF
The function @code{ncabort} (or @code{NCABOR} for FORTRAN), if not in
define mode, closes the netCDF file.  If the file is being created and
is still in define mode, the file is deleted.  If define mode was
entered by a call to @code{ncredef} (or @code{NCREDF}), the netCDF file
is restored to its state before definition mode was entered and the file
is closed.  The main reason for calling @code{ncabort} (or
@code{NCABOR}) is to restore the netCDF to a known consistent state in
case anything goes wrong during the definition of new dimensions,
variables, or attributes.

@findex ncclose
@findex NCCLOS
This function is called automatically if @code{ncclose} (or
@code{NCCLOS}) is called from define mode and the call to leave define
mode before closing fails.

In case of an error, @code{ncabort} returns -1; @code{NCABOR} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet

@item
When called from define mode while creating a netCDF, deletion of the
file failed.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncabort
@unnumberedsubsec ncabort:  C Interface
@example
int ncabort(int ncid);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.
@end table

@findex ncdimdef
@findex ncopen
@vindex NC_WRITE
@findex ncredef
@findex ncabort
Here is an example using @code{ncabort} to back out of redefinitions of
a file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);  /* open for writing */
   @dots{}
ncredef(ncid);                    /* enter define mode */
   @dots{}
if (ncdimdef(ncid, "lat", 18L) == -1)
   ncabort(ncid);                 /* define failed, abort */
@end group
@end example

@unnumberedsubsec NCABOR:  FORTRAN Interface

@findex NCABOR
@example
      SUBROUTINE NCABOR(INTEGER NCID, INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@vindex NCWRITE
@findex NCREDF
@findex NCDDEF
@findex NCABOR
Here is an example using @code{NCABOR} to back out of redefinitions of
a file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, LATID
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF(NCID, RCODE)
         @dots{}
      LATID = NCDDEF(NCID, 'LAT', 18, RCODE)
      IF (RCODE .EQ. -1) THEN  ! dimension definition failed
         CALL NCABOR(NCID, RCODE)  ! abort redefinitions
      ENDIF
         @dots{}
@end group
@end example

@page
@node ncsetfill and NCSFIL,  , ncabort and NCABOR, File Operations
@section Set Fill Mode for Writes

@cindex nofill mode
@cindex performance
@cindex efficiency
@findex ncsetfill
@findex NCSFIL
These calls are intended for advanced usage, to optimize writes under
some circumstances described below.  The function @code{ncsetfill} (or
@code{NCSFIL} for FORTRAN) sets the @dfn{fill mode} for an netCDF file
open for writing and returns the current fill mode.  The fill mode can
be specified as either @code{NC_FILL} or @code{NC_NOFILL} (@code{NCFILL}
or @code{NCNOFILL} for FORTRAN).  The default behavior corresponding to
@code{NC_FILL} is that data is pre-filled with fill values, that is fill
values are written when you create non-record variables or when you
write a value beyond data that hasn't been written yet.  This makes it
possible to detect attempts to read data before it was written.
@xref{Missing Values}, for more information on the use of fill values.
@xref{Attribute Conventions} for information about how to define your
own fill values.

The behavior corresponding to @code{NC_NOFILL} overrides the default
behavior of prefilling data with fill values.  This can be used to
enhance performance, because it avoids the duplicate writes that occur
when the netCDF library writes fill values that are immediately
overwritten with data.

A value indicating which mode the netCDF file was already in is
returned.  You can use this value to temporarily change the fill mode of
an open netCDF file and then restore it to the previous mode.

After you turn on @code{NC_NOFILL} mode for an open netCDF file, you
must be certain to write valid data in all the positions that will later
be read.  Note that @code{NC_NOFILL} mode is only a transient property
of a netCDF file open for writing: if you close and reopen the file, it
will revert to the default behavior.  You can also revert to the default
behavior by calling @code{ncsetfill} (or @code{NCSFIL} for FORTRAN)
again to explicitly set the fill mode to @code{NC_FILL}.

There are three situations where it is advantageous to set nofill mode:

@enumerate
@item
Creating and initializing a netCDF file.  In this case, you should set
nofill mode before calling @code{ncendef} (@code{NCENDF} for FORTRAN),
and then write @emph{completely} all non-record variables and the
initial records of all the record variables you want to initialize.
@item
Extending an existing record-oriented netCDF file.  Set nofill mode
after opening the file for writing, then append the additional records
to the file completely, leaving no intervening unwritten records.
@item
Adding new variables that you are going to initialize to an existing
netCDF file.  Set nofill mode before calling @code{ncendef}
(@code{NCENDF} for FORTRAN), then write all the new variables
completely.
@end enumerate
@sp 2
If the netCDF file has an unlimited dimension and the last record was
written while in @code{NC_NOFILL} mode, then the file will be 4 bytes
longer than if @code{NC_NOFILL} mode wasn't set, but this will be
completely transparent if you access the data only through the netCDF
interfaces.

In case of an error, @code{ncsetfill} returns -1; @code{NCSFIL} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The specified netCDF ID does not refer to an open netCDF file.
@item
The specified netCDF ID refers to a file open for read-only access.
@item
The fillmode argument is neither @code{NC_NOFILL} nor @code{NC_FILL}
(neither @code{NCNOFILL} nor @code{NCFILL} for FORTRAN).
@end itemize

@findex ncsetfill
@unnumberedsubsec ncsetfill:  C Interface
@example
int ncsetfill(int ncid, int fillmode);
@end example

@table @code

@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item fillmode
Desired fill mode for the file, either @code{NC_NOFILL} or
@code{NC_FILL}.

@item ncsetfill
Returns the current fill mode of the file before this call, either
@code{NC_NOFILL} or @code{NC_FILL}.
@end table

@findex ncsetfill
@findex ncopen
@vindex NC_WRITE
Here is an example using @code{ncsetfill} to set nofill mode for
subsequent writes of a netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);  /* open for writing */

   @dots{}          /* write data with default prefilling behavior */

ncsetfill(ncid, NC_NOFILL);      /* set nofill mode */

   @dots{}          /* write data with no prefilling */

@end group
@end example
@sp 2
@findex NCSFIL
@unnumberedsubsec NCSFIL:  FORTRAN Interface
@example
      INTEGER FUNCTION NCSFIL(INTEGER NCID, INTEGER FILLMODE,
     +                        INTEGER RCODE)
@end example

@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item FILLMODE
Desired fill mode for the file, either @code{NCNOFILL} or
@code{NCFILL}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.

@item NCSFIL
Returns the current fill mode of the file before this call, either
@code{NCNOFILL} or @code{NCFILL}.
@end table

@findex NCSFIL
Here is an example using @code{NCSFIL} to set nofill mode for
a netCDF file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, OMODE
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
         @dots{}
* write data with default prefilling behavior
         @dots{}
      OMODE = NCSFIL(NCID, NCNOFILL, RCODE)
         @dots{}
* write data with no prefilling
         @dots{}
@end group
@end example



@node Dimensions, Variables, File Operations, Top
@chapter Dimensions

@cindex dimensions
@cindex define mode
@cindex appending data
@cindex unlimited dimension
@cindex record dimension
@cindex records
@cindex dimension ID
Dimensions for a netCDF file are defined when it is created, while the
netCDF file is in define mode.  Additional dimensions may be added
later by reentering define mode.  A netCDF dimension has a name and a
size.  At most one dimension in a netCDF file can
have the @code{NC_UNLIMITED} size, which means a variable using this
dimension can grow to any length (like a record number in a file).

@cindex maximum number of dimensions
@cindex MAX_NC_DIMS
@cindex generic applications
@cindex netCDF implementation
There is a suggested limit (currently 32) to the number of dimensions
that can be defined in a single netCDF file.  The limit is the value of
the predefined macro @code{MAX_NC_DIMS} (MAXNCDIM for FORTRAN).  The
purpose of the limit is to make writing generic applications simpler.
They need only provide an array of
@code{MAX_NC_DIMS} dimensions to handle any netCDF file.  The
implementation of the netCDF library does not enforce this advisory
maximium, so it is possible to use more dimensions, if necessary; just
don't expect generic applications or netCDF utilities to be able to
handle the resulting netCDF files.

@cindex dimension name
@cindex dimension size
Ordinarily, the name and size of a dimension are fixed when the
dimension is first defined.  The name may be changed later, but the size
of a dimension cannot be changed without copying the netCDF to a new
netCDF with a redefined dimension size.

Dimension sizes in the C interface are type @code{long} rather than type
@code{int} to make it possible to access all the data in a netCDF file
on a platform that only supports a 16-bit @code{int} data types, for
example MSDOS.  If dimension sizes were type @code{int} instead, it
would not be possible to access data from variables with a dimension
size greater than a 16-bit @code{int} can accommodate.

Operations supported on dimensions are:
@itemize @bullet
@item
Create a dimension, given its name and size.
@item
Get a dimension ID from its name.
@item
Get a dimension's name and size from its ID.
@item
Rename a dimension.
@end itemize

@menu
* ncdimdef and NCDDEF::    Create a Dimension
* ncdimid and NCDID::      Get a Dimension ID from Its Name
* ncdiminq and NCDINQ::    Inquire about a Dimension
* ncdimrename and NCDREN:: Rename a Dimension
@end menu

@page
@node ncdimdef and NCDDEF, ncdimid and NCDID,  , Dimensions
@section Create a Dimension

@cindex creating a dimension
@cindex dimension IDs
@cindex dimension names
@cindex dimension size
@cindex unlimited dimension
@cindex record dimension
@findex ncdimdef
@findex NCDDEF
The function @code{ncdimdef} (or @code{NCDDEF} for FORTRAN) adds a new
dimension to an open netCDF file in define mode.  It returns a dimension
ID, given the netCDF ID, the dimension name, and the dimension size.  At
most one unlimited size dimension, called the record dimension,
may be defined for each netCDF file.

In case of an error, @code{ncdimdef} returns -1; @code{NCDDEF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The netCDF file is not in definition mode.

@item
The specified dimension name is the name of another existing dimension.

@item
The specified size is not greater than zero.

@item
The specified size is unlimited, but there is already an
unlimited size dimension defined for this netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimdef
@unnumberedsubsec ncdimdef:  C Interface
@example
int ncdimdef(int ncid, const char* name, long size);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Dimension name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@samp{_}).  Case is significant.

@vindex NC_UNLIMITED
@item size
Size of dimension; that is, number of values for this dimension as an
index to variables that use it.  This should be either a positive
integer (of type @code{long}) or the predefined constant @code{NC_UNLIMITED}.
@end table

@findex ncdimdef
@findex nccreate
@vindex NC_UNLIMITED
@vindex NC_NOCLOBBER
Here is an example using @code{ncdimdef} to create a dimension named
@code{lat} of size 18 and a record dimension named @code{rec} in a new
netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid, latid, recid;
   @dots{}
ncid = nccreate("foo.nc", NC_NOCLOBBER);
   @dots{}
latid = ncdimdef(ncid, "lat", 18L);
recid = ncdimdef(ncid, "rec", NC_UNLIMITED);
@end group
@end example

@findex NCDDEF
@unnumberedsubsec NCDDEF:  FORTRAN Interface
@example
      INTEGER FUNCTION NCDDEF (INTEGER NCID,
     +                   CHARACTER*(*) DIMNAM,
     +                   INTEGER DIMSIZ,
     +                   INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMNAM
Dimension name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@samp{_}).  Case is significant.

@vindex NCUNLIM
@item DIMSIZ
Size of dimension; that is, number of values for this dimension as an
index to variables that use it.  This should be either a positive
integer or the predefined constant @code{NCUNLIM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDDEF
@findex NCCRE
@vindex NCNOCLOB
@vindex NCUNLIM
Here is an example using @code{NCDDEF} to create a dimension named
@code{lat} of size 18 and a record dimension named @code{rec} in a new
netCDF file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, LATID, RECID
         @dots{}
      NCID = NCCRE('foo.nc', NCNOCLOB, RCODE)
         @dots{}
      LATID = NCDDEF(NCID, 'lat', 18, RCODE)
      RECID = NCDDEF(NCID, 'rec', NCUNLIM, RCODE)
@end group
@end example

@page
@node ncdimid and NCDID, ncdiminq and NCDINQ, ncdimdef and NCDDEF, Dimensions
@section Get a Dimension ID from Its Name
@cindex getting dimension ID
@cindex dimension IDs
@cindex dimension names
@findex ncdimid
@findex NCDID
The function @code{ncdimid} (or @code{NCDID} for FORTRAN) returns the ID
of a netCDF dimension, given the name of the dimension.  If @code{ndims}
is the number of dimensions defined for a netCDF file, each dimension
has an ID between @code{0} and @code{ndims-1} (or @code{1} and
@code{ndims} for FORTRAN).

In case of an error, @code{ncdimid} returns -1; @code{NCDID} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet

@item
The name that was specified is not the name of any currently defined
dimension in the netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimid
@unnumberedsubsec ncdimid:  C Interface
@example
int ncdimid(int ncid, const char* name);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Dimension name, a character string beginning with a letter and followed
by any sequence of letters, digits, or underscore (@samp{_}) characters.
Case is significant in dimension names.
@end table

@findex ncdimid
@findex ncopen
@vindex NC_NOWRITE
Here is an example using @code{ncdimid} to determine the dimension ID of
a dimension named @code{lat}, assumed to have been defined previously in
an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid, latid;
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);  /* open for reading */
   @dots{}
latid = ncdimid(ncid, "lat");
@end group
@end example

@unnumberedsubsec NCDID:  FORTRAN Interface

@findex NCDID
@example
      INTEGER FUNCTION NCDID (INTEGER NCID,
     +                        CHARACTER*(*) DIMNAME,
     +                        INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMNAME
Dimension name, a character string beginning with a letter and followed
by any sequence of letters, digits, or underscore (@samp{_}) characters.
Case is significant in dimension names.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDID
@findex NCOPN
@vindex NCNOWRIT
Here is an example using @code{NCDID} to determine the dimension ID of
a dimension named @code{lat}, assumed to have been defined previously in
an existing netCDF file named @file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, LATID
         @dots{}
      NCID = NCOPN('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      LATID = NCDID(NCID, 'lat', RCODE)
@end group
@end example

@page
@node ncdiminq and NCDINQ, ncdimrename and NCDREN, ncdimid and NCDID, Dimensions
@section Inquire about a Dimension

@cindex getting dimension name
@cindex getting dimension size
@cindex dimension IDs
@cindex dimension names
@cindex dimension size
@cindex dimension inquire
@cindex maximum number of records
@cindex number of records written
@cindex records
@cindex unlimited dimension
@cindex record dimension
@findex ncdiminq
@findex NCDINQ
The function @code{ncdiminq} (or @code{NCDINQ} for FORTRAN) returns the
name and size of a dimension, given its ID.  The size for the
unlimited dimension, if any, is the maximum value used so far in
writing data for that dimension (which is the same as the current
maximum record number).

In case of an error, @code{ncdiminq} returns -1; @code{NCDINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The dimension ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdiminq
@unnumberedsubsec ncdiminq:  C Interface
@example
int ncdiminq(int ncid, int dimid, char* name, long* size);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item dimid
Dimension ID, as returned from a previous call to @code{ncdimid} or
@code{ncdimdef}.

@cindex dimension names
@vindex MAX_NC_NAME
@item name
Returned dimension name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
dimension name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @samp{(char *) 0}, no name will be
returned so no space needs to be allocated.

@item size
Returned size of dimension.  For the unlimited dimension, this is the
current maximum value used for writing any variables with this
dimension, that is the maximum record number.  If this parameter is
given as @samp{(long *) 0}, the size will not be returned, so no space
for this information need be declared or allocated.
@end table

@findex ncdiminq
@findex ncopen
@findex ncinquire
@vindex NC_NOWRITE
@findex ncdimid
@vindex MAX_NC_NAME
Here is an example using @code{ncdiminq} to determine the size of a
dimension named @code{lat}, and the name and current maximum size of the
unlimited (or record) dimension for an existing netCDF file named
@file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid, latid, ndims, nvars, ngatts, recid;
long latsize, recs;
char recname[MAX_NC_NAME];
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);  /* open for reading */
   @dots{}
latid = ncdimid(ncid, "lat");
/* get lat size, but don't get name, since we already know it */
ncdiminq(ncid, latid, (char *) 0, &latsize);
/* get ID of record dimension (among other things) */
ncinquire(ncid, &ndims, &nvars, &ngatts, &recid);
/* get record dimension name and current size */
ncdiminq(ncid, recid, recname, &recs);
@end group
@end example

@findex NCDINQ
@unnumberedsubsec NCDINQ:  FORTRAN Interface
@example
      SUBROUTINE NCDINQ (INTEGER NCID, INTEGER DIMID,
     +                   CHARACTER*(*) DIMNAM, INTEGER DIMSIZ,
     +                   INTEGER RCODE)
@end example

@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMID
Dimension ID, as returned from a previous call to @code{NCDID} or @code{NCDDEF}.

@cindex dimension names
@vindex MAXNCNAM
@item DIMNAM
Returned dimension name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
dimension name is given by the predefined constant @code{MAXNCNAM}.

@item DIMSIZ
Returned size of dimension.  For the unlimited dimension, this is
the current maximum value used for writing any variables with this
dimension, that is the maximum record number.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDINQ
@findex NCOPN
@findex NCINQ
@vindex NCNOWRIT
@findex NCDID
@vindex MAXNCNAM
Here is an example using @code{NCDINQ} to determine the size of a
dimension named @code{lat}, and the name and current maximum size of the
unlimited (or record) dimension for an existing netCDF file named
@file{foo.nc}:
@example
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, LATID, LATSIZ
      INTEGER NDIMS, NVARS, NGATTS, RECID, NRECS
* 31 in following statement is parameter MAXNCNAM
      CHARACTER*31 LATNAM, RECNAM
         @dots{}
      NCID = NCOPN('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      LATID = NCDID(NCID, 'lat', RCODE)
* get lat name and size, (even though we already know name)
      CALL NCDINQ(NCID, LATID, LATNAM, LATSIZ, RCODE)
* get ID of record dimension (among other things)
      CALL NCINQ(NCID, NDIMS, NVARS, NGATTS, RECID, RCODE)
* get record dimension name and current size
      CALL NCDINQ(NCID, RECID, RECNAME, NRECS, RCODE)
@end group
@end example

@page
@node ncdimrename and NCDREN,  , ncdiminq and NCDINQ, Dimensions
@section Rename a Dimension

@cindex renaming dimensions
@cindex dimension names
@findex ncdimrename
@findex NCDREN
The function @code{ncdimrename} (or @code{NCDREN} for FORTRAN) renames
an existing dimension in a netCDF file open for writing.  If the new name is
longer than the old name, the netCDF must be in define mode.  You cannot
rename a dimension to have the same name as another dimension.

In case of an error, @code{ncdimrename} returns -1; @code{NCDREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The new name is the name of another dimension.

@item
The dimension ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncdimrename
@unnumberedsubsec ncdimrename:  C Interface
@example
int ncdimrename(int ncid, int dimid, const char* name);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item dimid
Dimension ID, as returned from a previous call to @code{ncdimid} or @code{ncdimdef}.

@item name
New dimension name.
@end table

@findex ncdimrename
@findex ncopen
@findex ncredef
@findex ncendef
@vindex NC_WRITE
@findex ncdimid
Here is an example using @code{ncdimrename} to rename the dimension
@code{lat} to @code{latitude} in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int ncid, latid;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);  /* open for writing */
   @dots{}
ncredef(ncid);  /* put in define mode to rename dimension */
latid = ncdimid(ncid, "lat");
ncdimrename(ncid, latid, "latitude");
ncendef(ncid);  /* leave define mode */
@end group
@end example

@findex NCDREN
@unnumberedsubsec NCDREN:  FORTRAN Interface
@example
      SUBROUTINE NCDREN (INTEGER NCID, INTEGER DIMID,
     +                   CHARACTER*(*) DIMNAME, INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item DIMID
Dimension ID, as returned from a previous call to @code{NCDID} or
@code{NCDDEF}.

@item DIMNAM
New name for the dimension.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCDREN
@findex NCREDF
@findex NCOPN
@vindex NCWRITE
@findex NCDID
@findex NCENDF
Here is an example using @code{NCDREN} to rename the dimension
"lat" to "latitude" in an existing netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE, LATID
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
         @dots{}
* put in define mode to rename dimension
      CALL NCREDF(NCID, RCODE)
      LATID = NCDID(NCID, 'lat', RCODE)
      CALL NCDREN(NCID, LATID, 'latitude', RCODE)
* leave define mode
      CALL NCENDF(NCID, RCODE)
@end group
@end example

@node Variables, Attributes, Dimensions, Top
@chapter Variables

@cindex variables
@cindex define mode
@cindex variable name
@cindex variable type
@cindex variable shape
@cindex variable values
Variables for a netCDF file are defined when the file is created, while the
netCDF file is in define mode.  Other variables may be added later
by reentering define mode.  A netCDF variable has a name, a type, and a
shape, which are specified when it is defined.  A variable may also have
values, which are established later in data mode.

@cindex appending data
@cindex unlimited dimension
@cindex record dimension
Ordinarily, the name, type, and shape are fixed when the variable is
first defined.  The name may be changed, but the type and shape of a
variable cannot be changed.  However, a variable defined in terms of
the unlimited dimension can grow without bound in that dimension.

@cindex variable ID
A netCDF variable is referred to by a small integer called a variable
ID.  Attributes may be associated with a variable to specify such
properties as units, fill values, maximum and minimum valid values,
scaling factors, and offsets.

Operations supported on variables are:
@itemize @bullet
@item
Create a variable, given its name, data type, and shape.

@item
Get a variable ID from its name.

@item
Get a variable's name, data type, shape, and number of attributes from its ID.

@item
Put a data value into a variable, given variable ID, indices, and value.

@item
Put a hyperslab of values into a variable, given variable ID, corner
indices, edge lengths, and a block of values.

@item
Put a generalized hyperslab of values into a variable, given variable ID, 
corner indices, edge lengths, stride vector, index mapping vector, 
and a block of values.

@item
Put values into record variables, given record number and pointers to
blocks of values.

@item
Get a data value from a variable, given variable ID and indices.

@item
Get a hyperslab of values from a variable, given variable ID, corner
indices, and edge lengths.

@item
Get a generalized hyperslab of values from a variable, given variable ID, 
corner indices, edge lengths, stride vector, and index mapping vector.

@item
Get values from record variables, given record number and pointers to
where the data should be stored for each record variable.

@item
Rename a variable.

@item
Get number of bytes for a given data type.

@item
Get the number of record variables, their IDs, and their record sizes.

@end itemize

@menu
* ncvardef and NCVDEF::     Create a Variable
* ncvarid and NCVID::       Get a Variable ID from Its Name
* ncvarinq and NCVINQ::     Get Information about a Variable from Its ID
* ncvarput1 and NCVPT1::    Write a Single Data Value
* ncvarput and NCVPT::      Write a Hyperslab of Values
* ncvarputg NCVPTG and NCVPGC::    Write a Generalized Hyperslab of Values
* ncrecput::                Write a Record of Values
* ncvarget1 and NCVGT1::    Read a Single Data Value
* ncvarget and NCVGT(C)::   Read a Hyperslab of Values
* ncvargetg NCVGTG and NCVGGC::    Read a Generalized Hyperslab of Values
* ncrecget::                Read a Record of Values
* Character String I/O::    Reading and Writing Character String Values
* Missing Values::          Conventions for Missing Values
* ncvarrename and NCVREN::  Rename a Variable
* nctypelen and NCTLEN::    Get Number of Bytes for a Data Type
* ncrecinq::                Get Information about Record Variables
@end menu

@page
@node ncvardef and NCVDEF, ncvarid and NCVID,  , Variables
@section Create a Variable

@cindex creating a variable
@cindex variable ID
@cindex variable name
@cindex variable type
@cindex variable shape
@findex ncvardef
@findex NCVDEF
The function @code{ncvardef} (or @code{NCVDEF} for FORTRAN) adds a new
variable to an open netCDF file in define mode.  It returns a variable
ID, given the netCDF ID, the variable name, the variable type, the
number of dimensions, and a list of the dimension IDs.

@cindex define mode
@cindex maximum dimensions
@cindex dimension IDs
In case of an error, @code{ncvardef} returns -1; @code{NCVDEF} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The netCDF file is not in define mode.

@item
The specified variable name is the name of another existing variable.

@item
The specified type is not a valid netCDF type.

@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item
The specified number of dimensions is negative or more than the
constant @code{MAX_VAR_DIMS}, the maximum number of dimensions
permitted for a netCDF variable.

@item
One or more of the dimension IDS in the list of dimensions is not a
valid dimension ID for the netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvardef
@unnumberedsubsec ncvardef:  C Interface
@example
int ncvardef(int ncid, const char* name, nc_type datatype,
             int ndims, const int dimids[]);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Variable name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore (@samp{_}).  Case is
significant.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.

@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item ndims
Number of dimensions for the variable.  For example, @code{2} specifies
a matrix, @code{1} specifies a vector, and @code{0} means the variable
is a scalar with no dimensions.  Must not be negative or greater than
the predefined constant @code{MAX_VAR_DIMS}.

@item dimids
Vector of @code{ndims} dimension IDs corresponding to the variable
dimensions.  If the ID of the unlimited dimension is included, it
must be first.
@end table

@findex nccreate
@findex ncdimdef
@findex ncvardef
@vindex NC_UNLIMITED
@vindex NC_CLOBBER
Here is an example using @code{ncvardef} to create a variable named
@code{rh} of type @code{long} with three dimensions, @code{time},
@code{lat}, and @code{lon} in a new netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  lat_dim, lon_dim, time_dim;   /* dimension IDs */
int  rh_id;                        /* variable ID */
int  rh_dimids[3];                 /* variable shape */
   @dots{}
ncid = nccreate("foo.nc", NC_CLOBBER);
   @dots{}
                                   /* define dimensions */
lat_dim = ncdimdef(ncid, "lat", 5L);
lon_dim = ncdimdef(ncid, "lon", 10L);
time_dim = ncdimdef(ncid, "time", NC_UNLIMITED);
   @dots{}
                                  /* define variable */
rh_dimids[0] = time_dim;
rh_dimids[1] = lat_dim;
rh_dimids[2] = lon_dim;
rh_id = ncvardef (ncid, "rh", NC_DOUBLE, 3, rh_dimids);
@end group
@end example

@findex NCVDEF
@unnumberedsubsec NCVDEF:  FORTRAN Interface
@example
      INTEGER FUNCTION NCVDEF(INTEGER NCID, CHARACTER*(*) VARNAM,
     +                        INTEGER VARTYP, INTEGER NVDIMS,
     +                        INTEGER VDIMS(*), INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARNAM
Variable name.  Must begin with an alphabetic character, which is
followed by zero or more alphanumeric characters including the underscore (@samp{_}).
Case is significant.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VARTYP
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@cindex maximum variable dimensions
@vindex MAXVDIMS
@item NVDIMS
Number of dimensions for the variable.  For example, @code{2} specifies
a matrix, @code{1} specifies a vector, and @code{0} means the variable
is a scalar with no dimensions.  Must not be negative or greater than
the predefined constant @code{MAXVDIMS}.

@item VDIMS
Vector of @code{NVDIMS} dimension IDs corresponding to the variable
dimensions.  If the ID of the unlimited dimension is included, it
must be last.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCCRE
@findex NCDDEF
@findex NCVDEF
@vindex NC_CLOBBER
@vindex NCUNLIM
Here is an example using @code{NCVDEF} to create a variable named
@code{rh} of type @code{long} with three dimensions, @code{time},
@code{lat}, and @code{lon} in a new netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  LATDIM, LONDIM, TIMDIM ! dimension IDs
      INTEGER  RHID                    ! variable ID
      INTEGER  RHDIMS(3)               ! variable shape
         @dots{}
      NCID = NCCRE ('foo.nc', NC_CLOBBER, RCODE)
         @dots{}
                                       ! define dimensions
      LATDIM = NCDDEF(NCID, 'lat', 5, RCODE)
      LONDIM = NCDDEF(NCID, 'lon', 10, RCODE)
      TIMDIM = NCDDEF(NCID, 'time', NCUNLIM, RCODE)
         @dots{}
                                       ! define variable
      RHDIMS(1) = LONDIM
      RHDIMS(2) = LATDIM
      RHDIMS(3) = TIMDIM
      RHID = NCVDEF (NCID, 'rh', NCDOUBLE, 3, RHDIMS, RCODE)
@end group
@end example


@page
@node ncvarid and NCVID, ncvarinq and NCVINQ, ncvardef and NCVDEF, Variables
@section Get a Variable ID from Its Name

@cindex variable ID
@cindex variable name
@findex ncvarid
@findex NCVID
The function @code{ncvarid} (or @code{NCVID} for FORTRAN) returns the ID
of a netCDF variable, given its name.

In case of an error, @code{ncvarid} returns -1; @code{NCVID} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The specified variable name is not a valid name for a variable in the
specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarid
@unnumberedsubsec ncvarid:  C Interface
@example
int ncvarid(int ncid, const char* name);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item name
Variable name for which ID is desired.
@end table

@findex ncopen
@findex ncvarid
@vindex NC_NOWRITE
Here is an example using @code{ncvarid} to find out the ID of a variable
named @code{rh} in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
@end group
@end example

@findex NCVID
@unnumberedsubsec NCVID:  FORTRAN Interface
@example
      INTEGER FUNCTION NCVID(INTEGER NCID,
     +                       CHARACTER*(*) VARNAM,
     +                       INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARNAM
Variable name for which ID is desired.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@vindex NCNOWRIT
Here is an example using @code{NCVID} to find out the ID of a variable
named @code{rh} in an existing netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID                    ! variable ID
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)
@end group
@end example

@page
@node ncvarinq and NCVINQ, ncvarput1 and NCVPT1, ncvarid and NCVID, Variables
@section Get Information about a Variable from Its ID

@cindex getting variable name
@cindex getting variable type
@cindex getting variable shape
@cindex variable name
@cindex variable type
@cindex variable shape
@cindex variable inquire
@cindex variable dimensions
@findex ncvarinq
@findex NCVINQ
The function @code{ncvarinq} (or @code{NCVINQ} for FORTRAN) returns
information about a netCDF variable, given its ID.  The information
returned is the name, type, number of dimensions, a list of
dimension IDs describing the shape of the variable, and the number of
variable attributes that have been assigned to the variable.

In case of an error, @code{ncvarinq} returns -1; @code{NCVINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarinq
@unnumberedsubsec ncvarinq:  C Interface
@example
int ncvarinq(int ncid, int varid, char* name, nc_type* datatype,
             int* ndims, int dimids[], int* natts);
@end example

@cindex variable name
@cindex variable type
@cindex variable dimensions
@cindex variable attributes
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@cindex maximum name length
@vindex MAX_NC_NAME
@item name
Returned variable name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
variable name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @samp{(char *) 0}, no name will be
returned so no space needs to be allocated.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
Returned variable type, one of the set of predefined netCDF data types.
The type of this parameter, @code{nc_type}, is defined in the netCDF
header file.  The valid netCDF data types are @code{NC_BYTE},
@code{NC_CHAR}, @code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and
@code{NC_DOUBLE}.  If this parameter is given as @samp{(nc_type *) 0},
no type will be returned so no variable to hold the type needs to be
declared.

@item ndims
Returned number of dimensions the variable was defined as using.  For
example, @code{2} specifies a matrix, @code{1} specifies a vector, and
@code{0} means the variable is a scalar with no dimensions.  If this
parameter is given as @samp{(int *) 0}, no number of dimensions will be
returned so no variable to hold this information needs to be declared.

@cindex variable dimensions
@cindex maximum variable dimensions
@vindex MAX_VAR_DIMS
@item dimids
Returned vector of @code{ndims} dimension IDs corresponding to the
variable dimensions.  The caller must allocate enough space for a vector
of at least @code{ndims} integers to be returned.  The maximum possible
number of dimensions for a variable is given by the predefined constant
@code{MAX_VAR_DIMS}.  If this parameter is given as @samp{(int *) 0}, no
vector will be returned so no space to hold the dimension IDs needs to
be declared or allocated.

@item natts
Returned number of variable attributes assigned to this variable.  If
this parameter is given as @samp{(int *) 0}, the number of attributes
will not be returned so no space to hold this information needs to be
declared or allocated.
@end table
@sp 1
@findex ncopen
@findex ncvarid
@findex ncvarinq
@vindex nc_type
@vindex NC_NOWRITE
@vindex MAX_VAR_DIMS
Here is an example using @code{ncvarinq} to find out about a variable
named @code{rh} in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
nc_type rh_type;                   /* variable type */
int rh_ndims;                      /* number of dims */
int  rh_dims[MAX_VAR_DIMS];        /* variable shape */
int rh_natts                       /* number of attributes */
   @dots{}
ncid = ncopen ("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
/* we don't need name, since we already know it */
ncvarinq (ncid, rh_id, (char *) 0, &rh_type, &rh_ndims, rh_dims,
          &rh_natts);
@end group
@end example

@findex NCVINQ
@unnumberedsubsec NCVINQ:  FORTRAN Interface
@example
      SUBROUTINE NCVINQ (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) VARNAM, INTEGER VARTYP,
     +                   INTEGER NVDIMS, INTEGER VDIMS(*),
     +                   INTEGER NVATTS, INTEGER RCODE)
@end example

@cindex variable name
@cindex variable type
@cindex variable dimensions
@cindex variable attributes
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@cindex maximum name length
@vindex MAXNCNAM
@item VARNAM
Returned variable name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of a
variable name is given by the predefined constant @code{MAXNCNAM}.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VARTYP
Returned variable type, one of the set of predefined netCDF data types.
The valid netCDF data types are @code{NCBYTE}, @code{NCCHAR},
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@item NVDIMS
Returned number of dimensions for the variable.  For example, @code{2}
specifies a matrix, @code{1} specifies a vector, and @code{0} means the
variable is a scalar with no dimensions.

@cindex maximum variable dimensions
@vindex MAXVDIMS
@item VDIMS
Returned vector of @code{NVDIMS} dimension IDs corresponding to the
variable dimensions.  The caller must allocate enough space for a vector
of at least @code{NVDIMS} integers to be returned.  The maximum possible
number of dimensions for a variable is given by the predefined constant
@code{MAXVDIMS}.

@item NVATTS
Returned number of variable attributes assigned to this variable.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVINQ
@vindex NCNOWRIT
@vindex MAXVDIMS
Here is an example using @code{NCVINQ} to find out about a variable
named @code{rh} in an existing netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      CHARACTER*31 RHNAME         ! variable name
      INTEGER  RHTYPE             ! variable type
      INTEGER  RHN                ! number of dimensions
      INTEGER  RHDIMS(MAXVDIMS)   ! variable shape
      INTEGER  RHNATT             ! number of attributes
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
      CALL NCVINQ (NCID, RHID, RHNAME, RHTYPE, RHN, RHDIMS, RHNATT,
     +             RCODE)
@end group
@end example

@page
@node ncvarput1 and NCVPT1, ncvarput and NCVPT, ncvarinq and NCVINQ, Variables
@section Write a Single Data Value

@cindex putting variable data
@cindex writing data
@findex ncvarput1
@findex NCVPT1
@findex NCVP1C
The function @code{ncvarput1} (or @code{NCVPT1} or @code{NCVP1C} for
FORTRAN) puts a single data value into a variable of an open netCDF file
that is in data mode.  Inputs are the netCDF ID, the variable ID, a
multidimensional index that specifies which value to add or alter, and
the data value.

In case of an error, @code{ncvarput1} returns -1; @code{NCVPT1} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified indices were out of range for the dimensionality of the
specified variable.  For example, a negative index or an index that is
larger than the corresponding dimension size will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarput1
@unnumberedsubsec ncvarput1:  C Interface
@example
int ncvarput1(int ncid, int varid, const long mindex[], const void *value);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item mindex
The multidimensional index of the the data value to be written.  The
indices are relative to 0, so for example, the first data value of a
two-dimensional variable would have index @code{(0,0)}.  The elements
of @code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the first index would correspond to
the record number.

@item value
Pointer to the data value to be written.  The pointer is declared to be
of type @code{void *} because it can point to data of any of the basic
netCDF types.  The data should be of the appropriate type for the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect whether the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarput1
@vindex NC_WRITE
Here is an example using @code{ncvarput1} to set the @code{(1,2,3)}
element of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.nc}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{time},
@code{lat}, and @code{lon}, so we want to set the value of @code{rh} that
corresponds to the second @code{time} value, the third @code{lat} value,
and the fourth @code{lon} value:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
static long rh_index[] = @{1, 2, 3@}; /* where to put value */
static double rh_val = 0.5;        /* value to put */
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
ncvarput1(ncid, rh_id, rh_index, (void *) &rh_val);
@end group
@end example

@findex NCVPT1
@unnumberedsubsec NCVPT1:  FORTRAN Interface
@example
      SUBROUTINE NCVPT1 (INTEGER NCID, INTEGER VARID,
     +                   INTEGER MINDEX(*), @var{type} VALUE,
     +                   INTEGER RCODE)

      SUBROUTINE NCVP1C (INTEGER NCID, INTEGER VARID,
     +                   INTEGER MINDEX(*), CHARACTER CHVAL,
     +                   INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVPT1} and @code{NCVP1C}, for
putting a single value in a variable.  The first puts a
numeric value in a variable of numeric type, and the second puts
a character value in a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item MINDEX
The multidimensional index of the the data value to be written.  The
indices are relative to 1, so for example, the first data value of a
two-dimensional variable would have index @code{(1,1)}.  The elements
of @code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the last index would correspond to
the record number.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUE
For @code{NCVPT1}, the data value to be written.  The data may be of a
type corresponding to any of the netCDF types @code{NCSHORT},
@code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but must be appropriate
for the type of the netCDF variable.  @strong{Warning: neither the
compiler nor the netCDF software can detect whether the wrong type of data is
used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item CHVAL
For @code{NCVP1C}, the data value to be written.  The data should be of
a type character, corresponding to the netCDF types @code{NCCHAR} or
@code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVPT1
Here is an example using @code{NCVPT1} to set the @code{(4,3,2)}
element of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.nc}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{lon},
@code{lat}, and @code{time}, so we want to set the value of @code{rh} that
corresponds to the fourth @code{lon} value, the third @code{lat} value,
and the second @code{time} value:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  RHINDX(3)          ! where to put value
      DATA RHINDX /4, 3, 2/
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)  ! get ID
      CALL NCVPT1 (NCID, RHID, RHINDX, 0.5, RCODE)
@end group
@end example

@page
@node ncvarput and NCVPT, ncvarputg NCVPTG and NCVPGC, ncvarput1 and NCVPT1, Variables
@section Write a Hyperslab of Values

@cindex putting variable data
@cindex writing data
@cindex hyperslab access
@findex ncvarput
@findex NCVPT
@findex NCVPTC
The function @code{ncvarput} (or @code{NCVPT} or @code{NCVPTC} for
FORTRAN) writes a hyperslab of values into a netCDF variable of an open
netCDF file.  The hyperslab is specified by giving a corner and a vector
of edge lengths.  The values are specified as a vector whose elements
are ordered by assuming that the last dimension of the hyperslab varies
fastest for C, the first dimension varies fastest for FORTRAN.  The
netCDF file must be in data mode.

In case of an error, @code{ncvarput} returns -1; @code{NCVPT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index, or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths added to the specified corner would have
referenced data out of range for the dimensionality of the specified
variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error.

@item
The specified netCDF file is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarput
@unnumberedsubsec ncvarput:  C Interface
@example
int ncvarput(int ncid, int varid, const long start[], const long count[],
             const void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of long integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for writing the data values.

@item count
A vector of long integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to write.

@item value
Pointer to a block of data values to be written.  The order in which the
data will be written to the netCDF variable 
is with the last dimension of the specified hyperslab
varying fastest.
The pointer is declared to be of the type
@code{void *} because it can point to data of any of the basic netCDF
types.  The data should be of the appropriate type for the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect whether the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarput
Here is an example using @code{ncvarput} to add or change all the values
of the variable named @code{rh} to @code{0.5} in an existing netCDF file
named @file{foo.nc}.  For simplicity in this example, we assume that we
know that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, and that there are three @code{time} values, five @code{lat}
values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{}
#define TIMES 3
#define LATS  5
#define LONS  10
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
static long start[] = @{0, 0, 0@};    /* start at first value */
static long count[] = @{TIMES, LATS, LONS@};
double rh_vals[TIMES*LATS*LONS];   /* array to hold values */
int i;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
for (i = 0; i < TIMES*LATS*LONS; i++)
    rh_vals[i] = 0.5;
/* write hyperslab of values into netCDF variable */
ncvarput(ncid, rh_id, start, count, (void *) rh_vals);
@end group
@end example

@findex NCVPT
@unnumberedsubsec NCVPT:  FORTRAN Interface
@example
      SUBROUTINE NCVPT (INTEGER NCID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNT(*),
     +                  @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVPTC(INTEGER NCID, INTEGER VARID,
     +                  INTEGER START(*), INTEGER COUNTS(*),
     +                  CHARACTER*(*) STRING, INTEGER LENSTR,
     +                  INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVPT} and @code{NCVPTC}, for
writing a hyperslab of values into a netCDF variable.  The first writes
numeric values into a variable of numeric type, and the second 
writes character values into a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 1, so for example, the first data
value of a variable would have index @code{(1, 1, @dots{}, 1)}.  The
size of @code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for writing the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a
count of the number of records to write.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVPT}, the block of data values to be written.  The order in
which the data will be written into the specified hyperslab is with the
first dimension varying fastest (like the ordinary FORTRAN convention).
The data may be of a type corresponding to any of the netCDF types
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but
must be appropriate for the type of the netCDF variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
whether the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVPTC}, the characters to be written.  The order in which the
characters will be written to the netCDF variable
is with the first dimension of the
specified hyperslab
varying fastest (like the FORTRAN convention).  The data
may be of a type corresponding to the netCDF types @code{NCCHAR} or
@code{NCBYTE}.

@item LENSTR
For @code{NCVPTC}, the total declared length (in characters) of the
@code{STRING} argument.  This should be at least as large as the product
of the elements of the @code{COUNT} vector.  Note that this is not
necessarily the same as the value returned by the FORTRAN @code{LEN}
function, because an array argument may be provided.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVPT
Here is an example using @code{NCVPT} to add or change all the
values of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.nc}.  For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{lon},
@code{lat}, and @code{time}, and that there are ten @code{lon} values, five
@code{lat} values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3)         ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  START(NDIMS), COUNT(NDIMS) ! hyperslab
      DOUBLE RHVALS(LONS, LATS, TIMES)      
      DATA START /1, 1, 1/        ! start at first value
      DATA COUNT /LONS, LATS, TIMES/
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)   ! get ID
      DO 10 ILON = 1, LONS
         DO 10 ILAT = 1, LATS
            DO 10 ITIME = 1, TIMES
               RHVALS(ILON, ILAT, ITIME) = 0.5
   10 CONTINUE
      CALL NCVPT (NCID, RHID, START, COUNT, RHVALS, RCODE)
@end group
@end example

@page
@node ncvarputg NCVPTG and NCVPGC, ncrecput, ncvarput and NCVPT, Variables
@comment  node-name,  next,  previous,  up
@section Write a Generalized Hyperslab of Values

@cindex putting variable data
@cindex writing data
@cindex generalized hyperslab access
@findex ncvarputg
@findex NCVPTG
@findex NCVPGC
The function @code{ncvarputg} (or @code{NCVPTG} or @code{NCVPGC} for
FORTRAN) writes a generalized hyperslab of values into a netCDF variable 
of an open
netCDF file.  The generalized hyperslab is specified by giving a corner,
a vector of edge lengths, a stride vector, and an index mapping vector.
No assumptions are made about the ordering or size of the dimensions of the
data array.
The netCDF file must be in data mode.

In case of an error, @code{ncvarputg} returns -1; @code{NCVPTG} and
@code{NCVPGC} return a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index, or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths and strides added to the specified corner would have
referenced data out of range for the dimensionality of the specified
variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error,
as will accessing two or more points using a stride that is greater than the
size of the netCDF variable in the corresponding dimension.

@item
A non-positive stride.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarputg
@unnumberedsubsec ncvarputg:  C Interface
@example
int ncvarputg(int ncid, int varid, const long start[], const long count[],
              const long stride[], const long imap[], const void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of long integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for writing the data values.

@item count
A vector of long integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to write.

@item stride
A vector of long integers specifying,
for each dimension,
the interval between the accessed values of a netCDF variable.
The size of the vector shall be at least the number of dimensions of the
associated
netCDF variable and its elements shall correspond, in order, to the
variable's dimensions.
A value of 1 accesses adjacent values of the netCDF variable 
in the corresponding dimension;
a value of 2 accesses every other value of the netCDF variable in the
corresponding dimension; and so on.
A @code{NULL} stride argument obtains the default behavior in which
adjacent values are accessed along each dimension.

@item imap
A vector of long integers specifying,
for each dimension,
how data values associated with a 
netCDF variable are arranged in memory.
The offset, in bytes, from the memory location pointed to by the @code{value}
argument to a particular datum is given by the
inner product of the index mapping vector with the coordinates of 
the datum.
(The @dfn{inner product} of two vectors [x0, x1, @dots{}, xn] and
[y0, y1, @dots{}, yn] is just x0*y0 + x1*y1 + @dots{} + xn*yn.)
The vector may contain negative values if the
@code{value} argument is appropriately specified.
A @code{NULL} argument obtains the default behavior in
which the memory-resident values are assumed to have the same structure as the 
associated netCDF variable.

@item value
Pointer to a block of data values to be written.  The order in which the
data will be written to the netCDF variable
is with the last
dimension of the generalized hyperslab varying fastest.
The pointer is declared to be of the type
@code{void *} because it can point to data of any of the basic netCDF
types.  The data should be of the appropriate type for the netCDF
variable.  @strong{Warning: neither the compiler nor the netCDF software
can detect whether the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarputg
Here is an example using @code{ncvarputg} to add or change every other value
in each dimension
of the variable named @code{rh} to @code{0.5} in an existing netCDF file
named @file{foo.nc}.
Values are taken, using the same dimensional strides, from points 
in a 3-dimensional array of 
structures whose dimensions are the reverse of the netCDF variable.
For simplicity in this example, we assume that we
know that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, and that there are three @code{time} values, five @code{lat}
values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{}
#define TIMES 3
#define LATS  5
#define LONS  10
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
static long start[] = @{0, 0, 0@};   /* start at first value */
static long count[] = @{TIMES, LATS, LONS@};
static long stride[] = @{2, 2, 2@};  /* every other value */
long imap[3];                      /* set to reverse of variable */
struct datum @{
    int    dummy;                  /* to illustrate mapping vector */
    double rh_val;                 /* actual value to be written */
@}      data[LONS][LATS][TIMES];    /* reversed array to hold values. */
int itime, ilat, ilon;
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
for (ilon = 0; ilon < LONS; ilon += stride[2])
    for (ilat = 0; ilat < LATS; ilat += stride[1])
        for (itime = 0; itime < TIMES; itime += stride[0])
            data[ilon][ilat][itime].rh_val = 0.5;
/* access every `stride' in-memory value using reversed dimensions */
imap[0] = stride[2]*sizeof(struct datum);
imap[1] = stride[1]*(1+(LONS-1)/stride[0])*imap[0];
imap[2] = stride[0]*(1+(LATS-1)/stride[1])*imap[1];
/* write generalized hyperslab of values into netCDF variable */
ncvarputg(ncid, rh_id, start, count, stride, imap, (void*)&data[0][0][0].rh_val);
@end group
@end example

@findex NCVPTG
@findex NCVPGC
@unnumberedsubsec NCVPTG, NCVPGC:  FORTRAN Interface
@example
      SUBROUTINE NCVPTG (INTEGER NCID, INTEGER VARID,
     +                   INTEGER START(*), INTEGER COUNT(*),
     +                   INTEGER STRIDE(*), INTEGER IMAP(*),
     +                   @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVPGC (INTEGER NCID, INTEGER VARID,
     +                   INTEGER START(*), INTEGER COUNT(*),
     +                   INTEGER STRIDE(*), INTEGER IMAP(*),
     +                   CHARACTER*(*) STRING, INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVPTG} and @code{NCVPGC}, for
writing a generalized hyperslab of values into a netCDF variable.  
The first writes
numeric values into a variable of numeric type, and the second 
writes character values into a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be
written.  The indices are relative to 1, so for example, the first data
value of a variable would have index @code{(1, 1, @dots{}, 1)}.  The
size of @code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for writing the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
written.  To write a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a
count of the number of records to write.

@item STRIDE
A vector of integers specifying,
for each dimension,
the interval between the accessed values of a netCDF variable or the value
@code{0}.
The size of the vector shall be at least the number of dimensions of the
associated
netCDF variable and its elements shall correspond, in order, to the
variable's dimensions.
A value of 1 accesses adjacent values of the netCDF variable 
in the corresponding dimension;
a value of 2 accesses every other value of the netCDF variable in the
corresponding dimension; and so on.
An @code{0} argument obtains the default behavior in which
adjacent values are accessed along each dimension.

@item IMAP
A vector of long integers specifying,
for each dimension,
how data values associated with a 
netCDF variable are arranged in memory or the value @code{0}.
The offset, in bytes, from the memory location pointed to by the @code{value}
argument to a particular datum is given by the
inner product of the index mapping vector with the (origin-0) coordinates of 
the datum.
(The @dfn{inner product} of two vectors [x1, x2, @dots{}, xn] and
[y1, y2, @dots{}, yn] is just x1*y1 + x2*y2 + @dots{} + xn*yn.)
The vector may contain negative values if the
@code{value} argument is appropriately specified.
A @code{0} argument obtains the default behavior in
which the memory-resident values are assumed to have the same structure as the 
associated netCDF variable.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVPTG}, the block of data values to be written.  The order in
which the data will be written from the specified hyperslab is with the
first dimension of the generalized hyperslab varying fastest (like the 
ordinary FORTRAN convention).
The data may be of a type corresponding to any of the netCDF types
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but
must be appropriate for the type of the netCDF variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
whether the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVPGC}, the characters to be written.  The order in which the
characters will be written to the netCDF variable
is with the
first dimension 
of the generalized hyperslab
varying fastest (like the FORTRAN convention).
The data
may be of a type corresponding to the netCDF types @code{NCCHAR} or
@code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVPTG
Here is an example using @code{NCVPTG} to add or change every other
value in each dimension
of the variable named @code{rh} to @code{0.5} in an existing
netCDF file named @file{foo.nc}.
Values are taken, using the same dimensional strides, from a 2-parameter
array whose dimensions
are the reverse of the netCDF variable.
For simplicity in this example, we
assume that we know that @code{rh} is dimensioned with @code{lon},
@code{lat}, and @code{time}, and that there are ten @code{lon} values, five
@code{lat} values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3)         ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  START(NDIMS), COUNT(NDIMS),
     +         STRIDE(NDIMS), IMAP(NDIMS)  ! generalized hyperslab
      DOUBLE DATA(2, TIMES, LATS, LONS)    ! rh is second parameter
      DATA START /1, 1, 1/        ! start at first value
      DATA COUNT /LONS, LATS, TIMES/
      DATA STRIDE /2, 2, 2/
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)   ! get ID
      DO 10 ILON = 1, LONGS, STRIDE(1)
         DO 10 ILAT = 1, LATS, STRIDE(2)
            DO 10 ITIME = 1, TIMES, STRIDE(3)
               DATA(2, ITIME, ILAT, ILON) = 0.5
   10 CONTINUE
      IMAP(3) = 8*2*2   ! every other point of vector of 2-doubles
      IMAP(2) = IMAP(3)*(1+(TIMES-1)/STRIDE(3))*2
      IMAP(1) = IMAP(2)*(1+(LATS-1)/STRIDE(2))*2
      CALL NCVPTG (NCID, RHID, START, COUNT, STRIDE, IMAP, 
     +             DATA(2,1,1,1), RCODE)
@end group
@end example

@page
@node ncrecput, ncvarget1 and NCVGT1, ncvarputg NCVPTG and NCVPGC, Variables
@section Put a Record

@cindex record I/O
@cindex writing a record
The function @code{ncrecput} writes a multi-variable record of values
(or part of a record of values) into the record variables of an open
netCDF file.  The record is specified by giving a record number.  The
values to be written are specified by an array of pointers, one for each
record variable, to blocks of values.  Each block of values should be of
the appropriate size and type for a record's worth of data for the
corresponding record variable.  Each such pointer must be either NULL,
to indicate that no data is to be written for that variable, or must
point to an entire record's worth of data of the appropriate type for
the corresponding record variable.  The values for each record variable are assumed to be ordered with the
last dimension varying fastest.  The netCDF file must be in data mode.

The @code{ncrecput} function is not strictly necessary, since the same
data may be written with a sequence of calls to @code{ncvarput}, one for
each record variable for which a non-NULL pointer is specified.  This
function is provided in the C interface for convenience only; no
corresponding Fortran interface is available, so Fortran users should
use multiple calls to @code{NCVPT} or @code{NCVPTC} instead.

To use @code{ncrecput} properly, you must know the number, order, and
types of record variables in the netCDF file, information that can be
determined with a call to @code{ncrecinq}.  If your assumptions about
the number, order, or types of record variables in the file is
incorrect, calling this function may lead to incorrect results or even a
segmentation violation.  @strong{Warning: neither the compiler nor the
netCDF software can detect errors with the pointer array argument to
@code{ncrecput}.}

In case of a detected error, @code{ncrecput} returns -1.  Possible
causes of detectable errors include:
@itemize @bullet
@item
The specified record number is less than zero.

@item
The specified netCDF file is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncrecput
@unnumberedsubsec ncrecput:  C Interface
@example
int ncrecput(int ncid, long recnum, const void *datap[]);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or
@code{nccreate}.

@cindex appending data
@item recnum
Record number, specifying the value of the unlimited dimension for which
data is to be written.  The first record is record number @code{0}.
Note that if you specify a value for @code{recnum} that is larger than
the current size of the unlimited dimension, intervening records will be
written with fill values before the data is written in the specified
record, unless @code{ncsetfill} has been called to specify no
prefilling.

@item datap
Array of pointers to blocks of data values to be written, one for each
record variable.  @code{datap[i]}, if non-NULL, must point to an entire
record's worth of data for the @code{i}-th record variable.  For NULL
pointers, no data will be written for the corresponding record
variables.  This permits you to specify an arbitrary subset of record
variables.  The data pointed to should be of the appropriate type for
each record variable.  @strong{Warning: neither the compiler nor the
netCDF software can detect whether the wrong type of data is used.}
@end table

@findex ncrecput
Here is an example using @code{ncrecput} to write the value of a C
struct into a netCDF file with a single call.  This example assumes that
record variables of the appropriate shapes and types have previously
been created in the netCDF file.
@example 
@group
#include "netcdf.h"
   @dots{} 
    static struct @{
    char city[20];
    long date;
    float lat;
    float lon;
    float precip[24];           /* hourly precipitation */
    @} rec = @{
        "Pocatello", 
        930228, 
        42.92, 
        -112.60, 
        @{0,0,.1,.2,.2,.3,.2,0,0,0,0,0,0,0,0,0,.3,1.1,0,0,0,0,0,0@}
    @};

    int ncid;                   /* id of open netcdf file */
    long recnum;                /* number of record to write */
    void *datap[5];             /* array of address pointers for record
vars */
    @dots{}
    datap[0] = &rec.city[0];
    datap[1] = &rec.date;
    datap[2] = &rec.lat;
    datap[3] = &rec.lon;
    datap[4] = &rec.precip[0];

    ncrecput(ncid, recnum, datap);  /* instead of 5 calls to ncvarget */
@end group
@end example

@page
@node ncvarget1 and NCVGT1, ncvarget and NCVGT(C), ncrecput, Variables
@section Read a Single Data Value

@cindex getting variable data
@cindex reading data
@findex ncvarget1
@findex NCVGT1
@findex NCVG1C
The function @code{ncvarget1} (or @code{NCVGT1} or @code{NCVG1C} for
FORTRAN) gets a single data value from a variable of an open netCDF file
that is in data mode.  Inputs are the netCDF ID, the variable ID, a
multidimensional index that specifies which value to get, and the
address of a location into which the data value will be read.

In case of an error, @code{ncvarget1} returns -1; @code{NCVGT1} returns
a nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified indices were out of range for the dimensionality of the
specified variable.  For example, a negative index or an index that is
larger than the corresponding dimension size will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarget1
@unnumberedsubsec ncvarget1:  C Interface
@example
int ncvarget1(int ncid, int varid, const long mindex[], void *value);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or
@code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item mindex
The multidimensional index of the the data value to be read.  The
indices are relative to 0, so for example, the first data value of a
two-dimensional variable would have index @code{(0,0)}.  The elements of
@code{mindex} must correspond to the variable's dimensions.  Hence, if
the variable is a record variable, the first index is the record number.

@item value
Pointer to the location into which the data value is read.  The pointer
is declared to be of the type @code{void *} because it can point to data
of any of the basic netCDF types.  The data should be of the appropriate
type for the netCDF variable.  @strong{Warning: neither the compiler nor
the netCDF software can detect whether the wrong type for the data value
is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarget1
Here is an example using @code{ncvarget1} to get the @code{(1,2,3)}
element of the variable named @code{rh} in an existing netCDF file named
@file{foo.nc}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, so we want to get the value of @code{rh} that corresponds to
the second @code{time} value, the third @code{lat} value, and the fourth
@code{lon} value:
@example 
@group
#include "netcdf.h"
   @dots{} 
int ncid;                              /* netCDF ID */ 
int rh_id;                             /* variable ID */ 
static long rh_index[] = @{1, 2, 3@};  /* where to get value from */ 
double rh_val;                         /* where to put it */
   @dots{} 
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
ncvarget1(ncid, rh_id, rh_index, (void *) &rh_val);
@end group
@end example

@findex NCVGT1
@unnumberedsubsec NCVGT1:  FORTRAN Interface
@example
      SUBROUTINE NCVGT1 (INTEGER NCID, INTEGER VARID,
     + INTEGER MINDEX(*), @var{type} VALUE,
     + INTEGER RCODE)

      SUBROUTINE NCVG1C (INTEGER NCID, INTEGER VARID,
     + INTEGER MINDEX(*), CHARACTER CHVAL,
     + INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCVGT1} and @code{NCVG1C}, for
reading a single value from a variable.  The first reads a numeric value
in a variable of numeric type, and the second reads a character value in
a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code

@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or
@code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item MINDEX
The multidimensional index of the the data value to be read.  The
indices are relative to 1, so for example, the first data value of a
two-dimensional variable has index @code{(1,1)}.  The elements of
@code{mindex} correspond to the variable's dimensions.  Hence, if the
variable is a record variable, the last index is the record number.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUE
For @code{NCVGT1}, the location into which the data value will be read.
The data may be of a type corresponding to any of the netCDF types
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, or @code{NCDOUBLE}, but
must be appropriate for the type of the netCDF variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
whether the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item CHVAL
For @code{NCVG1C}, the location into which the data value will be read.
This should be of a type character, corresponding to the netCDF types
@code{NCCHAR} or @code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVGT1
Here is an example using @code{NCVGT1} to get the @code{(4,3,2)} element
of the variable named @code{rh} in an existing netCDF file named
@file{foo.nc}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{lon}, @code{lat}, and
@code{time}, so we want to get the value of @code{rh} that corresponds
to the fourth @code{lon} value, the third @code{lat} value, and the
second @code{time} value:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER NCID, RCODE
      INTEGER RHID ! variable ID
      INTEGER RHINDX(3) ! where to get value
      DOUBLE PRECISION RHVAL ! put it here
      DATA RHINDX /4, 3, 2/
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
      CALL NCVGT1 (NCID, RHID, RHINDX, RHVAL, RCODE)
@end group
@end example

@page
@node ncvarget and NCVGT(C), ncvargetg NCVGTG and NCVGGC, ncvarget1 and NCVGT1, Variables
@section Read a Hyperslab of Values

@cindex putting variable data
@cindex reading data
@cindex hyperslab access
@findex ncvarget
@findex NCVGT
@findex NCVGTC
The function @code{ncvarget} (or @code{NCVGT} or @code{NCVGTC} for
FORTRAN) reads a hyperslab of values from a netCDF variable of an open
netCDF file.  The hyperslab is specified by giving a corner and a vector
of edge lengths.  The values are read into consecutive locations with
the last (or first for FORTRAN) dimension of the hyperslab varying
fastest.  The netCDF file must be in data mode.

In case of an error, @code{ncvarget} returns -1; @code{NCVGT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths added to the specified corner would have
referenced data out of range for the dimensionality of the specified
variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarget
@unnumberedsubsec ncvarget:  C Interface
@example
int ncvarget(int ncid, int varid, const long start[], const long count[],
             void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or
@code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of long integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be read
from.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for reading the data values.

@item count
A vector of long integers specifying the multidimensional edge lengths
from the corner of the hyperslab where the first of the data values will
be read.  To read a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to read.

@item value
Pointer to the first of the locations into which the data values will be
read.  The order in which the data will be read from the netCDF variable
is with the last dimension of the specified hyperslab varying fastest.
The pointer is declared to be of the type @code{void *} because it can
point to data of any of the basic netCDF types.  The data should be of
the appropriate type for the netCDF variable.  @strong{Warning: neither
the compiler nor the netCDF software can detect whether the wrong type
of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvarget
Here is an example using @code{ncvarget} to read all the values of the
variable named @code{rh} from an existing netCDF file named
@file{foo.nc}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{time}, @code{lat}, and
@code{lon}, and that there are three @code{time} values, five @code{lat}
values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{} #define TIMES 3 #define LATS 5 #define LONS 10 int ncid; /*
netCDF ID */ int rh_id; /* variable ID */ static long start[] = @{0, 0,
0@}; /* start at first value */ static long count[] = @{TIMES, LATS,
LONS@}; double rh_vals[TIMES*LATS*LONS]; /* array to hold values */
   @dots{} ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{} rh_id = ncvarid (ncid, "rh");
   @dots{} /* read hyperslab of values from netCDF variable */
ncvarget(ncid, rh_id, start, count, (void *) rh_vals);
@end group
@end example

@findex NCVGT
@findex NCVGTC
@unnumberedsubsec NCVGT, NCVGTC:  FORTRAN Interface
@example
@group
      SUBROUTINE NCVGT (INTEGER NCID, INTEGER VARID,
     + INTEGER START(*), INTEGER COUNT(*),
     + @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVGTC(INTEGER NCID, INTEGER VARID,
     + INTEGER START(*), INTEGER COUNTS(*),
     + CHARACTER*(*) STRING, INTEGER LENSTR,
     + INTEGER RCODE)
@end group
@end example

There are two FORTRAN subroutines, @code{NCVGT} and @code{NCVGTC}, for
reading a hyperslab of values from a netCDF variable.  The first reads
numeric values from a variable of numeric type, and the second reads
character values from a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or
@code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the corner
of the hyperslab where the first of the data values will be read.  The
indices are relative to 1, so for example, the first data value of a
variable would have index @code{(1, 1, @dots{}, 1)}.  The size of
@code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for reading the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
read.  To read a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a count
of the number of records to read.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVGT}, the locations into which the data values will be read.
The order in which the data will be read from the netCDF variable is
with the first dimension of the specified hyperslab varying fastest
(like the ordinary FORTRAN convention).  The data may be of a type
corresponding to any of the netCDF types @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, or @code{NCDOUBLE}, but must be appropriate for the type
of the netCDF variable.  @strong{Warning: neither the compiler nor the
netCDF software can detect whether the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVGTC}, the character string into which the character data
will be read.  The order in which the characters will be read from the
netCDF variable is with the first dimension of the specified hyperslab
varying fastest (like the FORTRAN convention).  The data may be of a
type corresponding to the netCDF types @code{NCCHAR} or @code{NCBYTE}.

@item LENSTR
For @code{NCVGTC}, the total declared length (in characters) of the
@code{STRING} argument.  This should be at least as large as the product
of the elements of the @code{COUNT} vector.  Note that this is not
necessarily the same as the value returned by the FORTRAN @code{LEN}
function, because an array argument may be provided.  @code{NCVGTC} will
check to make sure the requested data will fit in @code{LENSTR}
characters.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVGT
Here is an example using @code{NCVGT} to read all the values of the
variable named @code{rh} from an existing netCDF file named
@file{foo.nc}.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{lon}, @code{lat}, and
@code{time}, and that there are ten @code{lon} values, five @code{lat}
values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3) ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER NCID, RCODE
      INTEGER RHID ! variable ID
      INTEGER START(NDIMS), COUNT(NDIMS) ! hyperslab
      DOUBLE RHVALS(LONS, LATS, TIMES)
      DATA START /1, 1, 1/ ! start at first value
      DATA COUNT /LONS, LATS, TIMES/
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
      CALL NCVGT (NCID, RHID, START, COUNT, RHVALS, RCODE)
@end group
@end example

@page
@node ncvargetg NCVGTG and NCVGGC, ncrecget, ncvarget and NCVGT(C), Variables
@section Read a Generalized Hyperslab of Values

@cindex putting variable data
@cindex reading data
@cindex generalized hyperslab access
@findex ncvargetg
@findex NCVGTG
@findex NCVGGC
The function @code{ncvargetg} (or @code{NCVGTG} or @code{NCVGGC} for
FORTRAN) reads a generalized hyperslab of values from a netCDF variable
of an open netCDF file.  The generalized hyperslab is specified by
giving a corner, a vector of edge lengths, a stride vector, and an index
mapping vector.  The values are read with the last (or first for
FORTRAN) dimension of the generalized hyperslab varying fastest.  The
netCDF file must be in data mode.

In case of an error, @code{ncvargetg} returns -1; @code{NCVGTG} and
@code{NCVGGC} return a nonzero value in @code{rcode}.  Possible causes
of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified corner indices were out of range for the dimensionality of
the specified variable.  For example, a negative index or an index that
is larger than the corresponding dimension size will cause an error.

@item
The specified edge lengths and strides added to the specified corner
would have referenced data out of range for the dimensionality of the
specified variable.  For example, an edge length that is larger than the
corresponding dimension size minus the corner index will cause an error,
as will accessing two or more points using a stride that is greater than
the size of the netCDF variable in the corresponding dimension.

@item
A non-positive stride.

@item
The specified netCDF is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvargetg
@unnumberedsubsec ncvargetg:  C Interface
@example
int ncvargetg(int ncid, int varid, const long start[], const long count[],
              const long stride[], const long imap[], void *values);
@end example

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or
@code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item start
A vector of long integers specifying the multidimensional index of the
corner of the hyperslab where the first of the data values will be read
from.  The indices are relative to 0, so for example, the first data
value of a variable would have index @code{(0, 0, @dots{}, 0)}.  The
size of @code{start} must be the same as the number of dimensions of the
specified variable.  The elements of @code{start} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the first index would correspond to the starting record number
for reading the data values.

@item count
A vector of long integers specifying the multidimensional edge lengths
from the corner of the hyperslab where the first of the data values will
be read.  To read a single value, for example, specify @code{count} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{count} is the number of
dimensions of the specified variable.  The elements of @code{count}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the first element of @code{count} corresponds to a
count of the number of records to read.

@item stride
A vector of long integers specifying, for each dimension, the interval
between the accessed values of a netCDF variable.  The size of the
vector shall be at least the number of dimensions of the associated
netCDF variable and its elements shall correspond, in order, to the
variable's dimensions.  A value of 1 accesses adjacent values of the
netCDF variable in the corresponding dimension; a value of 2 accesses
every other value of the netCDF variable in the corresponding dimension;
and so on.  A @code{NULL} stride argument obtains the default behavior
in which adjacent values are accessed along each dimension.

@item imap
A vector of long integers specifying, for each dimension, how data
values associated with a netCDF variable are arranged in memory.  The
offset, in bytes, from the memory location pointed to by the
@code{value} argument to a particular datum is given by the inner
product of the index mapping vector with the coordinates of the datum.
(The @dfn{inner product} of two vectors [x0, x1, @dots{}, xn] and [y0,
y1, @dots{}, yn] is just x0*y0 + x1*y1 + @dots{} + xn*yn.)  The vector
may contain negative values if the @code{value} argument is
appropriately specified.  A @code{NULL} argument obtains the default
behavior in which the memory-resident values are assumed to have the
same structure as the associated netCDF variable.

@item value
Pointer to the first of the locations into which the data values will be
read.  The order in which the data will be read from the netCDF variable
is with the last dimension of the generalized hyperslab varying fastest.
The pointer is declared to be of the type @code{void *} because it can
point to data of any of the basic netCDF types.  The data should be of
the appropriate type for the netCDF variable.  @strong{Warning: neither
the compiler nor the netCDF software can detect whether the wrong type
of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncvargetg
Here is an example using @code{ncvargetg} to read every other value in
each dimension of the variable named @code{rh} from an existing netCDF
file named @file{foo.nc}.  Values are assigned, using the same
dimensional strides, to points in a 3-dimensional array of structures
whose dimensions are the reverse of the netCDF variable.  For simplicity
in this example, we assume that we know that @code{rh} is dimensioned
with @code{time}, @code{lat}, and @code{lon}, and that there are three
@code{time} values, five @code{lat} values, and ten @code{lon} values.
@example 
@group
#include "netcdf.h"
   @dots{}
#define TIMES 3
#define LATS  5
#define LONS 10
int ncid;                           /* netCDF ID */
int rh_id;                          /* variable ID */
static long start[] = @{0, 0, 0@};  /* start at first value */
static long count[] = @{TIMES, LATS, LONS@};
static long stride[] = @{2, 2, 2@}; /* every other value */
long imap[3];                       /* set to reverse of variable */
struct datum @{
    int dummy;                      /* to illustrate mapping vector usage */
    double rh_val;                  /* actual value to be read */
@}      data[TIMES][LATS][LONS];    /* array to hold values */
   @dots{}
   ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
   rh_id = ncvarid (ncid, "rh");
   @dots{}
   /* access every `stride' in-memory value using reversed dimensions */
   imap[0] = stride[2]*sizeof(struct datum);
   imap[1] = stride[1]*(1+(LONS-1)/stride[0])*imap[0];
   imap[2] = stride[0]*(1+(LATS-1)/stride[1])*imap[1];
   /* read generalized hyperslab of values from netCDF variable */
   ncvargetg(ncid, rh_id, start, count, stride, imap, (void*)&data[0][0][0].rh_val);
   @dots{}
@end group
@end example

@findex NCVGTG
@findex NCVGGC
@unnumberedsubsec NCVGTG, NCVGGC:  FORTRAN Interface
@example
@group
      SUBROUTINE NCVGTG (INTEGER NCID, INTEGER VARID,
     + INTEGER START(*), INTEGER COUNT(*),
     + INTEGER STRIDE(*), INTEGER IMAP(*),
     + @var{type} VALUES, INTEGER RCODE)

      SUBROUTINE NCVGGC (INTEGER NCID, INTEGER VARID,
     + INTEGER START(*), INTEGER COUNT(*),
     + INTEGER STRIDE(*), INTEGER IMAP(*),
     + CHARACTER*(*) STRING, INTEGER RCODE)
@end group
@end example

There are two FORTRAN subroutines, @code{NCVGTG} and @code{NCVGGC}, for
reading a generalized hyperslab of values from a netCDF variable.  The
first reads numeric values from a variable of numeric type, and the
second reads character values from a variable of character type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or
@code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item START
A vector of integers specifying the multidimensional index of the corner
of the hyperslab where the first of the data values will be read.  The
indices are relative to 1, so for example, the first data value of a
variable would have index @code{(1, 1, @dots{}, 1)}.  The size of
@code{START} must be the same as the number of dimensions of the
specified variable.  The elements of @code{START} must correspond to the
variable's dimensions in order.  Hence, if the variable is a record
variable, the last index would correspond to the starting record number
for reading the data values.

@item COUNT
A vector of integers specifying the multidimensional edge lengths from
the corner of the hyperslab where the first of the data values will be
read.  To read a single value, for example, specify @code{COUNT} as
@code{(1, 1, @dots{}, 1)}.  The size of @code{COUNT} is the number of
dimensions of the specified variable.  The elements of @code{COUNT}
correspond to the variable's dimensions.  Hence, if the variable is a
record variable, the last element of @code{COUNT} corresponds to a count
of the number of records to read.

@item STRIDE
A vector of integers specifying, for each dimension, the interval
between the accessed values of a netCDF variable or the value @code{0}.
The size of the vector shall be at least the number of dimensions of the
associated netCDF variable and its elements shall correspond, in order,
to the variable's dimensions.  A value of 1 accesses adjacent values of
the netCDF variable in the corresponding dimension; a value of 2
accesses every other value of the netCDF variable in the corresponding
dimension; and so on.  An @code{0} argument obtains the default behavior
in which adjacent values are accessed along each dimension.

@item IMAP
A vector of long integers specifying, for each dimension, how data
values associated with a netCDF variable are arranged in memory or the
value @code{0}.  The offset, in bytes, from the memory location pointed
to by the @code{value} argument to a particular datum is given by the
inner product of the index mapping vector with the (origin-0)
coordinates of the datum.  (The @dfn{inner product} of two vectors [x1,
x2, @dots{}, xn] and [y1, y2, @dots{}, yn] is just x1*y1 + x2*y2 +
@dots{} + xn*yn.)  The vector may contain negative values if the
@code{value} argument is appropriately specified.  A @code{0} argument
obtains the default behavior in which the memory-resident values are
assumed to have the same structure as the associated netCDF variable.

@cindex data types
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item VALUES
For @code{NCVGTG}, the locations into which the data values will be
read.  The order in which the data will be read from the netCDF variable
is with the first dimension of the generalized hyperslab varying fastest
(like the ordinary FORTRAN convention).  The data may be of a type
corresponding to any of the netCDF types @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, or @code{NCDOUBLE}, but must be appropriate for the type
of the netCDF variable.  @strong{Warning: neither the compiler nor the
netCDF software can detect whether the wrong type of data is used.}

@cindex data types
@vindex NCCHAR
@vindex NCBYTE
@item STRING
For @code{NCVGGC}, the character string into which the character data
will be read.  The order in which the characters will be read from the
netCDF variable is with the first dimension of the generalized hyperslab
varying fastest (like the FORTRAN convention).  The data may be of a
type corresponding to the netCDF types @code{NCCHAR} or @code{NCBYTE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVGTG
Here is an example using @code{NCVGTG} to read every other value in each
dimension of the variable named @code{rh} from an existing netCDF file
named @file{foo.nc}.  Values are assigned, using the same dimensional
strides, to a 2-parameter array whose dimensions are the reverse of the
netCDF variable.  For simplicity in this example, we assume that we know
that @code{rh} is dimensioned with @code{lon}, @code{lat}, and
@code{time}, and that there are ten @code{lon} values, five @code{lat}
values, and three @code{time} values.
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (NDIMS=3) ! number of dimensions
      PARAMETER (TIMES=3, LATS=5, LONS=10) ! dimension sizes
      INTEGER NCID, RCODE
      INTEGER RHID ! variable ID
      INTEGER START(NDIMS), COUNT(NDIMS)
     + STRIDE(NDIMS), IMAP(NDIMS) ! generalized hyperslab
      DOUBLE DATA(2, TIMES, LATS, LONS) ! rh is second parameter
      DATA START /1, 1, 1/ ! start at first value
      DATA COUNT /LONS, LATS, TIMES/
      DATA STRIDE /2, 2, 2/
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
      IMAP(3) = 8*2*2 ! every other point of vector of 2-doubles
      IMAP(2) = IMAP(3)*(1+(TIMES-1)/STRIDE(3))*2
      IMAP(1) = IMAP(2)*(1+(LATS-1)/STRIDE(2))*2
      CALL NCVGTG (NCID, RHID, START, COUNT, STRIDE, IMAP,
     + DATA(2,1,1,1), RCODE)
@end group
@end example

@page
@node ncrecget, Character String I/O, ncvargetg NCVGTG and NCVGGC, Variables
@section Get a Record

@cindex record I/O
@cindex reading a record
The function @code{ncrecget} reads a multi-variable record of values (or
part of a record of values) from the record variables of an open netCDF
file.  The record is specified by giving a record number.  The locations
into which the data will be read are specified by an array of pointers,
one for each record variable, to blocks of data.  Each block of data
should be of the appropriate size and type for a record's worth of data
for the corresponding record variable.  Each such pointer must be either
NULL, to indicate that no data is to be written for that variable, or
must point to space for an entire record's worth of data of the
appropriate type for the corresponding record variable.  The values for
each record variable will be ordered with the last dimension varying
fastest.  The netCDF file must be in data mode.

The @code{ncrecget} function is not strictly necessary, since the same
data may be read with a sequence of calls to @code{ncvarget}, one for
each record variable for which a non-NULL pointer is specified.  This
function is provided in the C interface for convenience only; no
corresponding Fortran interface is available, so Fortran users should
use multiple calls to @code{NCVGT} or @code{NCVGTC} instead.

To use @code{ncrecget} properly, you must know the number, order, and
types of record variables in the netCDF file, information that can be
determined with a call to @code{ncrecinq}.  If your assumptions about
the number, order, or types of record variables in the file is
incorrect, calling this function may lead to incorrect results or even a
segmentation violation.  @strong{Warning: neither the compiler nor the
netCDF software can detect errors with the pointer array argument to
@code{ncrecget}.}

In case of a detected error, @code{ncrecget} returns -1.  Possible
causes of detectable errors include:
@itemize @bullet
@item
The specified record number is less than zero.

@item
The specified netCDF file is in define mode rather than data mode.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncrecget
@unnumberedsubsec ncrecget:  C Interface
@example
int ncrecget(int ncid, long recnum, void *datap[]);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or
@code{nccreate}.

@item recnum
Record number, specifying the value of the unlimited dimension for which
data is to be read.  The first record is record number @code{0}.

@item datap
Array of pointers to blocks of data into which the requested values will
be read, one for each record variable.  @code{datap[i]}, if non-NULL,
must point to enough space to hold an entire record's worth of data for
the @code{i}-th record variable.  For NULL pointers, no data will be
read for the corresponding record variables.  This permits you to
specify an arbitrary subset of record variables.  The data pointed to
should be of the appropriate type for each record variable.
@strong{Warning: neither the compiler nor the netCDF software can detect
whether the wrong type of data is used.}
@end table

@findex ncrecget
Here is an example using @code{ncrecget} to read values into several C
arrays and scalars with a single call.  This example assumes that record
variables of the appropriate shapes and types have previously been
created in the netCDF file.
@example 
@group
#include "netcdf.h"
   @dots{} 
    static struct @{
    char city[20];
    long date;
    float lat;
    float lon;
    float precip[24];
    @} rec[10];

    int ncid;           /* id of open netcdf file */
    long i;             /* number of record to read */
    void *datap[5];     /* array of address pointers for record vars */
    @dots{}

    /* Get first 10 records of data */
    for(i=0; i<10; i++) @{
        datap[0] = &rec[i].city[0];
        datap[1] = &rec[i].date;
        datap[2] = &rec[i].lat;
        datap[3] = &rec[i].lon;
        datap[4] = &rec[i].precip[0];
        ncrecget(ncid, i, datap);  /* instead of 5 calls to ncvarget */
    @}
@end group
@end example

@page
@node Character String I/O, Missing Values, ncrecget, Variables
@section Reading and Writing Character String Values

@cindex putting character string data
@cindex writing character string data
@cindex getting character string data
@cindex reading character string data
@cindex character string data
@cindex character strings
@cindex writing data
@cindex hyperslab access
@cindex fixed-length character strings
@cindex variable-length strings
@findex ncvarput
@findex NCVPT
@findex NCVPTC
@findex NCVPGC
@cindex reading data
@findex ncvarget
@findex NCVGT
@findex NCVGTC
@findex NCVGGC

Character strings are not a primitive netCDF data type, in part because
FORTRAN does not support the abstraction of variable-length character
strings (the FORTRAN @code{LEN} function returns the static length of a
character string, not its dynamic length).  As a result, a character
string cannot be written or read as a single object in the netCDF
interface.  Instead, a character string must be treated as an array of
characters, and hyperslab access must be used to read and write
character strings as variable data in netCDF files.  Furthermore,
variable-length strings are not supported by the netCDF interface except
by convention; for example, you may treat a null (zero) byte as
terminating a character string, but you must explicitly specify the
length of strings to be read from and written to netCDF variables.

@cindex character-string attributes
@cindex attribute length
Character strings as attribute values are easier to use, since the
strings are treated as a single unit for access; no hyperslab access is
necessary (or possible) for attributes.  However, the value of a
character-string attribute is still an array of characters with an
explicit length that must be specified when the attribute is defined.

@cindex character-position dimension
@cindex netCDF disk representation
@cindex netCDF file size
@cindex variable shape
When you define a variable that will have character-string values, use a
@var{character-position dimension} as the most quickly varying dimension
for the variable (the last dimension for the variable in C, the first in
FORTRAN).  The size of the character-position dimension will be the
maximum string length of any value to be stored in the character-string
variable.  Space for maximum-size strings will be allocated in the disk
representation of character-string variables whether you use the space
or not.  If two or more variables have the same maximum length, the same
character-position dimension may be used in defining the variable shapes.

@cindex hyperslab access
@cindex hyperslab corner
@cindex hyperslab edge lengths
To write a character-string value into a character-string variable, use
hyperslab access.  This requires that you specify both a corner and a
vector of edge lengths.  The character-position dimension at the corner
should be zero (one for FORTRAN).  If the length of the string to be
written is @code{n}, then the vector of edge lengths will specify
@code{n} in the character-position dimension, and one for all the other
dimensions, i.e., @code{(1, 1, @dots{}, 1, n)} or @code{(n, 1, 1, @dots{},
1)} in FORTRAN.

@unnumberedsubsec C Interface

@cindex fixed-size strings
@cindex null byte
@cindex netCDF file size
@cindex variable-length strings
In C, fixed-size strings may be written to a netCDF file without the
terminating null byte, to save space.  Variable-length strings should be
written @emph{with} a terminating null byte so that the intended length
of the string can be determined when it is later read.

@findex ncvarput
@findex ncopen
@findex ncredef
@findex ncdimdef
@findex ncvardef
@findex ncendef
@vindex NC_CHAR
Here is an example that defines a record variable, @code{tx}, for
character strings and stores a character-string value into the third
record using @code{ncvarput}.  In this example, we assume the string
variable and data are to be added to an existing netCDF file named
@file{foo.nc} that already has an unlimited record dimension @code{time}.

@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;            /* netCDF ID */
int  chid;            /* dimension ID for char positions */
int  timeid;          /* dimension ID for record dimension */
int  tx_id;           /* variable ID */
#define TDIMS 2       /* dimensionality of tx variable */
int tx_dims[TDIMS];   /* variable shape */
long tx_start[TDIMS];
long tx_count[TDIMS];
static char tx_val[] =
        "example string"; /* string to be put */
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
ncredef(ncid);       /* enter define mode */
   @dots{}
/* define character-position dimension for strings of max length 40 */
chid = ncdimdef(ncid, "chid", 40L);
   @dots{}
/* define a character-string variable */
tx_dims[0] = timeid;
tx_dims[1] = chid;    /* character-position dimension last */
tx_id = ncvardef (ncid, "tx", NC_CHAR, TDIMS, tx_dims);
   @dots{}
ncendef(ncid);       /* leave define mode */
   @dots{}
/* write tx_val into tx netCDF variable in record 3 */
tx_start[0] = 3;      /* record number to write */
tx_start[1] = 0;      /* start at beginning of variable */
tx_count[0] = 1;      /* only write one record */
tx_count[1] = strlen(tx_val) + 1;  /* number of chars to write */
ncvarput(ncid, tx_id, tx_start, tx_count, (void *) tx_val);
@end group
@end example


@unnumberedsubsec FORTRAN Interface

@cindex fixed-size strings
@cindex null byte
@cindex netCDF file size
@cindex variable-length strings
In FORTRAN, fixed-size strings may be written to a netCDF file without a
terminating character, to save space.  Variable-length strings
should follow the C convention of writing strings with a terminating
null byte so that the intended length of the string can be determined
when it is later read by either C or FORTRAN programs.

@cindex character-string values
@cindex numeric values
@cindex string length, actual
@cindex string length, declared
@cindex character-position dimension
@findex NCVPTC
@findex NCVPGC
@findex NCVGTC
@findex NCVGGC
The FORTRAN interface for reading and writing strings requires the use
of different subroutines for accessing string values and numeric values,
because standard FORTRAN does not permit the same formal parameter to be
used for both character values and numeric values.  An additional
argument, specifying the declared length of the character string passed
as a value, is required for @code{NCVPTC} and @code{NCVGTC}.  The actual
length of the string is specified as the value of the hyperslab
edge-length vector corresponding to the character-position dimension.

@findex NCOPN
@findex NCREDF
@findex NCDDEF
@findex NCENDF
@findex NCVPTC
@findex NCVDEF
@vindex NCCHAR
Here is an example that defines a record variable, @code{tx}, for
character strings and stores a character-string value into the third
record using @code{NCVPTC}.  In this example, we assume the string
variable and data are to be added to an existing netCDF file named
@file{foo.nc} that already has an unlimited record dimension
@code{time}.

@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (TDIMS=2)    ! number of TX dimensions
      PARAMETER (TXLEN = 15) ! length of example string
      INTEGER  NCID, RCODE
      INTEGER  CHID          ! char position dimension id
      INTEGER  TIMEID        ! record dimension id
      INTEGER  TXID          ! variable ID
      INTEGER  TXDIMS(TDIMS) ! variable shape
      INTEGER  TSTART(TDIMS), TCOUNT(TDIMS) ! hyperslab
      CHARACTER*40 TXVAL     ! max length 40
      DATA TXVAL /'example string'/
         @dots{}
      TXVAL(TXLEN:TXLEN) = CHAR(0)   ! null terminate
         @dots{}
      NCID = NCOPN('foo.nc', NCWRITE, RCODE)
      CALL NCREDF(NCID, RCODE) ! enter define mode
         @dots{}
* define character-position dimension for strings of max length 40
      CHID = NCDDEF(NCID, "chid", 40, RCODE)
         @dots{}
* define a character-string variable
      TXDIMS[1] = CHID   ! character-position dimension first
      TXDIMS[2] = TIMEID
      TXID = NCVDEF(NCID, "tx", NCCHAR, TDIMS, TXDIMS, RCODE)
         @dots{}
      CALL NCENDF(NCID, RCODE) ! leave define mode
         @dots{}
* write txval into tx netCDF variable in record 3
      TSTART[1] = 0      ! start at beginning of variable
      TSTART[2] = 3      ! record number to write
      TCOUNT[1] = TXLEN  ! number of chars to write
      TCOUNT[2] = 1      ! only write one record
      CALL NCVPTC (NCID, TXID, TSTART, TCOUNT, TXVAL, 40, RCODE)
@end group
@end example

@page
@node Missing Values, ncvarrename and NCVREN, Character String I/O, Variables
@section Missing Values

@cindex missing values
@cindex fill values
What happens when you try to read a value that was never written in an
open netCDF file?  You might expect that this should always be an error,
and that you should get an error message or an error status returned.
You @emph{do} get an error if you try to read data from a netCDF file
that is not open for reading, if the variable ID is invalid for the
specified netCDF file, or if the specified hyperslab is not properly
within the range defined by the dimension sizes of the specified
variable.  Otherwise, reading a value that was not written returns a
special @dfn{fill value} used to fill in any missing values when a
netCDF variable is first written.

You may also ignore fill values and use the entire range of a netCDF
data type, but in this case you should make sure you write all data
values before reading them.  If you know you will be writing all
the data before reading it, you can specify that no prefilling of
variables with fill values will occur by calling @code{ncsetfill}
before writing.  This may provide a significant performance gain for
netCDF writes.

There are several reasons for using a fill value instead of an error
return for missing data.  First, the interface for hyperslab access
would necessarily be more complex and slower if information had to be
returned about whether each value read had been written.  Since data may
have been written in a different order from that in which it is later
read, it is possibile that only a few values in a block of retrieved
values were never written.  Second, it is usually preferable to delay
the detection of missing values until there is a need for the values,
since they may not be used in subsequent computations.  Finally, the use
of missing values is a common way to represent data points outside the
boundaries of irregular regions of data enclosed by a hyperslab,
making it possible to handle such data in a simpler way than would be
possible with a more compact representation that represented the
boundary explicitly.

@cindex default fill values
The default fill values for each type are defined in the include file
@file{netcdf.h} (or @file{netcdf.inc} for FORTRAN).  It is usually
better to use your own fill value instead, by defining the attribute
@code{_FillValue} for a variable before writing it.  A disadvantage of
the default fill values for floating-point and double-precision types is
that they may be defined differently for different platforms, and may be
difficult to compare with other values, since they are defined to be
right at the edge of the valid floating-point number ranges for each
machine.

Fill values are used for filling in missing data whenever a value is put
beyond the end of data that has already been written.  A default fill
value has no other special meaning, so it can be used for valid values
if you use your own fill value instead.

@cindex byte vs. character
@cindex character vs. byte
Currently the only difference between the netCDF byte and character
types is that the two types have different default fill values.  The
fill value for bytes is on the edge of the range, representing the
largest negative value for signed bytes.  The fill value for characters,
however, is the zero byte, a more useful value for detecting the end of
C character strings.

@cindex _FillValue attribute
@cindex missing_value attribute
Sometimes there is need for more than one value to represent different
kinds of missing data.  In this case, the user should use one or more
other variable attributes for the different kinds of missing data.  For
example, it might be appropriate to use @code{_FillValue} to mean that
data that was expected never appeared, but @code{missing_value} where
the creator of the data intends data to be missing, as around an
irregular region represented by a rectangular grid.

@page
@node ncvarrename and NCVREN, nctypelen and NCTLEN, Missing Values, Variables
@section Rename a Variable

@cindex renaming variables
@cindex variable name
@findex ncvarrename
@findex NCVREN
The function @code{ncvarrename} (or @code{NCVREN} for FORTRAN) changes
the name of a netCDF variable in an open netCDF.  If the new name is
longer than the old name, the netCDF must be in define mode.  You cannot
rename a variable to have the name of any existing variable.

In case of an error, @code{ncvarrename} returns -1; @code{NCVREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The new name is in use as the name of another variable.

@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncvarrename
@unnumberedsubsec ncvarrename:  C Interface
@example
int ncvarrename(int ncid, int varid, const char* name);
@end example

@cindex variable name

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID, returned from a previous call to @code{ncvardef} or
@code{ncvarid}.

@item name
New name for the specified variable.
@end table

@findex ncopen
@findex ncvarid
@findex ncredef
@findex ncendef
@findex ncvarrename
Here is an example using @code{ncvarrename} to rename the variable
@code{rh} to @code{rel_hum} in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
ncredef(ncid);  /* put in define mode to rename variable */
rh_id = ncvarid (ncid, "rh");
ncvarrename (ncid, rh_id, "rel_hum");
ncendef(ncid);  /* leave define mode */
@end group
@end example

@findex NCVREN
@unnumberedsubsec NCVREN:  FORTRAN Interface
@example
      SUBROUTINE NCVREN (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) NEWNAM, INTEGER RCODE)
@end example

@cindex variable name
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@item NEWNAM
New name for the specified variable.
@end table

@findex NCOPN
@findex NCVID
@findex NCVREN
@findex NCREDF
@findex NCENDF
Here is an example using @code{NCVREN} to rename the variable @code{rh}
to @code{rel_hum} in an existing netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF (CDFFID, RCODE)  ! enter definition mode
      RHID = NCVID (NCID, 'rh', RCODE)  ! get ID
      CALL NCVREN (NCID, RHID, 'rel_hum', RCODE)
      CALL NCENDF (CDFFID, RCODE)  ! leave definition mode
@end group
@end example

@page
@node nctypelen and NCTLEN, ncrecinq, ncvarrename and NCVREN, Variables
@section Get Number of Bytes for a Data Type

@cindex netCDF data types
@cindex data sizes
@cindex type lengths
@findex nctypelen
@findex NCTLEN
The function @code{nctypelen} (or @code{NCTLEN} for FORTRAN) returns
the number of bytes per netCDF data type.

In case of an error, @code{nctypelen} returns -1; @code{NCTLEN} returns a
nonzero value in @code{rcode}.  One possible cause of errors is:
@itemize @bullet
@item
The specified data type is not a valid netCDF data type.
@end itemize
@findex nctypelen
@unnumberedsubsec nctypelen:  C Interface
@example
int nctypelen (nc_type datatype);
@end example
@cindex attribute names
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@table @code
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.
@end table
@findex ncopen
@findex ncvarid
@findex ncvarinq
@findex nctypelen
@vindex nc_type
@vindex MAX_VAR_DIMS
Here is an example using @code{nctypelen} to determine how many bytes
are required to store a single value of the variable @code{rh} in an
existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;        /* netCDF ID */
int  rh_id;       /* variable ID */
nc_type rh_type;           /* variable type */
int rh_ndims;              /* number of dims */
int rh_dims[MAX_VAR_DIMS]; /* variable shape */
int rh_natts;              /* number of attributes */
int rhbytes;      /* number of bytes per value for "rh" */
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
/* get type.  we don't need name, since we already know it */
ncvarinq (ncid, rh_id, (char *) 0, &rh_type, &rh_ndims, rh_dims,
          &rh_natts);
rhbytes = nctypelen (rh_type);
@end group
@end example

@findex NCTLEN
@unnumberedsubsec NCTLEN:  FORTRAN Interface
@example
      INTEGER FUNCTION NCTLEN (INTEGER TYPE ,INTEGER RCODE)
@end example

@table @code

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item TYPE
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, and @code{NCDOUBLE}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCVINQ
@findex NCTLEN
@vindex MAXVDIMS
Here is an example using @code{NCTLEN} to determine how many bytes are
required to store a single value of the variable @code{rh} in an existing
netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID              ! netCDF ID
      INTEGER  RHID               ! variable ID
      CHARACTER*31 RHNAME         ! variable name
      INTEGER  RHTYPE             ! variable type
      INTEGER  RHN                ! number of dimensions
      INTEGER  RHDIMS(MAXVDIMS)   ! variable shape
      INTEGER  RHNATT             ! number of attributes
      INTEGER  RHBYTS             ! bytes per value
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)
* get type of "rh"
      CALL NCVINQ (NCID, RHID, RHNAME, RHTYPE, RHN, RHDIMS, RHNATT,
     +             RCODE)
      RHBYTS = NCTLEN (RHTYPE)
@end group
@end example

@page
@node ncrecinq,  , nctypelen and NCTLEN, Variables
@section Get Information About Record Variables

@cindex record I/O
@cindex inquiring about records
The function @code{ncrecinq} returns information about the record
variables (variables that use the unlimited dimension) in a netCDF file.
The information returned is the number of record variables, their
variable IDs, and the size (in bytes) for a record's worth of data for
each record variable.

The @code{ncrecinq} function is not strictly necessary, since the
information it returns can be computed from information returned by
@code{ncinquire}, @code{ncdiminq}, and @code{ncvarinq} functions or
their FORTRAN counterparts.  This function is provided in the C
interface for convenience only, to assist in using the C functions
@code{ncrecput} and @code{ncrecget}.

In case of an error, @code{ncrecinq} returns -1.  Possible causes of
errors include:
@itemize @bullet
@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncrecinq
@unnumberedsubsec ncrecinq:  C Interface
@example
int ncrecinq(int ncid, int* nrvars, int rvarids[], long rsizes[]);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item nrvars
Number of record variables.

@item rvarids
Returned vector of @code{nrvars} variable IDs for the record variables
in this netCDF file.  The caller must allocate enough space for a vector
of at least @code{nrvars} integers to be returned.  The maximum possible
number of variable IDs returned is given by the predefined constant
@code{MAX_NC_VARS}.  If this parameter is given as @samp{(int *) 0}, no
vector will be returned so no space to hold the record variable IDs
needs to be declared or allocated.

@item rsizes
Returned vector of @code{nrvars} sizes for the record variables in this
netCDF file.  The size of a record variable is the number of bytes
required to hold a record's worth of data, which is the product of the
non-record dimensions and the size of data type, in bytes.  The caller
must allocate enough space for a vector of at least @code{nrvars} longs
to be returned.  The maximum possible number of variable IDs returned is
given by the predefined constant @code{MAX_NC_VARS}.  If this parameter
is given as @samp{(int *) 0}, no vector will be returned so no space to
hold the record variable sizes needs to be declared or allocated.
@end table
@sp 1
Here is an example using @code{ncrecinq} to find out about the record
variables in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                     /* netCDF ID */
int  nrvars;                   /* number of record variables */
int  rvarids[MAX_NC_VARS];     /* IDs of record variables */
long rvarsizes[MAX_NC_VARS];   /* record sizes of record variables */
   @dots{}
ncid = ncopen ("foo.nc", NC_NOWRITE);
   @dots{}
ncrecinq (ncid, &nrvars, rvarids, rvarsizes);
@end group
@end example

@node Attributes, File Structure, Variables, Top
@chapter Attributes

@cindex attributes
@cindex define mode
@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex attribute values
@findex ncattname
@findex NCANAM
Attributes may be associated with each netCDF variable to specify such
properties as units, special values, maximum and minimum valid values,
scaling factors, and offsets.  Attributes for a netCDF file are
defined when the file is first created, while the netCDF file is in define
mode.  Additional attributes may be added later by reentering define
mode.  A netCDF attribute has a netCDF variable to which it is assigned,
a name, a type, a length, and a sequence of one or more values.  An
attribute is designated by its variable ID and name, except in one case
(@code{ncattname} or @code{NCANAM} in FORTRAN), where attributes are
designated by variable ID and number because their names are unknown.

@cindex data mode
@cindex define mode
@cindex attribute type
@cindex attribute length
@cindex attribute values
@cindex attribute space
The attributes associated with a variable are typically defined right
after the variable is created, while still in define mode.  The data
type, length, and value of an attribute may be changed even when in data
mode, as long as the changed attribute requires no more space than the
attribute as originally defined.

@cindex global attributes
@vindex NC_GLOBAL
@cindex define mode
@cindex data mode
It is also possible to assign attributes not associated with any
variable to the netCDF as a whole, by using the @code{NC_GLOBAL} variable
pseudo-ID.  Global attributes may be used for purposes such as providing
a title or processing history for a netCDF data set.

@cindex attribute operations
Operations supported on attributes are:
@itemize @bullet
@item
Create an attribute, given its variable ID, name, data type, length, and
value.

@item
Get attribute's data type and length from its variable ID and name.

@item
Get attribute's value from its variable ID and name.

@item
Copy attribute from one netCDF to another.

@item
Get name of attribute from its number.

@item
Rename an attribute.

@item
Delete an attribute.
@end itemize

@menu
* ncattput and NCAPT::      Create an Attribute
* ncattinq and NCAINQ::      Get Information about an Attribute
* ncattget and NCAGT(C)::      Get Attribute's Values
* ncattcopy and NCACPY::      Copy Attribute from One netCDF to Another
* ncattname and NCANAM::      Get Name of Attribute from Its Number
* ncattrename and NCAREN::      Rename an Attribute
* ncattdel and NCADEL::      Delete an Attribute
@end menu

@page
@node ncattput and NCAPT, ncattinq and NCAINQ,  , Attributes
@section Create an Attribute

@cindex creating attributes
@cindex defining attributes
@cindex variable attributes
@cindex global attributes
@findex ncattput
@findex NCAPT
@findex NCAPTC
The function @code{ncattput} (or @code{NCAPT} or @code{NCAPTC} for
FORTRAN) adds or changes a variable attribute or global attribute of an
open netCDF file.  If this attribute is new, or if the space required to
store the attribute is greater than before, the netCDF file must be in
define mode.

In case of an error, @code{ncattput} returns -1; @code{NCAPT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified netCDF type is invalid.

@item
The specified length is negative.

@item
The specified open netCDF file is in data mode and the specified
attribute would expand.

@item
The specified open netCDF file is in data mode and the specified
attribute does not already exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattput
@unnumberedsubsec ncattput:  C Interface
@example
int ncattput(int ncid, int varid, const char* name, nc_type datatype,
             int len, const void* values);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex global attributes
@vindex NC_GLOBAL
@item varid
Variable ID of the variable to which the attribute will be assigned or
@code{NC_GLOBAL} for a global attribute.

@cindex attribute names
@item name
Attribute name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@samp{_}).  Case is significant.  Attribute name conventions are
assumed by some netCDF generic applications, e.g., @code{units} as the
name for a string attribute that gives the units for a netCDF variable.
@xref{Attribute Conventions}, for examples of attribute conventions.

@cindex attribute type
@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@item datatype
One of the set of predefined netCDF data types.  The type of this
parameter, @code{nc_type}, is defined in the netCDF header file.  The
valid netCDF data types are @code{NC_BYTE}, @code{NC_CHAR},
@code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and @code{NC_DOUBLE}.

@cindex data types
@vindex NC_CHAR
@item len
Number of values provided for the attribute.  If the attribute is of type
@code{NC_CHAR}, this is one more than the string length (since the
terminating null character is stored).

@cindex attribute values
@item values
Pointer to one or more data values.  The pointer is declared to be of
the type @code{void *} because it can point to data of any of the basic
netCDF types.  The data should be of the appropriate type for the netCDF
attribute.  @strong{Warning: neither the compiler nor the netCDF
software can detect whether the wrong type of data is used.}
@end table

@findex ncopen
@findex ncvarid
@findex ncattput
@findex ncredef
@vindex NC_GLOBAL
@vindex NC_CHAR
@vindex NC_DOUBLE
@findex ncendef
Here is an example using @code{ncattput} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                         /* netCDF ID */
int  rh_id;                        /* variable ID */
static double rh_range[] = @{0.0, 100.0@};  /* attribute vals */
static char title[] = "example netCDF file";
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
ncredef(ncid);                    /* enter define mode */
rh_id = ncvarid (ncid, "rh");
   @dots{}
ncattput (ncid, rh_id, "valid_range", NC_DOUBLE, 2, rh_range);
ncattput (ncid, NC_GLOBAL, "title", NC_CHAR, strlen(title)+1,
          title);
   @dots{}
ncendef(ncid);                    /* leave define mode */
@end group
@end example

@findex NCAPT
@findex NCAPTC
@unnumberedsubsec NCAPT, NCAPTC:  FORTRAN Interface
@example
      SUBROUTINE NCAPT (INTEGER NCID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                  INTEGER ATTLEN, type VALUE,
     +                  INTEGER RCODE)

      SUBROUTINE NCAPTC (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                   INTEGER LENSTR, CHARACTER*(*) STRING,
     +                   INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCAPT} and @code{NCAPTC}, for
creating attributes.  The first is for attributes of numeric type, and
the second is for attributes of character-string type.

@cindex variable data
@cindex variable indices
@cindex variable dimensions
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID, returned from a previous call to @code{NCVDEF} or
@code{NCVID}.

@cindex attribute names
@item ATTNAM
Attribute name.  Must begin with an alphabetic character, followed by
zero or more alphanumeric characters including the underscore
(@samp{_}).  Case is significant.  Attribute name conventions are
assumed by some netCDF generic applications, e.g., @code{units} as the
name for a string attribute that gives the units for a netCDF variable.
A table of conventional attribute names is presented in the earlier
chapter on the netCDF interface.

@cindex attribute type
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item ATTYPE
One of the set of predefined netCDF data types.  The valid netCDF data
types are @code{NCBYTE}, @code{NCCHAR}, @code{NCSHORT}, @code{NCLONG},
@code{NCFLOAT}, and @code{NCDOUBLE}.

@item ATTLEN
In @code{NCAPT}, the number of numeric values provided for the
attribute.

@item VALUE
In @code{NCAPT}, an array of @code{ATTLEN} data values.  The data should
be of the appropriate type for the netCDF attribute.  @strong{Warning:
neither the compiler nor the netCDF software can detect if the wrong
type of data is used.}

@item STRING
In @code{NCAPTC}, the character-string value of the attribute.

@item LENSTR
In @code{NCAPTC}, the total declared length (in characters) of the
@code{STRING} parameter.  Note that this is not necessarily the same as
the value returned by the FORTRAN @code{LEN} function, because an array
argument may be provided.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAPT
@findex NCREDF
@vindex NCDOUBLE
@findex NCAPTC
@vindex NCGLOBAL
@vindex NCCHAR
@findex NCENDF
Here is an example using @code{NCAPT} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      DOUBLE RHRNGE(2)
      DATA RHRNGE /0.0D0, 100.0D0/
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      CALL NCREDF (NCID, RCODE)     ! enter define mode
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
         @dots{}
      CALL NCAPT (NCID, RHID, 'valid_range', NCDOUBLE, 2,
     +            RHRNGE, RCODE)
      CALL NCAPTC (NCID, NCGLOBAL, 'title', NCCHAR, 19,
     +            'example netCDF file', RCODE)
         @dots{}
      CALL NCENDF (NCID, RCODE)     ! leave define mode
@end group
@end example

@page
@node ncattinq and NCAINQ, ncattget and NCAGT(C), ncattput and NCAPT, Attributes
@section Get Information about an Attribute

@cindex attribute inquire
@cindex attribute names
@cindex variable attributes
@cindex global attributes
@findex ncattinq
@findex NCAINQ
The function @code{ncattinq} (or @code{NCAINQ} for FORTRAN) returns
information about a netCDF attribute, given its variable ID and name.
The information returned is the type and length of the attribute.

In case of an error, @code{ncattinq} returns -1; @code{NCAINQ} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattinq
@unnumberedsubsec ncattinq:  C Interface
@example
int ncattinq(int ncid, int varid, const char* name,
             nc_type* datatype, int* len);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@item varid
Variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
Attribute name.

@cindex data types
@vindex nc_type
@vindex NC_BYTE
@vindex NC_CHAR
@vindex NC_SHORT
@vindex NC_LONG
@vindex NC_FLOAT
@vindex NC_DOUBLE
@vindex NC_CHAR
@item datatype
Returned attribute type, one of the set of predefined netCDF data types.
The type of this parameter, @code{nc_type}, is defined in the netCDF
header file.  The valid netCDF data types are @code{NC_BYTE},
@code{NC_CHAR}, @code{NC_SHORT}, @code{NC_LONG}, @code{NC_FLOAT}, and
@code{NC_DOUBLE}.  If this parameter is given as @samp{(nc_type *) 0},
no type will be returned so no variable to hold the type needs to be
declared.

@cindex data types
@item len
Returned number of values currently stored in the attribute.  If the
attribute is of type @code{NC_CHAR}, this is one more than the string
length (since the terminating null character is stored).  If this
parameter is given as @samp{(int *) 0}, no length will be returned so no
variable to hold this information needs to be declared.
@end table

@findex ncopen
@findex ncvarid
@findex ncattinq
@vindex nc_type
@vindex NC_GLOBAL
Here is an example using @code{ncattinq} to find out the type and length
of a variable attribute named @code{valid_range} for a netCDF variable
named @code{rh} and a global attribute named @code{title} in an existing
netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                 /* netCDF ID */
int  rh_id;                /* variable ID */
nc_type vr_type, t_type;   /* attribute types */
int  vr_len, t_len;        /* attribute lengths *'

   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
ncattinq (ncid, rh_id, "valid_range", &vr_type, &vr_len);
ncattinq (ncid, NC_GLOBAL, "title", &t_type, &t_len);
   @dots{}
@end group
@end example

@findex NCAINQ
@unnumberedsubsec NCAINQ:  FORTRAN Interface
@example
      SUBROUTINE NCAINQ (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER ATTYPE,
     +                   INTEGER ATTLEN,INTEGER RCODE)
@end example

@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex global attributes
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
Variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
Attribute name.

@cindex data types
@vindex NCBYTE
@vindex NCCHAR
@vindex NCSHORT
@vindex NCLONG
@vindex NCFLOAT
@vindex NCDOUBLE
@item ATTYPE
Returned attribute type, one of the set of predefined netCDF data types.  The
valid netCDF data types are @code{NCBYTE}, @code{NCCHAR},
@code{NCSHORT}, @code{NCLONG}, @code{NCFLOAT}, and @code{NCDOUBLE}.

@item ATTLEN
Returned number of values currently stored in the attribute.  For a
string-valued attribute, this is the number of characters in the string.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAINQ
@vindex NCGLOBAL
Here is an example using @code{NCAINQ} to add a variable attribute
named @code{valid_range} for a netCDF variable named @code{rh} and a
global attribute named @code{title} to an existing netCDF file named
@file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  VRTYPE, TTYPE      ! attribute types
      INTEGER  VRLEN, TLEN        ! attribute lengths
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)! get ID
         @dots{}
      CALL NCAINQ (NCID, RHID, 'valid_range', VRTYPE, VRLEN,
     +             RCODE)
      CALL NCAINQ (NCID, NCGLOBAL, 'title', TTYPE, TLEN,
     +             RCODE)
@end group
@end example

@page
@node ncattget and NCAGT(C), ncattcopy and NCACPY, ncattinq and NCAINQ, Attributes
@section Get Attribute's Values

@cindex getting attribute values
@cindex attribute values
@findex ncattget
@findex NCAGT
@findex NCAGTC
The function @code{ncattget} (or @code{NCAGT} or @code{NCAGTC} for
FORTRAN) gets the value(s) of a netCDF attribute, given its
variable ID and name.

In case of an error, @code{ncattget} returns -1; @code{NCAGT} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattget
@unnumberedsubsec ncattget:  C Interface
@example
int ncattget(int ncid, int varid, const char* name, void* value);
@end example

@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
Variable ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
Attribute name.

@cindex attribute values
@findex ncattinq
@item value
Returned attribute values.  All elements of the vector of attribute
values are returned, so you must allocate enough space to hold
them.  If you don't know how much space to reserve, call @code{ncattinq}
first to find out the length of the attribute.
@end table

@findex ncopen
@findex ncvarid
@findex ncattget
@vindex nc_type
@vindex NC_GLOBAL
@findex nctypelen
Here is an example using @code{ncattget} to determine the values of a
variable attribute named @code{valid_range} for a netCDF variable named
@code{rh} and a global attribute named @code{title} in an existing
netCDF file named @file{foo.nc}.  In this example, it is assumed that
we don't know how many values will be returned, but that we do know the
types of the attributes.  Hence, to allocate enough space to store them,
we must first inquire about the length of the attributes.
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;                 /* netCDF ID */
int  rh_id;                /* variable ID */
nc_type vr_type, t_type;   /* attribute types */
int  vr_len, t_len;        /* attribute lengths */
double *vr_val;            /* ptr to attribute values */
char *title;               /* ptr to attribute values */
extern char *malloc();     /* memory allocator */

   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
/* find out how much space is needed for attribute values */
ncattinq (ncid, rh_id, "valid_range", &vr_type, &vr_len);
ncattinq (ncid, NC_GLOBAL, "title", &t_type, &t_len);

/* allocate required space before retrieving values */
vr_val = (double *) malloc(vr_len * nctypelen(vr_type));
title = (char *) malloc(t_len * nctypelen(t_type));

/* get attribute values */
ncattget(ncid, rh_id, "valid_range", (void *)vr_val);
ncattget(ncid, NC_GLOBAL, "title", (void *)title);
   @dots{}
@end group
@end example

@findex NCAGT
@findex NCAGTC
@unnumberedsubsec NCAGT, NCAGTC:  FORTRAN Interface
@example
      SUBROUTINE NCAGT (INTEGER NCID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, type VALUES,
     +                  INTEGER RCODE)

      SUBROUTINE NCAGTC (INTEGER NCID, INTEGER VARID,
     +                  CHARACTER*(*) ATTNAM, CHARACTER*(*) STRING,
     +                  INTEGER LENSTR, INTEGER RCODE)
@end example

There are two FORTRAN subroutines, @code{NCAGT} and @code{NCAGTC}, for
retrieving attribute values.  The first is for attributes of numeric
type, and the second is for attributes of character-string type.

@cindex attribute names
@cindex attribute type
@cindex attribute length
@cindex global attributes
@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item VARID
Variable ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
Attribute name.

@cindex attribute values
@findex NCAINQ
@item VALUES
Returned attribute values.  All elements of the vector of attribute
values are returned, so you must provide enough space to hold
them.  If you don't know how much space to reserve, call @code{NCAINQ}
first to find out the length of the attribute.  @strong{Warning:
neither the compiler nor the netCDF software can detect if the wrong
type of data is used.}

@item STRING
In @code{NCAGTC}, the character-string value of the attribute.

@item LENSTR
In @code{NCAGTC}, the total declared length (in characters) of the
@code{STRING} parameter in the caller.  Note that this is not
necessarily the same as the value returned by the FORTRAN @code{LEN}
function, because an array argument may be provided.  @code{NCAGTC} will
check to make sure the requested data will fit in @code{LENSTR}
characters.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.

@end table

@findex NCOPN
@findex NCVID
@findex NCAGT
@findex NCAGTC
@findex NCAINQ
@vindex NCGLOBAL
Here is an example using @code{NCAGT} to determine the values of an
attribute named @code{valid_range} for a netCDF variable named @code{rh}
and a global attribute named @code{title} in an existing netCDF file
named @file{foo.nc}.  In this example, it is assumed that we don't know
how many values will be returned, so we first inquire about the length
of the attributes to make sure we have enough space to store them:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      PARAMETER (MVRLEN=3) ! max number of "valid_range" values
      PARAMETER (MTLEN=80) ! max length of "title" attribute
      INTEGER  NCID, RCODE
      INTEGER  RHID               ! variable ID
      INTEGER  VRTYPE, TTYPE      ! attribute types
      INTEGER  VRLEN, TLEN        ! attribute lengths
      DOUBLE PRECISION VRVAL(MVRLEN) ! vr attribute values
      CHARACTER*80 TITLE          ! title attribute values
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE) ! get ID
         @dots{}
* find out attribute lengths, to make sure we have enough space
      CALL NCAINQ (NCID, RHID, 'valid_range', VRTYPE, VRLEN,
     +             RCODE)
      CALL NCAINQ (NCID, NCGLOBAL, 'title', TTYPE, TLEN,
     +             RCODE)
* get attribute values, if not too big
      IF (VRLEN > MVRLEN) THEN
          WRITE (*,*) 'valid_range attribute too big!'
          CALL EXIT
      ELSE
          CALL NCAGT (NCID, RHID, 'valid_range', VRVAL, RCODE)
      ENDIF
      IF (TLEN > MTLEN) THEN
          WRITE (*,*) 'title attribute too big!'
          CALL EXIT
      ELSE
          CALL NCAGTC (NCID, NCGLOBAL, 'title', TITLE, MTLEN, RCODE)
      ENDIF
@end group
@end example

@page
@node ncattcopy and NCACPY, ncattname and NCANAM, ncattget and NCAGT(C), Attributes
@section Copy Attribute from One NetCDF to Another

@cindex copying attributes
@findex ncattcopy
@findex NCACPY
The function @code{ncattcopy} (or @code{NCACPY} for FORTRAN) copies an
attribute from one open netCDF file to another.  It can also be used to
copy an attribute from one variable to another within the same netCDF.

In case of an error, @code{ncattcopy} returns -1; @code{NCACPY} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The input or output variable ID is invalid for the specified netCDF file.

@item
The specified attribute does not exist.

@item
The output netCDF is not in define mode and the attribute is new for the
output file is larger than the existing attribute.

@item
The input or output netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattcopy
@unnumberedsubsec ncattcopy:  C Interface
@example
int ncattcopy(int incdf, int invar, const char* name, int outcdf, int outvar);
@end example

@table @code
@item incdf
The netCDF ID of an input netCDF file from which the attribute will be copied,
returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex variables
@vindex NC_GLOBAL
@item invar
ID of the variable in the input netCDF file from which the
attribute will be copied, or @code{NC_GLOBAL} for a global attribute.

@item name
Name of the attribute in the input netCDF file to be copied.

@item outcdf
The netCDF ID of the output netCDF file to which the attribute will be copied,
returned from a previous call to @code{ncopen} or @code{nccreate}.  It
is permissible for the input and output netCDF IDs to be the same.  The
output netCDF file should be in define mode if the attribute to be
copied does not already exist for the target variable, or if it would
cause an existing target attribute to grow.

@cindex variables
@vindex NC_GLOBAL
@item outvar
ID of the variable in the output netCDF file to which the attribute will
be copied, or @code{NC_GLOBAL} to copy to a global attribute.
@end table

@findex ncopen
@findex ncvarid
@findex ncredef
@findex ncendef
@findex ncattcopy
Here is an example using @code{ncattcopy} to copy the variable attribute
@code{units} from the variable @code{rh} in an existing netCDF file
named @file{foo.nc} to the variable @code{avgrh} in another existing
netCDF file named @file{bar.nc}, assuming that the variable
@code{avgrh} already exists, but does not yet have a @code{units}
attribute:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid1, ncid2;       /* netCDF IDs */
int  rh_id, avgrh_id;      /* variable IDs */
   @dots{}
ncid1 = ncopen("foo.nc", NC_NOWRITE);
ncid2 = ncopen("bar.nc", NC_WRITE);
   @dots{}
rh_id = ncvarid (ncid1, "rh");
avgrh_id = ncvarid (ncid2, "avgrh");
   @dots{}
ncredef(ncid2);           /* enter define mode */
/* copy variable attribute from "rh" to "avgrh" */
ncattcopy(ncid1, rh_id, "units", ncid2, avgrh_id);
   @dots{}
ncendef(ncid2);           /* leave define mode */
@end group
@end example

@findex NCACPY
@unnumberedsubsec NCACPY:  FORTRAN Interface
@example
      SUBROUTINE NCACPY (INTEGER INCDF, INTEGER INVAR,
     +                   CHARACTER*(*) ATTNAM, INTEGER OUTCDF,
     +                   INTEGER OUTVAR, INTEGER RCODE)
@end example

@table @code
@item INCDF
The netCDF ID of an input netCDF file from which the attribute will be copied,
returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@item INVAR
ID of the variable in the input netCDF file from which the
attribute will be copied, or @code{NCGLOBAL} for a global attribute.

@item ATTNAM
Name of the attribute in the input netCDF file to be copied.

@item OUTCDF
The netCDF ID of the output netCDF file to which the attribute will be copied,
returned from a previous call to @code{NCOPN} or @code{NCCRE}.  It
is permissible for the input and output netCDF IDs to be the same.  The
output netCDF file should be in define mode if the attribute to be
copied does not already exist for the target variable, or if it would
cause an existing target attribute to grow.

@cindex variable
@vindex NCGLOBAL
@item OUTVAR
ID of the variable in the output netCDF file to which the
attribute will be copied, or @code{NCGLOBAL} to copy to a global
attribute.
@end table

@findex NCOPN
@findex NCVID
@findex NCREDF
@findex NCENDF
@findex NCACPY
@vindex NCGLOBAL
Here is an example using @code{NCACPY} to copy the variable attribute
@code{units} from the variable @code{rh} in an existing netCDF file
named @file{foo.nc} to the variable @code{avgrh} in another existing
netCDF file named @file{bar.nc}, assuming that the variable
@code{avgrh} already exists, but does not yet have a @code{units}
attribute:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID1, NCID2     ! netCDF IDs
      INTEGER  RHID, AVRHID       ! variable IDs
         @dots{}
      NCID1 = NCOPN ('foo.nc', NCNOWRIT, RCODE)
      NCID2 = NCOPN ('bar.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID1, 'rh', RCODE)
      AVRHID = NCVID (NCID2, 'avgrh', RCODE)
         @dots{}
      CALL NCREDF (NCID2, RCODE)  ! enter define mode
* copy variable attribute from "rh" to "avgrh"
      CALL NCACPY (NCID1, RHID, 'units', NCID2, AVRHID, RCODE)
         @dots{}
      CALL NCENDF (NCID2, RCODE)  ! leave define mode
@end group
@end example

@page
@node ncattname and NCANAM, ncattrename and NCAREN, ncattcopy and NCACPY, Attributes
@section Get Name of Attribute from Its Number

@cindex getting attribute name
@cindex attribute names
@cindex attribute numbers
@cindex generic applications
@cindex attribute deletion
@cindex attribute ID
@findex ncattname
@findex NCANAM
The function @code{ncattname} (or @code{NCANAM} for FORTRAN) gets the
name of an attribute, given its variable ID and number. 
This function is useful in generic applications that
need to get the names of all the attributes associated with a variable,
since attributes are accessed by name rather than number in all other
attribute functions.  The number of an attribute is more volatile than
the name, since it can change when other attributes of the same variable
are deleted.  This is why an attribute number is not called an attribute
ID.

In case of an error, @code{ncattname} returns -1; @code{NCANAM} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The specified variable ID is not valid.

@item
The specified attribute number is negative or more than the number of
attributes defined for the specified variable.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattname
@unnumberedsubsec ncattname:  C Interface
@example
int ncattname (int ncid, int varid, int attnum, char* name);
@end example

@cindex attribute numbers
@cindex attribute names
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
ID of the attribute's variable, or @code{NC_GLOBAL} for a global
attribute.

@findex ncvarinq
@item attnum
Number of the attribute.  The attributes for each variable are numbered
from 0 (the first attribute) to @code{nvatts-1}, where @code{nvatts} is
the number of attributes for the variable, as returned from a call to
@code{ncvarinq}.

@cindex maximum name length
@vindex MAX_NC_NAME
@item name
Returned attribute name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of an
attribute name is given by the predefined constant @code{MAX_NC_NAME}.
If the name parameter is given as @code{(char *) 0}, no name will be
returned and no space needs to be allocated.
@end table

@findex ncopen
@findex ncvarid
@findex ncattname
@vindex MAX_NC_NAME
Here is an example using @code{ncattname} to determine the name of the
first attribute of the variable @code{rh} in an existing netCDF file
named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;        /* netCDF ID */
int  rh_id;       /* variable ID */
char attname[MAX_NC_NAME];  /* maximum-size attribute name */
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
/* get name of first attribute (number 0) */
ncattname(ncid, rh_id, 0, attname);
@end group
@end example

@findex NCANAM
@unnumberedsubsec NCANAM:  FORTRAN Interface
@example
      SUBROUTINE NCANAM (INTEGER NCID, INTEGER VARID,
     +                   INTEGER ATTNUM, CHARACTER*(*) ATTNAM,
     +                   INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
ID of the attribute's variable, or @code{NCGLOBAL} for a global
attribute.

@findex NCVINQ
@item ATTNUM
Number of the attribute.  The attributes for each variable are numbered
from 1 (the first attribute) to @code{NVATTS}, where @code{NVATTS} is
the number of attributes for the variable, as returned from a call to
@code{NCVINQ}.

@cindex maximum name length
@vindex MAXNCNAM
@item ATTNAM
Returned attribute name.  The caller must allocate space for the
returned name.  The maximum possible length, in characters, of an
attribute name is given by the predefined constant @code{MAXNCNAM}.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCANAM
@vindex MAXNCNAM
Here is an example using @code{NCANAM} determine the name of the
first attribute of the variable @code{rh} in an existing netCDF file
named @file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID     ! netCDF ID
      INTEGER  RHID      ! variable ID
* 31 in the following should be MAXNCNAM
      CHARACTER*31 ATTNAM
         @dots{}
      NCID = NCOPN ('foo.nc', NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)
         @dots{}
* get name of first attribute (number 1)
      CALL NCANAM (NCID, RHID, 1, ATTNAM, RCODE)
@end group
@end example

@page
@node ncattrename and NCAREN, ncattdel and NCADEL, ncattname and NCANAM, Attributes
@section Rename an Attribute


@cindex renaming attributes
@cindex attribute names
@findex ncattrename
@findex NCAREN
The function @code{ncattrename} (or @code{NCAREN} for FORTRAN) changes the
name of an attribute.  If the new name is longer than the original name,
the netCDF must be in define mode.  You cannot rename an attribute to
have the same name as another attribute of the same variable.

In case of an error, @code{ncattrename} returns -1; @code{NCAREN} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The specified variable ID is not valid.
@item
The new attribute name is already in use for another attribute of the
specified variable.
@item
The specified netCDF file is in data mode and the new name is longer
than the old name.
@item
The specified attribute does not exist.
@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattrename
@unnumberedsubsec ncattrename:  C Interface
@example
int ncattrename (int ncid, int varid, const char* name, const char* newname);
@end example

@cindex attribute names
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}
@item varid
ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute
@item name
The original attribute name.
@item newname
The new name to be assigned to the specified attribute.  If the new name
is longer than the old name, the netCDF file must be in define mode.
@end table

@findex ncopen
@findex ncvarid
@findex ncattrename
Here is an example using @code{ncattrename} to rename the variable
attribute @code{units} to @code{Units} for a variable @code{rh}
in an existing netCDF file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;        /* netCDF ID */
int  rh_id;       /* variable id */
   @dots{}
ncid = ncopen("foo.nc", NC_NOWRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
/* rename attribute */
ncattrename(ncid, rh_id, "units", "Units");
@end group
@end example

@findex NCAREN
@unnumberedsubsec NCAREN:  FORTRAN Interface
@example
      SUBROUTINE NCAREN (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM,
     +                   CHARACTER*(*) NEWNAM, INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}
@item VARID
ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute
@item ATTNAM
The original attribute name.
@item NEWNAM
The new name to be assigned to the specified attribute.  If the new name
is longer than the old name, the netCDF file must be in define mode.
@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCAREN
Here is an example using @code{NCAREN} to rename the variable
attribute @code{units} to @code{Units} for a variable @code{rh}
in an existing netCDF file named @file{foo.nc}:
@example 
@group
      INCLUDE "netcdf.inc"
         @dots{}
      INTEGER  NCID     ! netCDF ID
      INTEGER  RHID      ! variable ID
         @dots{}
      NCID = NCOPN ("foo.nc", NCNOWRIT, RCODE)
         @dots{}
      RHID = NCVID (NCID, "rh", RCODE)
         @dots{}
* rename attribute
      CALL NCAREN (NCID, RHID, "units", "Units", RCODE)
@end group
@end example

@page
@node ncattdel and NCADEL,  , ncattrename and NCAREN, Attributes
@section Delete an Attribute

@cindex deleting attributes
@cindex removing attributes
@findex ncattdel
@findex NCADEL
The function @code{ncattdel} (or @code{NCADEL} for FORTRAN) deletes a
netCDF attribute from an open netCDF file.  The netCDF file must be in
define mode.

In case of an error, @code{ncattdel} returns -1; @code{NCADEL} returns a
nonzero value in @code{rcode}.  Possible causes of errors include:
@itemize @bullet
@item
The specified variable ID is not valid.

@item
The specified netCDF file is in data mode.

@item
The specified attribute does not exist.

@item
The specified netCDF ID does not refer to an open netCDF file.
@end itemize

@findex ncattdel
@unnumberedsubsec ncattdel:  C Interface
@example
int ncattdel (int ncid, int varid, const char* name);
@end example

@cindex attribute names
@table @code
@item ncid
NetCDF ID, returned from a previous call to @code{ncopen} or @code{nccreate}.

@cindex attribute variable ID
@vindex NC_GLOBAL
@item varid
ID of the attribute's variable, or @code{NC_GLOBAL} for a
global attribute.

@item name
The name of the attribute to be deleted.
@end table

@findex ncopen
@findex ncvarid
@findex ncattdel
@findex ncredef
@findex ncendef
Here is an example using @code{ncattdel} to delete the variable
attribute @code{Units} for a variable @code{rh} in an existing netCDF
file named @file{foo.nc}:
@example 
@group
#include "netcdf.h"
   @dots{}
int  ncid;        /* netCDF ID */
int  rh_id;       /* variable ID */
   @dots{}
ncid = ncopen("foo.nc", NC_WRITE);
   @dots{}
rh_id = ncvarid (ncid, "rh");
   @dots{}
/* delete attribute */
ncredef(ncid);                  /* enter define mode */
ncattdel(ncid, rh_id, "Units");
ncendef(ncid);                  /* leave define mode */
@end group
@end example

@findex NCADEL
@unnumberedsubsec NCADEL:  FORTRAN Interface
@example
      SUBROUTINE NCADEL (INTEGER NCID, INTEGER VARID,
     +                   CHARACTER*(*) ATTNAM, INTEGER RCODE)
@end example

@table @code
@item NCID
NetCDF ID, returned from a previous call to @code{NCOPN} or @code{NCCRE}.

@cindex attribute variable ID
@vindex NCGLOBAL
@item VARID
ID of the attribute's variable, or @code{NCGLOBAL} for a
global attribute.

@item ATTNAM
The original attribute name.

@item RCODE
Returned error code.  If no errors occurred, 0 is returned.
@end table

@findex NCOPN
@findex NCVID
@findex NCADEL
@findex NCREDF
@findex NCENDF
Here is an example using @code{NCADEL} to delete the variable attribute
@code{Units} for a variable @code{rh} in an existing netCDF file named
@file{foo.nc}:
@example 
@group
      INCLUDE 'netcdf.inc'
         @dots{}
      INTEGER  NCID     ! netCDF ID
      INTEGER  RHID      ! variable ID
         @dots{}
      NCID = NCOPN ('foo.nc', NCWRITE, RCODE)
         @dots{}
      RHID = NCVID (NCID, 'rh', RCODE)
         @dots{}
* delete attribute
      CALL NCREDF (NCID, RCODE)  ! enter define mode
      CALL NCADEL (NCID, RHID, 'Units', RCODE)
      CALL NCENDF (NCID, RCODE)  ! leave define mode
@end group
@end example

@cindex efficiency
@cindex performance
@cindex format
@cindex netCDF format
@cindex file structure
@cindex netCDF file structure
@node File Structure, Utilities, Attributes, Top
@chapter NetCDF File Structure and Performance

NetCDF is a data abstraction for scientific data access and a software
library that provides a concrete implementation of the interfaces that
support that abstraction.  The implementation provides a
machine-independent format for representing scientific data.  Although
the netCDF file format is completely hidden below the interfaces, some
understanding of the implementation and associated file structure may
help to make clear which netCDF operations are expensive and why.

A detailed description of the netCDF @emph{format} is not appropriate
for this User's Guide, however.  It is not needed to read and
write netCDF files or understand efficiency issues.  Programs that use
only the documented interfaces and that make no other assumptions about
the format will continue to work even if the netCDF format is changed in
the future, because any such change will be made below the documented
interfaces and will support earlier versions of netCDF data.

This chapter describes the structure of a netCDF file and some
characteristics of the XDR layer that provides network transparency in
enough detail to understand netCDF performance issues.

@menu
* File parts::  Parts of a netCDF File
* XDR layer::   The XDR Layer
@end menu

@cindex header part
@cindex parts of a netCDF file
@cindex fixed-size data part
@cindex record-data part
@cindex XDR
@node File parts, XDR layer,  , File Structure
@section Parts of a NetCDF File

A netCDF data set is stored as a single file comprising three parts:
@itemize @bullet
@item
a @dfn{header}, containing all the information about dimensions,
attributes, and variables except for the variable data;
@item
@dfn{fixed-size data}, containing the data for variables that
don't have an unlimited dimension; and
@item
@dfn{record data}, containing the data records for variables that
have an unlimited dimension.
@end itemize
All the data are represented in XDR form to make them machine-independent.

@cindex variable offsets
The descriptive header at the beginning of the netCDF file is an XDR
encoding of a high-level data structure that represents information
about the dimensions, variables, and attributes in the file.  The
variable descriptions in this header contain offsets to the beginning of
each variable's data or the relative offset of a variable within a
record. The descriptions also contain the dimension size and information
needed to determine how to map multidimensional indices for each
variable to the appropriate offsets.

@cindex file size
@cindex expense of operations
This header has no usable extra space; it is only as large as it needs
to be for the dimensions, variables, and attributes in each netCDF file.
This has the advantage that netCDF files are compact, requiring very
little overhead to store the ancillary data that makes the files
self-describing.  A potential disadvantage of this organization is
that any operation on a netCDF file that requires expanding the header,
for example adding a set of new dimensions and new variables to an
existing netCDF file, will be as expensive as copying the file.  This
expense is incurred when @code{ncendef()} is called, after a call to
@code{ncredef()}.  If you create all necessary dimensions, variables,
and attributes @emph{before} writing variable data, and avoid later
additions and renamings of netCDF components that require more space in
the header part of the file, you avoid the cost associated with
expanding the header.

The fixed-size data part that follows the header contains all the
variable data for variables that do not employ the unlimited (record)
dimension.  The data for each variable is stored contiguously in this
part of the file.  If there is no unlimited dimension, this is the last
part of the netCDF file.

@cindex appending data
The record-data part that follows the fixed-size data consists of a
variable number of records, each of which contains data for all
the record variables.  The record data for each variable is stored
contiguously in each record.

The order in which the data in the fixed-size data part and in each
record appears is the same as the order in which the variables were
defined, in increasing numerical order by netCDF variable ID.  This
knowledge can sometimes be used to enhance data access performance,
since the best data access is currently achieved by reading or writing
the data in sequential order.

@cindex XDR
@node XDR layer,  , File parts, File Structure
@section The XDR Layer

XDR is a standard for describing and encoding data and a library of
functions for external data representation, allowing programmers to
encode data structures in a machine-independent way.  NetCDF employs XDR
for representing all data, in both the header part and the data parts.
XDR is used to write portable data that can be read on any other machine
for which the XDR library has been implemented.

Many vendors provide an XDR library along with other C run-time
libraries.  The netCDF software distribution also includes Sun's
portable implementation of XDR for platforms that don't already have a
vendor-supplied XDR library.

@cindex stdio
@cindex concurrency
@cindex buffers
@cindex flushing
An I/O layer implemented much like the C standard I/O (stdio) library is
used by the XDR layer to read and write XDR-encoded data to netCDF
files.  Hence an understanding of the standard I/O library provides
answers to most questions about multiple processes accessing data
concurrently, the use of I/O buffers, and the costs of opening and
closing netCDF files.  In particular, it is possible to have one process
writing a netCDF file while other processes read it.  Data reads and
writes are no more atomic than calls to stdio @code{fread()} and
@code{fwrite()}.  An @code{ncsync()} call (@code{NCSNC()} for FORTRAN)
is analogous to the @code{fflush()} call in the standard I/O library,
writing unwritten buffered data so other processes can read it;
@code{ncsync()} also brings header changes up-to-date (e.g., changes to
attribute values).

As in the stdio library, flushes are also performed when ``seeks'' occur
to a different area of the file.  Hence the order of read and write
operations can influence I/O performance significantly.  Reading data in
the same order in which it was written within each record will minimize
buffer flushes.

There is one unusual case where the situation is more complex: when a
writer enters define mode to add some additional dimensions, variables,
or attributes to an existing netCDF file that is also open for reading
by other processes.  In this case, when the writer leaves define mode, a
new copy of the file is created with the new dimensions, attributes, or
variables and the old data, but readers that still have the file open
will not see the changes.  You should not expect netCDF data access to
work with multiple writers having the same file open for writing
simultaneously.

@cindex VMS performance
For VMS systems, the performance penalty for permitting shared access
(under the current implementation of stdio in the C run-time library)
seemed too great to make shared access the default, so netCDF files on VMS
are opened non-shared.  This still permits multiple simultaneous readers
of the same file, but one writer prevents any readers from accessing the
file.  Implementors can easily allow shared access for a VMS
implementation, if shared access is a more important requirement than
access speed.

It is possible to tune an implementation of netCDF for some platforms by
replacing the I/O layer beneath XDR with a different platform-specific
I/O layer.  This may change the similarities between netCDF and standard
I/O, and hence characteristics related to data sharing, buffering, and
the cost of I/O operations.

The cost of using a canonical representation for data like XDR varies
according to the type of data and whether the XDR form is the same as the
machine's native form for that type.  XDR is especially efficient for
byte, character, and short integer data.

@cindex XDR
@cindex floating-point conversion costs
For some data types on some machines, the time required to convert data
to and from XDR form can be significant.  The best case is byte arrays,
for which very little conversion expense occurs, since the XDR library
has built-in support for them.  The netCDF implementation
includes similar support added to XDR for arrays of short (16-bit)
integers.  The worst case is reading or writing large arrays of
floating-point data on a machine that does not use IEEE floating-point
as its native representation.  The XDR library incurs the expense of a
function call for each floating-point quantity accessed.  On some
architectures the cost of a function invocation for each floating-point
number can dominate the cost of netCDF access to floating-point fields.

@cindex portability
@cindex platform-specific optimizations
The distributed netCDF implementation is meant to be portable.
Platform-specific ports that further optimize the implementation for
better I/O performance or that unroll the loops in the XDR library to
optimize XDR conversion of long integer and floating-point arrays are
practical and desirable in cases where higher performance for data
access is necessary.

@node Utilities, FAQ, File Structure, Top
@chapter Higher-Level netCDF Operations

@cindex higher-level netCDF operations
@findex ncgen
@findex ncdump
One of the primary reasons for using the netCDF interface for both
scientific data and applications that deal with scientific data is to
take advantage of higher-level netCDF operations and generic
applications for processing netCDF files.  NetCDF @dfn{operators} read
one or more netCDF input files and write a netCDF output file.  NetCDF
@dfn{utilities} read one or more netCDF files and produce some other
kind of output (e.g. a text file or graphics), or read some other kind
of input (e.g. a text file) and write netCDF files.  Currently two
netCDF utilities are available as part of the netCDF software
distribution: @code{ncgen} and @code{ncdump}.  A preliminary set of
example netCDF operators is available as a separate package.

This chapter describes the @code{ncgen} and @code{ncdump} utilities.
These two tools convert between binary netCDF files and an ASCII
representation of netCDF files.  The output of @code{ncdump} and the
input to @code{ncgen} is an ASCII description of a netCDF file in a tiny
language known as CDL (network Common data form Description Language).

The preliminary set of example netCDF operators is available via
anonymous FTP of the file @code{pub/sdm/ncopers<version>.tar.Z} from
host @code{unidata.ucar.edu}.  The programs include: @code{ncextr},
which extracts a subset of variables from a netCDF file into an output
netCDF file; @code{ncstat}, which reads a netCDF file and writes
selected statistics along one or more summary dimensions into another
netCDF file; and @code{ncbarne}, which performs a Barnes objective
analysis of raw data contained in a netCDF file and writes the result to
an output netCDF file.  These programs are documented in the ncopers
release.

A number of freely-available and commercial software packages are also
available for manipulating or graphically displaying netCDF data.  A
list of these packages is maintained in the file
@code{pub/netcdf/utilities.txt} from host @code{unidata.ucar.edu}.

@menu

* CDL Syntax::    The syntax of CDL, a tiny language for representing
                  netCDF files or their structure in ASCII.
* CDL Data Types::The data types of CDL.
* CDL Constants:: The CDL notation for data constants.
* ncgen::         Check CDL syntax or generate netCDF file (or C or Fortran)
                  from netCDF file.
* ncdump::        Generate CDL file (or a portion of a CDL file) from a netCDF
                  file.
@end menu

@node CDL Syntax, CDL Data Types,  , Utilities
@section CDL Syntax

@cindex CDL syntax
@cindex CDL example
Below is an example of CDL, describing a netCDF file with several named
dimensions (@code{lat}, @code{lon}, @code{time}), variables
(@code{z}, @code{t}, @code{p}, @code{rh}, @code{lat}, @code{lon},
@code{time}), variable attributes (@code{units}, @code{valid_range},
@code{_FillValue}), and some data.

@example
@group
netcdf foo @{    // example netCDF specification in CDL

dimensions:
lat = 10, lon = 5, time = unlimited ;

variables:
  long    lat(lat), lon(lon), time(time);
  float   z(time,lat,lon), t(time,lat,lon);
  double  p(time,lat,lon);
  long    rh(time,lat,lon);

  lat:units = "degrees_north";
  lon:units = "degrees_east";
  time:units = "seconds";
  z:units = "meters";
  z:valid_range = 0., 5000.;
  p:_FillValue = -9999.;
  rh:_FillValue = -1;

data:
  lat   = 0, 10, 20, 30, 40, 50, 60, 70, 80, 90;
  lon   = -140, -118, -96, -84, -52;
@}
@end group
@end example

All CDL statements are terminated by a semicolon.  Spaces, tabs, and
newlines can be used freely for readability.  Comments may follow the
double slash characters @code{//} on any line.

A CDL description consists of three optional parts: dimensions,
variables, and data.  The variable part may contain variable
declarations and attribute assignments.

@cindex CDL dimensions
@cindex appending data
A dimension is used to define the shape of one or
more of the multidimensional variables described by the
CDL description.   A dimension has a name and a size.   At
most one dimension in a CDL description can have the unlimited size,
which means a variable using this dimension can grow to any
length (like a record number in a file).

@cindex CDL variables
@cindex coordinate variables
A variable represents a multidimensional array of values of the same
type.  A variable has a name, a data type, and a shape described by its
list of dimensions.  Each variable may also have associated attributes
(see below) as well as data values.  The name, data type, and shape of a
variable are specified by its declaration in the variable section of a
CDL description.  A variable may have the same name as a dimension; by
convention such a variable is one-dimensional and contains coordinates
of the dimension it names.  Dimensions need not have corresponding
variables.

@cindex CDL attributes
An attribute contains information about a variable or about the whole
netCDF data set.  Attributes are used to specify such properties as
units, special values, maximum and minimum valid values, scaling
factors, offsets, and parameters.  Attribute information is represented
by single values or arrays of values.  For example, @code{units} is an
attribute represented by a character array such as @code{celsius}.  An
attribute has an associated variable, a name, a data type, a length, and
a value.  In contrast to variables that are intended for data,
attributes are intended for ancillary data (data about data).

@cindex CDL attributes
@cindex variable attributes
@cindex global attributes
In CDL, an attribute is designated by a variable and attribute name,
separated by a colon (@samp{:}).  It is possible to assign global
attributes not associated with any variable to the netCDF file as a
whole by using the colon (@samp{:}) before the attribute name.  The data
type of an attribute in CDL is derived from the type of the value
assigned to it.  The length of an attribute is the number of data values
or the number of characters in the character string assigned to it.
Multiple values are assigned to noncharacter attributes by separating
the values with commas (@samp{,}).  All values assigned to an attribute
must be of the same type.

@cindex CDL names
CDL names for variables, attributes, and dimensions may be any
combination of alphabetic or numeric characters as well as @samp{_} and
@samp{-} characters, but names beginning with @samp{_} are reserved for
use by the library.  Case is significant in CDL names.  The netCDF
library does not enforce any restrictions on netCDF names, so it is
possible (though unwise) to define variables with names that are not
valid CDL names.  The names for the primitive data types are reserved
words in CDL, so the names of variables, dimensions, and attributes must
not be type names.
@sp 1
@cindex data section
@cindex CDL variable initialization
@cindex CDL variables
The optional data section of a CDL description is where
netCDF variables may be initialized.  The syntax of an initialization
is simple:
@display
        @i{variable} = @i{value_1}, @i{value_2}, @dots{};
@end display
The comma-delimited list of constants may be separated by spaces, tabs,
and newlines.  For multidimensional arrays, the last dimension varies
fastest.  Thus, row-order rather than column order is used for matrices.
If fewer values are supplied than are needed to fill a variable, it is
extended with a type-dependent fill value.  The types of
constants need not match the type declared for a variable; coercions are
done to convert integers to floating point, for example.  All
meaningful type conversions are supported.

@node CDL Data Types, CDL Constants, CDL Syntax, Utilities
@section CDL Data Types

@cindex CDL data types
The CDL data types are:
@table @code
@item char
Characters.

@item byte
Eight-bit data, including zero bytes.

@item short
16-bit signed integers.

@item long
32-bit signed integers.

@item int
(Synonymous with long).

@item float
IEEE single-precision floating point (32 bits).

@item real
(Synonymous with float).

@item double
IEEE double-precision floating point (64 bits).
@end table

@cindex CDL reserved words
Except for the added data-type @code{byte} and the lack of the type
qualifier @code{unsigned}, CDL supports the same primitive data types as
C.  In declarations, type names may be specified in either upper or
lower case.

@cindex byte data type
@cindex char data type
@code{Byte}s differ from characters in that they are intended to hold
eight bits of data, and the zero byte has no special significance, as it
may for character data.  @code{Ncgen} converts @code{byte} declarations
to @code{char} declarations in the output C code and to the nonstandard
@code{BYTE} declaration (or similar platform-specific declaration) in
output FORTRAN code.

@cindex short type
@code{Short}s can hold values between -32768 and 32767.  @code{Ncgen} converts
@code{short} declarations to @code{short} declarations in the output
C code and to the nonstandard @code{INTEGER*2} declaration in output
FORTRAN code.

@cindex long type
@code{Long}s can hold values between -2147483648 and 2147483647.
@code{Ncgen} converts @code{long} declarations to @code{long}
declarations in the output C code and to @code{INTEGER} declarations in
output FORTRAN code.  In CDL declarations @code{int} and @code{integer}
are accepted as synonyms for @code{long}.

@cindex float data type
@code{Float}s can hold values between about -3.4+38 and 3.4+38.
Their external representation is as 32-bit IEEE normalized
single-precision floating-point numbers.  @code{Ncgen} converts
@code{float} declarations to @code{float} declarations in the output C
code and to @code{REAL} declarations in output FORTRAN code.  
In CDL declarations @code{real} is accepted as a synonym for @code{float}.

@cindex double type
@code{Double}s can hold values between about -1.7+308 and 1.7+308.
Their external representation is as 64-bit IEEE standard
normalized double-precision, floating-point numbers.  @code{Ncgen}
converts @code{double} declarations to double declarations in the
output C code and to @code{DOUBLE PRECISION} declarations in output
FORTRAN code.

@node CDL Constants, ncgen, CDL Data Types, Utilities
@section CDL Notation for Data Constants

@cindex future changes planned
@cindex CDL constants
@findex ncdump
@findex ncgen
This section explains the CDL notation for netCDF constants.

@cindex CDL attribute initialization
@cindex attribute type
@cindex attribute length
Attributes are initialized in the @code{variables} section of a CDL description
by providing a list of constants that determines the attribute's type
and length.  (In the C and FORTRAN procedural interfaces to the netCDF
library, the type and length of an attribute must be explicitly provided
when it is defined.)  Since neither C nor FORTRAN provide suitable
standard syntax to distinguish between constants of type @code{byte} and
@code{char}, @code{short} and @code{long}, or @code{float} and
@code{double} (except that FORTRAN provides the latter), CDL defines a
syntax for constant values that allows it to determine the netCDF type
of any constant.
@cindex double type
@cindex float type
@cindex long type
@cindex short type
@cindex CDL constants
The syntax for CDL constants is similar to C syntax, except that type
suffixes are appended to @code{short}s and @code{float}s to distinguish
them from @code{long}s and @code{double}s.

@cindex byte type
@cindex byte constant
A @code{byte} constant is represented by a single character or multiple
character escape sequence enclosed in single quotes.  For example:
@example
'a'     // ASCII a
'\0'    // a zero byte
'\n'    // ASCII newline character
'\33'   // ASCII escape character (33 octal)
'\x2b'  // ASCII plus (2b hex)
'\377'  // 377 octal = 255 decimal, a non-ASCII byte
@end example

@cindex character type
@cindex character constant
Character constants are enclosed in double quotes.  A character array
may be represented as a string enclosed in double quotes.  Multiple
strings are concatenated into a single array of characters, permitting
long character arrays to appear on multiple lines.  To support multiple
variable-length string values, a conventional delimiter such as @samp{,}
may be used, but interpretation of any such convention for a string
delimiter must be implemented in software above the netCDF library
layer.  The usual escape conventions for C strings are honored.  For
example:
@example
"a"            // ASCII `a'
"Two\nlines\n" // a 10-character string with two embedded newlines
"a bell:\007"  // a string containing an ASCII bell
"ab","cde"     // the same as "abcde"
@end example

@cindex short type
@cindex short constant
The form of a @code{short} constant is an integer constant with an
@samp{s} or @samp{S} appended.  If a @code{short} constant begins with
@samp{0}, it is interpreted as octal.  When it begins with
@code{0x}, it is interpreted as a hexadecimal constant.  For example:
@example
2s      // a short 2
0123s   // octal
0x7ffs  // hexadecimal
@end example

@cindex long type
@cindex long constant
The form of a @code{long} constant is an ordinary integer constant,
although it is acceptable to append an optional @samp{l} or @samp{L}.
If a @code{long} constant begins with @samp{0}, it is interpreted as
octal.  When it begins with @code{0x}, it is interpreted as a
hexadecimal constant.  Examples of valid @code{long} constants include:
@example
-2
1234567890L
0123            // octal
0x7ff           // hexadecimal
@end example

@cindex float type
@cindex float constant
The @code{float} type is appropriate for representing
data with about seven significant digits of precision.
The form of a @code{float} constant is the same as a C floating-point constant
with an @samp{f} or @samp{F} appended.  A decimal point is required in a CDL
@code{float} to distinguish it from an integer.  For example,
the following are all acceptable @code{float} constants:
@example
-2.0f
3.14159265358979f       // will be truncated to less precision
1.f
.1f
@end example

@cindex double type
@cindex double constant
The @code{double} type is appropriate for representing floating-point
data with about 16 significant digits of precision.  The form of a
@code{double} constant is the same as a C floating-point constant.  An
optional @samp{d} or @samp{D} may be appended.  A decimal point is
required in a CDL @code{double} to distinguish it from an
@code{integer}.  For example, the following are all acceptable double
constants:
@sp 2
@example
-2.0
3.141592653589793
1.0e-20
1.d
@end example

@node ncgen, ncdump, CDL Constants, Utilities
@section ncgen

@findex ncgen
@cindex CDL
@cindex C, generation of
@cindex FORTRAN, generation of
@cindex CDF Description Language
@cindex generating code
@cindex generating netCDF files
The @code{ncgen} tool generates a netCDF file or the C or FORTRAN
programs required to create the netCDF file.  If no options are 
specified in invoking @code{ncgen}, the program merely checks the 
syntax of the CDL input, producing error messages for any violations 
of CDL syntax.  Other options can be used to create a netCDF file 
or to generate a program in C or FORTRAN that calls the routines 
required to create the netCDF file.

UNIX syntax for invoking @code{ncgen}:
@example
ncgen [-b] [-o @var{output-file}] [-c] [-f] [-n] [@var{input-file}]
@end example
@noindent
where:
@table @samp
@cindex netCDF file extension
@item -b
Create a (binary) netCDF file.  If the @samp{-o} option is absent, a
default file name will be constructed from the netCDF name (specified
after the @code{netcdf} keyword in the input) by appending the
@samp{.nc} extension.  If a file already exists with the specified name
it will be overwritten.

@item -o outputfile
Name for the netCDF file created.  If this option is specified, it
implies the @samp{-b} option.  (This option is necessary because netCDF
files are direct-access files created with seek calls, and
hence cannot be written to standard output.)

@item -c
Generate C source code that will create a netCDF file matching the
netCDF specification.  The C source code is written to standard output.

@item -f
Generate FORTRAN source code that will create a netCDF file matching the
netCDF specification.  The FORTRAN source code is written to standard
output.

@item -n
Like the @samp{-b} option, except creates a netCDF file with the
obsolete @samp{.cdf} extension instead of the @samp{.nc} extension, in
the absence of an output filename specified by the @samp{-O} option.
This option is only supported for backward compatibility.
@end table

@unnumberedsubsec Examples

Check the syntax of the CDL file @file{foo.cdl}:
@example 
ncgen foo.cdl
@end example

From the CDL file @file{foo.cdl}, generate an equivalent binary netCDF file
named @file{flu.nc}:
@example 
ncgen -o flu.nc foo.cdl
@end example

From the CDL file @file{foo.cdl}, generate a C program containing the
netCDF function invocations necessary to create an equivalent binary netCDF
file named @file{flu.nc}:
@example 
ncgen -c -o flu.nc foo.cdl
@end example

@node ncdump,  , ncgen, Utilities
@section ncdump

@findex ncdump
@findex ncgen
The @code{ncdump} tool generates an ASCII representation of a netCDF
file on standard output, either with or without an ASCII representation
of the variable data in the file.  The ASCII representation used is the
CDL notation that @code{ncgen} accepts as input.  Thus @code{ncdump} and
@code{ncgen} can be used as inverses to transform data representation
between binary and ASCII representations.  

@code{ncdump} may also be used as a simple browser for netCDF data
files, to display the dimension names and sizes; variable names, types,
and shapes; attribute names and values; and optionally, the values of
data for all variables or selected variables in a netCDF file.

@code{ncdump} defines a default format used for each type of netCDF
variable data, but this can be overridden if a @code{C_format} attribute is
defined for a netCDF variable.  In this case, @code{ncdump} will use the
@code{C_format} attribute to format values for that variable.  For example,
if floating-point data for the netCDF variable @code{Z} is known to be
accurate to only three significant digits, it would be appropriate to
use the variable attribute
@example
Z:C_format = "%.3g"
@end example

UNIX syntax for invoking @code{ncdump}:
@example
ncdump  [ -c | -h]  [-v @var{var1},@dots{}]  [-b @var{lang}]  [-f @var{lang}]
[-l @var{len}]  [ -d fdig[,ddig]] [ -n @var{name}]  [@var{input-file}]
@end example
@noindent
where:
@table @samp

@item -c
Show the values of @dfn{coordinate} variables (variables that are also
dimensions) as well as the declarations of all dimensions, variables, and
attribute values.  Data values of
non-coordinate variables are not included in the output.  This is often
the most suitable option to use for a brief look at the structure and
contents of a netCDF file.

@item -h
Show only the @dfn{header} information in the output, that is, output
only the declarations for the netCDF dimensions, variables, and
attributes of the input file, but no data values for any variables.  The
output is identical to using the @samp{-c} option except that the values
of coordinate variables are not included.  (At most one of @samp{-c} or
@samp{-h} options may be present.)

@item -v var1,@dots{}
The output will include data values for the specified variables, in
addition to the declarations of all dimensions, variables, and
attributes.  One or more variables must be specified by name in the
comma-delimited list following this option.  The list must be a single
argument to the command, hence cannot contain blanks or other white
space characters.  The named variables must be valid netCDF variables in
the input-file.  The default, without this option and in the absence of
the @samp{-c} or @samp{-h} options, is to include data values for @emph{all}
variables in the output.

@item -b lang
A brief annotation in the form of a CDL comment (text beginning with the
characters @samp{//}) will be included in the data section of the output
for each `row' of data, to help identify data values for
multidimensional variables.  If @var{lang} begins with @samp{C} or
@samp{c}, then C language conventions will be used (zero-based indices,
last dimension varying fastest).  If @var{lang} begins with @samp{F} or
@samp{f}, then Fortran language conventions will be used (one-based
indices, first dimension varying fastest).  In either case, the data
will be presented in the same order; only the annotations will differ.
This option is useful for browsing through large volumes of
multidimensional data.

@item -f lang
Full annotations in the form of trailing CDL comments (text beginning
with the characters @samp{//}) for every data value (except individual
characters in character arrays) will be included in the data section.
If @var{lang} begins with @samp{C} or @samp{c}, then C language
conventions will be used (zero-based indices, last dimension varying
fastest).  If @var{lang} begins with @samp{F} or @samp{f}, then Fortran
language conventions will be used (one-based indices, first dimension
varying fastest).  In either case, the data will be presented in the
same order; only the annotations will differ.  This option may be useful
for piping data into other filters, since each data value appears on a
separate line, fully identified.

@item -l len
Changes the default maximum line length (80) used in formatting lists of
non-character data values.

@item -d float_digits[,double_digits]
Specifies default number of significant digits to use in displaying
floating-point or double precision data values for variables that don't have
a `C_format' attribute.  Floating-point data will be displayed with
@var{float_digits} significant digits.  If @var{double_digits} is also
specoified, double-precision values will be displayed with that many
significant digits.  If a variable has a `C_format' attribute, that
overrides any specified floating-point default.  In the absence of any
@samp{-d} specifications, floating-point and double-precision data are
displayed with 7 and 15 significant digits respectively.  CDL files can be
made smaller if less precision is required.  If both floating-point and
double-presision precisions are specified, the two values must appear
separated by a comma (no blanks) as a single argument to the command.

@item -n name
CDL requires a name for a netCDF data set, for use by @samp{ncgen -b} in
generating a default netCDF file name.  By default, @code{ncdump}
constructs this name from the last component of the pathname of the
input netCDF file by stripping off any extension it has.  Use the
@samp{-n} option to specify a different name.  Although the output file
name used by @samp{ncgen -b} can be specified, it may be wise to have
@code{ncdump} change the default name to avoid inadvertantly overwriting
a valuable netCDF file when using @code{ncdump}, editing the resulting
CDL file, and using @samp{ncgen -b} to generate a new netCDF file from
the edited CDL file.
@end table

@unnumberedsubsec Examples

Look at the structure of the data in the netCDF file @file{foo.nc}:
@example 
ncdump -c foo.nc
@end example

Produce an annotated CDL version of the structure and data in the
netCDF file @file{foo.nc}, using C-style indexing for the annotations:
@example 
ncdump -b c foo.nc > foo.cdl
@end example

Output data for only the variables @code{uwind} and @code{vwind} from
the netCDF file @file{foo.nc}, and show the floating-point data with
only three significant digits of precision:
@example 
ncdump -v uwind,vwind -d 3 foo.nc
@end example

Produce a fully-annotated (one data value per line) listing of the data
for the variable @code{omega}, using Fortran conventions for indices,
and changing the netCDF dataset name in the resulting CDL file to
@code{omega}:
@example 
ncdump -v omega -f fortran -n omega foo.nc > Z.cdl
@end example

@node FAQ, C Interface, Utilities, Top
@chapter Answers to Some Frequently Asked Questions

Here we collect, in one place, answers to some of the most frequently
asked questions about netCDF availability and support.  A more
comprehensive and up-to-date list of answers to frequently asked
questions about netCDF is maintained in a file available for anonymous
FTP access from:
@example
host:  unidata.ucar.edu
file:  pub/netcdf/FAQ
@end example

@menu
* What is netCDF?::       
* How to get it::         Availability of the netCDF software
* Platforms::             What platforms it runs on
* netCDF and CDF::        Connection with NASA's Common Data Format
* netCDF and HDF::        Connection with NCSA's Hierarchical Data Format
* pub/netcdf::            Some files with volatile netCDF information
* XDR error messages::    Why occasional error messages from XDR layer
* representing data::     Ways to represent data in netCDF
* data compression::      Data compression in netCDF
* Other utilities::             What netCDF utilities exist
* mailing list::          The netCDF mailing lists
* bug reports::           Where to send bug reports
* Popularity::            Is netCDF widely used?
* WAIS/gopher access::    WIAS or gopher access to netCDF information
@end menu

@node What is netCDF?, How to get it,  , FAQ
@unnumberedsec What is netCDF?

NetCDF (network Common Data Form) is an interface for scientific data
access and a freely-distributed software library that provides an
implementation of the interface.  It was developed by Glenn Davis, Russ
Rew, and Steve Emmerson at the Unidata Program Center in Boulder,
Colorado.  The netCDF library also defines a machine-independent format
for representing scientific data.  Together, the interface, library, and
format support the creation, access, and sharing of scientific data.

NetCDF data is:

@itemize @bullet
@item
Self-Describing.  A netCDF file includes information about the data it
contains.
@item
Network-transparent.  A netCDF file is represented in a form that can
be accessed by computers with different ways of storing integers,
characters, and floating-point numbers.
@item
Direct-access.  A small subset of a large dataset may be accessed
efficiently, without first reading through all the preceding data.
@item
Appendable.  Data can be appended to a netCDF dataset along one
dimension without copying the dataset or redefining its structure.
The structure of a netCDF dataset can be changed, though this
sometimes causes the dataset to be copied.
@item
Sharable.  One writer and multiple readers may simultaneously access
the same netCDF file.
@end itemize

@node How to get it, Platforms, What is netCDF?, FAQ
@unnumberedsec How do I get the netCDF software package?

@cindex obtaining netCDF software
@cindex FTP access
Via anonymous FTP from
@example
host:       unidata.ucar.edu
file:       pub/netcdf/netcdf.tar.Z
@end example

Make sure the file is transmitted in BINARY mode.  This is version 2.3,
last updated in February 1993, or later.

@node Platforms, netCDF and CDF, How to get it, FAQ
@unnumberedsec What does netCDF run on?

@cindex computing environments
@cindex ports of netCDF
@cindex platforms
Version 2.3 of netCDF has been tested on the following platforms:
@itemize @bullet
@item
SPARCstation, SunOS 4.1.3
@item
DECstation or VAXstation, Ultrix 4.3
@item
VAXstation, VMS
@item
IBM RS-6000, AIX 3.x
@item
IBM PS/2, MSDOS 5.0
@item
IBM PS/2, OS/2
@item
CRAY YMP, UNICOS
@item
SGI, IRIX
@item
HP, HPUX
@end itemize

The experience of outside developers indicates that netCDF is relatively
easy to port to any system that has a C compiler and an XDR library
(eXternal Data Representation, used for NFS and usually supplied by
vendors).

@node netCDF and CDF, netCDF and HDF, Platforms, FAQ
@unnumberedsec What is the connection between netCDF and CDF?

@cindex CDF
CDF was developed at the NASA Space Science Data Center at Goddard, and
is freely available.  It was originally a VMS FORTRAN interface for
scientific data access.  Unidata reimplemented the library from scratch
to use XDR for a machine-independent representation, designed the CDL
text representation for netCDF data, wrote a User's Guide and made other
additions including aggregate data access, single-file implementation,
named dimensions, and variable-specific attributes.

NetCDF and CDF have evolved independently.  CDF now supports many of the
same features as netCDF (aggregate data access, XDR representation,
single-file representation, variable-specific attributes), but some
differences remain (netCDF doesn't support native-mode representation,
CDF doesn't support named dimensions).

@node netCDF and HDF, pub/netcdf, netCDF and CDF, FAQ
@unnumberedsec What is the connection between netCDF and HDF?

@cindex HDF
The National Center for Supercomputing Applications (NCSA) developed the
HDF software and makes it freely available.  HDF is an extensible data
format for self-describing files that was developed independently of
netCDF.  Applications and utilities based on HDF are available that
support raster-image manipulation and display and browsing through
multidimensional scientific data. The HDF software includes a package of
routines for accessing each HDF data type, as well as a lower-level
interface for building packages to support new types.  HDF supports both
C and Fortran interfaces, and it has been successfully ported to a wide
variety of machine architectures and operating systems.  HDF emphasizes
a single common format for data, on which many interfaces can be built.

NCSA has implemented software that provides a netCDF interface to HDF.
With this software, it is possible to use the netCDF calling interface
to place data into an HDF file.  The netCDF calling interface has not
changed and netCDF files stored in XDR format are readable, so existing
programs and data will still be usable (although programs will need to
be relinked to the new library).  There is currently no support for the
mixing of HDF and netCDF structures.  For example, a raster image can
exist in the same file as a netCDF object, but you have to use the
Raster Image interface to read the image and the netCDF interface to
read the netCDF object.  The other HDF interfaces are currently being
modified to allow multi-file access, closer integration with the netCDF
interface will probably be delayed until the end of that project.

Eventually, it may be possible to integrate netCDF objects with the
rest of the HDF tool suite.  Such an integration will then allow tools
written for netCDF and tools written for HDF to both interact
intelligently with the new data files.

@node pub/netcdf, XDR error messages, netCDF and HDF, FAQ
@unnumberedsec What are the files in pub/netcdf/ on unidata.ucar.edu?
@cindex information files
@table @file
@item README
general information about netCDF

@item FAQ
this file of frequently asked questions

@item utilities.txt
a list of software packages currently available or under development for
manipulating and displaying netCDF data

@item guide.ps.Z
a compressed PostScript file of the NetCDF User's Guide.  This is
included in the netcdf.tar.Z distribution, so you don't need both.

@item ncprogs.ps
a draft PostScript document describing an initial set of netCDF operator
and utility programs under development

@item ncprogs.txt
an ASCII version of ncprogs.ps

@item conventions.info
a draft document of some proposed netCDF conventions

@item cdl/
a directory containing some examples of CDL files (an ASCII
representation for netCDF files).

@item msdos/
a directory containing executables and binaries for netCDF under MSDOS
5.0.  These can also be built from the sources in netcdf.tar.Z, if you
have the necessary Microsoft compilers.

@item mac/
a directory containing notes and Macintosh MPW makefiles for porting
netCDF to an Apple Macintosh.  These were contributed by Chuck Denham,
U.S.  Geological Survey.
@end table

@node XDR error messages, representing data, pub/netcdf, FAQ
@unnumberedsec Why do I get XDR error messages when trying to write data?
@cindex XDR errors
Probably due to a write error, perhaps because of exceeding disk quotas,
a full device, or permission problems.  The netCDF library is usually
built on a vendor-supplied XDR library layer.  Sometimes errors occur in
the XDR layer rather than the netCDF layer, and in this case the error
messages from the XDR layer can be cryptic.  For example, if the user is
writing data and exceeds a disk space quota, this might be detected
first in the XDR layer.  Although we try to catch and elaborate on
errors that occur in the XDR layer, sometimes there is not enough
information passed up to calling routines from the XDR layer to make
construction of a meaningful error message possible.

@node representing data, data compression, XDR error messages, FAQ
@unnumberedsec What's the best way to represent data using netCDF?

There are many ways to represent the same information in any
general-purpose data model.  Choices left up to the user in the case of
netCDF include which information to represent as variables or as
variable attributes; what names to choose for variables, dimensions, and
attributes; what order to use for the dimensions of multidimensional
variables; what variables to include in the same netCDF file; and how to
use variable attributes to capture the structure and meaning of data.
We provide some guidelines in the NetCDF User's Guide (@xref{Attributes
and Variables}), but we've found that a little experience helps.
Occasionally we have decided it was useful to change the structure of
netCDF files after experience with how the data is used.

@node data compression, Other utilities, representing data, FAQ
@unnumberedsec Are there plans to add facilities for data compression to netCDF?

We have no plans to add data compression to netCDF (although we do plan
to eventually add a form of transparent data packing on write and
unpacking on read whenever the reserved attributes @code{_Nbits},
@code{_Scale}, and @code{_Offset} are defined).

Hyperslab access and direct access to individual array values conflict
with most simple compression schemes.  With netCDF, the elements of an
array variable can be filled in any order or as cross-sections in any
direction.  NetCDF permits writing elements in one order and reading
them later in different orders.

Some compression methods require that all the data to be compressed are
known before starting the compression.  Techniques like run-length
encoding or anything that depends on exploiting similarities in nearby
values can't be used if nearby values aren't all known at the time some
of the data are to be written.

An alternative that can be implemented above the netCDF library is to
adopt a convention for compressed data that uses a "compression"
attribute to encode the method of compression, e.g.
@example
x:compression = "rle" ;
@end example
for run-length encoding of the data in a variable @code{x}.  Then when you
write the data, compress them into a bland array of bytes and write all
the bytes.  Note that it would be difficult to define the size of such a
variable in advance, since its compressed size depends on its values.
You would also have to give up on hyperslab access for such variables,
but instead read the compressed array in all at once and uncompress it
before using it.

@node Other utilities, mailing list, data compression, FAQ
@unnumberedsec What utilities are available for netCDF?

The only utilities available in the current netCDF distribution are
ncdump and ncgen, for converting netCDF files to an ASCII human-readable
form and for converting from the ASCII human-readable form back to a
binary netCDF file or a C or FORTRAN program for generating the netCDF
file.  In addition, the first release of the netcdf operators package,
containing a few general-purpose netCDF operators, is available from
@code{unidata.ucar.edu} in the file @file{ncopers.tar.Z}.  See the
description of the file @file{utilities.txt} in the answer to the
question above on important files in @file{/pub/netcdf} on
@code{unidata.ucar.edu} for more information.

@node mailing list, bug reports, Other utilities, FAQ
@unnumberedsec Is there a mailing list for netCDF discussions and questions?

Yes - there are two.  The mailing list
@code{netcdfgroup@@unidata.ucar.edu} has over two hundred readers and
gateways; you can subscribe or unsubscribe to the mailing list by
sending mail to @code{netcdfgroup-adm@@unidata.ucar.edu}.

If you would prefer to get only a single daily digest of the postings to
the @code{netcdfgroup} mailing list, subscribe instead to the
@code{netcdfdigest} mailing list by sending a request to
@code{netcdfdigest-adm@@unidata.ucar.edu}.

All the postings to the @code{netcdfgroup} mailing list are archived in the
file @file{mail-archives/netcdfgroup} available via anonymous FTP from
@code{unidata.ucar.edu}.

@node bug reports, Popularity, mailing list, FAQ
@unnumberedsec How do I make a bug report?

If you find a bug, please send a description to
@code{support@@unidata.ucar.edu}.

This is also a better address to use for questions or discussions about
netCDF that you think are not appropriate for the entire
@code{netcdfgroup} mailing list.

@node Popularity, WAIS/gopher access, bug reports, FAQ
@unnumberedsec How widely is netCDF used?

We don't really know, but the netcdfgroup and netcdfdigest mailing lists
have 260 addresses, some of which are aliases to more addresses, in
fourteen countries.  Users in several groups have adopted netCDF as a
standard way to represent at least some kinds of scientific datasets.

@node WAIS/gopher access,  , Popularity, FAQ
@unnumberedsec Is there any WAIS or gopher access to netCDF information?

Yes, @file{netcdf-group.src} is a WAIS source that provides a full-text
search of the netcdfgroup mailing list archive and is registered with
think.com for general use.

Another WAIS source, @file{unidata-support-netcdf.src}, provides a
full-text search of the support questions and answers about netCDF
provided by Unidata support staff.

Both of these WAIS servers and access to other information about Unidata
can be accessed most easily through the Unidata gopher server at
gopher.unidata.ucar.edu.


@node C Interface, Fortran Interface, FAQ, Top
@appendix Summary of C Interface

@example
int nccreate (const char* path, int cmode);
int ncopen (const char* path, int mode);
int ncredef (int ncid);
int ncendef (int ncid);
int ncclose (int ncid);
int ncinquire (int ncid, int* ndims, int* nvars, int* natts, int* recdim);
int ncsync (int ncid);
int ncabort (int ncid);
int ncdimdef (int ncid, const char* name, long length);
int ncdimid (int ncid, const char* name);
int ncdiminq (int ncid, int dimid, char* name, long* length);
int ncdimrename (int ncid, int dimid, const char* name);
int ncvardef (int ncid, const char* name, nc_type datatype, int ndims, 
              const int dimids[]);
int ncvarid (int ncid, const char* name);
int ncvarinq (int ncid, int varid, char* name, nc_type* datatype, int* ndims,
              int dimids[], int* natts);
int ncvarput1 (int ncid, int varid, const long coords[], const void* value);
int ncvarget1 (int ncid, int varid, const long coords[], void* value);
int ncvarput (int ncid, int varid, const long start[], const long count[],
              const void* value);
int ncvarget (int ncid, int varid, const long start[], const long count[],
              void* value);
int ncvarputg (int ncid, int varid, const long start[], const long count[],
              const long stride[], const long imap[], const void* value);
int ncvargetg (int ncid, int varid, const long start[], const long count[],
              const long stride[], const long imap[], void* value);
int ncvarrename (int ncid, int varid, const char* name);
int ncattput (int ncid, int varid, const char* name, nc_type datatype, int len,
              const void* value);
int ncattinq (int ncid, int varid, const char* name, nc_type* datatype,
              int* len);
int ncattget (int ncid, int varid, const char* name, void* value);
int ncattcopy (int incdf, int invar, const char* name, int outcdf, int outvar);
int ncattname (int ncid, int varid, int attnum, char* name);
int ncattrename (int ncid, int varid, const char* name, const char* newname);
int ncattdel (int ncid, int varid, const char* name);
int nctypelen (nc_type datatype);
int ncsetfill (int ncid, int fillmode);
int ncrecput(int ncid, long recnum, void* const datap[]);
int ncrecget(int ncid, long recnum, void* datap[]);
int ncrecinq(int ncid, int *nrecvars, int recvarids[], long recsizes[]);
@end example

@node Fortran Interface, Units, C Interface, Top
@appendix Summary of FORTRAN Interface

Input parameters are in upper case, output parameters are in lower
case.  The FORTRAN types of all the parameters are listed below the
subroutine and function declarations.

@example
INTEGER FUNCTION NCCRE (PATHNAME,CLOBMODE, rcode)
INTEGER FUNCTION NCOPN (PATHNAME,RWMODE, rcode)
SUBROUTINE NCREDF (NCID, rcode)
SUBROUTINE NCENDF (NCID, rcode)
SUBROUTINE NCCLOS (NCID, rcode)
SUBROUTINE NCINQ (NCID, ndims,nvars,natts,recdim,rcode)
SUBROUTINE NCSNC (NCID, rcode)
SUBROUTINE NCABOR (NCID, rcode)
INTEGER FUNCTION NCDDEF (NCID,DIMNAME,SIZE, rcode)
INTEGER FUNCTION NCDID (NCID,DIMNAME, rcode)
SUBROUTINE NCDINQ (NCID,DIMID, dimname,size,rcode)
SUBROUTINE NCDREN (NCID,DIMID,DIMNAME, rcode)
INTEGER FUNCTION NCVDEF (NCID,VARNAME,DATATYPE,NVDIMS,VDIMS, rcode)
INTEGER FUNCTION NCVID (NCID,VARNAME, rcode)
SUBROUTINE NCVINQ (NCID,VARID, varname,datatype,nvdims,vdims,nvatts,rcode)
SUBROUTINE NCVPT1 (NCID,VARID,INDICES,VALUE, rcode)
SUBROUTINE NCVP1C (NCID,VARID,INDICES, CHVAL, rcode)
SUBROUTINE NCVGT1 (NCID,VARID,INDICES, value, rcode)
SUBROUTINE NCVG1C (NCID,VARID,INDICES, chval, rcode)
SUBROUTINE NCVPT (NCID,VARID,START,COUNTS,VALUE, rcode)
SUBROUTINE NCVPTC (NCID,VARID,START,COUNTS,STRING,LENSTR, rcode)
SUBROUTINE NCVPTG (NCID,VARID,START,COUNTS,STRIDE,IMAP,VALUE, rcode)
SUBROUTINE NCVPGC (NCID,VARID,START,COUNTS,STRIDE,IMAP,STRING,rcode)
SUBROUTINE NCVGT (NCID,VARID,START,COUNTS, value,rcode)
SUBROUTINE NCVGTC (NCID,VARID,START,COUNTS, string,LENSTR,rcode)
SUBROUTINE NCVGTG (NCID,VARID,START,COUNTS,STRIDE,IMAP,value,rcode)
SUBROUTINE NCVGGC (NCID,VARID,START,COUNTS,STRIDE,IMAP,string,rcode)
SUBROUTINE NCVREN (NCID,VARID,VARNAME, rcode)
SUBROUTINE NCAPT (NCID,VARID,ATTNAME,DATATYPE,ATTLEN,VALUE, rcode)
SUBROUTINE NCAPTC (NCID,VARID,ATTNAME,DATATYPE,LENSTR,string, rcode)
SUBROUTINE NCAINQ (NCID,VARID,ATTNAME, datatype,attlen,rcode)
SUBROUTINE NCAGT (NCID,VARID,ATTNAME, value,rcode)
SUBROUTINE NCAGTC (NCID,VARID,ATTNAME, string,LENSTR,rcode)
SUBROUTINE NCACPY (INNCID,INVARID,ATTNAME,OUTNCID,OUTVARID, rcode)
SUBROUTINE NCANAM (NCID,VARID,ATTNUM, attname,rcode)
SUBROUTINE NCAREN (NCID,VARID,ATTNAME,NEWNAME, rcode)
SUBROUTINE NCADEL (NCID,VARID,ATTNAME, rcode)
INTEGER FUNCTION NCTLEN (DATATYPE, rcode)
SUBROUTINE NCPOPT (NCOPTS)
SUBROUTINE NCGOPT (ncopts)
INTEGER FUNCTION NCSFIL (NCID,FILLMODE, rcode)

CHARACTER*(*) PATHNAME  ! absolute or relative name of netCDF file
INTEGER CLOBMODE        ! either NCCLOB or NCNOCLOB
INTEGER RWMODE          ! either NCWRITE or NCNOWRIT
INTEGER RCODE           ! returned error code, 0 if no errors
INTEGER NCID            ! netCDF ID, returned by NCCRE or NCOPN
INTEGER NDIMS           ! number of dimensions in netCDF
INTEGER NVARS           ! number of variables in netCDF
INTEGER NATTS           ! number of global attributes in netCDF
INTEGER RECDIM          ! dimension ID of unlimited dimension
CHARACTER*(*) DIMNAME   ! name for dimension
INTEGER SIZE            ! size of dimension
INTEGER DIMID           ! dimension ID from NCDDEF or NCDID
CHARACTER*(*) VARNAME   ! name for variable
INTEGER DATATYPE        ! data type code, one of NCBYTE, @dots{}, NCDOUBLE
INTEGER NVDIMS          ! number of dimensions in a variable
INTEGER VDIMS(NDIMS)    ! dimension IDs for a variable, giving its shape
INTEGER VARID           ! variable ID from NCVDEF or NCVID, or NCGLOBAL
INTEGER NVATTS          ! number of attributes assigned to a variable
INTEGER INDICES(NDIMS)  ! coordinates of a single element of a variable
CHARACTER CHVAL         ! character value of variable or attribute
CHARACTER*(*) STRING    ! character array value of variable or attribute
INTEGER LENSTR          ! length of character array value
DOUBLE VALUE            ! double precision value of variable or attribute
REAL VALUE              ! real value of variable or attribute
INTEGER VALUE           ! integer value of variable or attribute
INTEGER START(NVDIMS)   ! corner of hyperslab of values of a variable
INTEGER COUNTS(NVDIMS)  ! edge lengths of hyperslab of values
INTEGER STRIDE(NVDIMS)  ! netCDF variable dimensional strides
INTEGER IMAP(NVDIMS)    ! index mapping vector
CHARACTER*(*) ATTNAME   ! attribute name
INTEGER ATTLEN          ! number of elements in an attribute vector
INTEGER INNCID          ! input netCDF ID
INTEGER INVARID         ! input variable ID
INTEGER OUTNCID         ! output netCDF ID
INTEGER OUTVARID        ! output variable ID
INTEGER ATTNUM          ! attribute number
CHARACTER*(*) NEWNAME   ! new attribute name
INTEGER FILLMODE        ! NCNOFILL or NCFILL, for setting fill mode
@end example

@node Units, Name Index, Fortran Interface, Top
@appendix Units

The Unidata Program Center has developed a units library to 
convert between
formatted and binary forms of units specifications and perform unit
algebra on the binary form.  
Though the units library is self-contained and there is no dependency 
between it and the netCDF library, it is nevertheless useful in writing
generic netCDF programs and we suggest you obtain it.
A compressed tar file for the library is
available from the file @code{pub/sdm/udunits<version>.tar.Z} in the 
anonymous FTP directory of @code{unidata.ucar.edu}.

The following are examples of units strings that can be interpreted by
the @code{utScan()} function of the Unidata units library:
@example
10 kilogram.meters/seconds2
10 kg-m/sec2
10 kg m/s^2
10 kilogram meter second-2
(PI radian)2
degF
100rpm
geopotential meters
33 feet water
milliseconds since 1992-12-31 12:34:0.1 -7:00
@end example

A unit is specified as an arbitrary product of constants and unit-names
raised to arbitrary integral powers.  Division is indicated by a slash
@samp{/}.  Multiplication is indicated by whitespace, a period @samp{.},
or a hyphen @samp{-}.  Exponentiation is indicated by an integer suffix
or by the exponentiation operators @samp{^} and @samp{**}.  Parentheses
may be used for grouping and disambiguation.  The timestamp in the last
example is handled as a special case.

Arbitrary Galilean transformations (i.e. @emph{y = ax + b}) are
allowed.  In particular, temperature conversions are
correctly handled.  The specification:

@example
degF @@ 32
@end example

indicates a Fahrenheit scale with the origin shifted to
thirty-two degrees Fahrenheit (i.e. to zero Celsius).  Thus,
the Celsius scale is equivalent to the following unit:

@example
1.8 degF @@ 32
@end example

Note that the origin-shift operation takes precedence over
multiplication.  In order of increasing precedence, the
operations are division, multiplication, origin-shift, and
exponentiation.

@code{utScan()} understands all the SI prefixes (e.g.  "mega" and
"milli") plus their abbreviations (e.g. "M" and "m")

The function utPrint() always encodes a unit specification
one way.  To reduce misunderstandings, it is recommended
that this encoding style be used as the default. In general,
a unit is encoded in terms of basic units, factors, and
exponents.  Basic units are separated by spaces, and any
exponent directly appends its associated unit.  The above
examples would be encoded as follows:

@example
10 kilogram meter second-2
9.8696044 radian2
0.555556 kelvin @@ 255.372
10.471976 radian second-1
9.80665 meter2 second-2
98636.5 kilogram meter-1 second-2
0.001 seconds since 1992-12-31 19:34:0.1000 UTC
@end example

(Note that the Fahrenheit unit is encoded as a deviation, in
fractional kelvins, from an origin at 255.372 kelvin, and that the time
in the last example has been referenced to UTC.)

The database for the units library is a formatted file containing unit 
definitions and is
used to initialize this package.  It is the first place to look to
discover the set of valid names and symbols.

The format for the units-file is documented internally and the file may be
modified by the user as necessary.  In particular, additional units and
constants may be easily added (including variant spellings of existing
units or constants).

@code{utScan()} is case-sensitive.  If this causes difficulties, you
might try making appropriate additional entries to the
units-file.

Some unit abbreviations in the default units-file might seem
counter-intuitive.  In particular, note the following:

@example
For       Use               Not     Which Instead Means

Celsius   `Celsius'         `C'     coulomb
gram      `gram'            `g'     <standard free fall>
gallon    `gallon'          `gal'   <acceleration>
radian    `radian'          `rad'   <absorbed dose>
Newton    `newton' or `N'   `nt'    nit (unit of photometry)
@end example

For additional information on this units library, please consult the manual
pages that come with the distribution.

@node Name Index, General Index, Units, Top
@unnumbered Function and Variable Index

@printindex fn

@node General Index,  , Name Index, Top
@unnumbered General Index

@printindex cp


@c Print the tables of contents
@contents

@c That's all
@bye
