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

Last change on this file since 380 was 380, checked in by ymipsl, 12 years ago

cleaning some output

YM

File size: 14.4 KB
Line 
1#include "onetcdf4.hpp"
2#include "group_template.hpp"
3#include <mpi.h>
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
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()+1, 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      //---------------------------------------------------------------
293     
294      template <>
295         void CONetCDF4::addAttribute
296            (const StdString & name, const float & value, const StdString * varname )
297      {
298         int grpid = this->getCurrentGroup();
299         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
300         CheckError(nc_put_att_float(grpid, varid, name.c_str(), NC_FLOAT, 1, &value));
301      }
302     
303      //---------------------------------------------------------------
304     
305      template <>
306         void CONetCDF4::addAttribute
307            (const StdString & name, const int & value, const StdString * varname )
308      {
309         int grpid = this->getCurrentGroup();
310         int varid = (varname == NULL) ? NC_GLOBAL : this->getVariable(*varname);
311         CheckError(nc_put_att_int(grpid, varid, name.c_str(), NC_INT,1, &value));
312      }
313
314      //---------------------------------------------------------------
315
316      void CONetCDF4::getWriteDataInfos(const StdString & name, StdSize record, StdSize & array_size,
317                                        std::vector<StdSize> & sstart,
318                                        std::vector<StdSize> & scount,
319                                        const std::vector<StdSize> * start,
320                                        const std::vector<StdSize> * count)
321      {   
322         std::vector<std::size_t> sizes  = this->getDimensions(name);
323         std::vector<std::string> iddims = this->getDimensionsIdList (&name);   
324         std::vector<std::size_t>::const_iterator
325            it  = sizes.begin(), end = sizes.end();
326         int i = 0;
327     
328         if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
329         {
330            sstart.push_back(record);
331            scount.push_back(1); 
332            if ((start == NULL) &&
333                (count == NULL)) i++;
334            it++;
335         }
336
337         for (;it != end; it++)
338         {     
339            if ((start != NULL) && (count != NULL))
340            {
341               sstart.push_back((*start)[i]);
342               scount.push_back((*count)[i]);
343               array_size *= (*count)[i];
344               i++;
345            }
346            else
347            {
348               sstart.push_back(0);
349               scount.push_back(sizes[i]);
350               array_size *= sizes[i];
351               i++;
352            }
353         }
354         
355      }
356
357      //---------------------------------------------------------------
358
359      template <>
360         void CONetCDF4::writeData_(int grpid, int varid,
361                                    const std::vector<StdSize> & sstart,
362                                    const std::vector<StdSize> & scount, const double * data)
363      {
364         CheckError(nc_put_vara_double(grpid, varid, &(sstart[0]), &(scount[0]), data));
365//         sync() ;
366      }
367     
368      //---------------------------------------------------------------
369     
370      template <>
371         void CONetCDF4::writeData_(int grpid, int varid,
372                                    const std::vector<StdSize> & sstart,
373                                    const std::vector<StdSize> & scount, const int * data)
374      {
375          CheckError(nc_put_vara_int(grpid, varid, &(sstart[0]), &(scount[0]), data));
376//          sync() ;
377      }
378     
379      //---------------------------------------------------------------
380     
381      template <>
382         void CONetCDF4::writeData_(int grpid, int varid,
383                                    const std::vector<StdSize> & sstart,
384                                    const std::vector<StdSize> & scount, const float * data)
385      {
386          CheckError(nc_put_vara_float(grpid, varid, &(sstart[0]), &(scount[0]), data));
387//          sync() ;
388      }
389
390      //---------------------------------------------------------------
391
392      void CONetCDF4::writeData(const CArray<int, 2>& data, const StdString & name)
393      {
394         int grpid = this->getCurrentGroup();
395         int varid = this->getVariable(name);
396         StdSize array_size = 1;
397         std::vector<StdSize> sstart, scount;
398
399         this->getWriteDataInfos(name, 0, array_size,  sstart, scount, NULL, NULL);
400         this->writeData_(grpid, varid, sstart, scount, data.dataFirst());
401      }
402
403      //---------------------------------------------------------------
404     
405      bool CONetCDF4::varExist(const StdString & varname)
406      {
407         int varid = 0;
408         int grpid = this->getCurrentGroup();
409         return (nc_inq_varid (grpid, varname.c_str(), &varid) == NC_NOERR);
410      }
411
412      void CONetCDF4::sync(void)
413      {
414         CheckError(nc_sync(this->ncidp)) ;
415      } 
416      ///--------------------------------------------------------------
417 } // namespace xios
Note: See TracBrowser for help on using the repository browser.