Changeset 599
- Timestamp:
- 05/26/15 16:13:48 (9 years ago)
- Location:
- XIOS/trunk/src
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/trunk/src/input/inetcdf4.cpp
r501 r599 1 1 #include "inetcdf4.hpp" 2 #include "netCdfInterface.hpp" 2 3 3 4 #include <boost/algorithm/string.hpp> … … 5 6 namespace xios 6 7 { 7 /// ////////////////////// Définitions ////////////////////// /// 8 CINetCDF4::CINetCDF4(const StdString & filename) 9 { 10 CheckError(nc_open(filename.c_str(), NC_NOWRITE, &this->ncidp)); 11 } 12 13 CINetCDF4::~CINetCDF4(void) 14 { 15 CheckError(nc_close(this->ncidp)); 16 } 17 18 ///-------------------------------------------------------------- 19 20 void CINetCDF4::CheckError(int status) 21 { 22 if (status != NC_NOERR) 23 { 24 StdString errormsg (nc_strerror(status)); // fuite mémoire ici ? 25 ERROR("CINetCDF4::CheckError(int status)", 26 << "[ status = " << status << " ] " << errormsg); 27 } 28 } 29 30 //--------------------------------------------------------------- 31 32 int CINetCDF4::getGroup(const CVarPath * const path) 33 { 34 int retvalue = this->ncidp; 35 if (path == NULL) return (retvalue); 36 CVarPath::const_iterator it = path->begin(), end = path->end(); 37 38 for (; it != end; it++) 39 { 40 const StdString & groupid = *it; 41 CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue)); 42 } 43 44 return (retvalue); 45 } 46 47 int CINetCDF4::getVariable(const StdString & varname, 48 const CVarPath * const path) 49 { 50 int varid = 0; 51 int grpid = this->getGroup(path); 52 CheckError(nc_inq_varid (grpid, varname.c_str(), &varid)); 53 return (varid); 54 } 55 56 int CINetCDF4::getDimension(const StdString & dimname, 57 const CVarPath * const path) 58 { 59 int dimid = 0; 60 int grpid = this->getGroup(path); 61 CheckError(nc_inq_dimid (grpid, dimname.c_str(), &dimid)); 62 return (dimid); 63 } 64 65 std::pair<nc_type, StdSize> CINetCDF4::getAttribute 66 (const StdString & attname, 67 const StdString * const var, 68 const CVarPath * const path) 69 { 70 std::pair<nc_type, StdSize> retvalue; 71 int grpid = this->getGroup(path); 72 int varid = (var != NULL) 73 ? this->getVariable(*var, path) : NC_GLOBAL; 74 CheckError(nc_inq_att(grpid, varid, attname.c_str(), 75 &retvalue.first, &retvalue.second)); 76 return (retvalue); 77 } 78 79 int CINetCDF4::getUnlimitedDimension(const CVarPath * const path) 80 { 81 int dimid = 0; 82 int grpid = this->getGroup(path); 83 CheckError(nc_inq_unlimdim (grpid, &dimid)); 84 return (dimid); 85 } 86 87 StdString CINetCDF4::getUnlimitedDimensionName(const CVarPath * const path) 88 { 89 char full_name_in[NC_MAX_NAME +1]; 90 int grpid = this->getGroup(path); 91 int dimid = this->getUnlimitedDimension(path); 92 CheckError(nc_inq_dimname(grpid, dimid, full_name_in)); 93 94 StdString dimname(full_name_in); 95 return (dimname); 96 } 97 98 //--------------------------------------------------------------- 99 StdSize CINetCDF4::getNbVertex(const StdString & name, 100 const CVarPath * const path) 101 { 102 103 if (this->isRectilinear(name, path) || 104 this->isCurvilinear(name, path)) 105 { 106 if (this->is3Dim(name, path)) return (8); 107 else return (4); 108 } 109 if (this->isUnstructured(name, path)) 110 { 111 StdString bound = this->getBoundsId 112 (this->getCoordinatesIdList(name, path).back(), path); 113 StdString dim = this->getDimensionsList(&bound, path).back(); 114 return (this->getDimensions(&bound, path)[dim]); 115 } 116 return ((size_t)(-1)); 117 } 118 119 //--------------------------------------------------------------- 120 121 std::list<StdString> CINetCDF4::getGroups(const CVarPath * const path) 122 { 123 StdSize strlen = 0; 124 char full_name_in[NC_MAX_NAME +1]; 125 int nbgroup = 0, *groupid = NULL; 126 int grpid = this->getGroup(path); 127 std::list<StdString> retvalue; 128 129 CheckError(nc_inq_grps(grpid, &nbgroup, NULL)); 130 groupid = new int[nbgroup](); 131 CheckError(nc_inq_grps(grpid, NULL, groupid)); 132 133 for (int i = 0; i < nbgroup; i++) 134 { 135 CheckError(nc_inq_grpname_full(groupid[i], &strlen, full_name_in)); 136 StdString groupname(full_name_in, strlen); 137 retvalue.push_back(groupname); 138 } 139 140 delete [] groupid; 141 return (retvalue); 142 } 143 144 std::list<StdString> CINetCDF4::getVariables(const CVarPath * const path) 145 { 146 char full_name_in[NC_MAX_NAME +1]; 147 int nbvar = 0, *varid = NULL; 148 int grpid = this->getGroup(path); 149 std::list<StdString> retvalue; 150 151 CheckError(nc_inq_varids(grpid, &nbvar, NULL)); 152 varid = new int[nbvar](); 153 CheckError(nc_inq_varids(grpid, NULL, varid)); 154 155 for (int i = 0; i < nbvar; i++) 156 { 157 CheckError(nc_inq_varname(grpid, varid[i], full_name_in)); 158 StdString varname(full_name_in); 159 retvalue.push_back(varname); 160 } 161 162 delete [] varid; 163 return (retvalue); 164 } 165 166 StdSize CINetCDF4::getNbOfTimestep(const CVarPath * const path) 167 { 168 return (this->getDimensions(NULL, path)[this->getUnlimitedDimensionName(path)]); 169 } 170 171 std::set<StdString> CINetCDF4::getBoundVariables(const CVarPath * const path) 172 { 173 std::set<StdString> retvalue; 174 std::list<StdString> variables = this->getVariables(path); 175 std::list<StdString>::const_iterator it = variables.begin(), end = variables.end(); 176 for (; it != end; it++) 177 { 178 const StdString & var = *it; 179 if (this->hasBounds(var, path)) 180 retvalue.insert(retvalue.end(), this->getBoundsId(var, path)); 181 } 182 return (retvalue); 183 } 184 185 std::set<StdString> CINetCDF4::getCoordVariables(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 std::list<StdString> coords = this->getCoordinatesIdList(var, path); 194 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 195 for (; it != end; it++) 196 { 197 const StdString & coord = *it; 198 if (this->hasVariable(coord, path)) 199 retvalue.insert(retvalue.end(), coord); 200 } 201 } 202 return (retvalue); 203 } 204 205 std::list<StdString> CINetCDF4::getDimensionsList 206 (const StdString * const var, const CVarPath * const path) 207 { 208 char full_name_in[NC_MAX_NAME +1]; 209 int nbdim = 0, *dimid = NULL; 210 int grpid = this->getGroup(path); 211 int varid = (var != NULL) 212 ? this->getVariable(*var, path) : NC_GLOBAL; 213 std::list<StdString> retvalue; 214 215 if (var != NULL) 216 { 217 CheckError(nc_inq_varndims(grpid, varid, &nbdim)); 218 dimid = new int[nbdim](); 219 CheckError(nc_inq_vardimid(grpid, varid, dimid)); 220 } 221 else 222 { 223 CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1)); 224 dimid = new int[nbdim](); 225 CheckError(nc_inq_dimids(grpid, NULL, dimid, 1)); 226 } 227 228 for (int i = 0; i < nbdim; i++) 229 { 230 CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in)); 231 StdString dimname(full_name_in); 232 retvalue.push_back(dimname); 233 } 234 delete [] dimid; 235 236 return (retvalue); 237 } 238 239 std::map<StdString, StdSize> CINetCDF4::getDimensions 240 (const StdString * const var, const CVarPath * const path) 241 { 242 StdSize size = 0; 243 char full_name_in[NC_MAX_NAME +1]; 244 int nbdim = 0, *dimid = NULL; 245 int grpid = this->getGroup(path); 246 int varid = (var != NULL) 247 ? this->getVariable(*var, path) : NC_GLOBAL; 248 std::map<StdString, StdSize> retvalue; 249 250 if (var != NULL) 251 { 252 CheckError(nc_inq_varndims(grpid, varid, &nbdim)); 253 dimid = new int[nbdim](); 254 CheckError(nc_inq_vardimid(grpid, varid, dimid)); 255 } 256 else 257 { 258 CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1)); 259 dimid = new int[nbdim](); 260 CheckError(nc_inq_dimids(grpid, NULL, dimid, 1)); 261 } 262 263 for (int i = 0; i < nbdim; i++) 264 { 265 CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in)); 266 CheckError(nc_inq_dimlen (grpid, dimid[i], &size)); 267 268 StdString dimname(full_name_in); 269 retvalue.insert(retvalue.end(), std::make_pair(dimname, size)); 270 } 271 delete [] dimid; 272 273 return (retvalue); 274 } 275 276 std::list<StdString> CINetCDF4::getAttributes 277 (const StdString * const var, const CVarPath * const path ) 278 { 279 int nbatt = 0; 280 char full_name_in[NC_MAX_NAME +1]; 281 std::list<StdString> retvalue; 282 int grpid = this->getGroup(path); 283 int varid = (var != NULL) 284 ? this->getVariable(*var, path) : NC_GLOBAL; 285 286 if (var != NULL) 287 CheckError(nc_inq_varnatts (grpid, varid, &nbatt)); 288 else 289 CheckError(nc_inq_natts(grpid, &nbatt)); 290 291 for (int i = 0; i < nbatt; i++) 292 { 293 CheckError(nc_inq_attname(grpid, varid, i, full_name_in)); 294 StdString attname(full_name_in); 295 retvalue.push_back(attname); 296 } 297 return (retvalue); 298 } 299 300 int CINetCDF4::getAttributeId(const StdString & name, 301 const StdString * const var, 302 const CVarPath * const path) 303 { 304 int retvalue = 0; 305 std::list<StdString> atts = this->getAttributes(var, path); 306 std::list<StdString>::const_iterator it = atts.begin(), end = atts.end(); 307 for (; it != end; it++) 308 { 309 const StdString & attname = *it; 310 if (attname.compare(name) == 0) 311 return (retvalue); 312 retvalue++; 313 } 314 return (-1); 315 } 316 317 //--------------------------------------------------------------- 318 319 bool CINetCDF4::hasMissingValue(const StdString & name, 320 const CVarPath * const path) 321 { 322 return (this->hasAttribute("missing_value", &name, path) || 323 this->hasAttribute("_FillValue", &name, path)); 324 } 325 326 bool CINetCDF4::hasAttribute(const StdString & name, 327 const StdString * const var , 328 const CVarPath * const path) 329 { 330 std::list<StdString> atts = this->getAttributes(var, path); 331 std::list<StdString>::const_iterator it = atts.begin(), end = atts.end(); 332 for (; it != end; it++) 333 { 334 const StdString & attname = *it; 335 if (attname.compare(name) == 0) return (true); 336 } 337 return (false); 338 } 339 340 bool CINetCDF4::hasVariable(const StdString & name, 341 const CVarPath * const path) 342 { 343 std::list<StdString> variables = this->getVariables(path); 344 std::list<StdString>::const_iterator it = variables.begin(), end = variables.end(); 345 for (; it != end; it++) 346 { 347 const StdString & varname = *it; 348 if (varname.compare(name) == 0) return (true); 349 } 350 return (false); 351 } 352 353 bool CINetCDF4::hasCoordinates(const StdString & name, 354 const CVarPath * const path) 355 { 356 return (this->hasAttribute("coordinates", &name, path)); 357 } 358 359 bool CINetCDF4::hasBounds(const StdString & name, 360 const CVarPath * const path) 361 { 362 return (this->hasAttribute("bounds", &name, path)); 363 } 364 365 bool CINetCDF4::hasTemporalDim(const CVarPath * const path) 366 { 367 return (this->getUnlimitedDimension(path) != -1); 368 } 369 370 //--------------------------------------------------------------- 371 372 #define GET_ATTRIBUTE_VALUE(type, func_ext, type_enum) \ 373 template <> \ 374 std::vector<type> CINetCDF4::getAttributeValue \ 375 (const StdString & name, const StdString * const var, \ 376 const CVarPath * const path) \ 377 { \ 378 int grpid = this->getGroup(path); \ 379 int varid = (var != NULL) \ 380 ? this->getVariable(*var, path) : NC_GLOBAL; \ 381 std::pair<nc_type , StdSize> attinfos = \ 382 this->getAttribute(name, var, path); \ 383 std::vector<type> retvalue(attinfos.second); \ 384 if (attinfos.first != type_enum) \ 385 ERROR("CINetCDF4::getAttributeValue<double>(name, var, path", \ 386 << "[ name : " << name \ 387 << ", type requested :" << attinfos.first \ 388 << ", type stored : " << type_enum << "]" \ 389 << " Invalid type !"); \ 390 CheckError(nc_get_att_##func_ext \ 391 (grpid, varid, name.c_str(), &(retvalue[0]))); \ 392 return (retvalue); \ 393 } 394 395 GET_ATTRIBUTE_VALUE(double, double, NC_DOUBLE) 396 GET_ATTRIBUTE_VALUE(float , float , NC_FLOAT) 397 GET_ATTRIBUTE_VALUE(int , int , NC_INT) 398 GET_ATTRIBUTE_VALUE(char , text , NC_CHAR) 399 400 template <> 401 StdString CINetCDF4::getAttributeValue 402 (const StdString & name, const StdString * const var, 403 const CVarPath * const path) 404 { 405 std::vector<char> chart = this->getAttributeValue 406 <std::vector<char> >(name, var, path); 407 StdString retvalue(&(chart[0]), chart.size()); 408 return (retvalue); 409 } 410 411 template <> 412 int CINetCDF4::getMissingValue(const StdString & name, 413 const CVarPath * const path) 414 { 415 if (this->hasAttribute("missing_value", &name, path)) 416 return (this->getAttributeValue<std::vector<int> >("missing_value", &name, path)[0]); 417 if (this->hasAttribute("_FillValue", &name, path)) 418 return (this->getAttributeValue<std::vector<int> >("_FillValue", &name, path)[0]); 419 return (0); 420 } 421 422 template <> 423 double CINetCDF4::getMissingValue(const StdString & name, 424 const CVarPath * const path) 425 { 426 if (this->hasAttribute("missing_value", &name, path)) 427 return (this->getAttributeValue<std::vector<double> >("missing_value", &name, path)[0]); 428 if (this->hasAttribute("_FillValue", &name, path)) 429 return (this->getAttributeValue<std::vector<double> >("_FillValue", &name, path)[0]); 430 return (0); 431 } 432 433 template <> 434 float CINetCDF4::getMissingValue(const StdString & name, 435 const CVarPath * const path) 436 { 437 if (this->hasAttribute("missing_value", &name, path)) 438 return (this->getAttributeValue<std::vector<float> >("missing_value", &name, path)[0]); 439 if (this->hasAttribute("_FillValue", &name, path)) 440 return (this->getAttributeValue<std::vector<float> >("_FillValue", &name, path)[0]); 441 return (0); 442 } 443 444 //--------------------------------------------------------------- 445 446 std::list<StdString> CINetCDF4::getCoordinatesIdList 447 (const StdString & name, const CVarPath * const path) 448 { 449 std::list<StdString> retvalue; 450 StdString value = this->getCoordinatesId(name, path); 451 452 boost::split(retvalue, value, boost::is_any_of(" ")); 453 454 std::list<StdString>::iterator it = retvalue.begin(), end = retvalue.end(); 455 for (; it != end; it++) 456 { 457 StdString & coord = *it; 458 coord.assign(coord.data()); 459 } 460 return (retvalue); 461 } 462 463 StdString CINetCDF4::getCoordinatesId 464 (const StdString & name, const CVarPath * const path) 465 { 466 StdString retvalue; 467 if (this->hasAttribute("coordinates", &name, path)) 468 { 469 return (this->getAttributeValue<StdString>("coordinates", &name, path)); 470 } 471 else 472 { 473 std::list<StdString> dims = this->getDimensionsList(&name, path); 474 std::list<StdString>::const_iterator it = dims.begin(), end = dims.end(); 475 for (; it != end; it++) 476 { 477 const StdString & value = *it; 478 retvalue.append(value).push_back(' '); 479 } 480 retvalue.erase (retvalue.end()-1) ; 481 } 482 483 return (retvalue); 484 } 485 486 StdString CINetCDF4::getBoundsId(const StdString & name, 487 const CVarPath * const path) 488 { 489 StdString retvalue; 490 if (this->hasAttribute("bounds", &name, path)) 491 return (this->getAttributeValue<StdString>("bounds", &name, path)); 492 return (retvalue); 493 } 494 495 //--------------------------------------------------------------- 496 497 bool CINetCDF4::isBound(const StdString & name, 498 const CVarPath * const path) 499 { 500 std::set<StdString> bounds = this->getBoundVariables(path); 501 return (bounds.find(name) != bounds.end()); 502 } 503 504 bool CINetCDF4::isCoordinate(const StdString & name, 505 const CVarPath * const path) 506 { 507 std::set<StdString> coords = this->getCoordVariables(path); 508 return (coords.find(name) != coords.end()); 509 } 510 511 bool CINetCDF4::isRectilinear(const StdString & name, const CVarPath * const path) 512 { 513 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 514 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 515 for (; it != end; it++) 516 { 517 const StdString & coord = *it; 518 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path)) 519 { 520 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 521 if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end())) 522 continue; 523 else 524 return (false); 525 } 526 } 527 return (true); 528 } 529 530 bool CINetCDF4::isCurvilinear(const StdString & name, const CVarPath * const path) 531 { 532 if (this->isRectilinear(name, path) || 533 !this->hasCoordinates(name, path)) 534 return (false); 535 536 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 537 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 538 for (; it != end; it++) 539 { 540 const StdString & coord = *it; 541 if (this->hasVariable(coord, path)) 542 { 543 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 544 if (dimvar.size() != 2) return (false); 545 } 546 else return (false); 547 } 548 return (true); 549 } 550 551 bool CINetCDF4::isUnstructured(const StdString & name, const CVarPath * const path) 552 { 553 if (this->isRectilinear(name, path) || 554 this->isCurvilinear(name, path) || 555 !this->hasCoordinates(name, path)) 556 return (false); 557 558 StdString dimname = this->getDimensionsList(&name, path).back(); 559 560 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 561 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 562 for (; it != end; it++) 563 { 564 const StdString & coord = *it; 565 if (this->hasVariable(coord, path)) 566 { 567 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 568 if ((dimvar.size() == 1) && 569 (dimvar.find(dimname) != dimvar.end())) 570 continue; 571 else 572 return (false); 573 } 574 else return (false); 575 } 576 577 return (true); 578 } 579 580 bool CINetCDF4::isUnknown(const StdString & name, const CVarPath * const path) 581 { 582 return !(this->isRectilinear(name, path) || 583 this->isCurvilinear(name, path) || 584 this->isUnstructured(name, path)); 585 } 586 587 bool CINetCDF4::isTemporal(const StdString & name, const CVarPath * const path) 588 { 589 if (!this->hasTemporalDim(path)) return (false); 590 std::map<StdString, StdSize> dims = this->getDimensions(&name, path); 591 if (dims.find(this->getUnlimitedDimensionName(path)) != dims.end()) 592 return (true); 593 return (false); 594 } 595 596 bool CINetCDF4::is3Dim(const StdString & name, const CVarPath * const path) 597 { 598 int i = 0; 599 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 600 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 601 for (; it != end; it++) 602 { 603 const StdString & coord = *it; 604 if (this->hasVariable(coord, path)) 605 { 606 if (this->isTemporal(coord, path)) 607 continue; 608 i++; 609 } 610 else 611 { 612 if (coord.compare(this->getUnlimitedDimensionName()) == 0) 613 continue; 614 i++; 615 } 616 } 617 return (i == 3); 618 } 619 620 bool CINetCDF4::isCellGrid(const StdString & name, const CVarPath * const path) 621 { 622 if (this->isCoordinate(name, path)) 623 { 624 return (this->hasBounds(name, path)); 625 } 626 else 627 { 628 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 629 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 630 for (; it != end; it++) 631 { 632 const StdString & coord = *it; 633 if (this->hasVariable(coord, path)) 634 { 635 if (this->isTemporal(coord, path)) 636 continue; 637 if (this->isCellGrid(coord, path)) 638 continue; 639 return (false); 640 } 641 else 642 { 643 if (coord.compare(this->getUnlimitedDimensionName()) == 0) 644 continue; 645 return (false); 646 } 647 } 648 } 649 650 return (true); 651 } 652 653 //--------------------------------------------------------------- 654 655 std::list<StdString> CINetCDF4::getDataVariables(bool _is3D, bool _isRecti, 656 bool _isCurvi, bool _isUnstr, 657 bool _isCellData, bool _isTemporal, 658 const CVarPath * const path) 659 { 660 std::list<StdString> retvalue; 661 std::list<StdString> allvars = this->getVariables(path); 662 std::set<StdString> allcoords = this->getCoordVariables(path); 663 664 std::list<StdString>::const_iterator it = allvars.begin(), end = allvars.end(); 665 for (; it != end; it++) 666 { 667 const StdString & var = *it; 668 if (this->isCoordinate(var, path)) continue; 669 670 if (!_isRecti && this->isRectilinear(var, path) ) continue; 671 if (!_isCurvi && this->isCurvilinear(var, path) ) continue; 672 if (!_isUnstr && this->isUnstructured(var, path)) continue; 673 674 if (!_isTemporal && this->isTemporal(var, path)) continue; 675 if (!_is3D && this->is3Dim(var, path) ) continue; 676 if (!_isCellData && this->isCellGrid(var, path)) continue; 677 678 if (this->isUnknown(var, path)) continue; 679 680 retvalue.push_back(var); 681 } 682 return (retvalue); 683 } 684 685 //--------------------------------------------------------------- 686 687 void CINetCDF4::getDataInfo(const StdString & var, const CVarPath * const path, StdSize record, 688 std::vector<StdSize> & start, std::vector<StdSize> & count, 689 StdSize & array_size) 690 { 691 std::list<StdString> dimlist = this->getDimensionsList(&var, path); 692 std::map<StdString, StdSize> dimmap = this->getDimensions(&var, path); 693 std::list<StdString>::iterator it = dimlist.begin(); 694 if (this->isTemporal(var, path)) 695 { 696 if (record != UNLIMITED_DIM) 697 start.push_back(record); 698 else 699 start.push_back(0); 700 count.push_back(1); 701 it++; 702 } 703 for (; it != dimlist.end(); it++) 704 { 705 start.push_back(0); 706 count.push_back(dimmap[*it]); 707 array_size *= dimmap[*it]; 708 } 709 } 710 711 template <> 712 void CINetCDF4::getData(CArray<int, 1>& data, const StdString & var, 713 const CVarPath * const path, StdSize record) 714 { 715 716 std::vector<StdSize> start, count; 717 int grpid = this->getGroup(path); 718 int varid = this->getVariable(var, path); 719 StdSize array_size = 1; 720 this->getDataInfo(var, path, record, start, count, array_size); 721 data.resize(array_size); 722 CheckError(nc_get_vara_int (grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 723 } 724 725 template <> 726 void CINetCDF4::getData(CArray<double, 1>& data, const StdString & var, 727 const CVarPath * const path, StdSize record) 728 { 729 std::vector<StdSize> start, count; 730 int grpid = this->getGroup(path); 731 int varid = this->getVariable(var, path); 732 StdSize array_size = 1; 733 this->getDataInfo(var, path, record, start, count, array_size); 734 data.resize(array_size); 735 CheckError(nc_get_vara_double (grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 736 } 737 738 template <> 739 void CINetCDF4::getData(CArray<float, 1>& data, const StdString & var, 740 const CVarPath * const path, StdSize record) 741 { 742 std::vector<StdSize> start, count; 743 int grpid = this->getGroup(path); 744 int varid = this->getVariable(var, path); 745 StdSize array_size = 1; 746 this->getDataInfo(var, path, record, start, count, array_size); 747 data.resize(array_size); 748 CheckError(nc_get_vara_float (grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 749 } 750 751 //--------------------------------------------------------------- 752 StdString CINetCDF4::getLonCoordName(const StdString & varname, 753 const CVarPath * const path) 754 { 755 std::list<StdString> clist = 756 this->getCoordinatesIdList(varname, path); 757 if (this->hasCoordinates(varname, path)) 758 return (*clist.begin()); 759 else 760 return (*clist.rbegin()); 761 } 762 763 StdString CINetCDF4::getLatCoordName(const StdString & varname, 764 const CVarPath * const path) 765 { 766 std::list<StdString> clist = 767 this->getCoordinatesIdList(varname, path); 768 if (this->hasCoordinates(varname, path)) 769 return (*(++clist.begin())); 770 else 771 return (*(++clist.rbegin())); 772 } 773 774 StdString CINetCDF4::getVertCoordName(const StdString & varname, 775 const CVarPath * const path) 776 { 777 if (!this->is3Dim(varname, path)) return (""); 778 std::list<StdString> clist = 779 this->getCoordinatesIdList(varname, path); 780 if (this->hasCoordinates(varname, path)) 781 return (*(++(++clist.begin()))); 782 else 783 return (*(++(++clist.rbegin()))); 784 } 785 786 ///-------------------------------------------------------------- 787 8 CINetCDF4::CINetCDF4(const StdString& filename, const MPI_Comm* comm /*= NULL*/, bool multifile /*= true*/) 9 : mpi(comm != NULL && !multifile) 10 { 11 if (comm != NULL) 12 { 13 if (!multifile) CNetCdfInterface::openPar(filename, NC_NOWRITE, *comm, MPI_INFO_NULL, this->ncidp); 14 else CNetCdfInterface::open(filename, NC_NOWRITE, this->ncidp); 15 } 16 else CNetCdfInterface::open(filename, NC_NOWRITE, this->ncidp); 17 } 18 19 CINetCDF4::~CINetCDF4(void) 20 { /* Nothing to do */ } 21 22 ///-------------------------------------------------------------- 23 24 void CINetCDF4::CheckError(int status) 25 { 26 if (status != NC_NOERR) 27 { 28 StdString errormsg(nc_strerror(status)); // fuite mémoire ici ? 29 ERROR("CINetCDF4::CheckError(int status)", 30 << "[ status = " << status << " ] " << errormsg); 31 } 32 } 33 34 //--------------------------------------------------------------- 35 36 void CINetCDF4::close(void) 37 { 38 CheckError(nc_close(this->ncidp)); 39 } 40 41 //--------------------------------------------------------------- 42 43 int CINetCDF4::getGroup(const CVarPath* const path) 44 { 45 int retvalue = this->ncidp; 46 if (path == NULL) return retvalue; 47 CVarPath::const_iterator it = path->begin(), end = path->end(); 48 49 for (; it != end; it++) 50 { 51 const StdString& groupid = *it; 52 CheckError(nc_inq_ncid(retvalue, const_cast<char*>(groupid.c_str()), &retvalue)); 53 } 54 55 return retvalue; 56 } 57 58 int CINetCDF4::getVariable(const StdString& varname, 59 const CVarPath* const path) 60 { 61 int varid = 0; 62 int grpid = this->getGroup(path); 63 CheckError(nc_inq_varid(grpid, varname.c_str(), &varid)); 64 return varid; 65 } 66 67 int CINetCDF4::getDimension(const StdString& dimname, 68 const CVarPath* const path) 69 { 70 int dimid = 0; 71 int grpid = this->getGroup(path); 72 CheckError(nc_inq_dimid(grpid, dimname.c_str(), &dimid)); 73 return dimid; 74 } 75 76 std::pair<nc_type, StdSize> CINetCDF4::getAttribute(const StdString& attname, 77 const StdString* const var, 78 const CVarPath* const path) 79 { 80 std::pair<nc_type, StdSize> retvalue; 81 int grpid = this->getGroup(path); 82 int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL; 83 CheckError(nc_inq_att(grpid, varid, attname.c_str(), 84 &retvalue.first, &retvalue.second)); 85 return retvalue; 86 } 87 88 int CINetCDF4::getUnlimitedDimension(const CVarPath* const path) 89 { 90 int dimid = 0; 91 int grpid = this->getGroup(path); 92 CheckError(nc_inq_unlimdim(grpid, &dimid)); 93 return dimid; 94 } 95 96 StdString CINetCDF4::getUnlimitedDimensionName(const CVarPath* const path) 97 { 98 char full_name_in[NC_MAX_NAME +1]; 99 int grpid = this->getGroup(path); 100 int dimid = this->getUnlimitedDimension(path); 101 CheckError(nc_inq_dimname(grpid, dimid, full_name_in)); 102 103 StdString dimname(full_name_in); 104 return dimname; 105 } 106 107 //--------------------------------------------------------------- 108 StdSize CINetCDF4::getNbVertex(const StdString& name, 109 const CVarPath* const path) 110 { 111 112 if (this->isRectilinear(name, path) || 113 this->isCurvilinear(name, path)) 114 { 115 if (this->is3Dim(name, path)) return 8; 116 else return 4; 117 } 118 if (this->isUnstructured(name, path)) 119 { 120 StdString bound = this->getBoundsId 121 (this->getCoordinatesIdList(name, path).back(), path); 122 StdString dim = this->getDimensionsList(&bound, path).back(); 123 return (this->getDimensions(&bound, path)[dim]); 124 } 125 return size_t(-1); 126 } 127 128 //--------------------------------------------------------------- 129 130 std::list<StdString> CINetCDF4::getGroups(const CVarPath* const path) 131 { 132 StdSize strlen = 0; 133 char full_name_in[NC_MAX_NAME +1]; 134 int nbgroup = 0, *groupid = NULL; 135 int grpid = this->getGroup(path); 136 std::list<StdString> retvalue; 137 138 CheckError(nc_inq_grps(grpid, &nbgroup, NULL)); 139 groupid = new int[nbgroup](); 140 CheckError(nc_inq_grps(grpid, NULL, groupid)); 141 142 for (int i = 0; i < nbgroup; i++) 143 { 144 CheckError(nc_inq_grpname_full(groupid[i], &strlen, full_name_in)); 145 StdString groupname(full_name_in, strlen); 146 retvalue.push_back(groupname); 147 } 148 149 delete [] groupid; 150 return retvalue; 151 } 152 153 std::list<StdString> CINetCDF4::getVariables(const CVarPath* const path) 154 { 155 char full_name_in[NC_MAX_NAME +1]; 156 int nbvar = 0, *varid = NULL; 157 int grpid = this->getGroup(path); 158 std::list<StdString> retvalue; 159 160 CheckError(nc_inq_varids(grpid, &nbvar, NULL)); 161 varid = new int[nbvar](); 162 CheckError(nc_inq_varids(grpid, NULL, varid)); 163 164 for (int i = 0; i < nbvar; i++) 165 { 166 CheckError(nc_inq_varname(grpid, varid[i], full_name_in)); 167 StdString varname(full_name_in); 168 retvalue.push_back(varname); 169 } 170 171 delete [] varid; 172 return retvalue; 173 } 174 175 StdSize CINetCDF4::getNbOfTimestep(const CVarPath* const path) 176 { 177 return (this->getDimensions(NULL, path)[this->getUnlimitedDimensionName(path)]); 178 } 179 180 std::set<StdString> CINetCDF4::getBoundVariables(const CVarPath* const path) 181 { 182 std::set<StdString> retvalue; 183 std::list<StdString> variables = this->getVariables(path); 184 std::list<StdString>::const_iterator it = variables.begin(), end = variables.end(); 185 for (; it != end; it++) 186 { 187 const StdString& var = *it; 188 if (this->hasBounds(var, path)) 189 retvalue.insert(retvalue.end(), this->getBoundsId(var, path)); 190 } 191 return retvalue; 192 } 193 194 std::set<StdString> CINetCDF4::getCoordVariables(const CVarPath* const path) 195 { 196 std::set<StdString> retvalue; 197 std::list<StdString> variables = this->getVariables(path); 198 std::list<StdString>::const_iterator it = variables.begin(), end = variables.end(); 199 for (; it != end; it++) 200 { 201 const StdString& var = *it; 202 std::list<StdString> coords = this->getCoordinatesIdList(var, path); 203 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 204 for (; it != end; it++) 205 { 206 const StdString& coord = *it; 207 if (this->hasVariable(coord, path)) 208 retvalue.insert(retvalue.end(), coord); 209 } 210 } 211 return retvalue; 212 } 213 214 std::list<StdString> CINetCDF4::getDimensionsList(const StdString* const var, const CVarPath* const path) 215 { 216 char full_name_in[NC_MAX_NAME +1]; 217 int nbdim = 0, *dimid = NULL; 218 int grpid = this->getGroup(path); 219 int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL; 220 std::list<StdString> retvalue; 221 222 if (var != NULL) 223 { 224 CheckError(nc_inq_varndims(grpid, varid, &nbdim)); 225 dimid = new int[nbdim](); 226 CheckError(nc_inq_vardimid(grpid, varid, dimid)); 227 } 228 else 229 { 230 CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1)); 231 dimid = new int[nbdim](); 232 CheckError(nc_inq_dimids(grpid, NULL, dimid, 1)); 233 } 234 235 for (int i = 0; i < nbdim; i++) 236 { 237 CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in)); 238 StdString dimname(full_name_in); 239 retvalue.push_back(dimname); 240 } 241 delete [] dimid; 242 243 return retvalue; 244 } 245 246 std::map<StdString, StdSize> CINetCDF4::getDimensions(const StdString* const var, const CVarPath* const path) 247 { 248 StdSize size = 0; 249 char full_name_in[NC_MAX_NAME + 1]; 250 int nbdim = 0, *dimid = NULL; 251 int grpid = this->getGroup(path); 252 int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL; 253 std::map<StdString, StdSize> retvalue; 254 255 if (var != NULL) 256 { 257 CheckError(nc_inq_varndims(grpid, varid, &nbdim)); 258 dimid = new int[nbdim](); 259 CheckError(nc_inq_vardimid(grpid, varid, dimid)); 260 } 261 else 262 { 263 CheckError(nc_inq_dimids(grpid, &nbdim, NULL, 1)); 264 dimid = new int[nbdim](); 265 CheckError(nc_inq_dimids(grpid, NULL, dimid, 1)); 266 } 267 268 for (int i = 0; i < nbdim; i++) 269 { 270 CheckError(nc_inq_dimname(grpid, dimid[i], full_name_in)); 271 CheckError(nc_inq_dimlen (grpid, dimid[i], &size)); 272 273 StdString dimname(full_name_in); 274 retvalue.insert(retvalue.end(), std::make_pair(dimname, size)); 275 } 276 delete [] dimid; 277 278 return retvalue; 279 } 280 281 std::list<StdString> CINetCDF4::getAttributes(const StdString* const var, const CVarPath* const path ) 282 { 283 int nbatt = 0; 284 char full_name_in[NC_MAX_NAME +1]; 285 std::list<StdString> retvalue; 286 int grpid = this->getGroup(path); 287 int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL; 288 289 if (var != NULL) 290 CheckError(nc_inq_varnatts(grpid, varid, &nbatt)); 291 else 292 CheckError(nc_inq_natts(grpid, &nbatt)); 293 294 for (int i = 0; i < nbatt; i++) 295 { 296 CheckError(nc_inq_attname(grpid, varid, i, full_name_in)); 297 StdString attname(full_name_in); 298 retvalue.push_back(attname); 299 } 300 return retvalue; 301 } 302 303 int CINetCDF4::getAttributeId(const StdString& name, 304 const StdString* const var, 305 const CVarPath* const path) 306 { 307 int retvalue = 0; 308 std::list<StdString> atts = this->getAttributes(var, path); 309 std::list<StdString>::const_iterator it = atts.begin(), end = atts.end(); 310 for (; it != end; it++) 311 { 312 const StdString& attname = *it; 313 if (attname.compare(name) == 0) 314 return retvalue; 315 retvalue++; 316 } 317 return -1; 318 } 319 320 //--------------------------------------------------------------- 321 322 bool CINetCDF4::hasMissingValue(const StdString& name, 323 const CVarPath* const path) 324 { 325 return (this->hasAttribute("missing_value", &name, path) || 326 this->hasAttribute("_FillValue", &name, path)); 327 } 328 329 bool CINetCDF4::hasAttribute(const StdString& name, 330 const StdString* const var , 331 const CVarPath* const path) 332 { 333 std::list<StdString> atts = this->getAttributes(var, path); 334 std::list<StdString>::const_iterator it = atts.begin(), end = atts.end(); 335 for (; it != end; it++) 336 { 337 const StdString& attname = *it; 338 if (attname.compare(name) == 0) return true; 339 } 340 return false; 341 } 342 343 bool CINetCDF4::hasVariable(const StdString& name, 344 const CVarPath* const path) 345 { 346 std::list<StdString> variables = this->getVariables(path); 347 std::list<StdString>::const_iterator it = variables.begin(), end = variables.end(); 348 for (; it != end; it++) 349 { 350 const StdString& varname = *it; 351 if (varname.compare(name) == 0) return true; 352 } 353 return false; 354 } 355 356 bool CINetCDF4::hasCoordinates(const StdString& name, 357 const CVarPath* const path) 358 { 359 return (this->hasAttribute("coordinates", &name, path)); 360 } 361 362 bool CINetCDF4::hasBounds(const StdString& name, 363 const CVarPath* const path) 364 { 365 return (this->hasAttribute("bounds", &name, path)); 366 } 367 368 bool CINetCDF4::hasTemporalDim(const CVarPath* const path) 369 { 370 return (this->getUnlimitedDimension(path) != -1); 371 } 372 373 //--------------------------------------------------------------- 374 375 #define GET_ATTRIBUTE_VALUE(type, func_ext, type_enum) \ 376 template <> \ 377 std::vector<type> CINetCDF4::getAttributeValue(const StdString& name, \ 378 const StdString* const var, \ 379 const CVarPath* const path) \ 380 { \ 381 int grpid = this->getGroup(path); \ 382 int varid = (var != NULL) ? this->getVariable(*var, path) : NC_GLOBAL; \ 383 std::pair<nc_type , StdSize> attinfos = this->getAttribute(name, var, path); \ 384 std::vector<type> retvalue(attinfos.second); \ 385 if (attinfos.first != type_enum) \ 386 ERROR("CINetCDF4::getAttributeValue<double>(name, var, path", \ 387 << "[ name : " << name \ 388 << ", type requested :" << attinfos.first \ 389 << ", type stored : " << type_enum << "]" \ 390 << " Invalid type !"); \ 391 CheckError(nc_get_att_##func_ext(grpid, varid, name.c_str(), &(retvalue[0]))); \ 392 return retvalue; \ 393 } 394 395 GET_ATTRIBUTE_VALUE(double, double, NC_DOUBLE) 396 GET_ATTRIBUTE_VALUE(float, float, NC_FLOAT) 397 GET_ATTRIBUTE_VALUE(int, int , NC_INT) 398 GET_ATTRIBUTE_VALUE(char, text, NC_CHAR) 399 400 template <> 401 StdString CINetCDF4::getAttributeValue(const StdString& name, 402 const StdString* const var, 403 const CVarPath* const path) 404 { 405 std::vector<char> chart = this->getAttributeValue<std::vector<char> >(name, var, path); 406 StdString retvalue(&(chart[0]), chart.size()); 407 return retvalue; 408 } 409 410 template <> 411 int CINetCDF4::getMissingValue(const StdString& name, 412 const CVarPath* const path) 413 { 414 if (this->hasAttribute("missing_value", &name, path)) 415 return (this->getAttributeValue<std::vector<int> >("missing_value", &name, path)[0]); 416 if (this->hasAttribute("_FillValue", &name, path)) 417 return (this->getAttributeValue<std::vector<int> >("_FillValue", &name, path)[0]); 418 return 0; 419 } 420 421 template <> 422 double CINetCDF4::getMissingValue(const StdString& name, 423 const CVarPath* const path) 424 { 425 if (this->hasAttribute("missing_value", &name, path)) 426 return (this->getAttributeValue<std::vector<double> >("missing_value", &name, path)[0]); 427 if (this->hasAttribute("_FillValue", &name, path)) 428 return (this->getAttributeValue<std::vector<double> >("_FillValue", &name, path)[0]); 429 return 0; 430 } 431 432 template <> 433 float CINetCDF4::getMissingValue(const StdString& name, 434 const CVarPath* const path) 435 { 436 if (this->hasAttribute("missing_value", &name, path)) 437 return (this->getAttributeValue<std::vector<float> >("missing_value", &name, path)[0]); 438 if (this->hasAttribute("_FillValue", &name, path)) 439 return (this->getAttributeValue<std::vector<float> >("_FillValue", &name, path)[0]); 440 return 0; 441 } 442 443 //--------------------------------------------------------------- 444 445 std::list<StdString> CINetCDF4::getCoordinatesIdList(const StdString& name, const CVarPath* const path) 446 { 447 std::list<StdString> retvalue; 448 StdString value = this->getCoordinatesId(name, path); 449 450 boost::split(retvalue, value, boost::is_any_of(" ")); 451 452 std::list<StdString>::iterator it = retvalue.begin(), end = retvalue.end(); 453 for (; it != end; it++) 454 { 455 StdString& coord = *it; 456 coord.assign(coord.data()); 457 } 458 return retvalue; 459 } 460 461 StdString CINetCDF4::getCoordinatesId(const StdString& name, const CVarPath* const path) 462 { 463 StdString retvalue; 464 if (this->hasAttribute("coordinates", &name, path)) 465 { 466 return (this->getAttributeValue<StdString>("coordinates", &name, path)); 467 } 468 else 469 { 470 std::list<StdString> dims = this->getDimensionsList(&name, path); 471 std::list<StdString>::const_iterator it = dims.begin(), end = dims.end(); 472 for (; it != end; it++) 473 { 474 const StdString& value = *it; 475 retvalue.append(value).push_back(' '); 476 } 477 retvalue.erase(retvalue.end() - 1) ; 478 } 479 480 return retvalue; 481 } 482 483 StdString CINetCDF4::getBoundsId(const StdString& name, 484 const CVarPath* const path) 485 { 486 StdString retvalue; 487 if (this->hasAttribute("bounds", &name, path)) 488 return (this->getAttributeValue<StdString>("bounds", &name, path)); 489 return retvalue; 490 } 491 492 //--------------------------------------------------------------- 493 494 bool CINetCDF4::isBound(const StdString& name, 495 const CVarPath* const path) 496 { 497 std::set<StdString> bounds = this->getBoundVariables(path); 498 return (bounds.find(name) != bounds.end()); 499 } 500 501 bool CINetCDF4::isCoordinate(const StdString& name, 502 const CVarPath* const path) 503 { 504 std::set<StdString> coords = this->getCoordVariables(path); 505 return (coords.find(name) != coords.end()); 506 } 507 508 bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path) 509 { 510 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 511 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 512 for (; it != end; it++) 513 { 514 const StdString& coord = *it; 515 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path)) 516 { 517 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 518 if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end())) 519 continue; 520 else 521 return false; 522 } 523 } 524 return true; 525 } 526 527 bool CINetCDF4::isCurvilinear(const StdString& name, const CVarPath* const path) 528 { 529 if (this->isRectilinear(name, path) || !this->hasCoordinates(name, path)) 530 return false; 531 532 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 533 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 534 for (; it != end; it++) 535 { 536 const StdString& coord = *it; 537 if (this->hasVariable(coord, path)) 538 { 539 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 540 if (dimvar.size() != 2) return false; 541 } 542 else return false; 543 } 544 return true; 545 } 546 547 bool CINetCDF4::isUnstructured(const StdString& name, const CVarPath* const path) 548 { 549 if (this->isRectilinear(name, path) || 550 this->isCurvilinear(name, path) || 551 !this->hasCoordinates(name, path)) 552 return false; 553 554 StdString dimname = this->getDimensionsList(&name, path).back(); 555 556 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 557 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 558 for (; it != end; it++) 559 { 560 const StdString& coord = *it; 561 if (this->hasVariable(coord, path)) 562 { 563 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 564 if ((dimvar.size() == 1) && 565 (dimvar.find(dimname) != dimvar.end())) 566 continue; 567 else 568 return false; 569 } 570 else return false; 571 } 572 573 return true; 574 } 575 576 bool CINetCDF4::isUnknown(const StdString& name, const CVarPath* const path) 577 { 578 return !(this->isRectilinear(name, path) || this->isCurvilinear(name, path) || this->isUnstructured(name, path)); 579 } 580 581 bool CINetCDF4::isTemporal(const StdString& name, const CVarPath* const path) 582 { 583 if (!this->hasTemporalDim(path)) return false; 584 std::map<StdString, StdSize> dims = this->getDimensions(&name, path); 585 if (dims.find(this->getUnlimitedDimensionName(path)) != dims.end()) 586 return true; 587 return false; 588 } 589 590 bool CINetCDF4::is3Dim(const StdString& name, const CVarPath* const path) 591 { 592 int i = 0; 593 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 594 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 595 for (; it != end; it++) 596 { 597 const StdString& coord = *it; 598 if (this->hasVariable(coord, path)) 599 { 600 if (this->isTemporal(coord, path)) 601 continue; 602 i++; 603 } 604 else 605 { 606 if (coord.compare(this->getUnlimitedDimensionName()) == 0) 607 continue; 608 i++; 609 } 610 } 611 return (i == 3); 612 } 613 614 bool CINetCDF4::isCellGrid(const StdString& name, const CVarPath* const path) 615 { 616 if (this->isCoordinate(name, path)) 617 { 618 return (this->hasBounds(name, path)); 619 } 620 else 621 { 622 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 623 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 624 for (; it != end; it++) 625 { 626 const StdString& coord = *it; 627 if (this->hasVariable(coord, path)) 628 { 629 if (this->isTemporal(coord, path)) 630 continue; 631 if (this->isCellGrid(coord, path)) 632 continue; 633 return false; 634 } 635 else 636 { 637 if (coord.compare(this->getUnlimitedDimensionName()) == 0) 638 continue; 639 return false; 640 } 641 } 642 } 643 644 return true; 645 } 646 647 //--------------------------------------------------------------- 648 649 std::list<StdString> CINetCDF4::getDataVariables(bool _is3D, bool _isRecti, 650 bool _isCurvi, bool _isUnstr, 651 bool _isCellData, bool _isTemporal, 652 const CVarPath* const path) 653 { 654 std::list<StdString> retvalue; 655 std::list<StdString> allvars = this->getVariables(path); 656 std::set<StdString> allcoords = this->getCoordVariables(path); 657 658 std::list<StdString>::const_iterator it = allvars.begin(), end = allvars.end(); 659 for (; it != end; it++) 660 { 661 const StdString& var = *it; 662 if (this->isCoordinate(var, path)) continue; 663 664 if (!_isRecti && this->isRectilinear(var, path)) continue; 665 if (!_isCurvi && this->isCurvilinear(var, path)) continue; 666 if (!_isUnstr && this->isUnstructured(var, path)) continue; 667 668 if (!_isTemporal && this->isTemporal(var, path)) continue; 669 if (!_is3D && this->is3Dim(var, path)) continue; 670 if (!_isCellData && this->isCellGrid(var, path)) continue; 671 672 if (this->isUnknown(var, path)) continue; 673 674 retvalue.push_back(var); 675 } 676 return retvalue; 677 } 678 679 //--------------------------------------------------------------- 680 681 void CINetCDF4::getDataInfo(const StdString& var, const CVarPath* const path, StdSize record, 682 std::vector<StdSize>& sstart, std::vector<StdSize>& scount, StdSize& array_size, 683 const std::vector<StdSize>* start /*= NULL*/, const std::vector<StdSize>* count /*= NULL*/) 684 { 685 std::list<StdString> dimlist = this->getDimensionsList(&var, path); 686 std::map<StdString, StdSize> dimmap = this->getDimensions(&var, path); 687 std::list<StdString>::iterator it = dimlist.begin(); 688 if (this->isTemporal(var, path)) 689 { 690 if (record != UNLIMITED_DIM) 691 sstart.push_back(record); 692 else 693 sstart.push_back(0); 694 scount.push_back(1); 695 it++; 696 } 697 for (int i = 0; it != dimlist.end(); it++, i++) 698 { 699 if (start && count) 700 { 701 sstart.push_back((*start)[i]); 702 scount.push_back((*count)[i]); 703 array_size *= (*count)[i]; 704 } 705 else 706 { 707 sstart.push_back(0); 708 scount.push_back(dimmap[*it]); 709 array_size *= dimmap[*it]; 710 } 711 } 712 } 713 714 template <> 715 void CINetCDF4::getData(CArray<int, 1>& data, const StdString& var, 716 const CVarPath* const path, StdSize record) 717 { 718 719 std::vector<StdSize> start, count; 720 int grpid = this->getGroup(path); 721 int varid = this->getVariable(var, path); 722 StdSize array_size = 1; 723 this->getDataInfo(var, path, record, start, count, array_size); 724 data.resize(array_size); 725 CheckError(nc_get_vara_int(grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 726 } 727 728 template <> 729 void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var, 730 const CVarPath* const path, StdSize record) 731 { 732 std::vector<StdSize> start, count; 733 int grpid = this->getGroup(path); 734 int varid = this->getVariable(var, path); 735 StdSize array_size = 1; 736 this->getDataInfo(var, path, record, start, count, array_size); 737 data.resize(array_size); 738 CheckError(nc_get_vara_double(grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 739 } 740 741 template <> 742 void CINetCDF4::getData(CArray<float, 1>& data, const StdString& var, 743 const CVarPath* const path, StdSize record) 744 { 745 std::vector<StdSize> start, count; 746 int grpid = this->getGroup(path); 747 int varid = this->getVariable(var, path); 748 StdSize array_size = 1; 749 this->getDataInfo(var, path, record, start, count, array_size); 750 data.resize(array_size); 751 CheckError(nc_get_vara_float(grpid, varid, &(start[0]), &(count[0]), data.dataFirst())); 752 } 753 754 template <> 755 void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var, 756 bool collective, StdSize record, 757 const std::vector<StdSize>* start /*= NULL*/, 758 const std::vector<StdSize>* count /*= NULL*/) 759 { 760 int varid = this->getVariable(var); 761 762 if (this->mpi && collective) 763 CNetCdfInterface::varParAccess(ncidp, varid, NC_COLLECTIVE); 764 if (this->mpi && !collective) 765 CNetCdfInterface::varParAccess(ncidp, varid, NC_INDEPENDENT); 766 767 std::vector<StdSize> sstart, scount; 768 StdSize array_size = 1; 769 this->getDataInfo(var, NULL, record, sstart, scount, array_size, start, count); 770 771 if (data.numElements() != array_size) 772 { 773 ERROR("CONetCDF4::getData(...)", 774 << "[ Array size = " << data.numElements() 775 << ", Data size = " << array_size 776 << " ] Invalid array size"); 777 } 778 779 CheckError(nc_get_vara_double(ncidp, varid, &(sstart[0]), &(scount[0]), data.dataFirst())); 780 } 781 782 //--------------------------------------------------------------- 783 784 StdString CINetCDF4::getLonCoordName(const StdString& varname, 785 const CVarPath* const path) 786 { 787 std::list<StdString> clist = this->getCoordinatesIdList(varname, path); 788 if (this->hasCoordinates(varname, path)) 789 return (*clist.begin()); 790 else 791 return (*clist.rbegin()); 792 } 793 794 StdString CINetCDF4::getLatCoordName(const StdString& varname, 795 const CVarPath* const path) 796 { 797 std::list<StdString> clist = this->getCoordinatesIdList(varname, path); 798 if (this->hasCoordinates(varname, path)) 799 return (*(++clist.begin())); 800 else 801 return (*(++clist.rbegin())); 802 } 803 804 StdString CINetCDF4::getVertCoordName(const StdString& varname, 805 const CVarPath* const path) 806 { 807 if (!this->is3Dim(varname, path)) return ""; 808 std::list<StdString> clist = this->getCoordinatesIdList(varname, path); 809 if (this->hasCoordinates(varname, path)) 810 return (*(++(++clist.begin()))); 811 else 812 return (*(++(++clist.rbegin()))); 813 } 788 814 } // namespace xios -
XIOS/trunk/src/input/inetcdf4.hpp
r591 r599 11 11 12 12 #ifndef UNLIMITED_DIM 13 14 #endif // UNLIMITED_DIM13 #define UNLIMITED_DIM (size_t)(-1) 14 #endif // UNLIMITED_DIM 15 15 16 16 namespace xios 17 17 { 18 /// ////////////////////// Déclarations ////////////////////// /// 19 typedef std::vector<StdString> CVarPath; 20 21 class CINetCDF4 22 { 23 public : 24 25 /// Constructeurs /// 26 CINetCDF4(void); // Not implemented. 27 CINetCDF4(const StdString & filename); 28 CINetCDF4(const CINetCDF4 & inetcdf4); // Not implemented. 29 CINetCDF4(const CINetCDF4 * const inetcdf4); // Not implemented. 30 31 //------------------------------------------------------------- 32 33 /// Accesseurs /// 34 StdSize getNbOfTimestep(const CVarPath * const path = NULL); 35 36 StdString getUnlimitedDimensionName(const CVarPath * const path = NULL); 37 38 StdString getCoordinatesId(const StdString & name, 39 const CVarPath * const path = NULL); 40 41 StdString getBoundsId(const StdString & name, 42 const CVarPath * const path = NULL); 43 44 StdString getLonCoordName(const StdString & varname, 45 const CVarPath * const path = NULL); 46 StdString getLatCoordName(const StdString & varname, 47 const CVarPath * const path = NULL); 48 StdString getVertCoordName(const StdString & varname, 49 const CVarPath * const path = NULL); 50 51 std::set<StdString> getCoordVariables(const CVarPath * const path = NULL); 52 std::set<StdString> getBoundVariables(const CVarPath * const path = NULL); 53 54 std::list<StdString> getGroups (const CVarPath * const path = NULL); 55 std::list<StdString> getVariables(const CVarPath * const path = NULL); 56 57 std::list<StdString> getDataVariables(bool _is3D = true, 58 bool _isRecti = true, 59 bool _isCurvi = true, 60 bool _isUnstr = true, 61 bool _isCellData = true, 62 bool _isTemporal = true, 63 const CVarPath * const path = NULL); 64 65 std::list<StdString> getAttributes 66 (const StdString * const var = NULL, 67 const CVarPath * const path = NULL); 68 69 std::list<StdString> getDimensionsList 70 (const StdString * const var = NULL, 71 const CVarPath * const path = NULL); 72 73 std::list<StdString> getCoordinatesIdList(const StdString & name, 74 const CVarPath * const path = NULL); 75 76 std::map<StdString, StdSize> getDimensions (const StdString * const var = NULL, 77 const CVarPath * const path = NULL); 78 79 StdSize getNbVertex(const StdString & name, 80 const CVarPath * const path = NULL); 81 //------------------------------------------------------------- 82 83 template <class T> 84 T getMissingValue(const StdString & name, 85 const CVarPath * const path = NULL); 86 87 template <class T> 88 T getAttributeValue(const StdString & name, 89 const StdString * const var = NULL, 90 const CVarPath * const path = NULL); 91 92 template <class T> 93 void getData(CArray<T, 1>& data, 94 const StdString & var, 95 const CVarPath * const path = NULL, 96 StdSize record = UNLIMITED_DIM); 97 98 //------------------------------------------------------------- 99 100 /// Tests /// 101 bool hasMissingValue(const StdString & name, 102 const CVarPath * const path = NULL); 103 104 bool hasAttribute(const StdString & name, 105 const StdString * const var = NULL, 106 const CVarPath * const path = NULL); 107 108 bool hasVariable(const StdString & name, 109 const CVarPath * const path = NULL); 110 111 bool hasCoordinates(const StdString & name, 112 const CVarPath * const path = NULL); 113 114 bool hasTemporalDim(const CVarPath * const path = NULL); 115 116 bool hasBounds(const StdString & name, 117 const CVarPath * const path = NULL); 118 119 //------------------------------------------------------------- 120 121 bool isBound(const StdString & name, 122 const CVarPath * const path = NULL); 123 bool isCoordinate(const StdString & name, 124 const CVarPath * const path = NULL); 125 bool isRectilinear(const StdString & name, 126 const CVarPath * const path = NULL); 127 bool isCurvilinear(const StdString & name, 128 const CVarPath * const path = NULL); 129 bool isUnknown(const StdString & name, 130 const CVarPath * const path = NULL); 131 bool isUnstructured(const StdString & name, 132 const CVarPath * const path = NULL); 133 134 bool isTemporal(const StdString & name, 135 const CVarPath * const path = NULL); 136 bool is3Dim(const StdString & name, 137 const CVarPath * const path = NULL); 138 bool isCellGrid(const StdString & name, 139 const CVarPath * const path = NULL); 140 141 //------------------------------------------------------------- 142 143 /// Destructeur /// 144 virtual ~CINetCDF4(void); 145 146 protected : 147 148 //------------------------------------------------------------- 149 150 /// Accesseurs /// 151 int getGroup (const CVarPath * const path = NULL); 152 int getVariable(const StdString & varname, 153 const CVarPath * const path = NULL); 154 int getDimension(const StdString & dimname, 155 const CVarPath * const path = NULL); 156 int getUnlimitedDimension(const CVarPath * const path = NULL); 157 int getAttributeId(const StdString & name, 158 const StdString * const var = NULL, 159 const CVarPath * const path = NULL); 160 161 std::pair<nc_type , StdSize> getAttribute(const StdString & attname, 162 const StdString * const var = NULL, 163 const CVarPath * const path = NULL); 164 165 //------------------------------------------------------------- 166 167 void getDataInfo(const StdString & var, const CVarPath * const path, StdSize record, 168 std::vector<StdSize> & start, std::vector<StdSize> & count, 169 StdSize & array_size); 170 171 private : 172 173 /// Vérification des erreurs NetCDF /// 174 static void CheckError(int status); 175 176 int ncidp; // Identifiant de fichier netcdf. 177 178 }; // class CINetCDF4 179 180 ///-------------------------------------------------------------- 181 template <> 182 StdString CINetCDF4::getAttributeValue 183 (const StdString & name, const StdString * const var, 184 const CVarPath * const path); 185 186 template <> 187 std::vector<double> CINetCDF4::getAttributeValue 188 (const StdString & name, const StdString * const var, 189 const CVarPath * const path); 190 191 template <> 192 std::vector<float> CINetCDF4::getAttributeValue 193 (const StdString & name, const StdString * const var, 194 const CVarPath * const path); 195 196 template <> 197 std::vector<int> CINetCDF4::getAttributeValue 198 (const StdString & name, const StdString * const var, 199 const CVarPath * const path); 200 201 template <> 202 std::vector<char> CINetCDF4::getAttributeValue 203 (const StdString & name, const StdString * const var, 204 const CVarPath * const path); 205 206 //--------------------------------------------------------------- 207 template <> 208 int CINetCDF4::getMissingValue 209 (const StdString & name, const CVarPath * const path); 210 211 template <> 212 double CINetCDF4::getMissingValue 213 (const StdString & name, const CVarPath * const path); 214 215 template <> 216 float CINetCDF4::getMissingValue 217 (const StdString & name, const CVarPath * const path); 218 219 //--------------------------------------------------------------- 220 template <> 221 void CINetCDF4::getData(CArray<int, 1>& data, const StdString & var, 222 const CVarPath * const path, StdSize record); 223 224 template <> 225 void CINetCDF4::getData(CArray<double, 1>& data, const StdString & var, 226 const CVarPath * const path, StdSize record); 227 228 template <> 229 void CINetCDF4::getData(CArray<float, 1>& data, const StdString & var, 230 const CVarPath * const path, StdSize record); 231 ///-------------------------------------------------------------- 232 18 typedef std::vector<StdString> CVarPath; 19 20 class CINetCDF4 21 { 22 public: 23 /// Constructors /// 24 CINetCDF4(const StdString& filename, const MPI_Comm* comm = NULL, bool multifile = true); 25 CINetCDF4(const CINetCDF4& inetcdf4); // Not implemented. 26 CINetCDF4(const CINetCDF4* const inetcdf4); // Not implemented. 27 28 //------------------------------------------------------------- 29 30 /// Destructor /// 31 virtual ~CINetCDF4(void); 32 33 //------------------------------------------------------------- 34 35 void close(void); 36 37 //------------------------------------------------------------- 38 39 /// Getters /// 40 StdSize getNbOfTimestep(const CVarPath* const path = NULL); 41 42 StdString getUnlimitedDimensionName(const CVarPath* const path = NULL); 43 44 StdString getCoordinatesId(const StdString& name, const CVarPath* const path = NULL); 45 46 StdString getBoundsId(const StdString& name, const CVarPath* const path = NULL); 47 48 StdString getLonCoordName(const StdString& varname, const CVarPath* const path = NULL); 49 StdString getLatCoordName(const StdString& varname, const CVarPath* const path = NULL); 50 StdString getVertCoordName(const StdString& varname, const CVarPath* const path = NULL); 51 52 std::set<StdString> getCoordVariables(const CVarPath* const path = NULL); 53 std::set<StdString> getBoundVariables(const CVarPath* const path = NULL); 54 55 std::list<StdString> getGroups (const CVarPath* const path = NULL); 56 std::list<StdString> getVariables(const CVarPath* const path = NULL); 57 58 std::list<StdString> getDataVariables(bool _is3D = true, 59 bool _isRecti = true, 60 bool _isCurvi = true, 61 bool _isUnstr = true, 62 bool _isCellData = true, 63 bool _isTemporal = true, 64 const CVarPath* const path = NULL); 65 66 std::list<StdString> getAttributes(const StdString* const var = NULL, 67 const CVarPath* const path = NULL); 68 69 std::list<StdString> getDimensionsList(const StdString* const var = NULL, 70 const CVarPath* const path = NULL); 71 72 std::list<StdString> getCoordinatesIdList(const StdString& name, 73 const CVarPath* const path = NULL); 74 75 std::map<StdString, StdSize> getDimensions(const StdString* const var = NULL, 76 const CVarPath* const path = NULL); 77 78 StdSize getNbVertex(const StdString& name, const CVarPath* const path = NULL); 79 80 //------------------------------------------------------------- 81 82 template <class T> 83 T getMissingValue(const StdString& name, const CVarPath* const path = NULL); 84 85 template <class T> 86 T getAttributeValue(const StdString& name, 87 const StdString* const var = NULL, 88 const CVarPath* const path = NULL); 89 90 template <class T> 91 void getData(CArray<T, 1>& data, 92 const StdString& var, 93 const CVarPath* const path = NULL, 94 StdSize record = UNLIMITED_DIM); 95 96 template <class T> 97 void getData(CArray<T, 1>& data, const StdString& var, 98 bool collective, StdSize record, 99 const std::vector<StdSize>* start = NULL, 100 const std::vector<StdSize>* count = NULL); 101 102 //------------------------------------------------------------- 103 104 /// Tests /// 105 bool hasMissingValue(const StdString& name, const CVarPath* const path = NULL); 106 107 bool hasAttribute(const StdString& name, const StdString* const var = NULL, const CVarPath* const path = NULL); 108 109 bool hasVariable(const StdString& name, const CVarPath* const path = NULL); 110 111 bool hasCoordinates(const StdString& name, const CVarPath* const path = NULL); 112 113 bool hasTemporalDim(const CVarPath* const path = NULL); 114 115 bool hasBounds(const StdString& name, const CVarPath* const path = NULL); 116 117 //------------------------------------------------------------- 118 119 bool isBound(const StdString& name, const CVarPath* const path = NULL); 120 bool isCoordinate(const StdString& name, const CVarPath* const path = NULL); 121 bool isRectilinear(const StdString& name, const CVarPath* const path = NULL); 122 bool isCurvilinear(const StdString& name, const CVarPath* const path = NULL); 123 bool isUnknown(const StdString& name, const CVarPath* const path = NULL); 124 bool isUnstructured(const StdString& name, const CVarPath* const path = NULL); 125 126 bool isTemporal(const StdString& name, const CVarPath* const path = NULL); 127 bool is3Dim(const StdString& name, const CVarPath* const path = NULL); 128 bool isCellGrid(const StdString& name, const CVarPath* const path = NULL); 129 130 protected: 131 /// Getters /// 132 int getGroup (const CVarPath* const path = NULL); 133 int getVariable(const StdString& varname, const CVarPath* const path = NULL); 134 int getDimension(const StdString& dimname, const CVarPath* const path = NULL); 135 int getUnlimitedDimension(const CVarPath* const path = NULL); 136 int getAttributeId(const StdString& name, 137 const StdString* const var = NULL, 138 const CVarPath* const path = NULL); 139 140 std::pair<nc_type , StdSize> getAttribute(const StdString& attname, 141 const StdString* const var = NULL, 142 const CVarPath* const path = NULL); 143 144 //------------------------------------------------------------- 145 146 void getDataInfo(const StdString& var, const CVarPath* const path, StdSize record, 147 std::vector<StdSize>& sstart, std::vector<StdSize>& scount, StdSize& array_size, 148 const std::vector<StdSize>* start = NULL, const std::vector<StdSize>* count = NULL); 149 150 private: 151 /// Vérification des erreurs NetCDF /// 152 static void CheckError(int status); 153 154 int ncidp; // Identifiant de fichier netcdf. 155 bool mpi; //< Whether parallel file access is used 156 }; // class CINetCDF4 157 158 ///-------------------------------------------------------------- 159 160 template <> 161 StdString CINetCDF4::getAttributeValue(const StdString& name, const StdString* const var, 162 const CVarPath* const path); 163 164 template <> 165 std::vector<double> CINetCDF4::getAttributeValue(const StdString& name, const StdString* const var, 166 const CVarPath* const path); 167 168 template <> 169 std::vector<float> CINetCDF4::getAttributeValue(const StdString& name, const StdString* const var, 170 const CVarPath* const path); 171 172 template <> 173 std::vector<int> CINetCDF4::getAttributeValue(const StdString& name, const StdString* const var, 174 const CVarPath* const path); 175 176 template <> 177 std::vector<char> CINetCDF4::getAttributeValue(const StdString& name, const StdString* const var, 178 const CVarPath* const path); 179 180 //--------------------------------------------------------------- 181 182 template <> 183 int CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path); 184 185 template <> 186 double CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path); 187 188 template <> 189 float CINetCDF4::getMissingValue(const StdString& name, const CVarPath* const path); 190 191 //--------------------------------------------------------------- 192 193 template <> 194 void CINetCDF4::getData(CArray<int, 1>& data, const StdString& var, 195 const CVarPath* const path, StdSize record); 196 197 template <> 198 void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var, 199 const CVarPath* const path, StdSize record); 200 201 template <> 202 void CINetCDF4::getData(CArray<float, 1>& data, const StdString& var, 203 const CVarPath* const path, StdSize record); 204 205 template <> 206 void CINetCDF4::getData(CArray<double, 1>& data, const StdString& var, 207 bool collective, StdSize record, 208 const std::vector<StdSize>* start /*= NULL*/, 209 const std::vector<StdSize>* count /*= NULL*/); 233 210 } // namespace xios 234 211 -
XIOS/trunk/src/input/nc4_data_input.cpp
r501 r599 1 1 #include "nc4_data_input.hpp" 2 3 #include "context.hpp" 4 #include "context_server.hpp" 2 5 3 6 namespace xios 4 7 { 5 /// ////////////////////// Définitions ////////////////////// /// 6 CNc4DataInput::CNc4DataInput(void) 7 { /* ne rien faire de plus */ } 8 CNc4DataInput::CNc4DataInput(const StdString& filename, MPI_Comm comm_file, bool multifile, bool isCollective /*= true*/) 9 : SuperClass() 10 , SuperClassWriter(filename, &comm_file, multifile) 11 , comm_file(comm_file) 12 , filename(filename) 13 , isCollective(isCollective) 14 { 15 SuperClass::type = multifile ? MULTI_FILE : ONE_FILE; 16 } 8 17 9 10 { /* ne rien faire de plus*/ }18 CNc4DataInput::~CNc4DataInput(void) 19 { /* Nothing more to do */ } 11 20 21 StdSize CNc4DataInput::getFieldNbRecords_(CField* field) 22 { 23 StdString fieldId = !field->name.isEmpty() ? field->name.getValue() : field->getBaseFieldReference()->getId(); 24 25 if (SuperClassWriter::isTemporal(fieldId)) 26 { 27 return SuperClassWriter::getDimensions(&fieldId)[SuperClassWriter::getUnlimitedDimensionName()]; 28 } 29 30 return 1; 31 } 32 33 void CNc4DataInput::readFieldData_(CField* field) 34 { 35 CContext* context = CContext::getCurrent(); 36 CContextServer* server = context->server; 37 38 CGrid* grid = field->grid; 39 40 if (!grid->doGridHaveDataToWrite()) 41 if (SuperClass::type==MULTI_FILE || !isCollective) return; 42 43 StdString fieldId = !field->name.isEmpty() ? field->name.getValue() : field->getBaseFieldReference()->getId(); 44 45 CArray<double,1> fieldData(grid->getWrittenDataSize()); 46 if (!field->default_value.isEmpty()) fieldData = field->default_value; 47 48 switch (SuperClass::type) 49 { 50 case MULTI_FILE: 51 SuperClassWriter::getData(fieldData, fieldId, isCollective, field->getNStep() - 1); 52 break; 53 case ONE_FILE: 54 { 55 std::vector<int> nZoomBeginGlobal = grid->getDistributionServer()->getZoomBeginGlobal(); 56 std::vector<int> nZoomBeginServer = grid->getDistributionServer()->getZoomBeginServer(); 57 std::vector<int> nZoomSizeServer = grid->getDistributionServer()->getZoomSizeServer(); 58 59 int ssize = nZoomBeginGlobal.size(); 60 61 std::vector<StdSize> start(ssize); 62 std::vector<StdSize> count(ssize); 63 64 for (int i = 0; i < ssize; ++i) 65 { 66 start[i] = nZoomBeginServer[ssize - i - 1] - nZoomBeginGlobal[ssize - i - 1]; 67 count[i] = nZoomSizeServer[ssize - i - 1]; 68 } 69 70 SuperClassWriter::getData(fieldData, fieldId, isCollective, field->getNStep() - 1, &start, &count); 71 break; 72 } 73 } 74 75 field->inputField(fieldData); 76 77 if (!field->scale_factor.isEmpty() || !field->add_offset.isEmpty()) 78 { 79 double scaleFactor = 1.0, addOffset = 0.0; 80 if (!field->scale_factor.isEmpty()) scaleFactor = field->scale_factor; 81 if (!field->add_offset.isEmpty()) addOffset = field->add_offset; 82 field->invertScaleFactorAddOffset(scaleFactor, addOffset); 83 } 84 } 85 86 void CNc4DataInput::closeFile_(void) 87 { 88 SuperClassWriter::close(); 89 } 12 90 } // namespace xios -
XIOS/trunk/src/input/nc4_data_input.hpp
r591 r599 4 4 /// XIOS headers /// 5 5 #include "xios_spl.hpp" 6 #include "data_input.hpp" 6 7 #include "inetcdf4.hpp" 7 8 8 9 namespace xios 9 10 { 10 /// ////////////////////// Déclarations ////////////////////// /// 11 class CNc4DataInput 12 : protected CINetCDF4 13 , public virtual CDataInput 14 { 15 public: 16 /// Type definitions /// 17 typedef CINetCDF4 SuperClassWriter; 18 typedef CDataInput SuperClass; 11 19 12 class CNc4DataInput 13 { 14 public : 20 /// Constructors /// 21 CNc4DataInput(const StdString& filename, MPI_Comm comm_file, bool multifile, bool isCollective = true); 22 CNc4DataInput(const CNc4DataInput& dataInput); // Not implemented. 23 CNc4DataInput(const CNc4DataInput* const dataInput); // Not implemented. 15 24 16 /// Constructeurs /// 17 CNc4DataInput(void); 18 CNc4DataInput(const CNc4DataInput & datainput); // Not implemented. 19 CNc4DataInput(const CNc4DataInput * const datainput); // Not implemented. 25 /// Destructor /// 26 virtual ~CNc4DataInput(void); 20 27 21 /// Destructeur///22 virtual ~CNc4DataInput(void);28 /// Getters /// 29 const StdString& getFileName(void) const; 23 30 24 }; // class CNc4DataInput 31 protected: 32 // Read methods 33 virtual StdSize getFieldNbRecords_(CField* field); 34 virtual void readFieldData_(CField* field); 35 virtual void closeFile_(void); 25 36 37 private: 38 /// Private attributes /// 39 MPI_Comm comm_file; 40 const StdString filename; 41 bool isCollective; 42 }; // class CNc4DataInput 26 43 } // namespace xios 27 44 -
XIOS/trunk/src/node/field.cpp
r598 r599 23 23 , grid(), file() 24 24 , freq_operation(), freq_write() 25 , nstep(0) 25 , nstep(0), nstepMax(0), isEOF(false) 26 26 , last_Write(), last_operation() 27 27 , foperation(), hasInstantData(false), hasExpression(false) … … 36 36 , grid(), file() 37 37 , freq_operation(), freq_write() 38 , nstep(0) 38 , nstep(0), nstepMax(0), isEOF(false) 39 39 , last_Write(), last_operation() 40 40 , foperation(), hasInstantData(false), hasExpression(false) … … 267 267 if (!getRelFile()->allDomainEmpty) 268 268 { 269 if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) // if (! grid->domain->isEmpty() || getRelFile()->type == CFile::type_attr::one_file)269 if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 270 270 { 271 271 getRelFile()->checkFile(); … … 329 329 std::list<CMessage> msgs; 330 330 331 // TODO: Read the data from the file 332 if (data_srv.empty()) 333 { 334 for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it) 335 data_srv.insert( pair<int, CArray<double,1>* >(it->first, new CArray<double,1>(it->second->numElements()))); 336 } 331 bool hasData = readField(); 337 332 338 333 map<int, CArray<double,1>* >::iterator it; … … 341 336 msgs.push_back(CMessage()); 342 337 CMessage& msg = msgs.back(); 343 msg << getId() << getNStep() << *it->second; 338 msg << getId(); 339 if (hasData) 340 msg << getNStep() - 1 << *it->second; 341 else 342 msg << SIZE_MAX; 344 343 event.push(it->first, grid->nbSenders[it->first], msg); 345 344 } 346 345 client->sendEvent(event); 347 348 incrementNStep(); 346 } 347 348 bool CField::readField(void) 349 { 350 if (!getRelFile()->allDomainEmpty) 351 { 352 if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 353 { 354 if (data_srv.empty()) 355 { 356 for (map<int, CArray<size_t, 1>* >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it) 357 data_srv.insert(pair<int, CArray<double,1>*>(it->first, new CArray<double,1>(it->second->numElements()))); 358 } 359 360 getRelFile()->checkFile(); 361 this->incrementNStep(); 362 363 if (!nstepMax) 364 { 365 nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this)); 366 } 367 368 if (getNStep() > nstepMax) 369 return false; 370 371 getRelFile()->getDataInput()->readFieldData(CField::get(this)); 372 } 373 } 374 375 return true; 349 376 } 350 377 … … 373 400 { 374 401 int rank = ranks[i]; 375 CArray<int,1>& index = *grid->storeIndex_toSrv[rank]; 376 CArray<double,1> data_tmp(index.numElements()); 377 *buffers[i] >> record >> data_tmp; 378 379 for (int n = 0; n < data_tmp.numElements(); n++) 380 instantData(index(n)) = data_tmp(n); 381 } 382 383 for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it) 384 it->first->setSlot(it->second); 385 386 if (!hasExpression) // Should be always true ? 387 { 388 const std::vector<CField*>& refField = getAllReference(); 389 std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end(); 390 391 for (; it != end; it++) (*it)->setDataFromExpression(instantData); 392 if (hasFieldOut) updateDataFromExpression(instantData); 402 *buffers[i] >> record; 403 isEOF = (record == SIZE_MAX); 404 405 if (!isEOF) 406 { 407 CArray<int,1>& index = *grid->storeIndex_toSrv[rank]; 408 CArray<double,1> data_tmp(index.numElements()); 409 *buffers[i] >> data_tmp; 410 for (int n = 0; n < data_tmp.numElements(); n++) 411 instantData(index(n)) = data_tmp(n); 412 } 413 else 414 break; 415 } 416 417 if (!isEOF) 418 { 419 for (list< pair<CField*, int> >::iterator it = fieldDependency.begin(); it != fieldDependency.end(); ++it) 420 it->first->setSlot(it->second); 421 422 if (!hasExpression) // Should be always true ? 423 { 424 const std::vector<CField*>& refField = getAllReference(); 425 std::vector<CField*>::const_iterator it = refField.begin(), end = refField.end(); 426 427 for (; it != end; it++) (*it)->setDataFromExpression(instantData); 428 if (hasFieldOut) updateDataFromExpression(instantData); 429 } 393 430 } 394 431 … … 437 474 { 438 475 this->nstep = 0; 476 } 477 478 void CField::resetNStepMax(void) 479 { 480 this->nstepMax = 0; 439 481 } 440 482 … … 761 803 } 762 804 805 void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 806 { 807 map<int, CArray<double,1>* >::iterator it; 808 for (it = data_srv.begin(); it != data_srv.end(); it++) *it->second = *it->second * scaleFactor + addOffset; 809 } 810 763 811 void CField::outputField(CArray<double,3>& fieldOut) 764 812 { … … 786 834 { 787 835 grid->outputField(it->first,*it->second, fieldOut.dataFirst()) ; 836 } 837 } 838 839 void CField::inputField(CArray<double,3>& fieldOut) 840 { 841 map<int, CArray<double,1>*>::iterator it; 842 for (it = data_srv.begin(); it != data_srv.end(); it++) 843 { 844 grid->inputField(it->first, fieldOut.dataFirst(), *it->second); 845 } 846 } 847 848 void CField::inputField(CArray<double,2>& fieldOut) 849 { 850 map<int, CArray<double,1>*>::iterator it; 851 for(it = data_srv.begin(); it != data_srv.end(); it++) 852 { 853 grid->inputField(it->first, fieldOut.dataFirst(), *it->second); 854 } 855 } 856 857 void CField::inputField(CArray<double,1>& fieldOut) 858 { 859 map<int, CArray<double,1>*>::iterator it; 860 for (it = data_srv.begin(); it != data_srv.end(); it++) 861 { 862 grid->inputField(it->first, fieldOut.dataFirst(), *it->second); 788 863 } 789 864 } -
XIOS/trunk/src/node/field.hpp
r598 r599 89 89 void incrementNStep(void); 90 90 void resetNStep() ; 91 void resetNStepMax(); 91 92 92 93 template <int N> bool updateData(const CArray<double, N>& data); … … 138 139 static void recvReadDataRequest(CEventServer& event); 139 140 void recvReadDataRequest(void); 141 bool readField(void); 140 142 static void recvReadDataReady(CEventServer& event); 141 143 void recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers); … … 143 145 void outputField(CArray<double,2>& fieldOut) ; 144 146 void outputField(CArray<double,1>& fieldOut) ; 147 void inputField(CArray<double,3>& fieldOut); 148 void inputField(CArray<double,2>& fieldOut); 149 void inputField(CArray<double,1>& fieldOut); 145 150 void scaleFactorAddOffset(double scaleFactor, double addOffset) ; 151 void invertScaleFactorAddOffset(double scaleFactor, double addOffset); 146 152 void parse(xml::CXMLNode & node) ; 147 153 CArray<double,1>* getInstantData(void) ; … … 176 182 CDuration freq_operation_srv, freq_write_srv; 177 183 178 StdSize nstep; 184 StdSize nstep, nstepMax; 185 bool isEOF; 179 186 boost::shared_ptr<CDate> last_Write, last_operation; 180 187 boost::shared_ptr<CDate> lastlast_Write_srv,last_Write_srv, last_operation_srv; -
XIOS/trunk/src/node/field_impl.hpp
r598 r599 190 190 context->checkBuffersAndListen(); 191 191 192 if (isEOF) 193 ERROR("void CField::getData(CArray<double, N>& _data) const", 194 << "Impossible to access field data, all the records of the field [ id = " << getId() << " ] have been already read."); 195 192 196 grid->outputField(instantData, _data); 193 197 } -
XIOS/trunk/src/node/file.cpp
r598 r599 5 5 #include "group_template.hpp" 6 6 #include "object_factory.hpp" 7 #include "data_output.hpp"8 7 #include "context.hpp" 9 8 #include "context_server.hpp" 10 9 #include "nc4_data_output.hpp" 10 #include "nc4_data_input.hpp" 11 11 #include "calendar_util.hpp" 12 12 #include "date.hpp" … … 48 48 //---------------------------------------------------------------- 49 49 /*! 50 \brief Get data that will be written out.50 \brief Get data writer object. 51 51 Each enabled file in xml represents a physical netcdf file. 52 This function allows to access t o data to be written out into netcdf file53 \return data writ ten out.52 This function allows to access the data writer object. 53 \return data writer object. 54 54 */ 55 55 boost::shared_ptr<CDataOutput> CFile::getDataOutput(void) const 56 56 { 57 return (data_out); 57 return data_out; 58 } 59 60 /*! 61 \brief Get data reader object. 62 Each enabled file in xml represents a physical netcdf file. 63 This function allows to access the data reader object. 64 \return data reader object. 65 */ 66 boost::shared_ptr<CDataInput> CFile::getDataInput(void) const 67 { 68 return data_in; 58 69 } 59 70 … … 239 250 void CFile::checkFile(void) 240 251 { 241 if (!isOpen) createHeader() ; 242 checkSync() ; 243 checkSplit() ; 252 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 253 { 254 if (!isOpen) createHeader(); 255 checkSync(); 256 } 257 else 258 { 259 if (!isOpen) openInReadMode(); 260 } 261 checkSplit(); 244 262 } 245 246 263 247 264 /*! … … 283 300 *lastSplit = *lastSplit + split_freq.getValue(); 284 301 std::vector<CField*>::iterator it, end = this->enabledFields.end(); 285 for (it = this->enabledFields.begin() ;it != end; it++) (*it)->resetNStep() ; 286 createHeader() ; 302 for (it = this->enabledFields.begin(); it != end; it++) 303 { 304 (*it)->resetNStep(); 305 (*it)->resetNStepMax(); 306 } 307 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 308 createHeader() ; 309 else 310 openInReadMode(); 287 311 return true ; 288 312 } … … 398 422 } 399 423 424 /*! 425 \brief Open an existing NetCDF file in read-only mode 426 */ 427 void CFile::openInReadMode(void) 428 { 429 CContext* context = CContext::getCurrent(); 430 CContextServer* server=context->server; 431 432 if (!allDomainEmpty) 433 { 434 StdString filename = (!name.isEmpty()) ? name.getValue() : getId(); 435 StdOStringStream oss; 436 oss << filename; 437 if (!name_suffix.isEmpty()) oss << name_suffix.getValue(); 438 439 if (!split_freq.isEmpty()) 440 { 441 string splitFormat; 442 if (split_freq_format.isEmpty()) 443 { 444 if (split_freq.getValue().second != 0) splitFormat = "%y%mo%d%h%mi%s"; 445 else if (split_freq.getValue().minute != 0) splitFormat = "%y%mo%d%h%mi"; 446 else if (split_freq.getValue().hour != 0) splitFormat = "%y%mo%d%h"; 447 else if (split_freq.getValue().day != 0) splitFormat = "%y%mo%d"; 448 else if (split_freq.getValue().month != 0) splitFormat = "%y%mo"; 449 else splitFormat = "%y"; 450 } 451 else splitFormat=split_freq_format; 452 oss << "_" << lastSplit->getStr(splitFormat) 453 << "-" << (*lastSplit + split_freq.getValue() - 1 * Second).getStr(splitFormat); 454 } 455 456 bool multifile = true; 457 if (!type.isEmpty()) 458 { 459 if (type == type_attr::one_file) multifile = false; 460 else if (type == type_attr::multiple_file) multifile = true; 461 } 462 #ifndef USING_NETCDF_PAR 463 if (!multifile) 464 { 465 info(0) << "!!! Warning -> Using non parallel version of netcdf, switching in multiple_file mode for file : " << filename << " ..." << endl; 466 multifile = true; 467 } 468 #endif 469 if (multifile) 470 { 471 int commSize, commRank; 472 MPI_Comm_size(fileComm, &commSize); 473 MPI_Comm_rank(fileComm, &commRank); 474 475 if (server->intraCommSize > 1) 476 { 477 oss << "_" ; 478 int width = 0, n = commSize - 1; 479 while (n != 0) { n = n / 10; width++; } 480 if (!min_digits.isEmpty() && width < min_digits) 481 width = min_digits; 482 oss.width(width); 483 oss.fill('0'); 484 oss << right << commRank; 485 } 486 } 487 oss << ".nc"; 488 489 bool isCollective = par_access.isEmpty() || par_access == par_access_attr::collective; 490 491 if (isOpen) data_out->closeFile(); 492 493 data_in = shared_ptr<CDataInput>(new CNc4DataInput(oss.str(), fileComm, multifile, isCollective)); 494 isOpen = true; 495 } 496 } 497 400 498 //! Close file 401 499 void CFile::close(void) … … 406 504 if (isOpen) 407 505 { 408 this->data_out->closeFile(); 506 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 507 this->data_out->closeFile(); 508 else 509 this->data_in->closeFile(); 409 510 } 410 511 if (fileComm != MPI_COMM_NULL) MPI_Comm_free(&fileComm) ; -
XIOS/trunk/src/node/file.hpp
r598 r599 6 6 #include "field.hpp" 7 7 #include "data_output.hpp" 8 #include "data_input.hpp" 8 9 #include "declare_group.hpp" 9 10 #include "date.hpp" … … 69 70 /// Accesseurs /// 70 71 boost::shared_ptr<CDataOutput> getDataOutput(void) const; 72 boost::shared_ptr<CDataInput> getDataInput(void) const; 71 73 CFieldGroup* getVirtualFieldGroup(void) const; 72 74 CVariableGroup* getVirtualVariableGroup(void) const; … … 94 96 95 97 void createHeader(void); 98 void openInReadMode(void); 96 99 void close(void) ; 97 100 … … 162 165 CVariableGroup* vVariableGroup ; 163 166 boost::shared_ptr<CDataOutput> data_out; 167 boost::shared_ptr<CDataInput> data_in; 164 168 std::vector<CField*> enabledFields; 165 169 -
XIOS/trunk/src/node/grid.cpp
r598 r599 507 507 } 508 508 509 void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored) 510 { 511 CArray<size_t,1>& out_i = *outIndexFromClient[rank]; 512 StdSize numElements = stored.numElements(); 513 for (StdSize n = 0; n < numElements; ++n) 514 { 515 stored(n) = *(field+out_i(n)); 516 } 517 } 518 509 519 //---------------------------------------------------------------- 510 520 -
XIOS/trunk/src/node/grid.hpp
r598 r599 106 106 CArray<double, 1>& storedServer) const; 107 107 108 void outputField(int rank, const CArray<double,1>& stored, CArray<double,3>& field) ; 109 void outputField(int rank, const CArray<double,1>& stored, CArray<double,2>& field) ; 110 void outputField(int rank, const CArray<double,1>& stored, CArray<double,1>& field) ; 111 void outputField(int rank, const CArray<double,1>& stored, double* field); 108 void outputField(int rank, const CArray<double,1>& stored, double* field); 109 void inputField(int rank, const double* const field, CArray<double,1>& stored); 112 110 113 111 virtual void parse(xml::CXMLNode & node); -
XIOS/trunk/src/output/onetcdf4.hpp
r591 r599 1 #ifndef __XIOS_ INETCDF4__2 #define __XIOS_ INETCDF4__1 #ifndef __XIOS_ONETCDF4__ 2 #define __XIOS_ONETCDF4__ 3 3 4 4 /// XIOS headers /// … … 130 130 } // namespace xios 131 131 132 #endif //__XIOS_ INETCDF4__132 #endif //__XIOS_ONETCDF4__
Note: See TracChangeset
for help on using the changeset viewer.