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

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

bug fixed in mpi_comm_split. Key needs to be specifify.

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