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 nc_def_var_example 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 *namenc_type xtype,
208    int ndims,  const int *dimidsp, int *varidp)
209{
210   NCncp;
211   int stat = NC_NOERR;
212
213   if ((stat = NC_check_id(ncid, &ncp)))
214      return stat;
215   TRACE(nc_def_var);
216   return ncp->dispatch->def_var(ncidnamextypendims,
217  dimidspvaridp);
218}
219/*! \} */
220
221/** \name Rename a Variable
222
223Rename a variable.
224 */
225/*! \{ */
226
227/** Rename a variable.
228\ingroup variables
229
230This function changes the name of a netCDF variable in an open netCDF
231file or group. You cannot rename a variable to have the name of any existing
232variable.
233
234For classic format, 64-bit offset format, and netCDF-4/HDF5 with
235classic mode, if the new name is longer than the old name, the netCDF
236dataset must be in define mode.
237
238\param ncid NetCDF or group ID, from a previous call to nc_open(),
239nc_create(), nc_def_grp(), or associated inquiry functions such as
240nc_inq_ncid().
241
242\param varid Variable ID
243
244\param name New name of the variable.
245
246\returns ::NC_NOERR No error.
247\returns ::NC_EBADID Bad ncid.
248\returns ::NC_ENOTVAR Invalid variable ID.
249\returns ::NC_EBADNAME Bad name.
250\returns ::NC_EMAXNAME Name is too long.
251\returns ::NC_ENAMEINUSE Name in use.
252\returns ::NC_ENOMEM Out of memory.
253
254\section nc_rename_var_example Example
255
256Here is an example using nc_rename_var to rename the variable rh to
257rel_hum in an existing netCDF dataset named foo.nc:
258
259\code
260     #include <netcdf.h>
261        ...
262     int  status;
263     int  ncid;
264     int  rh_id;
265        ...
266     status = nc_open("foo.nc", NC_WRITE, &ncid);
267     if (status != NC_NOERR) handle_error(status);
268        ...
269     status = nc_redef(ncid);
270     if (status != NC_NOERR) handle_error(status);
271     status = nc_inq_varid (ncid, "rh", &rh_id);
272     if (status != NC_NOERR) handle_error(status);
273     status = nc_rename_var (ncid, rh_id, "rel_hum");
274     if (status != NC_NOERR) handle_error(status);
275     status = nc_enddef(ncid);
276     if (status != NC_NOERR) handle_error(status);
277\endcode
278
279*/
280int
281nc_rename_var(int ncid, int varid, const char *name)
282{
283   NCncp;
284   int stat = NC_check_id(ncid, &ncp);
285   if(stat != NC_NOERR) return stat;
286   TRACE(nc_rename_var);
287   return ncp->dispatch->rename_var(ncidvaridname);
288}
289/*! \} */
290
291/** \internal
292\ingroup variables
293 */
294int
295NC_is_recvar(int ncid, int varid, size_t* nrecs)
296{
297   int status = NC_NOERR;
298   int unlimid;
299   int ndims;
300   int dimset[NC_MAX_VAR_DIMS];
301
302   status = nc_inq_unlimdim(ncid,&unlimid);
303   if(status != NC_NOERR) return 0; /* no unlimited defined */
304   status = nc_inq_varndims(ncid,varid,&ndims);
305   if(status != NC_NOERR) return 0; /* no unlimited defined */
306   if(ndims == 0) return 0; /* scalar */
307   status = nc_inq_vardimid(ncid,varid,dimset);
308   if(status != NC_NOERR) return 0; /* no unlimited defined */
309   status = nc_inq_dim(ncid,dimset[0],NULL,nrecs);
310   if(status != NC_NOERR) return 0;
311   return (dimset[0] == unlimid ? 1: 0);
312}
313
314/** \internal
315\ingroup variables
316Get the number of record dimensions for a variable and an array that
317identifies which of a variable's dimensions are record dimensions.
318Intended to be used instead of NC_is_recvar, which doesn't work for
319netCDF-4 variables which have multiple unlimited dimensions or an
320unlimited dimension that is not the first of a variable's dimensions.
321Example use:
322\code
323int nrecdims;
324int is_recdim[NC_MAX_VAR_DIMS];
325  ...
326status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim);
327isrecvar = (nrecdims > 0);
328\endcode
329 */
330int
331NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim)
332{
333   int status = NC_NOERR;
334   int unlimid;
335   int nvardims;
336   int dimset[NC_MAX_VAR_DIMS];
337   int dim;
338   int nrecdims = 0;
339
340   status = nc_inq_varndims(ncid,varid,&nvardims);
341   if(status != NC_NOERR) return status;
342   if(nvardims == 0) return NC_NOERR; /* scalars have no dims */
343   for(dim = 0; dim < nvardimsdim++)
344     is_recdim[dim] = 0;
345   status = nc_inq_unlimdim(ncid, &unlimid);
346   if(status != NC_NOERR) return status;
347   if(unlimid == -1) return status; /* no unlimited dims for any variables */
348#ifdef USE_NETCDF4
349   {
350     int nunlimdims;
351     int *unlimids;
352     int recdim;
353     status = nc_inq_unlimdims(ncid, &nunlimdimsNULL); /* for group or file, not variable */
354     if(status != NC_NOERR) return status;
355     if(nunlimdims == 0) return status;
356
357     if (!(unlimids = malloc(nunlimdims * sizeof(int))))
358       return NC_ENOMEM;
359     status = nc_inq_unlimdims(ncid, &nunlimdimsunlimids); /* for group or file, not variable */
360     if(status != NC_NOERR) {
361       free(unlimids);
362       return status;
363     }
364     status = nc_inq_vardimid(ncidvariddimset);
365     if(status != NC_NOERR) {
366       free(unlimids);
367       return status;
368     }
369     for (dim = 0; dim < nvardimsdim++) { /* netCDF-4 rec dims need not be first dim for a rec var */
370       for(recdim = 0; recdim < nunlimdimsrecdim++) {
371  if(dimset[dim] == unlimids[recdim]) {
372    is_recdim[dim] = 1;
373    nrecdims++;
374  }
375       }
376     }
377     free(unlimids);
378   }
379#else
380   status = nc_inq_vardimid(ncidvariddimset);
381   if(status != NC_NOERR) return status;
382   if(dimset[0] == unlimid) {
383     is_recdim[0] = 1;
384     nrecdims++;
385   }
386#endif /* USE_NETCDF4 */
387   if(nrecdimsp) *nrecdimsp = nrecdims;
388   return status;
389}
390
391/* Ok to use NC pointers because
392   all IOSP's will use that structure,
393   but not ok to use e.g. NC_Var pointers
394   because they may be different structure
395   entirely.
396*/
397
398/** \internal
399\ingroup variables
400Find the length of a type. This is how much space is required by the user, as in
401\code
402vals = malloc(nel * nctypelen(var.type));
403ncvarget(cdfid, varid, cor, edg, vals);
404\endcode
405 */
406int
407nctypelen(nc_type type)
408{
409   switch(type){
410      case NC_CHAR :
411  return ((int)sizeof(char));
412      case NC_BYTE :
413  return ((int)sizeof(signed char));
414      case NC_SHORT :
415  return ((int)sizeof(short));
416      case NC_INT :
417  return ((int)sizeof(int));
418      case NC_FLOAT :
419  return ((int)sizeof(float));
420      case NC_DOUBLE :
421  return ((int)sizeof(double));
422
423  /* These can occur in netcdf-3 code */
424      case NC_UBYTE :
425  return ((int)sizeof(unsigned char));
426      case NC_USHORT :
427  return ((int)(sizeof(unsigned short)));
428      case NC_UINT :
429  return ((int)sizeof(unsigned int));
430      case NC_INT64 :
431  return ((int)sizeof(signed long long));
432      case NC_UINT64 :
433  return ((int)sizeof(unsigned long long));
434#ifdef USE_NETCDF4
435      case NC_STRING :
436  return ((int)sizeof(char*));
437#endif /*USE_NETCDF4*/
438
439      default:
440  return -1;
441   }
442}
443
444/** \internal
445\ingroup variables
446Find the length of a type. Redunant over nctypelen() above. */
447size_t
448NC_atomictypelen(nc_type xtype)
449{
450   size_t sz = 0;
451   switch(xtype) {
452      case NC_NATsz = 0; break;
453      case NC_BYTEsz = sizeof(signed char); break;
454      case NC_CHARsz = sizeof(char); break;
455      case NC_SHORTsz = sizeof(short); break;
456      case NC_INTsz = sizeof(int); break;
457      case NC_FLOATsz = sizeof(float); break;
458      case NC_DOUBLEsz = sizeof(double); break;
459      case NC_INT64sz = sizeof(signed long long); break;
460      case NC_UBYTEsz = sizeof(unsigned char); break;
461      case NC_USHORTsz = sizeof(unsigned short); break;
462      case NC_UINTsz = sizeof(unsigned int); break;
463      case NC_UINT64sz = sizeof(unsigned long long); break;
464#ifdef USE_NETCDF4
465      case NC_STRINGsz = sizeof(char*); break;
466#endif
467      default: break;
468   }
469   return sz;
470}
471
472/** \internal
473\ingroup variables
474    Get the type name. */
475char *
476NC_atomictypename(nc_type xtype)
477{
478   char* nm = NULL;
479   switch(xtype) {
480      case NC_NATnm = "undefined"; break;
481      case NC_BYTEnm = "byte"; break;
482      case NC_CHARnm = "char"; break;
483      case NC_SHORTnm = "short"; break;
484      case NC_INTnm = "int"; break;
485      case NC_FLOATnm = "float"; break;
486      case NC_DOUBLEnm = "double"; break;
487      case NC_INT64nm = "int64"; break;
488      case NC_UBYTEnm = "ubyte"; break;
489      case NC_USHORTnm = "ushort"; break;
490      case NC_UINTnm = "uint"; break;
491      case NC_UINT64nm = "uint64"; break;
492#ifdef USE_NETCDF4
493      case NC_STRINGnm = "string"; break;
494#endif
495      default: break;
496   }
497   return nm;
498}
499
500/** \internal
501\ingroup variables
502Get the shape of a variable.
503 */
504int
505NC_getshape(int ncid, int varid, int ndims, size_t* shape)
506{
507   int dimids[NC_MAX_VAR_DIMS];
508   int i;
509   int status = NC_NOERR;
510
511   if ((status = nc_inq_vardimid(ncidvariddimids)))
512      return status;
513   for(i = 0; i < ndimsi++)
514      if ((status = nc_inq_dimlen(nciddimids[i], &shape[i])))
515  break;
516
517   return status;
518}
519
520#ifdef USE_NETCDF4
521/** \ingroup variables
522
523\param ncid NetCDF or group ID, from a previous call to nc_open(),
524nc_create(), nc_def_grp(), or associated inquiry functions such as
525nc_inq_ncid().
526
527\param varid Variable ID
528
529\param size The total size of the raw data chunk cache, in bytes.
530
531\param nelems The number of chunk slots in the raw data chunk cache.
532
533\param preemption The preemption, a value between 0 and 1 inclusive
534that indicates how much chunks that have been fully read are favored
535for preemption. A value of zero means fully read chunks are treated no
536differently than other chunks (the preemption is strictly LRU) while a
537value of one means fully read chunks are always preempted before other
538chunks.
539
540\returns ::NC_NOERR No error.
541\returns ::NC_EBADID Bad ncid.
542\returns ::NC_ENOTVAR Invalid variable ID.
543\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
544\returns ::NC_EINVAL Invalid input
545 */
546int
547nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems,
548        float preemption)
549{
550    NCncp;
551    int stat = NC_check_id(ncid, &ncp);
552    if(stat != NC_NOERR) return stat;
553    return ncp->dispatch->set_var_chunk_cache(ncidvaridsize,
554       nelemspreemption);
555}
556
557/** \ingroup variables
558
559\param ncid NetCDF or group ID, from a previous call to nc_open(),
560nc_create(), nc_def_grp(), or associated inquiry functions such as
561nc_inq_ncid().
562
563\param varid Variable ID
564
565\param sizep The total size of the raw data chunk cache, in bytes,
566will be put here. \ref ignored_if_null.
567
568\param nelemsp The number of chunk slots in the raw data chunk cache
569hash table will be put here. \ref ignored_if_null.
570
571\param preemptionp The preemption will be put here. The preemtion
572value is between 0 and 1 inclusive and indicates how much chunks that
573have been fully read are favored for preemption. A value of zero means
574fully read chunks are treated no differently than other chunks (the
575preemption is strictly LRU) while a value of one means fully read
576chunks are always preempted before other chunks. \ref ignored_if_null.
577
578\returns ::NC_NOERR No error.
579\returns ::NC_EBADID Bad ncid.
580\returns ::NC_ENOTVAR Invalid variable ID.
581\returns ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file.
582\returns ::NC_EINVAL Invalid input
583*/
584int
585nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp,
586        float *preemptionp)
587{
588    NCncp;
589    int stat = NC_check_id(ncid, &ncp);
590    if(stat != NC_NOERR) return stat;
591    return ncp->dispatch->get_var_chunk_cache(ncidvaridsizep,
592       nelemsppreemptionp);
593}
594
595/** \ingroup variables
596Free string space allocated by the library.
597
598When you read string type the library will allocate the storage space
599for the data. This storage space must be freed, so pass the pointer
600back to this function, when you're done with the data, and it will
601free the string memory.
602
603\param len The number of character arrays in the array.
604\param data The pointer to the data array.
605
606\returns ::NC_NOERR No error.
607*/
608int
609nc_free_string(size_t len, char **data)
610{
611   int i;
612   for (i = 0; i < leni++)
613      free(data[i]);
614   return NC_NOERR;
615}
616
617int
618nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level)
619{
620    NCncp;
621    int stat = NC_check_id(ncid,&ncp);
622    if(stat != NC_NOERR) return stat;
623    return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level);
624}
625
626int
627nc_def_var_fletcher32(int ncid, int varid, int fletcher32)
628{
629    NCncp;
630    int stat = NC_check_id(ncid,&ncp);
631    if(stat != NC_NOERR) return stat;
632    return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32);
633}
634
635/*! Define chunking parameters for a variable
636
637\ingroup variables
638
639The function nc_def_var_chunking sets the chunking parameters for a variable in a netCDF-4 file. It can set the chunk sizes to get chunked storage, or it can set the contiguous flag to get contiguous storage.
640
641The total size of a chunk must be less than 4 GiB. That is, the product of all chunksizes and the size of the data (or the size of nc_vlen_t for VLEN types) must be less than 4 GiB.
642
643This function may only be called after the variable is defined, but before nc_enddef is called. Once the chunking parameters are set for a variable, they cannot be changed.
644
645Note that this does not work for scalar variables. Only non-scalar variables can have chunking.
646
647
648
649@param[in] ncid NetCDF ID, from a previous call to nc_open or nc_create.
650@param[in] varid Variable ID.
651@param[in] storage If ::NC_CONTIGUOUS, then contiguous storage is used for this variable. Variables with one or more unlimited dimensions cannot use contiguous storage. If contiguous storage is turned on, the chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked storage is used for this variable. Chunk sizes may be specified with the chunksizes parameter or default sizes will be used if that parameter is NULL.
652@param[in] chunksizesp A pointer to an array list of chunk sizes. The array must have one chunksize for each dimension of the variable. If ::NC_CONTIGUOUS storage is set, then the chunksizes parameter is ignored.
653
654@returns ::NC_NOERR No error.
655@returns ::NC_EBADID Bad ID.
656@returns ::NC_ENOTNC4 Not a netCDF-4 file.
657@returns ::NC_ELATEDEF This variable has already been the subject of a nc_enddef call.  In netCDF-4 files nc_enddef will be called automatically for any data read or write. Once nc_enddef has been called after the nc_def_var call for a variable, it is impossible to set the chunking for that variable.
658@returns ::NC_ENOTINDEFINE Not in define mode.  This is returned for netCDF classic or 64-bit offset files, or for netCDF-4 files, when they wwere created with NC_STRICT_NC3 flag. See \ref nc_create.
659@returns ::NC_EPERM Attempt to create object in read-only file.
660@returns ::NC_EBADCHUNK Retunrs if the chunk size specified for a variable is larger than the length of the dimensions associated with variable.
661
662\section nc_def_var_chunking_example Example
663
664In this example from libsrc4/tst_vars2.c, chunksizes are set with nc_var_def_chunking, and checked with nc_var_inq_chunking.
665
666\code
667        printf("**** testing chunking...");
668        {
669     #define NDIMS5 1
670     #define DIM5_NAME "D5"
671     #define VAR_NAME5 "V5"
672     #define DIM5_LEN 1000
673
674           int dimids[NDIMS5], dimids_in[NDIMS5];
675           int varid;
676           int ndims, nvars, natts, unlimdimid;
677           nc_type xtype_in;
678           char name_in[NC_MAX_NAME + 1];
679           int data[DIM5_LEN], data_in[DIM5_LEN];
680           size_t chunksize[NDIMS5] = {5};
681           size_t chunksize_in[NDIMS5];
682           int storage_in;
683           int i, d;
684
685           for (i = 0; i < DIM5_LEN; i++)
686              data[i] = i;
687
688           if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
689           if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR;
690           if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR;
691           if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR;
692           if (nc_put_var_int(ncid, varid, data)) ERR;
693
694           if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR;
695           for (d = 0; d < NDIMS5; d++)
696              if (chunksize[d] != chunksize_in[d]) ERR;
697           if (storage_in != NC_CHUNKED) ERR;
698\endcode
699
700*/
701int
702nc_def_var_chunking(int ncid, int varid, int storage,
703     const size_t *chunksizesp)
704{
705    NCncp;
706    int stat = NC_check_id(ncid, &ncp);
707    if(stat != NC_NOERR) return stat;
708    return ncp->dispatch->def_var_chunking(ncidvaridstorage,
709    chunksizesp);
710}
711
712int
713nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value)
714{
715    NCncp;
716    int stat = NC_check_id(ncid,&ncp);
717    if(stat != NC_NOERR) return stat;
718    return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value);
719}
720
721int
722nc_def_var_endian(int ncid, int varid, int endian)
723{
724    NCncp;
725    int stat = NC_check_id(ncid,&ncp);
726    if(stat != NC_NOERR) return stat;
727    return ncp->dispatch->def_var_endian(ncid,varid,endian);
728}
729
730#endif /* USE_NETCDF4 */


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed