source: XIOS/trunk/src/io/netCdfInterface.cpp @ 1050

Last change on this file since 1050 was 1050, checked in by ymipsl, 7 years ago
  • Add label attribute for axis
  • if label attribute is present, then only only string label for each level will be output in netcdf file, ie value and bounds will not be output.

YM

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