XMLIOSERVER 0.4
Serveur d'Entrées/Sorties parallèles
|
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