source: XIOS/trunk/src/output/onetcdf4.cpp @ 498

Last change on this file since 498 was 498, checked in by mhnguyen, 8 years ago

Making a wrapper of NetCdf? C functions

+) Add a wrapper class for NetCdf? functions
+) Add a class to manage exception for NetCdf? functions
+) Replace direct call to netcdf functions by functions of the wrapper

Test
+) On Curie
+) In case of error, exception is thrown and more information is provided

File size: 17.8 KB
Line 
1#include "onetcdf4.hpp"
2#include "group_template.hpp"
3#include "mpi.hpp"
4#include "netcdf.hpp"
5#include "netCdfInterface.hpp"
6#include "netCdfException.hpp"
7
8namespace xios
9{
10      /// ////////////////////// Définitions ////////////////////// ///
11
12      CONetCDF4::CONetCDF4
13         (const StdString & filename, bool exist, const MPI_Comm * comm, bool multifile)
14            : path()
15      {
16         this->wmpi = (comm != NULL) && !multifile;
17         this->initialize(filename, exist, comm,multifile);
18      }
19
20      //---------------------------------------------------------------
21
22
23      CONetCDF4::~CONetCDF4(void)
24      {
25//         CheckError(nc_close(this->ncidp));
26      }
27
28      ///--------------------------------------------------------------
29
30      void CONetCDF4::initialize
31         (const StdString & filename, bool exist, const MPI_Comm * comm, bool multifile)
32      {
33         if (!exist)
34         {
35            if (comm != NULL)
36            {
37               if (!multifile) (CNetCdfInterface::createPar(filename, NC_NETCDF4|NC_MPIIO, *comm, MPI_INFO_NULL, (this->ncidp)));
38               else (CNetCdfInterface::create(filename, NC_NETCDF4, this->ncidp));
39            }
40            else (CNetCdfInterface::create(filename, NC_NETCDF4, this->ncidp));
41         }
42         else
43         {
44            if (comm != NULL)
45            {
46               if (!multifile) (CNetCdfInterface::openPar(filename, NC_NETCDF4|NC_MPIIO, *comm, MPI_INFO_NULL, this->ncidp));
47               else (CNetCdfInterface::open(filename, NC_NETCDF4, this->ncidp));
48            }
49            else  (CNetCdfInterface::open(filename, NC_NETCDF4, this->ncidp));
50         }
51      }
52
53      void CONetCDF4::close()
54      {
55        (CNetCdfInterface::close(this->ncidp));
56      }
57
58      //---------------------------------------------------------------
59
60      void CONetCDF4::definition_start(void)
61      {
62         (CNetCdfInterface::reDef(this->ncidp));
63      }
64
65      //---------------------------------------------------------------
66
67      void CONetCDF4::definition_end(void)
68      {
69         (CNetCdfInterface::endDef(this->ncidp));
70      }
71
72      //---------------------------------------------------------------
73
74// Don't need it anymore?
75//      void CONetCDF4::CheckError(int status)
76//      {
77//         if (status != NC_NOERR)
78//         {
79//            StdString errormsg (nc_strerror(status)); // fuite mémoire ici ?
80//            ERROR("CONetCDF4::CheckError(int status)",
81//                  << "[ status = " << status << " ] " << errormsg);
82//         }
83//      }
84
85      //---------------------------------------------------------------
86
87      int CONetCDF4::getCurrentGroup(void)
88      {
89         return (this->getGroup(this->getCurrentPath()));
90      }
91
92      //---------------------------------------------------------------
93
94      int CONetCDF4::getGroup(const CONetCDF4Path & path)
95      {
96         int retvalue = this->ncidp;
97
98         CONetCDF4Path::const_iterator
99            it  = path.begin(), end = path.end();
100
101         for (;it != end; it++)
102         {
103            const StdString & groupid = *it;
104            (CNetCdfInterface::inqNcId(retvalue, groupid, retvalue));
105         }
106         return (retvalue);
107      }
108
109      //---------------------------------------------------------------
110
111      int CONetCDF4::getVariable(const StdString & varname)
112      {
113         int varid = 0;
114         int grpid = this->getCurrentGroup();
115         (CNetCdfInterface::inqVarId(grpid, varname, varid));
116         return (varid);
117      }
118
119      //---------------------------------------------------------------
120
121      int CONetCDF4::getDimension(const StdString & dimname)
122      {
123         int dimid = 0;
124         int grpid = this->getCurrentGroup();
125         (CNetCdfInterface::inqDimId(grpid, dimname, dimid));
126         return (dimid);
127      }
128
129      //---------------------------------------------------------------
130
131      int CONetCDF4::getUnlimitedDimension(void)
132      {
133         int dimid = 0;
134         int grpid = this->getCurrentGroup();
135         (CNetCdfInterface::inqUnLimDim(grpid, dimid));
136         return (dimid);
137      }
138
139      StdString CONetCDF4::getUnlimitedDimensionName(void)
140      {
141         int grpid = this->getGroup(path);
142         int dimid = this->getUnlimitedDimension();
143
144         if (dimid == -1) return (std::string());
145         StdString dimname;
146         (CNetCdfInterface::inqDimName(grpid, dimid, dimname));
147
148         return (dimname);
149      }
150
151      //---------------------------------------------------------------
152
153      std::vector<StdSize> CONetCDF4::getDimensions(const StdString & varname)
154      {
155         StdSize size = 0;
156         std::vector<StdSize> retvalue;
157         int grpid = this->getCurrentGroup();
158         int varid = this->getVariable(varname);
159         int nbdim = 0, *dimid = NULL;
160
161         (CNetCdfInterface::inqVarNDims(grpid, varid, nbdim));
162         dimid = new int[nbdim]();
163         (CNetCdfInterface::inqVarDimId(grpid, varid, dimid));
164
165         for (int i = 0; i < nbdim; i++)
166         {
167            (CNetCdfInterface::inqDimLen(grpid, dimid[i], size));
168            if (size == NC_UNLIMITED)
169                size = UNLIMITED_DIM;
170            retvalue.push_back(size);
171         }
172         delete [] dimid;
173         return (retvalue);
174      }
175
176      std::vector<std::string> CONetCDF4::getDimensionsIdList (const std::string * _varname)
177      {
178         int nDimNull = 0;
179         int nbdim = 0, *dimid = NULL;
180         int grpid = this->getCurrentGroup();
181         int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
182         std::vector<std::string> retvalue;
183
184         if (_varname != NULL)
185         {
186            (CNetCdfInterface::inqVarNDims(grpid, varid, nbdim));
187            dimid = new int[nbdim]();
188            (CNetCdfInterface::inqVarDimId(grpid, varid, dimid));
189         }
190         else
191         {
192            (CNetCdfInterface::inqDimIds(grpid, nbdim, NULL, 1));
193            dimid = new int[nbdim]();
194            (CNetCdfInterface::inqDimIds(grpid, nDimNull, dimid, 1));
195         }
196
197         for (int i = 0; i < nbdim; i++)
198         {
199            std::string dimname;
200            (CNetCdfInterface::inqDimName(grpid, dimid[i], dimname));
201            retvalue.push_back(dimname);
202         }
203         delete [] dimid;
204
205         return (retvalue);
206      }
207
208
209      //---------------------------------------------------------------
210
211      const CONetCDF4::CONetCDF4Path & CONetCDF4::getCurrentPath(void) const
212      { return (this->path); }
213
214      void CONetCDF4::setCurrentPath(const CONetCDF4Path & path)
215      { this->path = path; }
216
217      //---------------------------------------------------------------
218
219      int CONetCDF4::addGroup(const StdString & name)
220      {
221         int retvalue = 0;
222         int grpid = this->getCurrentGroup();
223         (CNetCdfInterface::defGrp(grpid, name, retvalue));
224         return (retvalue);
225      }
226
227      //---------------------------------------------------------------
228
229      int CONetCDF4::addDimension(const StdString& name, const StdSize size)
230      {
231         int retvalue = 0;
232         int grpid = this->getCurrentGroup();
233         if (size != UNLIMITED_DIM)
234            (CNetCdfInterface::defDim(grpid, name, size, retvalue));
235         else
236            (CNetCdfInterface::defDim(grpid, name, NC_UNLIMITED, retvalue));
237         return (retvalue);
238      }
239
240      //---------------------------------------------------------------
241
242      int CONetCDF4::addVariable(const StdString & name, nc_type type,
243                                  const std::vector<StdString> & dim)
244      {
245         int varid = 0;
246         std::vector<int> dimids;
247         std::vector<StdSize> dimsizes ;
248         StdSize size ;
249         StdSize totalSize ;
250         StdSize maxSize=1024*1024*256 ; // == 2GB/8 if output double
251
252         int grpid = this->getCurrentGroup();
253
254         std::vector<StdString>::const_iterator
255            it  = dim.begin(), end = dim.end();
256
257         for (;it != end; it++)
258         {
259            const StdString & dimid = *it;
260            dimids.push_back(this->getDimension(dimid));
261            (CNetCdfInterface::inqDimLen(grpid, this->getDimension(dimid), size));
262            if (size==NC_UNLIMITED) size=1 ;
263            dimsizes.push_back(size) ;
264         }
265
266         (CNetCdfInterface::defVar(grpid, name, type, dimids.size(), &(dimids[0]), varid));
267
268// set chunksize : size of one record
269// but must not be > 2GB (netcdf or HDF5 problem)
270         totalSize=1 ;
271         for(vector<StdSize>::reverse_iterator it=dimsizes.rbegin(); it!=dimsizes.rend();++it)
272         {
273           totalSize*= *it ;
274           if (totalSize>=maxSize) *it=1 ;
275         }
276
277         (CNetCdfInterface::defVarChunking(grpid, varid, NC_CHUNKED, &(dimsizes[0])));
278         (CNetCdfInterface::defVarFill(grpid, varid, true, NULL));
279         return (varid);
280      }
281
282      //---------------------------------------------------------------
283
284      template <>
285         void CONetCDF4::addAttribute
286            (const StdString & name, const StdString & value, const StdString * varname )
287      {
288         int grpid = this->getCurrentGroup();
289         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
290         (CNetCdfInterface::putAtt(grpid, varid, name, NC_CHAR, value.size(), value.c_str()));
291         //CheckError(nc_put_att_string(grpid, varid, name.c_str(), 1, &str));
292      }
293
294      //---------------------------------------------------------------
295
296      template <>
297         void CONetCDF4::addAttribute
298            (const StdString & name, const double & value, const StdString * varname )
299      {
300         int grpid = this->getCurrentGroup();
301         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
302         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
303      }
304
305       template <>
306         void CONetCDF4::addAttribute
307            (const StdString & name, const CArray<double,1>& value, const StdString * varname )
308      {
309         int grpid = this->getCurrentGroup();
310         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
311         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
312      }
313      //---------------------------------------------------------------
314
315      template <>
316         void CONetCDF4::addAttribute
317            (const StdString & name, const float & value, const StdString * varname )
318      {
319         int grpid = this->getCurrentGroup();
320         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
321         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
322      }
323
324       template <>
325         void CONetCDF4::addAttribute
326            (const StdString & name, const CArray<float,1>& value, const StdString * varname )
327      {
328         int grpid = this->getCurrentGroup();
329         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
330         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
331      }
332
333      //---------------------------------------------------------------
334
335      template <>
336         void CONetCDF4::addAttribute
337            (const StdString & name, const int & value, const StdString * varname )
338      {
339         int grpid = this->getCurrentGroup();
340         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
341         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
342      }
343
344       template <>
345         void CONetCDF4::addAttribute
346            (const StdString & name, const CArray<int,1>& value, const StdString * varname )
347      {
348         int grpid = this->getCurrentGroup();
349         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
350         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
351      }
352
353      template <>
354         void CONetCDF4::addAttribute
355            (const StdString & name, const short int & value, const StdString * varname )
356      {
357         int grpid = this->getCurrentGroup();
358         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
359         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
360      }
361
362       template <>
363         void CONetCDF4::addAttribute
364            (const StdString & name, const CArray<short int,1>& value, const StdString * varname )
365      {
366         int grpid = this->getCurrentGroup();
367         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
368         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
369      }
370
371
372
373      template <>
374         void CONetCDF4::addAttribute
375            (const StdString & name, const long int & value, const StdString * varname )
376      {
377         int grpid = this->getCurrentGroup();
378         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
379         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
380      }
381
382       template <>
383         void CONetCDF4::addAttribute
384            (const StdString & name, const CArray<long int,1>& value, const StdString * varname )
385      {
386         int grpid = this->getCurrentGroup();
387         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
388         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
389      }
390
391
392
393                //---------------------------------------------------------------
394
395      void CONetCDF4::getWriteDataInfos(const StdString & name, StdSize record, StdSize & array_size,
396                                        std::vector<StdSize> & sstart,
397                                        std::vector<StdSize> & scount,
398                                        const std::vector<StdSize> * start,
399                                        const std::vector<StdSize> * count)
400      {
401         std::vector<std::size_t> sizes  = this->getDimensions(name);
402         std::vector<std::string> iddims = this->getDimensionsIdList (&name);
403         std::vector<std::size_t>::const_iterator
404            it  = sizes.begin(), end = sizes.end();
405         int i = 0;
406
407         if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
408         {
409            sstart.push_back(record);
410            scount.push_back(1); 
411            if ((start == NULL) &&
412                (count == NULL)) i++;
413            it++;
414         }
415
416         for (;it != end; it++)
417         { 
418            if ((start != NULL) && (count != NULL))
419            {
420               sstart.push_back((*start)[i]);
421               scount.push_back((*count)[i]);
422               array_size *= (*count)[i];
423               i++;
424            }
425            else
426            {
427               sstart.push_back(0);
428               scount.push_back(sizes[i]);
429               array_size *= sizes[i];
430               i++;
431            }
432         }
433
434      }
435
436
437
438      template <>
439         void CONetCDF4::writeData_(int grpid, int varid,
440                                    const std::vector<StdSize> & sstart,
441                                    const std::vector<StdSize> & scount, const double * data)
442      {
443         (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
444//         sync() ;
445      }
446
447      //---------------------------------------------------------------
448
449      template <>
450         void CONetCDF4::writeData_(int grpid, int varid,
451                                    const std::vector<StdSize> & sstart,
452                                    const std::vector<StdSize> & scount, const int * data)
453      {
454          (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
455//          sync() ;
456      }
457
458      //---------------------------------------------------------------
459
460      template <>
461         void CONetCDF4::writeData_(int grpid, int varid,
462                                    const std::vector<StdSize> & sstart,
463                                    const std::vector<StdSize> & scount, const float * data)
464      {
465          (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
466//          sync() ;
467      }
468
469      //---------------------------------------------------------------
470
471      void CONetCDF4::writeData(const CArray<int, 2>& data, const StdString & name)
472      {
473         int grpid = this->getCurrentGroup();
474         int varid = this->getVariable(name);
475         StdSize array_size = 1;
476         std::vector<StdSize> sstart, scount;
477
478         this->getWriteDataInfos(name, 0, array_size,  sstart, scount, NULL, NULL);
479         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
480      }
481
482      void CONetCDF4::writeTimeAxisData(const CArray<double, 1>& data, const StdString & name,
483                                        bool collective, StdSize record, bool isRoot)
484      {
485         int grpid = this->getCurrentGroup();
486         int varid = this->getVariable(name);
487
488         map<int,size_t>::iterator it=timeAxis.find(varid) ;
489         if (it==timeAxis.end()) timeAxis[varid]=record ;
490         else
491         {
492           if (it->second >= record) return ;
493           else it->second =record ;
494         }
495
496         StdSize array_size = 1;
497         std::vector<StdSize> sstart, scount;
498
499         if (this->wmpi && collective)
500         (CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE));
501         if (this->wmpi && !collective)
502         (CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT));
503
504         this->getWriteDataInfos(name, record, array_size,  sstart, scount, NULL, NULL);
505         if (using_netcdf_internal)  if (!isRoot) { sstart[0]=sstart[0]+1 ; scount[0]=0 ;}
506         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
507       }
508
509      //---------------------------------------------------------------
510
511      bool CONetCDF4::varExist(const StdString & varname)
512      {
513         int grpid = this->getCurrentGroup();
514         return (CNetCdfInterface::isVarExisted(grpid, varname));
515      }
516
517      void CONetCDF4::sync(void)
518      {
519         (CNetCdfInterface::sync(this->ncidp)) ;
520      }
521      ///--------------------------------------------------------------
522 } // namespace xios
Note: See TracBrowser for help on using the repository browser.