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

Last change on this file since 605 was 605, checked in by rlacroix, 6 years ago

Don't enable NETCDF parallel mode when only one server is 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: 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            , 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      template <>
291         void CONetCDF4::addAttribute
292            (const StdString & name, const StdString & value, const StdString * varname )
293      {
294         int grpid = this->getCurrentGroup();
295         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
296         (CNetCdfInterface::putAtt(grpid, varid, name, NC_CHAR, value.size(), value.c_str()));
297         //CheckError(nc_put_att_string(grpid, varid, name.c_str(), 1, &str));
298      }
299
300      //---------------------------------------------------------------
301
302      template <>
303         void CONetCDF4::addAttribute
304            (const StdString & name, const double & value, const StdString * varname )
305      {
306         int grpid = this->getCurrentGroup();
307         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
308         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
309      }
310
311       template <>
312         void CONetCDF4::addAttribute
313            (const StdString & name, const CArray<double,1>& value, const StdString * varname )
314      {
315         int grpid = this->getCurrentGroup();
316         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
317         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
318      }
319      //---------------------------------------------------------------
320
321      template <>
322         void CONetCDF4::addAttribute
323            (const StdString & name, const float & value, const StdString * varname )
324      {
325         int grpid = this->getCurrentGroup();
326         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
327         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
328      }
329
330       template <>
331         void CONetCDF4::addAttribute
332            (const StdString & name, const CArray<float,1>& value, const StdString * varname )
333      {
334         int grpid = this->getCurrentGroup();
335         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
336         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
337      }
338
339      //---------------------------------------------------------------
340
341      template <>
342         void CONetCDF4::addAttribute
343            (const StdString & name, const int & value, const StdString * varname )
344      {
345         int grpid = this->getCurrentGroup();
346         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
347         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
348      }
349
350       template <>
351         void CONetCDF4::addAttribute
352            (const StdString & name, const CArray<int,1>& value, const StdString * varname )
353      {
354         int grpid = this->getCurrentGroup();
355         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
356         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
357      }
358
359      template <>
360         void CONetCDF4::addAttribute
361            (const StdString & name, const short int & value, const StdString * varname )
362      {
363         int grpid = this->getCurrentGroup();
364         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
365         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
366      }
367
368       template <>
369         void CONetCDF4::addAttribute
370            (const StdString & name, const CArray<short int,1>& value, const StdString * varname )
371      {
372         int grpid = this->getCurrentGroup();
373         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
374         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
375      }
376
377
378
379      template <>
380         void CONetCDF4::addAttribute
381            (const StdString & name, const long int & value, const StdString * varname )
382      {
383         int grpid = this->getCurrentGroup();
384         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
385         (CNetCdfInterface::putAttType(grpid, varid, name, 1, &value));
386      }
387
388       template <>
389         void CONetCDF4::addAttribute
390            (const StdString & name, const CArray<long int,1>& value, const StdString * varname )
391      {
392         int grpid = this->getCurrentGroup();
393         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
394         (CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst()));
395      }
396
397
398
399                //---------------------------------------------------------------
400
401      void CONetCDF4::getWriteDataInfos(const StdString & name, StdSize record, StdSize & array_size,
402                                        std::vector<StdSize> & sstart,
403                                        std::vector<StdSize> & scount,
404                                        const std::vector<StdSize> * start,
405                                        const std::vector<StdSize> * count)
406      {
407         std::vector<std::size_t> sizes  = this->getDimensions(name);
408         std::vector<std::string> iddims = this->getDimensionsIdList (&name);
409         std::vector<std::size_t>::const_iterator
410            it  = sizes.begin(), end = sizes.end();
411         int i = 0;
412
413         if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
414         {
415            sstart.push_back(record);
416            scount.push_back(1); 
417            if ((start == NULL) &&
418                (count == NULL)) i++;
419            it++;
420         }
421
422         for (;it != end; it++)
423         { 
424            if ((start != NULL) && (count != NULL))
425            {
426               sstart.push_back((*start)[i]);
427               scount.push_back((*count)[i]);
428               array_size *= (*count)[i];
429               i++;
430            }
431            else
432            {
433               sstart.push_back(0);
434               scount.push_back(sizes[i]);
435               array_size *= sizes[i];
436               i++;
437            }
438         }
439
440      }
441
442
443
444      template <>
445         void CONetCDF4::writeData_(int grpid, int varid,
446                                    const std::vector<StdSize> & sstart,
447                                    const std::vector<StdSize> & scount, const double * data)
448      {
449         (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
450//         sync() ;
451      }
452
453      //---------------------------------------------------------------
454
455      template <>
456         void CONetCDF4::writeData_(int grpid, int varid,
457                                    const std::vector<StdSize> & sstart,
458                                    const std::vector<StdSize> & scount, const int * data)
459      {
460          (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
461//          sync() ;
462      }
463
464      //---------------------------------------------------------------
465
466      template <>
467         void CONetCDF4::writeData_(int grpid, int varid,
468                                    const std::vector<StdSize> & sstart,
469                                    const std::vector<StdSize> & scount, const float * data)
470      {
471          (CNetCdfInterface::putVaraType(grpid, varid, &(sstart[0]), &(scount[0]), data));
472//          sync() ;
473      }
474
475      //---------------------------------------------------------------
476
477      void CONetCDF4::writeData(const CArray<int, 2>& data, const StdString & name)
478      {
479         int grpid = this->getCurrentGroup();
480         int varid = this->getVariable(name);
481         StdSize array_size = 1;
482         std::vector<StdSize> sstart, scount;
483
484         this->getWriteDataInfos(name, 0, array_size,  sstart, scount, NULL, NULL);
485         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
486      }
487
488      void CONetCDF4::writeTimeAxisData(const CArray<double, 1>& data, const StdString & name,
489                                        bool collective, StdSize record, bool isRoot)
490      {
491         int grpid = this->getCurrentGroup();
492         int varid = this->getVariable(name);
493
494         map<int,size_t>::iterator it=timeAxis.find(varid) ;
495         if (it==timeAxis.end()) timeAxis[varid]=record ;
496         else
497         {
498           if (it->second >= record) return ;
499           else it->second =record ;
500         }
501
502         StdSize array_size = 1;
503         std::vector<StdSize> sstart, scount;
504
505         if (this->wmpi && collective)
506         (CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE));
507         if (this->wmpi && !collective)
508         (CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT));
509
510         this->getWriteDataInfos(name, record, array_size,  sstart, scount, NULL, NULL);
511         if (using_netcdf_internal)  if (!isRoot) { sstart[0]=sstart[0]+1 ; scount[0]=0 ;}
512         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
513       }
514
515      //---------------------------------------------------------------
516
517      bool CONetCDF4::varExist(const StdString & varname)
518      {
519         int grpid = this->getCurrentGroup();
520         return (CNetCdfInterface::isVarExisted(grpid, varname));
521      }
522
523      void CONetCDF4::sync(void)
524      {
525         (CNetCdfInterface::sync(this->ncidp)) ;
526      }
527      ///--------------------------------------------------------------
528 } // namespace xios
Note: See TracBrowser for help on using the repository browser.