XMLIOSERVER 0.4
Serveur d'Entrées/Sorties parallèles
inetcdf4.cpp
Aller à la documentation de ce fichier.
00001 /* ************************************************************************** *
00002  *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
00003  * ************************************************************************** */
00004 
00013 // XMLIOServer headers
00014 #include "inetcdf4.hpp"
00015 #include "inetcdf4_impl.hpp"
00016 
00017 // /////////////////////////////// Définitions ////////////////////////////// //
00018 
00019 namespace xmlioserver {
00020 namespace io {
00021     
00022     
00023    // ------------------------------ Constructeurs -----------------------------
00024    
00025    CINetCDF4::CINetCDF4(const std::string & filename)
00026    {
00027       CheckError(nc_open(filename.c_str(), NC_NOWRITE, &this->ncidp));
00028    }
00029 
00030    // ------------------------------- Destructeur ------------------------------
00031    
00032    CINetCDF4::~CINetCDF4(void)
00033    {
00034        CheckError(nc_close(this->ncidp));
00035    }
00036    
00037    // --------------------- Vérification des erreurs NetCDF --------------------
00038    
00039    void CINetCDF4::CheckError(int _status) throw (CException)
00040    {
00041       if (_status != NC_NOERR)
00042       {
00043          std::string errormsg (nc_strerror(_status)); // fuite mémoire ici ?
00044          XIOS_ERROR("CONetCDF4::CheckError(int status)",
00045               << "[ status = " << _status << " ] " << errormsg);
00046       }
00047    }
00048    
00049    // --------------------------- Accesseurs protégés --------------------------
00050    
00051    int CINetCDF4::getCurrentGroup(void)
00052    {
00053       return (this->getGroup(this->getCurrentPath()));
00054    }
00055    
00056    int CINetCDF4::getGroup(const CNetCDF4Path & path)
00057    {
00058       int retvalue = this->ncidp;
00059       
00060       CNetCDF4Path::const_iterator
00061          it  = path.begin(), end = path.end();
00062 
00063       for (;it != end; it++)
00064       {
00065          const std::string & groupid = *it;
00066          CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue));
00067       }
00068       return (retvalue);
00069    }
00070    
00071    int CINetCDF4::getVariable(const std::string & varname)
00072    {
00073       int varid = 0;
00074       int grpid = this->getCurrentGroup();
00075       CheckError(nc_inq_varid (grpid, varname.c_str(), &varid));
00076       return (varid);
00077    }
00078    
00079    int CINetCDF4::getDimension(const std::string & dimname)
00080    {
00081       int dimid = 0;
00082       int grpid = this->getCurrentGroup();
00083       CheckError(nc_inq_dimid (grpid, dimname.c_str(), &dimid));
00084       return (dimid);
00085    }
00086    
00087    int CINetCDF4::getUnlimitedDimension(void)
00088    {
00089       int dimid = 0;
00090       int grpid = this->getCurrentGroup();
00091       CheckError(nc_inq_unlimdim (grpid, &dimid));
00092       return (dimid);
00093    }
00094    
00095    std::vector<std::size_t> CINetCDF4::getDimensions(const std::string & varname)
00096    {
00097       std::size_t size = 0;
00098       std::vector<std::size_t> retvalue;
00099       int grpid = this->getCurrentGroup();
00100       int varid = this->getVariable(varname);
00101       int nbdim = 0, *dimid = NULL;
00102 
00103       CheckError(nc_inq_varndims(grpid, varid, &nbdim));
00104       dimid = new int[nbdim]();
00105       CheckError(nc_inq_vardimid(grpid, varid, dimid));
00106 
00107       for (int i = 0; i < nbdim; i++)
00108       {
00109          CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
00110          if (size == NC_UNLIMITED)
00111              size = UNLIMITED_DIM;
00112          retvalue.push_back(size);
00113       }
00114 
00115       return (retvalue);
00116    }
00117    
00118    bool CINetCDF4::varExist(const std::string & _varname)
00119    {
00120       int varid = 0;
00121       int grpid = this->getCurrentGroup();
00122       return (nc_inq_varid (grpid, _varname.c_str(), &varid) == NC_NOERR);
00123    }
00124    
00125    // ------------------------------- Accesseurs -------------------------------
00126    
00127    const CINetCDF4::CNetCDF4Path & CINetCDF4::getCurrentPath(void) const
00128    { 
00129        return (this->path); 
00130    }
00131 
00132    // ------------------------------- Mutateurs --------------------------------
00133 
00134    void CINetCDF4::setCurrentPath(const CNetCDF4Path & path)
00135    { 
00136        this->path = path; 
00137    }
00138    
00139    // ----------------- Obtention des informations de lecture ------------------
00140    
00141    void CINetCDF4::getReadDataInfos(const std::string & _varname,
00142                                     std::size_t   _record, 
00143                                     std::size_t & _array_size,
00144                                     std::vector<std::size_t> & _sstart,
00145                                     std::vector<std::size_t> & _scount,
00146                                     const std::vector<std::size_t> * _start,
00147                                     const std::vector<std::size_t> * _count)
00148    {
00149       std::vector<std::size_t> sizes  = this->getDimensions(_varname);
00150       std::vector<std::string> iddims = this->getDimensionsIdList (&_varname);   
00151       std::vector<std::size_t>::const_iterator
00152          it  = sizes.begin(), end = sizes.end();
00153       int i = 0;
00154       
00155       if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
00156       {
00157          _sstart.push_back(_record);
00158          _scount.push_back(1); 
00159          if ((_start == NULL) &&
00160              (_count == NULL)) i++;
00161          it++;
00162       }
00163 
00164       for (;it != end; it++)
00165       {      
00166          if ((_start != NULL) && (_count != NULL))
00167          {
00168             _sstart.push_back((*_start)[i]);
00169             _scount.push_back((*_count)[i]);
00170             _array_size *= (*_count)[i];
00171             i++;
00172          }
00173          else
00174          {
00175             _sstart.push_back(0);
00176             _scount.push_back(sizes[i]);
00177             _array_size *= sizes[i];
00178             i++;
00179          }
00180       }
00181    }
00182    
00183    // ------------------------- Lecture des données --------------------------
00184    
00185    template <>
00186       void CINetCDF4::readData_(int _grpid, int _varid,
00187                                 const std::vector<std::size_t> & _sstart,
00188                                 const std::vector<std::size_t> & _scount,
00189                                 float * _data)
00190    {
00191       CheckError(nc_get_vara_float(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00192    }
00193    
00194    template <>
00195       void CINetCDF4::readData_(int _grpid, int _varid,
00196                                 const std::vector<std::size_t> & _sstart,
00197                                 const std::vector<std::size_t> & _scount,
00198                                 int * _data)
00199    {
00200       CheckError(nc_get_vara_int(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00201    }
00202    
00203    template <>
00204       void CINetCDF4::readData_(int _grpid, int _varid,
00205                                 const std::vector<std::size_t> & _sstart,
00206                                 const std::vector<std::size_t> & _scount,
00207                                 double * _data)
00208    {
00209       CheckError(nc_get_vara_double(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00210    }
00211 
00212    // ------------------------- Lecture des attributs --------------------------
00213    void CINetCDF4::readAttribute
00214       (const std::string & _attname, std::string & _value, const std::string * _varname)
00215    {
00216         std::vector<char> chart;
00217         this->readAttribute(_attname,chart , _varname);
00218         _value.assign(&(chart[0]), chart.size());
00219    }
00220    
00221    template <>
00222       void CINetCDF4::readAttribute_
00223          (const std::string & _attname, double * _value, int _grpid, int _varid)
00224    {       
00225         CheckError(nc_get_att_double(_grpid, _varid, _attname.c_str(), _value));
00226    }
00227    
00228    template <>
00229       void CINetCDF4::readAttribute_
00230          (const std::string & _attname, float * _value, int _grpid, int _varid)
00231    {
00232        CheckError(nc_get_att_float(_grpid, _varid, _attname.c_str(), _value));
00233    }
00234    
00235    template <>
00236       void CINetCDF4::readAttribute_
00237          (const std::string & _attname, int * _value, int _grpid, int _varid)
00238    {
00239        CheckError(nc_get_att_int(_grpid, _varid, _attname.c_str(), _value));
00240    }
00241    
00242    template <>
00243       void CINetCDF4::readAttribute_
00244          (const std::string & _attname, char * _value, int _grpid, int _varid)
00245    {
00246        CheckError(nc_get_att_text(_grpid, _varid, _attname.c_str(), _value));
00247    }
00248    
00249    // ----------------- Accesseur de parcours (d'exploration) ------------------
00250 
00251    std::vector<std::string> CINetCDF4::getAttributes(const std::string * const _varname)
00252    {
00253       int nbatt = 0;
00254       char full_name_in[NC_MAX_NAME +1];
00255       std::vector<std::string> retvalue;
00256       int grpid = this->getCurrentGroup();
00257       int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
00258 
00259       if (_varname != NULL)
00260          CheckError(nc_inq_varnatts (grpid, varid, &nbatt));
00261       else
00262          CheckError(nc_inq_natts(grpid, &nbatt));
00263 
00264       for (int i = 0; i < nbatt; i++)
00265       {
00266          CheckError(nc_inq_attname(grpid, varid, i, full_name_in));
00267          std::string attname(full_name_in);
00268          retvalue.push_back(attname);
00269       }
00270       return (retvalue);
00271    }   
00272    
00273    std::map<std::string, std::size_t> CINetCDF4::getDimensions(const std::string * const _varname)
00274    {
00275       std::size_t size = 0;
00276       char full_name_in[NC_MAX_NAME +1];
00277       int nbdim = 0, *dimid = NULL;
00278       int grpid = this->getCurrentGroup();
00279       int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
00280       std::map<std::string, std::size_t> retvalue;
00281 
00282       if (_varname != NULL)
00283       {
00284          CheckError(nc_inq_varndims(grpid, varid, &nbdim));
00285          dimid = new int[nbdim]();
00286          CheckError(nc_inq_vardimid(grpid, varid, dimid));
00287       }
00288       else
00289       {
00290          CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
00291          dimid = new int[nbdim]();
00292          CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
00293       }
00294 
00295       for (int i = 0; i < nbdim; i++)
00296       {
00297          CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
00298          CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
00299 
00300          std::string dimname(full_name_in);
00301          retvalue.insert(retvalue.end(), std::make_pair(dimname, size));
00302       }
00303       delete [] dimid;
00304 
00305       return (retvalue);
00306    }
00307    
00308    std::vector<std::string> CINetCDF4::getGroups(void)
00309    {
00310       std::size_t strlen = 0;
00311       char full_name_in[NC_MAX_NAME +1];
00312       int nbgroup = 0, *groupid = NULL;
00313       int grpid = this->getCurrentGroup();
00314       std::vector<std::string> retvalue;
00315 
00316       CheckError(nc_inq_grps(grpid, &nbgroup, NULL));
00317       groupid = new int[nbgroup]();
00318       CheckError(nc_inq_grps(grpid, NULL, groupid));
00319 
00320       for (int i = 0; i < nbgroup; i++)
00321       {
00322          CheckError(nc_inq_grpname_full(groupid[i], &strlen, full_name_in));
00323          std::string groupname(full_name_in, strlen);
00324          retvalue.push_back(groupname);
00325       }
00326 
00327       delete [] groupid;
00328       return (retvalue);
00329    }
00330    
00331    std::vector<std::string> CINetCDF4::getVariables(void)
00332    {
00333       char full_name_in[NC_MAX_NAME +1];
00334       int nbvar = 0, *varid = NULL;
00335       int grpid = this->getCurrentGroup();
00336       std::vector<std::string> retvalue;
00337 
00338       CheckError(nc_inq_varids(grpid, &nbvar, NULL));
00339       varid = new int[nbvar]();
00340       CheckError(nc_inq_varids(grpid, NULL, varid));
00341 
00342       for (int i = 0; i < nbvar; i++)
00343       {
00344          CheckError(nc_inq_varname(grpid, varid[i], full_name_in));
00345          std::string varname(full_name_in);
00346          retvalue.push_back(varname);
00347       }
00348 
00349       delete [] varid;
00350       return (retvalue);
00351    }
00352    
00353    std::size_t CINetCDF4::getNbOfTimestep(void)
00354    {
00355       int dimid = this->getUnlimitedDimension();
00356       if (dimid == -1) return (1);
00357       return (this->getDimensions(NULL)[this->getUnlimitedDimensionName()]);
00358    }
00359             
00360    std::string CINetCDF4::getUnlimitedDimensionName(void)
00361    {
00362       char full_name_in[NC_MAX_NAME +1];
00363       int grpid = this->getGroup(path);
00364       int dimid = this->getUnlimitedDimension();
00365       
00366       if (dimid == -1) return (std::string());
00367       CheckError(nc_inq_dimname(grpid, dimid, full_name_in));
00368 
00369       std::string dimname(full_name_in);
00370       return (dimname);
00371    }
00372  
00373    std::vector<std::string> CINetCDF4::getDimensionsIdList (const std::string * _varname)
00374    {
00375       char full_name_in[NC_MAX_NAME +1];
00376       int nbdim = 0, *dimid = NULL;
00377       int grpid = this->getCurrentGroup();
00378       int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
00379       std::vector<std::string> retvalue;
00380 
00381       if (_varname != NULL)
00382       {
00383          CheckError(nc_inq_varndims(grpid, varid, &nbdim));
00384          dimid = new int[nbdim]();
00385          CheckError(nc_inq_vardimid(grpid, varid, dimid));
00386       }
00387       else
00388       {
00389          CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
00390          dimid = new int[nbdim]();
00391          CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
00392       }
00393 
00394       for (int i = 0; i < nbdim; i++)
00395       {
00396          CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
00397          std::string dimname(full_name_in);
00398          retvalue.push_back(dimname);
00399       }
00400       delete [] dimid;
00401 
00402       return (retvalue);
00403    }
00404    
00405 } // namespace io
00406 } // namespace xmlioserver
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Définition de type Énumérations Valeurs énumérées Amis Macros