source: XIOS3/trunk/src/io/onetcdf4.cpp @ 2604

Last change on this file since 2604 was 2600, checked in by jderouillat, 8 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: 32.5 KB
RevLine 
[528]1#include <fstream>
2
[219]3#include "onetcdf4.hpp"
[2529]4#include "onetcdf4_plugin.hpp"
[352]5#include "group_template.hpp"
[382]6#include "mpi.hpp"
[379]7#include "netcdf.hpp"
[498]8#include "netCdfInterface.hpp"
9#include "netCdfException.hpp"
[1158]10#include "timer.hpp"
[2579]11#include "file.hpp"
[219]12
[335]13namespace xios
[219]14{
15      /// ////////////////////// Définitions ////////////////////// ///
16
[686]17      CONetCDF4::CONetCDF4(const StdString& filename, bool append, bool useClassicFormat,
[878]18                                                        bool useCFConvention,
[1639]19                           const MPI_Comm* comm, bool multifile, const StdString& timeCounterName)
[686]20        : path()
21        , wmpi(false)
22        , useClassicFormat(useClassicFormat)
[878]23        , useCFConvention(useCFConvention)
[219]24      {
[878]25         this->initialize(filename, append, useClassicFormat, useCFConvention, comm, multifile, timeCounterName);
[219]26      }
[498]27
[219]28      //---------------------------------------------------------------
[286]29
[219]30      CONetCDF4::~CONetCDF4(void)
31      {
32      }
33
34      ///--------------------------------------------------------------
35
[878]36      void CONetCDF4::initialize(const StdString& filename, bool append, bool useClassicFormat, bool useCFConvention, 
[1639]37                                 const MPI_Comm* comm, bool multifile, const StdString& timeCounterName)
[219]38      {
[517]39         this->useClassicFormat = useClassicFormat;
[878]40         this->useCFConvention = useCFConvention;
[517]41
42         int mode = useClassicFormat ? 0 : NC_NETCDF4;
[605]43
44         // Don't use parallel mode if there is only one process
45         if (comm)
46         {
47            int commSize = 0;
[1639]48            MPI_Comm_size(*comm, &commSize);
[605]49            if (commSize <= 1)
50               comm = NULL;
51         }
52         wmpi = comm && !multifile;
53
54         if (wmpi)
[517]55            mode |= useClassicFormat ? NC_PNETCDF : NC_MPIIO;
56
[528]57         // If the file does not exist, we always create it
58         if (!append || !std::ifstream(filename.c_str()))
[219]59         {
[1158]60            CTimer::get("Files : create").resume();
[605]61            if (wmpi)
[1639]62               CNetCdfInterface::createPar(filename, mode, *comm, MPI_INFO_NULL, this->ncidp);
[605]63            else
64               CNetCdfInterface::create(filename, mode, this->ncidp);
[1158]65            CTimer::get("Files : create").suspend();
66 
[528]67            this->appendMode = false;
[219]68         }
69         else
70         {
[528]71            mode |= NC_WRITE;
[1158]72            CTimer::get("Files : open").resume();
[605]73            if (wmpi)
[1639]74               CNetCdfInterface::openPar(filename, mode, *comm, MPI_INFO_NULL, this->ncidp);
[605]75            else
76               CNetCdfInterface::open(filename, mode, this->ncidp);
[1158]77            CTimer::get("Files : open").suspend();
[528]78            this->appendMode = true;
[219]79         }
[517]80
81         // If the classic NetCDF format is used, we enable the "no-fill mode" globally.
82         // This is done per variable for the NetCDF4 format.
83         if (useClassicFormat)
[606]84            CNetCdfInterface::setFill(this->ncidp, false);
[802]85
86         this->timeCounterName = timeCounterName;
[219]87      }
[498]88
[286]89      void CONetCDF4::close()
90      {
[1158]91        CTimer::get("Files : close").resume();
[686]92        CNetCdfInterface::close(this->ncidp);
[1158]93        CTimer::get("Files : close").suspend();
[286]94      }
[498]95
[219]96      //---------------------------------------------------------------
[498]97
[219]98      void CONetCDF4::definition_start(void)
[498]99      {
[686]100         CNetCdfInterface::reDef(this->ncidp);
[219]101      }
[498]102
[219]103      //---------------------------------------------------------------
[498]104
[219]105      void CONetCDF4::definition_end(void)
106      {
[686]107         CNetCdfInterface::endDef(this->ncidp);
[219]108      }
109
110      //---------------------------------------------------------------
[498]111
[219]112      int CONetCDF4::getCurrentGroup(void)
113      {
[686]114         return this->getGroup(this->getCurrentPath());
[219]115      }
[498]116
[219]117      //---------------------------------------------------------------
[498]118
[686]119      int CONetCDF4::getGroup(const CONetCDF4Path& path)
[219]120      {
121         int retvalue = this->ncidp;
[498]122
[686]123         CONetCDF4Path::const_iterator it = path.begin(), end = path.end();
[219]124
[686]125         for (; it != end; it++)
[219]126         {
[686]127            const StdString& groupid = *it;
128            CNetCdfInterface::inqNcId(retvalue, groupid, retvalue);
[219]129         }
[686]130         return retvalue;
[219]131      }
[498]132
[219]133      //---------------------------------------------------------------
[498]134
[686]135      int CONetCDF4::getVariable(const StdString& varname)
[219]136      {
137         int varid = 0;
138         int grpid = this->getCurrentGroup();
[686]139         CNetCdfInterface::inqVarId(grpid, varname, varid);
140         return varid;
[219]141      }
[498]142
[219]143      //---------------------------------------------------------------
[498]144
[686]145      int CONetCDF4::getDimension(const StdString& dimname)
[219]146      {
147         int dimid = 0;
148         int grpid = this->getCurrentGroup();
[686]149         CNetCdfInterface::inqDimId(grpid, dimname, dimid);
150         return dimid;
[219]151      }
[498]152
[219]153      //---------------------------------------------------------------
[498]154
[219]155      int CONetCDF4::getUnlimitedDimension(void)
156      {
157         int dimid = 0;
158         int grpid = this->getCurrentGroup();
[686]159         CNetCdfInterface::inqUnLimDim(grpid, dimid);
160         return dimid;
[219]161      }
[498]162
[266]163      StdString CONetCDF4::getUnlimitedDimensionName(void)
164      {
165         int grpid = this->getGroup(path);
166         int dimid = this->getUnlimitedDimension();
[498]167
168         StdString dimname;
[686]169         if (dimid != -1)
170           CNetCdfInterface::inqDimName(grpid, dimid, dimname);
171         return dimname;
[266]172      }
[498]173
[219]174      //---------------------------------------------------------------
[498]175
[686]176      std::vector<StdSize> CONetCDF4::getDimensions(const StdString& varname)
[219]177      {
178         StdSize size = 0;
179         std::vector<StdSize> retvalue;
180         int grpid = this->getCurrentGroup();
181         int varid = this->getVariable(varname);
182         int nbdim = 0, *dimid = NULL;
183
[686]184         CNetCdfInterface::inqVarNDims(grpid, varid, nbdim);
[219]185         dimid = new int[nbdim]();
[686]186         CNetCdfInterface::inqVarDimId(grpid, varid, dimid);
[219]187
188         for (int i = 0; i < nbdim; i++)
189         {
[686]190            CNetCdfInterface::inqDimLen(grpid, dimid[i], size);
[219]191            if (size == NC_UNLIMITED)
192                size = UNLIMITED_DIM;
193            retvalue.push_back(size);
194         }
[401]195         delete [] dimid;
[686]196         return retvalue;
[219]197      }
198
[686]199      std::vector<std::string> CONetCDF4::getDimensionsIdList(const std::string* _varname)
[266]200      {
[498]201         int nDimNull = 0;
[266]202         int nbdim = 0, *dimid = NULL;
203         int grpid = this->getCurrentGroup();
204         int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
205         std::vector<std::string> retvalue;
[498]206
[266]207         if (_varname != NULL)
208         {
[686]209            CNetCdfInterface::inqVarNDims(grpid, varid, nbdim);
[266]210            dimid = new int[nbdim]();
[686]211            CNetCdfInterface::inqVarDimId(grpid, varid, dimid);
[266]212         }
213         else
214         {
[686]215            CNetCdfInterface::inqDimIds(grpid, nbdim, NULL, 1);
[266]216            dimid = new int[nbdim]();
[686]217            CNetCdfInterface::inqDimIds(grpid, nDimNull, dimid, 1);
[266]218         }
[498]219
[266]220         for (int i = 0; i < nbdim; i++)
221         {
[498]222            std::string dimname;
[686]223            CNetCdfInterface::inqDimName(grpid, dimid[i], dimname);
[266]224            retvalue.push_back(dimname);
225         }
226         delete [] dimid;
[498]227
[686]228         return retvalue;
[266]229      }
230
[219]231      //---------------------------------------------------------------
232
[707]233      void CONetCDF4::getTimeAxisBounds(CArray<double,2>& timeAxisBounds, const StdString& name, bool collective)
234      {
235        int grpid = this->getCurrentGroup();
236        int varid = this->getVariable(name);
237
238        std::vector<StdSize> start(2), count(2);
239        start[0] = 0;
240        // Find out how many temporal records have been written already to the file we are opening
241        int ncUnlimitedDimId;
242        CNetCdfInterface::inqUnLimDim(this->ncidp, ncUnlimitedDimId);
243        CNetCdfInterface::inqDimLen(this->ncidp, ncUnlimitedDimId, count[0]);
244        start[1] = 0;
245        count[1] = 2;
246
247        timeAxisBounds.resize(count[1], count[0]);
248
249        if (this->wmpi && collective)
250          CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE);
251        if (this->wmpi && !collective)
252          CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT);
253
254        CNetCdfInterface::getVaraType(grpid, varid, &start[0], &count[0], timeAxisBounds.dataFirst());
255      }
256
[1158]257      void CONetCDF4::getTimeAxisBounds(CArray<double,2>& timeAxisBounds, const StdString& name, bool collective, size_t record)
258      {
259        int grpid = this->getCurrentGroup();
260        int varid = this->getVariable(name);
[707]261
[1158]262        std::vector<StdSize> start(2), count(2);
263        start[0] = record;
264        count[0] = 1 ;
265        start[1] = 0;
266        count[1] = 2;
267
268        timeAxisBounds.resize(2, 1);
269
270        if (this->wmpi && collective)
271          CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE);
272        if (this->wmpi && !collective)
273          CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT);
274
275        CNetCdfInterface::getVaraType(grpid, varid, &start[0], &count[0], timeAxisBounds.dataFirst());
276      }
277
278
279
[686]280      const CONetCDF4::CONetCDF4Path& CONetCDF4::getCurrentPath(void) const
281      { return this->path; }
[219]282
[686]283      void CONetCDF4::setCurrentPath(const CONetCDF4Path& path)
[219]284      { this->path = path; }
285
286      //---------------------------------------------------------------
287
[686]288      int CONetCDF4::addGroup(const StdString& name)
[219]289      {
290         int retvalue = 0;
291         int grpid = this->getCurrentGroup();
[686]292         CNetCdfInterface::defGrp(grpid, name, retvalue);
293         return retvalue;
[219]294      }
[498]295
[219]296      //---------------------------------------------------------------
[498]297
[219]298      int CONetCDF4::addDimension(const StdString& name, const StdSize size)
299      {
300         int retvalue = 0;
301         int grpid = this->getCurrentGroup();
302         if (size != UNLIMITED_DIM)
[686]303            CNetCdfInterface::defDim(grpid, name, size, retvalue);
[219]304         else
[686]305            CNetCdfInterface::defDim(grpid, name, NC_UNLIMITED, retvalue);
306         return retvalue;
[219]307      }
[498]308
[219]309      //---------------------------------------------------------------
[498]310
[686]311      int CONetCDF4::addVariable(const StdString& name, nc_type type,
[2481]312                                 const std::vector<StdString>& dim, bool defineChunking)
[219]313      {
[350]314         int varid = 0;
[219]315         std::vector<int> dimids;
[606]316         std::vector<StdSize> dimsizes;
[857]317         int dimSize = dim.size();
[2479]318
[2481]319         StdSize size;
320
[2479]321         int grpid = this->getCurrentGroup();
322
323         std::vector<StdString>::const_iterator it = dim.begin(), end = dim.end();
324
325         for (int idx = 0; it != end; it++, ++idx)
326         {
327            const StdString& dimid = *it;
328            dimids.push_back(this->getDimension(dimid));
[2481]329            CNetCdfInterface::inqDimLen(grpid, this->getDimension(dimid), size);
330            if (size == NC_UNLIMITED) size = 1;
331            dimsizes.push_back(size);
[2479]332         }
333
334         CNetCdfInterface::defVar(grpid, name, type, dimids.size(), &dimids[0], varid);
[2481]335
336         if (defineChunking) {
337           int storageType = (0 == dimSize) ? NC_CONTIGUOUS : NC_CHUNKED;
338           CNetCdfInterface::defVarChunking(grpid, varid, storageType, &dimsizes[0]);
339           CNetCdfInterface::defVarFill(grpid, varid, true, NULL);
340         }
341
[878]342         
[2479]343         return varid;
344      }
345
346      //---------------------------------------------------------------
347
348      int CONetCDF4::addChunk(CField* field, nc_type type,
349                              const std::vector<StdString>& dim, int compressionLevel)
350      {
351         const StdString& name = field->getFieldOutputName();
352         int varid = 0;
353         std::vector<StdSize> dimsizes;
354         int dimSize = dim.size();
355         
[606]356         StdSize size;
357         StdSize totalSize;
[498]358
[2479]359         // default chunk size         
360         StdSize maxSize = 1024 * 1024 * 20; // = 20 Mo (exp using large NEMO like grids)
361         StdSize targetSize = maxSize;
362         if (!field->chunking_blocksize_target.isEmpty())
363         {
364           targetSize = field->chunking_blocksize_target.getValue()*1024*1024;
365         }
366         StdSize recordSize = 1; //sizeof(type);
367         if (field->prec.isEmpty()) recordSize *= 4;
368         else recordSize *= field->prec;
369
[219]370         int grpid = this->getCurrentGroup();
[498]371
[606]372         std::vector<StdString>::const_iterator it = dim.begin(), end = dim.end();
[219]373
[878]374         for (int idx = 0; it != end; it++, ++idx)
[219]375         {
[686]376            const StdString& dimid = *it;
[606]377            CNetCdfInterface::inqDimLen(grpid, this->getDimension(dimid), size);
378            if (size == NC_UNLIMITED) size = 1;
[2479]379            recordSize *= size;
[606]380            dimsizes.push_back(size);
[219]381         }
[2479]382         double chunkingRatio = (double)recordSize / (double)targetSize;
[453]383
[2479]384         varid = this->getVariable(name);
[498]385
[517]386         // The classic NetCDF format does not support chunking nor fill parameters
387         if (!useClassicFormat)
[453]388         {
[2479]389            // Browse field's elements (domain, axis) and NetCDF meta-data to retrieve corresponding chunking coefficients
390            //   in the file order !
391            CGrid* grid = field->getGrid();
392            std::vector<CDomain*> domains = grid->getDomains();
393            std::vector<CAxis*> axis = grid->getAxis();
[2579]394            bool singleDomain = (field->getRelFile()->nbDomains == 1);
[2479]395
396            std::vector<double> userChunkingWeights; // store chunking coefficients defined by users
397            std::vector<StdString>::const_reverse_iterator itId = dim.rbegin(); // NetCDF is fed using dim, see this::addVariable()
398            int elementIdx(0);
399            int outerAxis(-1), outerDomJ(-1), outerDomI(-1);
400            for (vector<StdSize>::reverse_iterator itDim = dimsizes.rbegin(); itDim != dimsizes.rend(); ++itDim, ++itId, ++elementIdx)
[517]401            {
[2479]402              bool isAxis(false);
403              for ( auto ax : axis )
404              {
405                StdString axisDim;
406                // Rebuild axis name from axis before comparing
407                if (ax->dim_name.isEmpty()) axisDim = ax->getAxisOutputName();
408                else axisDim=ax->dim_name.getValue();
409                if (axisDim == *itId)
410                {
411                  if (!ax->chunking_weight.isEmpty()) userChunkingWeights.push_back( ax->chunking_weight.getValue() );
412                  else userChunkingWeights.push_back( 0. );
413                  isAxis = true;
414                  outerAxis = elementIdx; // Going backward in dimsizes, overwriting will keep outer
415                  break;
416                }
417              } // end scanning axis
418              bool isDomain(false);
419              for ( auto dom : domains )
420              {
421                StdString axisDim;
422                // Rebuild axis I name from domain before comparing
423                if (!dom->dim_i_name.isEmpty()) axisDim = dom->dim_i_name.getValue();
424                else
425                {
426                  if (dom->type==CDomain::type_attr::curvilinear)  axisDim="x";
427                  if (dom->type==CDomain::type_attr::unstructured) axisDim="cell";
428                  if (dom->type==CDomain::type_attr::rectilinear)  axisDim="lon";
429                }
[2579]430                if (!singleDomain) axisDim+="_"+dom->getDomainOutputName();
[2479]431                if (axisDim == *itId)
432                {
433                  if (!dom->chunking_weight_i.isEmpty()) userChunkingWeights.push_back( dom->chunking_weight_i.getValue() );
434                  else userChunkingWeights.push_back( 0. );
435                  isDomain = true;
436                  outerDomI = elementIdx; // Going backward in dimsizes, overwriting will keep outer
437                  break;
438                }
439                // Rebuild axis J name from domain before comparing
440                if (!dom->dim_j_name.isEmpty()) axisDim = dom->dim_j_name.getValue();
441                else {
442                  if (dom->type==CDomain::type_attr::curvilinear)  axisDim="y";
443                  if (dom->type==CDomain::type_attr::rectilinear)  axisDim="lat";
444                }
[2579]445                if (!singleDomain) axisDim+="_"+dom->getDomainOutputName();
[2479]446                if (axisDim == *itId)
447                {
448                  if (!dom->chunking_weight_j.isEmpty()) userChunkingWeights.push_back( dom->chunking_weight_j.getValue() );
449                  else userChunkingWeights.push_back( 0. );
450                  outerDomJ = elementIdx; // Going backward in dimsizes, overwriting will keep outer
451                  isDomain = true;
452                  break;
453                }
454              } // end scanning domain
455              // No chunking applied on scalars or time
456              if ((!isAxis)&&(!isDomain))
457              {
458                userChunkingWeights.push_back( 0. );
459              }
[517]460            }
[2479]461
462            double sumChunkingWeights(0);
463            for (int i=0;i<userChunkingWeights.size();i++) sumChunkingWeights += userChunkingWeights[i];
464            if ( (!sumChunkingWeights) && (chunkingRatio > 1) )
465            {
466              if (outerAxis!=-1) userChunkingWeights[outerAxis] = 1;      // chunk along outer axis
467              else if (outerDomJ!=-1) userChunkingWeights[outerDomJ] = 1; // if no axis ? -> along j
468              else if (outerDomI!=-1) userChunkingWeights[outerDomI] = 1; // if no j      -> along i
469              else {;}
470            }
471
472            int countChunkingDims(0); // number of dimensions on which chunking is operated : algo uses pow(value, 1/countChunkingDims)
473            double normalizingWeight(0); // use to relativize chunking coefficients for all dimensions
474            for (int i=0;i<userChunkingWeights.size();i++)
475              if (userChunkingWeights[i]>0.)
476              {
477                countChunkingDims++;
478                normalizingWeight = userChunkingWeights[i];
479              }
480
481            std::vector<double> chunkingRatioPerDims; // will store coefficients used to compute chunk size
482            double productRatios = 1; // last_coeff = pow( shrink_ratio / (product of all ratios), 1/countChunkingDims )
483            for (int i=0;i<userChunkingWeights.size();i++)
484            {
485              chunkingRatioPerDims.push_back( userChunkingWeights[i] / normalizingWeight );
486              if (chunkingRatioPerDims[i]) productRatios *= chunkingRatioPerDims[i];
487            }
488            for (int i=0;i<userChunkingWeights.size();i++)
489            {
490              chunkingRatioPerDims[i] *= pow( chunkingRatio / productRatios, 1./countChunkingDims );
491            }
492           
493            std::vector<double>::iterator itChunkingRatios = chunkingRatioPerDims.begin();
494            //itId = dim.rbegin();
495            double correctionFromPreviousDim = 1.;
496            for (vector<StdSize>::reverse_iterator itDim = dimsizes.rbegin(); itDim != dimsizes.rend(); ++itDim, ++itChunkingRatios, ++itId)
497            {
498              *itChunkingRatios *= correctionFromPreviousDim;
499              correctionFromPreviousDim = 1;
500              if (*itChunkingRatios > 1) // else target larger than size !
501              {
502                StdSize dimensionSize = *itDim;
503                //info(0) << *itId << " " << *itDim << " " << *itChunkingRatios << " " << (*itDim)/(*itChunkingRatios) << endl;
504                *itDim = ceil( *itDim / ceil(*itChunkingRatios) );
505                correctionFromPreviousDim = *itChunkingRatios/ ((double)dimensionSize/(*itDim));
506              }
507            }
[857]508            int storageType = (0 == dimSize) ? NC_CONTIGUOUS : NC_CHUNKED;
509            CNetCdfInterface::defVarChunking(grpid, varid, storageType, &dimsizes[0]);
[517]510            CNetCdfInterface::defVarFill(grpid, varid, true, NULL);
[453]511         }
[1456]512         
[606]513         return varid;
[219]514      }
515
516      //---------------------------------------------------------------
517
[2529]518      void CONetCDF4::setCompressionLevel(const StdString& varname, const StdString& compressionType, int compressionLevel, const CArray<double,1>& compressionParams)
[606]519      {
[607]520         if (compressionLevel < 0 || compressionLevel > 9)
521           ERROR("void CONetCDF4::setCompressionLevel(const StdString& varname, int compressionLevel)",
522                 "Invalid compression level for variable \"" << varname << "\", the value should range between 0 and 9.");
[2529]523#ifndef PARALLEL_COMPRESSION
524         if ( ((compressionLevel)||(compressionParams.numElements())) && wmpi)
[607]525           ERROR("void CONetCDF4::setCompressionLevel(const StdString& varname, int compressionLevel)",
526                 "Impossible to use compression for variable \"" << varname << "\" when using parallel mode.");
[2529]527#endif
[606]528         int grpid = this->getCurrentGroup();
529         int varid = this->getVariable(varname);
[2529]530         if (compressionType=="None")
531         {
532         }
533         else if (compressionType=="gzip")
534         {
535           CNetCdfInterface::defVarDeflate(grpid, varid, compressionLevel);
536         }
537         else
538         {
539           size_t cd_nelmts;
540           unsigned int* cd_values = NULL;
541           if (compressionType=="SZ")
542           {
543             CONetCDF4Plugin::interpretParametersSZ(compressionParams, &cd_nelmts, &cd_values);
544             CNetCdfInterface::defVarFilter(grpid, varid, 32017, cd_nelmts, cd_values);
545           }
[2532]546           else if (compressionType=="ZFP")
547           {
548             CONetCDF4Plugin::interpretParametersZFP(compressionParams, &cd_nelmts, &cd_values);
549             CNetCdfInterface::defVarFilter(grpid, varid, 32013, cd_nelmts, cd_values);
550           }
[2529]551           else
552           {
553               ERROR("void CONetCDF4::setCompressionLevel(...)", "compression_type = " << compressionType << " is not managed");
554           }
555           if (cd_values!=NULL) delete [] cd_values;
556         }
557                     
[606]558      }
559
560      //---------------------------------------------------------------
561
[219]562      template <>
[686]563      void CONetCDF4::addAttribute(const StdString& name, const StdString& value, const StdString* varname)
[219]564      {
565         int grpid = this->getCurrentGroup();
566         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]567         CNetCdfInterface::putAttType(grpid, varid, name, value.size(), value.c_str());
[219]568      }
[498]569
[219]570      //---------------------------------------------------------------
[498]571
[219]572      template <>
[686]573      void CONetCDF4::addAttribute(const StdString& name, const double& value, const StdString* varname)
[219]574      {
575         int grpid = this->getCurrentGroup();
576         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]577         CNetCdfInterface::putAttType(grpid, varid, name, 1, &value);
[219]578      }
[391]579
[686]580      template <>
581      void CONetCDF4::addAttribute(const StdString& name, const CArray<double,1>& value, const StdString* varname)
[391]582      {
583         int grpid = this->getCurrentGroup();
584         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]585         CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst());
[498]586      }
[219]587      //---------------------------------------------------------------
[498]588
[219]589      template <>
[686]590      void CONetCDF4::addAttribute(const StdString& name, const float& value, const StdString* varname)
[219]591      {
592         int grpid = this->getCurrentGroup();
593         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]594         CNetCdfInterface::putAttType(grpid, varid, name, 1, &value);
[219]595      }
[391]596
[686]597      template <>
598      void CONetCDF4::addAttribute(const StdString& name, const CArray<float,1>& value, const StdString* varname)
[391]599      {
600         int grpid = this->getCurrentGroup();
601         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]602         CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst());
[498]603      }
604
[219]605      //---------------------------------------------------------------
[498]606
[219]607      template <>
[686]608      void CONetCDF4::addAttribute(const StdString& name, const int& value, const StdString* varname)
[219]609      {
610         int grpid = this->getCurrentGroup();
611         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]612         CNetCdfInterface::putAttType(grpid, varid, name, 1, &value);
[219]613      }
614
[686]615      template <>
616      void CONetCDF4::addAttribute(const StdString& name, const CArray<int,1>& value, const StdString* varname)
[391]617      {
618         int grpid = this->getCurrentGroup();
619         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]620         CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst());
[498]621      }
622
[472]623      template <>
[686]624      void CONetCDF4::addAttribute(const StdString& name, const short int& value, const StdString* varname)
[472]625      {
626         int grpid = this->getCurrentGroup();
627         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]628         CNetCdfInterface::putAttType(grpid, varid, name, 1, &value);
[472]629      }
[219]630
[686]631      template <>
632      void CONetCDF4::addAttribute(const StdString& name, const CArray<short int,1>& value, const StdString* varname)
[472]633      {
634         int grpid = this->getCurrentGroup();
635         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]636         CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst());
[498]637      }
638
[472]639      template <>
[686]640      void CONetCDF4::addAttribute(const StdString& name, const long int& value, const StdString* varname)
[472]641      {
642         int grpid = this->getCurrentGroup();
643         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]644         CNetCdfInterface::putAttType(grpid, varid, name, 1, &value);
[472]645      }
646
[686]647      template <>
648      void CONetCDF4::addAttribute(const StdString& name, const CArray<long int,1>& value, const StdString* varname)
[472]649      {
650         int grpid = this->getCurrentGroup();
651         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
[686]652         CNetCdfInterface::putAttType(grpid, varid, name, value.numElements(), value.dataFirst());
[498]653      }
654
[686]655      //---------------------------------------------------------------
[498]656
[686]657      void CONetCDF4::getWriteDataInfos(const StdString& name, StdSize record, StdSize& array_size,
658                                        std::vector<StdSize>& sstart,
659                                        std::vector<StdSize>& scount,
660                                        const std::vector<StdSize>* start,
661                                        const std::vector<StdSize>* count)
[498]662      {
[266]663         std::vector<std::size_t> sizes  = this->getDimensions(name);
[857]664         if (sizes.size()==0) 
[266]665         {
[2264]666           
667            if ((start != NULL) && (count != NULL) && start->size()==1 && count->size()==1) // pur scalar case
668              array_size*=(*count)[0] ;
669            else array_size=1 ;
[266]670         }
[857]671         else
672         {
673           std::vector<std::string> iddims = this->getDimensionsIdList (&name);
674           std::vector<std::size_t>::const_iterator
675           it  = sizes.begin(), end = sizes.end();
676           int i = 0;
[219]677
[857]678           if (iddims.begin()->compare(timeCounterName) == 0)
679           {
680             sstart.push_back(record);
681             scount.push_back(1);
[2264]682             if ((start == NULL) && (count == NULL)) i++;
683             it++;
684             if (it==end)
685             {
686               if ((start != NULL) && (count != NULL) && start->size()==1 && count->size()==1) // pur scalar case
687               {
688                 scount[0]=(*count)[0] ;
689                 array_size *= (*count)[0];
690               }
691             }
[857]692           }
[2264]693           
[857]694           for (;it != end; it++)
695           {
696              if ((start != NULL) && (count != NULL))
697              {
698                 sstart.push_back((*start)[i]);
699                 scount.push_back((*count)[i]);
700                 array_size *= (*count)[i];
701                 i++;
702              }
703              else
704              {
705                 sstart.push_back(0);
706                 scount.push_back(sizes[i]);
707                 array_size *= sizes[i];
708                 i++;
709              }
710           }
711
[219]712         }
713      }
[498]714
[857]715
[219]716      template <>
[686]717      void CONetCDF4::writeData_(int grpid, int varid,
718                                 const std::vector<StdSize>& sstart,
719                                 const std::vector<StdSize>& scount, const double* data)
[219]720      {
[686]721         CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
[219]722      }
[498]723
[219]724      //---------------------------------------------------------------
[498]725
[219]726      template <>
[686]727      void CONetCDF4::writeData_(int grpid, int varid,
728                                 const std::vector<StdSize>& sstart,
[1158]729                                 const std::vector<StdSize>& scount, char* data)
730      {
731          CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
732      }
733     
734      template <>
735      void CONetCDF4::writeData_(int grpid, int varid,
736                                 const std::vector<StdSize>& sstart,
[2600]737                                 const std::vector<StdSize>& scount, const short* data)
738      {
739          CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
740      }
741   
742      template <>
743      void CONetCDF4::writeData_(int grpid, int varid,
744                                 const std::vector<StdSize>& sstart,
[686]745                                 const std::vector<StdSize>& scount, const int* data)
[219]746      {
[686]747          CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
[219]748      }
749      //---------------------------------------------------------------
[498]750
[219]751      template <>
[686]752      void CONetCDF4::writeData_(int grpid, int varid,
753                                 const std::vector<StdSize>& sstart,
[1957]754                                 const std::vector<StdSize>& scount, const size_t* data)
755      {
756          CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
757      }
758      //---------------------------------------------------------------
759
760      template <>
761      void CONetCDF4::writeData_(int grpid, int varid,
762                                 const std::vector<StdSize>& sstart,
[686]763                                 const std::vector<StdSize>& scount, const float* data)
[219]764      {
[686]765          CNetCdfInterface::putVaraType(grpid, varid, &sstart[0], &scount[0], data);
[219]766      }
767
768      //---------------------------------------------------------------
769
[686]770      void CONetCDF4::writeData(const CArray<int, 2>& data, const StdString& name)
[219]771      {
772         int grpid = this->getCurrentGroup();
773         int varid = this->getVariable(name);
[2264]774         
[219]775         StdSize array_size = 1;
776         std::vector<StdSize> sstart, scount;
777
778         this->getWriteDataInfos(name, 0, array_size,  sstart, scount, NULL, NULL);
[1158]779
[369]780         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
[1158]781
[219]782      }
783
[686]784      void CONetCDF4::writeTimeAxisData(const CArray<double, 1>& data, const StdString& name,
[413]785                                        bool collective, StdSize record, bool isRoot)
786      {
787         int grpid = this->getCurrentGroup();
788         int varid = this->getVariable(name);
[498]789
[686]790         map<int,size_t>::iterator it=timeAxis.find(varid);
791         if (it == timeAxis.end()) timeAxis[varid] = record;
[498]792         else
[413]793         {
[686]794           if (it->second >= record) return;
795           else it->second =record;
[413]796         }
[498]797
[413]798         StdSize array_size = 1;
799         std::vector<StdSize> sstart, scount;
[498]800
[413]801         if (this->wmpi && collective)
[686]802            CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE);
[413]803         if (this->wmpi && !collective)
[686]804            CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT);
[498]805
[413]806         this->getWriteDataInfos(name, record, array_size,  sstart, scount, NULL, NULL);
[1158]807         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
808       }
809
810      void CONetCDF4::writeTimeAxisDataBounds(const CArray<double, 1>& data, const StdString& name,
811                                        bool collective, StdSize record, bool isRoot)
812      {
813         int grpid = this->getCurrentGroup();
814         int varid = this->getVariable(name);
815
816         map<int,size_t>::iterator it=timeAxis.find(varid);
817         if (it == timeAxis.end()) timeAxis[varid] = record;
818         else
[686]819         {
[1158]820           if (it->second >= record) return;
821           else it->second =record;
[686]822         }
[1158]823
824         StdSize array_size = 1;
825         std::vector<StdSize> sstart, scount;
826
827         if (this->wmpi && collective)
828            CNetCdfInterface::varParAccess(grpid, varid, NC_COLLECTIVE);
829         if (this->wmpi && !collective)
830            CNetCdfInterface::varParAccess(grpid, varid, NC_INDEPENDENT);
831
832         this->getWriteDataInfos(name, record, array_size,  sstart, scount, NULL, NULL);
[413]833         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
834       }
835
[1158]836
[219]837      //---------------------------------------------------------------
[498]838
[686]839      bool CONetCDF4::varExist(const StdString& varname)
[219]840      {
841         int grpid = this->getCurrentGroup();
[686]842         return CNetCdfInterface::isVarExisted(grpid, varname);
[219]843      }
844
[878]845      bool CONetCDF4::dimExist(const StdString& dimname)
846      {
847         int grpid = this->getCurrentGroup();
848         return CNetCdfInterface::isDimExisted(grpid, dimname);
849      }
850
[286]851      void CONetCDF4::sync(void)
852      {
[686]853         CNetCdfInterface::sync(this->ncidp);
[498]854      }
[219]855      ///--------------------------------------------------------------
[337]856 } // namespace xios
Note: See TracBrowser for help on using the repository browser.