source: XIOS/dev/branch_yushan_merged/src/io/netCdfInterface.cpp @ 1153

Last change on this file since 1153 was 1153, checked in by yushan, 7 years ago

save modif

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