source: XIOS/dev/dev_rv/src4/xmlio/netcdf/onetcdf4.cpp @ 2348

Last change on this file since 2348 was 258, checked in by hozdoba, 13 years ago
File size: 11.5 KB
Line 
1/* ************************************************************************** *
2 *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
3 * ************************************************************************** */
4 
5// XMLIOServer headers
6#include "onetcdf4.hpp"
7#include "onetcdf4_impl.hpp"
8
9// /////////////////////////////// Définitions ////////////////////////////// //
10
11namespace xmlioserver {
12namespace io {
13
14   // ------------------------------ Constructeurs -----------------------------
15   
16   CONetCDF4::CONetCDF4(const std::string & filename, bool exist,
17                        const MPI_Comm * _comm_server)
18   {
19      if (_comm_server != NULL) this->comm_server = *_comm_server;
20      if (this->comm_server)
21      { 
22         if (exist)
23            CheckError(nc_open_par(filename.c_str(), NC_NETCDF4|NC_MPIIO,
24                        this->comm_server.get(), MPI_INFO_NULL, &this->ncidp));
25         else
26            CheckError(nc_create_par(filename.c_str(), NC_NETCDF4|NC_MPIIO,
27                        this->comm_server.get(), MPI_INFO_NULL, &this->ncidp));
28      }
29      else
30      { 
31         if (exist)
32            CheckError(nc_open(filename.c_str(), NC_NETCDF4, &this->ncidp));
33         else
34            CheckError(nc_create(filename.c_str(), NC_NETCDF4, &this->ncidp));
35      }
36   }
37
38   // ------------------------------- Destructeur ------------------------------
39   
40   CONetCDF4::~CONetCDF4(void)
41   {
42       CheckError(nc_close(this->ncidp));
43   }
44   
45   // --------------------- Vérification des erreurs NetCDF --------------------
46   
47   void CONetCDF4::CheckError(int _status) throw (CException)
48   {
49      if (_status != NC_NOERR)
50      {
51         std::string errormsg (nc_strerror(_status));           // fuite mémoire ici ?
52         XIOS_ERROR_FORMAT("CONetCDF4::CheckError(int status)", // Identifiant d'erreur
53                           "[ status = %1% ] %2%",              // Format du message d'erreur
54                           %_status % errormsg);                // Variables écrites
55      }
56   }
57   
58   // ------------------------- Début/Fin de définition ------------------------
59   
60   void CONetCDF4::definition_start(void)
61   { 
62      CheckError(nc_redef(this->ncidp));
63   }
64     
65   void CONetCDF4::definition_end(void)
66   { 
67      CheckError(nc_enddef(this->ncidp));
68   }
69   
70   // ------------------------------- Accesseurs -------------------------------
71   
72   const CONetCDF4::CNetCDF4Path & CONetCDF4::getCurrentPath(void) const
73   { 
74       return (this->path); 
75   }
76   
77   std::string CONetCDF4::getUnlimitedDimensionName(void)
78   {
79      char full_name_in[NC_MAX_NAME +1];
80      int grpid = this->getGroup(path);
81      int dimid = this->getUnlimitedDimension();
82     
83      if (dimid == -1) return (std::string());
84      CheckError(nc_inq_dimname(grpid, dimid, full_name_in));
85
86      std::string dimname(full_name_in);
87      return (dimname);
88   }
89 
90   std::vector<std::string> CONetCDF4::getDimensionsIdList (const std::string * _varname)
91   {
92      char full_name_in[NC_MAX_NAME +1];
93      int nbdim = 0, *dimid = NULL;
94      int grpid = this->getCurrentGroup();
95      int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
96      std::vector<std::string> retvalue;
97
98      if (_varname != NULL)
99      {
100         CheckError(nc_inq_varndims(grpid, varid, &nbdim));
101         dimid = new int[nbdim]();
102         CheckError(nc_inq_vardimid(grpid, varid, dimid));
103      }
104      else
105      {
106         CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
107         dimid = new int[nbdim]();
108         CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
109      }
110
111      for (int i = 0; i < nbdim; i++)
112      {
113         CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
114         std::string dimname(full_name_in);
115         retvalue.push_back(dimname);
116      }
117      delete [] dimid;
118
119      return (retvalue);
120   }
121
122   // ------------------------------- Mutateurs --------------------------------
123
124   void CONetCDF4::setCurrentPath(const CONetCDF4::CNetCDF4Path & path)
125   { 
126       this->path = path; 
127   }
128   
129   int CONetCDF4::addDimension(const std::string & _name, std::size_t _size)
130   {
131      int retvalue = 0;
132      int grpid = this->getCurrentGroup();
133      if (_size != UNLIMITED_DIM)
134         CheckError(nc_def_dim (grpid, _name.c_str(), _size, &retvalue));
135      else
136         CheckError(nc_def_dim (grpid, _name.c_str(), NC_UNLIMITED, &retvalue));
137      return (retvalue);
138   }
139   
140   int CONetCDF4::addVariable (const std::string & _name, nc_type _type,
141                               const std::vector<std::string> & _dims)
142   {
143      int retvalue = 0;
144      std::vector<int> dimids;
145      int grpid = this->getCurrentGroup();
146         
147      std::vector<std::string>::const_iterator
148         it  = _dims.begin(), end = _dims.end();
149
150      for (;it != end; it++)
151      {
152         const std::string & dimid = *it;
153         dimids.push_back(this->getDimension(dimid));
154      }
155      CheckError(nc_def_var(grpid, _name.c_str(), _type, dimids.size(), &(dimids[0]), &retvalue));
156      return (retvalue);
157   }
158   
159   int CONetCDF4::addGroup(const std::string & _name)
160   {
161      int retvalue = 0;
162      int grpid = this->getCurrentGroup();
163      CheckError(nc_def_grp(grpid, const_cast<char*>(_name.c_str()), &retvalue));
164      return (retvalue);
165   }
166   
167   // --------------------------- Accesseurs protégés --------------------------
168   
169   int CONetCDF4::getCurrentGroup(void)
170   {
171      return (this->getGroup(this->getCurrentPath()));
172   }
173   
174   int CONetCDF4::getGroup(const CNetCDF4Path & path)
175   {
176      int retvalue = this->ncidp;
177     
178      CNetCDF4Path::const_iterator
179         it  = path.begin(), end = path.end();
180
181      for (;it != end; it++)
182      {
183         const std::string & groupid = *it;
184         CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue));
185      }
186      return (retvalue);
187   }
188   
189   int CONetCDF4::getVariable(const std::string & varname)
190   {
191      int varid = 0;
192      int grpid = this->getCurrentGroup();
193      CheckError(nc_inq_varid (grpid, varname.c_str(), &varid));
194      return (varid);
195   }
196   
197   int CONetCDF4::getDimension(const std::string & dimname)
198   {
199      int dimid = 0;
200      int grpid = this->getCurrentGroup();
201      CheckError(nc_inq_dimid (grpid, dimname.c_str(), &dimid));
202      return (dimid);
203   }
204   
205   int CONetCDF4::getUnlimitedDimension(void)
206   {
207      int dimid = 0;
208      int grpid = this->getCurrentGroup();
209      CheckError(nc_inq_unlimdim (grpid, &dimid));
210      return (dimid);
211   }
212   
213   std::vector<std::size_t> CONetCDF4::getDimensions(const std::string & varname)
214   {
215      std::size_t size = 0;
216      std::vector<std::size_t> retvalue;
217      int grpid = this->getCurrentGroup();
218      int varid = this->getVariable(varname);
219      int nbdim = 0, *dimid = NULL;
220
221      CheckError(nc_inq_varndims(grpid, varid, &nbdim));
222      dimid = new int[nbdim]();
223      CheckError(nc_inq_vardimid(grpid, varid, dimid));
224
225      for (int i = 0; i < nbdim; i++)
226      {
227         CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
228         if (size == NC_UNLIMITED)
229             size = UNLIMITED_DIM;
230         retvalue.push_back(size);
231      }
232
233      return (retvalue);
234   }
235   
236   bool CONetCDF4::varExist(const std::string & _varname)
237   {
238      int varid = 0;
239      int grpid = this->getCurrentGroup();
240      return (nc_inq_varid (grpid, _varname.c_str(), &varid) == NC_NOERR);
241   }
242   
243// ----------------- Obtention des informations d'écriture ------------------
244   
245   void CONetCDF4::getWriteDataInfos(const std::string & _varname,
246                                     std::size_t   _record, 
247                                     std::size_t & _array_size,
248                                     std::vector<std::size_t> & _sstart,
249                                     std::vector<std::size_t> & _scount,
250                                     const std::vector<std::size_t> * _start,
251                                     const std::vector<std::size_t> * _count)
252   {
253      std::vector<std::size_t> sizes  = this->getDimensions(_varname);
254      std::vector<std::string> iddims = this->getDimensionsIdList (&_varname);   
255      std::vector<std::size_t>::const_iterator
256         it  = sizes.begin(), end = sizes.end();
257      int i = 0;
258     
259      if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
260      {
261         _sstart.push_back(_record);
262         _scount.push_back(1); 
263         if ((_start == NULL) &&
264             (_count == NULL)) i++;
265         it++;
266      }
267
268      for (;it != end; it++)
269      {     
270         if ((_start != NULL) && (_count != NULL))
271         {
272            _sstart.push_back((*_start)[i]);
273            _scount.push_back((*_count)[i]);
274            _array_size *= (*_count)[i];
275            i++;
276         }
277         else
278         {
279            _sstart.push_back(0);
280            _scount.push_back(sizes[i]);
281            _array_size *= sizes[i];
282            i++;
283         }
284      }
285   }
286   
287   // ------------------------- Ecriture des données --------------------------
288     
289   template <>
290      void CONetCDF4::writeData_(int _grpid, int _varid,
291                                const std::vector<std::size_t> & _sstart,
292                                const std::vector<std::size_t> & _scount,
293                                const float * _data)
294   {
295      CheckError(nc_put_vara_float(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
296   }
297   
298   template <>
299      void CONetCDF4::writeData_(int _grpid, int _varid,
300                                const std::vector<std::size_t> & _sstart,
301                                const std::vector<std::size_t> & _scount,
302                                const int * _data)
303   {
304      CheckError(nc_put_vara_int(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
305   }
306   
307   template <>
308      void CONetCDF4::writeData_(int _grpid, int _varid,
309                                const std::vector<std::size_t> & _sstart,
310                                const std::vector<std::size_t> & _scount,
311                                const double * _data)
312   {
313      CheckError(nc_put_vara_double(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
314   }
315
316   // ------------------------- Ecriture des attributs --------------------------
317
318   template <>
319      void CONetCDF4::writeAttribute_
320         (const std::string & _attname, const double * _value, std::size_t _size, int _grpid, int _varid)
321   {       
322        CheckError(nc_put_att_double(_grpid, _varid, _attname.c_str(), NC_DOUBLE, _size, _value));
323   }
324   
325   template <>
326      void CONetCDF4::writeAttribute_
327         (const std::string & _attname, const float * _value, std::size_t _size, int _grpid, int _varid)
328   {
329       CheckError(nc_put_att_float(_grpid, _varid, _attname.c_str(), NC_FLOAT, _size, _value));
330   }
331   
332   template <>
333      void CONetCDF4::writeAttribute_
334         (const std::string & _attname, const int * _value, std::size_t _size, int _grpid, int _varid)
335   {
336       CheckError(nc_put_att_int(_grpid, _varid, _attname.c_str(), NC_INT, _size, _value));
337   }
338   
339   template <>
340      void CONetCDF4::writeAttribute_
341         (const std::string & _attname, const char * _value, std::size_t _size, int _grpid, int _varid)
342   {
343       CheckError(nc_put_att_text(_grpid, _varid, _attname.c_str(), _size, _value));
344   }
345   
346   void CONetCDF4::writeAttribute
347      (const std::string & _attname, const std::string & _value, const std::string * _varname)
348   {
349      std::vector<char> chart;
350      chart.assign (_value.begin(), _value.end());
351      this->writeAttribute(_attname, chart, _varname);
352   }
353   
354} // namespace io
355} // namespace xmlioserver
Note: See TracBrowser for help on using the repository browser.