source: XIOS3/branches/xios-3.0-beta/src/io/netCdfInterface.cpp @ 2530

Last change on this file since 2530 was 2530, checked in by jderouillat, 10 months ago

Enable parallel compression regarding NetCDF & HDF5 configurations at compile time. Implement an API to use HDF5 lossy compression plugins (SZ is available for now).

  • Property copyright set to
    Software name : XIOS (Xml I/O Server)
    http://forge.ipsl.jussieu.fr/ioserver
    Creation date : January 2009
    Licence : CeCCIL version2
    see license file in root directory : Licence_CeCILL_V2-en.txt
    or http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
    Holder : CEA/LSCE (Laboratoire des Sciences du CLimat et de l'Environnement)
    CNRS/IPSL (Institut Pierre Simon Laplace)
    Project Manager : Yann Meurdesoif
    yann.meurdesoif@cea.fr
File size: 36.7 KB
Line 
1/*!
2   \file netCdfInterface.cpp
3   \author Ha NGUYEN
4   \date 08 Oct 2014
5   \since 03 Oct 2014
6
7   \brief Wrapper of netcdf functions.
8 */
9
10#include "netCdfInterface.hpp"
11#include "netCdfException.hpp"
12#include "mem_checker.hpp"
13#include <string>
14#include <sys/stat.h>
15
16namespace xios
17{
18/*!
19This function creates a new netcdf file and return its id
20\param [in] fileName Name of the file
21\param [in] cMode create mode
22\param [in/out] ncId id of the created file
23\return Status code
24*/
25int CNetCdfInterface::create(const StdString& fileName, int cMode, int& ncId)
26{
27  CMemChecker::get("NetCDF create").resume();
28  int status = nc_create(fileName.c_str(), cMode, &ncId);
29  if (NC_NOERR != status)
30  {
31    StdString errormsg(nc_strerror(status));
32    StdStringStream sstr;
33    sstr << "Error when calling function: nc_create(fileName.c_str(), cMode, &ncId) " << std::endl
34         << errormsg << std::endl
35         << "Unable to create file, given its name: " << fileName
36         << " and its creation mode " << creationMode2String(cMode) << std::endl;
37    StdString e = sstr.str();
38    throw CNetCdfException(e);
39  }
40  CMemChecker::get("NetCDF create").suspend();
41
42  return status;
43}
44
45/*!
46This function creates a new netcdf file on parallel file system
47\param [in] fileName Name of the file
48\param [in] cMode create mode
49\param [in] comm MPI communicator
50\param [in] info MPI information
51\param [in/out] ncId id of the created file
52\return Status code
53*/
54int CNetCdfInterface::createPar(const StdString& fileName, int cMode, MPI_Comm comm, MPI_Info info, int& ncId)
55{
56  CMemChecker::get("NetCDF create").resume();
57  int status = xios::nc_create_par(fileName.c_str(), cMode, comm, info, &ncId);
58  if (NC_NOERR != status)
59  {
60    StdString errormsg(nc_strerror(status));
61    StdStringStream sstr;
62    sstr << "Error when calling function: nc_create_par(fileName.c_str(), cMode, comm, info, &ncId) " << std::endl
63         << errormsg << std::endl
64         << "Unable to create file on parallel file system, given its name: " << std::endl
65         << "and its creation mode " << creationMode2String(cMode) << std::endl;
66    StdString e = sstr.str();
67    throw CNetCdfException(e);
68  }
69  CMemChecker::get("NetCDF create").suspend();
70
71  return status;
72}
73
74/*!
75This function opens a netcdf file, given its name and open mode, return its id
76\param [in] fileName Name of the file
77\param [in] oMode open mode
78\param [in/out] ncId id of the opening file
79\return Status code
80*/
81int CNetCdfInterface::open(const StdString& fileName, int oMode, int& ncId)
82{
83  CMemChecker::get("NetCDF open").resume();
84  int status = nc_open(fileName.c_str(), oMode, &ncId);
85  if (NC_NOERR != status)
86  {
87    StdString errormsg(nc_strerror(status));
88    StdStringStream sstr;
89    sstr << "Error when calling function: nc_open(fileName.c_str(), oMode, &ncId) "<< std::endl
90         << errormsg << std::endl
91         << "Unable to open file, given its name: " << fileName
92         << "and its open mode " << openMode2String(oMode) << std::endl;
93    StdString e = sstr.str();
94    throw CNetCdfException(e);
95  }
96  CMemChecker::get("NetCDF open").suspend();
97
98  return status;
99}
100
101
102/*!
103This function opens a new netcdf file on parallel file system
104\param [in] fileName Name of the file
105\param [in] oMode open mode
106\param [in] comm MPI communicator
107\param [in] info MPI information
108\param [in/out] ncId id of the opened file
109\return Status code
110*/
111int CNetCdfInterface::openPar(const StdString& fileName, int oMode, MPI_Comm comm, MPI_Info info, int& ncId)
112{
113  CMemChecker::get("NetCDF open").resume();
114  int status = xios::nc_open_par(fileName.c_str(), oMode, comm, info, &ncId);
115  if (NC_NOERR != status)
116  {
117    StdString errormsg(nc_strerror(status));
118    StdStringStream sstr;
119    sstr << "Error when calling function nc_open_par(fileName.c_str(), oMode, comm, info, &ncId) " << std::endl
120         << errormsg << std::endl
121         << "Unable to open file on parallel file system, given its name: " << fileName
122         << "and its open mode " << openMode2String(oMode) << std::endl;
123    StdString e = sstr.str();
124    throw CNetCdfException(e);
125  }
126  CMemChecker::get("NetCDF open").suspend();
127
128  return status;
129}
130
131/*!
132This function closes a netcdf file, given its id
133\param [in] ncId id of the opening netcdf file
134\return Status code
135*/
136int CNetCdfInterface::close(int ncId)
137{
138  CMemChecker::get("NetCDF close").resume();
139  int status = nc_close(ncId);
140  if (NC_NOERR != status)
141  {
142    StdString errormsg(nc_strerror(status));
143    StdStringStream sstr;
144    sstr << "Error when calling function nc_close(ncId)" << std::endl
145         << errormsg << std::endl
146         << "Unable to close file, given its id: " << ncId << std::endl;
147    StdString e = sstr.str();
148    throw CNetCdfException(e);
149  }
150  CMemChecker::get("NetCDF close").suspend();
151
152  return status;
153}
154
155/*!
156This function put a netcdf file into define mode, given its id
157\param [in] ncId id of the opening netcdf file to be put into define mode
158\return Status code
159*/
160int CNetCdfInterface::reDef(int ncId)
161{
162  CMemChecker::get("NetCDF other").resume();
163  int status = nc_redef(ncId);
164  if (NC_NOERR != status)
165  {
166    StdString errormsg(nc_strerror(status));
167    StdStringStream sstr;
168    sstr << "Error when calling function nc_redef(ncId)" << std::endl
169      << errormsg << std::endl
170      << "Unable to put this file into define mode given its id: " << ncId << std::endl;
171    StdString e = sstr.str();
172    throw CNetCdfException(e);
173  }
174  CMemChecker::get("NetCDF other").suspend();
175
176  return status;
177}
178
179/*!
180This function ends a netcdf file define mode, given its id
181\param [in] ncId id of the opening netcdf file to be put into define mode
182\return Status code
183*/
184int CNetCdfInterface::endDef(int ncId)
185{
186  CMemChecker::get("NetCDF other").resume();
187  int status = nc_enddef(ncId);
188  if (NC_NOERR != status)
189  {
190    StdString errormsg(nc_strerror(status));
191    StdStringStream sstr;
192
193    sstr << "Error when calling function nc_enddef(ncId)" << std::endl
194         << errormsg << std::endl
195         << "Unable to end define mode of this file, given its id: " << ncId << std::endl;
196    StdString e = sstr.str();
197    throw CNetCdfException(e);
198  }
199  CMemChecker::get("NetCDF other").suspend();
200
201  return status;
202}
203
204/*!
205This function makes a request to netcdf with ncid and group name then return ncid of the named group
206\param [in] ncid Groupd id (or File Id)
207\param [in] grpName Name of the desired group (or file)
208\param [in/out] grpId Group id if the group is found
209\return Status code
210*/
211int CNetCdfInterface::inqNcId(int ncid, const StdString& grpName, int& grpId)
212{
213  int status = nc_inq_ncid(ncid, grpName.c_str(), &grpId);
214  if (NC_NOERR != status)
215  {
216    StdString errormsg(nc_strerror(status));
217    StdStringStream sstr;
218
219    sstr << "Error when calling function nc_inq_ncid(ncid, grpName.c_str(), &grpId)" << std::endl
220         << errormsg << std::endl
221         << "Unable to get id of a group (File), given its name: " << grpName << std::endl;
222    StdString e = sstr.str();
223    throw CNetCdfException(e);
224  }
225
226  return status;
227}
228
229
230/*!
231This function makes a request to netcdf with ncid and variable name then return ncid of the named variable
232\param [in] ncid Groupd id (or File Id)
233\param [in] varName Name of the desired variable
234\param [in/out] varId Variable id if this variable is found
235\return Status code
236*/
237int CNetCdfInterface::inqVarId(int ncid, const StdString& varName, int& varId)
238{
239  int status = nc_inq_varid(ncid, varName.c_str(), &varId);
240  if (NC_NOERR != status)
241  {
242    StdString errormsg(nc_strerror(status));
243    StdStringStream sstr;
244
245    sstr << "Error when calling function: nc_inq_varid(ncid, varName.c_str(), &varId)" << std::endl
246         << (errormsg) << std::endl
247         << "Unable to get id of variable with name: " << varName << std::endl;
248    StdString e = sstr.str();
249    throw CNetCdfException(e);
250  }
251
252  return status;
253}
254
255/*!
256This function makes a request to netcdf with a netCdf dimension name then return ncid of the named dimension
257\param [in] ncid Groupd id (or File Id)
258\param [in] dimName Name of the desired dimension
259\param [in/out] dimId Dimension id if this dimension is found
260\return Status code
261*/
262int CNetCdfInterface::inqDimId(int ncid, const StdString& dimName, int& dimId)
263{
264  int status = nc_inq_dimid(ncid, dimName.c_str(), &dimId);
265  if (NC_NOERR != status)
266  {
267    StdString errormsg(nc_strerror(status));
268    StdStringStream sstr;
269
270    sstr << "Error when calling function nc_inq_dimid(ncid, dimName.c_str(), &dimId)" << std::endl
271         << errormsg << std::endl
272         << "Unable to get id of dimension, given its name: " << dimName << std::endl;
273    StdString e = sstr.str();
274    throw CNetCdfException(e);
275  }
276
277  return status;
278}
279
280/*!
281This function queries the name of a variable given its id.
282\param [in] ncid Groupd id (or File Id)
283\param [in] varId Id of desired variable
284\param [out] varName name of desired variable
285\return Status code
286*/
287int CNetCdfInterface::inqVarName(int ncid, int varId, StdString& varName)
288{
289  char varNameBuff[NC_MAX_NAME + 1];
290  int status = nc_inq_varname(ncid, varId, varNameBuff);
291  if (NC_NOERR != status)
292  {
293    StdString errormsg(nc_strerror(status));
294    StdStringStream sstr;
295
296    sstr << "Error when calling function nc_inq_varname(ncid, varId, varNameBuff)" << std::endl
297         << errormsg << std::endl
298         << "Unable to get variable name: "<< varName << " given its id: " << varId << std::endl;
299    StdString e = sstr.str();
300    throw CNetCdfException(e);
301  }
302  varName = varNameBuff;
303  return status;
304}
305
306/*!
307This function makes a request to netcdf with a netCdf dimension name then return ncid of the named dimension
308\param [in] ncid Groupd id (or File Id)
309\param [in/out] dimId Dimension id if this dimension is found
310\return Status code
311*/
312int CNetCdfInterface::inqUnLimDim(int ncid, int& dimId)
313{
314  int status = nc_inq_unlimdim(ncid, &dimId);
315  if (NC_NOERR != status)
316  {
317    StdString errormsg(nc_strerror(status));
318    StdStringStream sstr;
319
320    sstr << "Error when calling function nc_inq_dimid" << std::endl
321      << errormsg << std::endl
322      << "Unable to get id of unlimited dimension " << std::endl;
323    StdString e = sstr.str();
324    throw CNetCdfException(e);
325 }
326
327  return status;
328}
329
330/*!
331This function makes a request to netcdf, returns name of a dimension, given its id
332\param [in] ncid Groupd id (or File Id)
333\param [in] dimId Id of desired dimension
334\param [out] dimName Name of desired dimension
335\return Status code
336*/
337int CNetCdfInterface::inqDimName(int ncid, int dimId, StdString& dimName)
338{
339  char fullNameIn[NC_MAX_NAME + 1];
340  int status = nc_inq_dimname(ncid, dimId, fullNameIn);
341  if (NC_NOERR != status)
342  {
343    StdString errormsg(nc_strerror(status));
344    StdStringStream sstr;
345
346    sstr << "Error when calling function nc_inq_dimname(ncid, dimId, fullNameIn)" << std::endl
347         << errormsg << std::endl
348         << "Unable to get dimension name: " << dimName << " given its id: " << dimId << std::endl;
349    StdString e = sstr.str();
350    throw CNetCdfException(e);
351  }
352  dimName = StdString(fullNameIn);
353  return status;
354}
355
356/*!
357This function makes a request to netcdf, returns length of a dimension, given its id
358\param [in] ncid Groupd id (or File Id)
359\param [in] dimId Id of desired dimension
360\param [in/out] dimLen Length of desired dimension
361\return Status code
362*/
363int CNetCdfInterface::inqDimLen(int ncid, int dimId, StdSize& dimLen)
364{
365  int status = nc_inq_dimlen(ncid, dimId, &dimLen);
366  if (NC_NOERR != status)
367  {
368    StdString errormsg(nc_strerror(status));
369    StdStringStream sstr;
370
371    sstr << "Error when calling function nc_inq_dimlen(ncid, dimId, &dimLen)" << std::endl
372         << errormsg << std::endl
373         << "Unable to get dimension length given its id: " << dimId << std::endl;
374    StdString e = sstr.str();
375    throw CNetCdfException(e);
376  }
377
378  return status;
379}
380
381/*!
382This function makes a request to netcdf, returns number of dimensions of a variable, given its id
383\param [in] ncid Groupd id (or File Id)
384\param [in] varId Id of variable
385\param [in/out] ndims number of dimension of the variable
386\return Status code
387*/
388int CNetCdfInterface::inqVarNDims(int ncid, int varId, int& nDims)
389{
390  int status = nc_inq_varndims(ncid, varId, &nDims);
391  if (NC_NOERR != status)
392  {
393    StdString errormsg(nc_strerror(status));
394    StdStringStream sstr;
395
396    sstr << "Error when calling function nc_inq_varndims(ncid, varId, &nDims)" << std::endl
397         << errormsg << std::endl
398         << "Unable to get the number of dimension of variable with Id: " << varId << std::endl;
399    StdString e = sstr.str();
400    throw CNetCdfException(e);
401  }
402
403  return status;
404}
405
406/*!
407This function makes a request to netcdf, returns a list of dimension ID describing the shape of the variable, given its id
408\param [in] ncid Groupd id (or File Id)
409\param [in] varId Id of variable
410\param [in/out] dimIds list of dimension of the variable
411\return Status code
412*/
413int CNetCdfInterface::inqVarDimId(int ncid, int varId, int* dimIds)
414{
415  int status = nc_inq_vardimid(ncid, varId, dimIds);
416  if (NC_NOERR != status)
417  {
418    StdString errormsg(nc_strerror(status));
419    StdStringStream sstr;
420
421    sstr << "Error when calling function nc_inq_vardimid(ncid, varId, dimIds)" << std::endl
422         << errormsg << std::endl
423         << "Unable to get list of dimension id of the variable with id " << varId << std::endl;
424    StdString e = sstr.str();
425    throw CNetCdfException(e);
426  }
427
428  return status;
429}
430
431/*!
432This function makes a request to netcdf, to find all dimension in a group
433\param [in] ncid Groupd id (or File Id)
434\param [in/out] nDims number of list of dimension
435\param [in/out] dimIds list of dimension in a group or any of its parent
436\param [in] includeParents number of parents
437\return Status code
438*/
439int CNetCdfInterface::inqDimIds(int ncid, int& nDims, int* dimIds, int includeParents)
440{
441  int status = nc_inq_dimids(ncid, &nDims, dimIds, includeParents);
442  if (NC_NOERR != status)
443  {
444    StdString errormsg(nc_strerror(status));
445    StdStringStream sstr;
446
447    sstr << "Error when calling function nc_inq_dimids(ncid, &nDims, dimIds, includeParents)" << std::endl;
448    sstr << errormsg << std::endl;
449    sstr << "Unable to retrieve number of dimension in the group with id: " << ncid << std::endl;
450    sstr << "With number of Parents " << includeParents << std::endl;
451    StdString e = sstr.str();
452    throw CNetCdfException(e);
453  }
454
455  return status;
456}
457
458/*!
459This function queries the full name of a group given its id.
460\param [in] ncid Groupd id (or File Id)
461\param [in/out] grpFullName the full name of the group
462\return Status code
463*/
464int CNetCdfInterface::inqGrpFullName(int ncid, StdString& grpFullName)
465{
466  StdSize strlen = 0;
467  std::vector<char> buff;
468  int status = nc_inq_grpname_full(ncid, &strlen, NULL);
469  if (NC_NOERR == status)
470  {
471    buff.resize(strlen + 1);
472    status = nc_inq_grpname_full(ncid, NULL, &buff[0]);
473  }
474
475  if (NC_NOERR != status)
476  {
477    StdString errormsg(nc_strerror(status));
478    StdStringStream sstr;
479
480    sstr << "Error when calling function nc_inq_grpname_full(ncid, &strlen, &buff[0])" << std::endl
481         << errormsg << std::endl
482         << "Unable to get the full group name given its id: " << ncid << std::endl;
483    StdString e = sstr.str();
484    throw CNetCdfException(e);
485  }
486
487  grpFullName.assign(buff.begin(), buff.end());
488
489  return status;
490}
491
492/*!
493This function queries the list of group ids given a location id.
494\param [in] ncid Groupd id (or File Id)
495\param [in/out] numgrps number of groups
496\param [in/out] ncids list of group ids
497\return Status code
498*/
499int CNetCdfInterface::inqGrpIds(int ncid, int& numgrps, int* ncids)
500{
501  int status = nc_inq_grps(ncid, &numgrps, ncids);
502  if (NC_NOERR != status)
503  {
504    StdString errormsg(nc_strerror(status));
505    StdStringStream sstr;
506
507    sstr << "Error when calling function nc_inq_grps(ncid, &numgrps, ncids)" << std::endl;
508    sstr << errormsg << std::endl;
509    sstr << "Unable to retrieve the list of groups for location id: " << ncid << std::endl;
510    StdString e = sstr.str();
511    throw CNetCdfException(e);
512  }
513
514  return status;
515}
516
517/*!
518This function queries the list of variable ids given a location id.
519\param [in] ncid Groupd id (or File Id)
520\param [in/out] nvars number of variables
521\param [in/out] varids list of variable ids
522\return Status code
523*/
524int CNetCdfInterface::inqVarIds(int ncid, int& nvars, int* varids)
525{
526  int status = nc_inq_varids(ncid, &nvars, varids);
527  if (NC_NOERR != status)
528  {
529    StdString errormsg(nc_strerror(status));
530    StdStringStream sstr;
531
532    sstr << "Error when calling function nc_inq_varids(ncid, &nvars, varids)" << std::endl;
533    sstr << errormsg << std::endl;
534    sstr << "Unable to retrieve the list of variables for location id: " << ncid << std::endl;
535    StdString e = sstr.str();
536    throw CNetCdfException(e);
537  }
538
539  return status;
540}
541
542/*!
543This function queries the type and the size of an attribute given its name and the id of the variable to which it is attached.
544\param [in] ncid Groupd id (or File Id)
545\param [in] varid the id of the variable to which the attribute is attached
546\param [in] name the name of the attribute
547\param [out] type the type of the attribute
548\param [out] len the size of the attribute
549\return Status code
550*/
551int CNetCdfInterface::inqAtt(int ncid, int varid, const StdString& name, nc_type& type, size_t& len)
552{
553  int status = nc_inq_att(ncid, varid, name.c_str(), &type, &len);
554  if (NC_NOERR != status)
555  {
556    StdString errormsg(nc_strerror(status));
557    StdStringStream sstr;
558
559    sstr << "Error when calling function nc_inq_att(ncid, varid, name.c_str(), &type, &len)" << std::endl;
560    sstr << errormsg << std::endl;
561    sstr << "Unable to query the attribute information given its name: " << name << " and its variable id:" << varid << std::endl;
562    StdString e = sstr.str();
563    throw CNetCdfException(e);
564  }
565
566  return status;
567}
568
569/*!
570This function queries the number of global attributes given a location id.
571\param [in] ncid Groupd id (or File Id)
572\param [out] ngatts the number of global attributes
573\return Status code
574*/
575int CNetCdfInterface::inqNAtts(int ncid, int& ngatts)
576{
577  int status = nc_inq_natts(ncid, &ngatts);
578  if (NC_NOERR != status)
579  {
580    StdString errormsg(nc_strerror(status));
581    StdStringStream sstr;
582
583    sstr << "Error when calling function nc_inq_natts(ncid, &ngatts)" << std::endl;
584    sstr << errormsg << std::endl;
585    sstr << "Unable to query the number of global attributes given the location id:" << ncid << std::endl;
586    StdString e = sstr.str();
587    throw CNetCdfException(e);
588  }
589
590  return status;
591}
592
593/*!
594This function queries the number of global attributes given a location id and a variable id.
595\param [in] ncid Groupd id (or File Id)
596\param [in] varid the id of the variable
597\param [out] natts the number of global attributes
598\return Status code
599*/
600int CNetCdfInterface::inqVarNAtts(int ncid, int varid, int& natts)
601{
602  int status = nc_inq_varnatts(ncid, varid, &natts);
603  if (NC_NOERR != status)
604  {
605    StdString errormsg(nc_strerror(status));
606    StdStringStream sstr;
607
608    sstr << "Error when calling function nc_inq_varnatts(ncid, varid, &natts)" << std::endl;
609    sstr << errormsg << std::endl;
610    sstr << "Unable to query the number of attributes given the location id:" << ncid << " and the variable id:" << varid << std::endl;
611    StdString e = sstr.str();
612    throw CNetCdfException(e);
613  }
614
615  return status;
616}
617
618
619//! Query the name of an attribute given a location id, a variable id and the attribute number
620int CNetCdfInterface::inqAttName(int ncid, int varid, int attnum, StdString& name)
621{
622  std::vector<char> attName(NC_MAX_NAME + 1,' ');
623  int status = nc_inq_attname(ncid, varid, attnum, &attName[0]);
624  if (NC_NOERR != status)
625  {
626    StdString errormsg(nc_strerror(status));
627    StdStringStream sstr;
628
629    sstr << "Error when calling function nc_inq_attname(ncid, varid, attnum, attName)" << std::endl;
630    sstr << errormsg << std::endl;
631    sstr << "Unable to query the name: " << name << " of attribute " << attnum << " given the location id:" << ncid << " and the variable id:" << varid << std::endl;
632    StdString e = sstr.str();
633    throw CNetCdfException(e);
634  }
635
636  int nameSize = 0;
637  while ((nameSize < NC_MAX_NAME) && (' ' != attName[nameSize] )) ++nameSize;
638  name.resize(nameSize);
639//  for (int idx = 0; idx < nameSize; ++idx) name.at(idx) = attName[idx];
640  std::copy(&attName[0], &attName[nameSize-1], name.begin());
641
642  return status;
643}
644
645/*!
646This function makes a request to netcdf with a id of a prent groupd and then return id of the created group, given its name
647\param [in] parentNcid Id of parent groupd(or File Id)
648\param [in] grpName Name of the desired group
649\param [in/out] grpId Group id if this group is created sucessfully
650\return Status code
651*/
652int CNetCdfInterface::defGrp(int parentNcid, const StdString& grpName, int& grpId)
653{
654  int status = nc_def_grp(parentNcid, grpName.c_str(), &grpId);
655  if (NC_NOERR != status)
656  {
657    StdString errormsg(nc_strerror(status));
658    StdStringStream sstr;
659
660    sstr << "Error when calling function nc_def_grp(parentNcid, grpName.c_str(), &grpId)" << std::endl;
661    sstr << errormsg << std::endl;
662    sstr << "Unable to create group Id, given its name: " << grpName << std::endl;
663    StdString e = sstr.str();
664    throw CNetCdfException(e);
665  }
666
667  return status;
668}
669
670/*!
671This function makes a request to netcdf, add a new dimension to an open netcdf in define mode
672\param [in] ncid Id of groupd(or File Id)
673\param [in] dimName Name of the desired dimension
674\param [in/out] grpId Group id if this group is created sucessfully
675\return Status code
676*/
677int CNetCdfInterface::defDim(int ncid, const StdString& dimName, StdSize dimLen, int& dimId)
678{
679  int status = nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId);
680  if (NC_NOERR != status)
681  {
682    StdString errormsg(nc_strerror(status));
683    StdStringStream sstr;
684
685    sstr << "Error when calling function nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId)" << std::endl;
686    sstr << errormsg << std::endl;
687    sstr << "Unable to create dimension with name: " << dimName
688         << " and with length " << dimLen << std::endl;
689    StdString e = sstr.str();
690    throw CNetCdfException(e);
691  }
692
693  return status;
694}
695
696/*!
697This function makes a request to netcdf with its id, to add a new variable to an open netCdf in define mode,
698return a variable id, given its name, type, the number of dimensions and list of dimension id
699\param [in] ncid Id of groupd(or File Id)
700\param [in] varName Name of the desired dimension
701\param [in] xtypes One of the set of predefined netCDF data types
702\param [in] nDims Number of dimension for the variable
703\param [in] dimIds List of ndims dimension ids corresponding to the variable dimensions
704\param [in/out] varId Variable id if it is added sucessfully
705\return Status code
706*/
707int CNetCdfInterface::defVar(int ncid, const StdString& varName, nc_type xtype,
708                             int nDims, const int dimIds[], int& varId)
709{
710  int status = nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId);
711  if (NC_NOERR != status)
712  {
713    StdString errormsg(nc_strerror(status));
714    StdStringStream sstr;
715
716    sstr << "Error when calling function  nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId)" << std::endl;
717    sstr << errormsg << std::endl;
718    sstr << "Unable to add a new variable with name: " << varName
719         << " with type " << xtype
720         << " and number of dimension " << nDims << std::endl;
721    StdString e = sstr.str();
722    throw CNetCdfException(e);
723  }
724
725  return status;
726}
727
728/*!
729This function makes a request to netcdf with a ncid, to set the chunking size of a variable,
730given variable id and type of storage
731\param [in] ncid Id groupd(or File Id)
732\param [in] varId Id of the variable
733\param [in] storage Type of storage (It can be: NC_CONTIGUOUS, NC_CHUNKED)
734\param [in/out] chunkSize array list of chunk sizes
735\return Status code
736*/
737int CNetCdfInterface::defVarChunking(int ncid, int varId, int storage, StdSize chunkSize[])
738{
739  int status = nc_def_var_chunking(ncid, varId, storage, chunkSize);
740  if (NC_NOERR != status)
741  {
742    StdString errormsg(nc_strerror(status));
743    StdStringStream sstr;
744
745    sstr << "Error when calling function nc_def_var_chunking(ncid, varId, storage, chunkSize)" << std::endl;
746    sstr << errormsg << std::endl;
747    sstr << "Unable to set chunk size of the variable with id: " << varId
748      << " and storage type " << storage << std::endl;
749    StdString e = sstr.str();
750    throw CNetCdfException(e);
751  }
752
753  return status;
754}
755
756/*!
757This function sets the compression level to the specified variable
758\param [in] ncid Groud id (or file id)
759\param [in] varId Id of the variable
760\param [in] compressionLevel The compression level from 0 to 9 (0 disables the compression, 9 is the higher compression)
761\return Status code
762*/
763int CNetCdfInterface::defVarDeflate(int ncid, int varId, int compressionLevel)
764{
765 
766  if (compressionLevel == 0) return NC_NOERR ;
767  int status = nc_def_var_deflate(ncid, varId, (compressionLevel > 0), (compressionLevel > 0), compressionLevel);
768  if (NC_NOERR != status)
769  {
770    StdString errormsg(nc_strerror(status));
771    StdStringStream sstr;
772
773    sstr << "Error when calling function nc_def_var_deflate(ncid, varId, false, (compressionLevel > 0), compressionLevel)" << std::endl;
774    sstr << errormsg << std::endl;
775    sstr << "Unable to set the compression level of the variable with id: " << varId
776         << " and compression level: " << compressionLevel << std::endl;
777    StdString e = sstr.str();
778    throw CNetCdfException(e);
779  }
780 
781  return status;
782}
783
784int CNetCdfInterface::defVarFilter(int ncid, int varId, unsigned int filterId , size_t filterNbrParams, unsigned int* filterParams)
785{
786  const char* cplugin = getenv("HDF5_PLUGIN_PATH") ;
787  bool filterAvailable( false );
788 
789  StdString pluginLibName;
790  if ( filterId == 32017 ) // 32017 = SZ
791  {
792    pluginLibName = "libhdf5sz.so";
793  }
794  if (cplugin)
795  {
796    string plugin( cplugin );
797    string libsz( plugin+"/"+pluginLibName );
798    struct stat sb;
799    if (stat(libsz.c_str(), &sb) == 0) filterAvailable = true;
800  }
801  if (!filterAvailable)
802  {
803    StdStringStream sstr;
804    sstr << "Error when calling function nc_def_var_filter(...)" << std::endl;
805    sstr << "The SZ filter required for " << varId << " is not available."
806         << "Check that $HDF5_PLUGIN_PATH/"<< pluginLibName <<" exists." ;
807    StdString e = sstr.str();
808    throw CNetCdfException(e);
809  }
810 
811  int status = nc_def_var_filter(ncid, varId, filterId, filterNbrParams, filterParams);
812  if (NC_NOERR != status)
813  {
814    StdString errormsg(nc_strerror(status));
815    StdStringStream sstr;
816   
817    sstr << "Error when calling function nc_def_var_filter(...)" << std::endl;
818    sstr << errormsg << std::endl;
819    sstr << "Unable to set the compression filter of the variable with id: " << varId
820         << " and plugin: " << filterId << std::endl;
821    StdString e = sstr.str();
822    throw CNetCdfException(e);
823  }
824 
825  return status;
826}
827
828/*!
829Set or unset the fill mode for a NetCDF file specified by its file id.
830\param [in] ncid File id
831\param [in] fill Define whether the fill mode should be enabled or not
832\return Status code
833*/
834int CNetCdfInterface::setFill(int ncid, bool fill)
835{
836  CMemChecker::get("NetCDF other").resume();
837  int old_fill_mode;
838  int status = nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode);
839  if (NC_NOERR != status)
840  {
841    StdString errormsg(nc_strerror(status));
842    StdStringStream sstr;
843
844    sstr << "Error when calling function nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode)" << std::endl;
845    sstr << errormsg << std::endl;
846    sstr << "Unable to set the fill mode to: " << (fill ? "NC_FILL": "NC_NOFILL") << std::endl;
847    StdString e = sstr.str();
848    throw CNetCdfException(e);
849  }
850  CMemChecker::get("NetCDF other").suspend();
851
852  return status;
853}
854
855/*!
856This function makes a request to netcdf with a ncid, to set the fill parameters for a variable,
857given variable id and type of fill
858\param [in] ncid Id groupd(or File Id)
859\param [in] varId Id of the variable
860\param [in] noFill turn on/off nofill mode on a variable
861\param [in/out] fillValue
862\return Status code
863*/
864int CNetCdfInterface::defVarFill(int ncid, int varId, int noFill, void* fillValue)
865{
866  CMemChecker::get("NetCDF other").resume();
867  int status = nc_def_var_fill(ncid, varId, noFill, fillValue);
868  if (NC_NOERR != status)
869  {
870    StdString errormsg(nc_strerror(status));
871    StdStringStream sstr;
872
873    sstr << "Error when calling function nc_def_var_fill(ncid, varId, noFill, fillValue)" << std::endl;
874    sstr << errormsg << std::endl;
875    sstr << "Unable to set fill parameters of the variable with id: " << varId
876      << " and fill option " << noFill << std::endl;
877    StdString e = sstr.str();
878    throw CNetCdfException(e);
879  }
880  CMemChecker::get("NetCDF other").suspend();
881
882  return status;
883}
884
885/*!
886This function makes a request to netcdf with a ncid, to change the way read/write operations are performed
887collectively or independently on the variable.
888\param [in] ncid Id groupd(or File Id)
889\param [in] varId Id of the variable
890\param [in] noFill turn on/off nofill mode on a variable
891\param [in/out] fillValue
892\return Status code
893*/
894int CNetCdfInterface::varParAccess(int ncid, int varId, int access)
895{
896  CMemChecker::get("NetCDF other").resume();
897  int status = nc_var_par_access(ncid, varId, access);
898  if (NC_NOERR != status)
899  {
900    StdString errormsg(nc_strerror(status));
901    StdStringStream sstr;
902
903    sstr << "Error when calling function nc_var_par_access(ncid, varId, access)" << std::endl;
904    sstr << errormsg << std::endl;
905    sstr << "Unable to change read/write option of the variable with id: " << varId << std::endl;
906    StdString e = sstr.str();
907    throw CNetCdfException(e);
908  }
909  CMemChecker::get("NetCDF other").suspend();
910
911  return status;
912}
913
914/*!
915This function makes a synchronisation of the disk copy of a netCDF dataset.
916\param [in] ncid Id groupd(or File Id)
917\return Status code
918*/
919int CNetCdfInterface::sync(int ncid)
920{
921  CMemChecker::get("NetCDF other").resume();
922  int status = nc_sync(ncid);
923  if (NC_NOERR != status)
924  {
925    StdString errormsg(nc_strerror(status));
926    StdStringStream sstr;
927
928    sstr << "Error when calling function nc_sync(ncid)" << std::endl;
929    sstr << errormsg << std::endl;
930    sstr << "Unable to make a synchronization of a netCDF file with id: " << ncid << std::endl;
931    StdString e = sstr.str();
932    throw CNetCdfException(e);
933  }
934  CMemChecker::get("NetCDF other").suspend();
935
936  return status;
937}
938
939// Some specializations of getAttributeType
940template<>
941int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, double* data)
942{
943  return nc_get_att_double(ncid, varid, attrName, data);
944}
945
946template<>
947int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, float* data)
948{
949  return nc_get_att_float(ncid, varid, attrName, data);
950}
951
952template<>
953int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, int* data)
954{
955  return nc_get_att_int(ncid, varid, attrName, data);
956}
957
958template<>
959int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, long* data)
960{
961  return nc_get_att_long(ncid, varid, attrName, data);
962}
963
964template<>
965int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, size_t* data)
966{
967  return nc_get_att_ulonglong(ncid, varid, attrName, (unsigned long long*)data);
968}
969
970template<>
971int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, short* data)
972{
973  return nc_get_att_short(ncid, varid, attrName, data);
974}
975
976template<>
977int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, char* data)
978{
979  return nc_get_att_text(ncid, varid, attrName, data);
980}
981
982// Some specializations of putAttributeType
983template<>
984int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
985                                   StdSize numVal, const double* data)
986{
987  return nc_put_att_double(ncid, varid, attrName, NC_DOUBLE, numVal, data);
988}
989
990template<>
991int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
992                                   StdSize numVal, const float* data)
993{
994  return nc_put_att_float(ncid, varid, attrName, NC_FLOAT, numVal, data);
995}
996
997template<>
998int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
999                                   StdSize numVal, const int* data)
1000{
1001  return nc_put_att_int(ncid, varid, attrName, NC_INT, numVal, data);
1002}
1003
1004template<>
1005int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
1006                                   StdSize numVal, const long* data)
1007{
1008  return nc_put_att_long(ncid, varid, attrName, NC_LONG, numVal, data);
1009}
1010
1011template<>
1012int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
1013                                   StdSize numVal, const size_t* data)
1014{
1015  return nc_put_att_ulonglong(ncid, varid, attrName, NC_UINT64, numVal, (unsigned long long*) data);
1016}
1017
1018template<>
1019int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
1020                                   StdSize numVal, const short* data)
1021{
1022  return nc_put_att_short(ncid, varid, attrName, NC_SHORT, numVal, data);
1023}
1024
1025template<>
1026int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
1027                                   StdSize numVal, const char* data)
1028{
1029  return nc_put_att_text(ncid, varid, attrName, numVal, data);
1030}
1031
1032// Some specializations of getVariableType
1033template<>
1034int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, double* data)
1035{
1036  return nc_get_vara_double(ncid, varid, start, count, data);
1037}
1038
1039template<>
1040int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, float* data)
1041{
1042  return nc_get_vara_float(ncid, varid, start, count, data);
1043}
1044
1045template<>
1046int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, int* data)
1047{
1048  return nc_get_vara_int(ncid, varid, start, count, data);
1049}
1050
1051template<>
1052int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, size_t* data)
1053{
1054  return nc_get_vara_ulonglong(ncid, varid, start, count, (unsigned long long*) data);
1055}
1056
1057template<>
1058int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, char* data)
1059{
1060  return nc_get_vara_text(ncid, varid, start, count, data);
1061}
1062
1063// Some specializations of putVariableType
1064template<>
1065int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const double* data)
1066{
1067  return nc_put_vara_double(ncid, varid, start, count, data);
1068}
1069
1070template<>
1071int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const float* data)
1072{
1073  return nc_put_vara_float(ncid, varid, start, count, data);
1074}
1075
1076template<>
1077int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const int* data)
1078{
1079  return nc_put_vara_int(ncid, varid, start, count, data);
1080}
1081
1082template<>
1083int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const size_t* data)
1084{
1085  return nc_put_vara_ulonglong(ncid, varid, start, count, (unsigned long long*)data);
1086}
1087
1088template<>
1089int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const char* data)
1090{
1091  return nc_put_vara_text(ncid, varid, start, count, data);
1092}
1093
1094 /*!
1095 This function verifies an existence of a variable by using its name.
1096 Be careful, althoug false means variable doens't exist, it could show that netCDF file doesn't either
1097 \param [in] ncid Id of groupd(or File Id)
1098 \param [in] attrName Name of the variable
1099 \return Existence of variable
1100 */
1101bool CNetCdfInterface::isVarExisted(int ncId, const StdString& varName)
1102{
1103   int varId = 0;
1104   return (NC_NOERR == (nc_inq_varid(ncId, varName.c_str(), &varId)));
1105}
1106
1107bool CNetCdfInterface::isDimExisted(int ncId, const StdString& dimName)
1108{
1109   int dimId = 0;
1110   return (NC_NOERR == (nc_inq_dimid(ncId, dimName.c_str(), &dimId)));
1111}
1112
1113StdString CNetCdfInterface::openMode2String(int oMode)
1114{
1115  StdString modeMes;
1116  switch (oMode)
1117  {
1118  case NC_NOWRITE:
1119    modeMes = StdString("NC_NOWRITE: Opening netCDF file with read-only access with buffering and caching access");
1120    break;
1121  case NC_SHARE:
1122    modeMes = StdString("NC_SHARE: Several processes can read the file concurrently");
1123    break;
1124  case NC_WRITE:
1125    modeMes = StdString("NC_WRITE: NetCDF file is readable and writable");
1126    break;
1127  default:
1128    modeMes = StdString("In the composed opening mode");
1129    break;
1130  }
1131  return modeMes;
1132}
1133
1134StdString CNetCdfInterface::creationMode2String(int cMode)
1135{
1136  StdString modeMes;
1137  switch (cMode)
1138  {
1139  case NC_NOCLOBBER:
1140    modeMes = StdString("NC_NOCLOBBER: Not overwrite an exisiting netCDF file ");
1141    break;
1142  case NC_SHARE:
1143    modeMes = StdString("NC_SHARE: Several processes can read from and write into the file concurrently");
1144    break;
1145  case NC_64BIT_OFFSET:
1146    modeMes = StdString("NC_64BIT_OFFSET: NetCDF file is 64-bit offset");
1147    break;
1148  case NC_NETCDF4:
1149    modeMes = StdString("NC_NETCDF4: NetCDF file is HDF5/NetCDF-4");
1150    break;
1151  case NC_CLASSIC_MODEL:
1152    modeMes = StdString("NC_CLASSIC_MODEL: NetCDF file is classical model");
1153    break;
1154  default:
1155    modeMes = StdString("In the composed creation mode");
1156    break;
1157  }
1158  return modeMes;
1159}
1160
1161}
Note: See TracBrowser for help on using the repository browser.