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

Last change on this file since 413 was 413, checked in by ymipsl, 11 years ago

Performance improvment on Lustre

YM

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