source: XIOS3/trunk/src/io/netCdfInterface.cpp @ 2529

Last change on this file since 2529 was 2529, checked in by jderouillat, 12 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
RevLine 
[498]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
[525]10#include "netCdfInterface.hpp"
11#include "netCdfException.hpp"
[2426]12#include "mem_checker.hpp"
[2529]13#include <string>
14#include <sys/stat.h>
[1639]15
[525]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{
[2426]27  CMemChecker::get("NetCDF create").resume();
[686]28  int status = nc_create(fileName.c_str(), cMode, &ncId);
[525]29  if (NC_NOERR != status)
30  {
31    StdString errormsg(nc_strerror(status));
32    StdStringStream sstr;
[686]33    sstr << "Error when calling function: nc_create(fileName.c_str(), cMode, &ncId) " << std::endl
[525]34         << errormsg << std::endl
[686]35         << "Unable to create file, given its name: " << fileName
[1370]36         << " and its creation mode " << creationMode2String(cMode) << std::endl;
[525]37    StdString e = sstr.str();
38    throw CNetCdfException(e);
39  }
[2426]40  CMemChecker::get("NetCDF create").suspend();
[498]41
[525]42  return status;
43}
[498]44
[525]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*/
[1639]54int CNetCdfInterface::createPar(const StdString& fileName, int cMode, MPI_Comm comm, MPI_Info info, int& ncId)
[525]55{
[2426]56  CMemChecker::get("NetCDF create").resume();
[686]57  int status = xios::nc_create_par(fileName.c_str(), cMode, comm, info, &ncId);
[525]58  if (NC_NOERR != status)
59  {
60    StdString errormsg(nc_strerror(status));
61    StdStringStream sstr;
[686]62    sstr << "Error when calling function: nc_create_par(fileName.c_str(), cMode, comm, info, &ncId) " << std::endl
[525]63         << errormsg << std::endl
[686]64         << "Unable to create file on parallel file system, given its name: " << std::endl
[525]65         << "and its creation mode " << creationMode2String(cMode) << std::endl;
66    StdString e = sstr.str();
67    throw CNetCdfException(e);
68  }
[2426]69  CMemChecker::get("NetCDF create").suspend();
[498]70
[525]71  return status;
72}
[498]73
[525]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{
[2426]83  CMemChecker::get("NetCDF open").resume();
[686]84  int status = nc_open(fileName.c_str(), oMode, &ncId);
[525]85  if (NC_NOERR != status)
86  {
87    StdString errormsg(nc_strerror(status));
88    StdStringStream sstr;
[686]89    sstr << "Error when calling function: nc_open(fileName.c_str(), oMode, &ncId) "<< std::endl
[525]90         << errormsg << std::endl
[686]91         << "Unable to open file, given its name: " << fileName
[525]92         << "and its open mode " << openMode2String(oMode) << std::endl;
93    StdString e = sstr.str();
94    throw CNetCdfException(e);
95  }
[2426]96  CMemChecker::get("NetCDF open").suspend();
[498]97
[525]98  return status;
99}
[498]100
101
[525]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*/
[1639]111int CNetCdfInterface::openPar(const StdString& fileName, int oMode, MPI_Comm comm, MPI_Info info, int& ncId)
[525]112{
[2426]113  CMemChecker::get("NetCDF open").resume();
[686]114  int status = xios::nc_open_par(fileName.c_str(), oMode, comm, info, &ncId);
[525]115  if (NC_NOERR != status)
116  {
117    StdString errormsg(nc_strerror(status));
118    StdStringStream sstr;
[686]119    sstr << "Error when calling function nc_open_par(fileName.c_str(), oMode, comm, info, &ncId) " << std::endl
[525]120         << errormsg << std::endl
[686]121         << "Unable to open file on parallel file system, given its name: " << fileName
[525]122         << "and its open mode " << openMode2String(oMode) << std::endl;
123    StdString e = sstr.str();
124    throw CNetCdfException(e);
125  }
[2426]126  CMemChecker::get("NetCDF open").suspend();
[498]127
[525]128  return status;
129}
[498]130
[525]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{
[2426]138  CMemChecker::get("NetCDF close").resume();
[525]139  int status = nc_close(ncId);
140  if (NC_NOERR != status)
141  {
142    StdString errormsg(nc_strerror(status));
143    StdStringStream sstr;
[686]144    sstr << "Error when calling function nc_close(ncId)" << std::endl
[498]145         << errormsg << std::endl
[686]146         << "Unable to close file, given its id: " << ncId << std::endl;
[525]147    StdString e = sstr.str();
148    throw CNetCdfException(e);
149  }
[2426]150  CMemChecker::get("NetCDF close").suspend();
[498]151
[525]152  return status;
153}
[498]154
[525]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{
[2426]162  CMemChecker::get("NetCDF other").resume();
[525]163  int status = nc_redef(ncId);
164  if (NC_NOERR != status)
165  {
166    StdString errormsg(nc_strerror(status));
167    StdStringStream sstr;
[686]168    sstr << "Error when calling function nc_redef(ncId)" << std::endl
[525]169      << errormsg << std::endl
[686]170      << "Unable to put this file into define mode given its id: " << ncId << std::endl;
[525]171    StdString e = sstr.str();
172    throw CNetCdfException(e);
173  }
[2426]174  CMemChecker::get("NetCDF other").suspend();
[498]175
[525]176  return status;
177}
[498]178
[525]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{
[2426]186  CMemChecker::get("NetCDF other").resume();
[525]187  int status = nc_enddef(ncId);
188  if (NC_NOERR != status)
189  {
190    StdString errormsg(nc_strerror(status));
191    StdStringStream sstr;
[498]192
[686]193    sstr << "Error when calling function nc_enddef(ncId)" << std::endl
[525]194         << errormsg << std::endl
[686]195         << "Unable to end define mode of this file, given its id: " << ncId << std::endl;
[525]196    StdString e = sstr.str();
197    throw CNetCdfException(e);
198  }
[2426]199  CMemChecker::get("NetCDF other").suspend();
[498]200
[525]201  return status;
202}
[498]203
[525]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{
[686]213  int status = nc_inq_ncid(ncid, grpName.c_str(), &grpId);
[525]214  if (NC_NOERR != status)
215  {
216    StdString errormsg(nc_strerror(status));
217    StdStringStream sstr;
[498]218
[686]219    sstr << "Error when calling function nc_inq_ncid(ncid, grpName.c_str(), &grpId)" << std::endl
[525]220         << errormsg << std::endl
[686]221         << "Unable to get id of a group (File), given its name: " << grpName << std::endl;
[525]222    StdString e = sstr.str();
223    throw CNetCdfException(e);
224  }
[498]225
[525]226  return status;
227}
[498]228
229
[525]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*/
[686]237int CNetCdfInterface::inqVarId(int ncid, const StdString& varName, int& varId)
[525]238{
[686]239  int status = nc_inq_varid(ncid, varName.c_str(), &varId);
[525]240  if (NC_NOERR != status)
241  {
242    StdString errormsg(nc_strerror(status));
243    StdStringStream sstr;
[498]244
[686]245    sstr << "Error when calling function: nc_inq_varid(ncid, varName.c_str(), &varId)" << std::endl
[525]246         << (errormsg) << std::endl
[686]247         << "Unable to get id of variable with name: " << varName << std::endl;
[525]248    StdString e = sstr.str();
249    throw CNetCdfException(e);
250  }
[498]251
[525]252  return status;
253}
[498]254
[525]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*/
[686]262int CNetCdfInterface::inqDimId(int ncid, const StdString& dimName, int& dimId)
[525]263{
[686]264  int status = nc_inq_dimid(ncid, dimName.c_str(), &dimId);
[525]265  if (NC_NOERR != status)
266  {
267    StdString errormsg(nc_strerror(status));
268    StdStringStream sstr;
[498]269
[686]270    sstr << "Error when calling function nc_inq_dimid(ncid, dimName.c_str(), &dimId)" << std::endl
[498]271         << errormsg << std::endl
[686]272         << "Unable to get id of dimension, given its name: " << dimName << std::endl;
[525]273    StdString e = sstr.str();
274    throw CNetCdfException(e);
275  }
[498]276
[525]277  return status;
278}
[498]279
[525]280/*!
[686]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
[833]298         << "Unable to get variable name: "<< varName << " given its id: " << varId << std::endl;
[686]299    StdString e = sstr.str();
300    throw CNetCdfException(e);
301  }
302  varName = varNameBuff;
303  return status;
304}
305
306/*!
[525]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;
[498]319
[686]320    sstr << "Error when calling function nc_inq_dimid" << std::endl
[525]321      << errormsg << std::endl
322      << "Unable to get id of unlimited dimension " << std::endl;
323    StdString e = sstr.str();
324    throw CNetCdfException(e);
325 }
[498]326
[525]327  return status;
328}
[498]329
[525]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
[686]334\param [out] dimName Name of desired dimension
[525]335\return Status code
336*/
337int CNetCdfInterface::inqDimName(int ncid, int dimId, StdString& dimName)
338{
[686]339  char fullNameIn[NC_MAX_NAME + 1];
[525]340  int status = nc_inq_dimname(ncid, dimId, fullNameIn);
341  if (NC_NOERR != status)
342  {
343    StdString errormsg(nc_strerror(status));
344    StdStringStream sstr;
[498]345
[686]346    sstr << "Error when calling function nc_inq_dimname(ncid, dimId, fullNameIn)" << std::endl
[525]347         << errormsg << std::endl
[833]348         << "Unable to get dimension name: " << dimName << " given its id: " << dimId << std::endl;
[525]349    StdString e = sstr.str();
350    throw CNetCdfException(e);
351  }
352  dimName = StdString(fullNameIn);
353  return status;
354}
[498]355
[525]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;
[498]370
[686]371    sstr << "Error when calling function nc_inq_dimlen(ncid, dimId, &dimLen)" << std::endl
[525]372         << errormsg << std::endl
[686]373         << "Unable to get dimension length given its id: " << dimId << std::endl;
[525]374    StdString e = sstr.str();
375    throw CNetCdfException(e);
376  }
[498]377
[525]378  return status;
379}
[498]380
[525]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;
[498]395
[686]396    sstr << "Error when calling function nc_inq_varndims(ncid, varId, &nDims)" << std::endl
[525]397         << errormsg << std::endl
[686]398         << "Unable to get the number of dimension of variable with Id: " << varId << std::endl;
[525]399    StdString e = sstr.str();
400    throw CNetCdfException(e);
401  }
[498]402
[525]403  return status;
404}
[498]405
[525]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;
[498]420
[686]421    sstr << "Error when calling function nc_inq_vardimid(ncid, varId, dimIds)" << std::endl
[525]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  }
[498]427
[525]428  return status;
429}
[498]430
[525]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;
[498]446
[686]447    sstr << "Error when calling function nc_inq_dimids(ncid, &nDims, dimIds, includeParents)" << std::endl;
[525]448    sstr << errormsg << std::endl;
[686]449    sstr << "Unable to retrieve number of dimension in the group with id: " << ncid << std::endl;
[525]450    sstr << "With number of Parents " << includeParents << std::endl;
451    StdString e = sstr.str();
452    throw CNetCdfException(e);
453  }
[498]454
[525]455  return status;
456}
[498]457
[525]458/*!
[686]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{
[782]622  std::vector<char> attName(NC_MAX_NAME + 1,' ');
623  int status = nc_inq_attname(ncid, varid, attnum, &attName[0]);
[686]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;
[833]631    sstr << "Unable to query the name: " << name << " of attribute " << attnum << " given the location id:" << ncid << " and the variable id:" << varid << std::endl;
[686]632    StdString e = sstr.str();
633    throw CNetCdfException(e);
634  }
635
[782]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
[686]642  return status;
643}
644
645/*!
[525]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{
[686]654  int status = nc_def_grp(parentNcid, grpName.c_str(), &grpId);
[525]655  if (NC_NOERR != status)
656  {
657    StdString errormsg(nc_strerror(status));
658    StdStringStream sstr;
[498]659
[686]660    sstr << "Error when calling function nc_def_grp(parentNcid, grpName.c_str(), &grpId)" << std::endl;
[525]661    sstr << errormsg << std::endl;
[686]662    sstr << "Unable to create group Id, given its name: " << grpName << std::endl;
[525]663    StdString e = sstr.str();
664    throw CNetCdfException(e);
665  }
[498]666
[525]667  return status;
668}
[498]669
[525]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{
[686]679  int status = nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId);
[525]680  if (NC_NOERR != status)
681  {
682    StdString errormsg(nc_strerror(status));
683    StdStringStream sstr;
[498]684
[686]685    sstr << "Error when calling function nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId)" << std::endl;
[525]686    sstr << errormsg << std::endl;
[686]687    sstr << "Unable to create dimension with name: " << dimName
[525]688         << " and with length " << dimLen << std::endl;
689    StdString e = sstr.str();
690    throw CNetCdfException(e);
691  }
[498]692
[525]693  return status;
694}
[498]695
[525]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*/
[686]707int CNetCdfInterface::defVar(int ncid, const StdString& varName, nc_type xtype,
708                             int nDims, const int dimIds[], int& varId)
[525]709{
[686]710  int status = nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId);
[525]711  if (NC_NOERR != status)
712  {
713    StdString errormsg(nc_strerror(status));
714    StdStringStream sstr;
[498]715
[686]716    sstr << "Error when calling function  nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId)" << std::endl;
[525]717    sstr << errormsg << std::endl;
[686]718    sstr << "Unable to add a new variable with name: " << varName
[525]719         << " with type " << xtype
720         << " and number of dimension " << nDims << std::endl;
721    StdString e = sstr.str();
722    throw CNetCdfException(e);
723  }
[498]724
[525]725  return status;
726}
[498]727
[525]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
[686]733\param [in] storage Type of storage (It can be: NC_CONTIGUOUS, NC_CHUNKED)
[525]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)
[517]741  {
[525]742    StdString errormsg(nc_strerror(status));
743    StdStringStream sstr;
[517]744
[686]745    sstr << "Error when calling function nc_def_var_chunking(ncid, varId, storage, chunkSize)" << std::endl;
[525]746    sstr << errormsg << std::endl;
[686]747    sstr << "Unable to set chunk size of the variable with id: " << varId
[525]748      << " and storage type " << storage << std::endl;
749    StdString e = sstr.str();
750    throw CNetCdfException(e);
[517]751  }
752
[525]753  return status;
754}
[498]755
[525]756/*!
[606]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{
[972]765 
766  if (compressionLevel == 0) return NC_NOERR ;
[1454]767  int status = nc_def_var_deflate(ncid, varId, (compressionLevel > 0), (compressionLevel > 0), compressionLevel);
[606]768  if (NC_NOERR != status)
769  {
770    StdString errormsg(nc_strerror(status));
771    StdStringStream sstr;
772
[686]773    sstr << "Error when calling function nc_def_var_deflate(ncid, varId, false, (compressionLevel > 0), compressionLevel)" << std::endl;
[606]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  }
[2529]780 
781  return status;
782}
[606]783
[2529]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 
[606]825  return status;
826}
827
828/*!
[525]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{
[2426]836  CMemChecker::get("NetCDF other").resume();
[525]837  int old_fill_mode;
[686]838  int status = nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode);
[525]839  if (NC_NOERR != status)
840  {
841    StdString errormsg(nc_strerror(status));
842    StdStringStream sstr;
[498]843
[686]844    sstr << "Error when calling function nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode)" << std::endl;
[525]845    sstr << errormsg << std::endl;
[686]846    sstr << "Unable to set the fill mode to: " << (fill ? "NC_FILL": "NC_NOFILL") << std::endl;
[525]847    StdString e = sstr.str();
848    throw CNetCdfException(e);
849  }
[2426]850  CMemChecker::get("NetCDF other").suspend();
[498]851
[525]852  return status;
853}
[498]854
[525]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{
[2426]866  CMemChecker::get("NetCDF other").resume();
[525]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;
[498]872
[686]873    sstr << "Error when calling function nc_def_var_fill(ncid, varId, noFill, fillValue)" << std::endl;
[525]874    sstr << errormsg << std::endl;
[686]875    sstr << "Unable to set fill parameters of the variable with id: " << varId
[525]876      << " and fill option " << noFill << std::endl;
877    StdString e = sstr.str();
878    throw CNetCdfException(e);
879  }
[2426]880  CMemChecker::get("NetCDF other").suspend();
[498]881
[525]882  return status;
883}
[498]884
[525]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{
[2426]896  CMemChecker::get("NetCDF other").resume();
[525]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;
[498]902
[686]903    sstr << "Error when calling function nc_var_par_access(ncid, varId, access)" << std::endl;
[525]904    sstr << errormsg << std::endl;
[686]905    sstr << "Unable to change read/write option of the variable with id: " << varId << std::endl;
[525]906    StdString e = sstr.str();
907    throw CNetCdfException(e);
908  }
[2426]909  CMemChecker::get("NetCDF other").suspend();
[498]910
[525]911  return status;
912}
[498]913
[525]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{
[2426]921  CMemChecker::get("NetCDF other").resume();
[525]922  int status = nc_sync(ncid);
923  if (NC_NOERR != status)
[498]924  {
[525]925    StdString errormsg(nc_strerror(status));
926    StdStringStream sstr;
[498]927
[686]928    sstr << "Error when calling function nc_sync(ncid)" << std::endl;
[525]929    sstr << errormsg << std::endl;
[686]930    sstr << "Unable to make a synchronization of a netCDF file with id: " << ncid << std::endl;
[525]931    StdString e = sstr.str();
932    throw CNetCdfException(e);
[498]933  }
[2426]934  CMemChecker::get("NetCDF other").suspend();
[498]935
[525]936  return status;
937}
[498]938
[686]939// Some specializations of getAttributeType
940template<>
941int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, double* data)
[525]942{
[686]943  return nc_get_att_double(ncid, varid, attrName, data);
944}
[498]945
[686]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}
[498]951
[686]952template<>
953int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, int* data)
954{
955  return nc_get_att_int(ncid, varid, attrName, data);
[525]956}
[498]957
[525]958template<>
[686]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<>
[1957]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<>
[686]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<>
[525]984int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]985                                   StdSize numVal, const double* data)
[525]986{
[686]987  return nc_put_att_double(ncid, varid, attrName, NC_DOUBLE, numVal, data);
[525]988}
[498]989
[525]990template<>
991int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]992                                   StdSize numVal, const float* data)
[525]993{
[686]994  return nc_put_att_float(ncid, varid, attrName, NC_FLOAT, numVal, data);
[525]995}
[498]996
[525]997template<>
998int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]999                                   StdSize numVal, const int* data)
[525]1000{
[686]1001  return nc_put_att_int(ncid, varid, attrName, NC_INT, numVal, data);
[525]1002}
[498]1003
[525]1004template<>
1005int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]1006                                   StdSize numVal, const long* data)
[525]1007{
[686]1008  return nc_put_att_long(ncid, varid, attrName, NC_LONG, numVal, data);
[525]1009}
[498]1010
[525]1011template<>
1012int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[1957]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,
[686]1020                                   StdSize numVal, const short* data)
[525]1021{
[686]1022  return nc_put_att_short(ncid, varid, attrName, NC_SHORT, numVal, data);
[525]1023}
1024
[686]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}
[525]1031
[686]1032// Some specializations of getVariableType
[525]1033template<>
[686]1034int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, double* data)
[525]1035{
[686]1036  return nc_get_vara_double(ncid, varid, start, count, data);
[525]1037}
1038
1039template<>
[686]1040int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, float* data)
[525]1041{
[686]1042  return nc_get_vara_float(ncid, varid, start, count, data);
[525]1043}
1044
1045template<>
[686]1046int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, int* data)
[525]1047{
[686]1048  return nc_get_vara_int(ncid, varid, start, count, data);
[525]1049}
1050
[1158]1051template<>
[1957]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<>
[1158]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
[686]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
[1158]1082template<>
[1957]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<>
[1158]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
[525]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
[811]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
[525]1113StdString CNetCdfInterface::openMode2String(int oMode)
1114{
1115  StdString modeMes;
1116  switch (oMode)
[498]1117  {
[525]1118  case NC_NOWRITE:
[686]1119    modeMes = StdString("NC_NOWRITE: Opening netCDF file with read-only access with buffering and caching access");
[525]1120    break;
1121  case NC_SHARE:
[686]1122    modeMes = StdString("NC_SHARE: Several processes can read the file concurrently");
[525]1123    break;
1124  case NC_WRITE:
[686]1125    modeMes = StdString("NC_WRITE: NetCDF file is readable and writable");
[525]1126    break;
1127  default:
1128    modeMes = StdString("In the composed opening mode");
1129    break;
[578]1130  }
[525]1131  return modeMes;
1132}
[498]1133
[525]1134StdString CNetCdfInterface::creationMode2String(int cMode)
1135{
1136  StdString modeMes;
1137  switch (cMode)
[498]1138  {
[525]1139  case NC_NOCLOBBER:
[686]1140    modeMes = StdString("NC_NOCLOBBER: Not overwrite an exisiting netCDF file ");
[525]1141    break;
1142  case NC_SHARE:
[686]1143    modeMes = StdString("NC_SHARE: Several processes can read from and write into the file concurrently");
[525]1144    break;
1145  case NC_64BIT_OFFSET:
[686]1146    modeMes = StdString("NC_64BIT_OFFSET: NetCDF file is 64-bit offset");
[525]1147    break;
1148  case NC_NETCDF4:
[686]1149    modeMes = StdString("NC_NETCDF4: NetCDF file is HDF5/NetCDF-4");
[525]1150    break;
1151  case NC_CLASSIC_MODEL:
[686]1152    modeMes = StdString("NC_CLASSIC_MODEL: NetCDF file is classical model");
[525]1153    break;
1154  default:
1155    modeMes = StdString("In the composed creation mode");
1156    break;
[578]1157  }
[525]1158  return modeMes;
1159}
[498]1160
[525]1161}
Note: See TracBrowser for help on using the repository browser.