source: XIOS/dev/branch_openmp/src/io/netCdfInterface.cpp @ 1338

Last change on this file since 1338 was 1338, checked in by yushan, 6 years ago

dev_omp

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