in NetCDF Fortran 90 - Unidata - University Corporation for ...
in NetCDF Fortran 90 - Unidata - University Corporation for ...
in NetCDF Fortran 90 - Unidata - University Corporation for ...
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
<strong>NetCDF</strong> Version 3.6.0<br />
December 2004<br />
Russ Rew, Glenn Davis, Steve Emmerson, and Harvey Davies<br />
<strong>Unidata</strong> Program Center
Copyright c○ 2004 <strong>University</strong> <strong>Corporation</strong> <strong>for</strong> Atmospheric Research<br />
Permission is granted to make and distribute verbatim copies of this manual provided that<br />
the copyright notice and these paragraphs are preserved on all copies. The software and any<br />
accompany<strong>in</strong>g written materials are provided “as is” without warranty of any k<strong>in</strong>d. UCAR<br />
expressly disclaims all warranties of any k<strong>in</strong>d, either expressed or implied, <strong>in</strong>clud<strong>in</strong>g but not<br />
limited to the implied warranties of merchantability and fitness <strong>for</strong> a particular purpose.<br />
The <strong>Unidata</strong> Program Center is managed by the <strong>University</strong> <strong>Corporation</strong> <strong>for</strong> Atmospheric<br />
Research and sponsored by the National Science Foundation. Any op<strong>in</strong>ions, f<strong>in</strong>d<strong>in</strong>gs, conclusions,<br />
or recommendations expressed <strong>in</strong> this publication are those of the author(s) and<br />
do not necessarily reflect the views of the National Science Foundation.<br />
Mention of any commercial company or product <strong>in</strong> this document does not constitute an<br />
endorsement by the <strong>Unidata</strong> Program Center. <strong>Unidata</strong> does not authorize any use of<br />
<strong>in</strong><strong>for</strong>mation from this publication <strong>for</strong> advertis<strong>in</strong>g or publicity purposes.
i<br />
Table of Contents<br />
1 Use of the <strong>NetCDF</strong> Library . . . . . . . . . . . . . . . . 1<br />
1.1 Creat<strong>in</strong>g a <strong>NetCDF</strong> Dataset. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
1.2 Read<strong>in</strong>g a <strong>NetCDF</strong> Dataset with Known Names . . . . . . . . . . . . . . . 2<br />
1.3 Read<strong>in</strong>g a netCDF Dataset with Unknown Names . . . . . . . . . . . . . 2<br />
1.4 Writ<strong>in</strong>g Data <strong>in</strong> an Exist<strong>in</strong>g <strong>NetCDF</strong> Dataset . . . . . . . . . . . . . . . . . 3<br />
1.5 Add<strong>in</strong>g New Dimensions, Variables, Attributes . . . . . . . . . . . . . . . . 4<br />
1.6 Error Handl<strong>in</strong>g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
1.7 Compil<strong>in</strong>g and L<strong>in</strong>k<strong>in</strong>g with the <strong>NetCDF</strong> Library . . . . . . . . . . . . . . 6<br />
2 Datasets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.1 Datasets Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.2 <strong>NetCDF</strong> Library Interface Descriptions . . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.3 NF<strong>90</strong> STRERROR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.4 Get netCDF library version: NF<strong>90</strong> INQ LIBVERS . . . . . . . . . . . . 8<br />
2.5 NF<strong>90</strong> CREATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
2.6 NF<strong>90</strong> OPEN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
2.7 NF<strong>90</strong> REDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
2.8 NF<strong>90</strong> ENDDEF. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />
2.9 NF<strong>90</strong> CLOSE. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
2.10 nf<strong>90</strong> Inquire Family . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />
2.11 NF<strong>90</strong> SYNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
2.12 NF<strong>90</strong> ABORT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />
2.13 NF<strong>90</strong> SET FILL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
3 Dimensions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
3.1 Dimensions Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
3.2 NF<strong>90</strong> DEF DIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
3.3 NF<strong>90</strong> INQ DIMID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
3.4 NF<strong>90</strong> Inquire Dimension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23<br />
3.5 NF<strong>90</strong> RENAME DIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24<br />
4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
4.1 Variables Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
4.2 Language Types Correspond<strong>in</strong>g to netCDF external data types<br />
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
4.3 Create a Variable: NF<strong>90</strong>_DEF_VAR. . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />
4.4 Get a Variable ID from Its Name: NF<strong>90</strong> INQ VARID. . . . . . . . . 29<br />
4.5 Get In<strong>for</strong>mation about a Variable from Its ID:<br />
NF<strong>90</strong> Inquire Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30<br />
4.6 Writ<strong>in</strong>g Data Values: NF<strong>90</strong> PUT VAR . . . . . . . . . . . . . . . . . . . . . . 32<br />
4.7 Read<strong>in</strong>g Data Values: NF<strong>90</strong> GET VAR. . . . . . . . . . . . . . . . . . . . . . 36<br />
4.8 Read<strong>in</strong>g and Writ<strong>in</strong>g Character Str<strong>in</strong>g Values . . . . . . . . . . . . . . . . 41
ii<br />
<strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
4.9 Fill Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42<br />
4.10 NF<strong>90</strong> RENAME VAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43<br />
5 Attributes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />
5.1 Attributes Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />
5.2 Attribute Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45<br />
5.3 Create an Attribute: NF<strong>90</strong> PUT ATT . . . . . . . . . . . . . . . . . . . . . . . 48<br />
5.4 Get In<strong>for</strong>mation about an Attribute: NF<strong>90</strong> Inquire Att and<br />
NF<strong>90</strong> INQ ATTNAME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
5.5 Get Attribute’s Values: NF<strong>90</strong> GET ATT . . . . . . . . . . . . . . . . . . . . 51<br />
5.6 Copy Attribute from One <strong>NetCDF</strong> to Another: NF<strong>90</strong> COPY ATT<br />
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />
5.7 Rename an Attribute: NF<strong>90</strong> RENAME ATT . . . . . . . . . . . . . . . . 55<br />
5.8 NF<strong>90</strong> DEL ATT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />
Appendix A Appendix A - Summary of <strong>Fortran</strong><br />
<strong>90</strong> Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59<br />
Appendix B Appendix B - FORTRAN 77 to<br />
<strong>Fortran</strong> <strong>90</strong> Transition Guide . . . . . . . . . . . . . . 63<br />
The new <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
Changes to Inquiry functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
Changes to put and get function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63<br />
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Chapter 1: Use of the <strong>NetCDF</strong> Library 1<br />
1 Use of the <strong>NetCDF</strong> Library<br />
You can use the netCDF library without know<strong>in</strong>g about all of the netCDF <strong>in</strong>terface. If you<br />
are creat<strong>in</strong>g a netCDF dataset, only a handful of rout<strong>in</strong>es are required to def<strong>in</strong>e the necessary<br />
dimensions, variables, and attributes, and to write the data to the netCDF dataset. (Even<br />
less are needed if you use the ncgen utility to create the dataset be<strong>for</strong>e runn<strong>in</strong>g a program<br />
us<strong>in</strong>g netCDF library calls to write data. See section “ncgen” <strong>in</strong> <strong>NetCDF</strong> Users Guide.)<br />
Similarly, if you are writ<strong>in</strong>g software to access data stored <strong>in</strong> a particular netCDF object,<br />
only a small subset of the netCDF library is required to open the netCDF dataset and access<br />
the data. Authors of generic applications that access arbitrary netCDF datasets need to be<br />
familiar with more of the netCDF library.<br />
In this chapter we provide templates of common sequences of netCDF calls needed <strong>for</strong><br />
common uses. For clarity we present only the names of rout<strong>in</strong>es; omit declarations and error<br />
check<strong>in</strong>g; omit the type-specific suffixes of rout<strong>in</strong>e names <strong>for</strong> variables and attributes; <strong>in</strong>dent<br />
statements that are typically <strong>in</strong>voked multiple times; and use ... to represent arbitrary<br />
sequences of other statements. Full parameter lists are described <strong>in</strong> later chapters.<br />
1.1 Creat<strong>in</strong>g a <strong>NetCDF</strong> Dataset<br />
Here is a typical sequence of netCDF calls used to create a new netCDF dataset:<br />
NF<strong>90</strong>_CREATE<br />
...<br />
NF<strong>90</strong>_DEF_DIM<br />
...<br />
NF<strong>90</strong>_DEF_VAR<br />
...<br />
NF<strong>90</strong>_PUT_ATT<br />
...<br />
NF<strong>90</strong>_ENDDEF<br />
...<br />
NF<strong>90</strong>_PUT_VAR<br />
...<br />
NF<strong>90</strong>_CLOSE<br />
! create netCDF dataset: enter def<strong>in</strong>e mode<br />
! def<strong>in</strong>e dimensions: from name and length<br />
! def<strong>in</strong>e variables: from name, type, dims<br />
! assign attribute values<br />
! end def<strong>in</strong>itions: leave def<strong>in</strong>e mode<br />
! provide values <strong>for</strong> variable<br />
! close: save new netCDF dataset<br />
Only one call is needed to create a netCDF dataset, at which po<strong>in</strong>t you will be <strong>in</strong><br />
the first of two netCDF modes. When access<strong>in</strong>g an open netCDF dataset, it is either<br />
<strong>in</strong> def<strong>in</strong>e mode or data mode. In def<strong>in</strong>e mode, you can create dimensions, variables, and<br />
new attributes, but you cannot read or write variable data. In data mode, you can access<br />
data and change exist<strong>in</strong>g attributes, but you are not permitted to create new dimensions,<br />
variables, or attributes.<br />
One call to NF<strong>90</strong> DEF DIM is needed <strong>for</strong> each dimension created. Similarly, one call<br />
to NF<strong>90</strong> DEF VAR is needed <strong>for</strong> each variable creation, and one call to a member of the<br />
NF<strong>90</strong> PUT ATT family is needed <strong>for</strong> each attribute def<strong>in</strong>ed and assigned a value. To leave<br />
def<strong>in</strong>e mode and enter data mode, call NF<strong>90</strong> ENDDEF.<br />
Once <strong>in</strong> data mode, you can add new data to variables, change old values, and change<br />
values of exist<strong>in</strong>g attributes (so long as the attribute changes do not require more storage<br />
space). Data of all types is written to a netCDF variable us<strong>in</strong>g the NF<strong>90</strong> PUT VAR
2 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
subrout<strong>in</strong>e. S<strong>in</strong>gle values, arrays, or array sections may be supplied to NF<strong>90</strong> PUT VAR;<br />
optional arguments allow the writ<strong>in</strong>g of subsampled or mapped portions of the variable.<br />
(Subsampled and mapped access are general <strong>for</strong>ms of data access that are expla<strong>in</strong>ed later.)<br />
F<strong>in</strong>ally, you should explicitly close all netCDF datasets that have been opened <strong>for</strong> writ<strong>in</strong>g<br />
by call<strong>in</strong>g NF<strong>90</strong> CLOSE. By default, access to the file system is buffered by the netCDF<br />
library. If a program term<strong>in</strong>ates abnormally with netCDF datasets open <strong>for</strong> writ<strong>in</strong>g, your<br />
most recent modifications may be lost. This default buffer<strong>in</strong>g of data is disabled by sett<strong>in</strong>g<br />
the NF<strong>90</strong> SHARE flag when open<strong>in</strong>g the dataset. But even if this flag is set, changes to<br />
attribute values or changes made <strong>in</strong> def<strong>in</strong>e mode are not written out until NF<strong>90</strong> SYNC or<br />
NF<strong>90</strong> CLOSE is called.<br />
1.2 Read<strong>in</strong>g a <strong>NetCDF</strong> Dataset with Known Names<br />
Here we consider the case where you know the names of not only the netCDF datasets, but<br />
also the names of their dimensions, variables, and attributes. (Otherwise you would have<br />
to do "<strong>in</strong>quire" calls.) The order of typical C calls to read data from those variables <strong>in</strong> a<br />
netCDF dataset is:<br />
NF<strong>90</strong>_OPEN<br />
...<br />
NF<strong>90</strong>_INQ_DIMID<br />
...<br />
NF<strong>90</strong>_INQ_VARID<br />
...<br />
NF<strong>90</strong>_GET_ATT<br />
...<br />
NF<strong>90</strong>_GET_VAR<br />
...<br />
NF<strong>90</strong>_CLOSE<br />
! open exist<strong>in</strong>g netCDF dataset<br />
! get dimension IDs<br />
! get variable IDs<br />
! get attribute values<br />
! get values of variables<br />
! close netCDF dataset<br />
First, a s<strong>in</strong>gle call opens the netCDF dataset, given the dataset name, and returns a<br />
netCDF ID that is used to refer to the open netCDF dataset <strong>in</strong> all subsequent calls.<br />
Next, a call to NF<strong>90</strong> INQ DIMID <strong>for</strong> each dimension of <strong>in</strong>terest gets the dimension ID<br />
from the dimension name. Similarly, each required variable ID is determ<strong>in</strong>ed from its name<br />
by a call to NF<strong>90</strong> INQ VARID. Once variable IDs are known, variable attribute values<br />
can be retrieved us<strong>in</strong>g the netCDF ID, the variable ID, and the desired attribute name as<br />
<strong>in</strong>put to NF<strong>90</strong> GET ATT <strong>for</strong> each desired attribute. Variable data values can be directly<br />
accessed from the netCDF dataset with calls to NF<strong>90</strong> GET VAR.<br />
F<strong>in</strong>ally, the netCDF dataset is closed with NF<strong>90</strong> CLOSE. There is no need to close a<br />
dataset open only <strong>for</strong> read<strong>in</strong>g.<br />
1.3 Read<strong>in</strong>g a netCDF Dataset with Unknown Names<br />
It is possible to write programs (e.g., generic software) which do such th<strong>in</strong>gs as process<strong>in</strong>g<br />
every variable, without need<strong>in</strong>g to know <strong>in</strong> advance the names of these variables. Similarly,<br />
the names of dimensions and attributes may be unknown.<br />
Names and other <strong>in</strong><strong>for</strong>mation about netCDF objects may be obta<strong>in</strong>ed from netCDF<br />
datasets by call<strong>in</strong>g <strong>in</strong>quire functions. These return <strong>in</strong><strong>for</strong>mation about a whole netCDF
Chapter 1: Use of the <strong>NetCDF</strong> Library 3<br />
dataset, a dimension, a variable, or an attribute. The follow<strong>in</strong>g template illustrates how<br />
they are used:<br />
NF<strong>90</strong>_OPEN<br />
! open exist<strong>in</strong>g netCDF dataset<br />
...<br />
NF<strong>90</strong>_Inquire<br />
! f<strong>in</strong>d out what is <strong>in</strong> it<br />
...<br />
NF<strong>90</strong>_Inquire_Dimension ! get dimension names, lengths<br />
...<br />
NF<strong>90</strong>_Inquire_Variable ! get variable names, types, shapes<br />
...<br />
NF<strong>90</strong>_INQ_ATTNAME ! get attribute names<br />
...<br />
NF<strong>90</strong>_Inquire_Attribute ! get attribute values<br />
...<br />
NF<strong>90</strong>_GET_ATT ! get attribute values<br />
...<br />
NF<strong>90</strong>_GET_VAR<br />
! get values of variables<br />
...<br />
NF<strong>90</strong>_CLOSE<br />
! close netCDF dataset<br />
As <strong>in</strong> the previous example, a s<strong>in</strong>gle call opens the exist<strong>in</strong>g netCDF dataset, return<strong>in</strong>g<br />
a netCDF ID. This netCDF ID is given to the NF<strong>90</strong> Inquire rout<strong>in</strong>e, which returns the<br />
number of dimensions, the number of variables, the number of global attributes, and the<br />
ID of the unlimited dimension, if there is one.<br />
All the <strong>in</strong>quire functions are <strong>in</strong>expensive to use and require no I/O, s<strong>in</strong>ce the <strong>in</strong><strong>for</strong>mation<br />
they provide is stored <strong>in</strong> memory when a netCDF dataset is first opened.<br />
Dimension IDs use consecutive <strong>in</strong>tegers, beg<strong>in</strong>n<strong>in</strong>g at 1. Also dimensions, once created,<br />
cannot be deleted. There<strong>for</strong>e, know<strong>in</strong>g the number of dimension IDs <strong>in</strong> a netCDF dataset<br />
means know<strong>in</strong>g all the dimension IDs: they are the <strong>in</strong>tegers 1, 2, 3, ...up to the number of<br />
dimensions. For each dimension ID, a call to the <strong>in</strong>quire function NF<strong>90</strong> Inquire Dimension<br />
returns the dimension name and length.<br />
Variable IDs are also assigned from consecutive <strong>in</strong>tegers 1, 2, 3, ... up to the number of<br />
variables. These can be used <strong>in</strong> NF<strong>90</strong> Inquire Variable calls to f<strong>in</strong>d out the names, types,<br />
shapes, and the number of attributes assigned to each variable.<br />
Once the number of attributes <strong>for</strong> a variable is known, successive calls to<br />
NF<strong>90</strong> INQ ATTNAME return the name <strong>for</strong> each attribute given the netCDF ID, variable<br />
ID, and attribute number. Armed with the attribute name, a call to NF<strong>90</strong> Inquire Variable<br />
returns its type and length. Given the type and length, you can allocate enough space to<br />
hold the attribute values. Then a call to NF<strong>90</strong> GET ATT returns the attribute values.<br />
Once the IDs and shapes of netCDF variables are known, data values can be accessed<br />
by call<strong>in</strong>g NF<strong>90</strong> GET VAR.<br />
1.4 Writ<strong>in</strong>g Data <strong>in</strong> an Exist<strong>in</strong>g <strong>NetCDF</strong> Dataset<br />
With write access to an exist<strong>in</strong>g netCDF dataset, you can overwrite data values <strong>in</strong> exist<strong>in</strong>g<br />
variables or append more data to record variables along the unlimited (record) dimension.
4 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
To append more data to non-record variables requires chang<strong>in</strong>g the shape of such variables,<br />
which means creat<strong>in</strong>g a new netCDF dataset, def<strong>in</strong><strong>in</strong>g new variables with the desired<br />
shape, and copy<strong>in</strong>g data. The netCDF data model was not designed to make such "schema<br />
changes" efficient or easy, so it is best to specify the shapes of variables correctly when you<br />
create a netCDF dataset, and to anticipate which variables will later grow by us<strong>in</strong>g the<br />
unlimited dimension <strong>in</strong> their def<strong>in</strong>ition.<br />
The follow<strong>in</strong>g code template lists a typical sequence of calls to overwrite some exist<strong>in</strong>g<br />
values and add some new records to record variables <strong>in</strong> an exist<strong>in</strong>g netCDF dataset with<br />
known variable names:<br />
NF<strong>90</strong>_OPEN<br />
...<br />
NF<strong>90</strong>_INQ_VARID<br />
...<br />
NF<strong>90</strong>_PUT_VAR<br />
...<br />
NF<strong>90</strong>_PUT_ATT<br />
...<br />
NF<strong>90</strong>_CLOSE<br />
! open exist<strong>in</strong>g netCDF dataset<br />
! get variable IDs<br />
! provide new values <strong>for</strong> variables, if any<br />
! provide new values <strong>for</strong> attributes, if any<br />
! close netCDF dataset<br />
A netCDF dataset is first opened by the NF<strong>90</strong> OPEN call. This call puts the open<br />
dataset <strong>in</strong> data mode, which means exist<strong>in</strong>g data values can be accessed and changed,<br />
exist<strong>in</strong>g attributes can be changed, but no new dimensions, variables, or attributes can be<br />
added.<br />
Next, calls to NF<strong>90</strong> INQ VARID get the variable ID from the name, <strong>for</strong> each variable<br />
you want to write. Then each call to NF<strong>90</strong> PUT VAR writes data <strong>in</strong>to a specified variable,<br />
either a s<strong>in</strong>gle value at a time, or a whole set of values at a time, depend<strong>in</strong>g on which<br />
variant of the <strong>in</strong>terface is used. The calls used to overwrite values of non-record variables<br />
are the same as are used to overwrite values of record variables or append new data to record<br />
variables. The difference is that, with record variables, the record dimension is extended by<br />
writ<strong>in</strong>g values that don’t yet exist <strong>in</strong> the dataset. This extends all record variables at once,<br />
writ<strong>in</strong>g "fill values" <strong>for</strong> record variables <strong>for</strong> which the data has not yet been written (but<br />
see Section 4.9 [Fill Values], page 42 to specify different behavior).<br />
Calls to NF<strong>90</strong> PUT ATT may be used to change the values of exist<strong>in</strong>g attributes, although<br />
data that changes after a file is created is typically stored <strong>in</strong> variables rather than<br />
attributes.<br />
F<strong>in</strong>ally, you should explicitly close any netCDF datasets <strong>in</strong>to which data has been written<br />
by call<strong>in</strong>g NF<strong>90</strong> CLOSE be<strong>for</strong>e program term<strong>in</strong>ation. Otherwise, modifications to the<br />
dataset may be lost.<br />
1.5 Add<strong>in</strong>g New Dimensions, Variables, Attributes<br />
An exist<strong>in</strong>g netCDF dataset can be extensively altered. New dimensions, variables, and<br />
attributes can be added or exist<strong>in</strong>g ones renamed, and exist<strong>in</strong>g attributes can be deleted.<br />
Exist<strong>in</strong>g dimensions, variables, and attributes can be renamed. The follow<strong>in</strong>g code template<br />
lists a typical sequence of calls to add new netCDF components to an exist<strong>in</strong>g dataset:<br />
NF<strong>90</strong>_OPEN<br />
...<br />
! open exist<strong>in</strong>g netCDF dataset
Chapter 1: Use of the <strong>NetCDF</strong> Library 5<br />
NF<strong>90</strong>_REDEF<br />
...<br />
NF<strong>90</strong>_DEF_DIM<br />
...<br />
NF<strong>90</strong>_DEF_VAR<br />
...<br />
NF<strong>90</strong>_PUT_ATT<br />
...<br />
NF<strong>90</strong>_ENDDEF<br />
...<br />
NF<strong>90</strong>_PUT_VAR<br />
...<br />
NF<strong>90</strong>_CLOSE<br />
! put it <strong>in</strong>to def<strong>in</strong>e mode<br />
! def<strong>in</strong>e additional dimensions (if any)<br />
! def<strong>in</strong>e additional variables (if any)<br />
! def<strong>in</strong>e other attributes (if any)<br />
! check def<strong>in</strong>itions, leave def<strong>in</strong>e mode<br />
! provide new variable values<br />
! close netCDF dataset<br />
A netCDF dataset is first opened by the NF<strong>90</strong> OPEN call. This call puts the open<br />
dataset <strong>in</strong> data mode, which means exist<strong>in</strong>g data values can be accessed and changed,<br />
exist<strong>in</strong>g attributes can be changed (so long as they do not grow), but noth<strong>in</strong>g can be added.<br />
To add new netCDF dimensions, variables, or attributes you must enter def<strong>in</strong>e mode, by<br />
call<strong>in</strong>g NF<strong>90</strong> REDEF. In def<strong>in</strong>e mode, call NF<strong>90</strong> DEF DIM to def<strong>in</strong>e new dimensions,<br />
NF<strong>90</strong> DEF VAR to def<strong>in</strong>e new variables, and NF<strong>90</strong> PUT ATT to assign new attributes to<br />
variables or enlarge old attributes.<br />
You can leave def<strong>in</strong>e mode and reenter data mode, check<strong>in</strong>g all the new def<strong>in</strong>itions <strong>for</strong><br />
consistency and committ<strong>in</strong>g the changes to disk, by call<strong>in</strong>g NF<strong>90</strong> ENDDEF. If you do not<br />
wish to reenter data mode, just call NF<strong>90</strong> CLOSE, which will have the effect of first call<strong>in</strong>g<br />
NF<strong>90</strong> ENDDEF.<br />
Until the NF<strong>90</strong> ENDDEF call, you may back out of all the redef<strong>in</strong>itions made <strong>in</strong> def<strong>in</strong>e<br />
mode and restore the previous state of the netCDF dataset by call<strong>in</strong>g NF<strong>90</strong> ABORT. You<br />
may also use the NF<strong>90</strong> ABORT call to restore the netCDF dataset to a consistent state<br />
if the call to NF<strong>90</strong> ENDDEF fails. If you have called NF<strong>90</strong> CLOSE from def<strong>in</strong>ition mode<br />
and the implied call to NF<strong>90</strong> ENDDEF fails, NF<strong>90</strong> ABORT will automatically be called to<br />
close the netCDF dataset and leave it <strong>in</strong> its previous consistent state (be<strong>for</strong>e you entered<br />
def<strong>in</strong>e mode).<br />
At most one process should have a netCDF dataset open <strong>for</strong> writ<strong>in</strong>g at one time. The<br />
library is designed to provide limited support <strong>for</strong> multiple concurrent readers with one<br />
writer, via discipl<strong>in</strong>ed use of the NF<strong>90</strong> SYNC function and the NF<strong>90</strong> SHARE flag. If a<br />
writer makes changes <strong>in</strong> def<strong>in</strong>e mode, such as the addition of new variables, dimensions, or<br />
attributes, some means external to the library is necessary to prevent readers from mak<strong>in</strong>g<br />
concurrent accesses and to <strong>in</strong><strong>for</strong>m readers to call NF<strong>90</strong> SYNC be<strong>for</strong>e the next access.<br />
1.6 Error Handl<strong>in</strong>g<br />
The netCDF library provides the facilities needed to handle errors <strong>in</strong> a flexible way. Each<br />
netCDF function returns an <strong>in</strong>teger status value. If the returned status value <strong>in</strong>dicates an<br />
error, you may handle it <strong>in</strong> any way desired, from pr<strong>in</strong>t<strong>in</strong>g an associated error message and<br />
exit<strong>in</strong>g to ignor<strong>in</strong>g the error <strong>in</strong>dication and proceed<strong>in</strong>g (not recommended!). For simplicity,<br />
the examples <strong>in</strong> this guide check the error status and call a separate function to handle any<br />
errors.
6 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
The NF<strong>90</strong> STRERROR function is available to convert a returned <strong>in</strong>teger error status<br />
<strong>in</strong>to an error message str<strong>in</strong>g.<br />
Occasionally, low-level I/O errors may occur <strong>in</strong> a layer below the netCDF library. For<br />
example, if a write operation causes you to exceed disk quotas or to attempt to write to<br />
a device that is no longer available, you may get an error from a layer below the netCDF<br />
library, but the result<strong>in</strong>g write error will still be reflected <strong>in</strong> the returned status value.<br />
1.7 Compil<strong>in</strong>g and L<strong>in</strong>k<strong>in</strong>g with the <strong>NetCDF</strong> Library<br />
Details of how to compile and l<strong>in</strong>k a program that uses the netCDF C or FORTRAN<br />
<strong>in</strong>terfaces differ, depend<strong>in</strong>g on the operat<strong>in</strong>g system, the available compilers, and where the<br />
netCDF library and <strong>in</strong>clude files are <strong>in</strong>stalled. Nevertheless, we provide here examples of<br />
how to compile and l<strong>in</strong>k a program that uses the netCDF library on a Unix plat<strong>for</strong>m, so<br />
that you can adjust these examples to fit your <strong>in</strong>stallation.<br />
Every <strong>Fortran</strong> <strong>90</strong> procedure or module which references netCDF constants or procedures<br />
must have access to the module <strong>in</strong><strong>for</strong>mation created when the netCDF module was compiled.<br />
The suffix <strong>for</strong> this file depends on the compiler, but is often .MOD. Most <strong>Fortran</strong> <strong>90</strong><br />
compilers do not allow you to specify an alternative location <strong>for</strong> this file as you might the<br />
location of external libraries. The simplest solution, there<strong>for</strong>e, is to create a symbolic l<strong>in</strong>k<br />
from the directory <strong>in</strong> which your code resides to the location of the pre-compiled netCDF<br />
module. For example:<br />
ln -s /usr/local/netcdf/src/f<strong>90</strong>/netcdf.mod .<br />
You may then compile source files which reference netCDF constants or procedures.<br />
f<strong>90</strong> -c mymodule.f<strong>90</strong><br />
Unless the netCDF library is <strong>in</strong>stalled <strong>in</strong> a standard directory where the l<strong>in</strong>ker always<br />
looks, you must use the -L and -l options to l<strong>in</strong>k an object file that uses the netCDF library.<br />
For example:<br />
f<strong>90</strong> -o myprogram myprogram.o -L/usr/local/netcdf/lib -lnetcdf
Chapter 2: Datasets 7<br />
2 Datasets<br />
2.1 Datasets Introduction<br />
This chapter presents the <strong>in</strong>terfaces of the netCDF functions that deal with a netCDF<br />
dataset or the whole netCDF library.<br />
A netCDF dataset that has not yet been opened can only be referred to by its dataset<br />
name. Once a netCDF dataset is opened, it is referred to by a netCDF ID, which is a small<br />
nonnegative <strong>in</strong>teger returned when you create or open the dataset. A netCDF ID is much<br />
like a file descriptor <strong>in</strong> C or a logical unit number <strong>in</strong> FORTRAN. In any s<strong>in</strong>gle program,<br />
the netCDF IDs of dist<strong>in</strong>ct open netCDF datasets are dist<strong>in</strong>ct. A s<strong>in</strong>gle netCDF dataset<br />
may be opened multiple times and will then have multiple dist<strong>in</strong>ct netCDF IDs; however<br />
at most one of the open <strong>in</strong>stances of a s<strong>in</strong>gle netCDF dataset should permit writ<strong>in</strong>g. When<br />
an open netCDF dataset is closed, the ID is no longer associated with a netCDF dataset.<br />
Functions that deal with the netCDF library <strong>in</strong>clude:<br />
• Get version of library.<br />
• Get error message correspond<strong>in</strong>g to a returned error code.<br />
The operations supported on a netCDF dataset as a s<strong>in</strong>gle object are:<br />
• Create, given dataset name and whether to overwrite or not.<br />
• Open <strong>for</strong> access, given dataset name and read or write <strong>in</strong>tent.<br />
• Put <strong>in</strong>to def<strong>in</strong>e mode, to add dimensions, variables, or attributes.<br />
• Take out of def<strong>in</strong>e mode, check<strong>in</strong>g consistency of additions.<br />
• Close, writ<strong>in</strong>g to disk if required.<br />
• Inquire about the number of dimensions, number of variables, number of global attributes,<br />
and ID of the unlimited dimension, if any.<br />
• Synchronize to disk to make sure it is current.<br />
• Set and unset nofill mode <strong>for</strong> optimized sequential writes.<br />
• After a summary of conventions used <strong>in</strong> describ<strong>in</strong>g the netCDF <strong>in</strong>terfaces, the rest of<br />
this chapter presents a detailed description of the <strong>in</strong>terfaces <strong>for</strong> these operations.<br />
2.2 <strong>NetCDF</strong> Library Interface Descriptions<br />
Each <strong>in</strong>terface description <strong>for</strong> a particular netCDF function <strong>in</strong> this and later chapters conta<strong>in</strong>s:<br />
• a description of the purpose of the function;<br />
• a <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface block that presents the type and order of the <strong>for</strong>mal parameters<br />
to the function;<br />
• a description of each <strong>for</strong>mal parameter <strong>in</strong> the C <strong>in</strong>terface;<br />
• a list of possible error conditions; and<br />
• an example of a <strong>Fortran</strong> <strong>90</strong> program fragment call<strong>in</strong>g the netCDF function (and perhaps<br />
other netCDF functions).
8 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
The examples follow a simple convention <strong>for</strong> error handl<strong>in</strong>g, always check<strong>in</strong>g the error<br />
status returned from each netCDF function call and call<strong>in</strong>g a handle error function <strong>in</strong> case<br />
an error was detected. For an example of such a function, see Section 5.2 "Get error message<br />
correspond<strong>in</strong>g to error status: nc strerror".<br />
2.3 NF<strong>90</strong> STRERROR<br />
The function NF<strong>90</strong> STRERROR returns a static reference to an error message str<strong>in</strong>g correspond<strong>in</strong>g<br />
to an <strong>in</strong>teger netCDF error status or to a system error number, presumably<br />
returned by a previous call to some other netCDF function. The list of netCDF error<br />
status codes is available <strong>in</strong> the appropriate <strong>in</strong>clude file <strong>for</strong> each language b<strong>in</strong>d<strong>in</strong>g.<br />
Usage<br />
NCERR<br />
Errors<br />
function nf<strong>90</strong>_strerror(ncerr)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncerr<br />
character(len = 80) :: nf<strong>90</strong>_strerror<br />
An error status that might have been returned from a previous call to some<br />
netCDF function.<br />
If you provide an <strong>in</strong>valid <strong>in</strong>teger error status that does not correspond to any netCDF error<br />
message or or to any system error message (as understood by the system strerror function),<br />
NF<strong>90</strong> STRERROR returns a str<strong>in</strong>g <strong>in</strong>dicat<strong>in</strong>g that there is no such error status.<br />
Example<br />
Here is an example of a simple error handl<strong>in</strong>g function that uses NF<strong>90</strong> STRERROR to pr<strong>in</strong>t<br />
the error message correspond<strong>in</strong>g to the netCDF error status returned from any netCDF<br />
function call and then exit:<br />
subrout<strong>in</strong>e handle_err(status)<br />
<strong>in</strong>teger, <strong>in</strong>tent ( <strong>in</strong>) :: status<br />
if(status /= nf<strong>90</strong>_noerr) then<br />
pr<strong>in</strong>t *, trim(nf<strong>90</strong>_strerror(status))<br />
stop "Stopped"<br />
end if<br />
end subrout<strong>in</strong>e handle_err<br />
2.4 Get netCDF library version: NF<strong>90</strong> INQ LIBVERS<br />
The function NF<strong>90</strong> INQ LIBVERS returns a str<strong>in</strong>g identify<strong>in</strong>g the version of the netCDF<br />
library, and when it was built.<br />
Usage<br />
function nf<strong>90</strong>_<strong>in</strong>q_libvers()<br />
character(len = 80) :: nf<strong>90</strong>_<strong>in</strong>q_libvers
Chapter 2: Datasets 9<br />
Errors<br />
This function takes no arguments, and returns no error status.<br />
Example<br />
Here is an example us<strong>in</strong>g nc <strong>in</strong>q libvers to pr<strong>in</strong>t the version of the netCDF library with<br />
which the program is l<strong>in</strong>ked:<br />
pr<strong>in</strong>t *, trim(nf<strong>90</strong>_<strong>in</strong>q_libvers())<br />
2.5 NF<strong>90</strong> CREATE<br />
This function creates a new netCDF dataset, return<strong>in</strong>g a netCDF ID that can subsequently<br />
be used to refer to the netCDF dataset <strong>in</strong> other netCDF function calls. The new netCDF<br />
dataset opened <strong>for</strong> write access and placed <strong>in</strong> def<strong>in</strong>e mode, ready <strong>for</strong> you to add dimensions,<br />
variables, and attributes.<br />
A creation mode flag specifies whether to overwrite any exist<strong>in</strong>g dataset with the same<br />
name and whether access to the dataset is shared.<br />
Usage<br />
path<br />
function nf<strong>90</strong>_create(path, cmode, ncid)<br />
character (len = *), <strong>in</strong>tent(<strong>in</strong> ) :: path<br />
<strong>in</strong>teger, <strong>in</strong>tent(<strong>in</strong> ) :: cmode<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong> ) :: <strong>in</strong>itialsize<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong>out) :: chunksize<br />
<strong>in</strong>teger, <strong>in</strong>tent( out) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_create<br />
The file name of the new netCDF dataset.<br />
cmode The creation mode flag. The follow<strong>in</strong>g flags are available:<br />
NF<strong>90</strong> NOCLOBBER, NF<strong>90</strong> SHARE, and NF<strong>90</strong> 64BIT OFFSET.<br />
Sett<strong>in</strong>g NF<strong>90</strong> NOCLOBBER means you do not want to clobber (overwrite) an<br />
exist<strong>in</strong>g dataset; an error (NF<strong>90</strong> EEXIST) is returned if the specified dataset<br />
already exists.<br />
The NF<strong>90</strong> SHARE flag is appropriate when one process may be writ<strong>in</strong>g the<br />
dataset and one or more other processes read<strong>in</strong>g the dataset concurrently; it<br />
means that dataset accesses are not buffered and cach<strong>in</strong>g is limited. S<strong>in</strong>ce<br />
the buffer<strong>in</strong>g scheme is optimized <strong>for</strong> sequential access, programs that do not<br />
access data sequentially may see some per<strong>for</strong>mance improvement by sett<strong>in</strong>g the<br />
NF<strong>90</strong> SHARE flag.<br />
Sett<strong>in</strong>g NF<strong>90</strong> 64BIT OFFSET causes netCDF to create a 64-bit offset <strong>for</strong>mat<br />
file, <strong>in</strong>stead of a netCDF classic <strong>for</strong>mat file. The 64-bit offset <strong>for</strong>mat imposes far<br />
fewer restrictions on very large (i.e. over 2 GB) data files. See section “Large<br />
File Support” <strong>in</strong> <strong>NetCDF</strong> Users’ Guide.<br />
A zero value (def<strong>in</strong>ed <strong>for</strong> convenience as NF<strong>90</strong> CLOBBER) specifies the default<br />
behavior: overwrite any exist<strong>in</strong>g dataset with the same file name and buffer and
10 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
cache accesses <strong>for</strong> efficiency. The dataset will be <strong>in</strong> netCDF classic <strong>for</strong>mat. See<br />
section “<strong>NetCDF</strong> Classic Format Limitations” <strong>in</strong> <strong>NetCDF</strong> Users’ Guide.<br />
ncid<br />
Returned netCDF ID.<br />
The follow<strong>in</strong>g optional arguments allow additional per<strong>for</strong>mance tun<strong>in</strong>g.<br />
<strong>in</strong>itialsize<br />
The <strong>in</strong>itial size of the file (<strong>in</strong> bytes) at creation time. A value of 0 causes the<br />
file size to be computed when nf<strong>90</strong> enddef is called.<br />
chunksize<br />
Controls a space versus time trade-off, memory allocated <strong>in</strong> the netcdf library<br />
versus number of system calls. Because of <strong>in</strong>ternal requirements, the value may<br />
not be set to exactly the value requested. The actual value chosen is returned.<br />
The library chooses a system-dependent default value if NF<strong>90</strong> SIZEHINT DEFAULT<br />
is supplied as <strong>in</strong>put. If the "preferred I/O block size" is available from the<br />
stat() system call as member st blksize this value is used. Lack<strong>in</strong>g that, twice<br />
the system pagesize is used. Lack<strong>in</strong>g a call to discover the system pagesize,<br />
the default chunksize is set to 8192 bytes.<br />
The chunksize is a property of a given open netcdf descriptor ncid, it is not a<br />
persistent property of the netcdf dataset.<br />
Errors<br />
NF<strong>90</strong> CREATE returns the value NF<strong>90</strong> NOERR if no errors occurred. Possible causes of<br />
errors <strong>in</strong>clude:<br />
• Pass<strong>in</strong>g a dataset name that <strong>in</strong>cludes a directory that does not exist.<br />
• Specify<strong>in</strong>g a dataset name of a file that exists and also specify<strong>in</strong>g NF<strong>90</strong> NOCLOBBER.<br />
• Specify<strong>in</strong>g a mean<strong>in</strong>gless value <strong>for</strong> the creation mode.<br />
• Attempt<strong>in</strong>g to create a netCDF dataset <strong>in</strong> a directory where you don’t have permission<br />
to create files.<br />
Example<br />
In this example we create a netCDF dataset named foo.nc; we want the dataset to be<br />
created <strong>in</strong> the current directory only if a dataset with that name does not already exist:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_create(path = "foo.nc", cmode = nf<strong>90</strong>_noclobber, ncid = ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
2.6 NF<strong>90</strong> OPEN<br />
The function NF<strong>90</strong> OPEN opens an exist<strong>in</strong>g netCDF dataset <strong>for</strong> access.
Chapter 2: Datasets 11<br />
Usage<br />
function nf<strong>90</strong>_open(path, mode, ncid, chunksize)<br />
character (len = *), <strong>in</strong>tent(<strong>in</strong> ) :: path<br />
<strong>in</strong>teger, <strong>in</strong>tent(<strong>in</strong> ) :: mode<br />
<strong>in</strong>teger, <strong>in</strong>tent( out) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong>out) :: chunksize<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_open<br />
path<br />
omode<br />
ncid<br />
File name <strong>for</strong> netCDF dataset to be opened.<br />
A zero value (or NF<strong>90</strong> NOWRITE) specifies the default behavior: open the<br />
dataset with read-only access, buffer<strong>in</strong>g and cach<strong>in</strong>g accesses <strong>for</strong> efficiency<br />
Otherwise, the creation mode is NF<strong>90</strong> WRITE, NF<strong>90</strong> SHARE, or<br />
NF<strong>90</strong> WRITE|NF<strong>90</strong> SHARE. Sett<strong>in</strong>g the NF<strong>90</strong> WRITE flag opens the<br />
dataset with read-write access. ("Writ<strong>in</strong>g" means any k<strong>in</strong>d of change to the<br />
dataset, <strong>in</strong>clud<strong>in</strong>g append<strong>in</strong>g or chang<strong>in</strong>g data, add<strong>in</strong>g or renam<strong>in</strong>g dimensions,<br />
variables, and attributes, or delet<strong>in</strong>g attributes.) The NF<strong>90</strong> SHARE flag<br />
is appropriate when one process may be writ<strong>in</strong>g the dataset and one or<br />
more other processes read<strong>in</strong>g the dataset concurrently; it means that dataset<br />
accesses are not buffered and cach<strong>in</strong>g is limited. S<strong>in</strong>ce the buffer<strong>in</strong>g scheme is<br />
optimized <strong>for</strong> sequential access, programs that do not access data sequentially<br />
may see some per<strong>for</strong>mance improvement by sett<strong>in</strong>g the NF<strong>90</strong> SHARE flag.<br />
Returned netCDF ID.<br />
The follow<strong>in</strong>g optional argument allows additional per<strong>for</strong>mance tun<strong>in</strong>g.<br />
chunksize<br />
Controls a space versus time trade-off, memory allocated <strong>in</strong> the netcdf library<br />
versus number of system calls. Because of <strong>in</strong>ternal requirements, the value may<br />
not be set to exactly the value requested. The actual value chosen is returned.<br />
The library chooses a system-dependent default value if NF<strong>90</strong> SIZEHINT DEFAULT<br />
is supplied as <strong>in</strong>put. If the "preferred I/O block size" is available from the<br />
stat() system call as member st blksize this value is used. Lack<strong>in</strong>g that, twice<br />
the system pagesize is used. Lack<strong>in</strong>g a call to discover the system pagesize,<br />
the default chunksize is set to 8192 bytes.<br />
The chunksize is a property of a given open netcdf descriptor ncid, it is not a<br />
persistent property of the netcdf dataset.<br />
Errors<br />
Otherwise, the re-<br />
NF<strong>90</strong> OPEN returns the value NF<strong>90</strong> NOERR if no errors occurred.<br />
turned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified netCDF dataset does not exist.<br />
• A mean<strong>in</strong>gless mode was specified.
12 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> OPEN to open an exist<strong>in</strong>g netCDF dataset named foo.nc<br />
<strong>for</strong> read-only, non-shared access:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_open(path = "foo.nc", cmode = nf<strong>90</strong>_nowrite, ncid = ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
2.7 NF<strong>90</strong> REDEF<br />
The function NF<strong>90</strong> REDEF puts an open netCDF dataset <strong>in</strong>to def<strong>in</strong>e mode, so dimensions,<br />
variables, and attributes can be added or renamed and attributes can be deleted.<br />
Usage<br />
function nf<strong>90</strong>_redef(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_redef<br />
ncid<br />
netCDF ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Errors<br />
NF<strong>90</strong> REDEF returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the returned<br />
status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified netCDF dataset is already <strong>in</strong> def<strong>in</strong>e mode.<br />
• The specified netCDF dataset was opened <strong>for</strong> read-only.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> REDEF to open an exist<strong>in</strong>g netCDF dataset named foo.nc<br />
and put it <strong>in</strong>to def<strong>in</strong>e mode:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid) ! Open dataset<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_redef(ncid)<br />
! Put the file <strong>in</strong> def<strong>in</strong>e mode<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)
Chapter 2: Datasets 13<br />
2.8 NF<strong>90</strong> ENDDEF<br />
The function NF<strong>90</strong> ENDDEF takes an open netCDF dataset out of def<strong>in</strong>e mode. The<br />
changes made to the netCDF dataset while it was <strong>in</strong> def<strong>in</strong>e mode are checked and committed<br />
to disk if no problems occurred. Non-record variables may be <strong>in</strong>itialized to a "fill value" as<br />
well (see Section 2.13 [NF<strong>90</strong> SET FILL], page 19). The netCDF dataset is then placed <strong>in</strong><br />
data mode, so variable data can be read or written.<br />
This call may <strong>in</strong>volve copy<strong>in</strong>g data under some circumstances. For a more extensive<br />
discussion See section “File Structure and Per<strong>for</strong>mance” <strong>in</strong> <strong>NetCDF</strong> Users Guide.<br />
Usage<br />
ncid<br />
function nf<strong>90</strong>_enddef(ncid, h_m<strong>in</strong>free, v_align, v_m<strong>in</strong>free, r_align)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent( <strong>in</strong>) :: h_m<strong>in</strong>free, v_align, v_m<strong>in</strong>free, r_align<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_enddef<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
The follow<strong>in</strong>g arguments allow additional per<strong>for</strong>mance tun<strong>in</strong>g. Note: these arguments<br />
expose <strong>in</strong>ternals of the netcdf version 1 file <strong>for</strong>mat, and may not be available <strong>in</strong> future netcdf<br />
implementations.<br />
The current netcdf file <strong>for</strong>mat has three sections: the "header" section, the data section<br />
<strong>for</strong> fixed size variables, and the data section <strong>for</strong> variables which have an unlimited dimension<br />
(record variables). The header beg<strong>in</strong>s at the beg<strong>in</strong>n<strong>in</strong>g of the file. The <strong>in</strong>dex (offset) of the<br />
beg<strong>in</strong>n<strong>in</strong>g of the other two sections is conta<strong>in</strong>ed <strong>in</strong> the header. Typically, there is no space<br />
between the sections. This causes copy<strong>in</strong>g overhead to accrue if one wishes to change the<br />
size of the sections, as may happen when chang<strong>in</strong>g the names of th<strong>in</strong>gs, text attribute values,<br />
add<strong>in</strong>g attributes or add<strong>in</strong>g variables. Also, <strong>for</strong> buffered i/o, there may be advantages to<br />
align<strong>in</strong>g sections <strong>in</strong> certa<strong>in</strong> ways.<br />
h_m<strong>in</strong>free<br />
v_m<strong>in</strong>free<br />
v_align<br />
r_align<br />
The follow<strong>in</strong>g parameters allow one to control costs of future calls to nf<strong>90</strong> redef<br />
or nf<strong>90</strong> enddef by request<strong>in</strong>g that some space be available at the end of the<br />
section. The default value <strong>for</strong> both arguments is 0.<br />
Size of the pad (<strong>in</strong> bytes) at the end of the "header" section.<br />
Size of the pad (<strong>in</strong> bytes) at the end of the data section <strong>for</strong> fixed size variables.<br />
The align parameters allow one to set the alignment of the beg<strong>in</strong>n<strong>in</strong>g of<br />
the correspond<strong>in</strong>g sections. The beg<strong>in</strong>n<strong>in</strong>g of the section is rounded up<br />
to an <strong>in</strong>dex which is a multiple of the align parameter. The flag value<br />
NF<strong>90</strong> ALIGN CHUNK tells the library to use the chunksize (see above) as<br />
the align parameter. The default value <strong>for</strong> both arguments is 4 bytes.<br />
The alignment of the beg<strong>in</strong>n<strong>in</strong>g of the data section <strong>for</strong> fixed size variables.<br />
The alignment of the beg<strong>in</strong>n<strong>in</strong>g of the data section <strong>for</strong> variables which have an<br />
unlimited dimension (record variables).
14 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Errors<br />
NF<strong>90</strong> ENDDEF returns the value NF<strong>90</strong> NOERR if no errors occurred.<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified netCDF dataset is not <strong>in</strong> def<strong>in</strong>e mode.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Otherwise, the<br />
• The size of one or more variables exceed the size constra<strong>in</strong>ts <strong>for</strong> whichever variant of<br />
the file <strong>for</strong>mat is <strong>in</strong> use). See section “Large File Support” <strong>in</strong> The <strong>NetCDF</strong> Users’<br />
Guide.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> ENDDEF to f<strong>in</strong>ish the def<strong>in</strong>itions of a new netCDF dataset<br />
named foo.nc and put it <strong>in</strong>to data mode:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_create("foo.nc", nf<strong>90</strong>_noclobber, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
... ! create dimensions, variables, attributes<br />
status = nf<strong>90</strong>_enddef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
2.9 NF<strong>90</strong> CLOSE<br />
The function NF<strong>90</strong> CLOSE closes an open netCDF dataset. If the dataset is <strong>in</strong> def<strong>in</strong>e mode,<br />
NF<strong>90</strong> ENDDEF will be called be<strong>for</strong>e clos<strong>in</strong>g. (In this case, if NF<strong>90</strong> ENDDEF returns an<br />
error, NF<strong>90</strong> ABORT will automatically be called to restore the dataset to the consistent<br />
state be<strong>for</strong>e def<strong>in</strong>e mode was last entered.) After an open netCDF dataset is closed, its<br />
netCDF ID may be reassigned to the next netCDF dataset that is opened or created.<br />
Usage<br />
function nf<strong>90</strong>_close(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_close<br />
ncid<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Errors<br />
NF<strong>90</strong> CLOSE returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the returned<br />
status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• Def<strong>in</strong>e mode was entered and the automatic call made to NF<strong>90</strong> ENDDEF failed.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.
Chapter 2: Datasets 15<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> CLOSE to f<strong>in</strong>ish the def<strong>in</strong>itions of a new netCDF dataset<br />
named foo.nc and release its netCDF ID:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_create("foo.nc", nf<strong>90</strong>_noclobber, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
... ! create dimensions, variables, attributes<br />
status = nf<strong>90</strong>_close(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
2.10 nf<strong>90</strong> Inquire Family<br />
The NF<strong>90</strong> Inquire subrout<strong>in</strong>e returns <strong>in</strong><strong>for</strong>mation about an open netCDF dataset, given<br />
its netCDF ID. The subrout<strong>in</strong>e can be called from either def<strong>in</strong>e mode or data mode, and<br />
returns values <strong>for</strong> any or all of the follow<strong>in</strong>g: the number of dimensions, the number of<br />
variables, the number of global attributes, and the dimension ID of the dimension def<strong>in</strong>ed<br />
with unlimited length, if any.<br />
No I/O is per<strong>for</strong>med when NF<strong>90</strong> Inquire is called, s<strong>in</strong>ce the required <strong>in</strong><strong>for</strong>mation is<br />
available <strong>in</strong> memory <strong>for</strong> each open netCDF dataset.<br />
Usage<br />
ncid<br />
function nf<strong>90</strong>_Inquire(ncid, nDimensions, nVariables, nAttributes, &<br />
unlimitedDimId)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(out) :: nDimensions, nVariables, &<br />
nAttributes, unlimitedDimId<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
nDimensions<br />
Returned number of dimensions def<strong>in</strong>ed <strong>for</strong> this netCDF dataset.<br />
nVariables<br />
Returned number of variables def<strong>in</strong>ed <strong>for</strong> this netCDF dataset.<br />
nAttributes<br />
Returned number of global attributes def<strong>in</strong>ed <strong>for</strong> this netCDF dataset.<br />
unlimitedDimID<br />
Returned ID of the unlimited dimension, if there is one <strong>for</strong> this netCDF dataset.<br />
If no unlimited length dimension has been def<strong>in</strong>ed, -1 is returned.<br />
Errors<br />
Function NF<strong>90</strong> Inquire returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:
16 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g nf<strong>90</strong> Inquire to f<strong>in</strong>d out about a netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, nDims, nVars, nGlobalAtts, unlimDimID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = Nf<strong>90</strong>_Inquire(ncid, nDims, nVars, nGlobalAtts, unlimdimid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = Nf<strong>90</strong>_Inquire(ncid, nDimensions = nDims, &<br />
unlimitedDimID = unlimdimid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
2.11 NF<strong>90</strong> SYNC<br />
The function NF<strong>90</strong> SYNC offers a way to synchronize the disk copy of a netCDF dataset<br />
with <strong>in</strong>-memory buffers. There are two reasons you might want to synchronize after writes:<br />
• To m<strong>in</strong>imize data loss <strong>in</strong> case of abnormal term<strong>in</strong>ation, or<br />
• To make data available to other processes <strong>for</strong> read<strong>in</strong>g immediately after it is written.<br />
But note that a process that already had the dataset open <strong>for</strong> read<strong>in</strong>g would not see the<br />
number of records <strong>in</strong>crease when the writ<strong>in</strong>g process calls NF<strong>90</strong> SYNC; to accomplish<br />
this, the read<strong>in</strong>g process must call NF<strong>90</strong> SYNC.<br />
This function is backward-compatible with previous versions of the netCDF library. The<br />
<strong>in</strong>tent was to allow shar<strong>in</strong>g of a netCDF dataset among multiple readers and one writer, by<br />
hav<strong>in</strong>g the writer call NF<strong>90</strong> SYNC after writ<strong>in</strong>g and the readers call NF<strong>90</strong> SYNC be<strong>for</strong>e<br />
each read. For a writer, this flushes buffers to disk. For a reader, it makes sure that the<br />
next read will be from disk rather than from previously cached buffers, so that the reader<br />
will see changes made by the writ<strong>in</strong>g process (e.g., the number of records written) without<br />
hav<strong>in</strong>g to close and reopen the dataset. If you are only access<strong>in</strong>g a small amount of data,<br />
it can be expensive <strong>in</strong> computer resources to always synchronize to disk after every write,<br />
s<strong>in</strong>ce you are giv<strong>in</strong>g up the benefits of buffer<strong>in</strong>g.<br />
An easier way to accomplish shar<strong>in</strong>g (and what is now recommended) is to have the<br />
writer and readers open the dataset with the NF<strong>90</strong> SHARE flag, and then it will not be<br />
necessary to call NF<strong>90</strong> SYNC at all. However, the NF<strong>90</strong> SYNC function still provides<br />
f<strong>in</strong>er granularity than the NF<strong>90</strong> SHARE flag, if only a few netCDF accesses need to be<br />
synchronized among processes.<br />
It is important to note that changes to the ancillary data, such as attribute values, are<br />
not propagated automatically by use of the NF<strong>90</strong> SHARE flag. Use of the NF<strong>90</strong> SYNC<br />
function is still required <strong>for</strong> this purpose.<br />
Shar<strong>in</strong>g datasets when the writer enters def<strong>in</strong>e mode to change the data schema requires<br />
extra care. In previous releases, after the writer left def<strong>in</strong>e mode, the readers were left
Chapter 2: Datasets 17<br />
look<strong>in</strong>g at an old copy of the dataset, s<strong>in</strong>ce the changes were made to a new copy. The<br />
only way readers could see the changes was by clos<strong>in</strong>g and reopen<strong>in</strong>g the dataset. Now the<br />
changes are made <strong>in</strong> place, but readers have no knowledge that their <strong>in</strong>ternal tables are now<br />
<strong>in</strong>consistent with the new dataset schema. If netCDF datasets are shared across redef<strong>in</strong>ition,<br />
some mechanism external to the netCDF library must be provided that prevents access by<br />
readers dur<strong>in</strong>g redef<strong>in</strong>ition and causes the readers to call NF<strong>90</strong> SYNC be<strong>for</strong>e any subsequent<br />
access.<br />
When call<strong>in</strong>g NF<strong>90</strong> SYNC, the netCDF dataset must be <strong>in</strong> data mode. A netCDF<br />
dataset <strong>in</strong> def<strong>in</strong>e mode is synchronized to disk only when NF<strong>90</strong> ENDDEF is called. A process<br />
that is read<strong>in</strong>g a netCDF dataset that another process is writ<strong>in</strong>g may call NF<strong>90</strong> SYNC<br />
to get updated with the changes made to the data by the writ<strong>in</strong>g process (e.g., the number<br />
of records written), without hav<strong>in</strong>g to close and reopen the dataset.<br />
Data is automatically synchronized to disk when a netCDF dataset is closed, or whenever<br />
you leave def<strong>in</strong>e mode.<br />
Usage<br />
function nf<strong>90</strong>_sync(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_sync<br />
ncid<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Errors<br />
NF<strong>90</strong> SYNC returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the returned<br />
status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The netCDF dataset is <strong>in</strong> def<strong>in</strong>e mode.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> SYNC to synchronize the disk writes of a netCDF dataset<br />
named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! write data or change attributes<br />
...<br />
status = NF<strong>90</strong>_SYNC(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)
18 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
2.12 NF<strong>90</strong> ABORT<br />
You no longer need to call this function, s<strong>in</strong>ce it is called automatically by NF<strong>90</strong> CLOSE <strong>in</strong><br />
case the dataset is <strong>in</strong> def<strong>in</strong>e mode and someth<strong>in</strong>g goes wrong with committ<strong>in</strong>g the changes.<br />
The function NF<strong>90</strong> ABORT just closes the netCDF dataset, if not <strong>in</strong> def<strong>in</strong>e mode. If the<br />
dataset is be<strong>in</strong>g created and is still <strong>in</strong> def<strong>in</strong>e mode, the dataset is deleted. If def<strong>in</strong>e mode<br />
was entered by a call to NF<strong>90</strong> REDEF, the netCDF dataset is restored to its state be<strong>for</strong>e<br />
def<strong>in</strong>ition mode was entered and the dataset is closed.<br />
Usage<br />
function nf<strong>90</strong>_abort(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_abort<br />
ncid<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Errors<br />
NF<strong>90</strong> ABORT returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the returned<br />
status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• When called from def<strong>in</strong>e mode while creat<strong>in</strong>g a netCDF dataset, deletion of the dataset<br />
failed.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> ABORT to back out of redef<strong>in</strong>itions of a dataset named<br />
foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, LatDimID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_redef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_def_dim(ncid, "Lat", 18, LatDimID)<br />
if (status /= nf<strong>90</strong>_noerr) then ! Dimension def<strong>in</strong>ition failed<br />
call handle_err(status)<br />
status = nf<strong>90</strong>_abort(ncid) ! Abort redef<strong>in</strong>itions<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
end if<br />
...
Chapter 2: Datasets 19<br />
2.13 NF<strong>90</strong> SET FILL<br />
This function is <strong>in</strong>tended <strong>for</strong> advanced usage, to optimize writes under some circumstances<br />
described below. The function NF<strong>90</strong> SET FILL sets the fill mode <strong>for</strong> a netCDF dataset<br />
open <strong>for</strong> writ<strong>in</strong>g and returns the current fill mode <strong>in</strong> a return parameter. The fill mode can<br />
be specified as either NF<strong>90</strong> FILL or NF<strong>90</strong> NOFILL. The default behavior correspond<strong>in</strong>g<br />
to NF<strong>90</strong> FILL is that data is pre-filled with fill values, that is fill values are written when<br />
you create non-record variables or when you write a value beyond data that has not yet<br />
been written. This makes it possible to detect attempts to read data be<strong>for</strong>e it was written.<br />
See Section 4.9 [Fill Values], page 42, <strong>for</strong> more <strong>in</strong><strong>for</strong>mation on the use of fill values. See<br />
Section 5.2 [Attribute Conventions], page 45, <strong>for</strong> <strong>in</strong><strong>for</strong>mation about how to def<strong>in</strong>e your own<br />
fill values.<br />
The behavior correspond<strong>in</strong>g to NF<strong>90</strong> NOFILL overrides the default behavior of prefill<strong>in</strong>g<br />
data with fill values. This can be used to enhance per<strong>for</strong>mance, because it avoids<br />
the duplicate writes that occur when the netCDF library writes fill values that are later<br />
overwritten with data.<br />
A value <strong>in</strong>dicat<strong>in</strong>g which mode the netCDF dataset was already <strong>in</strong> is returned. You can<br />
use this value to temporarily change the fill mode of an open netCDF dataset and then<br />
restore it to the previous mode.<br />
After you turn on NF<strong>90</strong> NOFILL mode <strong>for</strong> an open netCDF dataset, you must be certa<strong>in</strong><br />
to write valid data <strong>in</strong> all the positions that will later be read. Note that nofill mode is only<br />
a transient property of a netCDF dataset open <strong>for</strong> writ<strong>in</strong>g: if you close and reopen the<br />
dataset, it will revert to the default behavior. You can also revert to the default behavior<br />
by call<strong>in</strong>g NF<strong>90</strong> SET FILL aga<strong>in</strong> to explicitly set the fill mode to NF<strong>90</strong> FILL.<br />
There are three situations where it is advantageous to set nofill mode:<br />
1. Creat<strong>in</strong>g and <strong>in</strong>itializ<strong>in</strong>g a netCDF dataset. In this case, you should set nofill mode<br />
be<strong>for</strong>e call<strong>in</strong>g NF<strong>90</strong> ENDDEF and then write completely all non-record variables and<br />
the <strong>in</strong>itial records of all the record variables you want to <strong>in</strong>itialize.<br />
2. Extend<strong>in</strong>g an exist<strong>in</strong>g record-oriented netCDF dataset. Set nofill mode after open<strong>in</strong>g<br />
the dataset <strong>for</strong> writ<strong>in</strong>g, then append the additional records to the dataset completely,<br />
leav<strong>in</strong>g no <strong>in</strong>terven<strong>in</strong>g unwritten records.<br />
3. Add<strong>in</strong>g new variables that you are go<strong>in</strong>g to <strong>in</strong>itialize to an exist<strong>in</strong>g netCDF dataset. Set<br />
nofill mode be<strong>for</strong>e call<strong>in</strong>g NF<strong>90</strong> ENDDEF then write all the new variables completely.<br />
If the netCDF dataset has an unlimited dimension and the last record was written while<br />
<strong>in</strong> nofill mode, then the dataset may be shorter than if nofill mode was not set, but this<br />
will be completely transparent if you access the data only through the netCDF <strong>in</strong>terfaces.<br />
The use of this feature may not be available (or even needed) <strong>in</strong> future releases. Programmers<br />
are cautioned aga<strong>in</strong>st heavy reliance upon this feature.<br />
Usage<br />
function nf<strong>90</strong>_set_fill(ncid, fillmode, old_mode)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, fillmode<br />
<strong>in</strong>teger, <strong>in</strong>tent(out) :: old_mode<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_set_fill
20 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
ncid<br />
fillmode<br />
old_mode<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Desired fill mode <strong>for</strong> the dataset, either NF<strong>90</strong> NOFILL or NF<strong>90</strong> FILL.<br />
Returned current fill mode of the dataset be<strong>for</strong>e this call, either NF<strong>90</strong> NOFILL<br />
or NF<strong>90</strong> FILL.<br />
Errors<br />
NF<strong>90</strong> SET FILL returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
• The specified netCDF ID refers to a dataset open <strong>for</strong> read-only access.<br />
• The fill mode argument is neither NF<strong>90</strong> NOFILL nor NF<strong>90</strong> FILL..<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> SET FILL to set nofill mode <strong>for</strong> subsequent writes of a<br />
netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, oldMode<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! Write data with prefill<strong>in</strong>g behavior<br />
...<br />
status = nf<strong>90</strong>_set_fill(ncid, nf<strong>90</strong>_nofill, oldMode)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! Write data with no prefill<strong>in</strong>g<br />
...
Chapter 3: Dimensions 21<br />
3 Dimensions<br />
3.1 Dimensions Introduction<br />
Dimensions <strong>for</strong> a netCDF dataset are def<strong>in</strong>ed when it is created, while the netCDF dataset<br />
is <strong>in</strong> def<strong>in</strong>e mode. Additional dimensions may be added later by reenter<strong>in</strong>g def<strong>in</strong>e mode. A<br />
netCDF dimension has a name and a length. At most one dimension <strong>in</strong> a netCDF dataset<br />
can have the unlimited length, which means variables us<strong>in</strong>g this dimension can grow along<br />
this dimension.<br />
There is a suggested limit (512) to the number of dimensions that can be def<strong>in</strong>ed <strong>in</strong> a<br />
s<strong>in</strong>gle netCDF dataset. The limit is the value of the constant NF<strong>90</strong> MAX DIMS. The purpose<br />
of the limit is to make writ<strong>in</strong>g generic applications simpler. They need only provide an<br />
array of NF<strong>90</strong> MAX DIMS dimensions to handle any netCDF dataset. The implementation<br />
of the netCDF library does not en<strong>for</strong>ce this advisory maximum, so it is possible to use<br />
more dimensions, if necessary, but netCDF utilities that assume the advisory maximums<br />
may not be able to handle the result<strong>in</strong>g netCDF datasets.<br />
Ord<strong>in</strong>arily, the name and length of a dimension are fixed when the dimension is first<br />
def<strong>in</strong>ed. The name may be changed later, but the length of a dimension (other than the<br />
unlimited dimension) cannot be changed without copy<strong>in</strong>g all the data to a new netCDF<br />
dataset with a redef<strong>in</strong>ed dimension length.<br />
A netCDF dimension <strong>in</strong> an open netCDF dataset is referred to by a small <strong>in</strong>teger called<br />
a dimension ID. In the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface, dimension IDs are 1, 2, 3, ..., <strong>in</strong> the order <strong>in</strong><br />
which the dimensions were def<strong>in</strong>ed.<br />
Operations supported on dimensions are:<br />
• Create a dimension, given its name and length.<br />
• Get a dimension ID from its name.<br />
• Get a dimension’s name and length from its ID.<br />
• Rename a dimension.<br />
3.2 NF<strong>90</strong> DEF DIM<br />
The function NF<strong>90</strong> DEF DIM adds a new dimension to an open netCDF dataset <strong>in</strong> def<strong>in</strong>e<br />
mode. It returns (as an argument) a dimension ID, given the netCDF ID, the dimension<br />
name, and the dimension length. At most one unlimited length dimension, called the record<br />
dimension, may be def<strong>in</strong>ed <strong>for</strong> each netCDF dataset.<br />
Usage<br />
ncid<br />
function nf<strong>90</strong>_def_dim(ncid, name, len, dimid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: len<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_def_dim<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.
22 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
name<br />
len<br />
dimid<br />
Dimension name. Must beg<strong>in</strong> with an alphabetic character, followed by zero or<br />
more alphanumeric characters <strong>in</strong>clud<strong>in</strong>g the underscore (’ ’). Case is significant.<br />
Length of dimension; that is, number of values <strong>for</strong> this dimension as an <strong>in</strong>dex to<br />
variables that use it. This should be either a positive <strong>in</strong>teger or the predef<strong>in</strong>ed<br />
constant NF<strong>90</strong> UNLIMITED.<br />
Returned dimension ID.<br />
Errors<br />
NF<strong>90</strong> DEF DIM returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The netCDF dataset is not <strong>in</strong> def<strong>in</strong>ition mode.<br />
• The specified dimension name is the name of another exist<strong>in</strong>g dimension.<br />
• The specified length is not greater than zero.<br />
• The specified length is unlimited, but there is already an unlimited length dimension<br />
def<strong>in</strong>ed <strong>for</strong> this netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> DEF DIM to create a dimension named lat of length 18<br />
and a unlimited dimension named rec <strong>in</strong> a new netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, LatDimID, RecordDimID<br />
...<br />
status = nf<strong>90</strong>_create("foo.nc", nf<strong>90</strong>_noclobber, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_def_dim(ncid, "Lat", 18, LatDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_def_dim(ncid, "Record", nf<strong>90</strong>_unlimited, RecordDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
3.3 NF<strong>90</strong> INQ DIMID<br />
The function NF<strong>90</strong> INQ DIMID returns (as an argument) the ID of a netCDF dimension,<br />
given the name of the dimension. If ndims is the number of dimensions def<strong>in</strong>ed <strong>for</strong> a netCDF<br />
dataset, each dimension has an ID between 1 and ndims.<br />
Usage<br />
function nf<strong>90</strong>_<strong>in</strong>q_dimid(ncid, name, dimid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_dimid
Chapter 3: Dimensions 23<br />
ncid<br />
name<br />
dimid<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Dimension name, a character str<strong>in</strong>g beg<strong>in</strong>n<strong>in</strong>g with a letter and followed by any<br />
sequence of letters, digits, or underscore (’ ’) characters. Case is significant <strong>in</strong><br />
dimension names.<br />
Returned dimension ID.<br />
Errors<br />
NF<strong>90</strong> INQ DIMID returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The name that was specified is not the name of a dimension <strong>in</strong> the netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> INQ DIMID to determ<strong>in</strong>e the dimension ID of a dimension<br />
named lat, assumed to have been def<strong>in</strong>ed previously <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named<br />
foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, LatDimID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_dimid(ncid, "Lat", LatDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
3.4 NF<strong>90</strong> Inquire Dimension<br />
This function <strong>in</strong><strong>for</strong>mation about a netCDF dimension. In<strong>for</strong>mation about a dimension<br />
<strong>in</strong>cludes its name and its length. The length <strong>for</strong> the unlimited dimension, if any, is the<br />
number of records written so far.<br />
Usage<br />
ncid<br />
dimid<br />
function nf<strong>90</strong>_Inquire_Dimension(ncid, dimid, name, len)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, dimid<br />
character (len = *), optional, <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: len<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Dimension<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Dimension ID, from a previous call to NF<strong>90</strong> INQ DIMID or NF<strong>90</strong> DEF DIM.<br />
name Returned dimension name. The caller must allocate space <strong>for</strong> the returned<br />
name. The maximum possible length, <strong>in</strong> characters, of a dimension name is<br />
given by the predef<strong>in</strong>ed constant NF<strong>90</strong> MAX NAME.
24 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
len<br />
Returned length of dimension. For the unlimited dimension, this is the current<br />
maximum value used <strong>for</strong> writ<strong>in</strong>g any variables with this dimension, that is the<br />
maximum record number.<br />
Errors<br />
These functions return the value NF<strong>90</strong> NOERR if no errors occurred.<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The dimension ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Otherwise, the<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> INQ DIM to determ<strong>in</strong>e the length of a dimension named<br />
lat, and the name and current maximum length of the unlimited dimension <strong>for</strong> an exist<strong>in</strong>g<br />
netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, LatDimID, RecordDimID<br />
<strong>in</strong>teger :: nLats, nRecords<br />
character(len = nf<strong>90</strong>_max_name) :: RecordDimName<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Get ID of unlimited dimension<br />
status = nf<strong>90</strong>_Inquire(ncid, unlimitedDimId = RecordDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_dimid(ncid, "Lat", LatDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! How many values of "lat" are there?<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, LatDimID, len = nLats)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! What is the name of the unlimited dimension, how many records are there?<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, RecordDimID, &<br />
name = RecordDimName, len = Records)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
3.5 NF<strong>90</strong> RENAME DIM<br />
The function NF<strong>90</strong> RENAME DIM renames an exist<strong>in</strong>g dimension <strong>in</strong> a netCDF dataset<br />
open <strong>for</strong> writ<strong>in</strong>g. If the new name is longer than the old name, the netCDF dataset must<br />
be <strong>in</strong> def<strong>in</strong>e mode. You cannot rename a dimension to have the same name as another<br />
dimension.<br />
Usage<br />
function nf<strong>90</strong>_rename_dim(ncid, dimid, name)
Chapter 3: Dimensions 25<br />
ncid<br />
dimid<br />
name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_dim<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Dimension ID, from a previous call to NF<strong>90</strong> INQ DIMID or NF<strong>90</strong> DEF DIM.<br />
New dimension name.<br />
Errors<br />
NF<strong>90</strong> RENAME DIM returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The new name is the name of another dimension.<br />
• The dimension ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
• The new name is longer than the old name and the netCDF dataset is not <strong>in</strong> def<strong>in</strong>e<br />
mode.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> RENAME DIM to rename the dimension lat to latitude <strong>in</strong><br />
an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, LatDimID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! Put <strong>in</strong> def<strong>in</strong>e mode so we can rename the dimension<br />
status = nf<strong>90</strong>_redef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Get the dimension ID <strong>for</strong> "Lat"...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_dimid(ncid, "Lat", LatDimID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! ... and change the name to "Latitude".<br />
status = nf<strong>90</strong>_rename_dim(ncid, LatDimID, "Latitude")<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Leave def<strong>in</strong>e mode<br />
status = nf<strong>90</strong>_enddef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)
26 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide
Chapter 4: Variables 27<br />
4 Variables<br />
4.1 Variables Introduction<br />
Variables <strong>for</strong> a netCDF dataset are def<strong>in</strong>ed when the dataset is created, while the netCDF<br />
dataset is <strong>in</strong> def<strong>in</strong>e mode. Other variables may be added later by reenter<strong>in</strong>g def<strong>in</strong>e mode.<br />
A netCDF variable has a name, a type, and a shape, which are specified when it is def<strong>in</strong>ed.<br />
A variable may also have values, which are established later <strong>in</strong> data mode.<br />
Ord<strong>in</strong>arily, the name, type, and shape are fixed when the variable is first def<strong>in</strong>ed. The<br />
name may be changed, but the type and shape of a variable cannot be changed. However,<br />
a variable def<strong>in</strong>ed <strong>in</strong> terms of the unlimited dimension can grow without bound <strong>in</strong> that<br />
dimension.<br />
A netCDF variable <strong>in</strong> an open netCDF dataset is referred to by a small <strong>in</strong>teger called a<br />
variable ID.<br />
Variable IDs reflect the order <strong>in</strong> which variables were def<strong>in</strong>ed with<strong>in</strong> a netCDF dataset.<br />
Variable IDs are 1, 2, 3,..., <strong>in</strong> the order <strong>in</strong> which the variables were def<strong>in</strong>ed. A function is<br />
available <strong>for</strong> gett<strong>in</strong>g the variable ID from the variable name and vice-versa.<br />
Attributes Chapter 5 [Attributes], page 45 may be associated with a variable to specify<br />
such properties as units.<br />
Operations supported on variables are:<br />
• Create a variable, given its name, data type, and shape.<br />
• Get a variable ID from its name.<br />
• Get a variable’s name, data type, shape, and number of attributes from its ID.<br />
• Put a data value <strong>in</strong>to a variable, given variable ID, <strong>in</strong>dices, and value.<br />
• Put an array of values <strong>in</strong>to a variable, given variable ID, corner <strong>in</strong>dices, edge lengths,<br />
and a block of values.<br />
• Put a subsampled or mapped array-section of values <strong>in</strong>to a variable, given variable ID,<br />
corner <strong>in</strong>dices, edge lengths, stride vector, <strong>in</strong>dex mapp<strong>in</strong>g vector, and a block of values.<br />
• Get a data value from a variable, given variable ID and <strong>in</strong>dices.<br />
• Get an array of values from a variable, given variable ID, corner <strong>in</strong>dices, and edge<br />
lengths.<br />
• Get a subsampled or mapped array-section of values from a variable, given variable ID,<br />
corner <strong>in</strong>dices, edge lengths, stride vector, and <strong>in</strong>dex mapp<strong>in</strong>g vector.<br />
• Rename a variable.<br />
4.2 Language Types Correspond<strong>in</strong>g to netCDF external<br />
data types<br />
The follow<strong>in</strong>g table gives the netCDF external data types and the correspond<strong>in</strong>g type<br />
constants <strong>for</strong> def<strong>in</strong><strong>in</strong>g variables <strong>in</strong> the FORTRAN <strong>in</strong>terface:<br />
Type FORTRAN API Mnemonic Bits<br />
byte NF<strong>90</strong> BYTE 8
28 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
char NF<strong>90</strong> CHAR 8<br />
short NF<strong>90</strong> SHORT 16<br />
<strong>in</strong>t NF<strong>90</strong> INT 32<br />
float NF<strong>90</strong> FLOAT 32<br />
double NF<strong>90</strong> DOUBLE 64<br />
The first column gives the netCDF external data type, which is the same as the CDL data<br />
type. The next column gives the correspond<strong>in</strong>g <strong>Fortran</strong> <strong>90</strong> parameter <strong>for</strong> use <strong>in</strong> netCDF<br />
functions (the parameters are def<strong>in</strong>ed <strong>in</strong> the netCDF <strong>Fortran</strong> <strong>90</strong> module netcdf.f<strong>90</strong>). The<br />
last column gives the number of bits used <strong>in</strong> the external representation of values of the<br />
correspond<strong>in</strong>g type.<br />
Note that there are no netCDF types correspond<strong>in</strong>g to 64-bit <strong>in</strong>tegers or to characters<br />
wider than 8 bits <strong>in</strong> the current version of the netCDF library.<br />
4.3 Create a Variable: NF<strong>90</strong>_DEF_VAR<br />
The function NF<strong>90</strong> DEF VAR adds a new variable to an open netCDF dataset <strong>in</strong> def<strong>in</strong>e<br />
mode. It returns (as an argument) a variable ID, given the netCDF ID, the variable name,<br />
the variable type, the number of dimensions, and a list of the dimension IDs.<br />
Usage<br />
ncid<br />
name<br />
xtype<br />
nvdims<br />
vdims<br />
varid<br />
function nf<strong>90</strong>_def_var(ncid, name, xtype, dimids, varid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: xtype<br />
<strong>in</strong>teger, dimension(:), <strong>in</strong>tent( <strong>in</strong>) :: dimids<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_def_var<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable name. Must beg<strong>in</strong> with an alphabetic character, followed by zero or<br />
more alphanumeric characters <strong>in</strong>clud<strong>in</strong>g the underscore (’ ’). Case is significant.<br />
One of the set of predef<strong>in</strong>ed netCDF external data types. The type of this parameter,<br />
NF<strong>90</strong> TYPE, is def<strong>in</strong>ed <strong>in</strong> the netCDF header file. The valid netCDF<br />
external data types are NF<strong>90</strong> BYTE, NF<strong>90</strong> CHAR, NF<strong>90</strong> SHORT, NF<strong>90</strong> INT,<br />
NF<strong>90</strong> FLOAT, and NF<strong>90</strong> DOUBLE.<br />
Number of dimensions <strong>for</strong> the variable. For example, 2 specifies a matrix, 1 specifies<br />
a vector, and 0 means the variable is a scalar with no dimensions. Must not<br />
be negative or greater than the predef<strong>in</strong>ed constant NF<strong>90</strong> MAX VAR DIMS.<br />
Vector of ndims dimension IDs correspond<strong>in</strong>g to the variable dimensions. If the<br />
ID of the unlimited dimension is <strong>in</strong>cluded, it must be first. This argument is<br />
ignored if ndims is 0.<br />
Returned variable ID.
Chapter 4: Variables 29<br />
Errors<br />
NF<strong>90</strong> DEF VAR returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The netCDF dataset is not <strong>in</strong> def<strong>in</strong>e mode.<br />
• The specified variable name is the name of another exist<strong>in</strong>g variable.<br />
• The specified type is not a valid netCDF type.<br />
• The specified number of dimensions is negative or more than the constant<br />
NF<strong>90</strong> MAX VAR DIMS, the maximum number of dimensions permitted <strong>for</strong> a<br />
netCDF variable.<br />
• One or more of the dimension IDs <strong>in</strong> the list of dimensions is not a valid dimension ID<br />
<strong>for</strong> the netCDF dataset.<br />
• The number of variables would exceed the constant NF<strong>90</strong> MAX VARS, the maximum<br />
number of variables permitted <strong>in</strong> a netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> DEF VAR to create a variable named rh of type double<br />
with three dimensions, time, lat, and lon <strong>in</strong> a new netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: status, ncid<br />
<strong>in</strong>teger :: LonDimId, LatDimId, TimeDimId<br />
<strong>in</strong>teger :: RhVarId<br />
...<br />
status = nf<strong>90</strong>_create("foo.nc", nf<strong>90</strong>_NoClobber, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
...<br />
! Def<strong>in</strong>e the dimensions<br />
status = nf<strong>90</strong>_def_dim(ncid, "lat", 5, LatDimId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
status = nf<strong>90</strong>_def_dim(ncid, "lon", 10, LonDimId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
status = nf<strong>90</strong>_def_dim(ncid, "time", nf<strong>90</strong>_unlimited, TimeDimId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
...<br />
! Def<strong>in</strong>e the variable<br />
status = nf<strong>90</strong>_def_var(ncid, "rh", nf<strong>90</strong>_double, &<br />
(/ LonDimId, LatDimID, TimeDimID /), RhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
4.4 Get a Variable ID from Its Name: NF<strong>90</strong> INQ VARID<br />
The function NF<strong>90</strong> INQ VARID returns the ID of a netCDF variable, given its name.
30 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Usage<br />
ncid<br />
name<br />
varid<br />
Errors<br />
function nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, name, varid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: varid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_varid<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable name <strong>for</strong> which ID is desired.<br />
Returned variable ID.<br />
NF<strong>90</strong> INQ VARID returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified variable name is not a valid name <strong>for</strong> a variable <strong>in</strong> the specified netCDF<br />
dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> INQ VARID to f<strong>in</strong>d out the ID of a variable named rh <strong>in</strong><br />
an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: status, ncid, RhVarId<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
4.5 Get In<strong>for</strong>mation about a Variable from Its ID:<br />
NF<strong>90</strong> Inquire Variable<br />
NF<strong>90</strong> Inquire Variable returns <strong>in</strong><strong>for</strong>mation about a netCDF variable given its ID. In<strong>for</strong>mation<br />
about a variable <strong>in</strong>cludes its name, type, number of dimensions, a list of dimension IDs<br />
describ<strong>in</strong>g the shape of the variable, and the number of variable attributes that have been<br />
assigned to the variable.<br />
Usage<br />
function nf<strong>90</strong>_Inquire_Variable(ncid, varid, name, xtype, ndims, dimids, nAtts)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), optional, <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: xtype, ndims
Chapter 4: Variables 31<br />
ncid<br />
varid<br />
name<br />
xtype<br />
ndims<br />
dimids<br />
natts<br />
<strong>in</strong>teger, dimension(*), optional, <strong>in</strong>tent(out) :: dimids<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: nAtts<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Variable<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID.<br />
Returned variable name. The caller must allocate space <strong>for</strong> the returned name.<br />
The maximum possible length, <strong>in</strong> characters, of a variable name is given by the<br />
predef<strong>in</strong>ed constant NF<strong>90</strong> MAX NAME.<br />
Returned variable type, one of the set of predef<strong>in</strong>ed netCDF external data types.<br />
The type of this parameter, NF<strong>90</strong> TYPE, is def<strong>in</strong>ed <strong>in</strong> the netCDF header<br />
file. The valid netCDF external data types are NF<strong>90</strong> BYTE, NF<strong>90</strong> CHAR,<br />
NF<strong>90</strong> SHORT, NF<strong>90</strong> INT, NF<strong>90</strong> FLOAT, AND NF<strong>90</strong> DOUBLE.<br />
Returned number of dimensions the variable was def<strong>in</strong>ed as us<strong>in</strong>g. For example,<br />
2 <strong>in</strong>dicates a matrix, 1 <strong>in</strong>dicates a vector, and 0 means the variable is a scalar<br />
with no dimensions.<br />
Returned vector of *ndimsp dimension IDs correspond<strong>in</strong>g to the variable dimensions.<br />
The caller must allocate enough space <strong>for</strong> a vector of at least *ndimsp<br />
<strong>in</strong>tegers to be returned. The maximum possible number of dimensions <strong>for</strong> a<br />
variable is given by the predef<strong>in</strong>ed constant NF<strong>90</strong> MAX VAR DIMS.<br />
Returned number of variable attributes assigned to this variable.<br />
These functions return the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> INQ VAR to f<strong>in</strong>d out about a variable named rh <strong>in</strong> an<br />
exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: status, ncid, &<br />
RhVarId &<br />
numDims, numAtts<br />
<strong>in</strong>teger, dimension(nf<strong>90</strong>_max_var_dims) :: rhDimIds<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_error(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Var(ncid, RhVarId, ndims = numDims, natts = numAtts)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)
32 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
status = nf<strong>90</strong>_Inquire_Var(ncid, RhVarId, dimids = rhDimIds(:numDims))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
4.6 Writ<strong>in</strong>g Data Values: NF<strong>90</strong> PUT VAR<br />
The function NF<strong>90</strong> PUT VAR puts one or more data values <strong>in</strong>to the variable of an open<br />
netCDF dataset that is <strong>in</strong> data mode. Required <strong>in</strong>puts are the netCDF ID, the variable ID,<br />
and one or more data values. Optional <strong>in</strong>puts may <strong>in</strong>dicate the start<strong>in</strong>g position of the data<br />
values <strong>in</strong> the netCDF variable (argument start), the sampl<strong>in</strong>g frequency with which data<br />
values are written <strong>in</strong>to the netCDF variable (argument stride), and a mapp<strong>in</strong>g between the<br />
dimensions of the data array and the netCDF variable (argument map). The values to be<br />
written are associated with the netCDF variable by assum<strong>in</strong>g that the first dimension of<br />
the netCDF variable varies fastest <strong>in</strong> the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface. Data values converted to the<br />
external type of the variable, if necessary.<br />
Take care when us<strong>in</strong>g the simplest <strong>for</strong>ms of this <strong>in</strong>terface with record variables when<br />
you don’t specify how many records are to be written. If you try to write all the values<br />
of a record variable <strong>in</strong>to a netCDF file that has no record data yet (hence has 0 records),<br />
noth<strong>in</strong>g will be written. Similarly, if you try to write all of a record variable but there are<br />
more records <strong>in</strong> the file than you assume, more data may be written to the file than you<br />
supply, which may result <strong>in</strong> a segmentation violation.<br />
Usage<br />
ncid<br />
varid<br />
values<br />
start<br />
count<br />
function nf<strong>90</strong>_put_var(ncid, varid, values, start, count, stride, map)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
any valid type, scalar or array of any rank, &<br />
<strong>in</strong>tent( <strong>in</strong>) :: values<br />
<strong>in</strong>teger, dimension(:), optional, <strong>in</strong>tent( <strong>in</strong>) :: start, count, stride, map<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_put_var<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID.<br />
The data value(s) to be written. The data may be of any type, and may be<br />
a scalar or an array of any rank. You cannot put CHARACTER data <strong>in</strong>to a<br />
numeric variable or numeric data <strong>in</strong>to a text variable. For numeric data, if the<br />
type of data differs from the netCDF variable type, type conversion will occur.<br />
See section “Type Conversion” <strong>in</strong> <strong>NetCDF</strong> Users Guide.<br />
A vector of <strong>in</strong>tegers specify<strong>in</strong>g the <strong>in</strong>dex <strong>in</strong> the variable where the first (or only)<br />
of the data values will be written. The <strong>in</strong>dices are relative to 1, so <strong>for</strong> example,<br />
the first data value of a variable would have <strong>in</strong>dex (1, 1, ..., 1). The elements of<br />
start correspond, <strong>in</strong> order, to the variable’s dimensions. Hence, if the variable is<br />
a record variable, the last <strong>in</strong>dex would correspond to the start<strong>in</strong>g record number<br />
<strong>for</strong> writ<strong>in</strong>g the data values.<br />
By default, start(:) = 1.<br />
A vector of <strong>in</strong>tegers specify<strong>in</strong>g the number of <strong>in</strong>dices selected along each dimension.<br />
To write a s<strong>in</strong>gle value, <strong>for</strong> example, specify count as (1, 1, ..., 1). The
Chapter 4: Variables 33<br />
stride<br />
imap<br />
elements of count correspond, <strong>in</strong> order, to the variable’s dimensions. Hence,<br />
if the variable is a record variable, the last element of count corresponds to a<br />
count of the number of records to write.<br />
By default, count(:numDims) = shape(values) and count(numDims + 1:) = 1,<br />
where numDims = size(shape(values)).<br />
A vector of <strong>in</strong>tegers that specifies the sampl<strong>in</strong>g <strong>in</strong>terval along each dimension of<br />
the netCDF variable. The elements of the stride vector correspond, <strong>in</strong> order, to<br />
the netCDF variable’s dimensions (stride(1) gives the sampl<strong>in</strong>g <strong>in</strong>terval along<br />
the most rapidly vary<strong>in</strong>g dimension of the netCDF variable). Sampl<strong>in</strong>g <strong>in</strong>tervals<br />
are specified <strong>in</strong> type-<strong>in</strong>dependent units of elements (a value of 1 selects consecutive<br />
elements of the netCDF variable along the correspond<strong>in</strong>g dimension, a<br />
value of 2 selects every other element, etc.).<br />
By default, stride(:) = 1.<br />
A vector of <strong>in</strong>tegers that specifies the mapp<strong>in</strong>g between the dimensions of a<br />
netCDF variable and the <strong>in</strong>-memory structure of the <strong>in</strong>ternal data array. The<br />
elements of the <strong>in</strong>dex mapp<strong>in</strong>g vector correspond, <strong>in</strong> order, to the netCDF<br />
variable’s dimensions (map(1) gives the distance between elements of the <strong>in</strong>ternal<br />
array correspond<strong>in</strong>g to the most rapidly vary<strong>in</strong>g dimension of the netCDF<br />
variable). Distances between elements are specified <strong>in</strong> units of elements.<br />
By default, edgeLengths = shape(values), and map = (/ 1, (product(edgeLengths(:i)),<br />
i = 1, size(edgeLengths) - 1) /), that is, there is no<br />
mapp<strong>in</strong>g.<br />
Use of <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>tr<strong>in</strong>sic functions (<strong>in</strong>clud<strong>in</strong>g reshape, transpose, and spread)<br />
may let you avoid us<strong>in</strong>g this argument.<br />
Errors<br />
NF<strong>90</strong> PUT VAR1 type returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified <strong>in</strong>dices were out of range <strong>for</strong> the rank of the specified variable. For<br />
example, a negative <strong>in</strong>dex or an <strong>in</strong>dex that is larger than the correspond<strong>in</strong>g dimension<br />
length will cause an error.<br />
• The specified value is out of the range of values representable by the external data type<br />
of the variable.<br />
• The specified netCDF is <strong>in</strong> def<strong>in</strong>e mode rather than data mode.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> PUT VAR to set the (4,3,2) element of the variable named<br />
rh to 0.5 <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc. For simplicity <strong>in</strong> this example, we<br />
assume that we know that rh is dimensioned with lon, lat, and time, so we want to set the<br />
value of rh that corresponds to the fourth lon value, the third lat value, and the second<br />
time value:
34 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncId, rhVarId, status<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId, 0.5, start = (/ 4, 3, 2 /) )<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
In this example we use NF<strong>90</strong> PUT VAR to add or change all the values of the variable<br />
named rh to 0.5 <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc. We assume that we know<br />
that rh is dimensioned with lon, lat, and time. In this example we query the netCDF file to<br />
discover the lengths of the dimensions, then use the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>tr<strong>in</strong>sic function reshape to<br />
create a temporary array of data values which is the same shape as the netCDF variable.<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncId, rhVarId,status, &<br />
lonDimID, latDimId, timeDimId, &<br />
numLons, numLats, numTimes, &<br />
i<br />
<strong>in</strong>teger, dimension(nf<strong>90</strong>_max_var_dims) :: dimIDs<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
! How big is the netCDF variable, that is, what are the lengths of<br />
! its constituent dimensions?<br />
status = nf<strong>90</strong>_Inquire_Variable(ncid, rhVarId, dimids = dimIDs)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(1), len = numLons)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(2), len = numLats)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(3), len = numTimes)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
! Make a temporary array the same shape as the netCDF variable.<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId, &<br />
reshape( &<br />
(/ (0.5, i = 1, numLons * numLats * numTimes) /) , &<br />
shape = (/ numLons, numLats, numTimes /) )<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)
Chapter 4: Variables 35<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> PUT VAR to add or change a section of the variable<br />
named rh to 0.5 <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc. For simplicity <strong>in</strong> this example,<br />
we assume that we know that rh is dimensioned with lon, lat, and time, that there are ten<br />
lon values, five lat values, and three time values, and that we want to replace all the values<br />
at the last time.<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 10, numLats = 5, numTimes = 3<br />
real, dimension(numLons, numLats) &<br />
:: rhValues<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
! Fill <strong>in</strong> all values at the last time<br />
rhValues(:, :) = 0.5<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId,rhvalues, &<br />
start = (/ 1, 1, numTimes /), &<br />
count = (/ numLats, numLons, 1 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
Here is an example of us<strong>in</strong>g NF PUT VAR to write every other po<strong>in</strong>t of a netCDF<br />
variable named rh hav<strong>in</strong>g dimensions (6, 4).<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) &<br />
:: rhValues = 0.5<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
! Fill <strong>in</strong> every other value us<strong>in</strong>g an array section<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId, rhValues(::2, ::2), &<br />
stride = (/ 2, 2 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
The follow<strong>in</strong>g map vector shows the default mapp<strong>in</strong>g between a 2x3x4 netCDF variable<br />
and an <strong>in</strong>ternal array of the same shape:<br />
real, dimension(2, 3, 4):: a ! same shape as netCDF variable<br />
<strong>in</strong>teger, dimension(3) :: map = (/ 1, 2, 6 /)
36 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
! netCDF dimension <strong>in</strong>ter-element distance<br />
! ---------------- ----------------------<br />
! most rapidly vary<strong>in</strong>g 1<br />
! <strong>in</strong>termediate 2 (= map(1)*2)<br />
! most slowly vary<strong>in</strong>g 6 (= map(2)*3)<br />
Us<strong>in</strong>g the map vector above obta<strong>in</strong>s the same result as simply not pass<strong>in</strong>g a map vector<br />
at all.<br />
Here is an example of us<strong>in</strong>g nf<strong>90</strong> put var to write a netCDF variable named rh whose<br />
dimensions are the transpose of the <strong>Fortran</strong> <strong>90</strong> array:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) :: rhValues<br />
! netCDF variable has dimensions (numLats, numLons)<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
!Write transposed values: map vector would be (/ 1, numLats /) <strong>for</strong><br />
! no transposition<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId,rhValues, map = (/ numLons, 1 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
The same effect can be obta<strong>in</strong>ed more simply us<strong>in</strong>g <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>tr<strong>in</strong>sic functions:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) :: rhValues<br />
! netCDF variable has dimensions (numLats, numLons)<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_put_var(ncid, rhVarId, transpose(rhValues))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)
Chapter 4: Variables 37<br />
4.7 Read<strong>in</strong>g Data Values: NF<strong>90</strong> GET VAR<br />
The function NF<strong>90</strong> GET VAR gets one or more data values from a netCDF variable of an<br />
open netCDF dataset that is <strong>in</strong> data mode. Required <strong>in</strong>puts are the netCDF ID, the variable<br />
ID, and a specification <strong>for</strong> the data values <strong>in</strong>to which the data will be read. Optional <strong>in</strong>puts<br />
may <strong>in</strong>dicate the start<strong>in</strong>g position of the data values <strong>in</strong> the netCDF variable (argument<br />
start), the sampl<strong>in</strong>g frequency with which data values are read from the netCDF variable<br />
(argument stride), and a mapp<strong>in</strong>g between the dimensions of the data array and the netCDF<br />
variable (argument map). The values to be read are associated with the netCDF variable<br />
by assum<strong>in</strong>g that the first dimension of the netCDF variable varies fastest <strong>in</strong> the <strong>Fortran</strong><br />
<strong>90</strong> <strong>in</strong>terface. Data values are converted from the external type of the variable, if necessary.<br />
Take care when us<strong>in</strong>g the simplest <strong>for</strong>ms of this <strong>in</strong>terface with record variables when you<br />
don’t specify how many records are to be read. If you try to read all the values of a record<br />
variable <strong>in</strong>to an array but there are more records <strong>in</strong> the file than you assume, more data<br />
will be read than you expect, which may cause a segmentation violation.<br />
Usage<br />
ncid<br />
varid<br />
values<br />
start<br />
count<br />
function nf<strong>90</strong>_get_var(ncid, varid, values, start, count, stride, map)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
any valid type, scalar or array of any rank, &<br />
<strong>in</strong>tent(out) :: values<br />
<strong>in</strong>teger, dimension(:), optional, <strong>in</strong>tent( <strong>in</strong>) :: start, count, stride, map<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_get_var<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID.<br />
The data value(s) to be read. The data may be of any type, and may be a<br />
scalar or an array of any rank. You cannot read CHARACTER data from a<br />
numeric variable or numeric data from a text variable. For numeric data, if the<br />
type of data differs from the netCDF variable type, type conversion will occur.<br />
See section “Type Conversion” <strong>in</strong> <strong>NetCDF</strong> Users Guide.<br />
A vector of <strong>in</strong>tegers specify<strong>in</strong>g the <strong>in</strong>dex <strong>in</strong> the variable from which the first<br />
(or only) of the data values will be read. The <strong>in</strong>dices are relative to 1, so <strong>for</strong><br />
example, the first data value of a variable would have <strong>in</strong>dex (1, 1, ..., 1). The<br />
elements of start correspond, <strong>in</strong> order, to the variable’s dimensions. Hence, if<br />
the variable is a record variable, the last <strong>in</strong>dex would correspond to the start<strong>in</strong>g<br />
record number <strong>for</strong> writ<strong>in</strong>g the data values.<br />
By default, start(:) = 1.<br />
A vector of <strong>in</strong>tegers specify<strong>in</strong>g the number of <strong>in</strong>dices selected along each dimension.<br />
To read a s<strong>in</strong>gle value, <strong>for</strong> example, specify count as (1, 1, ..., 1). The<br />
elements of count correspond, <strong>in</strong> order, to the variable’s dimensions. Hence,<br />
if the variable is a record variable, the last element of count corresponds to a<br />
count of the number of records to read.<br />
By default, count(:numDims) = shape(values) and count(numDims + 1:) = 1,<br />
where numDims = size(shape(values)).
38 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
stride<br />
map<br />
A vector of <strong>in</strong>tegers that specifies the sampl<strong>in</strong>g <strong>in</strong>terval along each dimension of<br />
the netCDF variable. The elements of the stride vector correspond, <strong>in</strong> order, to<br />
the netCDF variable’s dimensions (stride(1) gives the sampl<strong>in</strong>g <strong>in</strong>terval along<br />
the most rapidly vary<strong>in</strong>g dimension of the netCDF variable). Sampl<strong>in</strong>g <strong>in</strong>tervals<br />
are specified <strong>in</strong> type-<strong>in</strong>dependent units of elements (a value of 1 selects consecutive<br />
elements of the netCDF variable along the correspond<strong>in</strong>g dimension, a<br />
value of 2 selects every other element, etc.).<br />
By default, stride(:) = 1.<br />
A vector of <strong>in</strong>tegers that specifies the mapp<strong>in</strong>g between the dimensions of a<br />
netCDF variable and the <strong>in</strong>-memory structure of the <strong>in</strong>ternal data array. The<br />
elements of the <strong>in</strong>dex mapp<strong>in</strong>g vector correspond, <strong>in</strong> order, to the netCDF<br />
variable’s dimensions (map(1) gives the distance between elements of the <strong>in</strong>ternal<br />
array correspond<strong>in</strong>g to the most rapidly vary<strong>in</strong>g dimension of the netCDF<br />
variable). Distances between elements are specified <strong>in</strong> units of elements.<br />
By default, edgeLengths = shape(values), and map = (/ 1, (product(edgeLengths(:i)),<br />
i = 1, size(edgeLengths) - 1) /), that is, there is no<br />
mapp<strong>in</strong>g.<br />
Use of <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>tr<strong>in</strong>sic functions (<strong>in</strong>clud<strong>in</strong>g reshape, transpose, and spread)<br />
may let you avoid us<strong>in</strong>g this argument.<br />
Errors<br />
NF<strong>90</strong> GET VAR returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The assumed or specified start, count, and stride generate an <strong>in</strong>dex which is out of<br />
range. Note that no error check<strong>in</strong>g is possible on the map vector.<br />
• One or more of the specified values are out of the range of values representable by the<br />
desired type.<br />
• The specified netCDF is <strong>in</strong> def<strong>in</strong>e mode rather than data mode.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
(As noted above, another possible source of error is us<strong>in</strong>g this <strong>in</strong>terface to read all the<br />
values of a record variable without specify<strong>in</strong>g the number of records. If there are more<br />
records <strong>in</strong> the file than you assume, more data will be read than you expect!)<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> GET VAR to read the (4,3,2) element of the variable<br />
named rh from an exist<strong>in</strong>g netCDF dataset named foo.nc. For simplicity <strong>in</strong> this example,<br />
we assume that we know that rh is dimensioned with lon, lat, and time, so we want to read<br />
the value of rh that corresponds to the fourth lon value, the third lat value, and the second<br />
time value:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncId, rhVarId, status
Chapter 4: Variables 39<br />
real :: rhValue<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
-<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId, rhValue, start = (/ 4, 3, 2 /) )<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
In this example we use NF<strong>90</strong> GET VAR to read all the values of the variable named<br />
rh from an exist<strong>in</strong>g netCDF dataset named foo.nc. We assume that we know that rh is<br />
dimensioned with lon, lat, and time. In this example we query the netCDF file to discover<br />
the lengths of the dimensions, then allocate a <strong>Fortran</strong> <strong>90</strong> array the same shape as the<br />
netCDF variable.<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, &<br />
lonDimID, latDimId, timeDimId, &<br />
numLons, numLats, numTimes, &<br />
status<br />
<strong>in</strong>teger, dimension(nf<strong>90</strong>_max_var_dims) :: dimIDs<br />
real, dimension(:, :, :), allocatable :: rhValues<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
! How big is the netCDF variable, that is, what are the lengths of<br />
! its constituent dimensions?<br />
status = nf<strong>90</strong>_Inquire_Variable(ncid, rhVarId, dimids = dimIDs)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(1), len = numLons)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(2), len = numLats)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Dimension(ncid, dimIDs(3), len = numTimes)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
allocate(rhValues(numLons, numLats, numTimes))<br />
...<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId, rhValues)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> GET VAR to read a section of the variable named rh<br />
from an exist<strong>in</strong>g netCDF dataset named foo.nc. For simplicity <strong>in</strong> this example, we assume<br />
that we know that rh is dimensioned with lon, lat, and time, that there are ten lon values,
40 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
five lat values, and three time values, and that we want to replace all the values at the last<br />
time.<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 10, numLats = 5, numTimes = 3<br />
real, dimension(numLons, numLats, numTimes) &<br />
:: rhValues<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
!Read the values at the last time by pass<strong>in</strong>g an array section<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId, rhValues(:, :, 3), &<br />
start = (/ 1, 1, numTimes /), &<br />
count = (/ numLats, numLons, 1 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
Here is an example of us<strong>in</strong>g NF GET VAR to read every other po<strong>in</strong>t of a netCDF<br />
variable named rh hav<strong>in</strong>g dimensions (6, 4).<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) &<br />
:: rhValues<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
! Read every other value <strong>in</strong>to an array section<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId, rhValues(::2, ::2) &<br />
stride = (/ 2, 2 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
The follow<strong>in</strong>g map vector shows the default mapp<strong>in</strong>g between a 2x3x4 netCDF variable<br />
and an <strong>in</strong>ternal array of the same shape:<br />
real, dimension(2, 3, 4):: a ! same shape as netCDF variable<br />
<strong>in</strong>teger, dimension(3) :: map = (/ 1, 2, 6 /)<br />
! netCDF dimension <strong>in</strong>ter-element distance<br />
! ---------------- ----------------------<br />
! most rapidly vary<strong>in</strong>g 1<br />
! <strong>in</strong>termediate 2 (= map(1)*2)
Chapter 4: Variables 41<br />
! most slowly vary<strong>in</strong>g 6 (= map(2)*3)<br />
Us<strong>in</strong>g the map vector above obta<strong>in</strong>s the same result as simply not pass<strong>in</strong>g a map vector<br />
at all.<br />
Here is an example of us<strong>in</strong>g nf<strong>90</strong> get var to read a netCDF variable named rh whose<br />
dimensions are the transpose of the <strong>Fortran</strong> <strong>90</strong> array:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) :: rhValues<br />
! netCDF variable has dimensions (numLats, numLons)<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
! Read transposed values: map vector would be (/ 1, numLats /) <strong>for</strong><br />
! no transposition<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId,rhValues, map = (/ numLons, 1 /))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
The same effect can be obta<strong>in</strong>ed more simply, though us<strong>in</strong>g more memory, us<strong>in</strong>g <strong>Fortran</strong><br />
<strong>90</strong> <strong>in</strong>tr<strong>in</strong>sic functions:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncId, rhVarId, status<br />
<strong>in</strong>teger, parameter :: numLons = 6, numLats = 4<br />
real, dimension(numLons, numLats) :: rhValues<br />
! netCDF variable has dimensions (numLats, numLons)<br />
real, dimension(numLons, numLats) :: tempValues<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_NoWrite, ncid)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_get_var(ncid, rhVarId, tempValues))<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
rhValues(:, :) = transpose(tempValues)<br />
4.8 Read<strong>in</strong>g and Writ<strong>in</strong>g Character Str<strong>in</strong>g Values<br />
Character str<strong>in</strong>gs are not a primitive netCDF external data type, <strong>in</strong> part because FOR-<br />
TRAN does not support the abstraction of variable-length character str<strong>in</strong>gs (the FORTRAN
42 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
LEN function returns the static length of a character str<strong>in</strong>g, not its dynamic length). As<br />
a result, a character str<strong>in</strong>g cannot be written or read as a s<strong>in</strong>gle object <strong>in</strong> the netCDF<br />
<strong>in</strong>terface. Instead, a character str<strong>in</strong>g must be treated as an array of characters, and array<br />
access must be used to read and write character str<strong>in</strong>gs as variable data <strong>in</strong> netCDF datasets.<br />
Furthermore, variable-length str<strong>in</strong>gs are not supported by the netCDF <strong>in</strong>terface except by<br />
convention; <strong>for</strong> example, you may treat a zero byte as term<strong>in</strong>at<strong>in</strong>g a character str<strong>in</strong>g, but<br />
you must explicitly specify the length of str<strong>in</strong>gs to be read from and written to netCDF<br />
variables.<br />
Character str<strong>in</strong>gs as attribute values are easier to use, s<strong>in</strong>ce the str<strong>in</strong>gs are treated as a<br />
s<strong>in</strong>gle unit <strong>for</strong> access. However, the value of a character-str<strong>in</strong>g attribute is still an array of<br />
characters with an explicit length that must be specified when the attribute is def<strong>in</strong>ed.<br />
When you def<strong>in</strong>e a variable that will have character-str<strong>in</strong>g values, use a character-position<br />
dimension as the most quickly vary<strong>in</strong>g dimension <strong>for</strong> the variable (the first dimension <strong>for</strong><br />
the variable <strong>in</strong> <strong>Fortran</strong> <strong>90</strong>). The length of the character-position dimension will be the<br />
maximum str<strong>in</strong>g length of any value to be stored <strong>in</strong> the character-str<strong>in</strong>g variable. Space<br />
<strong>for</strong> maximum-length str<strong>in</strong>gs will be allocated <strong>in</strong> the disk representation of character-str<strong>in</strong>g<br />
variables whether you use the space or not. If two or more variables have the same maximum<br />
length, the same character-position dimension may be used <strong>in</strong> def<strong>in</strong><strong>in</strong>g the variable shapes.<br />
To write a character-str<strong>in</strong>g value <strong>in</strong>to a character-str<strong>in</strong>g variable, use either entire variable<br />
access or array access. The latter requires that you specify both a corner and a vector<br />
of edge lengths. The character-position dimension at the corner should be one <strong>for</strong> <strong>Fortran</strong><br />
<strong>90</strong>. If the length of the str<strong>in</strong>g to be written is n, then the vector of edge lengths will specify<br />
n <strong>in</strong> the character-position dimension, and one <strong>for</strong> all the other dimensions: (n, 1, 1, ..., 1).<br />
In <strong>Fortran</strong> <strong>90</strong>, fixed-length str<strong>in</strong>gs may be written to a netCDF dataset without a term<strong>in</strong>at<strong>in</strong>g<br />
character, to save space. Variable-length str<strong>in</strong>gs should follow the C convention<br />
of writ<strong>in</strong>g str<strong>in</strong>gs with a term<strong>in</strong>at<strong>in</strong>g zero byte so that the <strong>in</strong>tended length of the str<strong>in</strong>g can<br />
be determ<strong>in</strong>ed when it is later read by either C or <strong>Fortran</strong> <strong>90</strong> programs.<br />
4.9 Fill Values<br />
What happens when you try to read a value that was never written <strong>in</strong> an open netCDF<br />
dataset? You might expect that this should always be an error, and that you should get an<br />
error message or an error status returned. You do get an error if you try to read data from<br />
a netCDF dataset that is not open <strong>for</strong> read<strong>in</strong>g, if the variable ID is <strong>in</strong>valid <strong>for</strong> the specified<br />
netCDF dataset, or if the specified <strong>in</strong>dices are not properly with<strong>in</strong> the range def<strong>in</strong>ed by the<br />
dimension lengths of the specified variable. Otherwise, read<strong>in</strong>g a value that was not written<br />
returns a special fill value used to fill <strong>in</strong> any undef<strong>in</strong>ed values when a netCDF variable is<br />
first written.<br />
You may ignore fill values and use the entire range of a netCDF external data type, but<br />
<strong>in</strong> this case you should make sure you write all data values be<strong>for</strong>e read<strong>in</strong>g them. If you<br />
know you will be writ<strong>in</strong>g all the data be<strong>for</strong>e read<strong>in</strong>g it, you can specify that no prefill<strong>in</strong>g<br />
of variables with fill values will occur by call<strong>in</strong>g writ<strong>in</strong>g. This may provide a significant<br />
per<strong>for</strong>mance ga<strong>in</strong> <strong>for</strong> netCDF writes.<br />
The variable attribute FillValue may be used to specify the fill value <strong>for</strong> a<br />
variable. There are default fill values <strong>for</strong> each type, def<strong>in</strong>ed <strong>in</strong> module netcdf:<br />
NF<strong>90</strong> FILL CHAR, NF<strong>90</strong> FILL INT1 (same as NF<strong>90</strong> FILL BYTE), NF<strong>90</strong> FILL INT2
Chapter 4: Variables 43<br />
(same as NF<strong>90</strong> FILL SHORT), NF<strong>90</strong> FILL INT, NF<strong>90</strong> FILL REAL (same as<br />
NF<strong>90</strong> FILL FLOAT), and NF<strong>90</strong> FILL DOUBLE<br />
The netCDF byte and character types have different default fill values. The default fill<br />
value <strong>for</strong> characters is the zero byte, a useful value <strong>for</strong> detect<strong>in</strong>g the end of variable-length<br />
C character str<strong>in</strong>gs. If you need a fill value <strong>for</strong> a byte variable, it is recommended that you<br />
explicitly def<strong>in</strong>e an appropriate FillValue attribute, as generic utilities such as ncdump will<br />
not assume a default fill value <strong>for</strong> byte variables.<br />
Type conversion <strong>for</strong> fill values is identical to type conversion <strong>for</strong> other values: attempt<strong>in</strong>g<br />
to convert a value from one type to another type that can’t represent the value results <strong>in</strong><br />
a range error. Such errors may occur on writ<strong>in</strong>g or read<strong>in</strong>g values from a larger type (such<br />
as double) to a smaller type (such as float), if the fill value <strong>for</strong> the larger type cannot be<br />
represented <strong>in</strong> the smaller type.<br />
4.10 NF<strong>90</strong> RENAME VAR<br />
The function NF<strong>90</strong> RENAME VAR changes the name of a netCDF variable <strong>in</strong> an open<br />
netCDF dataset. If the new name is longer than the old name, the netCDF dataset must<br />
be <strong>in</strong> def<strong>in</strong>e mode. You cannot rename a variable to have the name of any exist<strong>in</strong>g variable.<br />
Usage<br />
ncid<br />
varid<br />
newname<br />
Errors<br />
function nf<strong>90</strong>_rename_var(ncid, varid, newname)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: newname<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_var<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID.<br />
New name <strong>for</strong> the specified variable.<br />
NF<strong>90</strong> RENAME VAR returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The new name is <strong>in</strong> use as the name of another variable.<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> RENAME VAR to rename the variable rh to rel hum <strong>in</strong><br />
an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncId, rhVarId, status<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_Write, ncid)
44 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", rhVarId)<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_redef(ncid) ! Enter def<strong>in</strong>e mode to change variable name<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_rename_var(ncid, rhVarId, "rel_hum")<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)<br />
status = nf<strong>90</strong>_enddef(ncid) ! Leave def<strong>in</strong>e mode<br />
if(status /= nf<strong>90</strong>_NoErr) call handle_err(status)
Chapter 5: Attributes 45<br />
5 Attributes<br />
5.1 Attributes Introduction<br />
Attributes may be associated with each netCDF variable to specify such properties as units,<br />
special values, maximum and m<strong>in</strong>imum valid values, scal<strong>in</strong>g factors, and offsets. Attributes<br />
<strong>for</strong> a netCDF dataset are def<strong>in</strong>ed when the dataset is first created, while the netCDF dataset<br />
is <strong>in</strong> def<strong>in</strong>e mode. Additional attributes may be added later by reenter<strong>in</strong>g def<strong>in</strong>e mode. A<br />
netCDF attribute has a netCDF variable to which it is assigned, a name, a type, a length,<br />
and a sequence of one or more values. An attribute is designated by its variable ID and<br />
name. When an attribute name is not known, it may be designated by its variable ID and<br />
number <strong>in</strong> order to determ<strong>in</strong>e its name, us<strong>in</strong>g the function NF<strong>90</strong> INQ ATTNAME.<br />
The attributes associated with a variable are typically def<strong>in</strong>ed immediately after the<br />
variable is created, while still <strong>in</strong> def<strong>in</strong>e mode. The data type, length, and value of an<br />
attribute may be changed even when <strong>in</strong> data mode, as long as the changed attribute requires<br />
no more space than the attribute as orig<strong>in</strong>ally def<strong>in</strong>ed.<br />
It is also possible to have attributes that are not associated with any variable. These are<br />
called global attributes and are identified by us<strong>in</strong>g NF<strong>90</strong> GLOBAL as a variable pseudo-ID.<br />
Global attributes are usually related to the netCDF dataset as a whole and may be used<br />
<strong>for</strong> purposes such as provid<strong>in</strong>g a title or process<strong>in</strong>g history <strong>for</strong> a netCDF dataset.<br />
Operations supported on attributes are:<br />
• Create an attribute, given its variable ID, name, data type, length, and value.<br />
• Get attribute’s data type and length from its variable ID and name.<br />
• Get attribute’s value from its variable ID and name.<br />
• Copy attribute from one netCDF variable to another.<br />
• Get name of attribute from its number.<br />
• Rename an attribute.<br />
• Delete an attribute.<br />
5.2 Attribute Conventions<br />
Names commenc<strong>in</strong>g with underscore (’ ’) are reserved <strong>for</strong> use by the netCDF library. Most<br />
generic applications that process netCDF datasets assume standard attribute conventions<br />
and it is strongly recommended that these be followed unless there are good reasons <strong>for</strong> not<br />
do<strong>in</strong>g so. Below we list the names and mean<strong>in</strong>gs of recommended standard attributes that<br />
have proven useful. Note that some of these (e.g. units, valid range, scale factor) assume<br />
numeric data and should not be used with character data. units<br />
A character str<strong>in</strong>g that specifies the units used <strong>for</strong> the variable’s data. <strong>Unidata</strong> has<br />
developed a freely-available library of rout<strong>in</strong>es to convert between character str<strong>in</strong>g and<br />
b<strong>in</strong>ary <strong>for</strong>ms of unit specifications and to per<strong>for</strong>m various useful operations on the b<strong>in</strong>ary<br />
<strong>for</strong>ms. This library is used <strong>in</strong> some netCDF applications. Us<strong>in</strong>g the recommended units<br />
syntax permits data represented <strong>in</strong> con<strong>for</strong>mable units to be automatically converted to<br />
common units <strong>for</strong> arithmetic operations. See section “Appendix A - Units” <strong>in</strong> The <strong>NetCDF</strong><br />
Users’ Guide.
46 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
long_name<br />
valid_m<strong>in</strong><br />
valid_max<br />
A long descriptive name. This could be used <strong>for</strong> label<strong>in</strong>g plots, <strong>for</strong> example. If<br />
a variable has no long name attribute assigned, the variable name should be<br />
used as a default.<br />
A scalar specify<strong>in</strong>g the m<strong>in</strong>imum valid value <strong>for</strong> this variable.<br />
A scalar specify<strong>in</strong>g the maximum valid value <strong>for</strong> this variable.<br />
valid_range<br />
A vector of two numbers specify<strong>in</strong>g the m<strong>in</strong>imum and maximum valid values<br />
<strong>for</strong> this variable, equivalent to specify<strong>in</strong>g values <strong>for</strong> both valid m<strong>in</strong> and<br />
valid max attributes. Any of these attributes def<strong>in</strong>e the valid range. The<br />
attribute valid range must not be def<strong>in</strong>ed if either valid m<strong>in</strong> or valid max is<br />
def<strong>in</strong>ed.<br />
Generic applications should treat values outside the valid range as miss<strong>in</strong>g. The<br />
type of each valid range, valid m<strong>in</strong> and valid max attribute should match the<br />
type of its variable (except that <strong>for</strong> byte data, these can be of a signed <strong>in</strong>tegral<br />
type to specify the <strong>in</strong>tended range).<br />
If neither valid m<strong>in</strong>, valid max nor valid range is def<strong>in</strong>ed then generic applications<br />
should def<strong>in</strong>e a valid range as follows. If the data type is byte and<br />
FillValue is not explicitly def<strong>in</strong>ed, then the valid range should <strong>in</strong>clude all possible<br />
values. Otherwise, the valid range should exclude the FillValue (whether<br />
def<strong>in</strong>ed explicitly or by default) as follows. If the FillValue is positive then<br />
it def<strong>in</strong>es a valid maximum, otherwise it def<strong>in</strong>es a valid m<strong>in</strong>imum. For <strong>in</strong>teger<br />
types, there should be a difference of 1 between the FillValue and this valid<br />
m<strong>in</strong>imum or maximum. For float<strong>in</strong>g po<strong>in</strong>t types, the difference should be twice<br />
the m<strong>in</strong>imum possible (1 <strong>in</strong> the least significant bit) to allow <strong>for</strong> round<strong>in</strong>g error.<br />
scale_factor<br />
If present <strong>for</strong> a variable, the data are to be multiplied by this factor after the<br />
data are read by the application that accesses the data.<br />
add_offset<br />
If present <strong>for</strong> a variable, this number is to be added to the data after it is read<br />
by the application that accesses the data. If both scale factor and add offset<br />
attributes are present, the data are first scaled be<strong>for</strong>e the offset is added. The<br />
attributes scale factor and add offset can be used together to provide simple<br />
data compression to store low-resolution float<strong>in</strong>g-po<strong>in</strong>t data as small <strong>in</strong>tegers <strong>in</strong><br />
a netCDF dataset. When scaled data are written, the application should first<br />
subtract the offset and then divide by the scale factor.<br />
When scale factor and add offset are used <strong>for</strong> pack<strong>in</strong>g, the associated variable<br />
(conta<strong>in</strong><strong>in</strong>g the packed data) is typically of type byte or short, whereas the<br />
unpacked values are <strong>in</strong>tended to be of type float or double. The attributes<br />
scale factor and add offset should both be of the type <strong>in</strong>tended <strong>for</strong> the unpacked<br />
data, e.g. float or double.
Chapter 5: Attributes 47<br />
_FillValue<br />
The FillValue attribute specifies the fill value used to pre-fill disk space allocated<br />
to the variable. Such pre-fill occurs unless nofill mode is set us<strong>in</strong>g<br />
NF<strong>90</strong> SET FILL. See Section 2.13 [NF<strong>90</strong> SET FILL], page 19. The fill value<br />
is returned when read<strong>in</strong>g values that were never written. If FillValue is def<strong>in</strong>ed<br />
then it should be scalar and of the same type as the variable. It is not<br />
necessary to def<strong>in</strong>e your own FillValue attribute <strong>for</strong> a variable if the default<br />
fill value <strong>for</strong> the type of the variable is adequate. However, use of the default<br />
fill value <strong>for</strong> data type byte is not recommended. Note that if you change the<br />
value of this attribute, the changed value applies only to subsequent writes;<br />
previously written data are not changed.<br />
Generic applications often need to write a value to represent undef<strong>in</strong>ed or miss<strong>in</strong>g<br />
values. The fill value provides an appropriate value <strong>for</strong> this purpose because<br />
it is normally outside the valid range and there<strong>for</strong>e treated as miss<strong>in</strong>g when read<br />
by generic applications. It is legal (but not recommended) <strong>for</strong> the fill value to<br />
be with<strong>in</strong> the valid range.<br />
See Section 4.9 [Fill Values], page 42.<br />
miss<strong>in</strong>g_value<br />
This attribute is not treated <strong>in</strong> any special way by the library or con<strong>for</strong>m<strong>in</strong>g<br />
generic applications, but is often useful documentation and may be used by<br />
specific applications. The miss<strong>in</strong>g value attribute can be a scalar or vector<br />
conta<strong>in</strong><strong>in</strong>g values <strong>in</strong>dicat<strong>in</strong>g miss<strong>in</strong>g data. These values should all be outside<br />
the valid range so that generic applications will treat them as miss<strong>in</strong>g.<br />
signedness<br />
Deprecated attribute, orig<strong>in</strong>ally designed to <strong>in</strong>dicate whether byte values should<br />
be treated as signed or unsigned. The attributes valid m<strong>in</strong> and valid max may<br />
be used <strong>for</strong> this purpose. For example, if you <strong>in</strong>tend that a byte variable store<br />
only nonnegative values, you can use valid m<strong>in</strong> = 0 and valid max = 255. This<br />
attribute is ignored by the netCDF library.<br />
C_<strong>for</strong>mat<br />
A character array provid<strong>in</strong>g the <strong>for</strong>mat that should be used by C applications<br />
to pr<strong>in</strong>t values <strong>for</strong> this variable. For example, if you know a variable is only accurate<br />
to three significant digits, it would be appropriate to def<strong>in</strong>e the C <strong>for</strong>mat<br />
attribute as "%.3g". The ncdump utility program uses this attribute <strong>for</strong> variables<br />
<strong>for</strong> which it is def<strong>in</strong>ed. The <strong>for</strong>mat applies to the scaled (<strong>in</strong>ternal) type<br />
and value, regardless of the presence of the scal<strong>in</strong>g attributes scale factor and<br />
add offset.<br />
FORTRAN_<strong>for</strong>mat<br />
A character array provid<strong>in</strong>g the <strong>for</strong>mat that should be used by FORTRAN<br />
applications to pr<strong>in</strong>t values <strong>for</strong> this variable. For example, if you know a variable<br />
is only accurate to three significant digits, it would be appropriate to def<strong>in</strong>e the<br />
FORTRAN <strong>for</strong>mat attribute as "(G10.3)".<br />
title<br />
A global attribute that is a character array provid<strong>in</strong>g a succ<strong>in</strong>ct description of<br />
what is <strong>in</strong> the dataset.
48 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
history A global attribute <strong>for</strong> an audit trail. This is a character array with a l<strong>in</strong>e<br />
<strong>for</strong> each <strong>in</strong>vocation of a program that has modified the dataset. Well-behaved<br />
generic netCDF applications should append a l<strong>in</strong>e conta<strong>in</strong><strong>in</strong>g: date, time of<br />
day, user name, program name and command arguments.<br />
Conventions<br />
If present, ’Conventions’ is a global attribute that is a character array <strong>for</strong> the<br />
name of the conventions followed by the dataset, <strong>in</strong> the <strong>for</strong>m of a str<strong>in</strong>g that<br />
is <strong>in</strong>terpreted as a directory name relative to a directory that is a repository of<br />
documents describ<strong>in</strong>g sets of discipl<strong>in</strong>e-specific conventions. This permits a hierarchical<br />
structure <strong>for</strong> conventions and provides a place where descriptions and<br />
examples of the conventions may be ma<strong>in</strong>ta<strong>in</strong>ed by the def<strong>in</strong><strong>in</strong>g <strong>in</strong>stitutions and<br />
groups. The conventions directory name is currently <strong>in</strong>terpreted relative to the<br />
directory pub/netcdf/Conventions/ on the host mach<strong>in</strong>e ftp.unidata.ucar.edu.<br />
Alternatively, a full URL specification may be used to name a WWW site where<br />
documents that describe the conventions are ma<strong>in</strong>ta<strong>in</strong>ed.<br />
For example, if a group named NUWG agrees upon a set of conventions <strong>for</strong><br />
dimension names, variable names, required attributes, and netCDF representations<br />
<strong>for</strong> certa<strong>in</strong> discipl<strong>in</strong>e-specific data structures, they may store a document<br />
describ<strong>in</strong>g the agreed-upon conventions <strong>in</strong> a dataset <strong>in</strong> the NUWG/ subdirectory<br />
of the Conventions directory. Datasets that followed these conventions<br />
would conta<strong>in</strong> a global Conventions attribute with value "NUWG".<br />
Later, if the group agrees upon some additional conventions <strong>for</strong> a specific subset<br />
of NUWG data, <strong>for</strong> example time series data, the description of the additional<br />
conventions might be stored <strong>in</strong> the NUWG/Time series/ subdirectory,<br />
and datasets that adhered to these additional conventions would use the global<br />
Conventions attribute with value "NUWG/Time series", imply<strong>in</strong>g that this<br />
dataset adheres to the NUWG conventions and also to the additional NUWG<br />
time-series conventions.<br />
5.3 Create an Attribute: NF<strong>90</strong> PUT ATT<br />
The function NF<strong>90</strong> PUT ATTadds or changes a variable attribute or global attribute of an<br />
open netCDF dataset. If this attribute is new, or if the space required to store the attribute<br />
is greater than be<strong>for</strong>e, the netCDF dataset must be <strong>in</strong> def<strong>in</strong>e mode.<br />
Usage<br />
Although it’s possible to create attributes of all types, text and double attributes are adequate<br />
<strong>for</strong> most purposes.<br />
ncid<br />
function nf<strong>90</strong>_put_att(ncid, varid, name, values)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character(len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
any valid type, scalar or array of rank 1, &<br />
<strong>in</strong>tent( <strong>in</strong>) :: values<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_put_att<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.
Chapter 5: Attributes 49<br />
varid<br />
name<br />
values<br />
Variable ID of the variable to which the attribute will be assigned or<br />
NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute.<br />
Attribute name. Must beg<strong>in</strong> with an alphabetic character, followed by zero or<br />
more alphanumeric characters <strong>in</strong>clud<strong>in</strong>g the underscore (’ ’). Case is significant.<br />
Attribute name conventions are assumed by some netCDF generic applications,<br />
e.g., units as the name <strong>for</strong> a str<strong>in</strong>g attribute that gives the units <strong>for</strong> a netCDF<br />
variable. For examples of attribute conventions Section 5.2 [Attribute Conventions],<br />
page 45.<br />
An array of attribute values. Values may be supplied as scalars or as arrays of<br />
rank one (one dimensional vectors). The external data type of the attribute is<br />
set to match the <strong>in</strong>ternal representation of the argument, that is if values is a<br />
two byte <strong>in</strong>teger array, the attribute will be of type NF<strong>90</strong> INT2. <strong>Fortran</strong> <strong>90</strong><br />
<strong>in</strong>tr<strong>in</strong>sic functions can be used to convert attributes to the desired type.<br />
Errors<br />
NF<strong>90</strong> PUT ATT returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified netCDF type is <strong>in</strong>valid.<br />
• The specified length is negative.<br />
• The specified open netCDF dataset is <strong>in</strong> data mode and the specified attribute would<br />
expand.<br />
• The specified open netCDF dataset is <strong>in</strong> data mode and the specified attribute does<br />
not already exist.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
• The number of attributes <strong>for</strong> this variable exceeds NF<strong>90</strong> MAX ATTRS.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> PUT ATT to add a variable attribute named valid range<br />
<strong>for</strong> a netCDF variable named rh and a global attribute named title to an exist<strong>in</strong>g netCDF<br />
dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status, RHVarID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_write, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! Enter def<strong>in</strong>e mode so we can add the attribute<br />
status = nf<strong>90</strong>_redef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Get the variable ID <strong>for</strong> "rh"...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RHVarID)
50 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! ... put the range attribute, sett<strong>in</strong>g it to eight byte reals...<br />
status = nf<strong>90</strong>_put_att(ncid, RHVarID, "valid_range", real((/ 0, 100 /))<br />
! ... and the title attribute.<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_put_att(ncid, RHVarID, "title", "example netCDF dataset") )<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Leave def<strong>in</strong>e mode<br />
status = nf<strong>90</strong>_enddef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
5.4 Get In<strong>for</strong>mation about an Attribute: NF<strong>90</strong> Inquire Att<br />
and NF<strong>90</strong> INQ ATTNAME<br />
The function NF<strong>90</strong> Inquire att returns <strong>in</strong><strong>for</strong>mation about a netCDF attribute given the<br />
variable ID and attribute name. In<strong>for</strong>mation about an attribute <strong>in</strong>cludes its type, length,<br />
name, and number. See NF<strong>90</strong> GET ATT <strong>for</strong> gett<strong>in</strong>g attribute values.<br />
The function NF<strong>90</strong> INQ ATTNAME gets the name of an attribute, given its variable<br />
ID and number. This function is useful <strong>in</strong> generic applications that need to get the names<br />
of all the attributes associated with a variable, s<strong>in</strong>ce attributes are accessed by name rather<br />
than number <strong>in</strong> all other attribute functions. The number of an attribute is more volatile<br />
than the name, s<strong>in</strong>ce it can change when other attributes of the same variable are deleted.<br />
This is why an attribute number is not called an attribute ID.<br />
Usage<br />
function nf<strong>90</strong>_Inquire_Attribute(ncid, varid, name, xtype, len, attnum)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>)<br />
:: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out), optional :: xtype, len, attnum<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Attribute<br />
function nf<strong>90</strong>_<strong>in</strong>q_attname(ncid, varid, attnum, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid, attnum<br />
character (len = *), <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_attname<br />
ncid<br />
varid<br />
name<br />
xtype<br />
len<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID of the attribute’s variable, or NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute.<br />
Attribute name. For NF<strong>90</strong> INQ ATTNAME, this is a po<strong>in</strong>ter to the location<br />
<strong>for</strong> the returned attribute name.<br />
Returned attribute type, one of the set of predef<strong>in</strong>ed netCDF external data<br />
types. The valid netCDF external data types are NF<strong>90</strong> BYTE, NF<strong>90</strong> CHAR,<br />
NF<strong>90</strong> SHORT, NF<strong>90</strong> INT, NF<strong>90</strong> FLOAT, and NF<strong>90</strong> DOUBLE.<br />
Returned number of values currently stored <strong>in</strong> the attribute. For a str<strong>in</strong>g-valued<br />
attribute, this is the number of characters <strong>in</strong> the str<strong>in</strong>g.
Chapter 5: Attributes 51<br />
attnum For NF<strong>90</strong> INQ ATTNAME, the <strong>in</strong>put attribute number; <strong>for</strong><br />
NF<strong>90</strong> INQ ATTID, the returned attribute number. The attributes<br />
<strong>for</strong> each variable are numbered from 1 (the first attribute) to NATTS, where<br />
NATTS is the number of attributes <strong>for</strong> the variable, as returned from a call to<br />
NF<strong>90</strong> INQ VARNATTS.<br />
Errors<br />
(If you already know an attribute name, know<strong>in</strong>g its number is not very useful,<br />
because access<strong>in</strong>g <strong>in</strong><strong>for</strong>mation about an attribute requires its name.)<br />
Each function returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the returned<br />
status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified attribute does not exist.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
• For NF<strong>90</strong> INQ ATTNAME, the specified attribute number is negative or more than<br />
the number of attributes def<strong>in</strong>ed <strong>for</strong> the specified variable.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> Inquire Att to <strong>in</strong>quire about the lengths of an attribute<br />
named valid range <strong>for</strong> a netCDF variable named rh and a global attribute named title <strong>in</strong><br />
an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid, status<br />
<strong>in</strong>teger :: RHVarID<br />
! Variable ID<br />
<strong>in</strong>teger :: validRangeLength, titleLength ! Attribute lengths<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! Get the variable ID <strong>for</strong> "rh"...<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! ... get the length of the "valid_range" attribute...<br />
status = nf<strong>90</strong>_Inquire_Att(ncid, RHVarID, "valid_range", &<br />
len = validRangeLength)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! ... and the global title attribute.<br />
status = nf<strong>90</strong>_Inquire_Att(ncid, nf<strong>90</strong>_global, "title", len = titleLength)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
5.5 Get Attribute’s Values: NF<strong>90</strong> GET ATT<br />
Function nf<strong>90</strong> get att gets the value(s) of a netCDF attribute, given its variable ID and<br />
name.
52 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Usage<br />
ncid<br />
varid<br />
name<br />
values<br />
Errors<br />
function nf<strong>90</strong>_get_att(ncid, varid, name, values)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character(len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
any valid type, scalar or array of rank 1, &<br />
<strong>in</strong>tent(out) :: values<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_get_att<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
Variable ID of the attribute’s variable, or NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute.<br />
Attribute name.<br />
Returned attribute values. All elements of the vector of attribute values are<br />
returned, so you must provide enough space to hold them. If you don’t know<br />
how much space to reserve, call NF<strong>90</strong> Inquire Att first to f<strong>in</strong>d out the length<br />
of the attribute. If there is only a s<strong>in</strong>gle attribute values may be a scalar. If<br />
the attribute is of type character values should be a variable of type character<br />
with the len <strong>Fortran</strong> <strong>90</strong> attribute set to an appropriate value (i.e. character (len<br />
= 80) :: values). You cannot read character data from a numeric variable or<br />
numeric data from a text variable. For numeric data, if the type of data differs<br />
from the netCDF variable type, type conversion will occur. See section “Type<br />
Conversion” <strong>in</strong> <strong>NetCDF</strong> Users Guide.<br />
NF<strong>90</strong> GET ATT type returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified attribute does not exist.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
• One or more of the attribute values are out of the range of values representable by the<br />
desired type.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> GET ATT to determ<strong>in</strong>e the values of an attribute named<br />
valid range <strong>for</strong> a netCDF variable named rh and a global attribute named title <strong>in</strong> an exist<strong>in</strong>g<br />
netCDF dataset named foo.nc. In this example, it is assumed that we don’t know how many<br />
values will be returned, so we first <strong>in</strong>quire about the length of the attributes to make sure<br />
we have enough space to store them:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger<br />
:: ncid, status<br />
<strong>in</strong>teger :: RHVarID ! Variable ID<br />
<strong>in</strong>teger<br />
:: validRangeLength, titleLength ! Attribute lengths<br />
real, dimension(:), allocatable, &
Chapter 5: Attributes 53<br />
:: validRange<br />
character (len = 80) :: title<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! F<strong>in</strong>d the lengths of the attributes<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Att(ncid, RHVarID, "valid_range", &<br />
len = validRangeLength)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_Inquire_Att(ncid, nf<strong>90</strong>_global, "title", len = titleLength)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
!Allocate space to hold attribute values, check str<strong>in</strong>g lengths<br />
allocate(validRange(validRangeLength), stat = status)<br />
if(status /= 0 .or. len(title) < titleLength)<br />
pr<strong>in</strong>t *, "Not enough space to put attribute values."<br />
exit<br />
end if<br />
! Read the attributes.<br />
status = nf<strong>90</strong>_get_att(ncid, RHVarID, "valid_range", validRange)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_get_att(ncid, nf<strong>90</strong>_global, "title", title)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
5.6 Copy Attribute from One <strong>NetCDF</strong> to Another:<br />
NF<strong>90</strong> COPY ATT<br />
The function NF<strong>90</strong> COPY ATT copies an attribute from one open netCDF dataset to<br />
another. It can also be used to copy an attribute from one variable to another with<strong>in</strong> the<br />
same netCDF dataset.<br />
Usage<br />
ncid_<strong>in</strong><br />
varid_<strong>in</strong><br />
name<br />
function nf<strong>90</strong>_copy_att(ncid_<strong>in</strong>, varid_<strong>in</strong>, name, ncid_out, varid_out)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid_<strong>in</strong>, varid_<strong>in</strong><br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid_out, varid_out<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_copy_att<br />
The netCDF ID of an <strong>in</strong>put netCDF dataset from which the attribute will be<br />
copied, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
ID of the variable <strong>in</strong> the <strong>in</strong>put netCDF dataset from which the attribute will<br />
be copied, or NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute.<br />
Name of the attribute <strong>in</strong> the <strong>in</strong>put netCDF dataset to be copied.
54 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
ncid_out<br />
varid_out<br />
The netCDF ID of the output netCDF dataset to which the attribute will be<br />
copied, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE. It is permissible<br />
<strong>for</strong> the <strong>in</strong>put and output netCDF IDs to be the same. The output netCDF<br />
dataset should be <strong>in</strong> def<strong>in</strong>e mode if the attribute to be copied does not already<br />
exist <strong>for</strong> the target variable, or if it would cause an exist<strong>in</strong>g target attribute to<br />
grow.<br />
ID of the variable <strong>in</strong> the output netCDF dataset to which the attribute will be<br />
copied, or NF<strong>90</strong> GLOBAL to copy to a global attribute.<br />
Errors<br />
NF<strong>90</strong> COPY ATT returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The <strong>in</strong>put or output variable ID is <strong>in</strong>valid <strong>for</strong> the specified netCDF dataset.<br />
• The specified attribute does not exist.<br />
• The output netCDF is not <strong>in</strong> def<strong>in</strong>e mode and the attribute is new <strong>for</strong> the output<br />
dataset is larger than the exist<strong>in</strong>g attribute.<br />
• The <strong>in</strong>put or output netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> COPY ATT to copy the variable attribute units from the<br />
variable rh <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc to the variable avgrh <strong>in</strong> another<br />
exist<strong>in</strong>g netCDF dataset named bar.nc, assum<strong>in</strong>g that the variable avgrh already exists,<br />
but does not yet have a units attribute:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid1, ncid2, status<br />
<strong>in</strong>teger :: RHVarID, avgRHVarID ! Variable ID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid1)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_open("bar.nc", nf<strong>90</strong>_write, ncid2)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! F<strong>in</strong>d the IDs of the variables<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid1, "rh", RHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid1, "avgrh", avgRHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_redef(ncid2) ! Enter def<strong>in</strong>e mode<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
! Copy variable attribute from "rh" <strong>in</strong> file 1 to "avgrh" <strong>in</strong> file 1<br />
status = nf<strong>90</strong>_copy_att(ncid1, RHVarID, "units", ncid2, avgRHVarID)
Chapter 5: Attributes 55<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_enddef(ncid2)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
5.7 Rename an Attribute: NF<strong>90</strong> RENAME ATT<br />
The function NF<strong>90</strong> RENAME ATT changes the name of an attribute. If the new name is<br />
longer than the orig<strong>in</strong>al name, the netCDF dataset must be <strong>in</strong> def<strong>in</strong>e mode. You cannot<br />
rename an attribute to have the same name as another attribute of the same variable.<br />
Usage<br />
ncid<br />
varid<br />
curname<br />
newname<br />
Errors<br />
function nf<strong>90</strong>_rename_att(ncid, varid, curname, newname)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: curname, newname<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_att<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE<br />
ID of the attribute’s variable, or NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute<br />
The current attribute name.<br />
The new name to be assigned to the specified attribute. If the new name is<br />
longer than the current name, the netCDF dataset must be <strong>in</strong> def<strong>in</strong>e mode.<br />
NF<strong>90</strong> RENAME ATT returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise,<br />
the returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified variable ID is not valid.<br />
• The new attribute name is already <strong>in</strong> use <strong>for</strong> another attribute of the specified variable.<br />
• The specified netCDF dataset is <strong>in</strong> data mode and the new name is longer than the<br />
old name.<br />
• The specified attribute does not exist.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> RENAME ATT to rename the variable attribute units to<br />
Units <strong>for</strong> a variable rh <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid1, status<br />
<strong>in</strong>teger :: RHVarID ! Variable ID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...
56 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
! F<strong>in</strong>d the IDs of the variables<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
status = nf<strong>90</strong>_rename_att(ncid, RHVarID, "units", "Units")<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
5.8 NF<strong>90</strong> DEL ATT<br />
The function NF<strong>90</strong> DEL ATT deletes a netCDF attribute from an open netCDF dataset.<br />
The netCDF dataset must be <strong>in</strong> def<strong>in</strong>e mode.<br />
Usage<br />
ncid<br />
varid<br />
name<br />
Errors<br />
function nf<strong>90</strong>_del_att(ncid, varid, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_del_att<br />
<strong>NetCDF</strong> ID, from a previous call to NF<strong>90</strong> OPEN or NF<strong>90</strong> CREATE.<br />
ID of the attribute’s variable, or NF<strong>90</strong> GLOBAL <strong>for</strong> a global attribute.<br />
The name of the attribute to be deleted.<br />
NF<strong>90</strong> DEL ATT returns the value NF<strong>90</strong> NOERR if no errors occurred. Otherwise, the<br />
returned status <strong>in</strong>dicates an error. Possible causes of errors <strong>in</strong>clude:<br />
• The specified variable ID is not valid.<br />
• The specified netCDF dataset is <strong>in</strong> data mode.<br />
• The specified attribute does not exist.<br />
• The specified netCDF ID does not refer to an open netCDF dataset.<br />
Example<br />
Here is an example us<strong>in</strong>g NF<strong>90</strong> DEL ATT to delete the variable attribute Units <strong>for</strong> a<br />
variable rh <strong>in</strong> an exist<strong>in</strong>g netCDF dataset named foo.nc:<br />
use netcdf<br />
implicit none<br />
<strong>in</strong>teger :: ncid1, status<br />
<strong>in</strong>teger :: RHVarID ! Variable ID<br />
...<br />
status = nf<strong>90</strong>_open("foo.nc", nf<strong>90</strong>_nowrite, ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
...<br />
! F<strong>in</strong>d the IDs of the variables<br />
status = nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, "rh", RHVarID)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)
Chapter 5: Attributes 57<br />
...<br />
status = nf<strong>90</strong>_redef(ncid) ! Enter def<strong>in</strong>e mode<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_del_att(ncid, RHVarID, "Units")<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)<br />
status = nf<strong>90</strong>_enddef(ncid)<br />
if (status /= nf<strong>90</strong>_noerr) call handle_err(status)
58 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide
Appendix A: Appendix A - Summary of <strong>Fortran</strong> <strong>90</strong> Interface 59<br />
Appendix A Appendix A - Summary of <strong>Fortran</strong><br />
<strong>90</strong> Interface<br />
Dataset Functions<br />
function nf<strong>90</strong>_<strong>in</strong>q_libvers()<br />
character(len = 80) :: nf<strong>90</strong>_<strong>in</strong>q_libvers<br />
function nf<strong>90</strong>_strerror(ncerr)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncerr<br />
character(len = 80) :: nf<strong>90</strong>_strerror<br />
function nf<strong>90</strong>_create(path, cmode, ncid)<br />
character (len = *), <strong>in</strong>tent(<strong>in</strong> ) :: path<br />
<strong>in</strong>teger, <strong>in</strong>tent(<strong>in</strong> ) :: cmode<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong> ) :: <strong>in</strong>itialsize<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong>out) :: chunksize<br />
<strong>in</strong>teger, <strong>in</strong>tent( out) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_create<br />
function nf<strong>90</strong>_open(path, mode, ncid, chunksize)<br />
character (len = *), <strong>in</strong>tent(<strong>in</strong> ) :: path<br />
<strong>in</strong>teger, <strong>in</strong>tent(<strong>in</strong> ) :: mode<br />
<strong>in</strong>teger, <strong>in</strong>tent( out) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(<strong>in</strong>out) :: chunksize<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_open<br />
function nf<strong>90</strong>_set_fill(ncid, fillmode, old_mode)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, fillmode<br />
<strong>in</strong>teger, <strong>in</strong>tent(out) :: old_mode<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_set_fill<br />
function nf<strong>90</strong>_redef(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_redef<br />
function nf<strong>90</strong>_enddef(ncid, h_m<strong>in</strong>free, v_align, v_m<strong>in</strong>free, r_align)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent( <strong>in</strong>) :: h_m<strong>in</strong>free, v_align, v_m<strong>in</strong>free, r_align<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_enddef<br />
function nf<strong>90</strong>_sync(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_sync<br />
function nf<strong>90</strong>_abort(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_abort<br />
function nf<strong>90</strong>_close(ncid)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_close<br />
function nf<strong>90</strong>_Inquire(ncid, nDimensions, nVariables, nAttributes, &<br />
unlimitedDimId)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
<strong>in</strong>teger, optional, <strong>in</strong>tent(out) :: nDimensions, nVariables, nAttributes, &<br />
unlimitedDimId<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire
60 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Dimension functions<br />
function nf<strong>90</strong>_def_dim(ncid, name, len, dimid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: len<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_def_dim<br />
function nf<strong>90</strong>_<strong>in</strong>q_dimid(ncid, name, dimid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_dimid<br />
function nf<strong>90</strong>_Inquire_Dimension(ncid, dimid, name, len)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, dimid<br />
character (len = *), optional, <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: len<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Dimension<br />
function nf<strong>90</strong>_rename_dim(ncid, dimid, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: dimid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_dim<br />
Variable functions<br />
function nf<strong>90</strong>_def_var(ncid, name, xtype, dimids, varid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: xtype<br />
<strong>in</strong>teger, dimension(:), <strong>in</strong>tent( <strong>in</strong>) :: dimids ! May be omitted, scalar,<br />
! vector<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_def_var<br />
function nf<strong>90</strong>_<strong>in</strong>q_varid(ncid, name, varid)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out) :: varid<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_varid<br />
function nf<strong>90</strong>_Inquire_Variable(ncid, varid, name, xtype, ndims, &<br />
dimids, nAtts)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), optional, <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: xtype, ndims<br />
<strong>in</strong>teger, dimension(*), optional, <strong>in</strong>tent(out) :: dimids<br />
<strong>in</strong>teger,<br />
optional, <strong>in</strong>tent(out) :: nAtts<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Variable<br />
function nf<strong>90</strong>_put_var(ncid, varid, values, start, stride, map)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
any valid type, scalar or array of any rank, &
Appendix A: Appendix A - Summary of <strong>Fortran</strong> <strong>90</strong> Interface 61<br />
<strong>in</strong>tent( <strong>in</strong>) :: values<br />
<strong>in</strong>teger, dimension(:), optional, <strong>in</strong>tent( <strong>in</strong>) :: start, count, stride, map<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_put_var<br />
function nf<strong>90</strong>_get_var(ncid, varid, values, start, stride, map)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
any valid type, scalar or array of any rank, &<br />
<strong>in</strong>tent(out) :: values<br />
<strong>in</strong>teger, dimension(:), optional, <strong>in</strong>tent( <strong>in</strong>) :: start, count, stride, map<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_get_var<br />
function nf<strong>90</strong>_rename_var(ncid, varid, newname)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: newname<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_var<br />
Attribute functions<br />
function nf<strong>90</strong>_Inquire_Attribute(ncid, varid, name, xtype, len, attnum)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>)<br />
:: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out), optional :: xtype, len, attnum<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Attribute<br />
function nf<strong>90</strong>_<strong>in</strong>q_attname(ncid, varid, attnum, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid, attnum<br />
character (len = *), <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_attname<br />
function nf<strong>90</strong>_put_att(ncid, varid, name, values)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character(len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
any valid type, scalar or array of rank 1, &<br />
<strong>in</strong>tent( <strong>in</strong>) :: values<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_put_att<br />
function nf<strong>90</strong>_get_att(ncid, varid, name, values)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character(len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
any valid type, scalar or array of rank 1, &<br />
<strong>in</strong>tent(out) :: values<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_get_att<br />
function nf<strong>90</strong>_copy_att(ncid_<strong>in</strong>, varid_<strong>in</strong>, name, ncid_out, varid_out)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid_<strong>in</strong>, varid_<strong>in</strong><br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid_out, varid_out<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_copy_att<br />
function nf<strong>90</strong>_rename_att(ncid, varid, curname, newname)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: curname, newname<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_rename_att<br />
function nf<strong>90</strong>_del_att(ncid, varid, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid
62 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>) :: name<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_del_att
Appendix B: Appendix B - FORTRAN 77 to <strong>Fortran</strong> <strong>90</strong> Transition Guide 63<br />
Appendix B Appendix B - FORTRAN 77 to<br />
<strong>Fortran</strong> <strong>90</strong> Transition Guide<br />
The new <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface<br />
The <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface to the netCDF library closely follows the FORTRAN 77 <strong>in</strong>terface.<br />
In most cases, function and constant names and argument lists are the same, except<br />
that nf<strong>90</strong> replaces nf <strong>in</strong> names. The <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface is much smaller than the FOR-<br />
TRAN 77 <strong>in</strong>terface, however. This has been accomplished by us<strong>in</strong>g optional arguments and<br />
overloaded functions wherever possible.<br />
Because FORTRAN 77 is a subset of <strong>Fortran</strong> <strong>90</strong>, there is no reason to modify work<strong>in</strong>g<br />
FORTRAN code to use the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface. New code, however, can easily be patterned<br />
after exist<strong>in</strong>g FORTRAN while tak<strong>in</strong>g advantage of the simpler <strong>in</strong>terface. Some compilers<br />
may provide additional support when us<strong>in</strong>g <strong>Fortran</strong> <strong>90</strong>. For example, compilers may issue<br />
warn<strong>in</strong>gs if arguments with <strong>in</strong>tent( <strong>in</strong>) are not set be<strong>for</strong>e they are passed to a procedure.<br />
The <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface is currently implemented as a set of wrappers around the base<br />
FORTRAN subrout<strong>in</strong>es <strong>in</strong> the netCDF distribution. Future versions may be implemented<br />
entirely <strong>in</strong> <strong>Fortran</strong> <strong>90</strong>, add<strong>in</strong>g additional error check<strong>in</strong>g possibilities.<br />
Changes to Inquiry functions<br />
In the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface there are two <strong>in</strong>quiry functions each <strong>for</strong> dimensions, variables,<br />
and attributes, and a s<strong>in</strong>gle <strong>in</strong>quiry function <strong>for</strong> datasets. These functions take optional arguments,<br />
allow<strong>in</strong>g users to request only the <strong>in</strong><strong>for</strong>mation they need. These functions replace<br />
the many-argument and s<strong>in</strong>gle-argument <strong>in</strong>quiry functions <strong>in</strong> the FORTRAN <strong>in</strong>terface.<br />
As an example, compare the attribute <strong>in</strong>quiry functions <strong>in</strong> the <strong>Fortran</strong> <strong>90</strong> <strong>in</strong>terface<br />
function nf<strong>90</strong>_Inquire_Attribute(ncid, varid, name, xtype, len, attnum)<br />
<strong>in</strong>teger, <strong>in</strong>tent( <strong>in</strong>) :: ncid, varid<br />
character (len = *), <strong>in</strong>tent( <strong>in</strong>)<br />
:: name<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent(out), optional :: xtype, len, attnum<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_Inquire_Attribute<br />
function nf<strong>90</strong>_<strong>in</strong>q_attname(ncid, varid, attnum, name)<br />
<strong>in</strong>teger,<br />
<strong>in</strong>tent( <strong>in</strong>) :: ncid, varid, attnum<br />
character (len = *), <strong>in</strong>tent(out) :: name<br />
<strong>in</strong>teger<br />
:: nf<strong>90</strong>_<strong>in</strong>q_attname<br />
with those <strong>in</strong> the FORTRAN <strong>in</strong>terface<br />
INTEGER FUNCTION NF_INQ_ATT (NCID, VARID, NAME, xtype, len)<br />
INTEGER FUNCTION NF_INQ_ATTID (NCID, VARID, NAME, attnum)<br />
INTEGER FUNCTION NF_INQ_ATTTYPE (NCID, VARID, NAME, xtype)<br />
INTEGER FUNCTION NF_INQ_ATTLEN (NCID, VARID, NAME, len)<br />
INTEGER FUNCTION NF_INQ_ATTNAME (NCID, VARID, ATTNUM, name)<br />
Changes to put and get function<br />
The biggest simplification <strong>in</strong> the <strong>Fortran</strong> <strong>90</strong> is <strong>in</strong> the nf<strong>90</strong> put var and nf<strong>90</strong> get var functions.<br />
Both functions are overloaded: the values argument can be a scalar or an array any<br />
rank (7 is the maximum rank allowed by <strong>Fortran</strong> <strong>90</strong>), and may be of any numeric type or<br />
the default character type. The netCDF library provides transparent conversion between<br />
the external representation of the data and the desired <strong>in</strong>ternal representation.
64 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
The start, count, stride, and map arguments to nf<strong>90</strong> put var and nf<strong>90</strong> get var are optional.<br />
By default, data is read from or written to consecutive values of start<strong>in</strong>g at the<br />
orig<strong>in</strong> of the netCDF variable; the shape of the argument determ<strong>in</strong>es how many values are<br />
read from or written to each dimension. Any or all of these arguments may be supplied to<br />
override the default behavior.<br />
Note also that <strong>Fortran</strong> <strong>90</strong> allows arbitrary array sections to be passed to any procedure,<br />
which may greatly simplify programm<strong>in</strong>g. For examples Section 4.6 [NF<strong>90</strong> PUT VAR],<br />
page 32 and Section 4.7 [NF<strong>90</strong> GET VAR], page 36.
Index 65
66 <strong>NetCDF</strong> <strong>Fortran</strong> <strong>90</strong> Interface Guide<br />
Index<br />
A<br />
attributes, add<strong>in</strong>g. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
C<br />
common netcdf commands. . . . . . . . . . . . . . . . . . . . . 1<br />
compil<strong>in</strong>g with netCDF library . . . . . . . . . . . . . . . . 6<br />
D<br />
dataset, creat<strong>in</strong>g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
datasets, overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
dimensions, add<strong>in</strong>g. . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
E<br />
error handl<strong>in</strong>g . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5<br />
I<br />
<strong>in</strong>terface descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
L<br />
l<strong>in</strong>k<strong>in</strong>g to netCDF library . . . . . . . . . . . . . . . . . . . . . 6<br />
N<br />
NF<strong>90</strong> ABORT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18<br />
NF<strong>90</strong> ABORT , example . . . . . . . . . . . . . . . . . . . . . 18<br />
NF<strong>90</strong> CLOSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14<br />
NF<strong>90</strong> CLOSE , example . . . . . . . . . . . . . . . . . . . . . 14<br />
NF<strong>90</strong> CLOSE, typical use . . . . . . . . . . . . . . . . . . . . . 1<br />
NF<strong>90</strong> COPY ATT. . . . . . . . . . . . . . . . . . . . . . . . . . . 53<br />
NF<strong>90</strong> COPY ATT, example . . . . . . . . . . . . . . . . . . 53<br />
NF<strong>90</strong> CREATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
NF<strong>90</strong> CREATE , example . . . . . . . . . . . . . . . . . . . . . 9<br />
NF<strong>90</strong> CREATE, typical use . . . . . . . . . . . . . . . . . . . 1<br />
NF<strong>90</strong> DEF DIM . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
NF<strong>90</strong> DEF DIM, example. . . . . . . . . . . . . . . . . . . . 21<br />
NF<strong>90</strong> DEF DIM, typical use . . . . . . . . . . . . . . . . . . 1<br />
NF<strong>90</strong> DEF VAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28<br />
NF<strong>90</strong> DEF VAR, example . . . . . . . . . . . . . . . . . . . 28<br />
NF<strong>90</strong> DEF VAR, typical use . . . . . . . . . . . . . . . . . . 1<br />
NF<strong>90</strong> DEL ATT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56<br />
NF<strong>90</strong> DEL ATT , example . . . . . . . . . . . . . . . . . . . 56<br />
NF<strong>90</strong> ENDDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13<br />
NF<strong>90</strong> ENDDEF , example. . . . . . . . . . . . . . . . . . . . 13<br />
NF<strong>90</strong> ENDDEF, typical use . . . . . . . . . . . . . . . . . . . 1<br />
NF<strong>90</strong> GET ATT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51<br />
NF<strong>90</strong> GET ATT, example . . . . . . . . . . . . . . . . . . . 51<br />
NF<strong>90</strong> GET ATT, typical use . . . . . . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> GET VAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37<br />
NF<strong>90</strong> GET VAR, example . . . . . . . . . . . . . . . . . . . 37<br />
NF<strong>90</strong> GET VAR, typical use . . . . . . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> INQ ATTNAME, typical use . . . . . . . . . . . . 2<br />
NF<strong>90</strong> INQ DIMID. . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
NF<strong>90</strong> INQ DIMID , example . . . . . . . . . . . . . . . . . 22<br />
NF<strong>90</strong> INQ DIMID, typical use . . . . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> INQ LIBVERS . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
NF<strong>90</strong> INQ LIBVERS, example . . . . . . . . . . . . . . . . 8<br />
NF<strong>90</strong> INQ VARID . . . . . . . . . . . . . . . . . . . . . . . . . . 29<br />
NF<strong>90</strong> INQ VARID , example . . . . . . . . . . . . . . . . . 29<br />
NF<strong>90</strong> INQ VARID, typical use . . . . . . . . . . . . . . 2, 3<br />
NF<strong>90</strong> Inquire, typical use . . . . . . . . . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> Inquire Att and NF<strong>90</strong> INQ ATTNAME<br />
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
NF<strong>90</strong> Inquire Att and NF<strong>90</strong> INQ ATTNAME,<br />
example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50<br />
NF<strong>90</strong> Inquire Attribute, typical use . . . . . . . . . . . . 2<br />
NF<strong>90</strong> Inquire Dimension . . . . . . . . . . . . . . . . . . . . . 23<br />
NF<strong>90</strong> Inquire Dimension , example . . . . . . . . . . . 23<br />
NF<strong>90</strong> Inquire Dimension, typical use . . . . . . . . . . . 2<br />
NF<strong>90</strong> Inquire Variable . . . . . . . . . . . . . . . . . . . . . . . 30<br />
NF<strong>90</strong> Inquire Variable , example . . . . . . . . . . . . . 30<br />
NF<strong>90</strong> Inquire Variable, typical use . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> OPEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
NF<strong>90</strong> OPEN , example . . . . . . . . . . . . . . . . . . . . . . 10<br />
NF<strong>90</strong> OPEN, typical use . . . . . . . . . . . . . . . . . . . . . . 2<br />
NF<strong>90</strong> PUT ATT . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48<br />
NF<strong>90</strong> PUT ATT, example . . . . . . . . . . . . . . . . . . . 48<br />
NF<strong>90</strong> PUT ATT, typical use . . . . . . . . . . . . . . . . 1, 3<br />
NF<strong>90</strong> PUT VAR . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />
NF<strong>90</strong> PUT VAR, example . . . . . . . . . . . . . . . . . . . 32<br />
NF<strong>90</strong> PUT VAR, typical use . . . . . . . . . . . . . . . . 1, 3<br />
NF<strong>90</strong> REDEF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
NF<strong>90</strong> REDEF , example . . . . . . . . . . . . . . . . . . . . . 12<br />
NF<strong>90</strong> REDEF, typical use. . . . . . . . . . . . . . . . . . . . . 4<br />
NF<strong>90</strong> RENAME ATT . . . . . . . . . . . . . . . . . . . . . . . 55<br />
NF<strong>90</strong> RENAME ATT, example . . . . . . . . . . . . . . 55<br />
NF<strong>90</strong> RENAME DIM . . . . . . . . . . . . . . . . . . . . . . . 24<br />
NF<strong>90</strong> RENAME DIM , example . . . . . . . . . . . . . . 24<br />
NF<strong>90</strong> RENAME VAR . . . . . . . . . . . . . . . . . . . . . . . 43<br />
NF<strong>90</strong> RENAME VAR , example. . . . . . . . . . . . . . 43<br />
NF<strong>90</strong> SET FILL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19<br />
NF<strong>90</strong> SET FILL , example . . . . . . . . . . . . . . . . . . . 19<br />
NF<strong>90</strong> STRERROR . . . . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
NF<strong>90</strong> STRERROR, example . . . . . . . . . . . . . . . . . . 8<br />
NF<strong>90</strong> STRERROR, <strong>in</strong>troduction. . . . . . . . . . . . . . . 5<br />
NF<strong>90</strong> SYNC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
NF<strong>90</strong> SYNC , example . . . . . . . . . . . . . . . . . . . . . . . 16<br />
R<br />
read<strong>in</strong>g dataset with unknown names . . . . . . . . . . . 2<br />
U<br />
users’ guide, netcdf . . . . . . . . . . . . . . . . . . . . . . . . . . . 1<br />
V<br />
variables, add<strong>in</strong>g. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4<br />
W<br />
writ<strong>in</strong>g to exist<strong>in</strong>g dataset . . . . . . . . . . . . . . . . . . . . . 3