source: XMLIO_V2/dev/dev_rv/src4/xmlio/netcdf/inetcdf4.cpp @ 249

Last change on this file since 249 was 249, checked in by hozdoba, 13 years ago

Ajout d'une partie d'Interface fortran pour la version 4
Ajout des sorties netcdf4 pour la version 4

File size: 12.5 KB
Line 
1/* ************************************************************************** *
2 *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
3 * ************************************************************************** */
4
5/**
6 * \file    inetcdf4.hpp
7 * \brief   Lecture des fichiers de données au format netCDF-4 (implémentation).
8 * \author  Hervé Ozdoba
9 * \version 0.4
10 * \date    15 Juin 2011
11 */
12
13// XMLIOServer headers
14#include "inetcdf4.hpp"
15#include "inetcdf4_impl.hpp"
16
17// /////////////////////////////// Définitions ////////////////////////////// //
18
19namespace xmlioserver {
20namespace io {
21   
22   
23   // ------------------------------ Constructeurs -----------------------------
24   
25   CINetCDF4::CINetCDF4(const std::string & filename)
26   {
27      CheckError(nc_open(filename.c_str(), NC_NOWRITE, &this->ncidp));
28   }
29
30   // ------------------------------- Destructeur ------------------------------
31   
32   CINetCDF4::~CINetCDF4(void)
33   {
34       CheckError(nc_close(this->ncidp));
35   }
36   
37   // --------------------- Vérification des erreurs NetCDF --------------------
38   
39   void CINetCDF4::CheckError(int _status) throw (CException)
40   {
41      if (_status != NC_NOERR)
42      {
43         std::string errormsg (nc_strerror(_status)); // fuite mémoire ici ?
44         XIOS_ERROR("CONetCDF4::CheckError(int status)",
45              << "[ status = " << _status << " ] " << errormsg);
46      }
47   }
48   
49   // --------------------------- Accesseurs protégés --------------------------
50   
51   int CINetCDF4::getCurrentGroup(void)
52   {
53      return (this->getGroup(this->getCurrentPath()));
54   }
55   
56   int CINetCDF4::getGroup(const CNetCDF4Path & path)
57   {
58      int retvalue = this->ncidp;
59     
60      CNetCDF4Path::const_iterator
61         it  = path.begin(), end = path.end();
62
63      for (;it != end; it++)
64      {
65         const std::string & groupid = *it;
66         CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue));
67      }
68      return (retvalue);
69   }
70   
71   int CINetCDF4::getVariable(const std::string & varname)
72   {
73      int varid = 0;
74      int grpid = this->getCurrentGroup();
75      CheckError(nc_inq_varid (grpid, varname.c_str(), &varid));
76      return (varid);
77   }
78   
79   int CINetCDF4::getDimension(const std::string & dimname)
80   {
81      int dimid = 0;
82      int grpid = this->getCurrentGroup();
83      CheckError(nc_inq_dimid (grpid, dimname.c_str(), &dimid));
84      return (dimid);
85   }
86   
87   int CINetCDF4::getUnlimitedDimension(void)
88   {
89      int dimid = 0;
90      int grpid = this->getCurrentGroup();
91      CheckError(nc_inq_unlimdim (grpid, &dimid));
92      return (dimid);
93   }
94   
95   std::vector<std::size_t> CINetCDF4::getDimensions(const std::string & varname)
96   {
97      std::size_t size = 0;
98      std::vector<std::size_t> retvalue;
99      int grpid = this->getCurrentGroup();
100      int varid = this->getVariable(varname);
101      int nbdim = 0, *dimid = NULL;
102
103      CheckError(nc_inq_varndims(grpid, varid, &nbdim));
104      dimid = new int[nbdim]();
105      CheckError(nc_inq_vardimid(grpid, varid, dimid));
106
107      for (int i = 0; i < nbdim; i++)
108      {
109         CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
110         if (size == NC_UNLIMITED)
111             size = UNLIMITED_DIM;
112         retvalue.push_back(size);
113      }
114
115      return (retvalue);
116   }
117   
118   bool CINetCDF4::varExist(const std::string & _varname)
119   {
120      int varid = 0;
121      int grpid = this->getCurrentGroup();
122      return (nc_inq_varid (grpid, _varname.c_str(), &varid) == NC_NOERR);
123   }
124   
125   // ------------------------------- Accesseurs -------------------------------
126   
127   const CINetCDF4::CNetCDF4Path & CINetCDF4::getCurrentPath(void) const
128   { 
129       return (this->path); 
130   }
131
132   // ------------------------------- Mutateurs --------------------------------
133
134   void CINetCDF4::setCurrentPath(const CNetCDF4Path & path)
135   { 
136       this->path = path; 
137   }
138   
139   // ----------------- Obtention des informations de lecture ------------------
140   
141   void CINetCDF4::getReadDataInfos(const std::string & _varname,
142                                    std::size_t   _record, 
143                                    std::size_t & _array_size,
144                                    std::vector<std::size_t> & _sstart,
145                                    std::vector<std::size_t> & _scount,
146                                    const std::vector<std::size_t> * _start,
147                                    const std::vector<std::size_t> * _count)
148   {
149      std::vector<std::size_t> sizes  = this->getDimensions(_varname);
150      std::vector<std::string> iddims = this->getDimensionsIdList (&_varname);   
151      std::vector<std::size_t>::const_iterator
152         it  = sizes.begin(), end = sizes.end();
153      int i = 0;
154     
155      if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
156      {
157         _sstart.push_back(_record);
158         _scount.push_back(1); 
159         if ((_start == NULL) &&
160             (_count == NULL)) i++;
161         it++;
162      }
163
164      for (;it != end; it++)
165      {     
166         if ((_start != NULL) && (_count != NULL))
167         {
168            _sstart.push_back((*_start)[i]);
169            _scount.push_back((*_count)[i]);
170            _array_size *= (*_count)[i];
171            i++;
172         }
173         else
174         {
175            _sstart.push_back(0);
176            _scount.push_back(sizes[i]);
177            _array_size *= sizes[i];
178            i++;
179         }
180      }
181   }
182   
183   // ------------------------- Lecture des données --------------------------
184   
185   template <>
186      void CINetCDF4::readData_(int _grpid, int _varid,
187                                const std::vector<std::size_t> & _sstart,
188                                const std::vector<std::size_t> & _scount,
189                                float * _data)
190   {
191      CheckError(nc_get_vara_float(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
192   }
193   
194   template <>
195      void CINetCDF4::readData_(int _grpid, int _varid,
196                                const std::vector<std::size_t> & _sstart,
197                                const std::vector<std::size_t> & _scount,
198                                int * _data)
199   {
200      CheckError(nc_get_vara_int(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
201   }
202   
203   template <>
204      void CINetCDF4::readData_(int _grpid, int _varid,
205                                const std::vector<std::size_t> & _sstart,
206                                const std::vector<std::size_t> & _scount,
207                                double * _data)
208   {
209      CheckError(nc_get_vara_double(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
210   }
211
212   // ------------------------- Lecture des attributs --------------------------
213   void CINetCDF4::readAttribute
214      (const std::string & _attname, std::string & _value, const std::string * _varname)
215   {
216        std::vector<char> chart;
217        this->readAttribute(_attname,chart , _varname);
218        _value.assign(&(chart[0]), chart.size());
219   }
220   
221   template <>
222      void CINetCDF4::readAttribute_
223         (const std::string & _attname, double * _value, int _grpid, int _varid)
224   {       
225        CheckError(nc_get_att_double(_grpid, _varid, _attname.c_str(), _value));
226   }
227   
228   template <>
229      void CINetCDF4::readAttribute_
230         (const std::string & _attname, float * _value, int _grpid, int _varid)
231   {
232       CheckError(nc_get_att_float(_grpid, _varid, _attname.c_str(), _value));
233   }
234   
235   template <>
236      void CINetCDF4::readAttribute_
237         (const std::string & _attname, int * _value, int _grpid, int _varid)
238   {
239       CheckError(nc_get_att_int(_grpid, _varid, _attname.c_str(), _value));
240   }
241   
242   template <>
243      void CINetCDF4::readAttribute_
244         (const std::string & _attname, char * _value, int _grpid, int _varid)
245   {
246       CheckError(nc_get_att_text(_grpid, _varid, _attname.c_str(), _value));
247   }
248   
249   // ----------------- Accesseur de parcours (d'exploration) ------------------
250
251   std::vector<std::string> CINetCDF4::getAttributes(const std::string * const _varname)
252   {
253      int nbatt = 0;
254      char full_name_in[NC_MAX_NAME +1];
255      std::vector<std::string> retvalue;
256      int grpid = this->getCurrentGroup();
257      int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
258
259      if (_varname != NULL)
260         CheckError(nc_inq_varnatts (grpid, varid, &nbatt));
261      else
262         CheckError(nc_inq_natts(grpid, &nbatt));
263
264      for (int i = 0; i < nbatt; i++)
265      {
266         CheckError(nc_inq_attname(grpid, varid, i, full_name_in));
267         std::string attname(full_name_in);
268         retvalue.push_back(attname);
269      }
270      return (retvalue);
271   }   
272   
273   std::map<std::string, std::size_t> CINetCDF4::getDimensions(const std::string * const _varname)
274   {
275      std::size_t size = 0;
276      char full_name_in[NC_MAX_NAME +1];
277      int nbdim = 0, *dimid = NULL;
278      int grpid = this->getCurrentGroup();
279      int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
280      std::map<std::string, std::size_t> retvalue;
281
282      if (_varname != NULL)
283      {
284         CheckError(nc_inq_varndims(grpid, varid, &nbdim));
285         dimid = new int[nbdim]();
286         CheckError(nc_inq_vardimid(grpid, varid, dimid));
287      }
288      else
289      {
290         CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
291         dimid = new int[nbdim]();
292         CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
293      }
294
295      for (int i = 0; i < nbdim; i++)
296      {
297         CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
298         CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
299
300         std::string dimname(full_name_in);
301         retvalue.insert(retvalue.end(), std::make_pair(dimname, size));
302      }
303      delete [] dimid;
304
305      return (retvalue);
306   }
307   
308   std::vector<std::string> CINetCDF4::getGroups(void)
309   {
310      std::size_t strlen = 0;
311      char full_name_in[NC_MAX_NAME +1];
312      int nbgroup = 0, *groupid = NULL;
313      int grpid = this->getCurrentGroup();
314      std::vector<std::string> retvalue;
315
316      CheckError(nc_inq_grps(grpid, &nbgroup, NULL));
317      groupid = new int[nbgroup]();
318      CheckError(nc_inq_grps(grpid, NULL, groupid));
319
320      for (int i = 0; i < nbgroup; i++)
321      {
322         CheckError(nc_inq_grpname_full(groupid[i], &strlen, full_name_in));
323         std::string groupname(full_name_in, strlen);
324         retvalue.push_back(groupname);
325      }
326
327      delete [] groupid;
328      return (retvalue);
329   }
330   
331   std::vector<std::string> CINetCDF4::getVariables(void)
332   {
333      char full_name_in[NC_MAX_NAME +1];
334      int nbvar = 0, *varid = NULL;
335      int grpid = this->getCurrentGroup();
336      std::vector<std::string> retvalue;
337
338      CheckError(nc_inq_varids(grpid, &nbvar, NULL));
339      varid = new int[nbvar]();
340      CheckError(nc_inq_varids(grpid, NULL, varid));
341
342      for (int i = 0; i < nbvar; i++)
343      {
344         CheckError(nc_inq_varname(grpid, varid[i], full_name_in));
345         std::string varname(full_name_in);
346         retvalue.push_back(varname);
347      }
348
349      delete [] varid;
350      return (retvalue);
351   }
352   
353   std::size_t CINetCDF4::getNbOfTimestep(void)
354   {
355      int dimid = this->getUnlimitedDimension();
356      if (dimid == -1) return (1);
357      return (this->getDimensions(NULL)[this->getUnlimitedDimensionName()]);
358   }
359           
360   std::string CINetCDF4::getUnlimitedDimensionName(void)
361   {
362      char full_name_in[NC_MAX_NAME +1];
363      int grpid = this->getGroup(path);
364      int dimid = this->getUnlimitedDimension();
365     
366      if (dimid == -1) return (std::string());
367      CheckError(nc_inq_dimname(grpid, dimid, full_name_in));
368
369      std::string dimname(full_name_in);
370      return (dimname);
371   }
372 
373   std::vector<std::string> CINetCDF4::getDimensionsIdList (const std::string * _varname)
374   {
375      char full_name_in[NC_MAX_NAME +1];
376      int nbdim = 0, *dimid = NULL;
377      int grpid = this->getCurrentGroup();
378      int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
379      std::vector<std::string> retvalue;
380
381      if (_varname != NULL)
382      {
383         CheckError(nc_inq_varndims(grpid, varid, &nbdim));
384         dimid = new int[nbdim]();
385         CheckError(nc_inq_vardimid(grpid, varid, dimid));
386      }
387      else
388      {
389         CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
390         dimid = new int[nbdim]();
391         CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
392      }
393
394      for (int i = 0; i < nbdim; i++)
395      {
396         CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
397         std::string dimname(full_name_in);
398         retvalue.push_back(dimname);
399      }
400      delete [] dimid;
401
402      return (retvalue);
403   }
404   
405} // namespace io
406} // namespace xmlioserver
Note: See TracBrowser for help on using the repository browser.