source: XIOS/dev/branch_openmp/extern/src_netcdf4/dvar.c @ 1501

Last change on this file since 1501 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 18.0 KB
Line 
1/*! \file
2Functions for defining and inquiring about variables.
3
4Copyright 2010 University Corporation for Atmospheric
5Research/Unidata. See COPYRIGHT file for more info.
6*/
7
8#include "ncdispatch.h"
9#include "netcdf_f.h"
10
11/** \defgroup variables Variables
12
13Variables hold multi-dimensional arrays of data.
14
15Variables for a netCDF dataset are defined when the dataset is
16created, while the netCDF dataset is in define mode. Other variables
17may be added later by reentering define mode. A netCDF variable has a
18name, a type, and a shape, which are specified when it is defined. A
19variable may also have values, which are established later in data
20mode.
21
22Ordinarily, the name, type, and shape are fixed when the variable is
23first defined. The name may be changed, but the type and shape of a
24variable cannot be changed. However, a variable defined in terms of
25the unlimited dimension can grow without bound in that dimension.
26
27A netCDF variable in an open netCDF dataset is referred to by a small
28integer called a variable ID.
29
30Variable IDs reflect the order in which variables were defined within
31a netCDF dataset. Variable IDs are 0, 1, 2,..., in the order in which
32the variables were defined. A function is available for getting the
33variable ID from the variable name and vice-versa.
34
35Attributes (see Attributes) may be associated with a variable to
36specify such properties as units.
37
38Operations supported on variables are:
39- Create a variable, given its name, data type, and shape.
40- Get a variable ID from its name.
41- Get a variable's name, data type, shape, and number of attributes
42  from its ID.
43- Put a data value into a variable, given variable ID, indices, and value.
44- Put an array of values into a variable, given variable ID, corner
45  indices, edge lengths, and a block of values.
46- Put a subsampled or mapped array-section of values into a variable,
47  given variable ID, corner indices, edge lengths, stride vector,
48  index mapping vector, and a block of values.
49- Get a data value from a variable, given variable ID and indices.
50- Get an array of values from a variable, given variable ID, corner
51  indices, and edge lengths.
52- Get a subsampled or mapped array-section of values from a variable,
53  given variable ID, corner indices, edge lengths, stride vector, and
54  index mapping vector.
55- Rename a variable.
56
57\section language_types Language Types Corresponding to netCDF
58External Data Types
59
60NetCDF supported six atomic data types through version 3.6.0 (char,
61byte, short, int, float, and double). Starting with version 4.0, many
62new atomic and user defined data types are supported (unsigned int
63types, strings, compound types, variable length arrays, enums,
64opaque).
65
66The additional data types are only supported in netCDF-4/HDF5
67files. To create netCDF-4/HDF5 files, use the HDF5 flag in
68nc_create. (see nc_create).
69
70\section classic_types NetCDF-3 Classic and 64-Bit Offset Data Types
71
72NetCDF-3 classic and 64-bit offset files support 6 atomic data types,
73and none of the user defined datatype introduced in NetCDF-4.
74
75The following table gives the netCDF-3 external data types and the
76corresponding type constants for defining variables in the C
77interface:
78
79<table>
80<tr><td>Type</td><td>C define</td><td>Bits</td></tr>
81<tr><td>byte</td><td>NC_BYTE</td><td>8</td></tr>
82<tr><td>char</td><td>NC_CHAR</td><td>8</td></tr>
83<tr><td>short</td><td>NC_SHORT</td><td>16</td></tr>
84<tr><td>int</td><td>NC_INT</td><td>32</td></tr>
85<tr><td>float</td><td>NC_FLOAT</td><td>32</td></tr>
86<tr><td>double</td><td>NC_DOUBLE</td><td>64</td></tr>
87</table>
88
89The first column gives the netCDF external data type, which is the
90same as the CDL data type. The next column gives the corresponding C
91pre-processor macro for use in netCDF functions (the pre-processor
92macros are defined in the netCDF C header-file netcdf.h). The last
93column gives the number of bits used in the external representation of
94values of the corresponding type.
95
96\section netcdf_4_atomic NetCDF-4 Atomic Types
97
98NetCDF-4 files support all of the atomic data types from netCDF-3,
99plus additional unsigned integer types, 64-bit integer types, and a
100string type.
101
102<table>
103<tr><td>Type</td><td>C define</td><td>Bits
104
105<tr><td>byte</td><td>NC_BYTE</td><td>8</td></tr>
106<tr><td>unsigned byte </td><td>NC_UBYTE^</td><td> 8</td></tr>
107<tr><td>char </td><td>NC_CHAR </td><td>8</td></tr>
108<tr><td>short </td><td>NC_SHORT </td><td>16</td></tr>
109<tr><td>unsigned short </td><td>NC_USHORT^ </td><td>16</td></tr>
110<tr><td>int </td><td>NC_INT </td><td>32</td></tr>
111<tr><td>unsigned int </td><td>NC_UINT^ </td><td>32</td></tr>
112<tr><td>unsigned long long </td><td>NC_UINT64^ </td><td>64</td></tr>
113<tr><td>long long </td><td>NC_INT64^ </td><td>64</td></tr>
114<tr><td>float </td><td>NC_FLOAT </td><td>32</td></tr>
115<tr><td>double </td><td>NC_DOUBLE </td><td>64</td></tr>
116<tr><td>char ** </td><td>NC_STRING^ </td><td>string length + 1</td></tr>
117</table>
118
119^This type was introduced in netCDF-4, and is not supported in netCDF
120classic or 64-bit offset format files, or in netCDF-4 files if they
121are created with the NC_CLASSIC_MODEL flags.
122 */
123
124/** \name Defining Variables
125
126Use these functions to define variables.
127 */
128/*! \{ */
129
130/**
131\ingroup variables
132Define a new variable.
133
134This function adds a new variable to an open netCDF dataset or group.
135It returns (as an argument) a variable ID, given the netCDF ID,
136the variable name, the variable type, the number of dimensions, and a
137list of the dimension IDs.
138
139\param ncid NetCDF or group ID, from a previous call to nc_open(),
140nc_create(), nc_def_grp(), or associated inquiry functions such as
141nc_inq_ncid().
142
143\param name Variable \ref object_name.
144
145\param xtype \ref data_type of the variable.
146
147\param ndims Number of dimensions for the variable. For example, 2
148specifies a matrix, 1 specifies a vector, and 0 means the variable is
149a scalar with no dimensions. Must not be negative or greater than the
150predefined constant ::NC_MAX_VAR_DIMS.
151
152\param dimidsp Vector of ndims dimension IDs corresponding to the
153variable dimensions. For classic model netCDF files, if the ID of the
154unlimited dimension is included, it must be first. This argument is
155ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there
156may be any number of unlimited dimensions, and they may be used in any
157element of the dimids array.
158
159\param varidp Pointer to location for the returned variable ID.
160
161\returns ::NC_NOERR No error.
162\returns ::NC_EBADID Bad ncid.
163\returns ::NC_ENOTINDEFINE Not in define mode.
164\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
165\returns ::NC_EMAXVARS NC_MAX_VARS exceeded
166\returns ::NC_EBADTYPE Bad type.
167\returns ::NC_EINVAL Invalid input.
168\returns ::NC_ENAMEINUSE Name already in use.
169\returns ::NC_EPERM Attempt to create object in read-only file.
170
171\section Example
172
173Here is an example using nc_def_var to create a variable named rh of
174type double with three dimensions, time, lat, and lon in a new netCDF
175dataset named foo.nc:
176
177\code
178     #include <netcdf.h>
179        ...
180     int  status;       
181     int  ncid;         
182     int  lat_dim, lon_dim, time_dim; 
183     int  rh_id;                       
184     int  rh_dimids[3];               
185        ...
186     status = nc_create("foo.nc", NC_NOCLOBBER, &ncid);
187     if (status != NC_NOERR) handle_error(status);
188        ...
189
190     status = nc_def_dim(ncid, "lat", 5L, &lat_dim);
191     if (status != NC_NOERR) handle_error(status);
192     status = nc_def_dim(ncid, "lon", 10L, &lon_dim);
193     if (status != NC_NOERR) handle_error(status);
194     status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
195     if (status != NC_NOERR) handle_error(status);
196        ...
197
198     rh_dimids[0] = time_dim;
199     rh_dimids[1] = lat_dim;
200     rh_dimids[2] = lon_dim;
201     status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id);
202     if (status != NC_NOERR) handle_error(status);
203\endcode
204
205 */
206int
207nc_def_var(int ncid, const char *name, nc_type xtype, 
208           int ndims,  const int *dimidsp, int *varidp)
209{
210   NC* ncp;
211   int stat = NC_NOERR;
212
213   if ((stat = NC_check_id(ncid, &ncp)))
214      return stat;
215   return ncp->dispatch->def_var(ncid, name, xtype, ndims,
216                                 dimidsp, varidp);
217}
218/*! \} */
219
220/** \name Rename a Variable
221
222Rename a variable.
223 */
224/*! \{ */
225
226/** Rename a variable.
227\ingroup variables
228
229This function changes the name of a netCDF variable in an open netCDF
230file or group. You cannot rename a variable to have the name of any existing
231variable.
232
233For classic format, 64-bit offset format, and netCDF-4/HDF5 with
234classic mode, if the new name is longer than the old name, the netCDF
235dataset must be in define mode.
236
237\param ncid NetCDF or group ID, from a previous call to nc_open(),
238nc_create(), nc_def_grp(), or associated inquiry functions such as
239nc_inq_ncid().
240
241\param varid Variable ID
242
243\param name New name of the variable.
244
245\returns ::NC_NOERR No error.
246\returns ::NC_EBADID Bad ncid.
247\returns ::NC_ENOTVAR Invalid variable ID.
248\returns ::NC_EBADNAME Bad name.
249\returns ::NC_EMAXNAME Name is too long.
250\returns ::NC_ENAMEINUSE Name in use.
251\returns ::NC_ENOMEM Out of memory.
252
253\section Example
254
255Here is an example using nc_rename_var to rename the variable rh to
256rel_hum in an existing netCDF dataset named foo.nc:
257
258\code
259     #include <netcdf.h>
260        ...
261     int  status;
262     int  ncid;   
263     int  rh_id; 
264        ...
265     status = nc_open("foo.nc", NC_WRITE, &ncid);
266     if (status != NC_NOERR) handle_error(status);
267        ...
268     status = nc_redef(ncid);
269     if (status != NC_NOERR) handle_error(status);
270     status = nc_inq_varid (ncid, "rh", &rh_id);
271     if (status != NC_NOERR) handle_error(status);
272     status = nc_rename_var (ncid, rh_id, "rel_hum");
273     if (status != NC_NOERR) handle_error(status);
274     status = nc_enddef(ncid);
275     if (status != NC_NOERR) handle_error(status);
276\endcode
277
278*/
279int
280nc_rename_var(int ncid, int varid, const char *name)
281{
282   NC* ncp;
283   int stat = NC_check_id(ncid, &ncp);
284   if(stat != NC_NOERR) return stat;
285   return ncp->dispatch->rename_var(ncid, varid, name);
286}
287/*! \} */
288
289/** \internal
290\ingroup variables
291 */
292int
293NC_is_recvar(int ncid, int varid, size_t* nrecs)
294{
295   int status = NC_NOERR;
296   int unlimid;
297   int ndims;
298   int dimset[NC_MAX_VAR_DIMS];
299   
300   status = nc_inq_unlimdim(ncid,&unlimid);
301   if(status != NC_NOERR) return 0; /* no unlimited defined */
302   status = nc_inq_varndims(ncid,varid,&ndims);
303   if(status != NC_NOERR) return 0; /* no unlimited defined */
304   if(ndims == 0) return 0; /* scalar */
305   status = nc_inq_vardimid(ncid,varid,dimset);
306   if(status != NC_NOERR) return 0; /* no unlimited defined */
307   status = nc_inq_dim(ncid,dimset[0],NULL,nrecs);
308   if(status != NC_NOERR) return 0;
309   return (dimset[0] == unlimid ? 1: 0);
310}
311
312/* Ok to use NC pointers because
313   all IOSP's will use that structure,
314   but not ok to use e.g. NC_Var pointers
315   because they may be different structure
316   entirely.
317*/
318
319/** \internal
320\ingroup variables
321Find the length of a type. This is how much space is required by the user, as in
322\code
323vals = malloc(nel * nctypelen(var.type));
324ncvarget(cdfid, varid, cor, edg, vals);
325\endcode
326 */
327int
328nctypelen(nc_type type) 
329{
330   switch(type){
331      case NC_CHAR :
332         return((int)sizeof(char));
333      case NC_BYTE :
334         return((int)sizeof(signed char));
335      case NC_SHORT :
336         return(int)(sizeof(short));
337      case NC_INT :
338         return((int)sizeof(int));
339      case NC_FLOAT :
340         return((int)sizeof(float));
341      case NC_DOUBLE :
342         return((int)sizeof(double));
343
344         /* These can occur in netcdf-3 code */ 
345      case NC_UBYTE :
346         return((int)sizeof(unsigned char));
347      case NC_USHORT :
348         return((int)(sizeof(unsigned short)));
349      case NC_UINT :
350         return((int)sizeof(unsigned int));
351      case NC_INT64 :
352         return((int)sizeof(signed long long));
353      case NC_UINT64 :
354         return((int)sizeof(unsigned long long));
355#ifdef USE_NETCDF4
356      case NC_STRING :
357         return((int)sizeof(char*));
358#endif /*USE_NETCDF4*/
359
360      default:
361         return -1;
362   }
363}
364
365/** \internal
366\ingroup variables
367Find the length of a type. Redunant over nctypelen() above. */
368int
369NC_atomictypelen(nc_type xtype)
370{
371   int sz = 0;
372   switch(xtype) {
373      case NC_NAT: sz = 0; break;
374      case NC_BYTE: sz = sizeof(signed char); break;
375      case NC_CHAR: sz = sizeof(char); break;
376      case NC_SHORT: sz = sizeof(short); break;
377      case NC_INT: sz = sizeof(int); break;
378      case NC_FLOAT: sz = sizeof(float); break;
379      case NC_DOUBLE: sz = sizeof(double); break;
380      case NC_INT64: sz = sizeof(signed long long); break;
381      case NC_UBYTE: sz = sizeof(unsigned char); break;
382      case NC_USHORT: sz = sizeof(unsigned short); break;
383      case NC_UINT: sz = sizeof(unsigned int); break;
384      case NC_UINT64: sz = sizeof(unsigned long long); break;
385#ifdef USE_NETCDF4
386      case NC_STRING: sz = sizeof(char*); break;
387#endif
388      default: break;
389   }   
390   return sz;
391}
392
393/** \internal
394\ingroup variables
395    Get the type name. */
396char *
397NC_atomictypename(nc_type xtype)
398{
399   char* nm = NULL;
400   switch(xtype) {
401      case NC_NAT: nm = "undefined"; break;
402      case NC_BYTE: nm = "byte"; break;
403      case NC_CHAR: nm = "char"; break;
404      case NC_SHORT: nm = "short"; break;
405      case NC_INT: nm = "int"; break;
406      case NC_FLOAT: nm = "float"; break;
407      case NC_DOUBLE: nm = "double"; break;
408      case NC_INT64: nm = "int64"; break;
409      case NC_UBYTE: nm = "ubyte"; break;
410      case NC_USHORT: nm = "ushort"; break;
411      case NC_UINT: nm = "uint"; break;
412      case NC_UINT64: nm = "uint64"; break;
413#ifdef USE_NETCDF4
414      case NC_STRING: nm = "string"; break;
415#endif
416      default: break;
417   }   
418   return nm;
419}
420
421/** \internal
422\ingroup variables
423Get the shape of a variable.   
424 */
425int
426NC_getshape(int ncid, int varid, int ndims, size_t* shape)
427{
428   int dimids[NC_MAX_VAR_DIMS];
429   int i;
430   int status = NC_NOERR;
431
432   if ((status = nc_inq_vardimid(ncid, varid, dimids)))
433      return status;
434   for(i = 0; i < ndims; i++) 
435      if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i])))
436         break;
437
438   return status;
439}
440
441#ifdef USE_NETCDF4
442/** \ingroup variables
443
444\param ncid NetCDF or group ID, from a previous call to nc_open(),
445nc_create(), nc_def_grp(), or associated inquiry functions such as
446nc_inq_ncid().
447
448\param varid Variable ID
449
450\param size The total size of the raw data chunk cache, in bytes.
451
452\param nelems The number of chunk slots in the raw data chunk cache.
453
454\param preemption The preemption, a value between 0 and 1 inclusive
455that indicates how much chunks that have been fully read are favored
456for preemption. A value of zero means fully read chunks are treated no
457differently than other chunks (the preemption is strictly LRU) while a
458value of one means fully read chunks are always preempted before other
459chunks.
460
461\returns ::NC_NOERR No error.
462\returns ::NC_EBADID Bad ncid.
463\returns ::NC_ENOTVAR Invalid variable ID.
464\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
465\returns ::NC_EINVAL Invalid input
466 */
467int
468nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems, 
469                       float preemption)
470{
471    NC* ncp;
472    int stat = NC_check_id(ncid, &ncp);
473    if(stat != NC_NOERR) return stat;
474    return ncp->dispatch->set_var_chunk_cache(ncid, varid, size, 
475                                              nelems, preemption);
476}
477
478/** \ingroup variables
479
480\param ncid NetCDF or group ID, from a previous call to nc_open(),
481nc_create(), nc_def_grp(), or associated inquiry functions such as
482nc_inq_ncid().
483
484\param varid Variable ID
485
486\param sizep The total size of the raw data chunk cache, in bytes,
487will be put here. \ref ignored_if_null.
488
489\param nelemsp The number of chunk slots in the raw data chunk cache
490hash table will be put here. \ref ignored_if_null.
491
492\param preemptionp The preemption will be put here. The preemtion
493value is between 0 and 1 inclusive and indicates how much chunks that
494have been fully read are favored for preemption. A value of zero means
495fully read chunks are treated no differently than other chunks (the
496preemption is strictly LRU) while a value of one means fully read
497chunks are always preempted before other chunks. \ref ignored_if_null.
498
499\returns ::NC_NOERR No error.
500\returns ::NC_EBADID Bad ncid.
501\returns ::NC_ENOTVAR Invalid variable ID.
502\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
503\returns ::NC_EINVAL Invalid input
504*/
505int
506nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp, 
507                       float *preemptionp)
508{
509    NC* ncp;
510    int stat = NC_check_id(ncid, &ncp);
511    if(stat != NC_NOERR) return stat;
512    return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep,
513                                              nelemsp, preemptionp);
514}
515
516/** \ingroup variables
517Free string space allocated by the library.
518
519When you read string type the library will allocate the storage space
520for the data. This storage space must be freed, so pass the pointer
521back to this function, when you're done with the data, and it will
522free the string memory.
523
524\param len The number of character arrays in the array.
525\param data The pointer to the data array.
526
527\returns ::NC_NOERR No error.
528*/
529int
530nc_free_string(size_t len, char **data)
531{
532   int i;
533   for (i = 0; i < len; i++)
534      free(data[i]);
535   return NC_NOERR;
536}
537
538int
539nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level)
540{
541    NC* ncp;
542    int stat = NC_check_id(ncid,&ncp);
543    if(stat != NC_NOERR) return stat;
544    return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level);
545}
546
547int
548nc_def_var_fletcher32(int ncid, int varid, int fletcher32)
549{
550    NC* ncp;
551    int stat = NC_check_id(ncid,&ncp);
552    if(stat != NC_NOERR) return stat;
553    return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32);
554}
555
556int
557nc_def_var_chunking(int ncid, int varid, int storage, 
558                    const size_t *chunksizesp)
559{
560    NC* ncp;
561    int stat = NC_check_id(ncid, &ncp);
562    if(stat != NC_NOERR) return stat;
563    return ncp->dispatch->def_var_chunking(ncid, varid, storage, 
564                                           chunksizesp);
565}
566
567int
568nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
569{
570    NC* ncp;
571    int stat = NC_check_id(ncid,&ncp);
572    if(stat != NC_NOERR) return stat;
573    return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
574}
575
576int
577nc_def_var_endian(int ncid, int varid, int endian)
578{
579    NC* ncp;
580    int stat = NC_check_id(ncid,&ncp);
581    if(stat != NC_NOERR) return stat;
582    return ncp->dispatch->def_var_endian(ncid,varid,endian);
583}
584
585#endif /* USE_NETCDF4 */
Note: See TracBrowser for help on using the repository browser.