XMLIOSERVER 0.4
Serveur d'Entrées/Sorties parallèles
onetcdf4.cpp
Aller à la documentation de ce fichier.
00001 /* ************************************************************************** *
00002  *      Copyright © IPSL/LSCE, XMLIOServer, Avril 2010 - Octobre 2011         *
00003  * ************************************************************************** */
00004  
00005 // XMLIOServer headers
00006 #include "onetcdf4.hpp"
00007 #include "onetcdf4_impl.hpp"
00008 
00009 // /////////////////////////////// Définitions ////////////////////////////// //
00010 
00011 namespace xmlioserver {
00012 namespace io {
00013 
00014    // ------------------------------ Constructeurs -----------------------------
00015    
00016    CONetCDF4::CONetCDF4(const std::string & filename, bool exist,
00017                         const MPI_Comm * _comm_server)
00018    {
00019       if (_comm_server != NULL) this->comm_server = *_comm_server;
00020       if (this->comm_server)
00021       {  
00022          if (exist)
00023             CheckError(nc_open_par(filename.c_str(), NC_NETCDF4|NC_MPIIO,
00024                         this->comm_server.get(), MPI_INFO_NULL, &this->ncidp));
00025          else
00026             CheckError(nc_create_par(filename.c_str(), NC_NETCDF4|NC_MPIIO,
00027                         this->comm_server.get(), MPI_INFO_NULL, &this->ncidp));
00028       }
00029       else
00030       {  
00031          if (exist)
00032             CheckError(nc_open(filename.c_str(), NC_NETCDF4, &this->ncidp));
00033          else
00034             CheckError(nc_create(filename.c_str(), NC_NETCDF4, &this->ncidp));
00035       }
00036    }
00037 
00038    // ------------------------------- Destructeur ------------------------------
00039    
00040    CONetCDF4::~CONetCDF4(void)
00041    {
00042        CheckError(nc_close(this->ncidp));
00043    }
00044    
00045    // --------------------- Vérification des erreurs NetCDF --------------------
00046    
00047    void CONetCDF4::CheckError(int _status) throw (CException)
00048    {
00049       if (_status != NC_NOERR)
00050       {
00051          std::string errormsg (nc_strerror(_status)); // fuite mémoire ici ?
00052          XIOS_ERROR("CONetCDF4::CheckError(int status)",
00053               << "[ status = " << _status << " ] " << errormsg);
00054       }
00055    }
00056    
00057    // ------------------------- Début/Fin de définition ------------------------
00058    
00059    void CONetCDF4::definition_start(void)
00060    { 
00061       CheckError(nc_redef(this->ncidp));
00062    }
00063       
00064    void CONetCDF4::definition_end(void)
00065    { 
00066       CheckError(nc_enddef(this->ncidp));
00067    }
00068    
00069    // ------------------------------- Accesseurs -------------------------------
00070    
00071    const CONetCDF4::CNetCDF4Path & CONetCDF4::getCurrentPath(void) const
00072    { 
00073        return (this->path); 
00074    }
00075    
00076    std::string CONetCDF4::getUnlimitedDimensionName(void)
00077    {
00078       char full_name_in[NC_MAX_NAME +1];
00079       int grpid = this->getGroup(path);
00080       int dimid = this->getUnlimitedDimension();
00081       
00082       if (dimid == -1) return (std::string());
00083       CheckError(nc_inq_dimname(grpid, dimid, full_name_in));
00084 
00085       std::string dimname(full_name_in);
00086       return (dimname);
00087    }
00088  
00089    std::vector<std::string> CONetCDF4::getDimensionsIdList (const std::string * _varname)
00090    {
00091       char full_name_in[NC_MAX_NAME +1];
00092       int nbdim = 0, *dimid = NULL;
00093       int grpid = this->getCurrentGroup();
00094       int varid = (_varname != NULL) ? this->getVariable(*_varname) : NC_GLOBAL;
00095       std::vector<std::string> retvalue;
00096 
00097       if (_varname != NULL)
00098       {
00099          CheckError(nc_inq_varndims(grpid, varid, &nbdim));
00100          dimid = new int[nbdim]();
00101          CheckError(nc_inq_vardimid(grpid, varid, dimid));
00102       }
00103       else
00104       {
00105          CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1));
00106          dimid = new int[nbdim]();
00107          CheckError(nc_inq_dimids(grpid, NULL, dimid, 1));
00108       }
00109 
00110       for (int i = 0; i < nbdim; i++)
00111       {
00112          CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in));
00113          std::string dimname(full_name_in);
00114          retvalue.push_back(dimname);
00115       }
00116       delete [] dimid;
00117 
00118       return (retvalue);
00119    }
00120 
00121    // ------------------------------- Mutateurs --------------------------------
00122 
00123    void CONetCDF4::setCurrentPath(const CONetCDF4::CNetCDF4Path & path)
00124    { 
00125        this->path = path; 
00126    }
00127    
00128    int CONetCDF4::addDimension(const std::string & _name, std::size_t _size)
00129    {
00130       int retvalue = 0;
00131       int grpid = this->getCurrentGroup();
00132       if (_size != UNLIMITED_DIM)
00133          CheckError(nc_def_dim (grpid, _name.c_str(), _size, &retvalue));
00134       else
00135          CheckError(nc_def_dim (grpid, _name.c_str(), NC_UNLIMITED, &retvalue));
00136       return (retvalue);
00137    }
00138    
00139    int CONetCDF4::addVariable (const std::string & _name, nc_type _type,
00140                                const std::vector<std::string> & _dims)
00141    {
00142       int retvalue = 0;
00143       std::vector<int> dimids;
00144       int grpid = this->getCurrentGroup();
00145          
00146       std::vector<std::string>::const_iterator
00147          it  = _dims.begin(), end = _dims.end();
00148 
00149       for (;it != end; it++)
00150       {
00151          const std::string & dimid = *it;
00152          dimids.push_back(this->getDimension(dimid));
00153       }
00154       CheckError(nc_def_var(grpid, _name.c_str(), _type, dimids.size(), &(dimids[0]), &retvalue));
00155       return (retvalue);
00156    }
00157    
00158    int CONetCDF4::addGroup(const std::string & _name)
00159    {
00160       int retvalue = 0;
00161       int grpid = this->getCurrentGroup();
00162       CheckError(nc_def_grp(grpid, const_cast<char*>(_name.c_str()), &retvalue));
00163       return (retvalue);
00164    }
00165    
00166    // --------------------------- Accesseurs protégés --------------------------
00167    
00168    int CONetCDF4::getCurrentGroup(void)
00169    {
00170       return (this->getGroup(this->getCurrentPath()));
00171    }
00172    
00173    int CONetCDF4::getGroup(const CNetCDF4Path & path)
00174    {
00175       int retvalue = this->ncidp;
00176       
00177       CNetCDF4Path::const_iterator
00178          it  = path.begin(), end = path.end();
00179 
00180       for (;it != end; it++)
00181       {
00182          const std::string & groupid = *it;
00183          CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue));
00184       }
00185       return (retvalue);
00186    }
00187    
00188    int CONetCDF4::getVariable(const std::string & varname)
00189    {
00190       int varid = 0;
00191       int grpid = this->getCurrentGroup();
00192       CheckError(nc_inq_varid (grpid, varname.c_str(), &varid));
00193       return (varid);
00194    }
00195    
00196    int CONetCDF4::getDimension(const std::string & dimname)
00197    {
00198       int dimid = 0;
00199       int grpid = this->getCurrentGroup();
00200       CheckError(nc_inq_dimid (grpid, dimname.c_str(), &dimid));
00201       return (dimid);
00202    }
00203    
00204    int CONetCDF4::getUnlimitedDimension(void)
00205    {
00206       int dimid = 0;
00207       int grpid = this->getCurrentGroup();
00208       CheckError(nc_inq_unlimdim (grpid, &dimid));
00209       return (dimid);
00210    }
00211    
00212    std::vector<std::size_t> CONetCDF4::getDimensions(const std::string & varname)
00213    {
00214       std::size_t size = 0;
00215       std::vector<std::size_t> retvalue;
00216       int grpid = this->getCurrentGroup();
00217       int varid = this->getVariable(varname);
00218       int nbdim = 0, *dimid = NULL;
00219 
00220       CheckError(nc_inq_varndims(grpid, varid, &nbdim));
00221       dimid = new int[nbdim]();
00222       CheckError(nc_inq_vardimid(grpid, varid, dimid));
00223 
00224       for (int i = 0; i < nbdim; i++)
00225       {
00226          CheckError(nc_inq_dimlen (grpid, dimid[i], &size));
00227          if (size == NC_UNLIMITED)
00228              size = UNLIMITED_DIM;
00229          retvalue.push_back(size);
00230       }
00231 
00232       return (retvalue);
00233    }
00234    
00235    bool CONetCDF4::varExist(const std::string & _varname)
00236    {
00237       int varid = 0;
00238       int grpid = this->getCurrentGroup();
00239       return (nc_inq_varid (grpid, _varname.c_str(), &varid) == NC_NOERR);
00240    }
00241    
00242 // ----------------- Obtention des informations d'écriture ------------------
00243    
00244    void CONetCDF4::getWriteDataInfos(const std::string & _varname,
00245                                      std::size_t   _record, 
00246                                      std::size_t & _array_size,
00247                                      std::vector<std::size_t> & _sstart,
00248                                      std::vector<std::size_t> & _scount,
00249                                      const std::vector<std::size_t> * _start,
00250                                      const std::vector<std::size_t> * _count)
00251    {
00252       std::vector<std::size_t> sizes  = this->getDimensions(_varname);
00253       std::vector<std::string> iddims = this->getDimensionsIdList (&_varname);   
00254       std::vector<std::size_t>::const_iterator
00255          it  = sizes.begin(), end = sizes.end();
00256       int i = 0;
00257       
00258       if (iddims.begin()->compare(this->getUnlimitedDimensionName()) == 0)
00259       {
00260          _sstart.push_back(_record);
00261          _scount.push_back(1); 
00262          if ((_start == NULL) &&
00263              (_count == NULL)) i++;
00264          it++;
00265       }
00266 
00267       for (;it != end; it++)
00268       {      
00269          if ((_start != NULL) && (_count != NULL))
00270          {
00271             _sstart.push_back((*_start)[i]);
00272             _scount.push_back((*_count)[i]);
00273             _array_size *= (*_count)[i];
00274             i++;
00275          }
00276          else
00277          {
00278             _sstart.push_back(0);
00279             _scount.push_back(sizes[i]);
00280             _array_size *= sizes[i];
00281             i++;
00282          }
00283       }
00284    }
00285    
00286    // ------------------------- Ecriture des données --------------------------
00287      
00288    template <>
00289       void CONetCDF4::writeData_(int _grpid, int _varid,
00290                                 const std::vector<std::size_t> & _sstart,
00291                                 const std::vector<std::size_t> & _scount,
00292                                 const float * _data)
00293    {
00294       CheckError(nc_put_vara_float(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00295    }
00296    
00297    template <>
00298       void CONetCDF4::writeData_(int _grpid, int _varid,
00299                                 const std::vector<std::size_t> & _sstart,
00300                                 const std::vector<std::size_t> & _scount,
00301                                 const int * _data)
00302    {
00303       CheckError(nc_put_vara_int(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00304    }
00305    
00306    template <>
00307       void CONetCDF4::writeData_(int _grpid, int _varid,
00308                                 const std::vector<std::size_t> & _sstart,
00309                                 const std::vector<std::size_t> & _scount,
00310                                 const double * _data)
00311    {
00312       CheckError(nc_put_vara_double(_grpid, _varid, &(_sstart[0]), &(_scount[0]), _data));       
00313    }
00314 
00315    // ------------------------- Ecriture des attributs --------------------------
00316 
00317    template <>
00318       void CONetCDF4::writeAttribute_
00319          (const std::string & _attname, const double * _value, std::size_t _size, int _grpid, int _varid)
00320    {       
00321         CheckError(nc_put_att_double(_grpid, _varid, _attname.c_str(), NC_DOUBLE, _size, _value));
00322    }
00323    
00324    template <>
00325       void CONetCDF4::writeAttribute_
00326          (const std::string & _attname, const float * _value, std::size_t _size, int _grpid, int _varid)
00327    {
00328        CheckError(nc_put_att_float(_grpid, _varid, _attname.c_str(), NC_FLOAT, _size, _value));
00329    }
00330    
00331    template <>
00332       void CONetCDF4::writeAttribute_
00333          (const std::string & _attname, const int * _value, std::size_t _size, int _grpid, int _varid)
00334    {
00335        CheckError(nc_put_att_int(_grpid, _varid, _attname.c_str(), NC_INT, _size, _value));
00336    }
00337    
00338    template <>
00339       void CONetCDF4::writeAttribute_
00340          (const std::string & _attname, const char * _value, std::size_t _size, int _grpid, int _varid)
00341    {
00342        CheckError(nc_put_att_text(_grpid, _varid, _attname.c_str(), _size, _value));
00343    }
00344    
00345    void CONetCDF4::writeAttribute
00346       (const std::string & _attname, const std::string & _value, const std::string * _varname)
00347    {
00348       std::vector<char> chart;
00349       chart.assign (_value.begin(), _value.end());
00350       this->writeAttribute(_attname, chart, _varname);
00351    }
00352    
00353 } // namespace io
00354 } // namespace xmlioserver
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Définition de type Énumérations Valeurs énumérées Amis Macros