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

Last change on this file since 1520 was 1520, checked in by yushan, 3 years ago

save dev. TO DO : test with xios

  • 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#include "ep_mpi.hpp"
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{
24  int status = nc_create(fileName.c_str(), cMode, &ncId);
25  if (NC_NOERR != status)
26  {
27    StdString errormsg(nc_strerror(status));
28    StdStringStream sstr;
29    sstr << "Error when calling function: nc_create(fileName.c_str(), cMode, &ncId) " << std::endl
30         << errormsg << std::endl
31         << "Unable to create file, given its name: " << fileName
32         << " and its creation mode " << creationMode2String(cMode) << std::endl;
33    StdString e = sstr.str();
34    throw CNetCdfException(e);
35  }
36
37  return status;
38}
39
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{
51  int status = xios::nc_create_par(fileName.c_str(), cMode, comm, to_mpi_info(MPI_INFO_NULL), &ncId);
52  if (NC_NOERR != status)
53  {
54    StdString errormsg(nc_strerror(status));
55    StdStringStream sstr;
56    sstr << "Error when calling function: nc_create_par(fileName.c_str(), cMode, comm, info, &ncId) " << std::endl
57         << errormsg << std::endl
58         << "Unable to create file on parallel file system, given its name: " << std::endl
59         << "and its creation mode " << creationMode2String(cMode) << std::endl;
60    StdString e = sstr.str();
61    throw CNetCdfException(e);
62  }
63
64  return status;
65}
66
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{
76  int status = nc_open(fileName.c_str(), oMode, &ncId);
77  if (NC_NOERR != status)
78  {
79    StdString errormsg(nc_strerror(status));
80    StdStringStream sstr;
81    sstr << "Error when calling function: nc_open(fileName.c_str(), oMode, &ncId) "<< std::endl
82         << errormsg << std::endl
83         << "Unable to open file, given its name: " << fileName
84         << "and its open mode " << openMode2String(oMode) << std::endl;
85    StdString e = sstr.str();
86    throw CNetCdfException(e);
87  }
88
89  return status;
90}
91
92
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{
104  int status;
105  #pragma omp critical (_netcdf)
106  status = xios::nc_open_par(fileName.c_str(), oMode, comm, to_mpi_info(MPI_INFO_NULL), &ncId);
107 
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 master
132  {
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    }
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 = nc_inq_dimlen(ncid, dimId, &dimLen);
356  if (NC_NOERR != status)
357  {
358    StdString errormsg(nc_strerror(status));
359    StdStringStream sstr;
360
361    sstr << "Error when calling function nc_inq_dimlen(ncid, dimId, &dimLen)" << std::endl
362         << errormsg << std::endl
363         << "Unable to get dimension length given its id: " << dimId << std::endl;
364    StdString e = sstr.str();
365    throw CNetCdfException(e);
366  }
367
368  return status;
369}
370
371/*!
372This function makes a request to netcdf, returns number of dimensions of a variable, given its id
373\param [in] ncid Groupd id (or File Id)
374\param [in] varId Id of variable
375\param [in/out] ndims number of dimension of the variable
376\return Status code
377*/
378int CNetCdfInterface::inqVarNDims(int ncid, int varId, int& nDims)
379{
380  int status = nc_inq_varndims(ncid, varId, &nDims);
381  if (NC_NOERR != status)
382  {
383    StdString errormsg(nc_strerror(status));
384    StdStringStream sstr;
385
386    sstr << "Error when calling function nc_inq_varndims(ncid, varId, &nDims)" << std::endl
387         << errormsg << std::endl
388         << "Unable to get the number of dimension of variable with Id: " << varId << std::endl;
389    StdString e = sstr.str();
390    throw CNetCdfException(e);
391  }
392
393  return status;
394}
395
396/*!
397This function makes a request to netcdf, returns a list of dimension ID describing the shape of the variable, given its id
398\param [in] ncid Groupd id (or File Id)
399\param [in] varId Id of variable
400\param [in/out] dimIds list of dimension of the variable
401\return Status code
402*/
403int CNetCdfInterface::inqVarDimId(int ncid, int varId, int* dimIds)
404{
405  int status = nc_inq_vardimid(ncid, varId, dimIds);
406  if (NC_NOERR != status)
407  {
408    StdString errormsg(nc_strerror(status));
409    StdStringStream sstr;
410
411    sstr << "Error when calling function nc_inq_vardimid(ncid, varId, dimIds)" << std::endl
412         << errormsg << std::endl
413         << "Unable to get list of dimension id of the variable with id " << varId << std::endl;
414    StdString e = sstr.str();
415    throw CNetCdfException(e);
416  }
417
418  return status;
419}
420
421/*!
422This function makes a request to netcdf, to find all dimension in a group
423\param [in] ncid Groupd id (or File Id)
424\param [in/out] nDims number of list of dimension
425\param [in/out] dimIds list of dimension in a group or any of its parent
426\param [in] includeParents number of parents
427\return Status code
428*/
429int CNetCdfInterface::inqDimIds(int ncid, int& nDims, int* dimIds, int includeParents)
430{
431  int status = nc_inq_dimids(ncid, &nDims, dimIds, includeParents);
432  if (NC_NOERR != status)
433  {
434    StdString errormsg(nc_strerror(status));
435    StdStringStream sstr;
436
437    sstr << "Error when calling function nc_inq_dimids(ncid, &nDims, dimIds, includeParents)" << std::endl;
438    sstr << errormsg << std::endl;
439    sstr << "Unable to retrieve number of dimension in the group with id: " << ncid << std::endl;
440    sstr << "With number of Parents " << includeParents << std::endl;
441    StdString e = sstr.str();
442    throw CNetCdfException(e);
443  }
444
445  return status;
446}
447
448/*!
449This function queries the full name of a group given its id.
450\param [in] ncid Groupd id (or File Id)
451\param [in/out] grpFullName the full name of the group
452\return Status code
453*/
454int CNetCdfInterface::inqGrpFullName(int ncid, StdString& grpFullName)
455{
456  StdSize strlen = 0;
457  std::vector<char> buff;
458  int status = nc_inq_grpname_full(ncid, &strlen, NULL);
459  if (NC_NOERR == status)
460  {
461    buff.resize(strlen + 1);
462    status = nc_inq_grpname_full(ncid, NULL, &buff[0]);
463  }
464
465  if (NC_NOERR != status)
466  {
467    StdString errormsg(nc_strerror(status));
468    StdStringStream sstr;
469
470    sstr << "Error when calling function nc_inq_grpname_full(ncid, &strlen, &buff[0])" << std::endl
471         << errormsg << std::endl
472         << "Unable to get the full group name given its id: " << ncid << std::endl;
473    StdString e = sstr.str();
474    throw CNetCdfException(e);
475  }
476
477  grpFullName.assign(buff.begin(), buff.end());
478
479  return status;
480}
481
482/*!
483This function queries the list of group ids given a location id.
484\param [in] ncid Groupd id (or File Id)
485\param [in/out] numgrps number of groups
486\param [in/out] ncids list of group ids
487\return Status code
488*/
489int CNetCdfInterface::inqGrpIds(int ncid, int& numgrps, int* ncids)
490{
491  int status = nc_inq_grps(ncid, &numgrps, ncids);
492  if (NC_NOERR != status)
493  {
494    StdString errormsg(nc_strerror(status));
495    StdStringStream sstr;
496
497    sstr << "Error when calling function nc_inq_grps(ncid, &numgrps, ncids)" << std::endl;
498    sstr << errormsg << std::endl;
499    sstr << "Unable to retrieve the list of groups for location id: " << ncid << std::endl;
500    StdString e = sstr.str();
501    throw CNetCdfException(e);
502  }
503
504  return status;
505}
506
507/*!
508This function queries the list of variable ids given a location id.
509\param [in] ncid Groupd id (or File Id)
510\param [in/out] nvars number of variables
511\param [in/out] varids list of variable ids
512\return Status code
513*/
514int CNetCdfInterface::inqVarIds(int ncid, int& nvars, int* varids)
515{
516  int status = nc_inq_varids(ncid, &nvars, varids);
517  if (NC_NOERR != status)
518  {
519    StdString errormsg(nc_strerror(status));
520    StdStringStream sstr;
521
522    sstr << "Error when calling function nc_inq_varids(ncid, &nvars, varids)" << std::endl;
523    sstr << errormsg << std::endl;
524    sstr << "Unable to retrieve the list of variables for location id: " << ncid << std::endl;
525    StdString e = sstr.str();
526    throw CNetCdfException(e);
527  }
528
529  return status;
530}
531
532/*!
533This function queries the type and the size of an attribute given its name and the id of the variable to which it is attached.
534\param [in] ncid Groupd id (or File Id)
535\param [in] varid the id of the variable to which the attribute is attached
536\param [in] name the name of the attribute
537\param [out] type the type of the attribute
538\param [out] len the size of the attribute
539\return Status code
540*/
541int CNetCdfInterface::inqAtt(int ncid, int varid, const StdString& name, nc_type& type, size_t& len)
542{
543  int status = nc_inq_att(ncid, varid, name.c_str(), &type, &len);
544  if (NC_NOERR != status)
545  {
546    StdString errormsg(nc_strerror(status));
547    StdStringStream sstr;
548
549    sstr << "Error when calling function nc_inq_att(ncid, varid, name.c_str(), &type, &len)" << std::endl;
550    sstr << errormsg << std::endl;
551    sstr << "Unable to query the attribute information given its name: " << name << " and its variable id:" << varid << std::endl;
552    StdString e = sstr.str();
553    throw CNetCdfException(e);
554  }
555
556  return status;
557}
558
559/*!
560This function queries the number of global attributes given a location id.
561\param [in] ncid Groupd id (or File Id)
562\param [out] ngatts the number of global attributes
563\return Status code
564*/
565int CNetCdfInterface::inqNAtts(int ncid, int& ngatts)
566{
567  int status = nc_inq_natts(ncid, &ngatts);
568  if (NC_NOERR != status)
569  {
570    StdString errormsg(nc_strerror(status));
571    StdStringStream sstr;
572
573    sstr << "Error when calling function nc_inq_natts(ncid, &ngatts)" << std::endl;
574    sstr << errormsg << std::endl;
575    sstr << "Unable to query the number of global attributes given the location id:" << ncid << std::endl;
576    StdString e = sstr.str();
577    throw CNetCdfException(e);
578  }
579
580  return status;
581}
582
583/*!
584This function queries the number of global attributes given a location id and a variable id.
585\param [in] ncid Groupd id (or File Id)
586\param [in] varid the id of the variable
587\param [out] natts the number of global attributes
588\return Status code
589*/
590int CNetCdfInterface::inqVarNAtts(int ncid, int varid, int& natts)
591{
592  int status = nc_inq_varnatts(ncid, varid, &natts);
593  if (NC_NOERR != status)
594  {
595    StdString errormsg(nc_strerror(status));
596    StdStringStream sstr;
597
598    sstr << "Error when calling function nc_inq_varnatts(ncid, varid, &natts)" << std::endl;
599    sstr << errormsg << std::endl;
600    sstr << "Unable to query the number of attributes given the location id:" << ncid << " and the variable id:" << varid << std::endl;
601    StdString e = sstr.str();
602    throw CNetCdfException(e);
603  }
604
605  return status;
606}
607
608
609//! Query the name of an attribute given a location id, a variable id and the attribute number
610int CNetCdfInterface::inqAttName(int ncid, int varid, int attnum, StdString& name)
611{
612  std::vector<char> attName(NC_MAX_NAME + 1,' ');
613  int status = nc_inq_attname(ncid, varid, attnum, &attName[0]);
614  if (NC_NOERR != status)
615  {
616    StdString errormsg(nc_strerror(status));
617    StdStringStream sstr;
618
619    sstr << "Error when calling function nc_inq_attname(ncid, varid, attnum, attName)" << std::endl;
620    sstr << errormsg << std::endl;
621    sstr << "Unable to query the name: " << name << " of attribute " << attnum << " given the location id:" << ncid << " and the variable id:" << varid << std::endl;
622    StdString e = sstr.str();
623    throw CNetCdfException(e);
624  }
625
626  int nameSize = 0;
627  while ((nameSize < NC_MAX_NAME) && (' ' != attName[nameSize] )) ++nameSize;
628  name.resize(nameSize);
629//  for (int idx = 0; idx < nameSize; ++idx) name.at(idx) = attName[idx];
630  std::copy(&attName[0], &attName[nameSize-1], name.begin());
631
632  return status;
633}
634
635/*!
636This function makes a request to netcdf with a id of a prent groupd and then return id of the created group, given its name
637\param [in] parentNcid Id of parent groupd(or File Id)
638\param [in] grpName Name of the desired group
639\param [in/out] grpId Group id if this group is created sucessfully
640\return Status code
641*/
642int CNetCdfInterface::defGrp(int parentNcid, const StdString& grpName, int& grpId)
643{
644  int status = nc_def_grp(parentNcid, grpName.c_str(), &grpId);
645  if (NC_NOERR != status)
646  {
647    StdString errormsg(nc_strerror(status));
648    StdStringStream sstr;
649
650    sstr << "Error when calling function nc_def_grp(parentNcid, grpName.c_str(), &grpId)" << std::endl;
651    sstr << errormsg << std::endl;
652    sstr << "Unable to create group Id, given its name: " << grpName << std::endl;
653    StdString e = sstr.str();
654    throw CNetCdfException(e);
655  }
656
657  return status;
658}
659
660/*!
661This function makes a request to netcdf, add a new dimension to an open netcdf in define mode
662\param [in] ncid Id of groupd(or File Id)
663\param [in] dimName Name of the desired dimension
664\param [in/out] grpId Group id if this group is created sucessfully
665\return Status code
666*/
667int CNetCdfInterface::defDim(int ncid, const StdString& dimName, StdSize dimLen, int& dimId)
668{
669  int status = nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId);
670  if (NC_NOERR != status)
671  {
672    StdString errormsg(nc_strerror(status));
673    StdStringStream sstr;
674
675    sstr << "Error when calling function nc_def_dim(ncid, dimName.c_str(), dimLen, &dimId)" << std::endl;
676    sstr << errormsg << std::endl;
677    sstr << "Unable to create dimension with name: " << dimName
678         << " and with length " << dimLen << std::endl;
679    StdString e = sstr.str();
680    throw CNetCdfException(e);
681  }
682
683  return status;
684}
685
686/*!
687This function makes a request to netcdf with its id, to add a new variable to an open netCdf in define mode,
688return a variable id, given its name, type, the number of dimensions and list of dimension id
689\param [in] ncid Id of groupd(or File Id)
690\param [in] varName Name of the desired dimension
691\param [in] xtypes One of the set of predefined netCDF data types
692\param [in] nDims Number of dimension for the variable
693\param [in] dimIds List of ndims dimension ids corresponding to the variable dimensions
694\param [in/out] varId Variable id if it is added sucessfully
695\return Status code
696*/
697int CNetCdfInterface::defVar(int ncid, const StdString& varName, nc_type xtype,
698                             int nDims, const int dimIds[], int& varId)
699{
700  int status = nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId);
701  if (NC_NOERR != status)
702  {
703    StdString errormsg(nc_strerror(status));
704    StdStringStream sstr;
705
706    sstr << "Error when calling function  nc_def_var(ncid, varName.c_str(), xtype, nDims, dimIds, &varId)" << std::endl;
707    sstr << errormsg << std::endl;
708    sstr << "Unable to add a new variable with name: " << varName
709         << " with type " << xtype
710         << " and number of dimension " << nDims << std::endl;
711    StdString e = sstr.str();
712    throw CNetCdfException(e);
713  }
714
715  return status;
716}
717
718/*!
719This function makes a request to netcdf with a ncid, to set the chunking size of a variable,
720given variable id and type of storage
721\param [in] ncid Id groupd(or File Id)
722\param [in] varId Id of the variable
723\param [in] storage Type of storage (It can be: NC_CONTIGUOUS, NC_CHUNKED)
724\param [in/out] chunkSize array list of chunk sizes
725\return Status code
726*/
727int CNetCdfInterface::defVarChunking(int ncid, int varId, int storage, StdSize chunkSize[])
728{
729  int status = nc_def_var_chunking(ncid, varId, storage, chunkSize);
730  if (NC_NOERR != status)
731  {
732    StdString errormsg(nc_strerror(status));
733    StdStringStream sstr;
734
735    sstr << "Error when calling function nc_def_var_chunking(ncid, varId, storage, chunkSize)" << std::endl;
736    sstr << errormsg << std::endl;
737    sstr << "Unable to set chunk size of the variable with id: " << varId
738      << " and storage type " << storage << std::endl;
739    StdString e = sstr.str();
740    throw CNetCdfException(e);
741  }
742
743  return status;
744}
745
746/*!
747This function sets the compression level to the specified variable
748\param [in] ncid Groud id (or file id)
749\param [in] varId Id of the variable
750\param [in] compressionLevel The compression level from 0 to 9 (0 disables the compression, 9 is the higher compression)
751\return Status code
752*/
753int CNetCdfInterface::defVarDeflate(int ncid, int varId, int compressionLevel)
754{
755 
756  if (compressionLevel == 0) return NC_NOERR ;
757  int status = nc_def_var_deflate(ncid, varId, (compressionLevel > 0), (compressionLevel > 0), compressionLevel);
758  if (NC_NOERR != status)
759  {
760    StdString errormsg(nc_strerror(status));
761    StdStringStream sstr;
762
763    sstr << "Error when calling function nc_def_var_deflate(ncid, varId, false, (compressionLevel > 0), compressionLevel)" << std::endl;
764    sstr << errormsg << std::endl;
765    sstr << "Unable to set the compression level of the variable with id: " << varId
766         << " and compression level: " << compressionLevel << std::endl;
767    StdString e = sstr.str();
768    throw CNetCdfException(e);
769  }
770
771  return status;
772}
773
774/*!
775Set or unset the fill mode for a NetCDF file specified by its file id.
776\param [in] ncid File id
777\param [in] fill Define whether the fill mode should be enabled or not
778\return Status code
779*/
780int CNetCdfInterface::setFill(int ncid, bool fill)
781{
782  int old_fill_mode;
783  int status = nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode);
784  if (NC_NOERR != status)
785  {
786    StdString errormsg(nc_strerror(status));
787    StdStringStream sstr;
788
789    sstr << "Error when calling function nc_set_fill(ncid, fill ? NC_FILL: NC_NOFILL, &old_fill_mode)" << std::endl;
790    sstr << errormsg << std::endl;
791    sstr << "Unable to set the fill mode to: " << (fill ? "NC_FILL": "NC_NOFILL") << std::endl;
792    StdString e = sstr.str();
793    throw CNetCdfException(e);
794  }
795
796  return status;
797}
798
799/*!
800This function makes a request to netcdf with a ncid, to set the fill parameters for a variable,
801given variable id and type of fill
802\param [in] ncid Id groupd(or File Id)
803\param [in] varId Id of the variable
804\param [in] noFill turn on/off nofill mode on a variable
805\param [in/out] fillValue
806\return Status code
807*/
808int CNetCdfInterface::defVarFill(int ncid, int varId, int noFill, void* fillValue)
809{
810  int status = nc_def_var_fill(ncid, varId, noFill, fillValue);
811  if (NC_NOERR != status)
812  {
813    StdString errormsg(nc_strerror(status));
814    StdStringStream sstr;
815
816    sstr << "Error when calling function nc_def_var_fill(ncid, varId, noFill, fillValue)" << std::endl;
817    sstr << errormsg << std::endl;
818    sstr << "Unable to set fill parameters of the variable with id: " << varId
819      << " and fill option " << noFill << std::endl;
820    StdString e = sstr.str();
821    throw CNetCdfException(e);
822  }
823
824  return status;
825}
826
827/*!
828This function makes a request to netcdf with a ncid, to change the way read/write operations are performed
829collectively or independently on the variable.
830\param [in] ncid Id groupd(or File Id)
831\param [in] varId Id of the variable
832\param [in] noFill turn on/off nofill mode on a variable
833\param [in/out] fillValue
834\return Status code
835*/
836int CNetCdfInterface::varParAccess(int ncid, int varId, int access)
837{
838  int status = nc_var_par_access(ncid, varId, access);
839  if (NC_NOERR != status)
840  {
841    StdString errormsg(nc_strerror(status));
842    StdStringStream sstr;
843
844    sstr << "Error when calling function nc_var_par_access(ncid, varId, access)" << std::endl;
845    sstr << errormsg << std::endl;
846    sstr << "Unable to change read/write option of the variable with id: " << varId << std::endl;
847    StdString e = sstr.str();
848    throw CNetCdfException(e);
849  }
850
851  return status;
852}
853
854/*!
855This function makes a synchronisation of the disk copy of a netCDF dataset.
856\param [in] ncid Id groupd(or File Id)
857\return Status code
858*/
859int CNetCdfInterface::sync(int ncid)
860{
861  int status = nc_sync(ncid);
862  if (NC_NOERR != status)
863  {
864    StdString errormsg(nc_strerror(status));
865    StdStringStream sstr;
866
867    sstr << "Error when calling function nc_sync(ncid)" << std::endl;
868    sstr << errormsg << std::endl;
869    sstr << "Unable to make a synchronization of a netCDF file with id: " << ncid << std::endl;
870    StdString e = sstr.str();
871    throw CNetCdfException(e);
872  }
873
874  return status;
875}
876
877// Some specializations of getAttributeType
878template<>
879int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, double* data)
880{
881  return nc_get_att_double(ncid, varid, attrName, data);
882}
883
884template<>
885int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, float* data)
886{
887  return nc_get_att_float(ncid, varid, attrName, data);
888}
889
890template<>
891int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, int* data)
892{
893  return nc_get_att_int(ncid, varid, attrName, data);
894}
895
896template<>
897int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, long* data)
898{
899  return nc_get_att_long(ncid, varid, attrName, data);
900}
901
902template<>
903int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, short* data)
904{
905  return nc_get_att_short(ncid, varid, attrName, data);
906}
907
908template<>
909int CNetCdfInterface::ncGetAttType(int ncid, int varid, const char* attrName, char* data)
910{
911  return nc_get_att_text(ncid, varid, attrName, data);
912}
913
914// Some specializations of putAttributeType
915template<>
916int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
917                                   StdSize numVal, const double* data)
918{
919  return nc_put_att_double(ncid, varid, attrName, NC_DOUBLE, numVal, data);
920}
921
922template<>
923int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
924                                   StdSize numVal, const float* data)
925{
926  return nc_put_att_float(ncid, varid, attrName, NC_FLOAT, numVal, data);
927}
928
929template<>
930int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
931                                   StdSize numVal, const int* data)
932{
933  return nc_put_att_int(ncid, varid, attrName, NC_INT, numVal, data);
934}
935
936template<>
937int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
938                                   StdSize numVal, const long* data)
939{
940  return nc_put_att_long(ncid, varid, attrName, NC_LONG, numVal, data);
941}
942
943template<>
944int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
945                                   StdSize numVal, const short* data)
946{
947  return nc_put_att_short(ncid, varid, attrName, NC_SHORT, numVal, data);
948}
949
950template<>
951int CNetCdfInterface::ncPutAttType(int ncid, int varid, const char* attrName,
952                                   StdSize numVal, const char* data)
953{
954  return nc_put_att_text(ncid, varid, attrName, numVal, data);
955}
956
957// Some specializations of getVariableType
958template<>
959int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, double* data)
960{
961  return nc_get_vara_double(ncid, varid, start, count, data);
962}
963
964template<>
965int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, float* data)
966{
967  return nc_get_vara_float(ncid, varid, start, count, data);
968}
969
970template<>
971int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, int* data)
972{
973  return nc_get_vara_int(ncid, varid, start, count, data);
974}
975
976template<>
977int CNetCdfInterface::ncGetVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, char* data)
978{
979  return nc_get_vara_text(ncid, varid, start, count, data);
980}
981
982// Some specializations of putVariableType
983template<>
984int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const double* data)
985{
986  return nc_put_vara_double(ncid, varid, start, count, data);
987}
988
989template<>
990int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const float* data)
991{
992  return nc_put_vara_float(ncid, varid, start, count, data);
993}
994
995template<>
996int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const int* data)
997{
998  return nc_put_vara_int(ncid, varid, start, count, data);
999}
1000
1001template<>
1002int CNetCdfInterface::ncPutVaraType(int ncid, int varid, const StdSize* start, const StdSize* count, const char* data)
1003{
1004  return nc_put_vara_text(ncid, varid, start, count, data);
1005}
1006
1007 /*!
1008 This function verifies an existence of a variable by using its name.
1009 Be careful, althoug false means variable doens't exist, it could show that netCDF file doesn't either
1010 \param [in] ncid Id of groupd(or File Id)
1011 \param [in] attrName Name of the variable
1012 \return Existence of variable
1013 */
1014bool CNetCdfInterface::isVarExisted(int ncId, const StdString& varName)
1015{
1016   int varId = 0;
1017   return (NC_NOERR == (nc_inq_varid(ncId, varName.c_str(), &varId)));
1018}
1019
1020bool CNetCdfInterface::isDimExisted(int ncId, const StdString& dimName)
1021{
1022   int dimId = 0;
1023   return (NC_NOERR == (nc_inq_dimid(ncId, dimName.c_str(), &dimId)));
1024}
1025
1026StdString CNetCdfInterface::openMode2String(int oMode)
1027{
1028  StdString modeMes;
1029  switch (oMode)
1030  {
1031  case NC_NOWRITE:
1032    modeMes = StdString("NC_NOWRITE: Opening netCDF file with read-only access with buffering and caching access");
1033    break;
1034  case NC_SHARE:
1035    modeMes = StdString("NC_SHARE: Several processes can read the file concurrently");
1036    break;
1037  case NC_WRITE:
1038    modeMes = StdString("NC_WRITE: NetCDF file is readable and writable");
1039    break;
1040  default:
1041    modeMes = StdString("In the composed opening mode");
1042    break;
1043  }
1044  return modeMes;
1045}
1046
1047StdString CNetCdfInterface::creationMode2String(int cMode)
1048{
1049  StdString modeMes;
1050  switch (cMode)
1051  {
1052  case NC_NOCLOBBER:
1053    modeMes = StdString("NC_NOCLOBBER: Not overwrite an exisiting netCDF file ");
1054    break;
1055  case NC_SHARE:
1056    modeMes = StdString("NC_SHARE: Several processes can read from and write into the file concurrently");
1057    break;
1058  case NC_64BIT_OFFSET:
1059    modeMes = StdString("NC_64BIT_OFFSET: NetCDF file is 64-bit offset");
1060    break;
1061  case NC_NETCDF4:
1062    modeMes = StdString("NC_NETCDF4: NetCDF file is HDF5/NetCDF-4");
1063    break;
1064  case NC_CLASSIC_MODEL:
1065    modeMes = StdString("NC_CLASSIC_MODEL: NetCDF file is classical model");
1066    break;
1067  default:
1068    modeMes = StdString("In the composed creation mode");
1069    break;
1070  }
1071  return modeMes;
1072}
1073
1074}
Note: See TracBrowser for help on using the repository browser.