USER GUIDE for EZcdf Library. ============================ 05/03/1999 C. Ludescher-Furth Revision: 06/22/00 C.Ludescher-Furth transp_support@pppl.gov (PPPL) Revision: 05/17/01 A.Pletzer pletzer@pppl.gov (PPPL) 10/10/02 A.Pletzer/S Hirshman (ORNL) 08/20/10 D.McCune -- comment on Netcdf-f90 Historical note and recommendation: EZcdf provided an early f90 interface to NetCDF. An NCAR supported full featured f90 interface is now available, and will usually be preferable to EZcdf for new code. Please see: http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-f90 o LANGUAGES: Fortran 90 and C++ The following routines allow to write/read data to/from file in binary, yet portable way, using the netCDF file format. EZcdf is a thin (f90) wrapper on netCDF, a freely available library that can be downloaded from http://www.unidata.ucar.edu/packages/netcdf/. NetCDF is platform (Unices, Windows, ...) and language (C/C++, Fortran, Java, Perl, Python, ...) independent. Thus, a file produced by EZcdf can be read on any of the netCDF supported architectures and in any of the above programming languages. There are presently two versions of EZcdf. We recommend the more recent version by Steve Hirshman (ORNL), which has the cleaner interface. Since the original version, a number of improvements to Ezcdf have been made. It is now possible (though not required) to: - specify dimension names (the default behaviour is to let Ezcdf choose) - set/get long names and units (default is no long name and no units). Specifying long names and units may be required by some graphics packages in order to set labels on axes. Moreover, both type and dimension sizes can now be inferred at run time when calling cdf_define. Ezcdf was first implemented in Fortran 90. The original version was then re-implemented in C++ (Ezcdf++). There is a one-to-one correspondence between the original Ezcdf API (see below) and the Ezcdf++ API with the notable difference that the C++ version does not support "logicals" or "complex" (Re/Im) types. The new version is of course backward compatible but contains additional routines that have not been not mirrored in Ezcdf++. Only the Fortran version is described here, please consult eztest2.cc to see the correspondence between EZcdf++ and the original Fortran 90 version. Not all netCDF calls are supported by EZcdf. In particular, arrays should have at most rank 3 and there should be no 'infinite' (time) dimension. EZcdf, however, is designed to be much easier to use than raw netCDF calls. Many tasks such as defining the dimension names and units are automated in EZcdf (though they can also be explicitly specified if required). Information about the data and the data proper are accessed using string key words (e.g. the name of the variable) as opposed to opaque integer id numbers in netCDF. Another advantage of EZcdf over netCDF is the support for COMPLEX numbers (both 64- and 128-bit long), which are laid out as REAL arrays of twice the size, and LOGICALs, which are stored as INT's. (Some name mangling keeps track of which arrays are stored as REAL and which as COMPLEX, and likewise for LOGICALs and INTs) Finally, type checking is enforced through the use of F90 interfaces, providing a safety net for the user. The variable types and shapes supported are: type shape ---- ----- logical scalar, array rank 1-3 (*) (o) default integer scalar, array rank 1-3 4-byte real scalar, array rank 1-3 8-byte real scalar, array rank 1-3 8-byte complex scalar, array rank 1-3 (*) (o) 16-byte complex scalar, array rank 1-3 (*) (o) default character string, vector of strings (*) type not supported by netCDF (o) type not supported by EZcdf++ Note: A character string is treated as a 1-dimensional array and must be defined with length of dimension = len(string). A vector of character strings is treated as a 2-dimensional array and must be defined with lengths = len(string(1)) and size(string). Variable-length strings are not supported by netCDF. A netCDF dataset is stored in a single file comprising two parts: - a header, containing info about variable type and shape. This part is defined via cdf_define and may be examined via cdf_inquire. - the data. This part is written via cdf_write and can be retrieved via cdf_read. For netCDF performance reasons, the EZcdf routines require that the header be *defined* before the data are written. From the user point of view, a read (write) process involves 4 steps: opening the file, inquiring about (defining) the variable type and shape, reading (writing) the data and closing the file. The process of reading is symmetric vs. the one of writing: The new, and preferred, syntax is ([..] indicates optional calls): READ: WRITE: cdf_open 'r' cdf_open 'w' (*) [cdf_inquire] cdf_define [cdf_getatt] [cdf_setatt] (%) cdf_read cdf_write cdf_close cdf_close (o) The older and equivalent syntax is READ: WRITE: ezcdf_open 'r' ezcdf_open 'w' (*) [cdfInqVar] cdfDefVar - - cdfGetVar cdfPutVar cdf_close cdf_close (o) (*) a constructor call in EZcdf++ (o) a destructor call in EZcdf++ (%) not available in EZcdf++ A note re: cdf_open. New features now available (Nov. 2002): cdf_open 'a' -- "append" -- add new data items to existing file. cdf_open 'm' -- "modify" -- modify (read/write) existing items in existing file (no new items). Note that all cdf_write (or cdfPutVar) calls *must* be preceded by calls to cdf_define (or cdfDefVar). On the other hand, calls to cdf_inquire are only useful to determine the size of the stored data before loading the data, and so are optional. (Many codes already seem to know the size of the arrays to be read.) NetCDF files open in "modify" mode allow any existing item may be read or written-- i.e. the values of existing data items can be modified, but new items cannot be defined or created. NetCDF files open in "append" mode, as in "write" mode, require all cdf_define and cdf_setatt calls to be executed before any cdf_write calls. After all cdf_define & cdf_write calls have been completed for new items, the file remains open in "modify" mode. Public Interface Module: ezcdf -- Must be USEd by User Public Callable Routines: cdf_open(ncid,filename,access[,ier]) -- create/open a file cdf_close(ncid[,ier]) -- close a netcdf file cdf_define(ncid,varnam,dimlens,xtype[,ier]) -- define a variable, -- or -- cdf_define(ncid,varnam, val [,ier]) -- length and type are inferred from val cdf_setatt(ncid,varnam, longnam [,units [,ier]]) -- set long name attributes/units (see netCDF doc) cdf_write(ncid,varnam,val[,ier]) -- write variable val cdf_inquire(ncid,varnam,dimlens[,xtype[,ier]]) -- get dimension(s) (and type) cdf_getatt(ncid,varnam, longnam [,units [,ier]]) --- get the long name/units attribute (see netCDF doc) cdf_read(ncid,varnam,val[,ier]) -- read variable val o USAGE access : character - 'r' (read) or 'w' (write) or 'a' (append) or 'm' (modify). argument for "cdf_open". ncid : integer - NetCDF ID, from "cdf_open". NOTE: do not declare ncid as "parameter". ncid is a return value. varnam : character*(*) - Name of variable. Must begin with alphabetic character, followed by alphanumeric including underscore. Case is significant. dimlens : integer(3) - Vector of length 3 containing the sizes of each dimension of "val". Rank of "val" should be <=3. For rank < 3 the user should set the sizes to 1 (or zero), as in (/n, 1, 1/) for a 1-D array of size n. Notice that dimlens=(/1, n, 1/) is different from dimlens=(/n, 1, 1/), since in the former case the array is stored with shape (1:1,1:n) while in the latter it is stored as having shape (1:n). Rank contraction occurs if all sizes to the right are 1 or zero. length(s) of dimension(s) of "val". If "val" is a scalar, dimlens(1[:3]) = 1. If "val" is a character string, dimlens(1) = len(val) If "val" is a character string vector, dimlens(1) = len(val(1)) dimlens(2) = size(val) Thus, EZcdf will guess how best to store an array by looking at dimlens. In some cases one may want to prevent the rank contraction, that is on may want to store for instance a 1-D array that happens to have only one element as a 1-D array. Using dimlens=(/1,1,1/) would contract the array to a scalar. Preventing this can be achieved by using *negative* sizes, as in dimlens=(/-1,1,1/). Here are more examples: dimlens rank array shape in netCDF file (/0,0,0/) 0 (/1,1,1/) 0 (/1,0,0/) 0 (1-D array of length 1 stored as a scalar) (/-1,0,0/) 1 (1:1) (1-D array of length 1 stored as 1-D array) (/5,1,1/) 1 (1:5) (/5,-1,1/) 2 (1:5,1:1) (/7,3,0/) 2 (1:7,1:3) (/7,3,1/) 2 (1:7,1:3) (same) (/7,3,-1/) 3 (1:7,1:3,1:1) (/7,3,-2/) 3 (1:7,1:3,1:2) (/7,3,2/) 3 (1:7,1:3,1:2) (same) (/-7,-3,-2/) 3 (1:7,1:3,1:2) (same) (/-nx,-ny,-nz/) 3 (1:nx,1:ny,1:nz) (/nx,ny,nz/) 3 or 2 or 1 or 0 (1:nx,1:ny,1:nz) or (1:nx,1:ny) if nz=1 or (1:nx) if ny=nz=1 or scalar if nx=ny=nz=1 xtype : character*(*) - Type of the variable: 'LOG' = logical (will be stored as INT) 'INT' = integer 'R4' = real*4 'R8' = real*8 'C8' = complex*8 (will be stored as R4) 'C16' = complex*16 (will be stored as R8) 'CHAR'= character longnam : character*(*) - a string susceptible to provide a description of var (see netcdf doc) units : character*(*) - units of the array (see netCDF doc) val : "xtype"[(*)] - Data of type "xtype" to be written. Scalar, Vector or array rank 2 or 3. If "xtype" = 'CHAR', only rank 1 is supported. ier : integer - Optional argument. Returned status: 0 = success. o EXAMPLES ! Fortran Example to Write netCDF File ! ===================================== USE ezcdf -- Interface ! Input: integer, dimension(2) :: dimlens -- length of dimensions character*4 :: xtype -- Variable Type real*8, dimension(m,n) :: val_r8 -- Array rank 2 character*8, dimension(k) :: val_char -- Character String Vector ! Output: integer, intent(out) :: ncid -- netCdf File Id ! Create netcdf File call cdf_open(ncid,'my_file','w'[,ier]) ! Define character string variable dimlens(1) = len(val_char(1)) dimlens(2) = size(val_char) call cdf_define(ncid,'my_text',dimlens,'CHAR'[,ier]) ! Define data array variable dimlens(1) = m dimlens(2) = n call cdf_define(ncid,'my_data',dimlens,'R8'[,ier]) call cdf_setatt(ncid, 'my_data', 'descriptive name for my_data', 'A/s', ier) : : ! Write Variable call cdf_write(ncid,'my_data',val_r8[,ier]) call cdf_write(ncid,'my_text',val_char[,ier]) : : !close the file call cdf_close(ncid) ! Fortran Example to Read netCDF File =================================== USE ezcdf -- Interface call cdf_open(ncid,filename,'r'[,ier]) -- open the file call cdf_inquire(ncid,varnam,dimlens,xtype[,ier]) -- get dimension(s) [call cdf_getatt(ncid,varnam, longnam, units)] call cdf_read(ncid,varnam,val[,ier]) -- read variable call cdf_close(ncid) -- close the file o COMPILING/LINKING when compiling your program you need to specify the location of the Fortran 90 modules, which are in /mod e.g.: f90 -c -/mod myprog.f where is the compiler specific option, and is the location where libezcdf was installed. to link your program use -L/lib -lezcdf -L/lib -lnetcdf where is the location of the netcdf library, usually /usr/local.