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

Last change on this file was 2600, checked in by jderouillat, 7 months ago

Add a field attribute, conversion_by_NetCDF, to operate type conversion in XIOS, and not in NetCDF

  • 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: 37.1 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  }
[2532]794  else if ( filterId == 32013 ) // 32013 = ZFP
795  {
796    pluginLibName = "libh5zzfp.so";
797  }
[2529]798  if (cplugin)
799  {
800    string plugin( cplugin );
801    string libsz( plugin+"/"+pluginLibName );
802    struct stat sb;
803    if (stat(libsz.c_str(), &sb) == 0) filterAvailable = true;
804  }
805  if (!filterAvailable)
806  {
807    StdStringStream sstr;
808    sstr << "Error when calling function nc_def_var_filter(...)" << std::endl;
809    sstr << "The SZ filter required for " << varId << " is not available."
810         << "Check that $HDF5_PLUGIN_PATH/"<< pluginLibName <<" exists." ;
811    StdString e = sstr.str();
812    throw CNetCdfException(e);
813  }
814 
815  int status = nc_def_var_filter(ncid, varId, filterId, filterNbrParams, filterParams);
816  if (NC_NOERR != status)
817  {
818    StdString errormsg(nc_strerror(status));
819    StdStringStream sstr;
820   
821    sstr << "Error when calling function nc_def_var_filter(...)" << std::endl;
822    sstr << errormsg << std::endl;
823    sstr << "Unable to set the compression filter of the variable with id: " << varId
824         << " and plugin: " << filterId << std::endl;
825    StdString e = sstr.str();
826    throw CNetCdfException(e);
827  }
828 
[606]829  return status;
830}
831
832/*!
[525]833Set or unset the fill mode for a NetCDF file specified by its file id.
834\param [in] ncid File id
835\param [in] fill Define whether the fill mode should be enabled or not
836\return Status code
837*/
838int CNetCdfInterface::setFill(int ncid, bool fill)
839{
[2426]840  CMemChecker::get("NetCDF other").resume();
[525]841  int old_fill_mode;
[686]842  int status = nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode);
[525]843  if (NC_NOERR != status)
844  {
845    StdString errormsg(nc_strerror(status));
846    StdStringStream sstr;
[498]847
[686]848    sstr << "Error when calling function nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode)" << std::endl;
[525]849    sstr << errormsg << std::endl;
[686]850    sstr << "Unable to set the fill mode to: " << (fill ? "NC_FILL": "NC_NOFILL") << std::endl;
[525]851    StdString e = sstr.str();
852    throw CNetCdfException(e);
853  }
[2426]854  CMemChecker::get("NetCDF other").suspend();
[498]855
[525]856  return status;
857}
[498]858
[525]859/*!
860This function makes a request to netcdf with a ncid, to set the fill parameters for a variable,
861given variable id and type of fill
862\param [in] ncid Id groupd(or File Id)
863\param [in] varId Id of the variable
864\param [in] noFill turn on/off nofill mode on a variable
865\param [in/out] fillValue
866\return Status code
867*/
868int CNetCdfInterface::defVarFill(int ncid, int varId, int noFill, void* fillValue)
869{
[2426]870  CMemChecker::get("NetCDF other").resume();
[525]871  int status = nc_def_var_fill(ncid, varId, noFill, fillValue);
872  if (NC_NOERR != status)
873  {
874    StdString errormsg(nc_strerror(status));
875    StdStringStream sstr;
[498]876
[686]877    sstr << "Error when calling function nc_def_var_fill(ncid, varId, noFill, fillValue)" << std::endl;
[525]878    sstr << errormsg << std::endl;
[686]879    sstr << "Unable to set fill parameters of the variable with id: " << varId
[525]880      << " and fill option " << noFill << std::endl;
881    StdString e = sstr.str();
882    throw CNetCdfException(e);
883  }
[2426]884  CMemChecker::get("NetCDF other").suspend();
[498]885
[525]886  return status;
887}
[498]888
[525]889/*!
890This function makes a request to netcdf with a ncid, to change the way read/write operations are performed
891collectively or independently on the variable.
892\param [in] ncid Id groupd(or File Id)
893\param [in] varId Id of the variable
894\param [in] noFill turn on/off nofill mode on a variable
895\param [in/out] fillValue
896\return Status code
897*/
898int CNetCdfInterface::varParAccess(int ncid, int varId, int access)
899{
[2426]900  CMemChecker::get("NetCDF other").resume();
[525]901  int status = nc_var_par_access(ncid, varId, access);
902  if (NC_NOERR != status)
903  {
904    StdString errormsg(nc_strerror(status));
905    StdStringStream sstr;
[498]906
[686]907    sstr << "Error when calling function nc_var_par_access(ncid, varId, access)" << std::endl;
[525]908    sstr << errormsg << std::endl;
[686]909    sstr << "Unable to change read/write option of the variable with id: " << varId << std::endl;
[525]910    StdString e = sstr.str();
911    throw CNetCdfException(e);
912  }
[2426]913  CMemChecker::get("NetCDF other").suspend();
[498]914
[525]915  return status;
916}
[498]917
[525]918/*!
919This function makes a synchronisation of the disk copy of a netCDF dataset.
920\param [in] ncid Id groupd(or File Id)
921\return Status code
922*/
923int CNetCdfInterface::sync(int ncid)
924{
[2426]925  CMemChecker::get("NetCDF other").resume();
[525]926  int status = nc_sync(ncid);
927  if (NC_NOERR != status)
[498]928  {
[525]929    StdString errormsg(nc_strerror(status));
930    StdStringStream sstr;
[498]931
[686]932    sstr << "Error when calling function nc_sync(ncid)" << std::endl;
[525]933    sstr << errormsg << std::endl;
[686]934    sstr << "Unable to make a synchronization of a netCDF file with id: " << ncid << std::endl;
[525]935    StdString e = sstr.str();
936    throw CNetCdfException(e);
[498]937  }
[2426]938  CMemChecker::get("NetCDF other").suspend();
[498]939
[525]940  return status;
941}
[498]942
[686]943// Some specializations of getAttributeType
944template<>
945int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, double* data)
[525]946{
[686]947  return nc_get_att_double(ncid, varid, attrName, data);
948}
[498]949
[686]950template<>
951int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, float* data)
952{
953  return nc_get_att_float(ncid, varid, attrName, data);
954}
[498]955
[686]956template<>
957int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, int* data)
958{
959  return nc_get_att_int(ncid, varid, attrName, data);
[525]960}
[498]961
[525]962template<>
[686]963int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, long* data)
964{
965  return nc_get_att_long(ncid, varid, attrName, data);
966}
967
968template<>
[1957]969int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, size_t* data)
970{
971  return nc_get_att_ulonglong(ncid, varid, attrName, (unsigned long long*)data);
972}
973
974template<>
[686]975int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, short* data)
976{
977  return nc_get_att_short(ncid, varid, attrName, data);
978}
979
980template<>
981int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, char* data)
982{
983  return nc_get_att_text(ncid, varid, attrName, data);
984}
985
986// Some specializations of putAttributeType
987template<>
[525]988int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]989                                   StdSize numVal, const double* data)
[525]990{
[686]991  return nc_put_att_double(ncid, varid, attrName, NC_DOUBLE, numVal, data);
[525]992}
[498]993
[525]994template<>
995int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]996                                   StdSize numVal, const float* data)
[525]997{
[686]998  return nc_put_att_float(ncid, varid, attrName, NC_FLOAT, numVal, data);
[525]999}
[498]1000
[525]1001template<>
1002int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]1003                                   StdSize numVal, const int* data)
[525]1004{
[686]1005  return nc_put_att_int(ncid, varid, attrName, NC_INT, numVal, data);
[525]1006}
[498]1007
[525]1008template<>
1009int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]1010                                   StdSize numVal, const long* data)
[525]1011{
[686]1012  return nc_put_att_long(ncid, varid, attrName, NC_LONG, numVal, data);
[525]1013}
[498]1014
[525]1015template<>
1016int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[1957]1017                                   StdSize numVal, const size_t* data)
1018{
1019  return nc_put_att_ulonglong(ncid, varid, attrName, NC_UINT64, numVal, (unsigned long long*) data);
1020}
1021
1022template<>
1023int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
[686]1024                                   StdSize numVal, const short* data)
[525]1025{
[686]1026  return nc_put_att_short(ncid, varid, attrName, NC_SHORT, numVal, data);
[525]1027}
1028
[686]1029template<>
1030int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
1031                                   StdSize numVal, const char* data)
1032{
1033  return nc_put_att_text(ncid, varid, attrName, numVal, data);
1034}
[525]1035
[686]1036// Some specializations of getVariableType
[525]1037template<>
[686]1038int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, double* data)
[525]1039{
[686]1040  return nc_get_vara_double(ncid, varid, start, count, data);
[525]1041}
1042
1043template<>
[686]1044int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, float* data)
[525]1045{
[686]1046  return nc_get_vara_float(ncid, varid, start, count, data);
[525]1047}
1048
1049template<>
[686]1050int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, int* data)
[525]1051{
[686]1052  return nc_get_vara_int(ncid, varid, start, count, data);
[525]1053}
1054
[1158]1055template<>
[2600]1056int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, short* data)
1057{
1058  return nc_get_vara_short(ncid, varid, start, count, data);
1059}
1060
1061template<>
[1957]1062int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, size_t* data)
1063{
1064  return nc_get_vara_ulonglong(ncid, varid, start, count, (unsigned long long*) data);
1065}
1066
1067template<>
[1158]1068int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, char* data)
1069{
1070  return nc_get_vara_text(ncid, varid, start, count, data);
1071}
1072
[686]1073// Some specializations of putVariableType
1074template<>
1075int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const double* data)
1076{
1077  return nc_put_vara_double(ncid, varid, start, count, data);
1078}
1079
1080template<>
1081int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const float* data)
1082{
1083  return nc_put_vara_float(ncid, varid, start, count, data);
1084}
1085
1086template<>
1087int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const int* data)
1088{
1089  return nc_put_vara_int(ncid, varid, start, count, data);
1090}
1091
[1158]1092template<>
[2600]1093int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const short* data)
1094{
1095  return nc_put_vara_short(ncid, varid, start, count, data);
1096}
1097
1098template<>
[1957]1099int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const size_t* data)
1100{
1101  return nc_put_vara_ulonglong(ncid, varid, start, count, (unsigned long long*)data);
1102}
1103
1104template<>
[1158]1105int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const char* data)
1106{
1107  return nc_put_vara_text(ncid, varid, start, count, data);
1108}
1109
[525]1110 /*!
1111 This function verifies an existence of a variable by using its name.
1112 Be careful, althoug false means variable doens't exist, it could show that netCDF file doesn't either
1113 \param [in] ncid Id of groupd(or File Id)
1114 \param [in] attrName Name of the variable
1115 \return Existence of variable
1116 */
1117bool CNetCdfInterface::isVarExisted(int ncId, const StdString& varName)
1118{
1119   int varId = 0;
1120   return (NC_NOERR == (nc_inq_varid(ncId, varName.c_str(), &varId)));
1121}
1122
[811]1123bool CNetCdfInterface::isDimExisted(int ncId, const StdString& dimName)
1124{
1125   int dimId = 0;
1126   return (NC_NOERR == (nc_inq_dimid(ncId, dimName.c_str(), &dimId)));
1127}
1128
[525]1129StdString CNetCdfInterface::openMode2String(int oMode)
1130{
1131  StdString modeMes;
1132  switch (oMode)
[498]1133  {
[525]1134  case NC_NOWRITE:
[686]1135    modeMes = StdString("NC_NOWRITE: Opening netCDF file with read-only access with buffering and caching access");
[525]1136    break;
1137  case NC_SHARE:
[686]1138    modeMes = StdString("NC_SHARE: Several processes can read the file concurrently");
[525]1139    break;
1140  case NC_WRITE:
[686]1141    modeMes = StdString("NC_WRITE: NetCDF file is readable and writable");
[525]1142    break;
1143  default:
1144    modeMes = StdString("In the composed opening mode");
1145    break;
[578]1146  }
[525]1147  return modeMes;
1148}
[498]1149
[525]1150StdString CNetCdfInterface::creationMode2String(int cMode)
1151{
1152  StdString modeMes;
1153  switch (cMode)
[498]1154  {
[525]1155  case NC_NOCLOBBER:
[686]1156    modeMes = StdString("NC_NOCLOBBER: Not overwrite an exisiting netCDF file ");
[525]1157    break;
1158  case NC_SHARE:
[686]1159    modeMes = StdString("NC_SHARE: Several processes can read from and write into the file concurrently");
[525]1160    break;
1161  case NC_64BIT_OFFSET:
[686]1162    modeMes = StdString("NC_64BIT_OFFSET: NetCDF file is 64-bit offset");
[525]1163    break;
1164  case NC_NETCDF4:
[686]1165    modeMes = StdString("NC_NETCDF4: NetCDF file is HDF5/NetCDF-4");
[525]1166    break;
1167  case NC_CLASSIC_MODEL:
[686]1168    modeMes = StdString("NC_CLASSIC_MODEL: NetCDF file is classical model");
[525]1169    break;
1170  default:
1171    modeMes = StdString("In the composed creation mode");
1172    break;
[578]1173  }
[525]1174  return modeMes;
1175}
[498]1176
[525]1177}
Note: See TracBrowser for help on using the repository browser.