source: XIOS3/branches/xios-3.0-beta/src/io/netCdfInterface.cpp

Last change on this file was 2598, checked in by jderouillat, 5 months ago

Add a field attribute, conversion_by_NetCDF, to operate type conversion in XIOS, and not in NetCDF

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