source: XIOS/dev/XIOS_DEV_CMIP6/src/io/inetcdf4.cpp @ 1534

Last change on this file since 1534 was 1534, checked in by ymipsl, 6 years ago

Bug fix : no return value in some case for "bool CINetCDF4::isLonOrLat()" methods

YM

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