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