Changeset 1460 for XIOS/dev/branch_openmp/src/io
- Timestamp:
- 03/22/18 10:43:20 (6 years ago)
- Location:
- XIOS/dev/branch_openmp/src/io
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/dev/branch_openmp/src/io/inetcdf4.cpp
r1362 r1460 85 85 std::pair<nc_type, StdSize> retvalue; 86 86 int grpid = this->getGroup(path); 87 int varid = (var != NULL ) ? this->getVariable(*var, path) : NC_GLOBAL;87 int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL; 88 88 CNetCdfInterface::inqAtt(grpid, varid, attname, retvalue.first, retvalue.second); 89 89 return retvalue; … … 218 218 int nbdim = 0, *dimid = NULL; 219 219 int grpid = this->getGroup(path); 220 int varid = (var != NULL ) ? this->getVariable(*var, path) : NC_GLOBAL;220 int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL; 221 221 std::list<StdString> retvalue; 222 222 223 if (var != NULL )223 if (var != NULL && this->hasVariable(*var, path)) 224 224 { 225 225 CNetCdfInterface::inqVarNDims(grpid, varid, nbdim); … … 249 249 int nbdim = 0, *dimid = NULL; 250 250 int grpid = this->getGroup(path); 251 int varid = (var != NULL ) ? this->getVariable(*var, path) : NC_GLOBAL;251 int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL; 252 252 std::map<StdString, StdSize> retvalue; 253 253 254 if (var != NULL )254 if (var != NULL && this->hasVariable(*var, path)) 255 255 { 256 256 CNetCdfInterface::inqVarNDims(grpid, varid, nbdim); … … 284 284 std::list<StdString> retvalue; 285 285 int grpid = this->getGroup(path); 286 int varid = (var != NULL ) ? this->getVariable(*var, path) : NC_GLOBAL;287 288 if (var != NULL )286 int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL; 287 288 if (var != NULL && this->hasVariable(*var, path)) 289 289 CNetCdfInterface::inqVarNAtts(grpid, varid, nbatt); 290 290 else … … 378 378 { 379 379 int grpid = this->getGroup(path); 380 int varid = (var != NULL ) ? this->getVariable(*var, path) : NC_GLOBAL;380 int varid = (var != NULL && this->hasVariable(*var, path)) ? this->getVariable(*var, path) : NC_GLOBAL; 381 381 std::pair<nc_type , StdSize> attinfos = this->getAttribute(name, var, path); 382 382 std::vector<T> retvalue(attinfos.second); … … 496 496 bool CINetCDF4::isRectilinear(const StdString& name, const CVarPath* const path) 497 497 { 498 std::list<StdString> coords = this->getCoordinatesIdList(name, path); 499 std::list<StdString>::const_iterator it = coords.begin(), end = coords.end(); 498 std::list<StdString> varCoords = this->getCoordinatesIdList(name, path); 499 std::list<StdString> varDims = this->getDimensionsList(&name, path); 500 std::list<StdString>::const_iterator it = varCoords.begin(), end = varCoords.end(); 501 std::set<StdString> varDims1D; 502 503 // Firstly, loop over coordinate list 500 504 for (; it != end; it++) 501 505 { 502 506 const StdString& coord = *it; 503 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path)) 504 { 505 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); 506 if ((dimvar.size() == 1) && (dimvar.find(coord) != dimvar.end())) 507 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) ) 508 { 509 std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path); 510 for (std::map<StdString, StdSize>::const_iterator itTmp = coordDims.begin(); itTmp != coordDims.end(); itTmp++) 511 { 512 varDims.remove(itTmp->first); 513 } 514 if (this->isLonOrLat(coord, path) && coordDims.size() == 1) 515 { 516 varDims1D.insert(coordDims.begin()->first); 507 517 continue; 508 else 509 return false; 510 } 511 } 512 return true; 518 } 519 } 520 } 521 // Secondly, loop over remaining dimensions 522 for (it= varDims.begin(); it != varDims.end(); it++) 523 { 524 const StdString& coord = *it; 525 std::map<StdString, StdSize> coordDims = this->getDimensions(&coord, path); 526 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) ) 527 { 528 if (this->isLonOrLat(coord, path) && coordDims.size() == 1) 529 { 530 varDims1D.insert(coordDims.begin()->first); 531 continue; 532 } 533 } 534 } 535 536 return (varDims1D.size() == 2); 513 537 } 514 538 … … 525 549 { 526 550 const StdString& coord = *it; 527 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )551 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path)) 528 552 { 529 553 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); … … 552 576 { 553 577 const StdString& coord = *it; 554 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) )578 if (this->hasVariable(coord, path) && !this->isTemporal(coord, path) && this->isLonOrLat(coord, path)) 555 579 { 556 580 std::map<StdString, StdSize> dimvar = this->getDimensions(&coord, path); … … 782 806 return *(++(++clist.rbegin())); 783 807 } 808 809 bool CINetCDF4::isLonOrLat(const StdString& varname, const CVarPath* const path) 810 { 811 if (this->hasAttribute(CCFKeywords::XIOS_CF_units, &varname, path)) 812 { 813 StdString unit = this->getAttributeValue(CCFKeywords::XIOS_CF_units, &varname, path); 814 return (CCFConvention::XIOS_CF_Latitude_units.end() != CCFConvention::XIOS_CF_Latitude_units.find(unit) 815 || CCFConvention::XIOS_CF_Longitude_units.end() != CCFConvention::XIOS_CF_Longitude_units.find(unit)); 816 } 817 } 818 784 819 } // namespace xios -
XIOS/dev/branch_openmp/src/io/inetcdf4.hpp
r1328 r1460 135 135 bool isCellGrid(const StdString& name, const CVarPath* const path = NULL); 136 136 137 bool isLonOrLat(const StdString& varname, const CVarPath* const path = NULL); 138 137 139 protected: 138 140 /// Getters /// -
XIOS/dev/branch_openmp/src/io/nc4_data_input.cpp
r1338 r1460 188 188 listDimSize.push_front(*itMap); 189 189 */ 190 for (std::list<StdString>::const_iterator it = dimList.begin(); it != dimList.end(); ++it) 191 listDimSize.push_front(*dimSizeMap.find(*it)); 190 191 if (!SuperClassWriter::isRectilinear(fieldId)) 192 { 193 for (std::list<StdString>::const_iterator it = dimList.begin(); it != dimList.end(); ++it) 194 listDimSize.push_front(*dimSizeMap.find(*it)); 195 } 196 else 197 { 198 std::list<StdString> coords = SuperClassWriter::getCoordinatesIdList(fieldId); 199 std::list<StdString>::const_iterator itCoord = coords.begin(); 200 for (; itCoord != coords.end(); itCoord++) 201 { 202 const StdString& coord = *itCoord; 203 if (SuperClassWriter::hasVariable(coord) && !SuperClassWriter::isTemporal(coord)) 204 { 205 std::map<StdString, StdSize> dimsTmp = SuperClassWriter::getDimensions(&coord); 206 StdString dimNameTmp = dimsTmp.begin()->first; 207 StdSize dimSizeTmp = dimsTmp.begin()->second; 208 listDimSize.push_front(make_pair(coord, dimSizeTmp)); 209 dimSizeMap.erase(dimNameTmp); 210 dimList.remove(dimNameTmp); 211 } 212 } 213 for (std::list<StdString>::const_iterator it = dimList.begin(); it != dimList.end(); ++it) 214 listDimSize.push_front(*dimSizeMap.find(*it)); 215 } 192 216 193 217 // Now process domain and axis … … 268 292 if ((CDomain::type_attr::rectilinear == domain->type)) 269 293 { 270 // Ok, try to read some f..attributes such as longitude and latitude294 // Ok, try to read some attributes such as longitude and latitude 271 295 bool hasLat = SuperClassWriter::hasVariable(itMapNj->first); 272 296 if (hasLat) … … 287 311 else if ((CDomain::type_attr::curvilinear == domain->type)) 288 312 { 289 int ni = domain->ni; 290 int nj = domain->nj; 313 // Make sure that if there is no local domain defined on a process, the process still reads just one value. 314 int ni, nj, ibegin, jbegin; 315 if (domain->ni == 0) 316 { 317 ni = 1; 318 ibegin = 0; 319 } 320 else 321 { 322 ni = domain->ni; 323 ibegin = domain->ibegin; 324 } 325 if (domain->nj == 0) 326 { 327 nj = 1; 328 jbegin = 0; 329 } 330 else 331 { 332 nj = domain->nj; 333 jbegin = domain->jbegin; 334 } 335 291 336 std::vector<StdSize> nBeginLatLon(2), nSizeLatLon(2); 292 nBeginLatLon[0] = 0; nBeginLatLon[1] = 0;293 nSizeLatLon[0] = domain->nj_glo.getValue(); nSizeLatLon[1] = domain->ni_glo.getValue();337 nBeginLatLon[0] = jbegin; nBeginLatLon[1] = ibegin; 338 nSizeLatLon[0] = nj; nSizeLatLon[1] = ni; 294 339 295 340 StdString latName = this->getLatCoordName(fieldId); 296 341 if (SuperClassWriter::hasVariable(latName)) 297 342 { 298 domain->latvalue_curvilinear_read_from_file.resize( domain->ni_glo,domain->nj_glo);343 domain->latvalue_curvilinear_read_from_file.resize(ni, nj); 299 344 readFieldVariableValue(domain->latvalue_curvilinear_read_from_file, latName, nBeginLatLon, nSizeLatLon); 300 345 } … … 302 347 if (SuperClassWriter::hasVariable(lonName)) 303 348 { 304 domain->lonvalue_curvilinear_read_from_file.resize( domain->ni_glo,domain->nj_glo);349 domain->lonvalue_curvilinear_read_from_file.resize(ni, nj); 305 350 readFieldVariableValue(domain->lonvalue_curvilinear_read_from_file, lonName, nBeginLatLon, nSizeLatLon); 306 351 } … … 309 354 StdString boundsLonName = this->getBoundsId(lonName); 310 355 311 int nbVertex = this->getNbVertex(fieldId);356 int nbVertex = 4; //this->getNbVertex(fieldId); 312 357 if (!domain->nvertex.isEmpty() && (domain->nvertex != nbVertex)) 313 358 { … … 324 369 325 370 std::vector<StdSize> nBeginBndsLatLon(3), nSizeBndsLatLon(3); 326 nBeginBndsLatLon[0] = 0; nSizeBndsLatLon[0] = domain->nj_glo.getValue();327 nBeginBndsLatLon[1] = 0; nSizeBndsLatLon[1] = domain->ni_glo.getValue();371 nBeginBndsLatLon[0] = jbegin; nSizeBndsLatLon[0] = nj; 372 nBeginBndsLatLon[1] = ibegin; nSizeBndsLatLon[1] = ni; 328 373 nBeginBndsLatLon[2] = 0; nSizeBndsLatLon[2] = nbVertex; 329 374 330 375 if (SuperClassWriter::hasVariable(boundsLatName)) 331 376 { 332 domain->bounds_latvalue_curvilinear_read_from_file.resize(nbVertex, domain->ni_glo,domain->nj_glo);377 domain->bounds_latvalue_curvilinear_read_from_file.resize(nbVertex, ni, nj); 333 378 readFieldVariableValue(domain->bounds_latvalue_curvilinear_read_from_file, boundsLatName, nBeginBndsLatLon, nSizeBndsLatLon); 334 379 … … 336 381 if (SuperClassWriter::hasVariable(boundsLonName)) 337 382 { 338 domain->bounds_lonvalue_curvilinear_read_from_file.resize(nbVertex, domain->ni_glo,domain->nj_glo);383 domain->bounds_lonvalue_curvilinear_read_from_file.resize(nbVertex, ni, nj); 339 384 readFieldVariableValue(domain->bounds_lonvalue_curvilinear_read_from_file, boundsLonName, nBeginBndsLatLon, nSizeBndsLatLon); 340 385 } … … 342 387 else if ((CDomain::type_attr::unstructured == domain->type))// || (this->isUnstructured(fieldId))) 343 388 { 389 // Make sure that if there is no local domain defined on a process, the process still reads just one value. 390 int ni, ibegin; 391 if (domain->ni == 0) 392 { 393 ni = 1; 394 ibegin = 0; 395 } 396 else 397 { 398 ni = domain->ni; 399 ibegin = domain->ibegin; 400 } 401 344 402 std::vector<StdSize> nBeginLatLon(1,0), nSizeLatLon(1,0); 345 n SizeLatLon[0] = domain->ni_glo.getValue();346 CArray<double,1> globalLonLat(domain->ni_glo.getValue());403 nBeginLatLon[0] = ibegin; 404 nSizeLatLon[0] = ni; 347 405 348 406 StdString latName = this->getLatCoordName(fieldId); 349 407 if (SuperClassWriter::hasVariable(latName)) 350 408 { 351 domain->latvalue_unstructured_read_from_file.resize( domain->ni_glo);409 domain->latvalue_unstructured_read_from_file.resize(ni); 352 410 readFieldVariableValue(domain->latvalue_unstructured_read_from_file, latName, nBeginLatLon, nSizeLatLon); 353 411 } … … 356 414 if (SuperClassWriter::hasVariable(lonName)) //(0 != lonName.compare("")) 357 415 { 358 // readFieldVariableValue(globalLonLat, lonName, nBeginLatLon, nSizeLatLon); 359 domain->lonvalue_unstructured_read_from_file.resize(domain->ni_glo); 416 domain->lonvalue_unstructured_read_from_file.resize(ni); 360 417 readFieldVariableValue(domain->lonvalue_unstructured_read_from_file, lonName, nBeginLatLon, nSizeLatLon); 361 418 } … … 379 436 380 437 std::vector<StdSize> nBeginBndsLatLon(2), nSizeBndsLatLon(2); 381 nBeginBndsLatLon[0] = 0; nSizeBndsLatLon[0] = domain->ni_glo.getValue();438 nBeginBndsLatLon[0] = ibegin; nSizeBndsLatLon[0] = ni; 382 439 nBeginBndsLatLon[1] = 0; nSizeBndsLatLon[1] = nbVertex; 383 440 … … 496 553 497 554 { // Read axis value 498 std::vector<StdSize> nBegin(1, 0), nSize(1, itMapN->second); 499 CArray<double,1> readAxisValue(itMapN->second); 500 readFieldVariableValue(readAxisValue, itMapN->first, nBegin, nSize, true); 501 int begin = 0, n = itMapN->second; 502 if (!axis->begin.isEmpty()) begin = axis->begin.getValue(); 503 if (!axis->n.isEmpty()) n = axis->n.getValue(); 504 axis->value.resize(n); 505 for (int i = 0; i < n; ++i) axis->value(i) = readAxisValue(begin + i); 555 bool hasValue = SuperClassWriter::hasVariable(itMapN->first); 556 if (hasValue) 557 { 558 std::vector<StdSize> nBegin(1, 0), nSize(1, itMapN->second); 559 CArray<double,1> readAxisValue(itMapN->second); 560 readFieldVariableValue(readAxisValue, itMapN->first, nBegin, nSize, true); 561 int begin = 0, n = itMapN->second; 562 if (!axis->begin.isEmpty()) begin = axis->begin.getValue(); 563 if (!axis->n.isEmpty()) n = axis->n.getValue(); 564 axis->value.resize(n); 565 for (int i = 0; i < n; ++i) axis->value(i) = readAxisValue(begin + i); 566 } 506 567 } 507 568 } -
XIOS/dev/branch_openmp/src/io/nc4_data_output.cpp
r1328 r1460 1 1 #include "nc4_data_output.hpp" 2 2 3 #include <boost/lexical_cast.hpp>4 3 #include "attribute_template.hpp" 5 4 #include "group_template.hpp" … … 24 23 { 25 24 SuperClass::type = MULTI_FILE; 25 compressionLevel= file->compression_level.isEmpty() ? 0 :file->compression_level ; 26 26 } 27 27 … … 37 37 { 38 38 SuperClass::type = (multifile) ? MULTI_FILE : ONE_FILE; 39 if (file==NULL) compressionLevel = 0 ; 40 else compressionLevel= file->compression_level.isEmpty() ? 0 :file->compression_level ; 39 41 } 40 42 … … 53 55 void CNc4DataOutput::writeDomain_(CDomain* domain) 54 56 { 57 StdString lonName,latName ; 58 59 domain->computeWrittenIndex(); 60 domain->computeWrittenCompressedIndex(comm_file); 61 55 62 if (domain->type == CDomain::type_attr::unstructured) 56 63 { … … 76 83 if (isWrittenDomain(domid)) return ; 77 84 else setWrittenDomain(domid); 85 86 int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex; 78 87 79 88 … … 89 98 { 90 99 case CDomain::type_attr::curvilinear : 91 dimXid = StdString("x").append(appendDomid); 92 dimYid = StdString("y").append(appendDomid); 100 101 if (domain->lon_name.isEmpty()) lonName = "nav_lon"; 102 else lonName = domain->lon_name; 103 104 if (domain->lat_name.isEmpty()) latName = "nav_lat"; 105 else latName = domain->lat_name; 106 107 if (domain->dim_i_name.isEmpty()) dimXid=StdString("x").append(appendDomid); 108 else dimXid=domain->dim_i_name.getValue() + appendDomid; 109 110 if (domain->dim_j_name.isEmpty()) dimYid=StdString("y").append(appendDomid); 111 else dimYid=domain->dim_j_name.getValue() + appendDomid; 112 93 113 break ; 114 94 115 case CDomain::type_attr::rectilinear : 95 dimXid = StdString("lon").append(appendDomid); 96 dimYid = StdString("lat").append(appendDomid); 116 117 if (domain->lon_name.isEmpty()) 118 { 119 if (domain->dim_i_name.isEmpty()) 120 lonName = "lon"; 121 else 122 lonName = domain->dim_i_name.getValue(); 123 } 124 else lonName = domain->lon_name; 125 126 if (domain->lat_name.isEmpty()) 127 { 128 if (domain->dim_j_name.isEmpty()) 129 latName = "lat"; 130 else 131 latName = domain->dim_j_name.getValue(); 132 } 133 else latName = domain->lat_name; 134 135 if (domain->dim_i_name.isEmpty()) dimXid = lonName+appendDomid; 136 else dimXid = domain->dim_i_name.getValue()+appendDomid; 137 138 if (domain->dim_j_name.isEmpty()) dimYid = latName+appendDomid; 139 else dimYid = domain->dim_j_name.getValue()+appendDomid; 97 140 break; 98 141 } … … 111 154 */ 112 155 156 CArray<size_t, 1>& indexToWrite = domain->localIndexToWriteOnServer; 157 int nbWritten = indexToWrite.numElements(); 158 CArray<double,1> writtenLat, writtenLon; 159 CArray<double,2> writtenBndsLat, writtenBndsLon; 160 CArray<double,1> writtenArea; 161 162 if (domain->hasLonLat) 163 { 164 writtenLat.resize(nbWritten); 165 writtenLon.resize(nbWritten); 166 for (int idx = 0; idx < nbWritten; ++idx) 167 { 168 if (idx < domain->latvalue.numElements()) 169 { 170 writtenLat(idx) = domain->latvalue(indexToWrite(idx)); 171 writtenLon(idx) = domain->lonvalue(indexToWrite(idx)); 172 } 173 else 174 { 175 writtenLat(idx) = 0.; 176 writtenLon(idx) = 0.; 177 } 178 } 179 180 181 if (domain->hasBounds) 182 { 183 int nvertex = domain->nvertex, idx; 184 writtenBndsLat.resize(nvertex, nbWritten); 185 writtenBndsLon.resize(nvertex, nbWritten); 186 CArray<double,2>& boundslat = domain->bounds_latvalue; 187 CArray<double,2>& boundslon = domain->bounds_lonvalue; 188 for (idx = 0; idx < nbWritten; ++idx) 189 for (int nv = 0; nv < nvertex; ++nv) 190 { 191 if (idx < boundslat.columns()) 192 { 193 writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx))); 194 writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx))); 195 } 196 else 197 { 198 writtenBndsLat(nv, idx) = 0.; 199 writtenBndsLon(nv, idx) = 0.; 200 } 201 } 202 } 203 } 204 205 if (domain->hasArea) 206 { 207 writtenArea.resize(nbWritten); 208 for (int idx = 0; idx < nbWritten; ++idx) 209 { 210 if (idx < domain->areavalue.numElements()) 211 writtenArea(idx) = domain->areavalue(indexToWrite(idx)); 212 else 213 writtenArea(idx) = 0.; 214 } 215 } 216 113 217 try 114 218 { … … 129 233 case CDomain::type_attr::curvilinear : 130 234 dim0.push_back(dimYid); dim0.push_back(dimXid); 131 lonid = StdString("nav_lon").append(appendDomid);132 latid = StdString("nav_lat").append(appendDomid);235 lonid = lonName+appendDomid; 236 latid = latName+appendDomid; 133 237 break ; 134 238 case CDomain::type_attr::rectilinear : 135 lonid = StdString("lon").append(appendDomid);136 latid = StdString("lat").append(appendDomid);239 lonid = lonName+appendDomid; 240 latid = latName+appendDomid; 137 241 dim0.push_back(dimYid); 138 242 dim1.push_back(dimXid); 139 243 break; 140 244 } 141 142 bounds_lonid = StdString("bounds_lon").append(appendDomid); 143 bounds_latid = StdString("bounds_lat").append(appendDomid); 144 145 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv); 146 SuperClassWriter::addDimension(dimYid, domain->zoom_nj_srv); 245 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name; 246 else bounds_lonid = "bounds_"+lonName+appendDomid; 247 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name; 248 else bounds_latid = "bounds_"+latName+appendDomid; 249 250 SuperClassWriter::addDimension(dimXid, domain->zoom_ni); 251 SuperClassWriter::addDimension(dimYid, domain->zoom_nj); 147 252 148 253 if (domain->hasBounds) … … 151 256 if (server->intraCommSize > 1) 152 257 { 153 this->writeLocalAttributes(domain->zoom_ibegin _srv,154 domain->zoom_ni _srv,155 domain->zoom_jbegin _srv,156 domain->zoom_nj _srv,258 this->writeLocalAttributes(domain->zoom_ibegin, 259 domain->zoom_ni, 260 domain->zoom_jbegin, 261 domain->zoom_nj, 157 262 appendDomid); 158 263 159 264 if (singleDomain) 160 265 this->writeLocalAttributes_IOIPSL(dimXid, dimYid, 161 domain->zoom_ibegin _srv,162 domain->zoom_ni _srv,163 domain->zoom_jbegin _srv,164 domain->zoom_nj _srv,266 domain->zoom_ibegin, 267 domain->zoom_ni, 268 domain->zoom_jbegin, 269 domain->zoom_nj, 165 270 domain->ni_glo,domain->nj_glo, 166 271 server->intraCommRank,server->intraCommSize); … … 172 277 { 173 278 case CDomain::type_attr::curvilinear : 174 SuperClassWriter::addVariable(latid, typePrec, dim0 );175 SuperClassWriter::addVariable(lonid, typePrec, dim0 );279 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 280 SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel); 176 281 break ; 177 282 case CDomain::type_attr::rectilinear : 178 SuperClassWriter::addVariable(latid, typePrec, dim0 );179 SuperClassWriter::addVariable(lonid, typePrec, dim1 );283 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 284 SuperClassWriter::addVariable(lonid, typePrec, dim1, compressionLevel); 180 285 break ; 181 286 } … … 193 298 dim0.push_back(dimXid); 194 299 dim0.push_back(dimVertId); 195 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0 );196 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0 );300 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel); 301 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel); 197 302 } 198 303 } … … 219 324 if (domain->hasArea) 220 325 { 221 SuperClassWriter::addVariable(areaId, typePrec, dim0 );326 SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel); 222 327 SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId); 223 328 SuperClassWriter::addAttribute("units", StdString("m2"), &areaId); … … 230 335 switch (domain->type) 231 336 { 232 case CDomain::type_attr::curvilinear : 233 SuperClassWriter::writeData( domain->latvalue_srv, latid, isCollective, 0);234 SuperClassWriter::writeData( domain->lonvalue_srv, lonid, isCollective, 0);337 case CDomain::type_attr::curvilinear : 338 SuperClassWriter::writeData(writtenLat, latid, isCollective, 0); 339 SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0); 235 340 break; 236 341 case CDomain::type_attr::rectilinear : 237 CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv)) ;342 CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->zoom_ni)) ; 238 343 SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0); 239 CArray<double,1> lon =domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1)) ;344 CArray<double,1> lon = writtenLon(Range(0,domain->zoom_ni-1)) ; 240 345 SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0); 241 346 break; … … 244 349 if (domain->hasBounds) 245 350 { 246 SuperClassWriter::writeData( domain->bounds_lon_srv, bounds_lonid, isCollective, 0);247 SuperClassWriter::writeData( domain->bounds_lat_srv, bounds_latid, isCollective, 0);351 SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0); 352 SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0); 248 353 } 249 354 } 250 355 251 356 if (domain->hasArea) 252 SuperClassWriter::writeData(domain->area_srv, areaId, isCollective, 0); 357 { 358 SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0); 359 } 253 360 254 361 SuperClassWriter::definition_start(); … … 270 377 case CDomain::type_attr::curvilinear : 271 378 dim0.push_back(dimYid); dim0.push_back(dimXid); 272 lonid = StdString("nav_lon").append(appendDomid);273 latid = StdString("nav_lat").append(appendDomid);274 SuperClassWriter::addVariable(latid, typePrec, dim0 );275 SuperClassWriter::addVariable(lonid, typePrec, dim0 );379 lonid = lonName+appendDomid; 380 latid = latName+appendDomid; 381 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 382 SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel); 276 383 break; 277 384 … … 279 386 dim0.push_back(dimYid); 280 387 dim1.push_back(dimXid); 281 lonid = StdString("lon").append(appendDomid);282 latid = StdString("lat").append(appendDomid);283 SuperClassWriter::addVariable(latid, typePrec, dim0 );284 SuperClassWriter::addVariable(lonid, typePrec, dim1 );388 lonid = lonName+appendDomid; 389 latid = latName+appendDomid; 390 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 391 SuperClassWriter::addVariable(lonid, typePrec, dim1, compressionLevel); 285 392 break; 286 393 } 287 288 bounds_lonid = StdString("bounds_lon").append(appendDomid); 289 bounds_latid = StdString("bounds_lat").append(appendDomid); 394 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name; 395 else bounds_lonid = "bounds_"+lonName+appendDomid; 396 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name; 397 else bounds_latid = "bounds_"+latName+appendDomid; 290 398 291 399 this->writeAxisAttributes … … 303 411 dim0.push_back(dimXid); 304 412 dim0.push_back(dimVertId); 305 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0 );306 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0 );413 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel); 414 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel); 307 415 } 308 416 } … … 312 420 dim0.clear(); 313 421 dim0.push_back(dimYid); dim0.push_back(dimXid); 314 SuperClassWriter::addVariable(areaId, typePrec, dim0 );422 SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel); 315 423 SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId); 316 424 SuperClassWriter::addAttribute("units", StdString("m2"), &areaId); … … 333 441 else 334 442 { 335 start[1]=domain->zoom_ibegin _srv-domain->global_zoom_ibegin;336 start[0]=domain->zoom_jbegin _srv-domain->global_zoom_jbegin;337 count[1]=domain->zoom_ni _srv ; count[0]=domain->zoom_nj_srv;443 start[1]=domain->zoom_ibegin-domain->global_zoom_ibegin; 444 start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin; 445 count[1]=domain->zoom_ni ; count[0]=domain->zoom_nj ; 338 446 } 339 447 340 448 if (domain->hasLonLat) 341 449 { 342 SuperClassWriter::writeData( domain->latvalue_srv, latid, isCollective, 0,&start,&count);343 SuperClassWriter::writeData( domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);450 SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count); 451 SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count); 344 452 } 345 453 break; … … 355 463 start[0]=0 ; 356 464 count[0]=0 ; 357 SuperClassWriter::writeData(domain->latvalue_srv, latid, isCollective, 0,&start,&count); 358 SuperClassWriter::writeData(domain->lonvalue_srv, lonid, isCollective, 0,&start,&count); 359 465 SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count); 466 SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count); 360 467 } 361 468 else 362 { 363 start[0]=domain->zoom_jbegin _srv-domain->global_zoom_jbegin;364 count[0]=domain->zoom_nj _srv ;365 CArray<double,1> lat = domain->latvalue_srv(Range(fromStart,toEnd,domain->zoom_ni_srv));469 { 470 start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin; 471 count[0]=domain->zoom_nj; 472 CArray<double,1> lat = writtenLat(Range(fromStart,toEnd,domain->zoom_ni)); 366 473 SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count); 367 474 368 start[0]=domain->zoom_ibegin _srv-domain->global_zoom_ibegin;369 count[0]=domain->zoom_ni _srv ;370 CArray<double,1> lon =domain->lonvalue_srv(Range(0,domain->zoom_ni_srv-1));475 start[0]=domain->zoom_ibegin-domain->global_zoom_ibegin; 476 count[0]=domain->zoom_ni; 477 CArray<double,1> lon = writtenLon(Range(0,domain->zoom_ni-1)); 371 478 SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count); 372 479 } … … 388 495 { 389 496 start[2] = 0; 390 start[1] = domain->zoom_ibegin _srv- domain->global_zoom_ibegin;391 start[0] = domain->zoom_jbegin _srv- domain->global_zoom_jbegin;497 start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin; 498 start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin; 392 499 count[2] = domain->nvertex; 393 count[1] = domain->zoom_ni _srv;394 count[0] = domain->zoom_nj _srv;500 count[1] = domain->zoom_ni; 501 count[0] = domain->zoom_nj; 395 502 } 396 397 SuperClassWriter::writeData(domain->bounds_lon_srv, bounds_lonid, isCollective, 0, &start, &count);398 SuperClassWriter::writeData(domain->bounds_lat_srv, bounds_latid, isCollective, 0, &start, &count);503 504 SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0, &start, &count); 505 SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0, &start, &count); 399 506 } 400 507 … … 411 518 else 412 519 { 413 start[1] = domain->zoom_ibegin _srv- domain->global_zoom_ibegin;414 start[0] = domain->zoom_jbegin _srv- domain->global_zoom_jbegin;415 count[1] = domain->zoom_ni _srv;416 count[0] = domain->zoom_nj _srv;520 start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin; 521 start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin; 522 count[1] = domain->zoom_ni; 523 count[0] = domain->zoom_nj; 417 524 } 418 419 SuperClassWriter::writeData( domain->area_srv, areaId, isCollective, 0, &start, &count);525 526 SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0, &start, &count); 420 527 } 421 528 … … 463 570 StdString domainName = domain->name; 464 571 domain->assignMesh(domainName, domain->nvertex); 465 domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue _srv, domain->latvalue_srv, domain->bounds_lon_srv, domain->bounds_lat_srv);572 domain->mesh->createMeshEpsilon(server->intraComm, domain->lonvalue, domain->latvalue, domain->bounds_lonvalue, domain->bounds_latvalue); 466 573 467 574 StdString node_x = domainName + "_node_x"; … … 489 596 { 490 597 dim0.clear(); 491 SuperClassWriter::addVariable(domainName, NC_INT, dim0 );598 SuperClassWriter::addVariable(domainName, NC_INT, dim0, compressionLevel); 492 599 SuperClassWriter::addAttribute("cf_role", StdString("mesh_topology"), &domainName); 493 600 SuperClassWriter::addAttribute("long_name", StdString("Topology data of 2D unstructured mesh"), &domainName); … … 510 617 dim0.clear(); 511 618 dim0.push_back(dimNode); 512 SuperClassWriter::addVariable(node_x, typePrec, dim0 );619 SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel); 513 620 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 514 621 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 515 622 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 516 SuperClassWriter::addVariable(node_y, typePrec, dim0 );623 SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel); 517 624 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 518 625 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); … … 529 636 dim0.clear(); 530 637 dim0.push_back(dimNode); 531 SuperClassWriter::addVariable(node_x, typePrec, dim0 );638 SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel); 532 639 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 533 640 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 534 641 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 535 SuperClassWriter::addVariable(node_y, typePrec, dim0 );642 SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel); 536 643 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 537 644 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); … … 543 650 dim0.clear(); 544 651 dim0.push_back(dimEdge); 545 SuperClassWriter::addVariable(edge_x, typePrec, dim0 );652 SuperClassWriter::addVariable(edge_x, typePrec, dim0, compressionLevel); 546 653 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x); 547 654 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x); 548 655 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x); 549 SuperClassWriter::addVariable(edge_y, typePrec, dim0 );656 SuperClassWriter::addVariable(edge_y, typePrec, dim0, compressionLevel); 550 657 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y); 551 658 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y); … … 554 661 dim0.push_back(dimEdge); 555 662 dim0.push_back(dimTwo); 556 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0 );663 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0, compressionLevel); 557 664 SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes); 558 665 SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes); … … 569 676 dim0.clear(); 570 677 dim0.push_back(dimNode); 571 SuperClassWriter::addVariable(node_x, typePrec, dim0 );678 SuperClassWriter::addVariable(node_x, typePrec, dim0, compressionLevel); 572 679 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &node_x); 573 680 SuperClassWriter::addAttribute("long_name", StdString("Longitude of mesh nodes."), &node_x); 574 681 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &node_x); 575 SuperClassWriter::addVariable(node_y, typePrec, dim0 );682 SuperClassWriter::addVariable(node_y, typePrec, dim0, compressionLevel); 576 683 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &node_y); 577 684 SuperClassWriter::addAttribute("long_name", StdString("Latitude of mesh nodes."), &node_y); … … 585 692 dim0.clear(); 586 693 dim0.push_back(dimEdge); 587 SuperClassWriter::addVariable(edge_x, typePrec, dim0 );694 SuperClassWriter::addVariable(edge_x, typePrec, dim0, compressionLevel); 588 695 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &edge_x); 589 696 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh edges."), &edge_x); 590 697 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &edge_x); 591 SuperClassWriter::addVariable(edge_y, typePrec, dim0 );698 SuperClassWriter::addVariable(edge_y, typePrec, dim0, compressionLevel); 592 699 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &edge_y); 593 700 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh edges."), &edge_y); … … 596 703 dim0.push_back(dimEdge); 597 704 dim0.push_back(dimTwo); 598 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0 );705 SuperClassWriter::addVariable(edge_nodes, NC_INT, dim0, compressionLevel); 599 706 SuperClassWriter::addAttribute("cf_role", StdString("edge_node_connectivity"), &edge_nodes); 600 707 SuperClassWriter::addAttribute("long_name", StdString("Maps every edge/link to two nodes that it connects."), &edge_nodes); … … 607 714 dim0.clear(); 608 715 dim0.push_back(dimFace); 609 SuperClassWriter::addVariable(face_x, typePrec, dim0 );716 SuperClassWriter::addVariable(face_x, typePrec, dim0, compressionLevel); 610 717 SuperClassWriter::addAttribute("standard_name", StdString("longitude"), &face_x); 611 718 SuperClassWriter::addAttribute("long_name", StdString("Characteristic longitude of mesh faces."), &face_x); 612 719 SuperClassWriter::addAttribute("units", StdString("degrees_east"), &face_x); 613 SuperClassWriter::addVariable(face_y, typePrec, dim0 );720 SuperClassWriter::addVariable(face_y, typePrec, dim0, compressionLevel); 614 721 SuperClassWriter::addAttribute("standard_name", StdString("latitude"), &face_y); 615 722 SuperClassWriter::addAttribute("long_name", StdString("Characteristic latitude of mesh faces."), &face_y); … … 618 725 dim0.push_back(dimFace); 619 726 dim0.push_back(dimVertex); 620 SuperClassWriter::addVariable(face_nodes, NC_INT, dim0 );727 SuperClassWriter::addVariable(face_nodes, NC_INT, dim0, compressionLevel); 621 728 SuperClassWriter::addAttribute("cf_role", StdString("face_node_connectivity"), &face_nodes); 622 729 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its corner nodes."), &face_nodes); … … 625 732 dim0.push_back(dimFace); 626 733 dim0.push_back(dimVertex); 627 SuperClassWriter::addVariable(face_edges, NC_INT, dim0 );734 SuperClassWriter::addVariable(face_edges, NC_INT, dim0, compressionLevel); 628 735 SuperClassWriter::addAttribute("cf_role", StdString("face_edge_connectivity"), &face_edges); 629 736 SuperClassWriter::addAttribute("long_name", StdString("Maps every face to its edges."), &face_edges); … … 633 740 dim0.push_back(dimEdge); 634 741 dim0.push_back(dimTwo); 635 SuperClassWriter::addVariable(edge_faces, NC_INT, dim0 );742 SuperClassWriter::addVariable(edge_faces, NC_INT, dim0, compressionLevel); 636 743 SuperClassWriter::addAttribute("cf_role", StdString("edge_face connectivity"), &edge_faces); 637 744 SuperClassWriter::addAttribute("long_name", StdString("neighbor faces for edges"), &edge_faces); … … 642 749 dim0.push_back(dimFace); 643 750 dim0.push_back(dimVertex); 644 SuperClassWriter::addVariable(face_faces, NC_INT, dim0 );751 SuperClassWriter::addVariable(face_faces, NC_INT, dim0, compressionLevel); 645 752 SuperClassWriter::addAttribute("cf_role", StdString("face_face connectivity"), &face_faces); 646 753 SuperClassWriter::addAttribute("long_name", StdString("Indicates which other faces neighbor each face"), &face_faces); … … 677 784 else 678 785 { 679 startNodes[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;680 countNodes[0] = domain->zoom_ni _srv;786 startNodes[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 787 countNodes[0] = domain->zoom_ni ; 681 788 } 682 789 … … 700 807 else 701 808 { 702 startEdges[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;703 countEdges[0] = domain->zoom_ni _srv;809 startEdges[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 810 countEdges[0] = domain->zoom_ni; 704 811 startNodes[0] = domain->mesh->node_start; 705 812 countNodes[0] = domain->mesh->node_count; 706 startEdgeNodes[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;813 startEdgeNodes[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 707 814 startEdgeNodes[1] = 0; 708 countEdgeNodes[0] = domain->zoom_ni _srv;709 countEdgeNodes[1] = 2;815 countEdgeNodes[0] = domain->zoom_ni; 816 countEdgeNodes[1] = 2; 710 817 } 711 818 SuperClassWriter::writeData(domain->mesh->node_lat, node_y, isCollective, 0, &startNodes, &countNodes); … … 736 843 else 737 844 { 738 startFaces[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;739 countFaces[0] = domain->zoom_ni _srv;845 startFaces[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 846 countFaces[0] = domain->zoom_ni ; 740 847 startNodes[0] = domain->mesh->node_start; 741 848 countNodes[0] = domain->mesh->node_count; … … 750 857 countEdgeFaces[0] = domain->mesh->edge_count; 751 858 countEdgeFaces[1]= 2; 752 startFaceConctv[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;753 startFaceConctv[1] = 0; 754 countFaceConctv[0] = domain->zoom_ni _srv;859 startFaceConctv[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 860 startFaceConctv[1] = 0; 861 countFaceConctv[0] = domain->zoom_ni; 755 862 countFaceConctv[1] = domain->nvertex; 756 863 } … … 773 880 if (domain->nvertex == 2) 774 881 { 775 startEdges[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;776 countEdges[0] = domain->zoom_ni _srv;777 startEdgeNodes[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;882 startEdges[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 883 countEdges[0] = domain->zoom_ni; 884 startEdgeNodes[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 778 885 startEdgeNodes[1] = 0; 779 countEdgeNodes[0] = domain->zoom_ni _srv;886 countEdgeNodes[0] = domain->zoom_ni; 780 887 countEdgeNodes[1]= 2; 781 888 SuperClassWriter::writeData(domain->mesh->edge_lat, edge_y, isCollective, 0, &startEdges, &countEdges); … … 798 905 SuperClassWriter::writeData(domain->mesh->edge_nodes, edge_nodes, isCollective, 0, &startEdgeNodes, &countEdgeNodes); 799 906 } 800 startFaces[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;801 countFaces[0] = domain->zoom_ni _srv;907 startFaces[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 908 countFaces[0] = domain->zoom_ni; 802 909 startEdgeFaces[0] = domain->mesh->edge_start; 803 910 startEdgeFaces[1]= 0; 804 911 countEdgeFaces[0] = domain->mesh->edge_count; 805 912 countEdgeFaces[1]= 2; 806 startFaceConctv[0] = domain->zoom_ibegin _srv-domain->global_zoom_ibegin;913 startFaceConctv[0] = domain->zoom_ibegin-domain->global_zoom_ibegin; 807 914 startFaceConctv[1] = 0; 808 countFaceConctv[0] = domain->zoom_ni _srv;809 countFaceConctv[1] = domain->nvertex;915 countFaceConctv[0] = domain->zoom_ni; 916 countFaceConctv[1] = domain->nvertex; 810 917 SuperClassWriter::writeData(domain->mesh->face_lat, face_y, isCollective, 0, &startFaces, &countFaces); 811 918 SuperClassWriter::writeData(domain->mesh->face_lon, face_x, isCollective, 0, &startFaces, &countFaces); … … 867 974 StdString appendDomid = (singleDomain) ? "" : "_"+domid ; 868 975 869 StdString dimXid = StdString("cell").append(appendDomid); 976 StdString lonName,latName, cellName ; 977 if (domain->lon_name.isEmpty()) lonName = "lon"; 978 else lonName = domain->lon_name; 979 980 if (domain->lat_name.isEmpty()) latName = "lat"; 981 else latName = domain->lat_name; 982 983 if (!domain->dim_i_name.isEmpty()) cellName=domain->dim_i_name; 984 else cellName="cell"; 985 StdString dimXid = cellName+appendDomid; 870 986 StdString dimVertId = StdString("nvertex").append(appendDomid); 871 987 … … 877 993 else if (domain->prec==4) typePrec = NC_FLOAT ; 878 994 else if (domain->prec==8) typePrec = NC_DOUBLE ; 995 996 int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex; 997 998 CArray<size_t, 1>& indexToWrite = domain->localIndexToWriteOnServer; 999 int nbWritten = indexToWrite.numElements(); 1000 CArray<double,1> writtenLat, writtenLon; 1001 CArray<double,2> writtenBndsLat, writtenBndsLon; 1002 CArray<double,1> writtenArea; 1003 1004 if (domain->hasLonLat) 1005 { 1006 writtenLat.resize(nbWritten); 1007 writtenLon.resize(nbWritten); 1008 for (int idx = 0; idx < nbWritten; ++idx) 1009 { 1010 if (idx < domain->latvalue.numElements()) 1011 { 1012 writtenLat(idx) = domain->latvalue(indexToWrite(idx)); 1013 writtenLon(idx) = domain->lonvalue(indexToWrite(idx)); 1014 } 1015 else 1016 { 1017 writtenLat(idx) = 0.; 1018 writtenLon(idx) = 0.; 1019 } 1020 } 1021 } 1022 1023 if (domain->hasBounds) 1024 { 1025 int nvertex = domain->nvertex, idx; 1026 writtenBndsLat.resize(nvertex, nbWritten); 1027 writtenBndsLon.resize(nvertex, nbWritten); 1028 CArray<double,2>& boundslat = domain->bounds_latvalue; 1029 CArray<double,2>& boundslon = domain->bounds_lonvalue; 1030 for (idx = 0; idx < nbWritten; ++idx) 1031 { 1032 for (int nv = 0; nv < nvertex; ++nv) 1033 { 1034 if (idx < boundslat.columns()) 1035 { 1036 writtenBndsLat(nv, idx) = boundslat(nv, int(indexToWrite(idx))); 1037 writtenBndsLon(nv, idx) = boundslon(nv, int(indexToWrite(idx))); 1038 } 1039 else 1040 { 1041 writtenBndsLat(nv, idx) = 0.; 1042 writtenBndsLon(nv, idx) = 0.; 1043 } 1044 } 1045 } 1046 } 1047 1048 if (domain->hasArea) 1049 { 1050 writtenArea.resize(nbWritten); 1051 for (int idx = 0; idx < nbWritten; ++idx) 1052 { 1053 if (idx < domain->areavalue.numElements()) 1054 writtenArea(idx) = domain->areavalue(indexToWrite(idx)); 1055 else 1056 writtenArea(idx) = 0.; 1057 } 1058 } 879 1059 880 1060 try … … 885 1065 { 886 1066 dim0.push_back(dimXid); 887 SuperClassWriter::addDimension(dimXid, domain->zoom_ni_srv); 888 889 lonid = StdString("lon").append(appendDomid); 890 latid = StdString("lat").append(appendDomid); 891 bounds_lonid = StdString("bounds_lon").append(appendDomid); 892 bounds_latid = StdString("bounds_lat").append(appendDomid); 1067 SuperClassWriter::addDimension(dimXid, domain->zoom_ni); 1068 1069 lonid = lonName+appendDomid; 1070 latid = latName+appendDomid; 1071 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name; 1072 else bounds_lonid = "bounds_"+lonName+appendDomid; 1073 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name; 1074 else bounds_latid = "bounds_"+latName+appendDomid; 1075 893 1076 if (domain->hasLonLat) 894 1077 { 895 SuperClassWriter::addVariable(latid, typePrec, dim0 );896 SuperClassWriter::addVariable(lonid, typePrec, dim0 );1078 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 1079 SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel); 897 1080 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid); 898 1081 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_lonid, &lonid); … … 906 1089 dim0.push_back(dimXid); 907 1090 dim0.push_back(dimVertId); 908 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0 );909 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0 );1091 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel); 1092 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel); 910 1093 } 911 1094 … … 914 1097 if (domain->hasArea) 915 1098 { 916 SuperClassWriter::addVariable(areaId, typePrec, dim0 );1099 SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel); 917 1100 SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId); 918 1101 SuperClassWriter::addAttribute("units", StdString("m2"), &areaId); … … 923 1106 if (domain->hasLonLat) 924 1107 { 925 SuperClassWriter::writeData( domain->latvalue_srv, latid, isCollective, 0);926 SuperClassWriter::writeData( domain->lonvalue_srv, lonid, isCollective, 0);1108 SuperClassWriter::writeData(writtenLat, latid, isCollective, 0); 1109 SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0); 927 1110 if (domain->hasBounds) 928 1111 { 929 SuperClassWriter::writeData( domain->bounds_lon_srv, bounds_lonid, isCollective, 0);930 SuperClassWriter::writeData( domain->bounds_lat_srv, bounds_latid, isCollective, 0);1112 SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0); 1113 SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0); 931 1114 } 932 1115 } 933 1116 934 1117 if (domain->hasArea) 935 SuperClassWriter::writeData( domain->area_srv, areaId, isCollective, 0);1118 SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0); 936 1119 937 1120 SuperClassWriter::definition_start(); … … 941 1124 case (ONE_FILE) : 942 1125 { 943 lonid = StdString("lon").append(appendDomid); 944 latid = StdString("lat").append(appendDomid); 945 bounds_lonid = StdString("bounds_lon").append(appendDomid); 946 bounds_latid = StdString("bounds_lat").append(appendDomid); 1126 lonid = lonName+appendDomid; 1127 latid = latName+appendDomid; 1128 if (!domain->bounds_lon_name.isEmpty()) bounds_lonid = domain->bounds_lon_name; 1129 else bounds_lonid = "bounds_"+lonName+appendDomid; 1130 if (!domain->bounds_lat_name.isEmpty()) bounds_latid = domain->bounds_lat_name; 1131 else bounds_latid = "bounds_"+latName+appendDomid; 1132 947 1133 dim0.push_back(dimXid); 948 1134 SuperClassWriter::addDimension(dimXid, domain->ni_glo); 949 1135 if (domain->hasLonLat) 950 1136 { 951 SuperClassWriter::addVariable(latid, typePrec, dim0 );952 SuperClassWriter::addVariable(lonid, typePrec, dim0 );1137 SuperClassWriter::addVariable(latid, typePrec, dim0, compressionLevel); 1138 SuperClassWriter::addVariable(lonid, typePrec, dim0, compressionLevel); 953 1139 954 1140 this->writeAxisAttributes(lonid, "", "longitude", "Longitude", "degrees_east", domid); … … 956 1142 this->writeAxisAttributes(latid, "", "latitude", "Latitude", "degrees_north", domid); 957 1143 if (domain->hasBounds) SuperClassWriter::addAttribute("bounds",bounds_latid, &latid); 958 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, domain->nvertex);1144 if (domain->hasBounds) SuperClassWriter::addDimension(dimVertId, nvertex); 959 1145 } 960 1146 dim0.clear(); … … 964 1150 dim0.push_back(dimXid); 965 1151 dim0.push_back(dimVertId); 966 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0 );967 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0 );1152 SuperClassWriter::addVariable(bounds_lonid, typePrec, dim0, compressionLevel); 1153 SuperClassWriter::addVariable(bounds_latid, typePrec, dim0, compressionLevel); 968 1154 } 969 1155 … … 972 1158 dim0.clear(); 973 1159 dim0.push_back(dimXid); 974 SuperClassWriter::addVariable(areaId, typePrec, dim0 );1160 SuperClassWriter::addVariable(areaId, typePrec, dim0, compressionLevel); 975 1161 SuperClassWriter::addAttribute("standard_name", StdString("cell_area"), &areaId); 976 1162 SuperClassWriter::addAttribute("units", StdString("m2"), &areaId); … … 986 1172 count[0]=0 ; 987 1173 startBounds[1]=0 ; 988 countBounds[1]= domain->nvertex ;1174 countBounds[1]=nvertex ; 989 1175 startBounds[0]=0 ; 990 1176 countBounds[0]=0 ; … … 992 1178 else 993 1179 { 994 start[0]=domain->zoom_ibegin _srv-domain->global_zoom_ibegin;995 count[0]=domain->zoom_ni _srv;996 startBounds[0]=domain->zoom_ibegin _srv-domain->global_zoom_ibegin;1180 start[0]=domain->zoom_ibegin - domain->global_zoom_ibegin; 1181 count[0]=domain->zoom_ni; 1182 startBounds[0]=domain->zoom_ibegin-domain->global_zoom_ibegin; 997 1183 startBounds[1]=0 ; 998 countBounds[0]=domain->zoom_ni _srv;999 countBounds[1]= domain->nvertex ;1184 countBounds[0]=domain->zoom_ni; 1185 countBounds[1]=nvertex ; 1000 1186 } 1001 1187 1002 1188 if (domain->hasLonLat) 1003 1189 { 1004 SuperClassWriter::writeData( domain->latvalue_srv, latid, isCollective, 0,&start,&count);1005 SuperClassWriter::writeData( domain->lonvalue_srv, lonid, isCollective, 0,&start,&count);1190 SuperClassWriter::writeData(writtenLat, latid, isCollective, 0,&start,&count); 1191 SuperClassWriter::writeData(writtenLon, lonid, isCollective, 0,&start,&count); 1006 1192 if (domain->hasBounds) 1007 1193 { 1008 SuperClassWriter::writeData( domain->bounds_lon_srv, bounds_lonid, isCollective, 0,&startBounds,&countBounds);1009 SuperClassWriter::writeData( domain->bounds_lat_srv, bounds_latid, isCollective, 0,&startBounds,&countBounds);1194 SuperClassWriter::writeData(writtenBndsLon, bounds_lonid, isCollective, 0,&startBounds,&countBounds); 1195 SuperClassWriter::writeData(writtenBndsLat, bounds_latid, isCollective, 0,&startBounds,&countBounds); 1010 1196 } 1011 1197 } 1012 1198 1013 1199 if (domain->hasArea) 1014 SuperClassWriter::writeData( domain->area_srv, areaId, isCollective, 0, &start, &count);1200 SuperClassWriter::writeData(writtenArea, areaId, isCollective, 0, &start, &count); 1015 1201 1016 1202 SuperClassWriter::definition_start(); … … 1041 1227 if (axis->IsWritten(this->filename)) return; 1042 1228 axis->checkAttributes(); 1043 int zoom_size_srv = axis->zoom_size_srv; 1044 int zoom_begin_srv = axis->zoom_begin_srv; 1045 int zoom_size = (MULTI_FILE == SuperClass::type) ? zoom_size_srv 1046 : axis->global_zoom_size_srv; 1047 1048 if ((0 == zoom_size_srv) && (MULTI_FILE == SuperClass::type)) return; 1229 1230 axis->computeWrittenIndex(); 1231 axis->computeWrittenCompressedIndex(comm_file); 1232 1233 int zoom_size = (MULTI_FILE == SuperClass::type) ? axis->zoom_n 1234 : axis->global_zoom_n; 1235 1236 int zoom_count = axis->zoom_n; 1237 int zoom_begin = axis->zoom_begin; 1238 // int zoom_begin = (MULTI_FILE == SuperClass::type) ? axis->global_zoom_begin 1239 // : axis->zoom_begin; 1240 1241 if ((0 == axis->zoom_n) && (MULTI_FILE == SuperClass::type)) return; 1049 1242 1050 1243 std::vector<StdString> dims; 1051 1244 StdString axisid = axis->getAxisOutputName(); 1245 StdString axisDim, axisBoundsId; 1052 1246 if (isWrittenAxis(axisid)) return ; 1053 1247 else setWrittenAxis(axisid); … … 1055 1249 nc_type typePrec ; 1056 1250 if (axis->prec.isEmpty()) typePrec = NC_FLOAT ; 1057 else if (axis->prec==4) typePrec = NC_FLOAT ;1251 else if (axis->prec==4) typePrec = NC_FLOAT ; 1058 1252 else if (axis->prec==8) typePrec = NC_DOUBLE ; 1059 1253 … … 1062 1256 try 1063 1257 { 1064 SuperClassWriter::addDimension(axisid, zoom_size); 1065 if (!axis->label.isEmpty()) SuperClassWriter::addDimension(strId, stringArrayLen); 1066 if (axis->hasValue) 1258 if (axis->dim_name.isEmpty()) axisDim = axisid; 1259 else axisDim=axis->dim_name.getValue(); 1260 SuperClassWriter::addDimension(axisDim, zoom_size); 1261 dims.push_back(axisDim); 1262 1263 if (!axis->label.isEmpty() && !SuperClassWriter::dimExist(strId)) SuperClassWriter::addDimension(strId, stringArrayLen); 1264 1265 if (axis->hasValue || !axis->label.isEmpty()) 1067 1266 { 1068 dims.push_back(axisid);1069 1267 if (!axis->label.isEmpty()) dims.push_back(strId); 1070 SuperClassWriter::addVariable(axisid, typePrec, dims); 1268 1269 SuperClassWriter::addVariable(axisid, typePrec, dims, compressionLevel); 1071 1270 1072 1271 if (!axis->name.isEmpty()) … … 1082 1281 SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisid); 1083 1282 1283 if (!axis->axis_type.isEmpty()) 1284 { 1285 switch(axis->axis_type) 1286 { 1287 case CAxis::axis_type_attr::X : 1288 SuperClassWriter::addAttribute("axis", string("X"), &axisid); 1289 break; 1290 case CAxis::axis_type_attr::Y : 1291 SuperClassWriter::addAttribute("axis", string("Y"), &axisid); 1292 break; 1293 case CAxis::axis_type_attr::Z : 1294 SuperClassWriter::addAttribute("axis", string("Z"), &axisid); 1295 break; 1296 case CAxis::axis_type_attr::T : 1297 SuperClassWriter::addAttribute("axis", string("T"), &axisid); 1298 break; 1299 } 1300 } 1301 1084 1302 if (!axis->positive.isEmpty()) 1085 1303 { 1086 SuperClassWriter::addAttribute("axis", string("Z"), &axisid);1087 1304 SuperClassWriter::addAttribute("positive", 1088 1305 (axis->positive == CAxis::positive_attr::up) ? string("up") : string("down"), … … 1090 1307 } 1091 1308 1092 StdString axisBoundsId = axisid + "_bounds"; 1093 if (!axis->bounds.isEmpty()) 1309 if (!axis->formula.isEmpty()) 1310 SuperClassWriter::addAttribute("formula", axis->formula.getValue(), &axisid); 1311 1312 if (!axis->formula_term.isEmpty()) 1313 SuperClassWriter::addAttribute("formula_term", axis->formula_term.getValue(), &axisid); 1314 1315 axisBoundsId = (axis->bounds_name.isEmpty()) ? axisid + "_bounds" : axis->bounds_name; 1316 if (!axis->bounds.isEmpty() && axis->label.isEmpty()) 1094 1317 { 1095 1318 dims.push_back("axis_nbounds"); 1096 SuperClassWriter::addVariable(axisBoundsId, typePrec, dims );1319 SuperClassWriter::addVariable(axisBoundsId, typePrec, dims, compressionLevel); 1097 1320 SuperClassWriter::addAttribute("bounds", axisBoundsId, &axisid); 1321 1322 if (!axis->standard_name.isEmpty()) 1323 SuperClassWriter::addAttribute("standard_name", axis->standard_name.getValue(), &axisBoundsId); 1324 1325 if (!axis->unit.isEmpty()) 1326 SuperClassWriter::addAttribute("units", axis->unit.getValue(), &axisBoundsId); 1327 1328 if (!axis->formula_bounds.isEmpty()) 1329 SuperClassWriter::addAttribute("formula", axis->formula_bounds.getValue(), &axisBoundsId); 1330 1331 if (!axis->formula_term_bounds.isEmpty()) 1332 SuperClassWriter::addAttribute("formula_term", axis->formula_term_bounds.getValue(), &axisBoundsId); 1098 1333 } 1099 1100 SuperClassWriter::definition_end(); 1101 1102 switch (SuperClass::type) 1334 } 1335 1336 SuperClassWriter::definition_end(); 1337 1338 CArray<size_t, 1>& indexToWrite = axis->localIndexToWriteOnServer; 1339 int nbWritten = indexToWrite.numElements(); 1340 CArray<double,1> axis_value(indexToWrite.numElements()); 1341 if (!axis->value.isEmpty()) 1342 { 1343 for (int i = 0; i < nbWritten; i++) 1103 1344 { 1104 case MULTI_FILE: 1345 if (i < axis->value.numElements()) 1346 axis_value(i) = axis->value(indexToWrite(i)); 1347 else 1348 axis_value(i) = 0.; 1349 } 1350 } 1351 CArray<double,2> axis_bounds; 1352 CArray<string,1> axis_label; 1353 if (!axis->label.isEmpty()) 1354 { 1355 axis_label.resize(indexToWrite.numElements()); 1356 for (int i = 0; i < nbWritten; i++) 1357 { 1358 if (i < axis->label.numElements()) 1359 axis_label(i) = axis->label(indexToWrite(i)); 1360 else 1361 axis_label(i) = boost::lexical_cast<string>(0); // Write 0 as a label 1362 } 1363 } 1364 1365 switch (SuperClass::type) 1366 { 1367 case MULTI_FILE: 1368 { 1369 if (axis->label.isEmpty()) 1105 1370 { 1106 CArray<double,1> axis_value(zoom_size_srv); 1107 for (int i = 0; i < zoom_size_srv; i++) axis_value(i) = axis->value_srv(i); 1108 if (axis->label.isEmpty()) SuperClassWriter::writeData(axis_value, axisid, isCollective, 0); 1109 1110 if (!axis->bounds.isEmpty() && axis->label.isEmpty()) 1111 SuperClassWriter::writeData(axis->bound_srv, axisBoundsId, isCollective, 0); 1112 1113 if (! axis->label.isEmpty()) SuperClassWriter::writeData(axis->label_srv, axisid, isCollective, 0); 1114 1115 SuperClassWriter::definition_start(); 1116 break; 1371 if (!axis->value.isEmpty()) 1372 SuperClassWriter::writeData(axis_value, axisid, isCollective, 0); 1373 1374 if (!axis->bounds.isEmpty()) 1375 { 1376 axis_bounds.resize(2, indexToWrite.numElements()); 1377 for (int i = 0; i < nbWritten; ++i) 1378 { 1379 if (i < axis->bounds.columns()) 1380 { 1381 axis_bounds(0, i) = axis->bounds(0, int(indexToWrite(i))); 1382 axis_bounds(1, i) = axis->bounds(1, int(indexToWrite(i))); 1383 } 1384 else 1385 { 1386 axis_bounds(0, i) = 0.; 1387 axis_bounds(1, i) = 0.; 1388 1389 } 1390 } 1391 SuperClassWriter::writeData(axis_bounds, axisBoundsId, isCollective, 0); 1392 } 1117 1393 } 1118 case ONE_FILE: 1394 else 1395 SuperClassWriter::writeData(axis_label, axisid, isCollective, 0); 1396 1397 SuperClassWriter::definition_start(); 1398 break; 1399 } 1400 case ONE_FILE: 1401 { 1402 std::vector<StdSize> start(1), startBounds(2) ; 1403 std::vector<StdSize> count(1), countBounds(2) ; 1404 start[0] = startBounds[0] = zoom_begin - axis->global_zoom_begin; 1405 count[0] = countBounds[0] = zoom_count; // zoom_size 1406 startBounds[1] = 0; 1407 countBounds[1] = 2; 1408 1409 if (axis->label.isEmpty()) 1119 1410 { 1120 CArray<double,1> axis_value(zoom_size_srv); 1121 axis_value = axis->value_srv; 1122 1123 std::vector<StdSize> start(1), startBounds(2) ; 1124 std::vector<StdSize> count(1), countBounds(2) ; 1125 start[0] = startBounds[0] = zoom_begin_srv-axis->global_zoom_begin_srv; 1126 count[0] = countBounds[0] = zoom_size_srv; 1127 startBounds[1] = 0; 1128 countBounds[1] = 2; 1129 if (axis->label.isEmpty()) SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count); 1130 1131 if (!axis->bounds.isEmpty()&& axis->label.isEmpty()) 1132 SuperClassWriter::writeData(axis->bound_srv, axisBoundsId, isCollective, 0, &startBounds, &countBounds); 1133 1134 if (! axis->label.isEmpty()) SuperClassWriter::writeData(axis->label_srv, axisid, isCollective, 0); 1135 1136 SuperClassWriter::definition_start(); 1137 1138 break; 1411 if (!axis->value.isEmpty()) 1412 SuperClassWriter::writeData(axis_value, axisid, isCollective, 0, &start, &count); 1413 1414 if (!axis->bounds.isEmpty()) 1415 { 1416 axis_bounds.resize(2, indexToWrite.numElements()); 1417 for (int i = 0; i < nbWritten; ++i) 1418 { 1419 if (i < axis->bounds.columns()) 1420 { 1421 axis_bounds(0, i) = axis->bounds(0, int(indexToWrite(i))); 1422 axis_bounds(1, i) = axis->bounds(1, int(indexToWrite(i))); 1423 } 1424 else 1425 { 1426 axis_bounds(0, i) = 0.; 1427 axis_bounds(1, i) = 0.; 1428 } 1429 } 1430 SuperClassWriter::writeData(axis_bounds, axisBoundsId, isCollective, 0, &startBounds, &countBounds); 1431 } 1139 1432 } 1140 default : 1141 ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", 1142 << "[ type = " << SuperClass::type << "]" 1143 << " not implemented yet !"); 1433 else 1434 { 1435 std::vector<StdSize> startLabel(2), countLabel(2); 1436 startLabel[0] = start[0]; startLabel[1] = 0; 1437 countLabel[0] = count[0]; countLabel[1] = stringArrayLen; 1438 SuperClassWriter::writeData(axis_label, axisid, isCollective, 0, &startLabel, &countLabel); 1439 } 1440 1441 SuperClassWriter::definition_start(); 1442 1443 break; 1144 1444 } 1445 default : 1446 ERROR("CNc4DataOutput::writeAxis_(CAxis* axis)", 1447 << "[ type = " << SuperClass::type << "]" 1448 << " not implemented yet !"); 1145 1449 } 1146 1450 } … … 1165 1469 1166 1470 StdString scalaId = scalar->getScalarOutputName(); 1471 StdString boundsId; 1167 1472 if (isWrittenAxis(scalaId)) return ; 1168 1473 else setWrittenAxis(scalaId); … … 1173 1478 else if (scalar->prec==8) typePrec = NC_DOUBLE ; 1174 1479 1175 1480 if (!scalar->label.isEmpty()) typePrec = NC_CHAR ; 1481 string strId="str_len" ; 1482 1176 1483 try 1177 1484 { 1178 if (!scalar->value.isEmpty()) 1485 if (!scalar->label.isEmpty() && !SuperClassWriter::dimExist(strId)) SuperClassWriter::addDimension(strId, stringArrayLen); 1486 1487 if (!scalar->value.isEmpty() || !scalar->label.isEmpty()) 1179 1488 { 1180 // dims.push_back(scalaId);1181 1489 std::vector<StdString> dims; 1490 StdString scalarDim = scalaId; 1491 1492 if (!scalar->label.isEmpty()) dims.push_back(strId); 1493 1182 1494 SuperClassWriter::addVariable(scalaId, typePrec, dims); 1183 1495 … … 1193 1505 if (!scalar->unit.isEmpty()) 1194 1506 SuperClassWriter::addAttribute("units", scalar->unit.getValue(), &scalaId); 1507 1508 if (!scalar->axis_type.isEmpty()) 1509 { 1510 switch(scalar->axis_type) 1511 { 1512 case CScalar::axis_type_attr::X : 1513 SuperClassWriter::addAttribute("axis", string("X"), &scalaId); 1514 break; 1515 case CScalar::axis_type_attr::Y : 1516 SuperClassWriter::addAttribute("axis", string("Y"), &scalaId); 1517 break; 1518 case CScalar::axis_type_attr::Z : 1519 SuperClassWriter::addAttribute("axis", string("Z"), &scalaId); 1520 break; 1521 case CScalar::axis_type_attr::T : 1522 SuperClassWriter::addAttribute("axis", string("T"), &scalaId); 1523 break; 1524 } 1525 } 1526 1527 if (!scalar->positive.isEmpty()) 1528 { 1529 SuperClassWriter::addAttribute("positive", 1530 (scalar->positive == CScalar::positive_attr::up) ? string("up") : string("down"), 1531 &scalaId); 1532 } 1533 1534 if (!scalar->bounds.isEmpty() && scalar->label.isEmpty()) 1535 { 1536 dims.clear(); 1537 dims.push_back("axis_nbounds"); 1538 boundsId = (scalar->bounds_name.isEmpty()) ? (scalaId + "_bounds") : scalar->bounds_name.getValue(); 1539 SuperClassWriter::addVariable(boundsId, typePrec, dims); 1540 SuperClassWriter::addAttribute("bounds", boundsId, &scalaId); 1541 } 1195 1542 1196 1543 SuperClassWriter::definition_end(); … … 1201 1548 { 1202 1549 CArray<double,1> scalarValue(scalarSize); 1203 scalarValue(0) = scalar->value; 1204 SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0); 1550 CArray<string,1> scalarLabel(scalarSize); 1551 CArray<double,1> scalarBounds(scalarSize*2); 1552 1553 if (!scalar->value.isEmpty() && scalar->label.isEmpty()) 1554 { 1555 scalarValue(0) = scalar->value; 1556 SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0); 1557 } 1558 1559 if (!scalar->bounds.isEmpty() && scalar->label.isEmpty()) 1560 { 1561 scalarBounds(0) = scalar->bounds(0); 1562 scalarBounds(1) = scalar->bounds(1); 1563 SuperClassWriter::writeData(scalarBounds, boundsId, isCollective, 0); 1564 } 1565 1566 if (!scalar->label.isEmpty()) 1567 { 1568 scalarLabel(0) = scalar->label; 1569 SuperClassWriter::writeData(scalarLabel, scalaId, isCollective, 0); 1570 } 1571 1205 1572 SuperClassWriter::definition_start(); 1206 1573 … … 1210 1577 { 1211 1578 CArray<double,1> scalarValue(scalarSize); 1212 scalarValue(0) = scalar->value; 1579 CArray<string,1> scalarLabel(scalarSize); 1580 CArray<double,1> scalarBounds(scalarSize*2); 1213 1581 1214 1582 std::vector<StdSize> start(1); … … 1216 1584 start[0] = 0; 1217 1585 count[0] = 1; 1218 SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0, &start, &count); 1586 if (!scalar->value.isEmpty() && scalar->label.isEmpty()) 1587 { 1588 scalarValue(0) = scalar->value; 1589 SuperClassWriter::writeData(scalarValue, scalaId, isCollective, 0, &start, &count); 1590 } 1591 if (!scalar->bounds.isEmpty() && scalar->label.isEmpty()) 1592 { 1593 scalarBounds(0) = scalar->bounds(0); 1594 scalarBounds(1) = scalar->bounds(1); 1595 count[0] = 2; 1596 SuperClassWriter::writeData(scalarBounds, boundsId, isCollective, 0, &start, &count); 1597 } 1598 if (!scalar->label.isEmpty()) 1599 { 1600 scalarLabel(0) = scalar->label; 1601 count[0] = stringArrayLen; 1602 SuperClassWriter::writeData(scalarLabel, scalaId, isCollective, 0, &start, &count); 1603 } 1604 1219 1605 SuperClassWriter::definition_start(); 1220 1606 … … 1285 1671 break; 1286 1672 case CDomain::type_attr::unstructured: 1287 compress << "cell" << appendDomId; 1673 StdString cellName = (!domain->dim_i_name.isEmpty()) ? cellName=domain->dim_i_name : "cell"; 1674 compress << cellName << appendDomId; 1675 // compress << "cell" << appendDomId; 1288 1676 break; 1289 1677 } … … 1305 1693 if (i != 0) compress << ' '; 1306 1694 } 1307 SuperClassWriter::addAttribute("compress", compress.str(), &varId); 1308 1309 grid->computeCompressedIndex(); 1695 SuperClassWriter::addAttribute("compress", compress.str(), &varId); 1310 1696 1311 1697 CArray<int, 1> indexes(grid->getNumberWrittenIndexes()); 1312 std::map<int, CArray<size_t, 1> >::const_iterator it; 1313 for (it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it) 1314 { 1315 const CArray<size_t, 1> compressedIndexes = grid->compressedOutIndexFromClient[it->first]; 1316 for (int i = 0; i < it->second.numElements(); i++) 1317 indexes(compressedIndexes(i)) = it->second(i); 1318 } 1698 indexes = grid->localIndexToWriteOnServer; 1319 1699 1320 1700 switch (SuperClass::type) … … 1373 1753 } 1374 1754 1375 const std::vector<int>& indexesToWrite = domain->getIndexesToWrite();1376 indexes.resize(indexesToWrite.size());1377 for (int n = 0; n < indexes.numElements(); ++n)1378 indexes(n) = indexesToWrite[n];1755 // indexes.resize(domain->compressedIndexToWriteOnServer[comm_file].numElements()); 1756 // indexes = domain->compressedIndexToWriteOnServer[com_file]; 1757 indexes.resize(domain->getCompressedIndexToWriteOnServer(comm_file).numElements()); 1758 indexes = domain->getCompressedIndexToWriteOnServer(comm_file); 1379 1759 1380 1760 isDistributed = domain->isDistributed(); 1381 nbIndexes = domain->getNumberWrittenIndexes( );1382 totalNbIndexes = domain->getTotalNumberWrittenIndexes( );1383 offset = domain->getOffsetWrittenIndexes( );1761 nbIndexes = domain->getNumberWrittenIndexes(comm_file); 1762 totalNbIndexes = domain->getTotalNumberWrittenIndexes(comm_file); 1763 offset = domain->getOffsetWrittenIndexes(comm_file); 1384 1764 firstGlobalIndex = domain->ibegin + domain->jbegin * domain->ni_glo; 1385 1765 … … 1401 1781 compress = axisId; 1402 1782 1403 const std::vector<int>& indexesToWrite = axis->getIndexesToWrite(); 1404 indexes.resize(indexesToWrite.size()); 1405 for (int n = 0; n < indexes.numElements(); ++n) 1406 indexes(n) = indexesToWrite[n]; 1783 // indexes.resize(axis->compressedIndexToWriteOnServer.numElements()); 1784 // indexes = axis->compressedIndexToWriteOnServer; 1785 1786 indexes.resize(axis->getCompressedIndexToWriteOnServer(comm_file).numElements()); 1787 indexes = axis->getCompressedIndexToWriteOnServer(comm_file); 1407 1788 1408 1789 isDistributed = axis->isDistributed(); 1409 nbIndexes = axis->getNumberWrittenIndexes( );1410 totalNbIndexes = axis->getTotalNumberWrittenIndexes( );1411 offset = axis->getOffsetWrittenIndexes( );1790 nbIndexes = axis->getNumberWrittenIndexes(comm_file); 1791 totalNbIndexes = axis->getTotalNumberWrittenIndexes(comm_file); 1792 offset = axis->getOffsetWrittenIndexes(comm_file); 1412 1793 firstGlobalIndex = axis->begin; 1413 1794 … … 1449 1830 } 1450 1831 } 1451 } 1452 1453 if (!dims.empty()) 1454 grid->computeCompressedIndex(); 1832 } 1455 1833 } 1456 1834 … … 1520 1898 StdString domId = domain->getDomainOutputName(); 1521 1899 StdString appendDomId = singleDomain ? "" : "_" + domId ; 1522 1900 StdString lonName,latName ; 1901 StdString dimIname,dimJname ; 1902 1903 if (domain->lon_name.isEmpty()) 1904 { 1905 if (domain->type==CDomain::type_attr::curvilinear) lonName = "nav_lon"; 1906 else lonName = "lon"; 1907 } 1908 else lonName = domain->lon_name; 1909 1910 if (domain->lat_name.isEmpty()) 1911 { 1912 if (domain->type==CDomain::type_attr::curvilinear) latName = "nav_lat"; 1913 else latName = "lat"; 1914 } 1915 else latName = domain->lat_name; 1916 1917 if (domain->dim_i_name.isEmpty()) 1918 { 1919 if (domain->type==CDomain::type_attr::curvilinear) dimIname = "x"; 1920 else if (domain->type==CDomain::type_attr::unstructured) dimIname = "cell"; 1921 else dimIname = lonName; 1922 } 1923 else dimIname = domain->dim_i_name; 1924 1925 if (domain->dim_j_name.isEmpty()) 1926 { 1927 if (domain->type==CDomain::type_attr::curvilinear) dimJname = "y"; 1928 else dimJname = latName; 1929 } 1930 else dimJname = domain->dim_j_name; 1931 1523 1932 if (compressedOutput && domain->isCompressible() && domain->type != CDomain::type_attr::unstructured) 1524 1933 { … … 1532 1941 if (!compressedOutput || !domain->isCompressible()) 1533 1942 { 1534 dimXid = StdString("x").append(appendDomId); 1943 dimXid=dimIname+appendDomId; 1944 dimYid=dimJname+appendDomId; 1535 1945 dimIdList.push_back(dimXid); 1536 dimYid = StdString("y").append(appendDomId);1537 1946 dimIdList.push_back(dimYid); 1538 1947 } 1539 dimCoordList.push_back( StdString("nav_lon").append(appendDomId));1540 dimCoordList.push_back( StdString("nav_lat").append(appendDomId));1948 dimCoordList.push_back(lonName+appendDomId); 1949 dimCoordList.push_back(latName+appendDomId); 1541 1950 break ; 1542 1951 case CDomain::type_attr::rectilinear: 1543 1952 if (!compressedOutput || !domain->isCompressible()) 1544 1953 { 1545 dimXid = StdString("lon").append(appendDomId); 1954 dimXid = dimIname+appendDomId; 1955 dimYid = dimJname+appendDomId; 1546 1956 dimIdList.push_back(dimXid); 1547 dimYid = StdString("lat").append(appendDomId);1548 1957 dimIdList.push_back(dimYid); 1549 1958 } 1959 if (lonName != dimIname) dimCoordList.push_back(lonName+appendDomId); 1960 if (latName != dimJname) dimCoordList.push_back(latName+appendDomId); 1961 1550 1962 break ; 1551 1963 case CDomain::type_attr::unstructured: … … 1553 1965 if (SuperClassWriter::useCFConvention) 1554 1966 { 1555 dimXid = StdString("cell").append(appendDomId);1967 dimXid = dimIname + appendDomId; 1556 1968 dimIdList.push_back(dimXid); 1557 dimCoordList.push_back( StdString("lon").append(appendDomId));1558 dimCoordList.push_back( StdString("lat").append(appendDomId));1969 dimCoordList.push_back(lonName+appendDomId); 1970 dimCoordList.push_back(latName+appendDomId); 1559 1971 } 1560 1972 else … … 1597 2009 CAxis* axis = CAxis::get(axisList[idxAxis]); 1598 2010 StdString axisId = axis->getAxisOutputName(); 2011 StdString axisDim; 2012 2013 if (axis->dim_name.isEmpty()) axisDim = axisId; 2014 else axisDim=axis->dim_name.getValue(); 1599 2015 1600 2016 if (compressedOutput && axis->isCompressible()) 1601 2017 { 1602 dimIdList.push_back(axis Id+ "_points");2018 dimIdList.push_back(axisDim + "_points"); 1603 2019 field->setUseCompressedOutput(); 1604 2020 } 1605 2021 else 1606 dimIdList.push_back(axis Id);1607 1608 dimCoordList.push_back(axisId);2022 dimIdList.push_back(axisDim); 2023 2024 if (axisDim != axisId) dimCoordList.push_back(axisId); 1609 2025 ++idxAxis; 1610 2026 } 1611 else // scalar2027 else 1612 2028 { 1613 /* Do nothing here */ 2029 CScalar* scalar = CScalar::get(scalarList[idxScalar]); 2030 StdString scalarId = scalar->getScalarOutputName(); 2031 if (!scalar->value.isEmpty() || !scalar->label.isEmpty()) 2032 dimCoordList.push_back(scalarId); 2033 ++idxScalar; 1614 2034 } 1615 2035 } … … 1712 2132 // write child variables as attributes 1713 2133 1714 1715 vector<CVariable*> listVars = field->getAllVariables() ;1716 for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ;1717 2134 1718 2135 bool alreadyAddCellMethod = false; … … 1776 2193 if (!field->default_value.isEmpty()) 1777 2194 { 1778 double default_value = field->default_value.getValue(); 1779 float fdefault_value = (float)default_value; 1780 if (type == NC_DOUBLE) 1781 SuperClassWriter::setDefaultValue(fieldid, &default_value); 1782 else 1783 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value); 2195 double default_value = field->default_value.getValue(); 2196 if (type == NC_DOUBLE) 2197 { 2198 SuperClassWriter::setDefaultValue(fieldid, &default_value); 2199 } 2200 else if (type == NC_SHORT) 2201 { 2202 short sdefault_value = (short)default_value; 2203 SuperClassWriter::setDefaultValue(fieldid, &sdefault_value); 2204 } 2205 else 2206 { 2207 float fdefault_value = (float)default_value; 2208 SuperClassWriter::setDefaultValue(fieldid, &fdefault_value); 2209 } 1784 2210 } 1785 2211 else … … 1807 2233 1808 2234 } 2235 2236 vector<CVariable*> listVars = field->getAllVariables() ; 2237 for (vector<CVariable*>::iterator it = listVars.begin() ;it != listVars.end(); it++) writeAttribute_(*it, fieldid) ; 2238 1809 2239 } 1810 2240 catch (CNetCdfException& e) … … 1840 2270 try 1841 2271 { 1842 this->writeFileAttributes(filename, description,1843 conv_str,1844 StdString("An IPSL model"),1845 this->getTimeStamp());2272 if (!appendMode) this->writeFileAttributes(filename, description, 2273 conv_str, 2274 StdString("An IPSL model"), 2275 this->getTimeStamp()); 1846 2276 1847 2277 if (!appendMode) … … 1999 2429 } 2000 2430 2001 2002 2431 StdString fieldid = field->getFieldOutputName(); 2003 2432 … … 2041 2470 if (wtime) 2042 2471 { 2043 2044 2472 Time lastWrite = field->last_Write_srv; 2045 2473 Time lastLastWrite = field->lastlast_Write_srv; … … 2184 2612 if (domain->isCompressible()) 2185 2613 { 2186 start.push_back(domain->getOffsetWrittenIndexes( ));2187 count.push_back(domain->getNumberWrittenIndexes( ));2614 start.push_back(domain->getOffsetWrittenIndexes(comm_file)); 2615 count.push_back(domain->getNumberWrittenIndexes(comm_file)); 2188 2616 idx -= 2; 2189 2617 } … … 2208 2636 if (axis->isCompressible()) 2209 2637 { 2210 start.push_back(axis->getOffsetWrittenIndexes( ));2211 count.push_back(axis->getNumberWrittenIndexes( ));2638 start.push_back(axis->getOffsetWrittenIndexes(comm_file)); 2639 count.push_back(axis->getNumberWrittenIndexes(comm_file)); 2212 2640 } 2213 2641 else … … 2225 2653 else 2226 2654 { 2227 2228 2655 CArray<int,1> axisDomainOrder = grid->axis_domain_order; 2229 2656 std::vector<StdString> domainList = grid->getDomainList(); … … 2231 2658 int numElement = axisDomainOrder.numElements(); 2232 2659 int idxDomain = domainList.size() - 1, idxAxis = axisList.size() - 1; 2233 int idx = nZoomBeginGlobal.size() - 1;2660 int idx = domainList.size() * 2 + axisList.size() - 1;// nZoomBeginGlobal.size() - 1; 2234 2661 2235 2662 start.reserve(nZoomBeginGlobal.size()); … … 2243 2670 if ((domain->type) != CDomain::type_attr::unstructured) 2244 2671 { 2245 start.push_back( nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);2246 count.push_back( nZoomSizeServer[idx]);2672 start.push_back(domain->zoom_jbegin - domain->global_zoom_jbegin); 2673 count.push_back(domain->zoom_nj); 2247 2674 } 2248 2675 --idx ; 2249 start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]); 2250 count.push_back(nZoomSizeServer[idx]); 2676 2677 start.push_back(domain->zoom_ibegin - domain->global_zoom_ibegin); 2678 count.push_back(domain->zoom_ni); 2251 2679 --idx ; 2252 2680 --idxDomain; … … 2254 2682 else if (1 == axisDomainOrder(i)) 2255 2683 { 2256 start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]); 2257 count.push_back(nZoomSizeServer[idx]); 2684 CAxis* axis = CAxis::get(axisList[idxAxis]); 2685 start.push_back(axis->zoom_begin - axis->global_zoom_begin); 2686 count.push_back(axis->zoom_n); 2258 2687 --idx; 2688 --idxAxis; 2259 2689 } 2260 2690 else … … 2779 3209 { 2780 3210 record = n + 1; 2781 break;3211 break; 2782 3212 } 2783 3213 } 2784 3214 it = timeToRecordCache.insert(std::make_pair(time, record)).first; 2785 3215 } 2786 3216 return it->second; 2787 3217 } 2788 3218 -
XIOS/dev/branch_openmp/src/io/nc4_data_output.hpp
r1328 r1460 42 42 bool singleDomain ; 43 43 bool isCollective ; 44 int compressionLevel ; 44 45 45 46 CFile* file; -
XIOS/dev/branch_openmp/src/io/netCdfInterface.cpp
r1362 r1460 30 30 << errormsg << std::endl 31 31 << "Unable to create file, given its name: " << fileName 32 << " and its creation mode " << creationMode2String(cMode) << std::endl;32 << " and its creation mode " << creationMode2String(cMode) << std::endl; 33 33 StdString e = sstr.str(); 34 34 throw CNetCdfException(e); … … 144 144 } 145 145 } 146 146 147 return status; 147 148 } … … 755 756 756 757 if (compressionLevel == 0) return NC_NOERR ; 757 int status = nc_def_var_deflate(ncid, varId, false, (compressionLevel > 0), compressionLevel);758 int status = nc_def_var_deflate(ncid, varId, (compressionLevel > 0), (compressionLevel > 0), compressionLevel); 758 759 if (NC_NOERR != status) 759 760 { -
XIOS/dev/branch_openmp/src/io/netCdfInterface.hpp
r1328 r1460 17 17 #endif 18 18 19 //#include "mpi.hpp" 19 20 #include "netcdf.hpp" 20 21 -
XIOS/dev/branch_openmp/src/io/onetcdf4.cpp
r1362 r1460 3 3 #include "onetcdf4.hpp" 4 4 #include "group_template.hpp" 5 //#include "mpi.hpp" 5 6 #include "netcdf.hpp" 6 7 #include "netCdfInterface.hpp" … … 310 311 311 312 int CONetCDF4::addVariable(const StdString& name, nc_type type, 312 const std::vector<StdString>& dim )313 const std::vector<StdString>& dim, int compressionLevel) 313 314 { 314 315 int varid = 0; … … 352 353 } 353 354 355 setCompressionLevel(name, compressionLevel) ; 356 354 357 return varid; 355 358 } -
XIOS/dev/branch_openmp/src/io/onetcdf4.hpp
r1328 r1460 8 8 #include "data_output.hpp" 9 9 #include "array_new.hpp" 10 //#include "mpi.hpp" 10 11 #include "netcdf.hpp" 11 12 … … 49 50 int addDimension(const StdString& name, const StdSize size = UNLIMITED_DIM); 50 51 int addVariable(const StdString& name, nc_type type, 51 const std::vector<StdString>& dim );52 const std::vector<StdString>& dim, int compressionLevel=0); 52 53 53 54 //---------------------------------------------------------------- -
XIOS/dev/branch_openmp/src/io/onetcdf4_decl.cpp
r1328 r1460 17 17 18 18 template void CONetCDF4::setDefaultValue<double>(const StdString & varname, const double* value) ; 19 template void CONetCDF4::setDefaultValue<short>(const StdString & varname, const short* value) ; 19 20 template void CONetCDF4::setDefaultValue<float>(const StdString & varname, const float* value) ; 20 21 } -
XIOS/dev/branch_openmp/src/io/onetcdf4_impl.hpp
r1328 r1460 60 60 CTimer::get("CONetCDF4::writeData getWriteDataInfos").suspend(); 61 61 62 int dimArrayLen; 63 for (int i=0; i<scount.size(); i++) 64 if (scount[i] == stringArrayLen) 65 dimArrayLen = i; 66 62 67 if (data.numElements()*stringArrayLen != array_size) 63 68 { 64 69 ERROR("CONetCDF4::writeData(...)", 65 << "[ input array size = " << data.numElements() 70 << "[ input array size = " << data.numElements()*stringArrayLen 66 71 << ", intern array size = " << array_size 67 72 << " ] Invalid input data !" ); 68 73 } 69 char* ArrayStr ;70 74 char *PtrArrayStr ; 71 PtrArrayStr= ArrayStr=new char[data.numElements()*stringArrayLen] ;75 PtrArrayStr=new char[stringArrayLen] ; 72 76 Array<StdString,1>::const_iterator it, itb=data.begin(), ite=data.end() ; 73 for(it=itb;it!=ite;++it,PtrArrayStr+=stringArrayLen) 77 int lineNb = 0; 78 for(it=itb;it!=ite;++it) 74 79 { 75 80 it->copy(PtrArrayStr,it->size()) ; 76 81 PtrArrayStr[it->size()]='\0' ; 82 sstart[0] = lineNb; 83 sstart[dimArrayLen] = 0; 84 scount[0] = 1; 85 scount[dimArrayLen] = it->size() + 1; 86 CTimer::get("CONetCDF4::writeData writeData_").resume(); 87 this->writeData_(grpid, varid, sstart, scount, PtrArrayStr); 88 CTimer::get("CONetCDF4::writeData writeData_").suspend(); 89 ++lineNb; 77 90 } 78 CTimer::get("CONetCDF4::writeData writeData_").resume(); 79 this->writeData_(grpid, varid, sstart, scount, ArrayStr); 80 CTimer::get("CONetCDF4::writeData writeData_").suspend(); 81 delete [] ArrayStr ; 91 delete [] PtrArrayStr; 82 92 } 83 93
Note: See TracChangeset
for help on using the changeset viewer.