/src/gdal/netcdf-c-4.7.4/libdispatch/dvar.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2010-2018 University Corporation for Atmospheric |
2 | | Research/Unidata. See COPYRIGHT file for more info. */ |
3 | | /** |
4 | | * @file |
5 | | * Functions for defining and inquiring about variables. @note The |
6 | | * order of functions in this file affects the doxygen documentation. |
7 | | */ |
8 | | |
9 | | #include "config.h" |
10 | | #include "netcdf.h" |
11 | | #include "netcdf_filter.h" |
12 | | #include "ncdispatch.h" |
13 | | #include "nc4internal.h" |
14 | | #include "netcdf_f.h" |
15 | | #include "nc4internal.h" |
16 | | |
17 | | /** |
18 | | @defgroup variables Variables |
19 | | |
20 | | Variables hold multi-dimensional arrays of data. |
21 | | |
22 | | Variables for a netCDF dataset are defined when the dataset is |
23 | | created, while the netCDF dataset is in define mode. Other |
24 | | variables may be added later by reentering define mode. A netCDF |
25 | | variable has a name, a type, and a shape, which are specified when |
26 | | it is defined. A variable may also have values, which are |
27 | | established later in data mode. |
28 | | |
29 | | Ordinarily, the name, type, and shape are fixed when the variable |
30 | | is first defined. The name may be changed, but the type and shape |
31 | | of a variable cannot be changed. However, a variable defined in |
32 | | terms of the unlimited dimension can grow without bound in that |
33 | | dimension. |
34 | | |
35 | | A netCDF variable in an open netCDF dataset is referred to by a |
36 | | small integer called a variable ID. |
37 | | |
38 | | Variable IDs reflect the order in which variables were defined |
39 | | within a netCDF dataset. Variable IDs are 0, 1, 2,..., in the order |
40 | | in which the variables were defined. A function is available for |
41 | | getting the variable ID from the variable name and vice-versa. |
42 | | |
43 | | @ref attributes may be associated with a variable to specify such |
44 | | properties as units. |
45 | | |
46 | | Operations supported on variables are: |
47 | | - Create a variable, given its name, data type, and shape. |
48 | | - Get a variable ID from its name. |
49 | | - Get a variable's name, data type, shape, and number of attributes |
50 | | from its ID. |
51 | | - Put a data value into a variable, given variable ID, indices, and value. |
52 | | - Put an array of values into a variable, given variable ID, corner |
53 | | indices, edge lengths, and a block of values. |
54 | | - Put a subsampled or mapped array-section of values into a variable, |
55 | | given variable ID, corner indices, edge lengths, stride vector, |
56 | | index mapping vector, and a block of values. |
57 | | - Get a data value from a variable, given variable ID and indices. |
58 | | - Get an array of values from a variable, given variable ID, corner |
59 | | indices, and edge lengths. |
60 | | - Get a subsampled or mapped array-section of values from a variable, |
61 | | given variable ID, corner indices, edge lengths, stride vector, and |
62 | | index mapping vector. |
63 | | - Rename a variable. |
64 | | |
65 | | @section language_types Data Types |
66 | | |
67 | | NetCDF supported six atomic data types through version 3.6.0 (char, |
68 | | byte, short, int, float, and double). Starting with version 4.0, many |
69 | | new atomic and user defined data types are supported (unsigned int |
70 | | types, strings, compound types, variable length arrays, enums, |
71 | | opaque). |
72 | | |
73 | | The additional data types are only supported in netCDF-4/HDF5 |
74 | | files. To create netCDF-4/HDF5 files, use the ::NC_NETCDF4 flag in |
75 | | nc_create(). |
76 | | |
77 | | @section classic_types NetCDF-3 Classic and 64-Bit Offset Data Types |
78 | | |
79 | | NetCDF-3 classic and 64-bit offset files support 6 atomic data types, |
80 | | and none of the user defined datatype introduced in NetCDF-4. |
81 | | |
82 | | The following table gives the netCDF-3 external data types and the |
83 | | corresponding type constants for defining variables in the C |
84 | | interface: |
85 | | |
86 | | <table> |
87 | | <tr><td>Type</td><td>C define</td><td>Bits</td></tr> |
88 | | <tr><td>byte</td><td>::NC_BYTE</td><td>8</td></tr> |
89 | | <tr><td>char</td><td>::NC_CHAR</td><td>8</td></tr> |
90 | | <tr><td>short</td><td>::NC_SHORT</td><td>16</td></tr> |
91 | | <tr><td>int</td><td>::NC_INT</td><td>32</td></tr> |
92 | | <tr><td>float</td><td>::NC_FLOAT</td><td>32</td></tr> |
93 | | <tr><td>double</td><td>::NC_DOUBLE</td><td>64</td></tr> |
94 | | </table> |
95 | | |
96 | | The first column gives the netCDF external data type, which is the |
97 | | same as the CDL data type. The next column gives the corresponding C |
98 | | pre-processor macro for use in netCDF functions (the pre-processor |
99 | | macros are defined in the netCDF C header-file netcdf.h). The last |
100 | | column gives the number of bits used in the external representation of |
101 | | values of the corresponding type. |
102 | | |
103 | | @section netcdf_4_atomic NetCDF-4 Atomic Data Types |
104 | | |
105 | | NetCDF-4 files support all of the atomic data types from netCDF-3, |
106 | | plus additional unsigned integer types, 64-bit integer types, and a |
107 | | string type. |
108 | | |
109 | | <table> |
110 | | <tr><td>Type</td><td>C define</td><td>Bits |
111 | | |
112 | | <tr><td>byte</td><td>::NC_BYTE</td><td>8</td></tr> |
113 | | <tr><td>unsigned byte </td><td>::NC_UBYTE^</td><td> 8</td></tr> |
114 | | <tr><td>char </td><td>::NC_CHAR </td><td>8</td></tr> |
115 | | <tr><td>short </td><td>::NC_SHORT </td><td>16</td></tr> |
116 | | <tr><td>unsigned short </td><td>::NC_USHORT^ </td><td>16</td></tr> |
117 | | <tr><td>int </td><td>::NC_INT </td><td>32</td></tr> |
118 | | <tr><td>unsigned int </td><td>::NC_UINT^ </td><td>32</td></tr> |
119 | | <tr><td>unsigned long long </td><td>::NC_UINT64^ </td><td>64</td></tr> |
120 | | <tr><td>long long </td><td>::NC_INT64^ </td><td>64</td></tr> |
121 | | <tr><td>float </td><td>::NC_FLOAT </td><td>32</td></tr> |
122 | | <tr><td>double </td><td>::NC_DOUBLE </td><td>64</td></tr> |
123 | | <tr><td>char ** </td><td>::NC_STRING^ </td><td>string length + 1</td></tr> |
124 | | </table> |
125 | | |
126 | | ^This type was introduced in netCDF-4, and is not supported in netCDF |
127 | | classic or 64-bit offset format files, or in netCDF-4 files if they |
128 | | are created with the ::NC_CLASSIC_MODEL flags. |
129 | | */ |
130 | | |
131 | | /** @{ */ |
132 | | /** |
133 | | @name Defining Variables |
134 | | |
135 | | Use these functions to define variables. |
136 | | */ |
137 | | /*! @{ */ |
138 | | |
139 | | /** |
140 | | Define a new variable. |
141 | | |
142 | | This function adds a new variable to an open netCDF dataset or group. |
143 | | It returns (as an argument) a variable ID, given the netCDF ID, |
144 | | the variable name, the variable type, the number of dimensions, and a |
145 | | list of the dimension IDs. |
146 | | |
147 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
148 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
149 | | nc_inq_ncid(). |
150 | | @param name Variable @ref object_name. |
151 | | @param xtype @ref data_type of the variable. |
152 | | @param ndims Number of dimensions for the variable. For example, 2 |
153 | | specifies a matrix, 1 specifies a vector, and 0 means the variable is |
154 | | a scalar with no dimensions. Must not be negative or greater than the |
155 | | predefined constant ::NC_MAX_VAR_DIMS. In netCDF-4/HDF5 files, may not |
156 | | exceed the HDF5 maximum number of dimensions (32). |
157 | | @param dimidsp Vector of ndims dimension IDs corresponding to the |
158 | | variable dimensions. For classic model netCDF files, if the ID of the |
159 | | unlimited dimension is included, it must be first. This argument is |
160 | | ignored if ndims is 0. For expanded model netCDF4/HDF5 files, there |
161 | | may be any number of unlimited dimensions, and they may be used in any |
162 | | element of the dimids array. |
163 | | @param varidp Pointer to location for the returned variable ID. |
164 | | |
165 | | @return ::NC_NOERR No error. |
166 | | @return ::NC_EBADID Bad ncid. |
167 | | @return ::NC_ENOTINDEFINE Not in define mode. |
168 | | @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 netcdf-4 file. |
169 | | @return ::NC_EMAXVARS NC_MAX_VARS exceeded [Not enforced after 4.5.0] |
170 | | @return ::NC_EBADTYPE Bad type. |
171 | | @return ::NC_EINVAL Invalid input. |
172 | | @return ::NC_ENAMEINUSE Name already in use. |
173 | | @return ::NC_EPERM Attempt to create object in read-only file. |
174 | | |
175 | | @section nc_def_var_example Example |
176 | | |
177 | | Here is an example using nc_def_var to create a variable named rh of |
178 | | type double with three dimensions, time, lat, and lon in a new netCDF |
179 | | dataset named foo.nc: |
180 | | |
181 | | @code |
182 | | #include <netcdf.h> |
183 | | ... |
184 | | int status; |
185 | | int ncid; |
186 | | int lat_dim, lon_dim, time_dim; |
187 | | int rh_id; |
188 | | int rh_dimids[3]; |
189 | | ... |
190 | | status = nc_create("foo.nc", NC_NOCLOBBER, &ncid); |
191 | | if (status != NC_NOERR) handle_error(status); |
192 | | ... |
193 | | |
194 | | status = nc_def_dim(ncid, "lat", 5L, &lat_dim); |
195 | | if (status != NC_NOERR) handle_error(status); |
196 | | status = nc_def_dim(ncid, "lon", 10L, &lon_dim); |
197 | | if (status != NC_NOERR) handle_error(status); |
198 | | status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim); |
199 | | if (status != NC_NOERR) handle_error(status); |
200 | | ... |
201 | | |
202 | | rh_dimids[0] = time_dim; |
203 | | rh_dimids[1] = lat_dim; |
204 | | rh_dimids[2] = lon_dim; |
205 | | status = nc_def_var (ncid, "rh", NC_DOUBLE, 3, rh_dimids, &rh_id); |
206 | | if (status != NC_NOERR) handle_error(status); |
207 | | @endcode |
208 | | |
209 | | @author Glenn Davis, Ed Hartnett, Dennis Heimbigner |
210 | | */ |
211 | | int |
212 | | nc_def_var(int ncid, const char *name, nc_type xtype, |
213 | | int ndims, const int *dimidsp, int *varidp) |
214 | 150k | { |
215 | 150k | NC* ncp; |
216 | 150k | int stat = NC_NOERR; |
217 | | |
218 | 150k | if ((stat = NC_check_id(ncid, &ncp))) |
219 | 0 | return stat; |
220 | 150k | TRACE(nc_def_var); |
221 | 150k | return ncp->dispatch->def_var(ncid, name, xtype, ndims, |
222 | 150k | dimidsp, varidp); |
223 | 150k | } |
224 | | |
225 | | /** |
226 | | Set the fill value for a variable. |
227 | | |
228 | | @note For netCDF classic, 64-bit offset, and CDF5 formats, it is |
229 | | allowed (but not good practice) to set the fill value after data |
230 | | have been written to the variable. In this case, unless the |
231 | | variable has been completely specified (without gaps in the data), |
232 | | any existing filled values will not be recognized as fill values by |
233 | | applications reading the data. Best practice is to set the fill |
234 | | value after the variable has been defined, but before any data have |
235 | | been written to that variable. In NetCDF-4 files, this is enforced |
236 | | by the HDF5 library. For netCDF-4 files, an error is returned if |
237 | | the user attempts to set the fill value after writing data to the |
238 | | variable. |
239 | | |
240 | | @param ncid NetCDF ID, from a previous call to nc_open() or |
241 | | nc_create(). |
242 | | @param varid Variable ID. |
243 | | @param no_fill Set to ::NC_NOFILL to turn off fill mode for this |
244 | | variable. Set to ::NC_FILL (the default) to turn on fill mode for |
245 | | the variable. |
246 | | @param fill_value the fill value to be used for this variable. Must |
247 | | be the same type as the variable. This must point to enough free |
248 | | memory to hold one element of the data type of the variable. (For |
249 | | example, an ::NC_INT will require 4 bytes for it's fill value, |
250 | | which is also an ::NC_INT.) |
251 | | |
252 | | @return ::NC_NOERR No error. |
253 | | @return ::NC_EBADID Bad ID. |
254 | | @return ::NC_ENOTINDEFINE Not in define mode. This is returned for |
255 | | netCDF classic, 64-bit offset, or 64-bit data files, or for |
256 | | netCDF-4 files, when they were created with ::NC_CLASSIC_MODEL flag by |
257 | | nc_creae(). |
258 | | @return ::NC_EPERM Attempt to create object in read-only file. |
259 | | @return ::NC_ELATEDEF (NetCDF-4 only). Returned when user attempts |
260 | | to set fill value after data are written. |
261 | | @return ::NC_EGLOBAL Attempt to set fill value on NC_GLOBAL. |
262 | | |
263 | | @section nc_def_var_fill_example Example |
264 | | |
265 | | In this example from libsrc4/tst_vars.c, a variable is defined, and |
266 | | the fill mode turned off. Then nc_inq_fill() is used to check that |
267 | | the setting is correct. Then some data are written to the |
268 | | variable. Since the data that are written do not cover the full |
269 | | extent of the variable, the missing values will just be random. If |
270 | | fill value mode was turned on, the missing values would get the |
271 | | fill value. |
272 | | |
273 | | @code |
274 | | #define DIM7_LEN 2 |
275 | | #define DIM7_NAME "dim_7_from_Indiana" |
276 | | #define VAR7_NAME "var_7_from_Idaho" |
277 | | #define NDIMS 1 |
278 | | int dimids[NDIMS]; |
279 | | size_t index[NDIMS]; |
280 | | int varid; |
281 | | int no_fill; |
282 | | unsigned short ushort_data = 42, ushort_data_in, fill_value_in; |
283 | | |
284 | | if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; |
285 | | if (nc_def_dim(ncid, DIM7_NAME, DIM7_LEN, &dimids[0])) ERR; |
286 | | if (nc_def_var(ncid, VAR7_NAME, NC_USHORT, NDIMS, dimids, |
287 | | &varid)) ERR; |
288 | | if (nc_def_var_fill(ncid, varid, 1, NULL)) ERR; |
289 | | |
290 | | if (nc_inq_var_fill(ncid, varid, &no_fill, &fill_value_in)) ERR; |
291 | | if (!no_fill) ERR; |
292 | | |
293 | | index[0] = 1; |
294 | | if (nc_put_var1_ushort(ncid, varid, index, &ushort_data)) ERR; |
295 | | |
296 | | index[0] = 0; |
297 | | if (nc_get_var1_ushort(ncid, varid, index, &ushort_data_in)) ERR; |
298 | | |
299 | | if (nc_close(ncid)) ERR; |
300 | | @endcode |
301 | | @author Glenn Davis, Ed Hartnett, Dennis Heimbigner |
302 | | */ |
303 | | int |
304 | | nc_def_var_fill(int ncid, int varid, int no_fill, const void *fill_value) |
305 | 0 | { |
306 | 0 | NC* ncp; |
307 | 0 | int stat = NC_check_id(ncid,&ncp); |
308 | 0 | if(stat != NC_NOERR) return stat; |
309 | | |
310 | | /* Using NC_GLOBAL is illegal, as this API has no provision for |
311 | | * specifying the type of the fillvalue, it must of necessity be |
312 | | * using the type of the variable to interpret the bytes of the |
313 | | * fill_value argument. */ |
314 | 0 | if (varid == NC_GLOBAL) return NC_EGLOBAL; |
315 | | |
316 | 0 | return ncp->dispatch->def_var_fill(ncid,varid,no_fill,fill_value); |
317 | 0 | } |
318 | | |
319 | | /** |
320 | | Set the zlib compression settings for a netCDF-4/HDF5 variable. |
321 | | |
322 | | This function must be called after nc_def_var and before nc_enddef |
323 | | or any functions which writes data to the file. |
324 | | |
325 | | Deflation and shuffline require chunked data. If this function is |
326 | | called on a variable with contiguous data, then the data is changed |
327 | | to chunked data, with default chunksizes. Use nc_def_var_chunking() |
328 | | to tune performance with user-defined chunksizes. |
329 | | |
330 | | If this function is called on a scalar variable, ::NC_EINVAL is |
331 | | returned. Only chunked variables may use filters. |
332 | | |
333 | | If this function is called on a variable which already has szip |
334 | | compression turned on, ::NC_EINVAL is returned. |
335 | | |
336 | | @note Parallel I/O reads work with compressed data. Parallel I/O |
337 | | writes work with compressed data in netcdf-c-4.7.4 and later |
338 | | releases, using hdf5-1.10.3 and later releases. Using the zlib, |
339 | | shuffle (or any other) filter requires that collective access be |
340 | | used with the variable. Turning on deflate and/or shuffle for a |
341 | | variable in a file opened for parallel I/O will automatically |
342 | | switch the access for that variable to collective access. |
343 | | |
344 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
345 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
346 | | nc_inq_ncid(). |
347 | | @param varid Variable ID |
348 | | @param shuffle True to turn on the shuffle filter. The shuffle |
349 | | filter can assist with the compression of data by changing the byte |
350 | | order in the data stream. It makes no sense to use the shuffle |
351 | | filter without setting a deflate level. |
352 | | @param deflate True to turn on deflation for this variable. |
353 | | @param deflate_level A number between 0 (no compression) and 9 |
354 | | (maximum compression). |
355 | | |
356 | | @return ::NC_NOERR No error. |
357 | | @return ::NC_EBADID Bad ncid. |
358 | | @return ::NC_ENOTVAR Invalid variable ID. |
359 | | @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is |
360 | | not netCDF-4/HDF5. |
361 | | @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 |
362 | | netcdf-4 file. |
363 | | @return ::NC_ELATEDEF Too late to change settings for this variable. |
364 | | @return ::NC_ENOTINDEFINE Not in define mode. |
365 | | @return ::NC_EPERM File is read only. |
366 | | @return ::NC_ESTRICTNC3 Attempting to create netCDF-4 type var in |
367 | | classic model file |
368 | | @return ::NC_EHDFERR Error returned by HDF5 layer. |
369 | | @return ::NC_EINVAL Invalid input. Deflate can't be set unless |
370 | | variable storage is NC_CHUNK. |
371 | | |
372 | | @section nc_def_var_deflate_example Example |
373 | | |
374 | | Here is an example from /examples/C/simple_xy_nc4_wr.c using |
375 | | nc_def_var_deflate to create a variable and then turn on the shuffle |
376 | | filter and compression. |
377 | | |
378 | | @code |
379 | | #include <netcdf.h> |
380 | | #define NDIMS 2 |
381 | | #define NX 6 |
382 | | #define NY 12 |
383 | | |
384 | | int ncid, x_dimid, y_dimid, varid; |
385 | | int dimids[NDIMS]; |
386 | | int shuffle, deflate, deflate_level; |
387 | | int data_out[NX][NY]; |
388 | | int x, y, retval; |
389 | | |
390 | | shuffle = NC_SHUFFLE; |
391 | | deflate = 1; |
392 | | deflate_level = 1; |
393 | | ... |
394 | | if ((retval = nc_create(FILE_NAME, NC_NETCDF4, &ncid))) |
395 | | ERR(retval); |
396 | | |
397 | | if ((retval = nc_def_dim(ncid, "x", NX, &x_dimid))) |
398 | | ERR(retval); |
399 | | if ((retval = nc_def_dim(ncid, "y", NY, &y_dimid))) |
400 | | ERR(retval); |
401 | | |
402 | | dimids[0] = x_dimid; |
403 | | dimids[1] = y_dimid; |
404 | | |
405 | | if ((retval = nc_def_var(ncid, "data", NC_INT, NDIMS, |
406 | | dimids, &varid))) |
407 | | ERR(retval); |
408 | | |
409 | | ... |
410 | | |
411 | | if ((retval = nc_def_var_deflate(ncid, varid, shuffle, deflate, |
412 | | deflate_level))) |
413 | | ERR(retval); |
414 | | ... |
415 | | @endcode |
416 | | @author Ed Hartnett, Dennis Heimbigner |
417 | | */ |
418 | | int |
419 | | nc_def_var_deflate(int ncid, int varid, int shuffle, int deflate, int deflate_level) |
420 | 0 | { |
421 | 0 | NC* ncp; |
422 | 0 | int stat = NC_check_id(ncid,&ncp); |
423 | 0 | if(stat != NC_NOERR) return stat; |
424 | 0 | return ncp->dispatch->def_var_deflate(ncid,varid,shuffle,deflate,deflate_level); |
425 | 0 | } |
426 | | |
427 | | /** |
428 | | Set checksum for a var. |
429 | | |
430 | | This function must be called after nc_def_var and before nc_enddef |
431 | | or any functions which writes data to the file. |
432 | | |
433 | | Checksums require chunked data. If this function is called on a |
434 | | variable with contiguous data, then the data is changed to chunked |
435 | | data, with default chunksizes. Use nc_def_var_chunking() to tune |
436 | | performance with user-defined chunksizes. |
437 | | |
438 | | @note Parallel I/O reads work with fletcher32 encoded |
439 | | data. Parallel I/O writes work with fletcher32 in netcdf-c-4.7.4 |
440 | | and later releases, using hdf5-1.10.2 and later releases. Using the |
441 | | fletcher32 (or any) filter requires that collective access be used |
442 | | with the variable. Turning on fletcher32 for a variable in a file |
443 | | opened for parallel I/O will automatically switch the access for |
444 | | that variable to collective access. |
445 | | |
446 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
447 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
448 | | nc_inq_ncid(). |
449 | | @param varid Variable ID |
450 | | @param fletcher32 True to turn on Fletcher32 checksums for this |
451 | | variable. |
452 | | |
453 | | @return ::NC_NOERR No error. |
454 | | @return ::NC_EBADID Bad ncid. |
455 | | @return ::NC_ENOTVAR Invalid variable ID. |
456 | | @return ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is |
457 | | not netCDF-4/HDF5. |
458 | | @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 |
459 | | netcdf-4 file. |
460 | | @return ::NC_ELATEDEF Too late to change settings for this variable. |
461 | | @return ::NC_EINVAL Invalid input |
462 | | @author Ed Hartnett, Dennis Heimbigner |
463 | | */ |
464 | | int |
465 | | nc_def_var_fletcher32(int ncid, int varid, int fletcher32) |
466 | 0 | { |
467 | 0 | NC* ncp; |
468 | 0 | int stat = NC_check_id(ncid,&ncp); |
469 | 0 | if(stat != NC_NOERR) return stat; |
470 | 0 | return ncp->dispatch->def_var_fletcher32(ncid,varid,fletcher32); |
471 | 0 | } |
472 | | |
473 | | /** |
474 | | Define storage and, if chunked storage is used, chunking parameters |
475 | | for a variable |
476 | | |
477 | | The storage may be set to NC_CONTIGUOUS, NC_COMPACT, or NC_CHUNKED. |
478 | | |
479 | | Contiguous storage means the variable is stored as one block of |
480 | | data in the file. This is the default storage. |
481 | | |
482 | | Compact storage means the variable is stored in the header record |
483 | | of the file. This can have large performance benefits on HPC system |
484 | | running many processors. Compact storage is only available for |
485 | | variables whose data are 64 KB or less. Attempting to turn on |
486 | | compact storage for a variable that is too large will result in the |
487 | | ::NC_EVARSIZE error. |
488 | | |
489 | | Chunked storage means the data are stored as chunks, of |
490 | | user-configurable size. Chunked storage is required for variable |
491 | | with one or more unlimted dimensions, or variable which use |
492 | | compression, or any other filter. |
493 | | |
494 | | The total size of a chunk must be less than 4 GiB. That is, the |
495 | | product of all chunksizes and the size of the data (or the size of |
496 | | nc_vlen_t for VLEN types) must be less than 4 GiB. |
497 | | |
498 | | This function may only be called after the variable is defined, but |
499 | | before nc_enddef is called. Once the chunking parameters are set for a |
500 | | variable, they cannot be changed. |
501 | | |
502 | | @note Scalar variables may have a storage of NC_CONTIGUOUS or |
503 | | NC_COMPACT. Attempts to set chunking on a scalare variable will |
504 | | cause ::NC_EINVEL to be returned. Only non-scalar variables can |
505 | | have chunking. |
506 | | |
507 | | @param ncid NetCDF ID, from a previous call to nc_open() or |
508 | | nc_create(). |
509 | | @param varid Variable ID. |
510 | | @param storage If ::NC_CONTIGUOUS or ::NC_COMPACT, then contiguous |
511 | | or compact storage is used for this variable. Variables with one or |
512 | | more unlimited dimensions cannot use contiguous or compact |
513 | | storage. If contiguous or compact storage is turned on, the |
514 | | chunksizes parameter is ignored. If ::NC_CHUNKED, then chunked |
515 | | storage is used for this variable. Chunk sizes may be specified |
516 | | with the chunksizes parameter or default sizes will be used if that |
517 | | parameter is NULL. |
518 | | @param chunksizesp A pointer to an array list of chunk sizes. The |
519 | | array must have one chunksize for each dimension of the variable. If |
520 | | ::NC_CONTIGUOUS storage is set, then the chunksizes parameter is |
521 | | ignored. Ignored if NULL. |
522 | | |
523 | | @return ::NC_NOERR No error. |
524 | | @return ::NC_EBADID Bad ID. |
525 | | @return ::NC_ENOTNC4 Not a netCDF-4 file. |
526 | | @return ::NC_ELATEDEF This variable has already been the subject of |
527 | | a nc_enddef call. In netCDF-4 files nc_enddef will be called |
528 | | automatically for any data read or write. Once nc_enddef has been |
529 | | called after the nc_def_var call for a variable, it is impossible |
530 | | to set the chunking for that variable. |
531 | | @return ::NC_ENOTINDEFINE Not in define mode. This is returned for |
532 | | netCDF classic or 64-bit offset files, or for netCDF-4 files, when |
533 | | they wwere created with ::NC_CLASSIC_MODEL flag by nc_create(). |
534 | | @return ::NC_EPERM Attempt to create object in read-only file. |
535 | | @return ::NC_EBADCHUNK Returns if the chunk size specified for a |
536 | | variable is larger than the length of the dimensions associated with |
537 | | variable. |
538 | | @return ::NC_EVARSIZE Compact storage attempted for variable bigger |
539 | | than 64 KB. |
540 | | @return ::NC_EINVAL Attempt to set contiguous or compact storage |
541 | | for var with one or more unlimited dimensions, or chunking for a |
542 | | scalar var. |
543 | | |
544 | | @section nc_def_var_chunking_example Example |
545 | | |
546 | | In this example from libsrc4/tst_vars2.c, chunksizes are set with |
547 | | nc_var_def_chunking, and checked with nc_var_inq_chunking. |
548 | | |
549 | | @code |
550 | | printf("**** testing chunking..."); |
551 | | { |
552 | | #define NDIMS5 1 |
553 | | #define DIM5_NAME "D5" |
554 | | #define VAR_NAME5 "V5" |
555 | | #define DIM5_LEN 1000 |
556 | | |
557 | | int dimids[NDIMS5], dimids_in[NDIMS5]; |
558 | | int varid; |
559 | | int ndims, nvars, natts, unlimdimid; |
560 | | nc_type xtype_in; |
561 | | char name_in[NC_MAX_NAME + 1]; |
562 | | int data[DIM5_LEN], data_in[DIM5_LEN]; |
563 | | size_t chunksize[NDIMS5] = {5}; |
564 | | size_t chunksize_in[NDIMS5]; |
565 | | int storage_in; |
566 | | int i, d; |
567 | | |
568 | | for (i = 0; i < DIM5_LEN; i++) |
569 | | data[i] = i; |
570 | | |
571 | | if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; |
572 | | if (nc_def_dim(ncid, DIM5_NAME, DIM5_LEN, &dimids[0])) ERR; |
573 | | if (nc_def_var(ncid, VAR_NAME5, NC_INT, NDIMS5, dimids, &varid)) ERR; |
574 | | if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, chunksize)) ERR; |
575 | | if (nc_put_var_int(ncid, varid, data)) ERR; |
576 | | |
577 | | if (nc_inq_var_chunking(ncid, varid, &storage_in, chunksize_in)) ERR; |
578 | | for (d = 0; d < NDIMS5; d++) |
579 | | if (chunksize[d] != chunksize_in[d]) ERR; |
580 | | if (storage_in != NC_CHUNKED) ERR; |
581 | | @endcode |
582 | | @author Ed Hartnett, Dennis Heimbigner |
583 | | */ |
584 | | int |
585 | | nc_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp) |
586 | 0 | { |
587 | 0 | NC* ncp; |
588 | 0 | int stat = NC_check_id(ncid, &ncp); |
589 | 0 | if(stat != NC_NOERR) return stat; |
590 | 0 | return ncp->dispatch->def_var_chunking(ncid, varid, storage, |
591 | 0 | chunksizesp); |
592 | 0 | } |
593 | | |
594 | | /** |
595 | | Define endianness of a variable. |
596 | | |
597 | | With this function the endianness (i.e. order of bits in integers) can |
598 | | be changed on a per-variable basis. By default, the endianness is the |
599 | | same as the default endianness of the platform. But with |
600 | | nc_def_var_endianness the endianness can be explicitly set for a |
601 | | variable. |
602 | | |
603 | | Warning: this function is only defined if the type of the variable |
604 | | is an atomic integer or float type. |
605 | | |
606 | | This function may only be called after the variable is defined, but |
607 | | before nc_enddef is called. |
608 | | |
609 | | @param ncid NetCDF ID, from a previous call to nc_open() or |
610 | | nc_create(). |
611 | | |
612 | | @param varid Variable ID. |
613 | | |
614 | | @param endian ::NC_ENDIAN_NATIVE to select the native endianness of |
615 | | the platform (the default), ::NC_ENDIAN_LITTLE to use |
616 | | little-endian, ::NC_ENDIAN_BIG to use big-endian. |
617 | | |
618 | | @return ::NC_NOERR No error. |
619 | | @return ::NC_EBADID Bad ID. |
620 | | @return ::NC_ENOTNC4 Not a netCDF-4 file. |
621 | | @return ::NC_ELATEDEF This variable has already been the subject of a |
622 | | nc_enddef call. In netCDF-4 files nc_enddef will be called |
623 | | automatically for any data read or write. Once nc_enddef has been |
624 | | called after the nc_def_var call for a variable, it is impossible to |
625 | | set the chunking for that variable. |
626 | | @return ::NC_ENOTINDEFINE Not in define mode. This is returned for |
627 | | netCDF classic or 64-bit offset files, or for netCDF-4 files, when |
628 | | they wwere created with ::NC_CLASSIC_MODEL flag by nc_create(). |
629 | | @return ::NC_EPERM Attempt to create object in read-only file. |
630 | | |
631 | | @section nc_def_var_endian_example Example |
632 | | |
633 | | In this example from libsrc4/tst_vars2.c, a variable is created, and |
634 | | the endianness set to ::NC_ENDIAN_BIG. |
635 | | |
636 | | @code |
637 | | #define NDIMS4 1 |
638 | | #define DIM4_NAME "Joe" |
639 | | #define VAR_NAME4 "Ed" |
640 | | #define DIM4_LEN 10 |
641 | | { |
642 | | int dimids[NDIMS4], dimids_in[NDIMS4]; |
643 | | int varid; |
644 | | int ndims, nvars, natts, unlimdimid; |
645 | | nc_type xtype_in; |
646 | | char name_in[NC_MAX_NAME + 1]; |
647 | | int data[DIM4_LEN], data_in[DIM4_LEN]; |
648 | | int endian_in; |
649 | | int i; |
650 | | |
651 | | for (i = 0; i < DIM4_LEN; i++) |
652 | | data[i] = i; |
653 | | |
654 | | if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR; |
655 | | if (nc_def_dim(ncid, DIM4_NAME, DIM4_LEN, &dimids[0])) ERR; |
656 | | if (dimids[0] != 0) ERR; |
657 | | if (nc_def_var(ncid, VAR_NAME4, NC_INT, NDIMS4, dimids, &varid)) ERR; |
658 | | if (nc_def_var_endian(ncid, varid, NC_ENDIAN_BIG)) ERR; |
659 | | @endcode |
660 | | @author Ed Hartnett |
661 | | */ |
662 | | int |
663 | | nc_def_var_endian(int ncid, int varid, int endian) |
664 | 0 | { |
665 | 0 | NC* ncp; |
666 | 0 | int stat = NC_check_id(ncid,&ncp); |
667 | 0 | if(stat != NC_NOERR) return stat; |
668 | 0 | return ncp->dispatch->def_var_endian(ncid,varid,endian); |
669 | 0 | } |
670 | | |
671 | | /** |
672 | | * Set szip compression settings on a variable. Szip is an |
673 | | * implementation of the extended-Rice lossless compression algorithm; |
674 | | * it is reported to provide fast and effective compression. Szip is |
675 | | * only available to netCDF if HDF5 was built with szip support. |
676 | | * |
677 | | * SZIP compression cannot be applied to variables with any |
678 | | * user-defined type. |
679 | | * |
680 | | * If zlib compression has already be turned on for a variable, then |
681 | | * this function will return ::NC_EINVAL. |
682 | | * |
683 | | * To learn the szip settings for a variable, use nc_inq_var_szip(). |
684 | | * |
685 | | * @note The options_mask parameter may be either NC_SZIP_EC (entropy |
686 | | * coding) or NC_SZIP_NN (nearest neighbor): |
687 | | * * The entropy coding method is best suited for data that has been |
688 | | * processed. The EC method works best for small numbers. |
689 | | * * The nearest neighbor coding method preprocesses the data then the |
690 | | * applies EC method as above. |
691 | | * |
692 | | * For more information about HDF5 and szip, see |
693 | | * https://support.hdfgroup.org/HDF5/doc/RM/RM_H5P.html#Property-SetSzip |
694 | | * and |
695 | | * https://support.hdfgroup.org/doc_resource/SZIP/index.html. |
696 | | * |
697 | | * @param ncid File ID. |
698 | | * @param varid Variable ID. |
699 | | * @param options_mask The options mask. Can be NC_SZIP_EC or |
700 | | * NC_SZIP_NN. |
701 | | * @param pixels_per_block Pixels per block. Must be even and not |
702 | | * greater than 32, with typical values being 8, 10, 16, or 32. This |
703 | | * parameter affects compression ratio; the more pixel values vary, |
704 | | * the smaller this number should be to achieve better performance. If |
705 | | * pixels_per_block is bigger than the total number of elements in a |
706 | | * dataset chunk, ::NC_EINVAL will be returned. |
707 | | * |
708 | | * @returns ::NC_NOERR No error. |
709 | | * @returns ::NC_EBADID Bad ncid. |
710 | | * @returns ::NC_ENOTVAR Invalid variable ID. |
711 | | * @returns ::NC_ENOTNC4 Attempting netcdf-4 operation on file that is |
712 | | * not netCDF-4/HDF5. |
713 | | * @returns ::NC_ELATEDEF Too late to change settings for this variable. |
714 | | * @returns ::NC_ENOTINDEFINE Not in define mode. |
715 | | * @returns ::NC_EINVAL Invalid input, or zlib filter already applied |
716 | | * to this var. |
717 | | * @author Ed Hartnett |
718 | | */ |
719 | | int |
720 | | nc_def_var_szip(int ncid, int varid, int options_mask, int pixels_per_block) |
721 | 0 | { |
722 | 0 | int ret; |
723 | | |
724 | | /* This will cause H5Pset_szip to be called when the var is |
725 | | * created. */ |
726 | 0 | unsigned int params[2]; |
727 | 0 | params[0] = options_mask; |
728 | 0 | params[1] = pixels_per_block; |
729 | 0 | if ((ret = nc_def_var_filter(ncid, varid, HDF5_FILTER_SZIP, 2, params))) |
730 | 0 | return ret; |
731 | | |
732 | 0 | return NC_NOERR; |
733 | 0 | } |
734 | | |
735 | | /** @} */ |
736 | | |
737 | | /** |
738 | | @name Rename a Variable |
739 | | |
740 | | Rename a variable. |
741 | | */ |
742 | | /** @{ */ |
743 | | |
744 | | /** |
745 | | Rename a variable. |
746 | | |
747 | | This function changes the name of a netCDF variable in an open netCDF |
748 | | file or group. You cannot rename a variable to have the name of any existing |
749 | | variable. |
750 | | |
751 | | For classic format, 64-bit offset format, and netCDF-4/HDF5 with |
752 | | classic mode, if the new name is longer than the old name, the netCDF |
753 | | dataset must be in define mode. |
754 | | |
755 | | For netCDF-4/HDF5 files, renaming the variable changes the order of |
756 | | the variables in the file. The renamed variable becomes the last |
757 | | variable in the file. |
758 | | |
759 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
760 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
761 | | nc_inq_ncid(). |
762 | | |
763 | | @param varid Variable ID |
764 | | |
765 | | @param name New name of the variable. |
766 | | |
767 | | @return ::NC_NOERR No error. |
768 | | @return ::NC_EBADID Bad ncid. |
769 | | @return ::NC_ENOTVAR Invalid variable ID. |
770 | | @return ::NC_EBADNAME Bad name. |
771 | | @return ::NC_EMAXNAME Name is too long. |
772 | | @return ::NC_ENAMEINUSE Name in use. |
773 | | @return ::NC_ENOMEM Out of memory. |
774 | | |
775 | | @section nc_rename_var_example Example |
776 | | |
777 | | Here is an example using nc_rename_var to rename the variable rh to |
778 | | rel_hum in an existing netCDF dataset named foo.nc: |
779 | | |
780 | | @code |
781 | | #include <netcdf.h> |
782 | | ... |
783 | | int status; |
784 | | int ncid; |
785 | | int rh_id; |
786 | | ... |
787 | | status = nc_open("foo.nc", NC_WRITE, &ncid); |
788 | | if (status != NC_NOERR) handle_error(status); |
789 | | ... |
790 | | status = nc_redef(ncid); |
791 | | if (status != NC_NOERR) handle_error(status); |
792 | | status = nc_inq_varid (ncid, "rh", &rh_id); |
793 | | if (status != NC_NOERR) handle_error(status); |
794 | | status = nc_rename_var (ncid, rh_id, "rel_hum"); |
795 | | if (status != NC_NOERR) handle_error(status); |
796 | | status = nc_enddef(ncid); |
797 | | if (status != NC_NOERR) handle_error(status); |
798 | | @endcode |
799 | | @author Glenn Davis, Ed Hartnett, Dennis Heimbigner |
800 | | */ |
801 | | int |
802 | | nc_rename_var(int ncid, int varid, const char *name) |
803 | 0 | { |
804 | 0 | NC* ncp; |
805 | 0 | int stat = NC_check_id(ncid, &ncp); |
806 | 0 | if(stat != NC_NOERR) return stat; |
807 | 0 | TRACE(nc_rename_var); |
808 | 0 | return ncp->dispatch->rename_var(ncid, varid, name); |
809 | 0 | } |
810 | | /** @} */ |
811 | | |
812 | | /** |
813 | | @internal Does a variable have a record dimension? |
814 | | |
815 | | @param ncid File ID. |
816 | | @param varid Variable ID. |
817 | | @param nrecs Pointer that gets number of records. |
818 | | |
819 | | @return 0 if not a record var, 1 if it is. |
820 | | */ |
821 | | int |
822 | | NC_is_recvar(int ncid, int varid, size_t* nrecs) |
823 | 0 | { |
824 | 0 | int status = NC_NOERR; |
825 | 0 | int unlimid; |
826 | 0 | int ndims; |
827 | 0 | int dimset[NC_MAX_VAR_DIMS]; |
828 | |
|
829 | 0 | status = nc_inq_unlimdim(ncid,&unlimid); |
830 | 0 | if(status != NC_NOERR) return 0; /* no unlimited defined */ |
831 | 0 | status = nc_inq_varndims(ncid,varid,&ndims); |
832 | 0 | if(status != NC_NOERR) return 0; /* no unlimited defined */ |
833 | 0 | if(ndims == 0) return 0; /* scalar */ |
834 | 0 | status = nc_inq_vardimid(ncid,varid,dimset); |
835 | 0 | if(status != NC_NOERR) return 0; /* no unlimited defined */ |
836 | 0 | status = nc_inq_dim(ncid,dimset[0],NULL,nrecs); |
837 | 0 | if(status != NC_NOERR) return 0; |
838 | 0 | return (dimset[0] == unlimid ? 1: 0); |
839 | 0 | } |
840 | | |
841 | | /** |
842 | | @internal Get the number of record dimensions for a variable and an |
843 | | array that identifies which of a variable's dimensions are record |
844 | | dimensions. Intended to be used instead of NC_is_recvar(), which |
845 | | doesn't work for netCDF-4 variables which have multiple unlimited |
846 | | dimensions or an unlimited dimension that is not the first of a |
847 | | variable's dimensions. |
848 | | |
849 | | @param ncid File ID. |
850 | | @param varid Variable ID. |
851 | | @param nrecdimsp Pointer that gets number of record dims. |
852 | | @param is_recdim Pointer that gets 1 if there is one or more record |
853 | | dimensions, 0 if not. |
854 | | |
855 | | @return 0 if not a record var, 1 if it is. |
856 | | |
857 | | Example use: |
858 | | @code |
859 | | int nrecdims; |
860 | | int is_recdim[NC_MAX_VAR_DIMS]; |
861 | | ... |
862 | | status = NC_inq_recvar(ncid,varid,&nrecdims,is_recdim); |
863 | | isrecvar = (nrecdims > 0); |
864 | | @endcode |
865 | | */ |
866 | | int |
867 | | NC_inq_recvar(int ncid, int varid, int* nrecdimsp, int *is_recdim) |
868 | 0 | { |
869 | 0 | int status = NC_NOERR; |
870 | 0 | int unlimid; |
871 | 0 | int nvardims; |
872 | 0 | int dimset[NC_MAX_VAR_DIMS]; |
873 | 0 | int dim; |
874 | 0 | int nrecdims = 0; |
875 | |
|
876 | 0 | status = nc_inq_varndims(ncid,varid,&nvardims); |
877 | 0 | if(status != NC_NOERR) return status; |
878 | 0 | if(nvardims == 0) return NC_NOERR; /* scalars have no dims */ |
879 | 0 | for(dim = 0; dim < nvardims; dim++) |
880 | 0 | is_recdim[dim] = 0; |
881 | 0 | status = nc_inq_unlimdim(ncid, &unlimid); |
882 | 0 | if(status != NC_NOERR) return status; |
883 | 0 | if(unlimid == -1) return status; /* no unlimited dims for any variables */ |
884 | 0 | #ifdef USE_NETCDF4 |
885 | 0 | { |
886 | 0 | int nunlimdims; |
887 | 0 | int *unlimids; |
888 | 0 | int recdim; |
889 | 0 | status = nc_inq_unlimdims(ncid, &nunlimdims, NULL); /* for group or file, not variable */ |
890 | 0 | if(status != NC_NOERR) return status; |
891 | 0 | if(nunlimdims == 0) return status; |
892 | | |
893 | 0 | if (!(unlimids = malloc(nunlimdims * sizeof(int)))) |
894 | 0 | return NC_ENOMEM; |
895 | 0 | status = nc_inq_unlimdims(ncid, &nunlimdims, unlimids); /* for group or file, not variable */ |
896 | 0 | if(status != NC_NOERR) { |
897 | 0 | free(unlimids); |
898 | 0 | return status; |
899 | 0 | } |
900 | 0 | status = nc_inq_vardimid(ncid, varid, dimset); |
901 | 0 | if(status != NC_NOERR) { |
902 | 0 | free(unlimids); |
903 | 0 | return status; |
904 | 0 | } |
905 | 0 | for (dim = 0; dim < nvardims; dim++) { /* netCDF-4 rec dims need not be first dim for a rec var */ |
906 | 0 | for(recdim = 0; recdim < nunlimdims; recdim++) { |
907 | 0 | if(dimset[dim] == unlimids[recdim]) { |
908 | 0 | is_recdim[dim] = 1; |
909 | 0 | nrecdims++; |
910 | 0 | } |
911 | 0 | } |
912 | 0 | } |
913 | 0 | free(unlimids); |
914 | 0 | } |
915 | | #else |
916 | | status = nc_inq_vardimid(ncid, varid, dimset); |
917 | | if(status != NC_NOERR) return status; |
918 | | if(dimset[0] == unlimid) { |
919 | | is_recdim[0] = 1; |
920 | | nrecdims++; |
921 | | } |
922 | | #endif /* USE_NETCDF4 */ |
923 | 0 | if(nrecdimsp) *nrecdimsp = nrecdims; |
924 | 0 | return status; |
925 | 0 | } |
926 | | |
927 | | /* Ok to use NC pointers because |
928 | | all IOSP's will use that structure, |
929 | | but not ok to use e.g. NC_Var pointers |
930 | | because they may be different structure |
931 | | entirely. |
932 | | */ |
933 | | |
934 | | /** |
935 | | @internal |
936 | | Find the length of a type. This is how much space is required by |
937 | | the in memory to hold one element of this type. |
938 | | |
939 | | @param type A netCDF atomic type. |
940 | | |
941 | | @return Length of the type in bytes, or -1 if type not found. |
942 | | @author Ed Hartnett |
943 | | */ |
944 | | int |
945 | | nctypelen(nc_type type) |
946 | 3.24M | { |
947 | 3.24M | switch(type){ |
948 | 1.81M | case NC_CHAR : |
949 | 1.81M | return ((int)sizeof(char)); |
950 | 1.36M | case NC_BYTE : |
951 | 1.36M | return ((int)sizeof(signed char)); |
952 | 0 | case NC_SHORT : |
953 | 0 | return ((int)sizeof(short)); |
954 | 37.9k | case NC_INT : |
955 | 37.9k | return ((int)sizeof(int)); |
956 | 10.4k | case NC_FLOAT : |
957 | 10.4k | return ((int)sizeof(float)); |
958 | 17.7k | case NC_DOUBLE : |
959 | 17.7k | return ((int)sizeof(double)); |
960 | | |
961 | | /* These can occur in netcdf-3 code */ |
962 | 2.08k | case NC_UBYTE : |
963 | 2.08k | return ((int)sizeof(unsigned char)); |
964 | 0 | case NC_USHORT : |
965 | 0 | return ((int)(sizeof(unsigned short))); |
966 | 0 | case NC_UINT : |
967 | 0 | return ((int)sizeof(unsigned int)); |
968 | 0 | case NC_INT64 : |
969 | 0 | return ((int)sizeof(signed long long)); |
970 | 0 | case NC_UINT64 : |
971 | 0 | return ((int)sizeof(unsigned long long)); |
972 | 0 | #ifdef USE_NETCDF4 |
973 | 0 | case NC_STRING : |
974 | 0 | return ((int)sizeof(char*)); |
975 | 0 | #endif /*USE_NETCDF4*/ |
976 | | |
977 | 0 | default: |
978 | 0 | return -1; |
979 | 3.24M | } |
980 | 3.24M | } |
981 | | |
982 | | /** |
983 | | @internal |
984 | | Find the length of a type. Redundant over nctypelen() above. |
985 | | |
986 | | @param xtype an nc_type. |
987 | | |
988 | | @author Dennis Heimbigner |
989 | | */ |
990 | | size_t |
991 | | NC_atomictypelen(nc_type xtype) |
992 | 0 | { |
993 | 0 | size_t sz = 0; |
994 | 0 | switch(xtype) { |
995 | 0 | case NC_NAT: sz = 0; break; |
996 | 0 | case NC_BYTE: sz = sizeof(signed char); break; |
997 | 0 | case NC_CHAR: sz = sizeof(char); break; |
998 | 0 | case NC_SHORT: sz = sizeof(short); break; |
999 | 0 | case NC_INT: sz = sizeof(int); break; |
1000 | 0 | case NC_FLOAT: sz = sizeof(float); break; |
1001 | 0 | case NC_DOUBLE: sz = sizeof(double); break; |
1002 | 0 | case NC_INT64: sz = sizeof(signed long long); break; |
1003 | 0 | case NC_UBYTE: sz = sizeof(unsigned char); break; |
1004 | 0 | case NC_USHORT: sz = sizeof(unsigned short); break; |
1005 | 0 | case NC_UINT: sz = sizeof(unsigned int); break; |
1006 | 0 | case NC_UINT64: sz = sizeof(unsigned long long); break; |
1007 | 0 | #ifdef USE_NETCDF4 |
1008 | 0 | case NC_STRING: sz = sizeof(char*); break; |
1009 | 0 | #endif |
1010 | 0 | default: break; |
1011 | 0 | } |
1012 | 0 | return sz; |
1013 | 0 | } |
1014 | | |
1015 | | /** |
1016 | | @internal |
1017 | | Get the type name. |
1018 | | |
1019 | | @param xtype an nc_type. |
1020 | | |
1021 | | @author Dennis Heimbigner |
1022 | | */ |
1023 | | char * |
1024 | | NC_atomictypename(nc_type xtype) |
1025 | 0 | { |
1026 | 0 | char* nm = NULL; |
1027 | 0 | switch(xtype) { |
1028 | 0 | case NC_NAT: nm = "undefined"; break; |
1029 | 0 | case NC_BYTE: nm = "byte"; break; |
1030 | 0 | case NC_CHAR: nm = "char"; break; |
1031 | 0 | case NC_SHORT: nm = "short"; break; |
1032 | 0 | case NC_INT: nm = "int"; break; |
1033 | 0 | case NC_FLOAT: nm = "float"; break; |
1034 | 0 | case NC_DOUBLE: nm = "double"; break; |
1035 | 0 | case NC_INT64: nm = "int64"; break; |
1036 | 0 | case NC_UBYTE: nm = "ubyte"; break; |
1037 | 0 | case NC_USHORT: nm = "ushort"; break; |
1038 | 0 | case NC_UINT: nm = "uint"; break; |
1039 | 0 | case NC_UINT64: nm = "uint64"; break; |
1040 | 0 | #ifdef USE_NETCDF4 |
1041 | 0 | case NC_STRING: nm = "string"; break; |
1042 | 0 | #endif |
1043 | 0 | default: break; |
1044 | 0 | } |
1045 | 0 | return nm; |
1046 | 0 | } |
1047 | | |
1048 | | /** |
1049 | | @internal |
1050 | | Get the shape of a variable. |
1051 | | |
1052 | | @param ncid NetCDF ID, from a previous call to nc_open() or |
1053 | | nc_create(). |
1054 | | @param varid Variable ID. |
1055 | | @param ndims Number of dimensions for this var. |
1056 | | @param shape Pointer to pre-allocated array that gets the size of |
1057 | | each dimension. |
1058 | | |
1059 | | @return ::NC_NOERR No error. |
1060 | | @return ::NC_EBADID Bad ncid. |
1061 | | @return ::NC_ENOTVAR Bad varid. |
1062 | | |
1063 | | @author Dennis Heimbigner |
1064 | | */ |
1065 | | int |
1066 | | NC_getshape(int ncid, int varid, int ndims, size_t* shape) |
1067 | 0 | { |
1068 | 0 | int dimids[NC_MAX_VAR_DIMS]; |
1069 | 0 | int i; |
1070 | 0 | int status = NC_NOERR; |
1071 | |
|
1072 | 0 | if ((status = nc_inq_vardimid(ncid, varid, dimids))) |
1073 | 0 | return status; |
1074 | 0 | for(i = 0; i < ndims; i++) |
1075 | 0 | if ((status = nc_inq_dimlen(ncid, dimids[i], &shape[i]))) |
1076 | 0 | break; |
1077 | |
|
1078 | 0 | return status; |
1079 | 0 | } |
1080 | | |
1081 | | /** |
1082 | | @internal Check the start, count, and stride parameters for gets |
1083 | | and puts, and handle NULLs. |
1084 | | |
1085 | | @param ncid The file ID. |
1086 | | @param varid The variable ID. |
1087 | | @param start Pointer to start array. If NULL ::NC_EINVALCOORDS will |
1088 | | be returned for non-scalar variable. |
1089 | | @param count Pointer to pointer to count array. If *count is NULL, |
1090 | | an array of the correct size will be allocated, and filled with |
1091 | | counts that represent the full extent of the variable. In this |
1092 | | case, the memory must be freed by the caller. |
1093 | | @param stride Pointer to pointer to stride array. If NULL, stide is |
1094 | | ignored. If *stride is NULL an array of the correct size will be |
1095 | | allocated, and filled with ones. In this case, the memory must be |
1096 | | freed by the caller. |
1097 | | |
1098 | | @return ::NC_NOERR No error. |
1099 | | @return ::NC_EBADID Bad ncid. |
1100 | | @return ::NC_ENOTVAR Variable not found. |
1101 | | @return ::NC_ENOMEM Out of memory. |
1102 | | @return ::NC_EINVALCOORDS Missing start array. |
1103 | | @author Ed Hartnett |
1104 | | */ |
1105 | | int |
1106 | | NC_check_nulls(int ncid, int varid, const size_t *start, size_t **count, |
1107 | | ptrdiff_t **stride) |
1108 | 0 | { |
1109 | 0 | int varndims; |
1110 | 0 | int stat; |
1111 | |
|
1112 | 0 | if ((stat = nc_inq_varndims(ncid, varid, &varndims))) |
1113 | 0 | return stat; |
1114 | | |
1115 | | /* For non-scalar vars, start is required. */ |
1116 | 0 | if (!start && varndims) |
1117 | 0 | return NC_EINVALCOORDS; |
1118 | | |
1119 | | /* If count is NULL, assume full extent of var. */ |
1120 | 0 | if (!*count) |
1121 | 0 | { |
1122 | 0 | if (!(*count = malloc(varndims * sizeof(size_t)))) |
1123 | 0 | return NC_ENOMEM; |
1124 | 0 | if ((stat = NC_getshape(ncid, varid, varndims, *count))) |
1125 | 0 | { |
1126 | 0 | free(*count); |
1127 | 0 | *count = NULL; |
1128 | 0 | return stat; |
1129 | 0 | } |
1130 | 0 | } |
1131 | | |
1132 | | /* If stride is NULL, do nothing, if *stride is NULL use all |
1133 | | * 1s. */ |
1134 | 0 | if (stride && !*stride) |
1135 | 0 | { |
1136 | 0 | int i; |
1137 | |
|
1138 | 0 | if (!(*stride = malloc(varndims * sizeof(ptrdiff_t)))) |
1139 | 0 | return NC_ENOMEM; |
1140 | 0 | for (i = 0; i < varndims; i++) |
1141 | 0 | (*stride)[i] = 1; |
1142 | 0 | } |
1143 | | |
1144 | 0 | return NC_NOERR; |
1145 | 0 | } |
1146 | | |
1147 | | /** |
1148 | | @name Free String Resources |
1149 | | |
1150 | | Use this functions to free resources associated with ::NC_STRING |
1151 | | data. |
1152 | | */ |
1153 | | /*! @{ */ |
1154 | | /** |
1155 | | Free string space allocated by the library. |
1156 | | |
1157 | | When you read string type the library will allocate the storage |
1158 | | space for the data. This storage space must be freed, so pass the |
1159 | | pointer back to this function, when you're done with the data, and |
1160 | | it will free the string memory. |
1161 | | |
1162 | | @param len The number of character arrays in the array. |
1163 | | @param data The pointer to the data array. |
1164 | | |
1165 | | @return ::NC_NOERR No error. |
1166 | | @author Ed Hartnett |
1167 | | */ |
1168 | | int |
1169 | | nc_free_string(size_t len, char **data) |
1170 | 0 | { |
1171 | 0 | int i; |
1172 | 0 | for (i = 0; i < len; i++) |
1173 | 0 | free(data[i]); |
1174 | 0 | return NC_NOERR; |
1175 | 0 | } |
1176 | | /** @} */ |
1177 | | |
1178 | | /** |
1179 | | @name Variables Chunk Caches |
1180 | | |
1181 | | Use these functions to change the variable chunk cache settings. |
1182 | | */ |
1183 | | /*! @{ */ |
1184 | | /** |
1185 | | Change the cache settings for a chunked variable. This function allows |
1186 | | users to control the amount of memory used in the per-variable chunk |
1187 | | cache at the HDF5 level. Changing the chunk cache only has effect |
1188 | | until the file is closed. Once re-opened, the variable chunk cache |
1189 | | returns to its default value. |
1190 | | |
1191 | | Current cache settings for each var may be obtained with |
1192 | | nc_get_var_chunk_cache(). |
1193 | | |
1194 | | Default values for these settings may be changed for the whole file |
1195 | | with nc_set_chunk_cache(). |
1196 | | |
1197 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
1198 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
1199 | | nc_inq_ncid(). |
1200 | | @param varid Variable ID |
1201 | | @param size The total size of the raw data chunk cache, in bytes. |
1202 | | @param nelems The number of chunk slots in the raw data chunk cache. |
1203 | | @param preemption The preemption, a value between 0 and 1 inclusive |
1204 | | that indicates how much chunks that have been fully read are favored |
1205 | | for preemption. A value of zero means fully read chunks are treated no |
1206 | | differently than other chunks (the preemption is strictly LRU) while a |
1207 | | value of one means fully read chunks are always preempted before other |
1208 | | chunks. |
1209 | | |
1210 | | @return ::NC_NOERR No error. |
1211 | | @return ::NC_EBADID Bad ncid. |
1212 | | @return ::NC_ENOTVAR Invalid variable ID. |
1213 | | @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 |
1214 | | netcdf-4 file. |
1215 | | @return ::NC_EINVAL Invalid input |
1216 | | |
1217 | | @section nc_def_var_chunk_cache_example Example |
1218 | | |
1219 | | In this example from nc_test4/tst_coords.c, a variable is defined, and |
1220 | | the chunk cache settings are changed for that variable. |
1221 | | |
1222 | | @code |
1223 | | printf("**** testing setting cache values for coordinate variables..."); |
1224 | | { |
1225 | | #define RANK_1 1 |
1226 | | #define DIM0_NAME "d0" |
1227 | | #define CACHE_SIZE 1000000 |
1228 | | #define CACHE_NELEMS 1009 |
1229 | | #define CACHE_PREEMPTION .90 |
1230 | | |
1231 | | int ncid, dimid, varid; |
1232 | | char name_in[NC_MAX_NAME + 1]; |
1233 | | |
1234 | | if (nc_create(FILE_NAME, NC_CLASSIC_MODEL|NC_NETCDF4, &ncid)) ERR; |
1235 | | if (nc_def_dim(ncid, DIM0_NAME, NC_UNLIMITED, &dimid)) ERR; |
1236 | | if (nc_def_var(ncid, DIM0_NAME, NC_DOUBLE, 1, &dimid, &varid)) ERR; |
1237 | | if (nc_set_var_chunk_cache(ncid, varid, CACHE_SIZE, CACHE_NELEMS, CACHE_PREEMPTION)) ERR; |
1238 | | if (nc_close(ncid)) ERR; |
1239 | | |
1240 | | ... |
1241 | | } |
1242 | | SUMMARIZE_ERR; |
1243 | | @endcode |
1244 | | @author Ed Hartnett |
1245 | | */ |
1246 | | int |
1247 | | nc_set_var_chunk_cache(int ncid, int varid, size_t size, size_t nelems, |
1248 | | float preemption) |
1249 | 64.5k | { |
1250 | 64.5k | NC* ncp; |
1251 | 64.5k | int stat = NC_check_id(ncid, &ncp); |
1252 | 64.5k | if(stat != NC_NOERR) return stat; |
1253 | 64.5k | return ncp->dispatch->set_var_chunk_cache(ncid, varid, size, |
1254 | 64.5k | nelems, preemption); |
1255 | 64.5k | } |
1256 | | |
1257 | | /** |
1258 | | Get the per-variable chunk cache settings from the HDF5 |
1259 | | layer. These settings may be changed with nc_set_var_chunk_cache(). |
1260 | | |
1261 | | See nc_set_chunk_cache() for a full discussion of these settings. |
1262 | | |
1263 | | @param ncid NetCDF or group ID, from a previous call to nc_open(), |
1264 | | nc_create(), nc_def_grp(), or associated inquiry functions such as |
1265 | | nc_inq_ncid(). |
1266 | | @param varid Variable ID |
1267 | | @param sizep The total size of the raw data chunk cache, in bytes, |
1268 | | will be put here. @ref ignored_if_null. |
1269 | | @param nelemsp The number of chunk slots in the raw data chunk |
1270 | | cache hash table will be put here. @ref ignored_if_null. |
1271 | | @param preemptionp The preemption will be put here. The preemtion |
1272 | | value is between 0 and 1 inclusive and indicates how much chunks |
1273 | | that have been fully read are favored for preemption. A value of |
1274 | | zero means fully read chunks are treated no differently than other |
1275 | | chunks (the preemption is strictly LRU) while a value of one means |
1276 | | fully read chunks are always preempted before other chunks. @ref |
1277 | | ignored_if_null. |
1278 | | |
1279 | | @return ::NC_NOERR No error. |
1280 | | @return ::NC_EBADID Bad ncid. |
1281 | | @return ::NC_ENOTVAR Invalid variable ID. |
1282 | | @return ::NC_ESTRICTNC3 Attempting netcdf-4 operation on strict nc3 |
1283 | | netcdf-4 file. |
1284 | | @return ::NC_EINVAL Invalid input |
1285 | | @author Ed Hartnett |
1286 | | */ |
1287 | | int |
1288 | | nc_get_var_chunk_cache(int ncid, int varid, size_t *sizep, size_t *nelemsp, |
1289 | | float *preemptionp) |
1290 | 64.5k | { |
1291 | 64.5k | NC* ncp; |
1292 | 64.5k | int stat = NC_check_id(ncid, &ncp); |
1293 | 64.5k | if(stat != NC_NOERR) return stat; |
1294 | 64.5k | return ncp->dispatch->get_var_chunk_cache(ncid, varid, sizep, |
1295 | 64.5k | nelemsp, preemptionp); |
1296 | 64.5k | } |
1297 | | /** @} */ |
1298 | | /** @} */ |