source: XIOS/dev/branch_openmp/src/io/inetcdf4.cpp @ 1538

Last change on this file since 1538 was 1538, checked in by yushan, 6 years ago

tests in XIOS OK (client, complete, remap, toy)

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