Changeset 1158 for XIOS/dev/dev_olga/src/node
- Timestamp:
- 06/06/17 17:58:16 (7 years ago)
- Location:
- XIOS/dev/dev_olga/src/node
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/dev/dev_olga/src/node/axis.cpp
r1144 r1158 27 27 , hasBounds_(false), isCompressible_(false) 28 28 , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 29 , transformationMap_(), hasValue(false), doZoomByIndex_(false) 29 , transformationMap_(), hasValue(false), doZoomByIndex_(false), hasLabel(false) 30 30 , computedWrittenIndex_(false) 31 31 { … … 38 38 , hasBounds_(false), isCompressible_(false) 39 39 , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 40 , transformationMap_(), hasValue(false), doZoomByIndex_(false) 40 , transformationMap_(), hasValue(false), doZoomByIndex_(false), hasLabel(false) 41 41 , computedWrittenIndex_(false) 42 42 { … … 58 58 59 59 ///--------------------------------------------------------------- 60 61 const std::set<StdString> & CAxis::getRelFiles(void) const 62 { 63 return (this->relFiles); 64 } 65 60 66 bool CAxis::IsWritten(const StdString & filename) const 61 67 { … … 70 76 bool CAxis::isDistributed(void) const 71 77 { 72 return (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) || 73 (!this->n.isEmpty() && (this->n != this->n_glo));; 78 bool distributed = (!this->begin.isEmpty() && !this->n.isEmpty() && (this->begin + this->n < this->n_glo)) || 79 (!this->n.isEmpty() && (this->n != this->n_glo)); 80 // A same stupid condition to make sure that if there is only one client, axis 81 // should be considered to be distributed. This should be a temporary solution 82 distributed |= (1 == CContext::getCurrent()->client->clientSize); 83 return distributed; 74 84 } 75 85 … … 132 142 std::map<int, StdSize> CAxis::getAttributesBufferSize() 133 143 { 134 // CContextClient* client = CContext::getCurrent()->client;135 144 // For now the assumption is that secondary server pools consist of the same number of procs. 136 145 // CHANGE the line below if the assumption changes. … … 172 181 if (hasBounds_) 173 182 sizeValEvent += CArray<double,2>::size(2 * it->second.size()); 183 184 if (hasLabel) 185 sizeValEvent += CArray<StdString,1>::size(it->second.size()); 174 186 175 187 size_t size = CEventClient::headerSize + getId().size() + sizeof(size_t) + std::max(sizeIndexEvent, sizeValEvent); … … 255 267 this->checkZoom(); 256 268 this->checkMask(); 257 this->checkBounds(); 269 this->checkBounds(); 270 this->checkLabel(); 258 271 } 259 272 … … 339 352 } 340 353 341 void CAxis::checkEligibilityForCompressedOutput() 342 { 343 // We don't check if the mask is valid here, just if a mask has been defined at this point. 344 isCompressible_ = !mask.isEmpty(); 345 } 354 void CAxis::checkLabel() 355 { 356 if (!label.isEmpty()) 357 { 358 if (label.extent(0) != n) 359 ERROR("CAxis::checkLabel(void)", 360 << "The label array of the axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] must be of dimension of axis size." << std::endl 361 << "Axis size is " << n.getValue() << "." << std::endl 362 << "label size is "<< label.extent(0)<< " ."); 363 hasLabel = true; 364 } 365 else hasLabel = false; 366 } 367 void CAxis::checkEligibilityForCompressedOutput() 368 { 369 // We don't check if the mask is valid here, just if a mask has been defined at this point. 370 isCompressible_ = !mask.isEmpty(); 371 } 346 372 347 373 bool CAxis::dispatchEvent(CEventServer& event) … … 437 463 CContext* context = CContext::getCurrent(); 438 464 439 // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;440 465 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; 441 466 for (int p = 0; p < nbSrvPools; ++p) … … 729 754 CContext* context = CContext::getCurrent(); 730 755 731 // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;732 756 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; 733 757 for (int p = 0; p < nbSrvPools; ++p) … … 1071 1095 } 1072 1096 } 1097 1098 if (hasLabel) 1099 { 1100 //label_srv(ind_srv) = labelVal( ind); 1101 } 1073 1102 } 1074 1103 … … 1114 1143 } 1115 1144 1145 /*! 1146 Compare two axis objects. 1147 They are equal if only if they have identical attributes as well as their values. 1148 Moreover, they must have the same transformations. 1149 \param [in] axis Compared axis 1150 \return result of the comparison 1151 */ 1152 bool CAxis::isEqual(CAxis* obj) 1153 { 1154 vector<StdString> excludedAttr; 1155 excludedAttr.push_back("axis_ref"); 1156 1157 bool objEqual = SuperClass::isEqual(obj, excludedAttr); 1158 if (!objEqual) return objEqual; 1159 1160 TransMapTypes thisTrans = this->getAllTransformations(); 1161 TransMapTypes objTrans = obj->getAllTransformations(); 1162 1163 TransMapTypes::const_iterator it, itb, ite; 1164 std::vector<ETranformationType> thisTransType, objTransType; 1165 for (it = thisTrans.begin(); it != thisTrans.end(); ++it) 1166 thisTransType.push_back(it->first); 1167 for (it = objTrans.begin(); it != objTrans.end(); ++it) 1168 objTransType.push_back(it->first); 1169 1170 if (thisTransType.size() != objTransType.size()) return false; 1171 for (int idx = 0; idx < thisTransType.size(); ++idx) 1172 objEqual &= (thisTransType[idx] == objTransType[idx]); 1173 1174 return objEqual; 1175 } 1116 1176 1117 1177 CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id) -
XIOS/dev/dev_olga/src/node/axis.hpp
r1144 r1158 68 68 69 69 static CAxis* createAxis(); 70 70 71 /// Accesseurs /// 72 const std::set<StdString> & getRelFiles(void) const; 73 71 74 int getNumberWrittenIndexes() const; 72 75 int getTotalNumberWrittenIndexes() const; … … 115 118 void duplicateTransformation(CAxis*); 116 119 CTransformation<CAxis>* addTransformation(ETranformationType transType, const StdString& id=""); 120 bool isEqual(CAxis* axis); 117 121 118 122 public: … … 121 125 CArray<double,1> value_srv; 122 126 CArray<double,2> bound_srv; 127 CArray<StdString,1> label_srv; 123 128 bool hasValue; 124 129 CArray<int,1> globalDimGrid; … … 131 136 void checkMask(); 132 137 void checkZoom(); 133 void checkBounds(); 138 void checkBounds(); 139 void checkLabel(); 134 140 void sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, 135 141 CServerDistributionDescription::ServerDistributionType distType); … … 166 172 std::map<int, CArray<int,1> > indiSrv_; 167 173 bool hasBounds_; 168 174 bool hasLabel; 169 175 bool doZoomByIndex_; 170 176 bool computedWrittenIndex_; -
XIOS/dev/dev_olga/src/node/calendar_wrapper.cpp
r983 r1158 83 83 { 84 84 // Create the calendar if possible 85 if ( 0 !=calendar)85 if (calendar) 86 86 { 87 87 ERROR("CCalendarWrapper::createCalendar(void)", -
XIOS/dev/dev_olga/src/node/context.cpp
r1144 r1158 14 14 #include "type.hpp" 15 15 #include "xios_spl.hpp" 16 #include "timer.hpp" 17 #include "memtrack.hpp" 16 18 17 19 #include "server.hpp" … … 372 374 comms.push_back(interCommClient); 373 375 } 374 client = new CContextClient(this,intraCommClient,interCommClient, cxtClient);376 client = new CContextClient(this,intraCommClient,interCommClient, cxtClient); 375 377 } 376 378 … … 615 617 void CContext::closeDefinition(void) 616 618 { 619 CTimer::get("Context : close definition").resume() ; 617 620 postProcessingGlobalAttributes(); 618 621 … … 640 643 if (!hasServer) startPrefetchingOfEnabledReadModeFiles(); 641 644 } 645 CTimer::get("Context : close definition").suspend() ; 642 646 } 643 647 … … 690 694 this->enabledFiles[i]->generateNewTransformationGridDest(); 691 695 } 692 693 696 } 694 697 … … 783 786 { 784 787 const std::vector<CFile*> allFiles = CFile::getAll(); 788 const CDate& initDate = calendar->getInitDate(); 785 789 786 790 for (unsigned int i = 0; i < allFiles.size(); i++) … … 788 792 { 789 793 if (allFiles[i]->enabled.getValue()) // Si l'attribut 'enabled' est fixé à vrai. 794 { 795 if ((initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep())) 796 { 797 error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl 798 << "Output frequency in file \""<<allFiles[i]->getFileOutputName() 799 <<"\" is less than the time step. File will not be written."<<endl; 800 } 801 else 790 802 enabledFiles.push_back(allFiles[i]); 803 } 791 804 } 792 else enabledFiles.push_back(allFiles[i]); // otherwise true by default 793 805 else 806 { 807 if ( (initDate + allFiles[i]->output_freq.getValue()) < (initDate + this->getCalendar()->getTimeStep())) 808 { 809 error(0)<<"WARNING: void CContext::findEnabledFiles()"<<endl 810 << "Output frequency in file \""<<allFiles[i]->getFileOutputName() 811 <<"\" is less than the time step. File will not be written."<<endl; 812 } 813 else 814 enabledFiles.push_back(allFiles[i]); // otherwise true by default 815 } 794 816 795 817 if (enabledFiles.size() == 0) … … 1267 1289 StdString fileDefRoot("file_definition"); 1268 1290 CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot); 1291 1269 1292 for (int i = 0; i < size; ++i) 1270 1293 { … … 1313 1336 CFile* file = allFiles[i]; 1314 1337 1338 std::vector<CVariable*> fileVars, fieldVars, vars = file->getAllVariables(); 1339 for (size_t k = 0; k < vars.size(); k++) 1340 { 1341 CVariable* var = vars[k]; 1342 1343 if (var->ts_target.isEmpty() 1344 || var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both) 1345 fileVars.push_back(var); 1346 1347 if (!var->ts_target.isEmpty() 1348 && (var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both)) 1349 fieldVars.push_back(var); 1350 } 1351 1315 1352 if (!file->timeseries.isEmpty() && file->timeseries != CFile::timeseries_attr::none) 1316 1353 { 1317 StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : file->getFileOutputName(); 1318 1354 StdString fileNameStr("%file_name%") ; 1355 StdString tsPrefix = !file->ts_prefix.isEmpty() ? file->ts_prefix : fileNameStr ; 1356 1357 StdString fileName=file->getFileOutputName(); 1358 size_t pos=tsPrefix.find(fileNameStr) ; 1359 while (pos!=std::string::npos) 1360 { 1361 tsPrefix=tsPrefix.replace(pos,fileNameStr.size(),fileName) ; 1362 pos=tsPrefix.find(fileNameStr) ; 1363 } 1364 1319 1365 const std::vector<CField*> allFields = file->getAllFields(); 1320 1366 for (size_t j = 0; j < allFields.size(); j++) … … 1326 1372 CFile* tsFile = CFile::create(); 1327 1373 tsFile->duplicateAttributes(file); 1328 tsFile->setVirtualVariableGroup(file->getVirtualVariableGroup()); 1329 1374 1375 // Add variables originating from file and targeted to timeserie file 1376 for (size_t k = 0; k < fileVars.size(); k++) 1377 tsFile->getVirtualVariableGroup()->addChild(fileVars[k]); 1378 1379 1330 1380 tsFile->name = tsPrefix + "_"; 1331 1381 if (!field->name.isEmpty()) … … 1341 1391 CField* tsField = tsFile->addField(); 1342 1392 tsField->field_ref = field->getId(); 1343 tsField->setVirtualVariableGroup(field->getVirtualVariableGroup()); 1393 1394 // Add variables originating from file and targeted to timeserie field 1395 for (size_t k = 0; k < fieldVars.size(); k++) 1396 tsField->getVirtualVariableGroup()->addChild(fieldVars[k]); 1397 1398 vars = field->getAllVariables(); 1399 for (size_t k = 0; k < vars.size(); k++) 1400 { 1401 CVariable* var = vars[k]; 1402 1403 // Add variables originating from field and targeted to timeserie field 1404 if (var->ts_target.isEmpty() 1405 || var->ts_target == CVariable::ts_target_attr::field || var->ts_target == CVariable::ts_target_attr::both) 1406 tsField->getVirtualVariableGroup()->addChild(var); 1407 1408 // Add variables originating from field and targeted to timeserie file 1409 if (!var->ts_target.isEmpty() 1410 && (var->ts_target == CVariable::ts_target_attr::file || var->ts_target == CVariable::ts_target_attr::both)) 1411 tsFile->getVirtualVariableGroup()->addChild(var); 1412 } 1344 1413 1345 1414 tsFile->solveFieldRefInheritance(true); … … 1456 1525 void CContext::updateCalendar(int step) 1457 1526 { 1458 info(50) << "Context "<< this->getId() <<"updateCalendar : before : " << calendar->getCurrentDate() << endl;1527 info(50) << "updateCalendar : before : " << calendar->getCurrentDate() << endl; 1459 1528 calendar->update(step); 1460 info(50) <<"Context "<< this->getId() << " updateCalendar : after : " << calendar->getCurrentDate() << endl; 1461 1529 info(50) << "updateCalendar : after : " << calendar->getCurrentDate() << endl; 1530 #ifdef XIOS_MEMTRACK_LIGHT 1531 info(50) << " Current memory used by XIOS : "<< MemTrack::getCurrentMemorySize()*1.0/(1024*1024)<<" Mbyte, at timestep "<<step<<" of context "<<this->getId()<<endl ; 1532 #endif 1462 1533 if (hasClient) 1463 1534 { … … 1537 1608 1538 1609 void CContext::sendRegistry(void) 1539 { 1610 { 1540 1611 registryOut->hierarchicalGatherRegistry() ; 1541 1612 -
XIOS/dev/dev_olga/src/node/domain.cpp
r1144 r1158 26 26 namespace xios { 27 27 28 /// ////////////////////// D finitions ////////////////////// ///28 /// ////////////////////// Définitions ////////////////////// /// 29 29 30 30 CDomain::CDomain(void) … … 79 79 } 80 80 81 const std::set<StdString> & CDomain::getRelFiles(void) const 82 { 83 return (this->relFiles); 84 } 85 86 81 87 /*! 82 88 Returns the number of indexes written by each server. … … 170 176 { 171 177 return ((this->zoom_i_index.isEmpty()) || (0 == this->zoom_i_index.numElements())); 172 // return ((this->zoom_ni_srv == 0) || 173 // (this->zoom_nj_srv == 0)); 178 174 179 } 175 180 … … 190 195 bool CDomain::isDistributed(void) const 191 196 { 192 return!((!ni.isEmpty() && (ni == ni_glo) && !nj.isEmpty() && (nj == nj_glo)) ||197 bool distributed = !((!ni.isEmpty() && (ni == ni_glo) && !nj.isEmpty() && (nj == nj_glo)) || 193 198 (!i_index.isEmpty() && i_index.numElements() == ni_glo*nj_glo)); 199 distributed |= (1 == CContext::getCurrent()->client->clientSize); 200 201 return distributed; 194 202 } 195 203 … … 221 229 222 230 //---------------------------------------------------------------- 231 232 /*! 233 Verify if all distribution information of a domain are available 234 This checking verifies the definition of distribution attributes (ni, nj, ibegin, jbegin) 235 */ 236 bool CDomain::distributionAttributesHaveValue() const 237 { 238 bool hasValues = true; 239 240 if (ni.isEmpty() && ibegin.isEmpty() && i_index.isEmpty()) 241 { 242 hasValues = false; 243 return hasValues; 244 } 245 246 return hasValues; 247 } 223 248 224 249 /*! … … 331 356 ni.setValue(ni_glo - ibeginVec[iIdx]); 332 357 } 333 } 334 335 // Now fill other attributes 336 if (type_attr::rectilinear == type) fillInRectilinearLonLat(); 358 } 337 359 } 338 360 else // unstructured domain … … 380 402 nj.setValue(1); 381 403 } 404 405 i_index.resize(ni); 406 for(int idx = 0; idx < ni; ++idx) i_index(idx)=ibegin+idx; 382 407 } 383 408 else … … 391 416 392 417 checkDomain(); 418 } 419 420 /*! 421 Fill in longitude and latitude whose values are read from file 422 */ 423 void CDomain::fillInLonLat() 424 { 425 switch (type) 426 { 427 case type_attr::rectilinear: 428 fillInRectilinearLonLat(); 429 break; 430 case type_attr::curvilinear: 431 fillInCurvilinearLonLat(); 432 break; 433 case type_attr::unstructured: 434 fillInUnstructuredLonLat(); 435 break; 436 437 default: 438 break; 439 } 440 393 441 } 394 442 … … 468 516 } 469 517 470 471 518 /* 519 Fill in longitude and latitude of curvilinear domain read from a file 520 If there are already longitude and latitude defined by model. We just igonore reading value. 521 */ 522 void CDomain::fillInCurvilinearLonLat() 523 { 524 if (!lonvalue_curvilinear_read_from_file.isEmpty() && lonvalue_2d.isEmpty()) 525 { 526 lonvalue_2d.resize(ni,nj); 527 for (int jdx = 0; jdx < nj; ++jdx) 528 for (int idx = 0; idx < ni; ++idx) 529 lonvalue_2d(idx,jdx) = lonvalue_curvilinear_read_from_file(idx+ibegin, jdx+jbegin); 530 531 lonvalue_curvilinear_read_from_file.free(); 532 } 533 534 if (!latvalue_curvilinear_read_from_file.isEmpty() && latvalue_2d.isEmpty()) 535 { 536 latvalue_2d.resize(ni,nj); 537 for (int jdx = 0; jdx < nj; ++jdx) 538 for (int idx = 0; idx < ni; ++idx) 539 latvalue_2d(idx,jdx) = latvalue_curvilinear_read_from_file(idx+ibegin, jdx+jbegin); 540 541 latvalue_curvilinear_read_from_file.free(); 542 } 543 544 if (!bounds_lonvalue_curvilinear_read_from_file.isEmpty() && bounds_lon_2d.isEmpty()) 545 { 546 bounds_lon_2d.resize(nvertex,ni,nj); 547 for (int jdx = 0; jdx < nj; ++jdx) 548 for (int idx = 0; idx < ni; ++idx) 549 for (int ndx = 0; ndx < nvertex; ++ndx) 550 bounds_lon_2d(ndx,idx,jdx) = bounds_lonvalue_curvilinear_read_from_file(ndx,idx+ibegin, jdx+jbegin); 551 552 bounds_lonvalue_curvilinear_read_from_file.free(); 553 } 554 555 if (!bounds_latvalue_curvilinear_read_from_file.isEmpty() && bounds_lat_2d.isEmpty()) 556 { 557 bounds_lat_2d.resize(nvertex,ni,nj); 558 for (int jdx = 0; jdx < nj; ++jdx) 559 for (int idx = 0; idx < ni; ++idx) 560 for (int ndx = 0; ndx < nvertex; ++ndx) 561 bounds_lat_2d(ndx,idx,jdx) = bounds_latvalue_curvilinear_read_from_file(ndx,idx+ibegin, jdx+jbegin); 562 563 bounds_latvalue_curvilinear_read_from_file.free(); 564 } 565 566 } 567 568 /* 569 Fill in longitude and latitude of unstructured domain read from a file 570 If there are already longitude and latitude defined by model. We just igonore reading value. 571 */ 572 void CDomain::fillInUnstructuredLonLat() 573 { 574 if (i_index.isEmpty()) 575 { 576 i_index.resize(ni); 577 for(int idx = 0; idx < ni; ++idx) i_index(idx)=ibegin+idx; 578 } 579 580 if (!lonvalue_unstructured_read_from_file.isEmpty() && lonvalue_1d.isEmpty()) 581 { 582 lonvalue_1d.resize(ni); 583 for (int idx = 0; idx < ni; ++idx) 584 lonvalue_1d(idx) = lonvalue_unstructured_read_from_file(i_index(idx)); 585 586 // We dont need these values anymore, so just delete them 587 lonvalue_unstructured_read_from_file.free(); 588 } 589 590 if (!latvalue_unstructured_read_from_file.isEmpty() && latvalue_1d.isEmpty()) 591 { 592 latvalue_1d.resize(ni); 593 for (int idx = 0; idx < ni; ++idx) 594 latvalue_1d(idx) = latvalue_unstructured_read_from_file(i_index(idx)); 595 596 // We dont need these values anymore, so just delete them 597 latvalue_unstructured_read_from_file.free(); 598 } 599 600 if (!bounds_lonvalue_unstructured_read_from_file.isEmpty() && bounds_lon_1d.isEmpty()) 601 { 602 int nbVertex = nvertex; 603 bounds_lon_1d.resize(nbVertex,ni); 604 for (int idx = 0; idx < ni; ++idx) 605 for (int jdx = 0; jdx < nbVertex; ++jdx) 606 bounds_lon_1d(jdx,idx) = bounds_lonvalue_unstructured_read_from_file(jdx, i_index(idx)); 607 608 // We dont need these values anymore, so just delete them 609 lonvalue_unstructured_read_from_file.free(); 610 } 611 612 if (!bounds_latvalue_unstructured_read_from_file.isEmpty() && bounds_lat_1d.isEmpty()) 613 { 614 int nbVertex = nvertex; 615 bounds_lat_1d.resize(nbVertex,ni); 616 for (int idx = 0; idx < ni; ++idx) 617 for (int jdx = 0; jdx < nbVertex; ++jdx) 618 bounds_lat_1d(jdx,idx) = bounds_latvalue_unstructured_read_from_file(jdx, i_index(idx)); 619 620 // We dont need these values anymore, so just delete them 621 lonvalue_unstructured_read_from_file.free(); 622 } 623 } 624 625 /* 626 Get global longitude and latitude of rectilinear domain. 627 */ 472 628 void CDomain::AllgatherRectilinearLonLat(CArray<double,1>& lon, CArray<double,1>& lat, CArray<double,1>& lon_g, CArray<double,1>& lat_g) 473 629 { … … 590 746 else 591 747 { 592 if (bounds_lat_start.isEmpty()) bounds_l on_start=-90. ;748 if (bounds_lat_start.isEmpty()) bounds_lat_start=-90. ; 593 749 if (bounds_lat_end.isEmpty()) bounds_lat_end=90 ; 594 750 } … … 695 851 for (int j = 0; j < nj; ++j) 696 852 for (int i = 0; i < ni; ++i) j_index(i+j*ni) = j+jbegin; 697 } 853 } 854 698 855 checkZoom(); 699 856 } … … 1431 1588 if (context->hasClient) 1432 1589 { 1433 // this->checkMask();1434 1590 this->computeConnectedClients(); 1435 // if (hasLonLat || hasArea || isCompressible_) this->computeConnectedClients();1436 1591 if (hasLonLat) 1437 1592 if (!context->hasServer) … … 1482 1637 if (context->hasClient) 1483 1638 { 1484 // this->completeLonLatClient();1485 1639 sendAttributes(); 1486 1640 } … … 2694 2848 } 2695 2849 2696 2697 2850 /*! 2698 2851 Receive area information from client(s) … … 2742 2895 2743 2896 } 2897 } 2898 2899 /*! 2900 Compare two domain objects. 2901 They are equal if only if they have identical attributes as well as their values. 2902 Moreover, they must have the same transformations. 2903 \param [in] domain Compared domain 2904 \return result of the comparison 2905 */ 2906 bool CDomain::isEqual(CDomain* obj) 2907 { 2908 vector<StdString> excludedAttr; 2909 excludedAttr.push_back("domain_ref"); 2910 bool objEqual = SuperClass::isEqual(obj, excludedAttr); 2911 if (!objEqual) return objEqual; 2912 2913 TransMapTypes thisTrans = this->getAllTransformations(); 2914 TransMapTypes objTrans = obj->getAllTransformations(); 2915 2916 TransMapTypes::const_iterator it, itb, ite; 2917 std::vector<ETranformationType> thisTransType, objTransType; 2918 for (it = thisTrans.begin(); it != thisTrans.end(); ++it) 2919 thisTransType.push_back(it->first); 2920 for (it = objTrans.begin(); it != objTrans.end(); ++it) 2921 objTransType.push_back(it->first); 2922 2923 if (thisTransType.size() != objTransType.size()) return false; 2924 for (int idx = 0; idx < thisTransType.size(); ++idx) 2925 objEqual &= (thisTransType[idx] == objTransType[idx]); 2926 2927 return objEqual; 2744 2928 } 2745 2929 -
XIOS/dev/dev_olga/src/node/domain.hpp
r1144 r1158 42 42 , public CDomainAttributes 43 43 { 44 /// typedef /// 45 typedef CObjectTemplate<CDomain> SuperClass; 46 typedef CDomainAttributes SuperClassAttribute; 47 48 public : 44 /// typedef /// 45 typedef CObjectTemplate<CDomain> SuperClass; 46 typedef CDomainAttributes SuperClassAttribute; 47 public: 49 48 enum EEventId 50 49 { … … 91 90 CTransformation<CDomain>* addTransformation(ETranformationType transType, const StdString& id=""); 92 91 93 public: 92 public: 93 const std::set<StdString> & getRelFiles(void) const; 94 94 bool IsWritten(const StdString & filename) const; 95 95 bool isWrittenCompressed(const StdString& filename) const; … … 116 116 vector< vector<int> > i_indSrv ; // for each server, i global index to send 117 117 vector< vector<int> > j_indSrv ; // for each server, j global index to send 118 118 std::vector<int> getNbGlob(); 119 bool isEqual(CDomain* domain); 119 120 public: 120 121 /// Mutateur /// … … 130 131 void fillInRectilinearBoundLonLat(CArray<double,1>& lon, CArray<double,1>& lat, 131 132 CArray<double,2>& boundsLon, CArray<double,2>& boundsLat); 132 void fillInRectilinearLonLat(); 133 134 void fillInLonLat(); 135 bool distributionAttributesHaveValue() const; 133 136 134 137 static bool dispatchEvent(CEventServer& event); … … 157 160 static StdString GetName(void); 158 161 static StdString GetDefName(void); 159 static ENodeType GetType(void); 160 162 163 static ENodeType GetType(void); 164 const std::map<int, vector<size_t> >& getIndexServer() const; 161 165 CArray<bool, 1> localMask; 162 166 bool isCurvilinear ; … … 182 186 183 187 void setTransformations(const TransMapTypes&); 184 188 void computeNGlobDomain(); 185 189 void sendAttributes(); 186 190 void sendIndex(); … … 192 196 void sendDataIndex(); 193 197 void convertLonLatValue(); 194 198 void fillInRectilinearLonLat(); 199 void fillInCurvilinearLonLat(); 200 void fillInUnstructuredLonLat(); 195 201 private: 196 202 bool doZoomByIndex_; -
XIOS/dev/dev_olga/src/node/expand_domain.cpp
r941 r1158 38 38 void CExpandDomain::checkValid(CDomain* domainDst) 39 39 { 40 if (CDomain::type_attr::unstructured != domainDst->type)41 {42 ERROR("CExpandDomain::checkValid(CDomain* domainDst)",43 << "Domain extension is only supported for unstructured" << std::endl44 << "Check type of domain destination, id = " << domainDst->getId());45 }40 // if (CDomain::type_attr::unstructured != domainDst->type) 41 // { 42 // ERROR("CExpandDomain::checkValid(CDomain* domainDst)", 43 // << "Domain extension is only supported for unstructured" << std::endl 44 // << "Check type of domain destination, id = " << domainDst->getId()); 45 // } 46 46 47 47 if (this->type.isEmpty()) this->type.setValue(CExpandDomain::type_attr::edge); -
XIOS/dev/dev_olga/src/node/field.cpp
r1144 r1158 38 38 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 39 39 , useCompressedOutput(false) 40 , hasTimeInstant(false) 41 , hasTimeCentered(false) 40 42 , wasDataAlreadyReceivedFromServer(false) 43 , isEOF(false) 41 44 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 42 45 … … 50 53 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 51 54 , useCompressedOutput(false) 55 , hasTimeInstant(false) 56 , hasTimeCentered(false) 52 57 , wasDataAlreadyReceivedFromServer(false) 58 , isEOF(false) 53 59 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 54 60 … … 122 128 void CField::sendUpdateData(const CArray<double,1>& data) 123 129 { 124 CTimer::get(" XIOS Send Data").resume();130 CTimer::get("Field : send data").resume(); 125 131 126 132 CContext* context = CContext::getCurrent(); … … 174 180 } 175 181 176 CTimer::get(" XIOS Send Data").suspend();182 CTimer::get("Field : send data").suspend(); 177 183 } 178 184 … … 183 189 list<CEventServer::SSubEvent>::iterator it; 184 190 string fieldId; 185 191 CTimer::get("Field : recv data").resume(); 186 192 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 187 193 { … … 192 198 } 193 199 get(fieldId)->recvUpdateData(rankBuffers); 200 CTimer::get("Field : recv data").suspend(); 194 201 } 195 202 … … 252 259 } 253 260 } 254 255 // void CField::recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers)256 // {257 // CContext* context = CContext::getCurrent();258 259 // if (data_srv.empty())260 // {261 // for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)262 // {263 // int rank = it->first;264 // data_srv.insert(std::make_pair(rank, CArray<double,1>(it->second.numElements())));265 // foperation_srv.insert(pair<int,boost::shared_ptr<func::CFunctor> >(rank,boost::shared_ptr<func::CFunctor>(new func::CInstant(data_srv[rank]))));266 // }267 // }268 269 // const CDate& currDate = context->getCalendar()->getCurrentDate();270 // const CDate opeDate = last_operation_srv +freq_op + freq_operation_srv - freq_op;271 // const CDate writeDate = last_Write_srv + freq_write_srv;272 273 // if (opeDate <= currDate)274 // {275 // for (int n = 0; n < ranks.size(); n++)276 // {277 // CArray<double,1> data_tmp;278 // *buffers[n] >> data_tmp;279 // (*foperation_srv[ranks[n]])(data_tmp);280 // }281 // last_operation_srv = currDate;282 // }283 284 // if (writeDate < (currDate + freq_operation_srv))285 // {286 // for (int n = 0; n < ranks.size(); n++)287 // {288 // this->foperation_srv[ranks[n]]->final();289 // }290 291 // last_Write_srv = writeDate;292 // }293 294 // if (context->hasClient && context->hasServer)295 // {296 // size_t writtenSize;297 // // if (field->getUseCompressedOutput())298 // // writtenSize = grid->getNumberWrittenIndexes();299 // // else300 // writtenSize = grid->getWrittenDataSize();301 302 // CArray<double,1> fieldData(writtenSize);303 // // if (!field->default_value.isEmpty()) fieldData = field->default_value;304 305 // // if (field->getUseCompressedOutput())306 // // field->outputCompressedField(fieldData);307 // // else308 // this->outputField(fieldData);309 // sendUpdateData(fieldData);310 // }311 // if (!context->hasClient && context->hasServer)312 // {313 // writeField();314 // }315 316 // lastlast_Write_srv = last_Write_srv;317 318 // }319 261 320 262 void CField::writeField(void) … … 331 273 } 332 274 333 voidCField::sendReadDataRequest(const CDate& tsDataRequested)275 bool CField::sendReadDataRequest(const CDate& tsDataRequested) 334 276 { 335 277 CContext* context = CContext::getCurrent(); … … 339 281 lastDataRequestedFromServer = tsDataRequested; 340 282 341 CEventClient event(getType(), EVENT_ID_READ_DATA); 342 if (client->isServerLeader()) 283 if (!isEOF) // No need to send the request if we already know we are at EOF 343 284 { 344 CMessage msg; 345 msg << getId(); 346 const std::list<int>& ranks = client->getRanksServerLeader(); 347 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 348 event.push(*itRank, 1, msg); 349 client->sendEvent(event); 350 } 351 else client->sendEvent(event); 285 CEventClient event(getType(), EVENT_ID_READ_DATA); 286 if (client->isServerLeader()) 287 { 288 CMessage msg; 289 msg << getId(); 290 const std::list<int>& ranks = client->getRanksServerLeader(); 291 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 292 event.push(*itRank, 1, msg); 293 client->sendEvent(event); 294 } 295 else client->sendEvent(event); 296 } 297 else 298 serverSourceFilter->signalEndOfStream(tsDataRequested); 299 300 return !isEOF; 352 301 } 353 302 … … 361 310 362 311 bool dataRequested = false; 312 363 313 while (currentDate >= lastDataRequestedFromServer) 364 314 { … … 368 318 info(20) << "lastDataRequestedFromServer + file->output_freq.getValue() : " << lastDataRequestedFromServer + file->output_freq << endl ; 369 319 370 sendReadDataRequest(lastDataRequestedFromServer + file->output_freq); 371 372 dataRequested = true; 373 } 320 dataRequested |= sendReadDataRequest(lastDataRequestedFromServer + file->output_freq); 321 } 322 374 323 return dataRequested; 375 324 } … … 386 335 { 387 336 CContext* context = CContext::getCurrent(); 388 CContextClient* client = context->client; 337 CContextClient* client = context->client; 389 338 390 339 CEventClient event(getType(), EVENT_ID_READ_DATA_READY); … … 393 342 bool hasData = readField(); 394 343 395 344 map<int, CArray<double,1> >::iterator it; 396 345 if (!grid->doGridHaveDataDistributed()) 397 346 { … … 413 362 } 414 363 } 415 416 364 client->sendEvent(event); 417 365 } … … 500 448 std::map<int, CArray<double,1> > data; 501 449 502 bool isEOF = false;503 504 450 for (int i = 0; i < ranks.size(); i++) 505 451 { … … 585 531 //---------------------------------------------------------------- 586 532 587 bool CField::isActive(void) const 588 { 589 return (instantDataFilter != NULL); 533 bool CField::isActive(bool atCurrentTimestep /*= false*/) const 534 { 535 if (clientSourceFilter) 536 return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 537 else if (storeFilter) 538 return true; 539 else if (instantDataFilter) 540 ERROR("bool CField::isActive(bool atCurrentTimestep)", 541 << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 542 543 return false; 590 544 } 591 545 … … 815 769 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 816 770 } 817 else if (context->hasServer)771 else if (context->hasServer) 818 772 solveServerOperation(); 819 773 … … 940 894 { 941 895 // Check if we have an expression to parse 942 if (hasExpression())896 if (hasExpression()) 943 897 { 944 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 945 boost::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 946 947 // Check if a spatial transformation is needed 948 if (!field_ref.isEmpty()) 949 { 950 CGrid* gridRef = CField::get(field_ref)->grid; 951 952 if (grid && grid != gridRef && grid->hasTransform()) 898 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 899 boost::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 900 901 // Check if a spatial transformation is needed 902 if (!field_ref.isEmpty()) 953 903 { 954 double defaultValue = !default_value.isEmpty() ? default_value : 0.0; 955 std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, defaultValue); 956 957 filter->connectOutput(filters.first, 0); 958 filter = filters.second; 904 CGrid* gridRef = CField::get(field_ref)->grid; 905 906 if (grid && grid != gridRef && grid->hasTransform()) 907 { 908 bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 909 double defaultValue = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 910 std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, hasMissingValue, defaultValue); 911 912 filter->connectOutput(filters.first, 0); 913 filter = filters.second; 914 } 959 915 } 960 } 961 962 instantDataFilter = filter; 916 917 instantDataFilter = filter; 963 918 } 964 919 // Check if we have a reference on another field … … 967 922 // Check if the data is to be read from a file 968 923 else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 969 instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid,970 freq_offset.isEmpty() ? NoneDu : freq_offset,971 true));924 instantDataFilter = serverSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, 925 freq_offset.isEmpty() ? NoneDu : freq_offset, 926 true)); 972 927 else // The data might be passed from the model 973 instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid));974 }975 976 // If the field data is to be read by the client or/and written to a file977 if (enableOutput && !storeFilter && !fileWriterFilter)978 {979 if (!read_access.isEmpty() && read_access)980 928 { 981 storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid)); 982 instantDataFilter->connectOutput(storeFilter, 0); 929 bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 930 double defaultValue = ignoreMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 931 instantDataFilter = clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, NoneDu, false, 932 ignoreMissingValue, defaultValue)); 983 933 } 984 985 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 986 { 987 fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this)); 988 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 989 } 990 } 991 } 992 } 993 934 } 935 } 936 937 // If the field data is to be read by the client or/and written to a file 938 if (enableOutput && !storeFilter && !fileWriterFilter) 939 { 940 if (!read_access.isEmpty() && read_access) 941 { 942 storeFilter = boost::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid)); 943 instantDataFilter->connectOutput(storeFilter, 0); 944 } 945 946 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 947 { 948 fileWriterFilter = boost::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this)); 949 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 950 } 951 } 952 } 994 953 995 954 /*! … … 1000 959 * \return the output pin corresponding to the field reference 1001 960 */ 1002 boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 1003 { 1004 if (instantDataFilter || field_ref.isEmpty()) 1005 ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 1006 "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 1007 1008 CField* fieldRef = CField::get(field_ref); 1009 fieldRef->buildFilterGraph(gc, false); 1010 1011 std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters; 1012 // Check if a spatial transformation is needed 1013 if (grid && grid != fieldRef->grid && grid->hasTransform()) 1014 { 1015 double defaultValue = !default_value.isEmpty() ? default_value : 0.0; 1016 filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, defaultValue); 1017 } 1018 else 1019 filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 1020 1021 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 1022 1023 return filters.second; 1024 } 961 boost::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 962 { 963 if (instantDataFilter || field_ref.isEmpty()) 964 ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 965 "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 966 967 CField* fieldRef = CField::get(field_ref); 968 fieldRef->buildFilterGraph(gc, false); 969 970 std::pair<boost::shared_ptr<CFilter>, boost::shared_ptr<CFilter> > filters; 971 // Check if a spatial transformation is needed 972 if (grid && grid != fieldRef->grid && grid->hasTransform()) 973 { 974 bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 975 double defaultValue = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 976 filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, hasMissingValue, defaultValue); 977 } 978 else 979 filters.first = filters.second = boost::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 980 981 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 982 983 return filters.second; 984 } 1025 985 1026 986 /*! … … 1058 1018 { 1059 1019 if (!clientSourceFilter) 1060 clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid)); 1020 { 1021 bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1022 double defaultValue = ignoreMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1023 clientSourceFilter = boost::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, NoneDu, false, 1024 ignoreMissingValue, defaultValue)); 1025 } 1061 1026 1062 1027 selfReferenceFilter = clientSourceFilter; … … 1104 1069 return it->second; 1105 1070 } 1071 1072 /*! 1073 * Returns the temporal filter corresponding to the field's temporal operation 1074 * for the specified operation frequency. 1075 * 1076 * \param gc the garbage collector to use 1077 * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 1078 * \return the output pin corresponding to the requested temporal filter 1079 */ 1080 1081 boost::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1082 { 1083 if (instantDataFilter || !hasExpression()) 1084 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 1085 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1086 1087 if (!selfReferenceFilter) getSelfReference(gc) ; 1088 1089 if (serverSourceFilter || clientSourceFilter) 1090 { 1091 if (operation.isEmpty()) 1092 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1093 << "An operation must be defined for field \"" << getId() << "\"."); 1094 1095 if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 1096 if (freq_offset.isEmpty()) freq_offset.setValue(NoneDu); 1097 1098 const bool ignoreMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1099 1100 boost::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1101 CContext::getCurrent()->getCalendar()->getInitDate(), 1102 freq_op, freq_offset, outFreq, 1103 ignoreMissingValue, ignoreMissingValue ? default_value : 0.0)); 1104 selfReferenceFilter->connectOutput(temporalFilter, 0); 1105 return temporalFilter ; 1106 } 1107 else if (!field_ref.isEmpty()) 1108 { 1109 CField* fieldRef = CField::get(field_ref); 1110 fieldRef->buildFilterGraph(gc, false); 1111 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1112 } 1113 } 1106 1114 1107 1115 //---------------------------------------------------------------- -
XIOS/dev/dev_olga/src/node/field.hpp
r1144 r1158 99 99 100 100 public: 101 bool isActive( void) const;101 bool isActive(bool atCurrentTimestep = false) const; 102 102 bool hasOutputFile; 103 103 … … 150 150 void recvUpdateData(std::map<int,CBufferIn*>& rankBuffers); 151 151 void writeField(void); 152 voidsendReadDataRequest(const CDate& tsDataRequested);152 bool sendReadDataRequest(const CDate& tsDataRequested); 153 153 bool sendReadDataRequestIfNeeded(void); 154 154 static void recvReadDataRequest(CEventServer& event); … … 157 157 static void recvReadDataReady(CEventServer& event); 158 158 void recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers); 159 void outputField(CArray<double,3>& fieldOut); 160 void outputField(CArray<double,2>& fieldOut); 159 161 void outputField(CArray<double,1>& fieldOut); 162 void inputField(CArray<double,3>& fieldOut); 163 void inputField(CArray<double,2>& fieldOut); 160 164 void inputField(CArray<double,1>& fieldOut); 161 165 void outputCompressedField(CArray<double, 1>& fieldOut); … … 240 244 //! The terminal filter which stores the instant data 241 245 boost::shared_ptr<CStoreFilter> storeFilter; 242 //! The terminal filter which sends the data to file246 //! The terminal filter which writes the data to file 243 247 boost::shared_ptr<CFileWriterFilter> fileWriterFilter; 244 248 //! The terminal filter which writes data to file -
XIOS/dev/dev_olga/src/node/file.cpp
r1144 r1158 14 14 #include "type.hpp" 15 15 #include "xios_spl.hpp" 16 #include "context_client.hpp" 16 17 #include "mpi.hpp" 18 #include "timer.hpp" 17 19 18 20 namespace xios { … … 49 51 //---------------------------------------------------------------- 50 52 51 const StdString &CFile::getFileOutputName(void) const52 { 53 return name.isEmpty() ? getId() : name;53 const StdString CFile::getFileOutputName(void) const 54 { 55 return (name.isEmpty() ? getId() : name) + (name_suffix.isEmpty() ? StdString("") : name_suffix.getValue()); 54 56 } 55 57 … … 215 217 if (!split_freq.isEmpty()) 216 218 { 217 if (context->registryIn->foundKey("splitStart") && context->registryIn->foundKey("splitEnd")) 219 StdString keySuffix("CContext_"+CContext::getCurrent()->getId()+"::CFile_"+getFileOutputName()+"::") ; 220 if (context->registryIn->foundKey(keySuffix+"splitStart") && context->registryIn->foundKey(keySuffix+"splitEnd")) 218 221 { 219 222 CDate savedSplitStart(*context->getCalendar()), savedSplitEnd(*context->getCalendar()); 220 context->registryIn->getKey( "splitStart", savedSplitStart);221 context->registryIn->getKey( "splitEnd", savedSplitEnd);223 context->registryIn->getKey(keySuffix+"splitStart", savedSplitStart); 224 context->registryIn->getKey(keySuffix+"splitEnd", savedSplitEnd); 222 225 223 226 if (savedSplitStart <= lastSplit && lastSplit <= savedSplitEnd) … … 234 237 const int recordOffset = record_offset.isEmpty() ? 0 : record_offset; 235 238 236 // set<CAxis*> setAxis;237 // set<CDomain*> setDomains;238 239 set<StdString> setAxis; 239 240 set<StdString> setDomains; … … 263 264 if (allDomainEmpty) MPI_Comm_free(&fileComm); 264 265 265 if (time_counter.isEmpty()) time_counter.setValue(time_counter_attr::centered);266 // if (time_counter.isEmpty()) time_counter.setValue(time_counter_attr::centered); 266 267 if (time_counter_name.isEmpty()) time_counter_name = "time_counter"; 267 268 } … … 281 282 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 282 283 { 284 CTimer::get("Files : create headers").resume(); 283 285 if (!isOpen) createHeader(); 286 CTimer::get("Files : create headers").suspend(); 284 287 checkSync(); 285 288 } … … 303 306 if (!mode.isEmpty() && mode.getValue() == mode_attr::read) 304 307 { 308 CTimer::get("Files : open headers").resume(); 305 309 if (!isOpen) openInReadMode(&(context->server->intraComm)); 310 CTimer::get("Files : open headers").suspend(); 306 311 } 307 312 //checkSplit(); // Really need for reading? … … 374 379 { 375 380 StdString filename = getFileOutputName(); 376 if (!name_suffix.isEmpty()) filename+=name_suffix.getValue();377 381 378 382 // determine splitting format in the file name : firstPart%start_date%middlePart%end_date%lastPart … … 441 445 oss << lastPart ; 442 446 443 context->registryOut->setKey("splitStart", lastSplit); 444 context->registryOut->setKey("splitEnd", splitEnd); 447 StdString keySuffix("CContext_"+CContext::getCurrent()->getId()+"::CFile_"+getFileOutputName()+"::") ; 448 context->registryOut->setKey(keySuffix+"splitStart", lastSplit); 449 context->registryOut->setKey(keySuffix+"splitEnd", splitEnd); 445 450 } 446 451 else oss<<firstPart<<lastPart ; … … 489 494 if (isOpen) data_out->closeFile(); 490 495 491 data_out = shared_ptr<CDataOutput>(new CNc4DataOutput( oss.str(), append, useClassicFormat, useCFConvention,496 data_out = shared_ptr<CDataOutput>(new CNc4DataOutput(this, oss.str(), append, useClassicFormat, useCFConvention, 492 497 fileComm, multifile, isCollective, time_counter_name)); 493 498 isOpen = true; … … 509 514 { 510 515 CField* field = *it; 516 this->data_out->writeFieldTimeAxis(field); 517 } 518 519 for (it = this->enabledFields.begin(); it != end; it++) 520 { 521 CField* field = *it; 511 522 this->data_out->writeField(field); 512 523 } … … 517 528 518 529 this->data_out->definition_end(); 530 } 531 else 532 { 533 // check time axis even in append mode 534 std::vector<CField*>::iterator it, end = this->enabledFields.end(); 535 for (it = this->enabledFields.begin(); it != end; it++) 536 { 537 CField* field = *it; 538 this->data_out->writeFieldTimeAxis(field); 539 } 519 540 } 520 541 } … … 535 556 StdOStringStream oss; 536 557 oss << filename; 537 if (!name_suffix.isEmpty()) oss << name_suffix.getValue();538 558 539 559 if (!split_freq.isEmpty()) … … 872 892 } 873 893 874 875 894 /*! 876 895 \brief Send a message to create a field on server side -
XIOS/dev/dev_olga/src/node/file.hpp
r1144 r1158 70 70 public: 71 71 /// Accesseurs /// 72 const StdString &getFileOutputName(void) const;72 const StdString getFileOutputName(void) const; 73 73 boost::shared_ptr<CDataOutput> getDataOutput(void) const; 74 74 boost::shared_ptr<CDataInput> getDataInput(void) const; -
XIOS/dev/dev_olga/src/node/grid.cpp
r1144 r1158 31 31 , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0) 32 32 , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 33 , globalDim_(),connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)33 , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false) 34 34 , transformations_(0), isTransformed_(false) 35 , axisPositionInGrid_(), positionDimensionDistributed_(1),hasDomainAxisBaseRef_(false)35 , axisPositionInGrid_(), hasDomainAxisBaseRef_(false) 36 36 , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_() 37 37 , computedWrittenIndex_(false) … … 50 50 , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0) 51 51 , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 52 , globalDim_(),connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false)52 , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), isCompressible_(false) 53 53 , transformations_(0), isTransformed_(false) 54 , axisPositionInGrid_(), positionDimensionDistributed_(1),hasDomainAxisBaseRef_(false)54 , axisPositionInGrid_(), hasDomainAxisBaseRef_(false) 55 55 , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_() 56 56 , computedWrittenIndex_(false) … … 76 76 77 77 78 StdSize CGrid::getDimension(void) const79 { 80 return g lobalDim_.size();78 StdSize CGrid::getDimension(void) 79 { 80 return getGlobalDimension().size(); 81 81 } 82 82 … … 196 196 for (int i = 0; i < axisListP.size(); ++i) 197 197 { 198 axisListP[i]->checkAttributesOnClientAfterTransformation(g lobalDim_,axisPositionInGrid_[i]);198 axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(),axisPositionInGrid_[i]); 199 199 } 200 200 } … … 243 243 this->solveScalarRef(areAttributesChecked); 244 244 this->solveAxisRef(areAttributesChecked); 245 this->solveDomainRef(areAttributesChecked); 246 computeGridGlobalDimension(getDomains(), getAxis(), getScalars(), axis_domain_order); 245 this->solveDomainRef(areAttributesChecked); 247 246 this->isDomainAxisChecked = areAttributesChecked; 248 247 } … … 311 310 {sendIndex(); this->isIndexSent = true;} 312 311 } 312 313 // Not sure about this 314 //if (!(this->hasTransform() && !this->isTransformed())) 315 // this->isChecked = true; 316 //return; 313 317 } 314 318 … … 409 413 using namespace std; 410 414 std::vector<CDomain*> domainP = this->getDomains(); 411 std::vector<CAxis*> axisP = this->getAxis(); 415 std::vector<CAxis*> axisP = this->getAxis(); 412 416 int dim = domainP.size() * 2 + axisP.size(); 413 417 … … 512 516 { 513 517 if (sendAtt) 514 axisListP[i]->sendCheckedAttributes(g lobalDim_,axisPositionInGrid_[i]);518 axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]); 515 519 else 516 520 axisListP[i]->checkAttributesOnClient(); … … 534 538 } 535 539 } 540 } 541 std::vector<int> CGrid::getAxisPositionInGrid() const 542 { 543 return axisPositionInGrid_; 536 544 } 537 545 … … 652 660 } 653 661 } 654 655 656 662 } 657 663 } … … 695 701 // Compute mapping between client and server 696 702 std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 697 CServerDistributionDescription serverDistributionDescription(g lobalDim_, client->serverSize);703 CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 698 704 serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 699 705 client->clientRank, … … 933 939 } 934 940 } 935 941 } 936 942 } 937 943 //---------------------------------------------------------------- … … 1122 1128 } 1123 1129 1130 /* 1131 void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field) 1132 { 1133 const CArray<size_t,1>& out_i = outIndexFromClient[rank]; 1134 StdSize numElements = stored.numElements(); 1135 for (StdSize n = 0; n < numElements; ++n) 1136 { 1137 field[out_i(n)] = stored(n); 1138 } 1139 } 1140 1141 void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored) 1142 { 1143 const CArray<size_t,1>& out_i = outIndexFromClient[rank]; 1144 StdSize numElements = stored.numElements(); 1145 for (StdSize n = 0; n < numElements; ++n) 1146 { 1147 stored(n) = field[out_i(n)]; 1148 } 1149 } 1150 1151 void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field) 1152 { 1153 const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank]; 1154 StdSize numElements = stored.numElements(); 1155 for (StdSize n = 0; n < numElements; ++n) 1156 { 1157 field[out_i(n)] = stored(n); 1158 } 1159 } 1160 */ 1161 //---------------------------------------------------------------- 1162 1124 1163 void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const 1125 1164 { … … 1170 1209 { 1171 1210 CContext* context = CContext::getCurrent(); 1172 // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;1173 1211 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1; 1174 1212 for (int p = 0; p < nbSrvPools; ++p) … … 1538 1576 } 1539 1577 1540 void CGrid::computeGridGlobalDimension(const std::vector<CDomain*>& domains, 1541 const std::vector<CAxis*>& axis, 1542 const std::vector<CScalar*>& scalars, 1543 const CArray<int,1>& axisDomainOrder) 1544 { 1545 globalDim_.resize(domains.size()*2+axis.size()+scalars.size()); 1578 /* 1579 Compute on the fly the global dimension of a grid with its elements 1580 \param[in/out] globalDim global dimension of grid 1581 \param[in] domains list of its domains 1582 \param[in] axiss list of its axis 1583 \param[in] scalars list of its scalars 1584 \param[in] axisDomainOrder the order of element in a grid (e.g: scalar then axis) 1585 \return The dimension of which we do distribution (often for server) 1586 */ 1587 int CGrid::computeGridGlobalDimension(std::vector<int>& globalDim, 1588 const std::vector<CDomain*> domains, 1589 const std::vector<CAxis*> axis, 1590 const std::vector<CScalar*> scalars, 1591 const CArray<int,1>& axisDomainOrder) 1592 { 1593 globalDim.resize(domains.size()*2+axis.size()+scalars.size()); 1594 int positionDimensionDistributed = 1; 1546 1595 int idx = 0, idxDomain = 0, idxAxis = 0, idxScalar = 0; 1547 1596 for (int i = 0; i < axisDomainOrder.numElements(); ++i) … … 1551 1600 if (!(domains[idxDomain]->type.isEmpty()) && (domains[idxDomain]->type==CDomain::type_attr::unstructured)) 1552 1601 { 1553 positionDimensionDistributed _= idx;1602 positionDimensionDistributed = idx; 1554 1603 } 1555 1604 else 1556 1605 { 1557 positionDimensionDistributed _= idx +1;1558 } 1559 1560 globalDim _[idx] = domains[idxDomain]->ni_glo.getValue();1561 globalDim _[idx+1] = domains[idxDomain]->nj_glo.getValue();1606 positionDimensionDistributed = idx +1; 1607 } 1608 1609 globalDim[idx] = domains[idxDomain]->ni_glo.getValue(); 1610 globalDim[idx+1] = domains[idxDomain]->nj_glo.getValue(); 1562 1611 1563 1612 ++idxDomain; … … 1566 1615 else if (1 == axisDomainOrder(i)) 1567 1616 { 1568 globalDim _[idx] = axis[idxAxis]->n_glo.getValue();1617 globalDim[idx] = axis[idxAxis]->n_glo.getValue(); 1569 1618 ++idxAxis; 1570 1619 ++idx; … … 1572 1621 else 1573 1622 { 1574 globalDim _[idx] = 1;1623 globalDim[idx] = 1; 1575 1624 ++idxScalar; 1576 1625 ++idx; 1577 1626 } 1578 1627 } 1579 } 1580 1628 1629 return positionDimensionDistributed; 1630 } 1631 1632 // Retrieve the global dimension of grid 1581 1633 std::vector<int> CGrid::getGlobalDimension() 1582 1634 { 1583 return globalDim_; 1635 std::vector<int> globalDim; 1636 computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order); 1637 1638 return globalDim; 1639 } 1640 1641 // Retrieve dimension on which we do distribution (Very often, it should be 2nd dimension) 1642 int CGrid::getDistributedDimension() 1643 { 1644 std::vector<int> globalDim; 1645 return computeGridGlobalDimension(globalDim, getDomains(), getAxis(), getScalars(), axis_domain_order); 1584 1646 } 1585 1647 -
XIOS/dev/dev_olga/src/node/grid.hpp
r1144 r1158 87 87 88 88 /// Accesseurs /// 89 StdSize getDimension(void) const;89 StdSize getDimension(void); 90 90 91 91 StdSize getDataSize(void) const; … … 176 176 std::vector<int> getGlobalDimension(); 177 177 bool isScalarGrid() const; 178 std::vector<int> getAxisPositionInGrid() const; 178 179 179 180 bool doGridHaveDataToWrite(); … … 268 269 void computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement, 269 270 CClientServerMapping::GlobalIndexMap& globalIndexOnServer); 271 int computeGridGlobalDimension(std::vector<int>& globalDim, 272 const std::vector<CDomain*> domains, 273 const std::vector<CAxis*> axis, 274 const std::vector<CScalar*> scalars, 275 const CArray<int,1>& axisDomainOrder); 276 int getDistributedDimension(); 270 277 271 278 void computeClientIndex(); … … 296 303 std::vector<int> axisPositionInGrid_; 297 304 CGridTransformation* transformations_; 298 bool hasDomainAxisBaseRef_; 299 std::vector<int> globalDim_; 305 bool hasDomainAxisBaseRef_; 300 306 std::map<CGrid*, std::pair<bool,StdString> > gridSrc_; 301 307 bool hasTransform_; -
XIOS/dev/dev_olga/src/node/interpolate_domain.cpp
r1021 r1158 55 55 { 56 56 case mode_attr::read: 57 if (this-> file.isEmpty())57 if (this->weight_filename.isEmpty()) 58 58 { 59 59 if (!this->write_weight) … … 64 64 else 65 65 { 66 weightFile = this-> file;66 weightFile = this->weight_filename; 67 67 ifstream f(weightFile.c_str()); 68 68 if (!f.good()) … … 75 75 break; 76 76 case mode_attr::read_or_compute: 77 if (!this-> file.isEmpty() && !this->write_weight)77 if (!this->weight_filename.isEmpty() && !this->write_weight) 78 78 { 79 weightFile = this-> file;79 weightFile = this->weight_filename; 80 80 ifstream f(weightFile.c_str()); 81 81 if (!f.good()) -
XIOS/dev/dev_olga/src/node/mesh.cpp
r946 r1158 11 11 /// ////////////////////// Définitions ////////////////////// /// 12 12 13 CMesh::CMesh(void) : nbNodesGlo {0}, nbEdgesGlo{0}14 , node_start {0}, node_count{0}15 , edge_start {0}, edge_count{0}16 , nbFaces_ {0}, nbNodes_{0}, nbEdges_{0}17 , nodesAreWritten {false}, edgesAreWritten{false}, facesAreWritten{false}13 CMesh::CMesh(void) : nbNodesGlo(0), nbEdgesGlo(0) 14 , node_start(0), node_count(0) 15 , edge_start(0), edge_count(0) 16 , nbFaces_(0), nbNodes_(0), nbEdges_(0) 17 , nodesAreWritten(false), edgesAreWritten(false), facesAreWritten(false) 18 18 , node_lon(), node_lat() 19 19 , edge_lon(), edge_lat(), edge_nodes() 20 20 , face_lon(), face_lat() 21 21 , face_nodes() 22 , pNodeGlobalIndex {NULL}, pEdgeGlobalIndex{NULL}22 , pNodeGlobalIndex(NULL), pEdgeGlobalIndex(NULL) 23 23 { 24 24 } … … 91 91 seed ^= sizetHash(first) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 92 92 } 93 return seed ;94 }95 96 ///----------------------------------------------------------------97 /*!98 * \fn size_t generateEdgeIndex(size_t first, size_t second, int rank)99 * Generates an edge index.100 * If the same edge is generated by two processes, each process will have its own edge index.101 * \param [in] first Edge node.102 * \param [in] second Edge node.103 * \param [in] rank MPI process rank.104 */105 size_t generateEdgeIndex(size_t first, size_t second, int rank)106 {107 size_t seed = rank ;108 if (first < second)109 {110 seed = hashPair(seed, first);111 seed = hashPair(seed, second);112 }113 else114 {115 seed = hashPair(seed, second);116 seed = hashPair(seed, first);117 }118 119 93 return seed ; 120 94 } … … 141 115 return seed ; 142 116 } 117 118 ///---------------------------------------------------------------- 119 /*! 120 * \fn size_t generateNodeIndex(vector<size_t>& valList) 121 * Generates a node index unique for all processes. 122 * \param [in] valList Vector storing four node hashes. 123 */ 124 size_t generateNodeIndex(vector<size_t>& valList) 125 { 126 // Sort is needed to avoid problems for nodes with lon = 0 generated by faces in east and west semisphere 127 vector<size_t> vec = valList; 128 sort (vec.begin(), vec.end()); 129 size_t seed = vec[0] ; 130 int it = 1; 131 for(; it != vec.size(); ++it) 132 { 133 seed = hashPair(seed, vec[it]); 134 } 135 return seed ; 136 } 137 143 138 144 139 ///---------------------------------------------------------------- … … 600 595 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2Idx; 601 596 CArray<size_t,1> nodeHashList(nbEdges_*nvertex*4); 597 int nbHash = 0; 602 598 for (int ne = 0; ne < nbEdges_; ++ne) 603 599 { … … 609 605 if (nodeHash2Idx[hashValues[nh]].size() == 0) 610 606 { 611 nodeHash2Idx[hashValues[nh]].push_back(generateNodeIndex(hashValues , mpiRank));607 nodeHash2Idx[hashValues[nh]].push_back(generateNodeIndex(hashValues)); 612 608 nodeHash2Idx[hashValues[nh]].push_back(mpiRank); 609 nodeHashList(nbHash) = hashValues[nh]; 610 ++nbHash; 613 611 } 614 nodeHashList((ne*nvertex + nv)*4 + nh) = hashValues[nh];615 616 617 }612 } 613 } 614 } 615 nodeHashList.resizeAndPreserve(nbHash); 618 616 619 617 // (2.2) Generating global node indexes 620 // The ownership criterion: priority of the process holding thesmaller index618 // The ownership criterion: priority of the process of smaller index 621 619 // Maps generated in this step are: 622 // nodeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 623 // nodeIdx2IdxMin = <idx, idxMin> 624 // nodeIdx2IdxGlo = <idxMin, idxMin> 625 626 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxMin; 627 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxGlo; 628 CArray<size_t,1> nodeIdxMinList(nbEdges_*nvertex); 629 630 CClientClientDHTSizet dhtNodeHash(nodeHash2Idx, comm); 631 dhtNodeHash.computeIndexInfoMapping(nodeHashList); 632 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2Info = dhtNodeHash.getInfoIndexMap(); 633 size_t iIdxMin = 0; 634 635 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeHash2Info.begin(); it != nodeHash2Info.end(); ++it) 636 { 637 size_t idx = (it->second)[0]; 638 size_t idxMin = (it->second)[0]; 639 for (int i = 2; i < (it->second).size();) 640 { 641 if (mpiRank == (it->second)[i+1]) 642 { 643 idx = (it->second)[i]; 644 } 645 if ((it->second)[i] < idxMin) 646 { 647 idxMin = (it->second)[i]; 648 (it->second)[i] = (it->second)[i-2]; 649 } 650 i += 2; 651 } 652 (it->second)[0] = idxMin; 653 if (nodeIdx2IdxMin.count(idx) == 0) 654 { 655 nodeIdx2IdxMin[idx].push_back(idxMin); 656 if (idx == idxMin) 657 nodeIdx2IdxGlo[idxMin].push_back(idxMin); 658 nodeIdxMinList(iIdxMin) = idxMin; 659 ++iIdxMin; 660 } 661 } 662 nodeIdxMinList.resizeAndPreserve(iIdxMin); 663 CDHTAutoIndexing dhtNodeIdxGlo = CDHTAutoIndexing(nodeIdx2IdxGlo, comm); 664 CClientClientDHTSizet dhtNodeIdx(nodeIdx2IdxGlo, comm); 665 dhtNodeIdx.computeIndexInfoMapping(nodeIdxMinList); 666 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdxMin2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 667 // nodeIdx2IdxGlo holds global indexes only for nodes owned by a process 668 // nodeIdxMin2IdxGlo holds global indexes for all nodes generated by a process 620 // Maps generated in this step are: 621 // nodeHash2Info = <hash, [[idx, rankMin], [idx, rank1], [idx, rank3]..]> 622 // nodeIdx2Idx = <idx, <rankOwner, idx>> 623 624 CClientClientDHTSizet dhtNodeHash(nodeHash2Idx, comm); 625 dhtNodeHash.computeIndexInfoMapping(nodeHashList); 626 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2Info = dhtNodeHash.getInfoIndexMap(); 627 628 629 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2Idx; 630 CArray<size_t,1> nodeIdxList(nbEdges_*nvertex*4); 631 size_t nIdx = 0; 632 633 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeHash2Info.begin(); it != nodeHash2Info.end(); ++it) 634 { 635 size_t rankMin = (it->second)[1]; 636 size_t idx = (it->second)[0]; 637 for (int i = 2; i < (it->second).size();) 638 { 639 if ( (it->second)[i+1] < rankMin) 640 { 641 idx = (it->second)[i]; 642 rankMin = (it->second)[i+1]; 643 (it->second)[i+1] = (it->second)[i-1]; 644 } 645 i += 2; 646 } 647 if (nodeIdx2Idx.count(idx) == 0) 648 { 649 if (mpiRank == rankMin) 650 { 651 nodeIdx2Idx[idx].push_back(rankMin); 652 nodeIdx2Idx[idx].push_back(idx); 653 } 654 nodeIdxList(nIdx) = idx; 655 ++nIdx; 656 } 657 } 658 nodeIdxList.resizeAndPreserve(nIdx); 659 660 // CDHTAutoIndexing will not give consistent node numbering for varying number of procs. => 661 // Solution: global node indexing by hand. 662 // Maps modified in this step: 663 // nodeIdx2Idx = <idx, idxGlo> 664 int nodeCount = nodeIdx2Idx.size(); 665 int nodeStart, nbNodes; 666 MPI_Scan(&nodeCount, &nodeStart, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm); 667 int nNodes = nodeStart; 668 MPI_Bcast(&nNodes, 1, MPI_UNSIGNED_LONG, mpiSize-1, comm); 669 nbNodesGlo = nNodes; 670 671 nodeStart -= nodeCount; 672 node_start = nodeStart; 673 node_count = nodeCount; 674 CClientClientDHTSizet::Index2VectorInfoTypeMap dummyMap; // just a dummy map used to ensure that each node is numbered only once 675 size_t count = 0; 676 677 for (int ne = 0; ne < nbEdges_; ++ne) 678 { 679 for (int nv = 0; nv < nvertex; ++nv) 680 { 681 vector<size_t> hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 682 size_t nodeIdx = generateNodeIndex(hashValues); 683 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeIdx2Idx.find(nodeIdx); 684 if (it != nodeIdx2Idx.end()) 685 { 686 if (dummyMap.count(nodeIdx) == 0) 687 { 688 dummyMap[nodeIdx].push_back(nodeIdx); 689 (it->second)[1] = node_start + count; 690 ++count; 691 } 692 } 693 } 694 } 695 696 CClientClientDHTSizet dhtNodeIdx(nodeIdx2Idx, comm); 697 dhtNodeIdx.computeIndexInfoMapping(nodeIdxList); 698 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdx2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 669 699 670 700 // (2.3) Saving variables: node_lon, node_lat, edge_nodes 671 701 // Creating map nodeHash2IdxGlo <hash, idxGlo> 672 702 // Creating map edgeHash2IdxGlo <hash, idxGlo> 673 nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal();674 node_count = dhtNodeIdxGlo.getIndexCount();675 node_start = dhtNodeIdxGlo.getIndexStart();703 // nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal(); 704 // node_count = dhtNodeIdxGlo.getIndexCount(); 705 // node_start = dhtNodeIdxGlo.getIndexStart(); 676 706 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeHash2IdxGlo; 677 707 node_lon.resize(node_count); … … 685 715 { 686 716 hashValues = CMesh::createHashes(bounds_lon(nv, ne), bounds_lat(nv, ne)); 687 size_t myIdx = generateNodeIndex(hashValues, mpiRank); 688 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = nodeIdx2IdxMin.find(myIdx); 689 size_t ownerIdx = (itIdx->second)[0]; 690 691 if (myIdx == ownerIdx) 692 { 693 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = nodeIdx2IdxGlo.find(myIdx); 694 idxGlo = (itIdxGlo->second)[0]; 717 size_t myIdx = generateNodeIndex(hashValues); 718 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = nodeIdx2IdxGlo.find(myIdx); 719 idxGlo = (itIdx->second)[1]; 720 721 if (mpiRank == (itIdx->second)[0]) 722 { 695 723 // node_lon(idxGlo - node_start) = (bounds_lon(nv, ne) == 360.) ? (0.) : (bounds_lon(nv, ne)); 696 724 node_lon(idxGlo - node_start) = bounds_lon(nv, ne); 697 725 node_lat(idxGlo - node_start) = bounds_lat(nv, ne); 698 726 } 699 else700 {701 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = nodeIdxMin2IdxGlo.find(ownerIdx);702 idxGlo = (itIdxGlo->second)[0];703 }704 705 727 edge_nodes(nv,ne) = idxGlo; 706 728 for (int nh = 0; nh < 4; ++nh) … … 793 815 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHash2Rank; 794 816 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 795 CArray<size_t,1> edgeIdx GloList(nbFaces_*nvertex);817 CArray<size_t,1> edgeIdxList(nbFaces_*nvertex); 796 818 size_t iIdx = 0; 797 819 … … 824 846 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) 825 847 { 826 edgeIdx GloList(iIdx) = edgeIdxGlo;848 edgeIdxList(iIdx) = edgeIdxGlo; 827 849 ++iIdx; 828 850 } 829 851 edgeIdxGlo2Face[edgeIdxGlo].push_back(faceIdxGlo); 830 edgeHash2Rank[edgeHash].push_back(itEdgeHash->first);831 852 edgeHash2Rank[edgeHash].push_back(mpiRank); 853 edgeHash2Rank[edgeHash].push_back(itEdgeHash->second[0]); 832 854 } 833 855 else … … 837 859 } 838 860 } 839 edgeIdx GloList.resizeAndPreserve(iIdx);861 edgeIdxList.resizeAndPreserve(iIdx); 840 862 841 863 // (1.3) Saving remaining variables edge_faces and face_faces … … 846 868 dhtEdgeHash.computeIndexInfoMapping(edgeHashList); 847 869 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2Info = dhtEdgeHash.getInfoIndexMap(); 848 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeHashMin2IdxGlo; 849 850 // edgeHash2Info = <edgeHash, <idxGlo, rank1, idxGlo, rank2>> 851 // edgeHashMin2IdxGlo = <edgeHashMin, idxGlo> 870 871 // edgeHash2Info = <edgeHash, < rank1, idxGlo, rank2, idxGlo>> 872 int edgeCount = 0; 852 873 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 853 874 { 854 875 vector <size_t> edgeInfo = it->second; 855 if (edgeInfo.size() == 4) // two processes generate the same edge 856 if (edgeInfo[1] > edgeInfo[3]) 857 edgeInfo[1] = edgeInfo[3]; 858 if (edgeInfo[1] == mpiRank) 859 edgeHashMin2IdxGlo[it->first].push_back(edgeInfo[0]); 860 } 861 862 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeHashMin2IdxGlo, comm); 863 edge_count = dhtEdgeIdxGlo.getIndexCount(); 864 edge_start = dhtEdgeIdxGlo.getIndexStart(); 876 if (edgeInfo[0] == mpiRank) 877 { 878 ++edgeCount; 879 } 880 } 881 882 int edgeStart, nbEdges; 883 MPI_Scan(&edgeCount, &edgeStart, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm); 884 int nEdges = edgeStart; 885 MPI_Bcast(&nEdges, 1, MPI_UNSIGNED_LONG, mpiSize-1, comm); 886 nbEdgesGlo = nEdges; 887 888 // edges to be splitted equally between procs 889 if ( (nbEdgesGlo % mpiSize) == 0) 890 { 891 edge_count = nbEdgesGlo/mpiSize; 892 edge_start = mpiRank*edge_count; 893 } 894 else 895 { 896 if (mpiRank == (mpiSize - 1) ) 897 { 898 edge_count = nbEdgesGlo/mpiSize; 899 edge_start = mpiRank*(nbEdgesGlo/mpiSize + 1); 900 } 901 else 902 { 903 edge_count = nbEdgesGlo/mpiSize + 1; 904 edge_start = mpiRank*edge_count; 905 } 906 } 907 CArray<size_t,1> edgeIdxGloList(edge_count); 908 for (int i = 0; i < edge_count; ++i) 909 { 910 edgeIdxGloList(i) = i + edge_start; 911 } 912 913 CClientClientDHTSizet dhtEdgeIdxGlo2Face (edgeIdxGlo2Face, comm); 914 CClientClientDHTSizet dhtEdge2Face (edgeIdxGlo2Face, comm); 915 dhtEdgeIdxGlo2Face.computeIndexInfoMapping(edgeIdxGloList); 916 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdgeIdxGlo2Face.getInfoIndexMap(); 917 dhtEdge2Face.computeIndexInfoMapping(edgeIdxList); 918 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdx2FaceIdx = dhtEdge2Face.getInfoIndexMap(); 919 865 920 866 921 edge_faces.resize(2, edge_count); 922 for (int i = 0; i < edge_count; ++i) 923 { 924 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeIdxGlo2FaceIdx.find(i + edge_start); 925 int indexGlo = it->first; 926 vector<size_t> faces = it->second; 927 int face1 = faces[0]; 928 edge_faces(0, indexGlo - edge_start) = face1; 929 if (faces.size() == 2) 930 { 931 int face2 = faces[1]; 932 edge_faces(1, indexGlo - edge_start) = face2; 933 } 934 else 935 { 936 edge_faces(1, indexGlo - edge_start) = -999; 937 } 938 } 939 940 size_t tmp; 941 vector<size_t> tmpVec; 942 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeIdx2FaceIdx.begin(); it != edgeIdx2FaceIdx.end(); it++) 943 { 944 tmp = it->first; 945 tmpVec = it->second; 946 tmp++; 947 } 948 949 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itFace1, itFace2, itIndex; 867 950 face_faces.resize(nvertex, nbFaces_); 868 869 CClientClientDHTSizet dhtEdge2Face (edgeIdxGlo2Face, comm);870 dhtEdge2Face.computeIndexInfoMapping(edgeIdxGloList);871 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdge2Face.getInfoIndexMap();872 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itFace1, itFace2;873 874 951 for (int nf = 0; nf < nbFaces_; ++nf) 875 952 { … … 896 973 size_t faceIdxGlo = nbFacesAccum + nf; 897 974 size_t edgeHash = hashPairOrdered(it1->second[0], it2->second[0]); 898 itEdgeHash = edgeHash2IdxGlo.find(edgeHash); 899 if (itEdgeHash != edgeHashMin2IdxGlo.end()) 975 itEdgeHash = edgeHash2Info.find(edgeHash); 976 int edgeIdxGlo = (itEdgeHash->second)[1]; 977 978 if ( (itEdgeHash->second)[0] == mpiRank) 900 979 { 901 int edgeIdxGlo = itEdgeHash->second[0]; 902 itFace1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 980 itFace1 = edgeIdx2FaceIdx.find(edgeIdxGlo); 903 981 int face1 = itFace1->second[0]; 904 982 if (itFace1->second.size() == 1) 905 983 { 906 edge_faces(0, edgeIdxGlo - edge_start) = face1;907 edge_faces(1, edgeIdxGlo - edge_start) = -999;908 984 face_faces(nv1, nf) = 999999; 909 985 } … … 911 987 { 912 988 int face2 = itFace1->second[1]; 913 edge_faces(0, edgeIdxGlo - edge_start) = face1;914 edge_faces(1, edgeIdxGlo - edge_start) = face2;915 989 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 916 990 } … … 918 992 else 919 993 { 920 itEdgeHash = edgeHashMin2IdxGlo.find(edgeHash); 921 size_t edgeIdxGlo = itEdgeHash->second[0]; 922 itFace1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 994 itFace1 = edgeIdx2FaceIdx.find(edgeIdxGlo); 923 995 int face1 = itFace1->second[0]; 924 996 int face2 = itFace1->second[1]; … … 957 1029 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it1, it2; 958 1030 CArray<size_t,1> edgeHashList(nbFaces_*nvertex); 1031 int nEdgeHash = 0; 959 1032 for (int nf = 0; nf < nbFaces_; ++nf) 960 1033 { … … 978 1051 face_nodes(nv1,nf) = it1->second[0]; 979 1052 size_t edgeHash = hashPairOrdered(it1->second[0], it2->second[0]); 980 edgeHash2Idx[edgeHash].push_back(generateEdgeIndex(it1->second[0], it2->second[0], mpiRank)); 981 edgeHash2Idx[edgeHash].push_back(mpiRank); 982 edgeHashList(nf*nvertex + nv1) = edgeHash; 983 } 984 } 985 986 // (2.2) Generating global edge indexes 987 // The ownership criterion: priority of the process holding the smaller index 1053 if (edgeHash2Idx.count(edgeHash) == 0) 1054 { 1055 edgeHash2Idx[edgeHash].push_back(edgeHash); 1056 edgeHash2Idx[edgeHash].push_back(mpiRank); 1057 edgeHashList(nEdgeHash) = edgeHash; 1058 ++nEdgeHash; 1059 } 1060 } 1061 } 1062 edgeHashList.resizeAndPreserve(nEdgeHash); 1063 1064 // (2.3) Generating global edge indexes 1065 // The ownership criterion: priority of the process with smaller rank 988 1066 // Maps generated in this step are: 989 // edgeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 990 // edgeIdx2IdxMin = = <idx, idxMin> 991 // edgeIdx2IdxGlo = <idxMin, idxGlo> 1067 // edgeIdx2Idx = = <idx, <rankOwner, idx>> 1068 // edgeIdx2IdxGlo = <idxMin, <rankOwner, idxGlo>> 992 1069 993 1070 CClientClientDHTSizet dhtEdgeHash(edgeHash2Idx, comm); 994 1071 dhtEdgeHash.computeIndexInfoMapping(edgeHashList); 995 1072 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeHash2Info = dhtEdgeHash.getInfoIndexMap(); 996 997 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxMin; 998 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxGlo; 999 CArray<size_t,1> edgeIdxMinList(nbFaces_*nvertex); 1000 size_t iIdxMin = 0; 1073 // edgeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 1074 1075 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2Idx; 1001 1076 1002 1077 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 1003 1078 { 1004 size_t idxMin = (it->second)[0];1079 size_t rankMin = (it->second)[1]; 1005 1080 size_t idx = (it->second)[0]; 1081 1006 1082 for (int i = 2; i < (it->second).size();) 1007 1083 { 1008 if (mpiRank == (it->second)[i+1]) 1009 { 1084 if ((it->second)[i+1] < rankMin) 1085 { 1086 rankMin = (it->second)[i+1]; 1010 1087 idx = (it->second)[i]; 1011 } 1012 if ((it->second)[i] < idxMin) 1013 { 1014 idxMin = (it->second)[i]; 1015 (it->second)[i] = (it->second)[i-2]; 1088 (it->second)[i+1] = (it->second)[i-1]; 1016 1089 } 1017 1090 i += 2; 1018 1091 } 1019 (it->second)[0] = idxMin; 1020 if (edgeIdx2IdxMin.count(idx) == 0) 1021 { 1022 edgeIdx2IdxMin[idx].push_back(idxMin); 1023 if (idx == idxMin) 1024 edgeIdx2IdxGlo[idxMin].push_back(idxMin); 1025 edgeIdxMinList(iIdxMin) = idxMin; 1026 ++iIdxMin; 1027 } 1028 } 1029 edgeIdxMinList.resizeAndPreserve(iIdxMin); 1030 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeIdx2IdxGlo, comm); 1031 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2IdxGlo, comm); 1032 dhtEdgeIdx.computeIndexInfoMapping(edgeIdxMinList); 1033 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxMin2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 1034 // edgeIdx2IdxGlo holds global indexes only for edges owned by a process 1035 // edgeIdxMin2IdxGlo holds global indexes for all edges generated by a process 1036 1037 // (2.3) Saving variables: edge_lon, edge_lat, face_edges 1038 nbEdgesGlo = dhtEdgeIdxGlo.getNbIndexesGlobal(); 1039 edge_count = dhtEdgeIdxGlo.getIndexCount(); 1040 edge_start = dhtEdgeIdxGlo.getIndexStart(); 1041 edge_lon.resize(edge_count); 1042 edge_lat.resize(edge_count); 1043 edge_nodes.resize(2, edge_count); 1044 face_edges.resize(nvertex, nbFaces_); 1045 1046 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 1047 CArray<size_t,1> edgeIdxGloList(nbFaces_*nvertex); 1048 size_t iIdx = 0; 1092 if (edgeIdx2Idx.count(idx) == 0) 1093 { 1094 if (mpiRank == rankMin) 1095 { 1096 edgeIdx2Idx[idx].push_back(rankMin); 1097 edgeIdx2Idx[idx].push_back(idx); 1098 } 1099 } 1100 } 1101 1102 int edgeCount = edgeIdx2Idx.size(); 1103 int edgeStart, nbEdges; 1104 MPI_Scan(&edgeCount, &edgeStart, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm); 1105 int nEdges = edgeStart; 1106 MPI_Bcast(&nEdges, 1, MPI_UNSIGNED_LONG, mpiSize-1, comm); 1107 nbEdgesGlo = nEdges; 1108 1109 edgeStart -= edgeCount; 1110 edge_start = edgeStart; 1111 edge_count = edgeCount; 1112 CClientClientDHTSizet::Index2VectorInfoTypeMap dummyEdgeMap; 1113 int count = 0; 1049 1114 1050 1115 for (int nf = 0; nf < nbFaces_; ++nf) … … 1068 1133 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 1069 1134 } 1135 size_t nodeIdxGlo1 = it1->second[0]; 1136 size_t nodeIdxGlo2 = it2->second[0]; 1137 1138 if (nodeIdxGlo1 != nodeIdxGlo2) 1139 { 1140 size_t edgeIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1141 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeIdx2Idx.find(edgeIdx); 1142 if (it != edgeIdx2Idx.end()) 1143 { 1144 if (dummyEdgeMap.count(edgeIdx) == 0) 1145 { 1146 dummyEdgeMap[edgeIdx].push_back(edgeIdx); 1147 (it->second)[1] = edge_start + count; 1148 ++count; 1149 } 1150 } 1151 } 1152 } 1153 } 1154 1155 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2Idx, comm); 1156 dhtEdgeIdx.computeIndexInfoMapping(edgeHashList); 1157 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdx2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 1158 1159 // (2.4) Saving variables: edge_lon, edge_lat, face_edges 1160 edge_lon.resize(edge_count); 1161 edge_lat.resize(edge_count); 1162 edge_nodes.resize(2, edge_count); 1163 face_edges.resize(nvertex, nbFaces_); 1164 1165 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdxGlo2Face; 1166 CArray<size_t,1> edgeIdxGloList(nbFaces_*nvertex); 1167 size_t iIdx = 0; 1168 1169 for (int nf = 0; nf < nbFaces_; ++nf) 1170 { 1171 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1172 { 1173 // Getting global indexes of edge's nodes 1174 int nh1 = 0; 1175 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1176 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1177 while (it1 == nodeHash2IdxGlo.end()) 1178 { 1179 ++nh1; 1180 it1 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh1)); 1181 } 1182 int nh2 = 0; 1183 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv2)*4 + nh2)); 1184 while (it2 == nodeHash2IdxGlo.end()) 1185 { 1186 ++nh2; 1187 it2 = nodeHash2IdxGlo.find(nodeHashList((nf*nvertex + nv1)*4 + nh2)); 1188 } 1070 1189 // Getting edge global index 1071 1190 size_t nodeIdxGlo1 = it1->second[0]; 1072 1191 size_t nodeIdxGlo2 = it2->second[0]; 1073 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank);1192 size_t myIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1074 1193 if (nodeIdxGlo1 != nodeIdxGlo2) 1075 1194 { 1076 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1077 size_t ownerIdx = (itIdx->second)[0]; 1078 int edgeIdxGlo = 0; 1195 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxGlo.find(myIdx); 1196 int edgeIdxGlo = (itIdx->second)[1]; 1079 1197 size_t faceIdxGlo = nbFacesAccum + nf; 1080 1198 1081 if (m yIdx == ownerIdx)1199 if (mpiRank == (itIdx->second)[0]) 1082 1200 { 1083 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx);1084 edgeIdxGlo = (itIdxGlo->second)[0];1085 1201 double edgeLon; 1086 1202 double diffLon = abs(bounds_lon(nv1, nf) - bounds_lon(nv2, nf)); … … 1096 1212 edge_nodes(1, edgeIdxGlo - edge_start) = nodeIdxGlo2; 1097 1213 } 1098 else1099 {1100 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx);1101 edgeIdxGlo = (itIdxGlo->second)[0];1102 }1103 1214 face_edges(nv1,nf) = edgeIdxGlo; 1104 1215 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) … … 1117 1228 edgeIdxGloList.resizeAndPreserve(iIdx); 1118 1229 1119 // (2. 4) Saving remaining variables edge_faces and face_faces1230 // (2.5) Saving remaining variables edge_faces and face_faces 1120 1231 edge_faces.resize(2, edge_count); 1121 1232 face_faces.resize(nvertex, nbFaces_); … … 1125 1236 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxGlo2FaceIdx = dhtEdge2Face.getInfoIndexMap(); 1126 1237 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdxGlo1, itNodeIdxGlo2; 1238 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx; 1127 1239 1128 1240 for (int nf = 0; nf < nbFaces_; ++nf) … … 1149 1261 size_t nodeIdxGlo2 = it2->second[0]; 1150 1262 1151 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1152 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1153 size_t ownerIdx = (itIdx->second)[0]; 1263 size_t myIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1264 itIdx = edgeIdx2IdxGlo.find(myIdx); 1154 1265 size_t faceIdxGlo = nbFacesAccum + nf; 1155 1156 if (myIdx == ownerIdx) 1157 { 1158 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx); 1159 int edgeIdxGlo = (itIdxGlo->second)[0]; 1266 int edgeIdxGlo = (itIdx->second)[1]; 1267 1268 if (mpiRank == (itIdx->second)[0]) 1269 { 1160 1270 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1161 1271 int face1 = it1->second[0]; … … 1176 1286 else 1177 1287 { 1178 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx);1179 size_t edgeIdxGlo = (itIdxGlo->second)[0];1180 1288 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1181 1289 int face1 = it1->second[0]; … … 1200 1308 { 1201 1309 hashValues = CMesh::createHashes(bounds_lon(nv, nf), bounds_lat(nv, nf)); 1202 size_t nodeIndex = generateNodeIndex(hashValues, mpiRank); 1310 // size_t nodeIndex = generateNodeIndex(hashValues, mpiRank); 1311 size_t nodeIndex = generateNodeIndex(hashValues); 1203 1312 for (int nh = 0; nh < 4; ++nh) 1204 1313 { … … 1216 1325 1217 1326 // (3.2) Generating global node indexes 1218 // The ownership criterion: priority of the process holding the smaller index 1327 // The ownership criterion: priority of the process with smaller rank. 1328 // With any other criterion it is not possible to have consistent node indexing for different number of procs. 1219 1329 // Maps generated in this step are: 1220 // nodeHash2Info = <hash, [[idxMin, rankMin], [idx1, rank1], [idx3, rank3]..]> 1221 // nodeIdx2IdxMin = = <idx, idxMin> 1222 // nodeIdx2IdxGlo = <idxMin, idxGlo> 1330 // nodeHash2Info = <hash, [[idx, rankMin], [idx, rank1], [idx, rank3]..]> 1331 // nodeIdx2Idx = <idx, <rankOwner, idx>> 1223 1332 1224 1333 CClientClientDHTSizet dhtNodeHash(nodeHash2Idx, comm); … … 1226 1335 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeHash2Info = dhtNodeHash.getInfoIndexMap(); 1227 1336 1228 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxMin; 1229 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2IdxGlo; 1230 CArray<size_t,1> nodeIdxMinList(nbFaces_*nvertex*4); 1231 size_t iIdxMin = 0; 1337 CClientClientDHTSizet::Index2VectorInfoTypeMap nodeIdx2Idx; 1338 CArray<size_t,1> nodeIdxList(nbFaces_*nvertex*4); 1339 size_t nIdx = 0; 1232 1340 1233 1341 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeHash2Info.begin(); it != nodeHash2Info.end(); ++it) 1234 1342 { 1235 size_t idxMin = (it->second)[0];1343 size_t rankMin = (it->second)[1]; 1236 1344 size_t idx = (it->second)[0]; 1237 1345 for (int i = 2; i < (it->second).size();) 1238 1346 { 1239 if ( mpiRank == (it->second)[i+1])1347 if ( (it->second)[i+1] < rankMin) 1240 1348 { 1241 1349 idx = (it->second)[i]; 1242 } 1243 if ((it->second)[i] < idxMin) 1244 { 1245 idxMin = (it->second)[i]; 1246 (it->second)[i] = (it->second)[i-2]; 1350 rankMin = (it->second)[i+1]; 1351 (it->second)[i+1] = (it->second)[i-1]; 1247 1352 } 1248 1353 i += 2; 1249 1354 } 1250 (it->second)[0] = idxMin; 1251 if (nodeIdx2IdxMin.count(idx) == 0) 1252 { 1253 nodeIdx2IdxMin[idx].push_back(idxMin); 1254 if (idx == idxMin) 1255 nodeIdx2IdxGlo[idxMin].push_back(idxMin); 1256 nodeIdxMinList(iIdxMin) = idxMin; 1257 ++iIdxMin; 1258 } 1259 } 1260 1261 nodeIdxMinList.resizeAndPreserve(iIdxMin); 1262 CDHTAutoIndexing dhtNodeIdxGlo = CDHTAutoIndexing(nodeIdx2IdxGlo, comm); 1263 CClientClientDHTSizet dhtNodeIdx(nodeIdx2IdxGlo, comm); 1264 dhtNodeIdx.computeIndexInfoMapping(nodeIdxMinList); 1265 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdxMin2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 1355 if (nodeIdx2Idx.count(idx) == 0) 1356 { 1357 if (mpiRank == rankMin) 1358 { 1359 nodeIdx2Idx[idx].push_back(rankMin); 1360 nodeIdx2Idx[idx].push_back(idx); 1361 } 1362 nodeIdxList(nIdx) = idx; 1363 ++nIdx; 1364 } 1365 } 1366 1367 // CDHTAutoIndexing dhtNodeIdxGlo = CDHTAutoIndexing(nodeIdx2Idx, comm); 1368 // CDHTAutoIndexing will not give consistent node numbering for varying number of procs. => 1369 // Solution: global node indexing by hand. 1370 // Maps modified in this step: 1371 // nodeIdx2Idx = <idx, idxGlo> 1372 int nodeCount = nodeIdx2Idx.size(); 1373 int nodeStart, nbNodes; 1374 MPI_Scan(&nodeCount, &nodeStart, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm); 1375 int nNodes = nodeStart; 1376 MPI_Bcast(&nNodes, 1, MPI_UNSIGNED_LONG, mpiSize-1, comm); 1377 nbNodesGlo = nNodes; 1378 1379 nodeStart -= nodeCount; 1380 node_start = nodeStart; 1381 node_count = nodeCount; 1382 CClientClientDHTSizet::Index2VectorInfoTypeMap dummyMap; // just a dummy map used to ensure that each node is numbered only once 1383 size_t count = 0; 1384 1385 for (int nf = 0; nf < nbFaces_; ++nf) 1386 { 1387 for (int nv = 0; nv < nvertex; ++nv) 1388 { 1389 vector<size_t> hashValues = CMesh::createHashes(bounds_lon(nv, nf), bounds_lat(nv, nf)); 1390 size_t nodeIdx = generateNodeIndex(hashValues); 1391 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = nodeIdx2Idx.find(nodeIdx); 1392 if (it != nodeIdx2Idx.end()) 1393 { 1394 if (dummyMap.count(nodeIdx) == 0) 1395 { 1396 dummyMap[nodeIdx].push_back(nodeIdx); 1397 (it->second)[1] = node_start + count; 1398 ++count; 1399 } 1400 } 1401 } 1402 } 1403 nodeIdxList.resizeAndPreserve(nIdx); 1404 CClientClientDHTSizet dhtNodeIdx(nodeIdx2Idx, comm); 1405 dhtNodeIdx.computeIndexInfoMapping(nodeIdxList); 1406 CClientClientDHTSizet::Index2VectorInfoTypeMap& nodeIdx2IdxGlo = dhtNodeIdx.getInfoIndexMap(); 1266 1407 1267 1408 // (3.3) Saving node data: node_lon, node_lat, and face_nodes 1268 1409 // Generating edgeHash2Info = <hash, <idx, rank>> and edgeHashList 1269 nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal();1270 node_count = dhtNodeIdxGlo.getIndexCount();1271 node_start = dhtNodeIdxGlo.getIndexStart();1410 // nbNodesGlo = dhtNodeIdxGlo.getNbIndexesGlobal(); 1411 // node_count = dhtNodeIdxGlo.getIndexCount(); 1412 // node_start = dhtNodeIdxGlo.getIndexStart(); 1272 1413 node_lon.resize(node_count); 1273 1414 node_lat.resize(node_count); … … 1286 1427 vector<size_t> hashValues1 = CMesh::createHashes(bounds_lon(nv1, nf), bounds_lat(nv1, nf)); 1287 1428 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1288 size_t myNodeIdx1 = generateNodeIndex(hashValues1, mpiRank);1289 size_t myNodeIdx2 = generateNodeIndex(hashValues2, mpiRank);1290 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx1 = nodeIdx2Idx Min.find(myNodeIdx1);1291 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx2 = nodeIdx2Idx Min.find(myNodeIdx2);1292 size_t owner NodeIdx= (itNodeIdx1->second)[0];1293 1294 if (myNodeIdx1 == ownerNodeIdx)1295 { 1296 itNodeIdxGlo1 = nodeIdx2IdxGlo.find(myNodeIdx1);1297 nodeIdxGlo1 = (itNodeIdxGlo1->second)[0];1429 size_t nodeIdx1 = generateNodeIndex(hashValues1); 1430 size_t nodeIdx2 = generateNodeIndex(hashValues2); 1431 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx1 = nodeIdx2IdxGlo.find(nodeIdx1); 1432 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx2 = nodeIdx2IdxGlo.find(nodeIdx2); 1433 size_t ownerRank = (itNodeIdx1->second)[0]; 1434 nodeIdxGlo1 = (itNodeIdx1->second)[1]; 1435 nodeIdxGlo2 = (itNodeIdx2->second)[1]; 1436 1437 if (mpiRank == ownerRank) 1438 { 1298 1439 node_lon(nodeIdxGlo1 - node_start) = bounds_lon(nv1, nf); 1299 1440 node_lat(nodeIdxGlo1 - node_start) = bounds_lat(nv1, nf); 1300 1441 } 1301 else1302 {1303 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find(ownerNodeIdx);1304 nodeIdxGlo1 = (itNodeIdxGlo1->second)[0];1305 }1306 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((itNodeIdx2->second)[0]);1307 nodeIdxGlo2 = (itNodeIdxGlo2->second)[0];1308 1442 if (nodeIdxGlo1 != nodeIdxGlo2) 1309 1443 { 1310 1444 size_t edgeHash = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1311 edgeHash2Idx[edgeHash].push_back( generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank));1445 edgeHash2Idx[edgeHash].push_back(edgeHash); 1312 1446 edgeHash2Idx[edgeHash].push_back(mpiRank); 1313 1447 edgeHashList(nEdgeHash) = edgeHash; … … 1321 1455 // (3.4) Generating global edge indexes 1322 1456 // Maps generated in this step are: 1323 // edgeIdx2Idx Min = = <idx, idxMin>1324 // edgeIdx2IdxGlo = <idxMin, idxGlo>1457 // edgeIdx2Idx = = <idx, <rankOwner, idx>> 1458 // edgeIdx2IdxGlo = <idxMin, <rankOwner, idxGlo>> 1325 1459 1326 1460 CClientClientDHTSizet dhtEdgeHash(edgeHash2Idx, comm); … … 1329 1463 // edgeHash2Info = <hash, [[idx1, rank1], [idx2, rank2], [idx3, rank3]..]> 1330 1464 1331 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxMin; 1332 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2IdxGlo; 1333 CArray<size_t,1> edgeIdxMinList(nbFaces_*nvertex); 1334 iIdxMin = 0; 1465 CClientClientDHTSizet::Index2VectorInfoTypeMap edgeIdx2Idx; 1335 1466 1336 1467 for (CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeHash2Info.begin(); it != edgeHash2Info.end(); ++it) 1337 1468 { 1338 size_t idxMin = (it->second)[0];1469 size_t rankMin = (it->second)[1]; 1339 1470 size_t idx = (it->second)[0]; 1340 1471 1341 1472 for (int i = 2; i < (it->second).size();) 1342 1473 { 1343 if (mpiRank == (it->second)[i+1]) 1344 { 1474 if ((it->second)[i+1] < rankMin) 1475 { 1476 rankMin = (it->second)[i+1]; 1345 1477 idx = (it->second)[i]; 1346 } 1347 if ((it->second)[i] < idxMin) 1348 { 1349 idxMin = (it->second)[i]; 1350 (it->second)[i] = (it->second)[i-2]; 1478 (it->second)[i+1] = (it->second)[i-1]; 1351 1479 } 1352 1480 i += 2; 1353 1481 } 1354 (it->second)[0] = idxMin; 1355 if (edgeIdx2IdxMin.count(idx) == 0) 1356 { 1357 edgeIdx2IdxMin[idx].push_back(idxMin); 1358 if (idx == idxMin) 1359 edgeIdx2IdxGlo[idxMin].push_back(idxMin); 1360 edgeIdxMinList(iIdxMin) = idxMin; 1361 ++iIdxMin; 1362 } 1363 } 1364 edgeIdxMinList.resizeAndPreserve(iIdxMin); 1365 CDHTAutoIndexing dhtEdgeIdxGlo = CDHTAutoIndexing(edgeIdx2IdxGlo, comm); 1366 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2IdxGlo, comm); 1367 dhtEdgeIdx.computeIndexInfoMapping(edgeIdxMinList); 1368 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdxMin2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 1482 if (edgeIdx2Idx.count(idx) == 0) 1483 { 1484 if (mpiRank == rankMin) 1485 { 1486 edgeIdx2Idx[idx].push_back(rankMin); 1487 edgeIdx2Idx[idx].push_back(idx); 1488 } 1489 } 1490 } 1491 1492 int edgeCount = edgeIdx2Idx.size(); 1493 int edgeStart, nbEdges; 1494 MPI_Scan(&edgeCount, &edgeStart, 1, MPI_UNSIGNED_LONG, MPI_SUM, comm); 1495 int nEdges = edgeStart; 1496 MPI_Bcast(&nEdges, 1, MPI_UNSIGNED_LONG, mpiSize-1, comm); 1497 nbEdgesGlo = nEdges; 1498 1499 edgeStart -= edgeCount; 1500 edge_start = edgeStart; 1501 edge_count = edgeCount; 1502 CClientClientDHTSizet::Index2VectorInfoTypeMap dummyEdgeMap; 1503 count = 0; 1504 1505 for (int nf = 0; nf < nbFaces_; ++nf) 1506 { 1507 for (int nv1 = 0; nv1 < nvertex; ++nv1) 1508 { 1509 int nv2 = (nv1 < nvertex -1 ) ? (nv1 + 1) : (nv1 + 1 - nvertex); // cyclic rotation 1510 vector<size_t> hashValues1 = CMesh::createHashes(bounds_lon(nv1, nf), bounds_lat(nv1, nf)); 1511 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1512 size_t nodeIdx1 = generateNodeIndex(hashValues1); 1513 size_t nodeIdx2 = generateNodeIndex(hashValues2); 1514 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx1 = nodeIdx2IdxGlo.find(nodeIdx1); 1515 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itNodeIdx2 = nodeIdx2IdxGlo.find(nodeIdx2); 1516 nodeIdxGlo1 = (itNodeIdx1->second)[1]; 1517 nodeIdxGlo2 = (itNodeIdx2->second)[1]; 1518 1519 if (nodeIdxGlo1 != nodeIdxGlo2) 1520 { 1521 size_t edgeIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1522 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator it = edgeIdx2Idx.find(edgeIdx); 1523 if (it != edgeIdx2Idx.end()) 1524 { 1525 if (dummyEdgeMap.count(edgeIdx) == 0) 1526 { 1527 dummyEdgeMap[edgeIdx].push_back(edgeIdx); 1528 (it->second)[1] = edge_start + count; 1529 ++count; 1530 } 1531 } 1532 } 1533 } 1534 } 1535 CClientClientDHTSizet dhtEdgeIdx(edgeIdx2Idx, comm); 1536 dhtEdgeIdx.computeIndexInfoMapping(edgeHashList); 1537 CClientClientDHTSizet::Index2VectorInfoTypeMap& edgeIdx2IdxGlo = dhtEdgeIdx.getInfoIndexMap(); 1369 1538 1370 1539 // (3.5) Saving variables: edge_lon, edge_lat, face_edges 1371 1540 // Creating map edgeIdxGlo2Face <idxGlo, face> 1372 1373 nbEdgesGlo = dhtEdgeIdxGlo.getNbIndexesGlobal();1374 edge_count = dhtEdgeIdxGlo.getIndexCount();1375 edge_start = dhtEdgeIdxGlo.getIndexStart(); 1541 // nbEdgesGlo = dhtEdgeIdxGlo.getNbIndexesGlobal(); 1542 // edge_count = dhtEdgeIdxGlo.getIndexCount(); 1543 // edge_start = dhtEdgeIdxGlo.getIndexStart(); 1544 1376 1545 edge_lon.resize(edge_count); 1377 1546 edge_lat.resize(edge_count); … … 1393 1562 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1394 1563 1395 size_t myNodeIdx1 = generateNodeIndex(hashValues1, mpiRank); 1396 size_t myNodeIdx2 = generateNodeIndex(hashValues2, mpiRank); 1397 it1 = nodeIdx2IdxMin.find(myNodeIdx1); 1398 it2 = nodeIdx2IdxMin.find(myNodeIdx2); 1399 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find((it1->second)[0]); 1400 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((it2->second)[0]); 1401 size_t nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1402 size_t nodeIdxGlo2 = (itNodeIdxGlo2->second)[0]; 1564 size_t nodeIdx1 = generateNodeIndex(hashValues1); 1565 size_t nodeIdx2 = generateNodeIndex(hashValues2); 1566 it1 = nodeIdx2IdxGlo.find(nodeIdx1); 1567 it2 = nodeIdx2IdxGlo.find(nodeIdx2); 1568 size_t nodeIdxGlo1 = (it1->second)[1]; 1569 size_t nodeIdxGlo2 = (it2->second)[1]; 1403 1570 1404 1571 if (nodeIdxGlo1 != nodeIdxGlo2) 1405 1572 { 1406 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1407 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1408 size_t ownerIdx = (itIdx->second)[0]; 1409 int edgeIdxGlo; 1573 size_t myIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1574 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxGlo.find(myIdx); 1575 int edgeIdxGlo = (itIdx->second)[1]; 1410 1576 size_t faceIdxGlo = nbFacesAccum + nf; 1411 1577 1412 if (m yIdx == ownerIdx)1578 if (mpiRank == (itIdx->second)[0]) 1413 1579 { 1414 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx);1415 edgeIdxGlo = (itIdxGlo->second)[0];1416 1580 double edgeLon; 1417 1581 double diffLon = abs(bounds_lon(nv1, nf) - bounds_lon(nv2, nf)); … … 1427 1591 edge_nodes(1, edgeIdxGlo - edge_start) = nodeIdxGlo2; 1428 1592 } 1429 else1430 {1431 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx);1432 edgeIdxGlo = (itIdxGlo->second)[0];1433 }1434 1593 face_edges(nv1,nf) = edgeIdxGlo; 1435 1594 if (edgeIdxGlo2Face.count(edgeIdxGlo) == 0) … … 1465 1624 vector<size_t> hashValues2 = CMesh::createHashes(bounds_lon(nv2, nf), bounds_lat(nv2, nf)); 1466 1625 1467 size_t myNodeIdx1 = generateNodeIndex(hashValues1 , mpiRank);1468 size_t myNodeIdx2 = generateNodeIndex(hashValues2 , mpiRank);1626 size_t myNodeIdx1 = generateNodeIndex(hashValues1); 1627 size_t myNodeIdx2 = generateNodeIndex(hashValues2); 1469 1628 if (myNodeIdx1 != myNodeIdx2) 1470 1629 { 1471 it1 = nodeIdx2IdxMin.find(myNodeIdx1); 1472 it2 = nodeIdx2IdxMin.find(myNodeIdx2); 1473 itNodeIdxGlo1 = nodeIdxMin2IdxGlo.find((it1->second)[0]); 1474 itNodeIdxGlo2 = nodeIdxMin2IdxGlo.find((it2->second)[0]); 1475 size_t nodeIdxGlo1 = (itNodeIdxGlo1->second)[0]; 1476 size_t nodeIdxGlo2 = (itNodeIdxGlo2->second)[0]; 1477 1478 size_t myIdx = generateEdgeIndex(nodeIdxGlo1, nodeIdxGlo2, mpiRank); 1479 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxMin.find(myIdx); 1480 size_t ownerIdx = (itIdx->second)[0]; 1630 it1 = nodeIdx2IdxGlo.find(myNodeIdx1); 1631 it2 = nodeIdx2IdxGlo.find(myNodeIdx2); 1632 size_t nodeIdxGlo1 = (it1->second)[1]; 1633 size_t nodeIdxGlo2 = (it2->second)[1]; 1634 size_t myIdx = hashPairOrdered(nodeIdxGlo1, nodeIdxGlo2); 1635 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdx = edgeIdx2IdxGlo.find(myIdx); 1636 int edgeIdxGlo = (itIdx->second)[1]; 1637 1481 1638 size_t faceIdxGlo = nbFacesAccum + nf; 1482 1639 1483 if (m yIdx == ownerIdx)1640 if (mpiRank == (itIdx->second)[0]) 1484 1641 { 1485 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdx2IdxGlo.find(myIdx);1486 int edgeIdxGlo = (itIdxGlo->second)[0];1487 1642 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1488 1643 int face1 = it1->second[0]; … … 1500 1655 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1501 1656 } 1502 } // myIdx == ownerIdx1657 } 1503 1658 else 1504 1659 { 1505 CClientClientDHTSizet::Index2VectorInfoTypeMap::iterator itIdxGlo = edgeIdxMin2IdxGlo.find(ownerIdx);1506 size_t edgeIdxGlo = (itIdxGlo->second)[0];1507 1660 it1 = edgeIdxGlo2FaceIdx.find(edgeIdxGlo); 1508 1661 int face1 = it1->second[0]; 1509 1662 int face2 = it1->second[1]; 1510 1663 face_faces(nv1, nf) = (faceIdxGlo == face1 ? face2 : face1); 1511 } // myIdx != ownerIdx1664 } 1512 1665 } // myNodeIdx1 != myNodeIdx2 1513 1666 else … … 1515 1668 } 1516 1669 } 1670 1517 1671 } 1518 1672 facesAreWritten = true; -
XIOS/dev/dev_olga/src/node/scalar.cpp
r1144 r1158 63 63 { 64 64 65 } 66 67 /*! 68 Compare two scalar objects. 69 They are equal if only if they have identical attributes as well as their values. 70 Moreover, they must have the same transformations. 71 \param [in] scalar Compared scalar 72 \return result of the comparison 73 */ 74 bool CScalar::isEqual(CScalar* obj) 75 { 76 vector<StdString> excludedAttr; 77 excludedAttr.push_back("scalar_ref"); 78 bool objEqual = SuperClass::isEqual(obj, excludedAttr); 79 if (!objEqual) return objEqual; 80 81 TransMapTypes thisTrans = this->getAllTransformations(); 82 TransMapTypes objTrans = obj->getAllTransformations(); 83 84 TransMapTypes::const_iterator it, itb, ite; 85 std::vector<ETranformationType> thisTransType, objTransType; 86 for (it = thisTrans.begin(); it != thisTrans.end(); ++it) 87 thisTransType.push_back(it->first); 88 for (it = objTrans.begin(); it != objTrans.end(); ++it) 89 objTransType.push_back(it->first); 90 91 if (thisTransType.size() != objTransType.size()) return false; 92 for (int idx = 0; idx < thisTransType.size(); ++idx) 93 objEqual &= (thisTransType[idx] == objTransType[idx]); 94 95 return objEqual; 65 96 } 66 97 -
XIOS/dev/dev_olga/src/node/scalar.hpp
r1144 r1158 76 76 void duplicateTransformation(CScalar*); 77 77 CTransformation<CScalar>* addTransformation(ETranformationType transType, const StdString& id=""); 78 bool isEqual(CScalar* scalar); 78 79 79 80 private: 80 81 std::set<StdString> relFiles; 82 TransMapTypes transformationMap_; 81 83 82 private:83 TransMapTypes transformationMap_;84 84 void setTransformations(const TransMapTypes&); 85 85 -
XIOS/dev/dev_olga/src/node/variable.cpp
r1071 r1158 40 40 if (!node.getContent(this->content)) 41 41 { 42 xml::THashAttributes attributes = node.getAttributes(); 43 StdString variableName = attributes["name"]; 44 45 node.goToParentElement(); 46 StdString parentName = node.getElementName(); 47 attributes = node.getAttributes(); 48 error << "The variable id = " << id << " and name = " << variableName << " does not have any content. Please define it!" << std::endl 49 << "This variable is inside another element whose attributes are :" << std::endl; 50 51 for (xml::THashAttributes::iterator it = attributes.begin(); it != attributes.end(); ++it) 52 { 53 error << it->first << "=\"" << it->second.c_str() << "\" "; 54 } 55 error << std::endl; 56 42 57 ERROR("CVariable::parse(xml::CXMLNode & node)", 43 58 << "[ variable id = " << id 44 << " ] variable is not defined ! ");59 << " ] variable is not defined !. It does not have any content. See error log for more details."); 45 60 } 46 61 content = boost::trim_copy(content) ; … … 108 123 } 109 124 } 110 111 // if (!context->hasServer)112 // {113 // CContextClient* client=context->client ;114 115 // CEventClient event(this->getType(),EVENT_ID_VARIABLE_VALUE) ;116 // if (client->isServerLeader())117 // {118 // CMessage msg ;119 // msg<<this->getId() ;120 // msg<<content ;121 // const std::list<int>& ranks = client->getRanksServerLeader();122 // for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)123 // event.push(*itRank,1,msg);124 // client->sendEvent(event) ;125 // }126 // else client->sendEvent(event) ;127 // }128 125 } 129 126 -
XIOS/dev/dev_olga/src/node/variable.hpp
r1071 r1158 9 9 #include "attribute_enum.hpp" 10 10 #include "attribute_enum_impl.hpp" 11 #include "declare_attribute.hpp" 11 12 12 13 namespace xios
Note: See TracChangeset
for help on using the changeset viewer.