Difference between revisions of "The COARDS netCDF conventions for earth science data"
(→Non-cartesian grids) |
(→Non-cartesian grids) |
||
Line 74: | Line 74: | ||
|Specifies the number of points along the time (<tt>T</tt>) axis. | |Specifies the number of points along the time (<tt>T</tt>) axis. | ||
|-valign="top" | |-valign="top" | ||
− | |<tt>Z</tt> | + | |<tt>Z</tt> or <tt>Zdim</tt> |
|Specifies the number of points along the vertical (<tt>Z</tt>) axis. | |Specifies the number of points along the vertical (<tt>Z</tt>) axis. | ||
|-valign="top" | |-valign="top" | ||
− | |<tt>Ydim</tt> | + | |<tt>Y</tt> or <tt>Ydim</tt> |
|Specifies the number of points along the (<tt>Y</tt>) horizonatal axis. | |Specifies the number of points along the (<tt>Y</tt>) horizonatal axis. | ||
|-valign="top" | |-valign="top" | ||
− | |<tt>Xdim</tt> | + | |<tt>X</tt> or <tt>Xdim</tt> |
|Specifies the number of points along the (<tt>X</tt>) horizontal axis. | |Specifies the number of points along the (<tt>X</tt>) horizontal axis. | ||
|-valign="top" | |-valign="top" |
Revision as of 17:43, 10 March 2021
Previous | Next | Guide to netCDF in GEOS-Chem
- Introduction to netCDF
- Check if netCDF is already installed on your system
- Use Spack to install netCDF on your system
- The COARDS netCDF conventions for earth science data
- Working with netCDF data files
- Creating netCDF data files for GEOS-Chem
- Other libraries used by GEOS-Chem
On this page, we describe the COARDS netCDF conventions, which is a standard used for sharing Earth Science data in netCDF files.
Contents
What is COARDS?
There is no "one standard way" to store data in a netCDF file. Because of this, several netCDF conventions have been developed in order to facilitate data exchange and visualization. The Cooperative Ocean/Atmosphere Research Data Service (COARDS) conventions defines regular conventions for naming dimensions as well as the attributes describing the data. You will find more information about these conventions in the sections below. The COARDS conventions for have become a standard for sharing Earth Science data in netCDF files.
Some netCDF files also use the the Climate and Forecast (CF) Conventions, which generalizes and extends the COARDS conventions by defining standard names for variables and attributes. Any netCDF data file that is CF-compliant by definition is also COARDS-compliant.
Both GEOS-Chem "Classic" and GCHP require that all input data in netCDF format adhere at least to the COARDS conventions (the CF conventions are optional).
--Bob Yantosca (talk) 15:17, 12 June 2019 (UTC)
Examining the layout of a netCDF file
The sections below display the layout of variables and attributes in a typical COARDS-compliant netCDF file. There are a couple of ways that you can scan a netCDF file to ensure that it is COARDS-compliant:
--Bob Yantosca (talk) 15:45, 12 June 2019 (UTC)
COARDS dimensions
Cartesian grids
The dimensions of a netCDF file define how many grid boxes there are along a given direction. While the COARDS standard does not require any specific names for dimensions, accepted practice is to use these names for cartesian (lat-lon) grids:
Dimension | Description |
---|---|
time | Specifies the number of points along the time (T) axis. |
lev | Specifies the number of points along the vertical level (Z) axis. |
lat | Specifies the number of points along the latitude (Y) axis. |
lon | Specifies the number of points along the longitude (X) axis. |
NOTES:
- The time dimension must always be specified. When you create the netCDF file, you may declare time to be UNLIMITED and then later define its size. This allows you to append further time points into the file later on.
- The lev dimension may be omitted if all of the data arrays in the netCDF file only contain a single level of data.
- The recommended ordering of dimensions in the file is time, lev (if necessary), lat, lon. Also see the Ordering of the data section below.
Non-cartesian grids
Non-cartesian grids (e.g. cubed-sphere grids) might use generic dimension names, because the horizontal dimensions for such grids typically do not correspond to longitude or latitude:
Dimension | Description |
---|---|
time | Specifies the number of points along the time (T) axis. |
Z or Zdim | Specifies the number of points along the vertical (Z) axis. |
Y or Ydim | Specifies the number of points along the (Y) horizonatal axis. |
X or Xdim | Specifies the number of points along the (X) horizontal axis. |
The choice of dimension names are typically implementation-dependent.
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
COARDS coordinate vectors
Coordinate vectors (aka index variables or axis variables) are 1-dimensional arrays that define the values along each axis—the longitudes, latitudes, levels, and times in the file.
The only COARDS requirement for coordinate vectors are these:
- Each coordinate vector must be given the same name as the dimension that is used to define it.
- All of the values contained within a coordinate vector must be either monotonically increasing or monotonically decreasing.
In practice, coordinate vectors in COARDS-compliant netCDF files generally use the same naming convention as for dimensions: time, lev, lon, lat. These are discussed in more detail below.
time
The time coordinate vector will typically have these features:
dimensions: time = UNLIMITED ; // (12 currently) # or however many timestamps there are along this dimension variables: float time(time) ; time:long_name = "time" ; time:units = "hours since 1985-01-01 00:00:00" ; time:calendar = "standard" ; time:axis = "T";
Here, time is a 4-byte floating point (aka REAL*4) of dimension time = 12 time points. You can also declare time to be an 8-byte floating point array (aka REAL*8) if you so choose.
- NOTE: The name time is typically used regardless of whether the data is placed on a cartesian or non-cartesian grid.
The COARDS standard also defines several netCDF attributes for use with the time coordinate vector:
Attribute | Type | Description |
---|---|---|
long_name | REQUIRED | Gives a detailed description of the contents of this array.
|
units | REQUIRED | Specifies the number of days hours, minutes, seconds, etc. that has elapsed with respect to a reference time. Set this to one of the following:
You can pick the units that make the most sense for your data. For example, if your data is monthly, then you can use "days since" the first of the year. If your data frequency is hourly, you can use "hours since", etc. We recommend that you choose the reference time YYYY-MM-DD to correspond with the first time value contained in the file. This will make the first index of the time coordinate array, time(0) = 0. For more information about the COARDS time standard, please visit the COARDS web page. |
calendar | REQUIRED | Specifies the calendar used to define the time system.
|
standard_name | OPTIONAL | Can be used instead of long_name. |
axis | OPTIONAL (but recommended) | Identifies which axis (X,Y,Z,T) this array corresponds to. Many software packages use this attribute to facilitate plotting.
|
lev
The lev coordinate vector will typically have the features shown below.
dimensions: lev = 72 ; # or however many points there along this dimension variables: int lev(lev) ; lev:long_name = "GEOS-Chem level" ; # Or whatever the level name is lev:units = "level" ; lev:positive = "up" ; lev:axis = "Z" ;
Here, lev is a 4-byte integer of dimension lev = 72 time points. You can also declare lev to be an 4-byte (aka REAL*4) or 8-byte floating point array (aka REAL*8) if you so choose.
- NOTE: For non-cartesian grids, the variable name "lev" might not be used. If this is the case, the name of this coordinate variable would have the same name as the name of the dimension used to define it, e.g.
int Z(Z) ;
The COARDS standard also defines several netCDF attributes for use with the time coordinate vector:
Attribute | Type | Description |
---|---|---|
long_name | REQUIRED | Gives a detailed description of the contents of this array.
IMPORTANT! If you give long_name the value of GEOS-Chem levels, then HEMCO will be able to vertically regrid the data from one GEOS-Chem grid to another. |
units | REQUIRED | Specifies the units of longitude.
IMPORTANT! If you give long_name the value of level, then HEMCO will be able to vertically regrid the data from one GEOS-Chem grid to another. |
standard_name | OPTIONAL | You may use this instead of long_name. |
axis | OPTIONAL (but recommended) | Identifies which axis (X,Y,Z,T) this array corresponds to. Many software packages use this attribute to facilitate plotting.
|
positive | OPTIONAL (but recommended) | Specifies in which direction that the vertical levels are indexed. Many software packages use this attribute to facilitate plotting.
|
--Bob Yantosca (talk) 15:29, 12 June 2019 (UTC)
lat
The lat coordinate vector typically has these features:
dimensions: lat = 181 ; # or however many points there are in that dimension variables: float lat(lat) ; lat:long_name = "Latitude" ; lat:units = "degrees_north" ; lat:axis = "Y" ;
Here, lat is a 4-byte floating point (aka REAL*4) of dimension lat = 181 latitudes. You can also declare lat to be an 8-byte floating point array (aka REAL*8) if you so choose.
- NOTE: For non-cartesian grids, the variable name "lat" might not be used. If this is the case, the name of this coordinate variable would have the same name as the name of the dimension used to define it, e.g.
float Y(Y) ;
The COARDS standard also defines several netCDF attributes for use with the lat coordinate vector:
Attribute | Type | Description |
---|---|---|
long_name | REQUIRED | Gives a detailed description of the contents of this array.
|
units | REQUIRED | Specifies the units of latitude.
|
standard_name | OPTIONAL | You may use this attribute instead of long_name. |
axis | OPTIONAL (but recommended) | Identifies which axis (X,Y,Z,T) this array corresponds to. Many software packages use this attribute to facilitate plotting.
|
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
lon
The lon coordinate vector typically has these features:
dimensions: lon = 360 ; # or however many points there are along this dimension variables: float lon(lon) ; lon:long_name = "Longitude" ; lon:units = "degrees_east" ; lon:axis = "X" ;
Here, lon is a 4-byte floating point (aka REAL*4) of dimension lon = 360 longitudes. You can also declare lon to be an 8-byte floating point array (aka REAL*8) if you so choose.
- NOTE: For non-cartesian grids, the variable name "lon" might not be used. If this is the case, the name of this coordinate variable would have the same name as the name of the dimension used to define it, e.g.
float X(X) ;
The COARDS standard also defines several netCDF attributes for use with the lon coordinate vector:
Attribute | Type | Description |
---|---|---|
long_name | REQUIRED | Gives a detailed description of the contents of this array.
|
units | REQUIRED | Specifies the units of longitude
|
standard_name | OPTIONAL | You may use this instead of long_name. |
axis | OPTIONAL (but recommended) | Identifies which axis (X,Y,Z,T) this array corresponds to. Many software packages use this attribute to facilitate plotting.
|
Longitudes may be represented modulo 360. Thus, for example, -180, 180, and 540 are all valid representations of the International Dateline and 0 and 360 are both valid representations of the Prime Meridian. Note, however, that the sequence of numerical longitude values stored in the netCDF file must be monotonic in a non-modulo sense.
Practical guidelines:
- If your grid begins at the International Dateline (-180°), then place your longitudes into the range -180..180.
- If your grid begins at the Prime Meridian (0°), then place your longitudes into the range 0..360.
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
COARDS data arrays
A COARDS-compliant netCDF file may contain several data arrays, as shown in this example:
dimensions: time = UNLIMITED ; // (12 currently) lev = 72 ; lat = 181 ; lon = 360 ; variables: float PRPE(time, lev, lat, lon) ; PRPE:long_name = "Propene" ; PRPE:units = "kgC/m2/s" ; PRPE:add_offset = 0.f ; PRPE:scale_factor = 1.f ; PRPE:_FillValue = 1.e+15f ; PRPE:missing_value = 1.e+15f ; PRPE:gamap_category = "ANTHSRCE" ; float CO(time, lev, lat, lon) ; CO:long_name = "CO" ; CO:units = "kg/m2/s" ; CO:add_offset = 0.f ; CO:scale_factor = 1.f ; CO:_FillValue = 1.e+15f ; CO:missing_value = 1.e+15f ; CO:gamap_category = "ANTHSRCE" ;
These arrays contain emissions for GEOS-Chem tracers PRPE (lumped < C3 alkenes) and CO.
Attributes
Data arrays in COARDS-compliant netCDF typically use these netCDF attributes.
Attribute | Type | Description |
---|---|---|
long_name | REQUIRED | Gives a detailed description of the contents of the array. |
units | REQUIRED | Specifies the units in the array. In general, SI units are preferred.
Special usage for HEMCO:
|
add_offset | OPTIONAL (but recommended) | Specifies an offset used to store floating-point data as packed integer. Ignored otherwise.
|
scale_factor | OPTIONAL (but recommended) | Specifies the scale factor used to store floating-point data as packed integer. Ignored otherwise.
|
standard_name | OPTIONAL (but recommended) | You may use this instead of long_name. |
missing_value | OPTIONAL (but recommended) | Specifies the value that represents missing data. This should be set to a number that will not be mistaken for a valid data value. Typical missing data values are 1e15, +/-1e32, or +/-1e-32.
NOTE: The missing_value attribute should not exceed the maximum or minimum allowable value for 4-byte (aka REAL*4) precision (i.e. ~ +/-1e32 or +/-1e-32) . This should avoid floating point errors in HEMCO caused by type conversion. |
_FillValue | OPTIONAL (but recommended) | Synonym for missing_value. It is recommended to set both missing_value and _FillValue attributes to the same value. Some data visualization packages look for the missing_value attribute, while others look for _FillValue. |
gamap_category | OPTIONAL | Specifies the GAMAP diagnostic category name. This makes it easier for the GAMAP visualization package to read the file. |
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
Ordering of the data
2D and 3D array variables in netCDF files must have specific dimension order. If the order is incorrect you will encounter netCDF read error "start+count exceeds dimension bound". You can check the dimension ordering of your arrays by using ncdump with the -h option, e.g. ncdump file.nc -h. Be sure to check the dimensions listed next to the array name rather than the ordering of the dimensions listed at the top of the ncdump output.
The following dimension orders are acceptable:
array(time,lat,lon) array(time,lat,lon,lev)
The rest of this section explains why the dimension ordering of arrays matters.
When you use ncdump utility to examine the contents of a netCDF file, you will notice that it displays the dimensions of the data in the opposite order with respect to Fortran. In our sample file, ncdump says that the CO and PRPE arrays have these dimensions:
CO(time,lev,lat,lon) PRPE(time,lev,lat,lon)
But if you tried to read this netCDF file into GEOS-Chem (or any other program written in Fortran), you must use data arrays that have these dimensions:
CO(lon,lat,lev,time) PRPE(lon,lat,lev,time)
Here's why:
Fortran is a column-major language, which means that arrays are stored in memory by columns first, then by rows. If you have declared an arrays such as:
INTEGER :: I, J, L, T INTEGER, PARAMETER :: N_LON = 360 INTEGER, PARAMETER :: N_LAT = 181 INTEGER, PARAMETER :: N_LEV = 72 INTEGER, PARAMTER :: N_TIME = 12 REAL*4 :: CO (N_LON,N_LAT,N_LEV,N_TIME) REAL*4 :: PRPE(N_LON,N_LAT,N_LEV,N_TIME)
then for optimal efficiency, the leftmost dimension (I) needs to vary the fastest, and needs to be accessed by the innermost DO-loop. Then the next leftmost dimension (J) should be accessed by the next innermost DO-loop, and so on. Therefore, the proper way to loop over these arrays is:
DO T = 1, N_TIME DO L = 1, N_LEV DO J = 1, N_LAT DO I = 1, N_LON CO (I,J,L,N) = ... PRPE(I,J,L,N) = ... ENDDO ENDDO ENDDO ENDDO
Note that the I index is varying most often, since it is the innermost DO-loop, then J, L, and T. This is opposite to how a car's odometer reads.
If you loop through an array in this fashion, with leftmost indices varying fastest, then the code minimizes the number of times it has to load subsections of the array into cache memory. In this optimal manner of execution, all of the array elements sitting in the cache memory are read in the proper order before the next array subsection needs to be loaded into the cache. But if you step through array elements in the wrong order, the number of cache loads is proportionally increased. Because it takes a finite amount of time to reload array elements into cache memory, the more times you have to access the cache, the longer it will take the code to execute. This can slow down the code dramatically.
On the other hand, C is a row-major language, which means that arrays are stored by rows first, then by columns. This means that the outermost do loop (I) is varying the fastest. This is identical to how a car's odometer reads.
If you use a Fortran program to write data to disk, and then try to read that data from disk into a program written in C (or NCL), then unless you reverse the order of the DO loops, you will be reading the array in the wrong order. In C you would have to use this ordering scheme (using Fortran-style syntax to illustrate the point):
DO I = 1, N_LON DO J = 1, N_LAT DO L = 1, N_LEV DO T = 1, N_TIME CO(T,L,J,I) = ... PRPE(T,L,J,I) = ... ENDDO ENDDO ENDDO ENDDO
Because ncdump is written in C, the order of the array appears opposite with respect to Fortran. The same goes for any code written in the NCAR command language (NCL), which is also written in C.
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
COARDS Global attributes
Global attributes are netCDF attributes that contain information about a netCDF file, as opposed to information about an individual data array. From our example above, the output from ncdump showed that our sample netCDF file has several global attributes:
// global attributes: :Title = "COARDS/netCDF file containing X data" :Contact = "GEOS-Chem Support Team (geos-chem-support@as.harvard.edu)" ; :References = "www.geos-chem.org; wiki.geos-chem.org" ; :Conventions = "COARDS" ; :Filename = "my_sample_data_file.1x1" :History = "Mon Mar 17 16:18:09 2014 GMT" ; :ProductionDateTime = "File generated on: Mon Mar 17 16:18:09 2014 GMT" ; :ModificationDateTime = "File generated on: Mon Mar 17 16:18:09 2014 GMT" ; :VersionID = "1.2" ; :Format = "NetCDF-3" ; :Model = "GEOS5" ; :Grid = "GEOS_1x1" ; :Delta_Lon = 1.f ; :Delta_Lat = 1.f ; :SpatialCoverage = "global" ; :NLayers = 72 ; :Start_Date = 20050101 ; :Start_Time = 00:00:00.0 ; :End_Date = 20051231 ; :End_Time = 23:59:59.99999 ;
You can add as many global attributes as you wish. The following are the most commonly used:
Attribute | Type | Description |
---|---|---|
Title | REQUIRED | Provides a short description of the the file.
|
Contact | OPTIONAL (but recommended) | Provides contact information about the person(s) who created the netCDF file. |
References | OPTIONAL (but recommended) | Provides references (or links to a web or wiki page) for the data contained in the netCDF file. |
Conventions | REQUIRED | Indicates if the netCDF file adheres to a standard (e.g. COARDS, CF, etc.)
|
Filename | OPTIONAL (but recommended) | Specifies the name of the netCDF file. |
History | OPTIONAL (but recommended) | Lists the date of file creation, and subsequent dates of modification.
|
ProductionDateTime | OPTIONAL (but recommended) | Specifies the date and time on which the file was originally created. |
ModificationDateTime | OPTIONAL (but recommended) | Specifies the dates and times on which the file was modified. |
VersionID | OPTIONAL (but recommended) | Specifies a version number corresponding to the data in the netCDF file.
|
Format | OPTIONAL (but recommended) | Specifies the format of the netCDF file. Possible options are:
|
Model | OPTIONAL | Specifies the vertical grid (e.g. GEOS-5, MERRA, GEOS-FP) of the GEOS-Chem simulation that was used to generate this data.
|
Delta_Lat | OPTIONAL | Specifies the spacing between points along the longitude axis.
|
Delta_Lon | OPTIONAL | Specifies the spacing between points along the longitude axis.
|
SpatialCoverage | OPTIONAL | Specifies the horizontal extent of the data. Possible values are:
|
NLayers | OPTIONAL | Specifies the number of vertical levels in the grid.
|
Start_Date | OPTIONAL | Specifies the starting date of the data in the file.
|
End_Date | OPTIONAL | Specifies the ending date of the data in the file.
|
Start_Time | OPTIONAL | Specifies the starting date of the data in the file.
|
End_Date | OPTIONAL | Specifies the ending date of the data in the file.
|
--Bob Yantosca (talk) 15:06, 12 June 2019 (UTC)
Determining if a netCDF file is COARDS-compliant
The GEOS-Chem Support Team has created a script named isCoards that will let you easily determine if a netCDF file is COARDS-compliant. In GEOS-Chem v11-01 and later versions, isCoards is included in the NcdfUtil/perl subfolder of the GEOS-Chem source code directory.
The isCoards will give you detailed output of which elements of a netCDF file are COARDS-compliant and which are not. Here is an example:
> cd /mnt/gcgrid/data/ExtData/HEMCO/GFED4/v2015-10/2013 > isCoards GFED4_3hrfrac_gen.025x025.201301.nc =========================================================================== Filename: GFED4_3hrfrac_gen.025x025.201301.nc =========================================================================== The following items adhere to the COARDS standard: --------------------------------------------------------------------------- -> time(time) -> time is monotonically increasing -> time:units = "hours since 1985-01-01 00:00:00" -> lon(lon) -> lon is monotonically increasing -> lon:units = "degrees_east" -> lat(lat) -> lat is monotonically increasing -> lat:units = "degrees_north" -> GFED_FRAC3HR(time,lat,lon) -> GFED_FRAC3HR:units = "1" The following items DO NOT ADHERE to the COARDS standard: --------------------------------------------------------------------------- -> time:calendar is missing -> time:long_name (or time:standard_name) is missing -> lon:long_name (or lon:standard_name) is missing -> lat:long_name (or lat:standard_name) is missing -> GFED_FRAC3HR:long_name (or GFED_FRAC3HR:standard_name) is missing -> The "Conventions" global attribute is missing -> The "History" global attribute is missing -> The "Title" global attribute is missing The following optional items are RECOMMENDED: --------------------------------------------------------------------------- -> Consider adding time:axis = "T" -> Consider adding lon:axis ="X" -> Consider adding lat:axis = "Y" -> Consider adding GFED_FRAC3HR:_FillValue -> Consider adding GFED_FRAC3HR:missing_value -> Consider adding GFED_FRAC3HR:add_offset -> Consider adding GFED_FRAC3HR:scale_factor -> Consider adding the "Format" global attribute -> Consider adding the "References" global attribute For more information how to fix non COARDS-compliant items, see: http://wiki.geos-chem.org/Preparing_data_files_for_use_with_HEMCO
--Bob Yantosca (talk) 15:48, 12 June 2019 (UTC)