source: XIOS/branchs/xios-1.0/src/output/onetcdf4.cpp @ 607

Last change on this file since 607 was 607, checked in by rlacroix, 9 years ago

Improve the error message when compression cannot be used.

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