source: XIOS/trunk/src/input/inetcdf4.cpp @ 631

Last change on this file since 631 was 599, checked in by rlacroix, 9 years ago

Implement reading fields from NetCDF files.

  • 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: 26.5 KB
Line 
1#include "inetcdf4.hpp"
2#include "netCdfInterface.hpp"
3
4#include <boost/algorithm/string.hpp>
5
6namespace xios
7{
8  CINetCDF4::CINetCDF4(const StdString& filename, const MPI_Comm* comm /*= NULL*/, bool multifile /*= true*/)
9    : mpi(comm != NULL && !multifile)
10  {
11    if (comm != NULL)
12    {
13      if (!multifile) CNetCdfInterface::openPar(filename, NC_NOWRITE, *comm, MPI_INFO_NULL, this->ncidp);
14      else CNetCdfInterface::open(filename, NC_NOWRITE, this->ncidp);
15    }
16      else CNetCdfInterface::open(filename, NC_NOWRITE, this->ncidp);
17  }
18
19  CINetCDF4::~CINetCDF4(void)
20  { /* Nothing to do */ }
21
22  ///--------------------------------------------------------------
23
24  void CINetCDF4::CheckError(int status)
25  {
26    if (status != NC_NOERR)
27    {
28      StdString errormsg(nc_strerror(status)); // fuite mémoire ici ?
29      ERROR("CINetCDF4::CheckError(int status)",
30            << "[ status = " << status << " ] " << errormsg);
31    }
32  }
33
34  //---------------------------------------------------------------
35
36  void CINetCDF4::close(void)
37  {
38    CheckError(nc_close(this->ncidp));
39  }
40
41  //---------------------------------------------------------------
42
43  int CINetCDF4::getGroup(const CVarPath* const path)
44  {
45    int retvalue = this->ncidp;
46    if (path == NULL) return retvalue;
47    CVarPath::const_iterator it = path->begin(), end = path->end();
48
49    for (; it != end; it++)
50    {
51      const StdString& groupid = *it;
52      CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue));
53    }
54
55    return retvalue;
56  }
57
58  int CINetCDF4::getVariable(const StdString& varname,
59                             const CVarPath* const path)
60  {
61    int varid = 0;
62    int grpid = this->getGroup(path);
63    CheckError(nc_inq_varid(grpid, varname.c_str(), &varid));
64    return varid;
65  }
66
67  int CINetCDF4::getDimension(const StdString& dimname,
68                              const CVarPath* const path)
69  {
70    int dimid = 0;
71    int grpid = this->getGroup(path);
72    CheckError(nc_inq_dimid(grpid, dimname.c_str(), &dimid));
73    return dimid;
74  }
75
76  std::pair<nc_type, StdSize> CINetCDF4::getAttribute(const StdString& attname,
77                                                      const StdString* const var,
78                                                      const CVarPath* const path)
79  {
80    std::pair<nc_type, StdSize> retvalue;
81    int grpid = this->getGroup(path);
82    int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL;
83    CheckError(nc_inq_att(grpid, varid, attname.c_str(),
84                          &retvalue.first, &retvalue.second));
85    return retvalue;
86  }
87
88  int CINetCDF4::getUnlimitedDimension(const CVarPath* const path)
89  {
90    int dimid = 0;
91    int grpid = this->getGroup(path);
92    CheckError(nc_inq_unlimdim(grpid, &dimid));
93    return dimid;
94  }
95
96  StdString CINetCDF4::getUnlimitedDimensionName(const CVarPath* const path)
97  {
98    char full_name_in[NC_MAX_NAME +1];
99    int grpid = this->getGroup(path);
100    int dimid = this->getUnlimitedDimension(path);
101    CheckError(nc_inq_dimname(grpid, dimid, full_name_in));
102
103    StdString dimname(full_name_in);
104    return dimname;
105  }
106
107  //---------------------------------------------------------------
108  StdSize CINetCDF4::getNbVertex(const StdString& name,
109                                 const CVarPath* const path)
110  {
111
112    if (this->isRectilinear(name, path) ||
113       this->isCurvilinear(name, path))
114    {
115      if (this->is3Dim(name, path)) return 8;
116      else return 4;
117    }
118    if (this->isUnstructured(name, path))
119    {
120      StdString bound = this->getBoundsId
121            (this->getCoordinatesIdList(name, path).back(), path);
122      StdString dim = this->getDimensionsList(&bound, path).back();
123      return (this->getDimensions(&bound, path)[dim]);
124    }
125    return size_t(-1);
126  }
127
128  //---------------------------------------------------------------
129
130  std::list<StdString> CINetCDF4::getGroups(const CVarPath* const path)
131  {
132    StdSize strlen = 0;
133    char full_name_in[NC_MAX_NAME +1];
134    int nbgroup = 0, *groupid = NULL;
135    int grpid = this->getGroup(path);
136    std::list<StdString> retvalue;
137
138    CheckError(nc_inq_grps(grpid, &nbgroup, NULL));
139    groupid = new int[nbgroup]();
140    CheckError(nc_inq_grps(grpid, NULL, groupid));
141
142    for (int i = 0; i < nbgroup; i++)
143    {
144      CheckError(nc_inq_grpname_full(groupid[i], &strlen, full_name_in));
145      StdString groupname(full_name_in, strlen);
146      retvalue.push_back(groupname);
147    }
148
149    delete [] groupid;
150    return retvalue;
151  }
152
153  std::list<StdString> CINetCDF4::getVariables(const CVarPath* const path)
154  {
155    char full_name_in[NC_MAX_NAME +1];
156    int nbvar = 0, *varid = NULL;
157    int grpid = this->getGroup(path);
158    std::list<StdString> retvalue;
159
160    CheckError(nc_inq_varids(grpid, &nbvar, NULL));
161    varid = new int[nbvar]();
162    CheckError(nc_inq_varids(grpid, NULL, varid));
163
164    for (int i = 0; i < nbvar; i++)
165    {
166      CheckError(nc_inq_varname(grpid, varid[i], full_name_in));
167      StdString varname(full_name_in);
168      retvalue.push_back(varname);
169    }
170
171    delete [] varid;
172    return retvalue;
173  }
174
175  StdSize CINetCDF4::getNbOfTimestep(const CVarPath* const path)
176  {
177    return (this->getDimensions(NULL, path)[this->getUnlimitedDimensionName(path)]);
178  }
179
180  std::set<StdString> CINetCDF4::getBoundVariables(const CVarPath* const path)
181  {
182    std::set<StdString> retvalue;
183    std::list<StdString> variables = this->getVariables(path);
184    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
185    for (; it != end; it++)
186    {
187      const StdString& var = *it;
188      if (this->hasBounds(var, path))
189        retvalue.insert(retvalue.end(), this->getBoundsId(var, path));
190    }
191    return retvalue;
192  }
193
194  std::set<StdString> CINetCDF4::getCoordVariables(const CVarPath* const path)
195  {
196    std::set<StdString> retvalue;
197    std::list<StdString> variables = this->getVariables(path);
198    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
199    for (; it != end; it++)
200    {
201      const StdString& var = *it;
202      std::list<StdString> coords = this->getCoordinatesIdList(var, path);
203      std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
204      for (; it != end; it++)
205      {
206        const StdString& coord = *it;
207        if (this->hasVariable(coord, path))
208          retvalue.insert(retvalue.end(), coord);
209      }
210    }
211    return retvalue;
212  }
213
214  std::list<StdString> CINetCDF4::getDimensionsList(const StdString* const var, const CVarPath* const path)
215  {
216    char full_name_in[NC_MAX_NAME +1];
217    int nbdim = 0, *dimid = NULL;
218    int grpid = this->getGroup(path);
219    int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL;
220    std::list<StdString> retvalue;
221
222    if (var != NULL)
223    {
224      CheckError(nc_inq_varndims(grpid, varid, &nbdim));
225      dimid = new int[nbdim]();
226      CheckError(nc_inq_vardimid(grpid, varid, dimid));
227    }
228    else
229    {
230      CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
231      dimid = new int[nbdim]();
232      CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
233    }
234
235    for (int i = 0; i < nbdim; i++)
236    {
237      CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
238      StdString dimname(full_name_in);
239      retvalue.push_back(dimname);
240    }
241    delete [] dimid;
242
243    return retvalue;
244  }
245
246  std::map<StdString, StdSize> CINetCDF4::getDimensions(const StdString* const var, const CVarPath* const path)
247  {
248    StdSize size = 0;
249    char full_name_in[NC_MAX_NAME + 1];
250    int nbdim = 0, *dimid = NULL;
251    int grpid = this->getGroup(path);
252    int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL;
253    std::map<StdString, StdSize> retvalue;
254
255    if (var != NULL)
256    {
257      CheckError(nc_inq_varndims(grpid, varid, &nbdim));
258      dimid = new int[nbdim]();
259      CheckError(nc_inq_vardimid(grpid, varid, dimid));
260    }
261    else
262    {
263      CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
264      dimid = new int[nbdim]();
265      CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
266    }
267
268    for (int i = 0; i < nbdim; i++)
269    {
270      CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
271      CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
272
273      StdString dimname(full_name_in);
274      retvalue.insert(retvalue.end(), std::make_pair(dimname, size));
275    }
276    delete [] dimid;
277
278    return retvalue;
279  }
280
281  std::list<StdString> CINetCDF4::getAttributes(const StdString* const var, const CVarPath* const path )
282  {
283    int nbatt = 0;
284    char full_name_in[NC_MAX_NAME +1];
285    std::list<StdString> retvalue;
286    int grpid = this->getGroup(path);
287    int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL;
288
289    if (var != NULL)
290      CheckError(nc_inq_varnatts(grpid, varid, &nbatt));
291    else
292      CheckError(nc_inq_natts(grpid, &nbatt));
293
294    for (int i = 0; i < nbatt; i++)
295    {
296      CheckError(nc_inq_attname(grpid, varid, i, full_name_in));
297      StdString attname(full_name_in);
298      retvalue.push_back(attname);
299    }
300    return retvalue;
301  }
302
303  int CINetCDF4::getAttributeId(const StdString& name,
304                                const StdString* const var,
305                                const CVarPath* const path)
306  {
307    int retvalue = 0;
308    std::list<StdString> atts = this->getAttributes(var, path);
309    std::list<StdString>::const_iterator it = atts.begin(), end = atts.end();
310    for (; it != end; it++)
311    {
312      const StdString& attname = *it;
313      if (attname.compare(name) == 0)
314        return retvalue;
315      retvalue++;
316    }
317    return -1;
318  }
319
320  //---------------------------------------------------------------
321
322  bool CINetCDF4::hasMissingValue(const StdString& name,
323                                  const CVarPath* const path)
324  {
325    return (this->hasAttribute("missing_value", &name, path) ||
326          this->hasAttribute("_FillValue", &name, path));
327  }
328
329  bool CINetCDF4::hasAttribute(const StdString& name,
330                               const StdString* const var ,
331                               const CVarPath* const path)
332  {
333    std::list<StdString> atts = this->getAttributes(var, path);
334    std::list<StdString>::const_iterator it = atts.begin(), end = atts.end();
335    for (; it != end; it++)
336    {
337      const StdString& attname = *it;
338      if (attname.compare(name) == 0) return true;
339    }
340    return false;
341  }
342
343  bool CINetCDF4::hasVariable(const StdString& name,
344                              const CVarPath* const path)
345  {
346    std::list<StdString> variables = this->getVariables(path);
347    std::list<StdString>::const_iterator it = variables.begin(), end = variables.end();
348    for (; it != end; it++)
349    {
350      const StdString& varname = *it;
351      if (varname.compare(name) == 0) return true;
352    }
353    return false;
354  }
355
356  bool CINetCDF4::hasCoordinates(const StdString& name,
357                                 const CVarPath* const path)
358  {
359    return (this->hasAttribute("coordinates", &name, path));
360  }
361
362  bool CINetCDF4::hasBounds(const StdString& name,
363                            const CVarPath* const path)
364  {
365    return (this->hasAttribute("bounds", &name, path));
366  }
367
368  bool CINetCDF4::hasTemporalDim(const CVarPath* const path)
369  {
370    return (this->getUnlimitedDimension(path) != -1);
371  }
372
373  //---------------------------------------------------------------
374
375#define GET_ATTRIBUTE_VALUE(type, func_ext, type_enum)                              \
376  template <>                                                                       \
377  std::vector<type> CINetCDF4::getAttributeValue(const StdString& name,             \
378                                                 const StdString* const var,        \
379                                                 const CVarPath* const path)        \
380  {                                                                                 \
381    int grpid = this->getGroup(path);                                               \
382    int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL;          \
383    std::pair<nc_type , StdSize> attinfos = this->getAttribute(name, var, path);    \
384    std::vector<type> retvalue(attinfos.second);                                    \
385    if (attinfos.first != type_enum)                                                \
386      ERROR("CINetCDF4::getAttributeValue<double>(name, var, path",                 \
387            << "[ name : " << name                                                  \
388            << ", type requested :" << attinfos.first                               \
389            << ", type stored : " << type_enum << "]"                               \
390            << " Invalid type !");                                                  \
391    CheckError(nc_get_att_##func_ext(grpid, varid, name.c_str(), &(retvalue[0])));  \
392    return retvalue;                                                                \
393  }
394
395  GET_ATTRIBUTE_VALUE(double, double, NC_DOUBLE)
396  GET_ATTRIBUTE_VALUE(float,  float,  NC_FLOAT)
397  GET_ATTRIBUTE_VALUE(int,    int ,   NC_INT)
398  GET_ATTRIBUTE_VALUE(char,   text,   NC_CHAR)
399
400  template <>
401  StdString CINetCDF4::getAttributeValue(const StdString& name,
402                                         const StdString* const var,
403                                         const CVarPath* const path)
404  {
405    std::vector<char> chart = this->getAttributeValue<std::vector<char> >(name, var, path);
406    StdString retvalue(&(chart[0]), chart.size());
407    return retvalue;
408  }
409
410  template <>
411  int CINetCDF4::getMissingValue(const StdString& name,
412                                 const CVarPath* const path)
413  {
414    if (this->hasAttribute("missing_value", &name, path))
415      return (this->getAttributeValue<std::vector<int> >("missing_value", &name, path)[0]);
416    if (this->hasAttribute("_FillValue", &name, path))
417      return (this->getAttributeValue<std::vector<int> >("_FillValue", &name, path)[0]);
418    return 0;
419  }
420
421  template <>
422  double CINetCDF4::getMissingValue(const StdString& name,
423                                    const CVarPath* const path)
424  {
425    if (this->hasAttribute("missing_value", &name, path))
426      return (this->getAttributeValue<std::vector<double> >("missing_value", &name, path)[0]);
427    if (this->hasAttribute("_FillValue", &name, path))
428      return (this->getAttributeValue<std::vector<double> >("_FillValue", &name, path)[0]);
429    return 0;
430  }
431
432  template <>
433  float CINetCDF4::getMissingValue(const StdString& name,
434                                   const CVarPath* const path)
435  {
436    if (this->hasAttribute("missing_value", &name, path))
437      return (this->getAttributeValue<std::vector<float> >("missing_value", &name, path)[0]);
438    if (this->hasAttribute("_FillValue", &name, path))
439      return (this->getAttributeValue<std::vector<float> >("_FillValue", &name, path)[0]);
440    return 0;
441  }
442
443  //---------------------------------------------------------------
444
445  std::list<StdString> CINetCDF4::getCoordinatesIdList(const StdString& name, const CVarPath* const path)
446  {
447    std::list<StdString> retvalue;
448    StdString value = this->getCoordinatesId(name, path);
449
450    boost::split(retvalue, value, boost::is_any_of(" "));
451
452    std::list<StdString>::iterator it = retvalue.begin(), end = retvalue.end();
453    for (; it != end; it++)
454    {
455      StdString& coord = *it;
456      coord.assign(coord.data());
457    }
458    return retvalue;
459  }
460
461  StdString CINetCDF4::getCoordinatesId(const StdString& name, const CVarPath* const path)
462  {
463    StdString retvalue;
464    if (this->hasAttribute("coordinates", &name, path))
465    {
466      return (this->getAttributeValue<StdString>("coordinates", &name, path));
467    }
468    else
469    {
470      std::list<StdString> dims = this->getDimensionsList(&name, path);
471      std::list<StdString>::const_iterator it = dims.begin(), end = dims.end();
472      for (; it != end; it++)
473      {
474        const StdString& value = *it;
475        retvalue.append(value).push_back(' ');
476      }
477      retvalue.erase(retvalue.end() - 1) ;
478    }
479
480    return retvalue;
481  }
482
483  StdString CINetCDF4::getBoundsId(const StdString& name,
484                                   const CVarPath* const path)
485  {
486    StdString retvalue;
487    if (this->hasAttribute("bounds", &name, path))
488      return (this->getAttributeValue<StdString>("bounds", &name, path));
489    return retvalue;
490  }
491
492  //---------------------------------------------------------------
493
494  bool CINetCDF4::isBound(const StdString& name,
495                          const CVarPath* const path)
496  {
497    std::set<StdString> bounds = this->getBoundVariables(path);
498    return (bounds.find(name) != bounds.end());
499  }
500
501  bool CINetCDF4::isCoordinate(const StdString& name,
502                               const CVarPath* const path)
503  {
504    std::set<StdString> coords = this->getCoordVariables(path);
505    return (coords.find(name) != coords.end());
506  }
507
508  bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path)
509  {
510    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
511    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
512    for (; it != end; it++)
513    {
514      const StdString& coord = *it;
515      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path))
516      {
517        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
518        if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end()))
519          continue;
520        else
521          return false;
522      }
523    }
524    return true;
525  }
526
527  bool CINetCDF4::isCurvilinear(const StdString& name, const CVarPath* const path)
528  {
529    if (this->isRectilinear(name, path) || !this->hasCoordinates(name, path))
530      return false;
531
532    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
533    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
534    for (; it != end; it++)
535    {
536      const StdString& coord = *it;
537      if (this->hasVariable(coord, path))
538      {
539        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
540        if (dimvar.size() != 2) return false;
541      }
542      else return false;
543    }
544    return true;
545  }
546
547  bool CINetCDF4::isUnstructured(const StdString& name, const CVarPath* const path)
548  {
549    if (this->isRectilinear(name, path) ||
550        this->isCurvilinear(name, path) ||
551        !this->hasCoordinates(name, path))
552       return false;
553
554    StdString dimname = this->getDimensionsList(&name, path).back();
555
556    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
557    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
558    for (; it != end; it++)
559    {
560      const StdString& coord = *it;
561      if (this->hasVariable(coord, path))
562      {
563        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
564        if ((dimvar.size() == 1) &&
565            (dimvar.find(dimname) != dimvar.end()))
566          continue;
567        else
568          return false;
569      }
570      else return false;
571    }
572
573    return true;
574  }
575
576  bool CINetCDF4::isUnknown(const StdString& name, const CVarPath* const path)
577  {
578    return !(this->isRectilinear(name, path) || this->isCurvilinear(name, path) || this->isUnstructured(name, path));
579  }
580
581  bool CINetCDF4::isTemporal(const StdString& name, const CVarPath* const path)
582  {
583    if (!this->hasTemporalDim(path)) return false;
584    std::map<StdString, StdSize> dims = this->getDimensions(&name, path);
585    if (dims.find(this->getUnlimitedDimensionName(path)) != dims.end())
586      return true;
587    return false;
588  }
589
590  bool CINetCDF4::is3Dim(const StdString& name, const CVarPath* const path)
591  {
592    int i = 0;
593    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
594    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
595    for (; it != end; it++)
596    {
597      const StdString& coord = *it;
598      if (this->hasVariable(coord, path))
599      {
600        if (this->isTemporal(coord, path))
601          continue;
602        i++;
603      }
604      else
605      {
606        if (coord.compare(this->getUnlimitedDimensionName()) == 0)
607          continue;
608        i++;
609      }
610    }
611    return (i == 3);
612  }
613
614  bool CINetCDF4::isCellGrid(const StdString& name, const CVarPath* const path)
615  {
616    if (this->isCoordinate(name, path))
617    {
618      return (this->hasBounds(name, path));
619    }
620    else
621    {
622      std::list<StdString> coords = this->getCoordinatesIdList(name, path);
623      std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
624      for (; it != end; it++)
625      {
626        const StdString& coord = *it;
627        if (this->hasVariable(coord, path))
628        {
629          if (this->isTemporal(coord, path))
630            continue;
631          if (this->isCellGrid(coord, path))
632            continue;
633          return false;
634        }
635        else
636        {
637          if (coord.compare(this->getUnlimitedDimensionName()) == 0)
638            continue;
639          return false;
640        }
641      }
642    }
643
644    return true;
645  }
646
647  //---------------------------------------------------------------
648
649  std::list<StdString> CINetCDF4::getDataVariables(bool _is3D,       bool _isRecti,
650                                                   bool _isCurvi,    bool _isUnstr,
651                                                   bool _isCellData, bool _isTemporal,
652                                                   const CVarPath* const path)
653  {
654    std::list<StdString> retvalue;
655    std::list<StdString> allvars  = this->getVariables(path);
656    std::set<StdString> allcoords = this->getCoordVariables(path);
657
658    std::list<StdString>::const_iterator it = allvars.begin(), end = allvars.end();
659    for (; it != end; it++)
660    {
661      const StdString& var = *it;
662      if (this->isCoordinate(var, path)) continue;
663
664      if (!_isRecti && this->isRectilinear(var, path))  continue;
665      if (!_isCurvi && this->isCurvilinear(var, path))  continue;
666      if (!_isUnstr && this->isUnstructured(var, path)) continue;
667
668      if (!_isTemporal && this->isTemporal(var, path)) continue;
669      if (!_is3D       && this->is3Dim(var, path))     continue;
670      if (!_isCellData && this->isCellGrid(var, path)) continue;
671
672      if (this->isUnknown(var, path)) continue;
673
674      retvalue.push_back(var);
675    }
676    return retvalue;
677  }
678
679  //---------------------------------------------------------------
680
681  void CINetCDF4::getDataInfo(const StdString& var, const CVarPath* const path, StdSize record,
682                              std::vector<StdSize>& sstart, std::vector<StdSize>& scount, StdSize& array_size,
683                              const std::vector<StdSize>* start /*= NULL*/, const std::vector<StdSize>* count /*= NULL*/)
684  {
685    std::list<StdString> dimlist = this->getDimensionsList(&var, path);
686    std::map<StdString, StdSize> dimmap = this->getDimensions(&var, path);
687    std::list<StdString>::iterator it = dimlist.begin();
688    if (this->isTemporal(var, path))
689    {
690      if (record != UNLIMITED_DIM)
691        sstart.push_back(record);
692      else
693        sstart.push_back(0);
694      scount.push_back(1);
695      it++;
696    }
697    for (int i = 0; it != dimlist.end(); it++, i++)
698    {
699      if (start && count)
700      {
701        sstart.push_back((*start)[i]);
702        scount.push_back((*count)[i]);
703        array_size *= (*count)[i];
704      }
705      else
706      {
707        sstart.push_back(0);
708        scount.push_back(dimmap[*it]);
709        array_size *= dimmap[*it];
710      }
711    }
712  }
713
714  template <>
715  void CINetCDF4::getData(CArray<int, 1>& data, const StdString& var,
716                          const CVarPath* const path, StdSize record)
717  {
718
719    std::vector<StdSize> start, count;
720    int grpid = this->getGroup(path);
721    int varid = this->getVariable(var, path);
722    StdSize array_size = 1;
723    this->getDataInfo(var, path, record, start, count, array_size);
724    data.resize(array_size);
725    CheckError(nc_get_vara_int(grpid, varid, &(start[0]), &(count[0]), data.dataFirst()));
726  }
727
728  template <>
729  void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var,
730                          const CVarPath* const path, StdSize record)
731  {
732    std::vector<StdSize> start, count;
733    int grpid = this->getGroup(path);
734    int varid = this->getVariable(var, path);
735    StdSize array_size = 1;
736    this->getDataInfo(var, path, record, start, count, array_size);
737    data.resize(array_size);
738    CheckError(nc_get_vara_double(grpid, varid, &(start[0]), &(count[0]), data.dataFirst()));
739  }
740
741  template <>
742  void CINetCDF4::getData(CArray<float, 1>& data, const StdString& var,
743                          const CVarPath* const path, StdSize record)
744  {
745    std::vector<StdSize> start, count;
746    int grpid = this->getGroup(path);
747    int varid = this->getVariable(var, path);
748    StdSize array_size = 1;
749    this->getDataInfo(var, path, record, start, count, array_size);
750    data.resize(array_size);
751    CheckError(nc_get_vara_float(grpid, varid, &(start[0]), &(count[0]), data.dataFirst()));
752  }
753
754  template <>
755  void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var,
756                          bool collective, StdSize record,
757                          const std::vector<StdSize>* start /*= NULL*/,
758                          const std::vector<StdSize>* count /*= NULL*/)
759  {
760    int varid = this->getVariable(var);
761
762    if (this->mpi && collective)
763      CNetCdfInterface::varParAccess(ncidp, varid, NC_COLLECTIVE);
764    if (this->mpi && !collective)
765      CNetCdfInterface::varParAccess(ncidp, varid, NC_INDEPENDENT);
766
767    std::vector<StdSize> sstart, scount;
768    StdSize array_size = 1;
769    this->getDataInfo(var, NULL, record, sstart, scount, array_size, start, count);
770
771    if (data.numElements() != array_size)
772    {
773      ERROR("CONetCDF4::getData(...)",
774            << "[ Array size = " << data.numElements()
775            << ", Data size = "  << array_size
776            << " ] Invalid array size");
777    }
778
779    CheckError(nc_get_vara_double(ncidp, varid, &(sstart[0]), &(scount[0]), data.dataFirst()));
780  }
781
782  //---------------------------------------------------------------
783
784  StdString CINetCDF4::getLonCoordName(const StdString& varname,
785                                       const CVarPath* const path)
786  {
787    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
788    if (this->hasCoordinates(varname, path))
789      return (*clist.begin());
790    else
791      return (*clist.rbegin());
792  }
793
794  StdString CINetCDF4::getLatCoordName(const StdString& varname,
795                                       const CVarPath* const path)
796  {
797    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
798    if (this->hasCoordinates(varname, path))
799      return (*(++clist.begin()));
800    else
801      return (*(++clist.rbegin()));
802  }
803
804  StdString CINetCDF4::getVertCoordName(const StdString& varname,
805                                        const CVarPath* const path)
806  {
807    if (!this->is3Dim(varname, path)) return "";
808    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
809    if (this->hasCoordinates(varname, path))
810      return (*(++(++clist.begin())));
811    else
812      return (*(++(++clist.rbegin())));
813  }
814} // namespace xios
Note: See TracBrowser for help on using the repository browser.