source: XIOS3/trunk/src/io/netCdfInterface.cpp @ 2426

Last change on this file since 2426 was 2426, checked in by jderouillat, 19 months ago

Clean MemCheckcer?, add memory consumption accumulators in main XIOS interfaces for clients, and in the NetCDF interface for servers.

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