source: XIOS/dev/dev_trunk_omp/src/io/inetcdf4.cpp @ 1957

Last change on this file since 1957 was 1665, checked in by yushan, 5 years ago

MARK: branch merged with trunk @1660. Add option --omp to enable multithreading.

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