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

Last change on this file since 2427 was 2427, checked in by jderouillat, 18 months ago

Backport the system to log the memory consumption (commit ID [2418-2420,2425-2426])

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