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

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

Append mode

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