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

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

Branch EP merged with Dev_cmip6 @r1490

  • 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.7 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{
[1491]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"*/)
[599]12  {
[736]13    // Don't use parallel mode if there is only one process
14    if (comm)
[599]15    {
[736]16      int commSize = 0;
[1328]17      ep_lib::MPI_Comm_size(*comm, &commSize);
[736]18      if (commSize <= 1)
19        comm = NULL;
[599]20    }
[1491]21    //mpi = comm && !multifile;
22    mpi = comm && !multifile && readMetaDataPar;
[1328]23    ep_lib::MPI_Info info_null;
[736]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)
[1362]28      CNetCdfInterface::openPar(filename, NC_NOWRITE | NC_MPIIO, *(static_cast<MPI_Comm*>(comm->mpi_comm)), *(static_cast<MPI_Info*>(info_null.mpi_info)), this->ncidp);
[1355]29      //CNetCdfInterface::openPar(filename, NC_NOWRITE | NC_MPIIO, *(static_cast<MPI_Comm*>(comm->mpi_comm)), info_null.mpi_info, this->ncidp);
[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);
[1460]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);
[1460]223    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[599]224    std::list<StdString> retvalue;
[219]225
[1460]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);
[1460]254    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[599]255    std::map<StdString, StdSize> retvalue;
[219]256
[1460]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);
[1460]289    int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL;
[219]290
[1460]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);
[1460]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
[1463]499/*
[599]500  bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path)
501  {
[1460]502    std::list<StdString> varCoords = this->getCoordinatesIdList(name, path);
[1462]503    std::list<StdString>::const_iterator it = varCoords.begin(), end = varCoords.end();
504    for (; it != end; it++)
505    {
506      const StdString& coord = *it;
507      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path))
508      {
509        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
510        if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end()))
511          continue;
512        else
513          return false;
514      }
515    }
516    return true;
517  }
[1463]518*/
[1462]519
[1463]520  bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path)
[1462]521  {
522    std::list<StdString> varCoords = this->getCoordinatesIdList(name, path);
[1460]523    std::list<StdString> varDims = this->getDimensionsList(&name, path);
524    std::list<StdString>::const_iterator it = varCoords.begin(), end = varCoords.end();
525    std::set<StdString> varDims1D;
526
527    // Firstly, loop over coordinate list
[599]528    for (; it != end; it++)
529    {
530      const StdString& coord = *it;
[1460]531      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )
[219]532      {
[1460]533        std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path);
534        for (std::map<StdString, StdSize>::const_iterator itTmp = coordDims.begin(); itTmp != coordDims.end(); itTmp++)
535        {
536          varDims.remove(itTmp->first);
537        }
538        if (this->isLonOrLat(coord, path) && coordDims.size() == 1)
539        {
540          varDims1D.insert(coordDims.begin()->first);
[599]541          continue;
[1460]542        }
[219]543      }
[599]544    }
[1460]545    // Secondly, loop over remaining dimensions
546    for (it= varDims.begin(); it != varDims.end(); it++)
547    {
548      const StdString& coord = *it;
549      std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path);
550      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )
551      {
552        if (this->isLonOrLat(coord, path) && coordDims.size() == 1)
553        {
554          varDims1D.insert(coordDims.begin()->first);
555          continue;
556        }
557      }
558    }
559
560    return (varDims1D.size() == 2);
[599]561  }
[219]562
[1463]563
[599]564  bool CINetCDF4::isCurvilinear(const StdString& name, const CVarPath* const path)
565  {
566    if (this->isRectilinear(name, path) || !this->hasCoordinates(name, path))
567      return false;
568
[782]569    bool isCurVi = true;
570    unsigned int nbLonLat = 0;
[599]571    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
572    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
573    for (; it != end; it++)
574    {
575      const StdString& coord = *it;
[1460]576      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path))
[219]577      {
[599]578        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
[782]579        if (2 == dimvar.size()) ++nbLonLat;
[219]580      }
[599]581    }
[782]582    if (2 != nbLonLat) isCurVi = false;
583
584    return isCurVi;
[599]585  }
[219]586
[599]587  bool CINetCDF4::isUnstructured(const StdString& name, const CVarPath* const path)
588  {
589    if (this->isRectilinear(name, path) ||
590        this->isCurvilinear(name, path) ||
591        !this->hasCoordinates(name, path))
592       return false;
[948]593    else return true ;
594   
595// check this part above   
[599]596    StdString dimname = this->getDimensionsList(&name, path).back();
[219]597
[599]598    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
599    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
600    for (; it != end; it++)
601    {
602      const StdString& coord = *it;
[1460]603      if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path))
[219]604      {
[599]605        std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path);
606        if ((dimvar.size() == 1) &&
607            (dimvar.find(dimname) != dimvar.end()))
608          continue;
609        else
610          return false;
611      }
612    }
[219]613
[599]614    return true;
615  }
[219]616
[599]617  bool CINetCDF4::isUnknown(const StdString& name, const CVarPath* const path)
618  {
619    return !(this->isRectilinear(name, path) || this->isCurvilinear(name, path) || this->isUnstructured(name, path));
620  }
[219]621
[599]622  bool CINetCDF4::isTemporal(const StdString& name, const CVarPath* const path)
623  {
[802]624    std::list<StdString> dims = this->getDimensionsList(&name, path);
625    return (std::find(dims.begin(), dims.end(), timeCounterName) != dims.end());
[599]626  }
[219]627
[599]628  bool CINetCDF4::is3Dim(const StdString& name, const CVarPath* const path)
629  {
630    int i = 0;
631    std::list<StdString> coords = this->getCoordinatesIdList(name, path);
632    std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
633    for (; it != end; it++)
634    {
635      const StdString& coord = *it;
636      if (this->hasVariable(coord, path))
[219]637      {
[599]638        if (this->isTemporal(coord, path))
639          continue;
640        i++;
[219]641      }
[599]642      else
[219]643      {
[782]644        StdString unlimitedDimName = this->getUnlimitedDimensionName();
645        if (coord.compare(0, unlimitedDimName.size(), unlimitedDimName) == 0)
[599]646          continue;
647        i++;
[219]648      }
[599]649    }
650    return (i == 3);
651  }
[219]652
[599]653  bool CINetCDF4::isCellGrid(const StdString& name, const CVarPath* const path)
654  {
655    if (this->isCoordinate(name, path))
656    {
[686]657      return this->hasBounds(name, path);
[599]658    }
659    else
660    {
661      std::list<StdString> coords = this->getCoordinatesIdList(name, path);
662      std::list<StdString>::const_iterator it = coords.begin(), end = coords.end();
663      for (; it != end; it++)
[219]664      {
[599]665        const StdString& coord = *it;
666        if (this->hasVariable(coord, path))
667        {
668          if (this->isTemporal(coord, path))
669            continue;
670          if (this->isCellGrid(coord, path))
671            continue;
672          return false;
673        }
674        else
675        {
[782]676          StdString unlimitedDimName = this->getUnlimitedDimensionName();
677          if (coord.compare(0, unlimitedDimName.size(), unlimitedDimName) == 0)
[599]678            continue;
679          return false;
680        }
[219]681      }
[599]682    }
[219]683
[599]684    return true;
685  }
[219]686
[599]687  //---------------------------------------------------------------
[219]688
[599]689  std::list<StdString> CINetCDF4::getDataVariables(bool _is3D,       bool _isRecti,
690                                                   bool _isCurvi,    bool _isUnstr,
691                                                   bool _isCellData, bool _isTemporal,
692                                                   const CVarPath* const path)
693  {
694    std::list<StdString> retvalue;
695    std::list<StdString> allvars  = this->getVariables(path);
696    std::set<StdString> allcoords = this->getCoordVariables(path);
[219]697
[599]698    std::list<StdString>::const_iterator it = allvars.begin(), end = allvars.end();
699    for (; it != end; it++)
700    {
701      const StdString& var = *it;
702      if (this->isCoordinate(var, path)) continue;
[219]703
[599]704      if (!_isRecti && this->isRectilinear(var, path))  continue;
705      if (!_isCurvi && this->isCurvilinear(var, path))  continue;
706      if (!_isUnstr && this->isUnstructured(var, path)) continue;
[219]707
[599]708      if (!_isTemporal && this->isTemporal(var, path)) continue;
709      if (!_is3D       && this->is3Dim(var, path))     continue;
710      if (!_isCellData && this->isCellGrid(var, path)) continue;
[219]711
[599]712      if (this->isUnknown(var, path)) continue;
[219]713
[599]714      retvalue.push_back(var);
715    }
716    return retvalue;
717  }
[219]718
[599]719  //---------------------------------------------------------------
[219]720
[599]721  void CINetCDF4::getDataInfo(const StdString& var, const CVarPath* const path, StdSize record,
722                              std::vector<StdSize>& sstart, std::vector<StdSize>& scount, StdSize& array_size,
723                              const std::vector<StdSize>* start /*= NULL*/, const std::vector<StdSize>* count /*= NULL*/)
724  {
725    std::list<StdString> dimlist = this->getDimensionsList(&var, path);
726    std::map<StdString, StdSize> dimmap = this->getDimensions(&var, path);
727    std::list<StdString>::iterator it = dimlist.begin();
728    if (this->isTemporal(var, path))
729    {
730      if (record != UNLIMITED_DIM)
731        sstart.push_back(record);
732      else
733        sstart.push_back(0);
734      scount.push_back(1);
735      it++;
736    }
737    for (int i = 0; it != dimlist.end(); it++, i++)
738    {
739      if (start && count)
[219]740      {
[599]741        sstart.push_back((*start)[i]);
742        scount.push_back((*count)[i]);
743        array_size *= (*count)[i];
[219]744      }
[599]745      else
[219]746      {
[599]747        sstart.push_back(0);
748        scount.push_back(dimmap[*it]);
749        array_size *= dimmap[*it];
[219]750      }
[599]751    }
752  }
[219]753
[686]754  template <class T>
755  void CINetCDF4::getData(CArray<T, 1>& data, const StdString& var,
[599]756                          const CVarPath* const path, StdSize record)
757  {
758    std::vector<StdSize> start, count;
759    int grpid = this->getGroup(path);
760    int varid = this->getVariable(var, path);
761    StdSize array_size = 1;
762    this->getDataInfo(var, path, record, start, count, array_size);
763    data.resize(array_size);
[686]764    CNetCdfInterface::getVaraType(grpid, varid, &start[0], &count[0], data.dataFirst());
[599]765  }
[219]766
[599]767  template <>
[686]768  void CINetCDF4::getData(CArray<int, 1>& data, const StdString& var,
769                          const CVarPath* const path, StdSize record);
770  template <>
[599]771  void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var,
[686]772                          const CVarPath* const path, StdSize record);
[599]773  template <>
774  void CINetCDF4::getData(CArray<float, 1>& data, const StdString& var,
[686]775                          const CVarPath* const path, StdSize record);
[219]776
[599]777  //---------------------------------------------------------------
778
779  StdString CINetCDF4::getLonCoordName(const StdString& varname,
780                                       const CVarPath* const path)
781  {
[825]782    StdString lonName;
[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_Longitude_units.end() != CCFConvention::XIOS_CF_Longitude_units.find(unit))
[825]792        {
793          lonName = *itList;
794          return lonName;
795        }
[782]796      }
797    }
[825]798    return lonName;
[599]799  }
800
801  StdString CINetCDF4::getLatCoordName(const StdString& varname,
802                                       const CVarPath* const path)
803  {
[825]804    StdString latName;
[782]805    std::list<StdString>::const_iterator itbList, itList, iteList;
[599]806    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
[782]807    itbList = clist.begin(); iteList = clist.end();
808    for (itList = itbList; itList != iteList; ++itList)
809    {
810      if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &(*itList), path))
811      {
812        StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &(*itList), path);
813        if (CCFConvention::XIOS_CF_Latitude_units.end() != CCFConvention::XIOS_CF_Latitude_units.find(unit))
[825]814        {
815          latName = *itList;
816          return latName;
817        }
[782]818      }
819    }
[825]820    return latName;
[599]821  }
822
823  StdString CINetCDF4::getVertCoordName(const StdString& varname,
824                                        const CVarPath* const path)
825  {
826    if (!this->is3Dim(varname, path)) return "";
827    std::list<StdString> clist = this->getCoordinatesIdList(varname, path);
828    if (this->hasCoordinates(varname, path))
[686]829      return *(++(++clist.begin()));
[599]830    else
[686]831      return *(++(++clist.rbegin()));
[599]832  }
[1460]833
834  bool CINetCDF4::isLonOrLat(const StdString& varname, const CVarPath* const path)
835  {
836  if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &varname, path))
837  {
838    StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &varname, path);
839    return (CCFConvention::XIOS_CF_Latitude_units.end() != CCFConvention::XIOS_CF_Latitude_units.find(unit)
840            || CCFConvention::XIOS_CF_Longitude_units.end() != CCFConvention::XIOS_CF_Longitude_units.find(unit));
841    }
842  }
843
[335]844} // namespace xios
Note: See TracBrowser for help on using the repository browser.