Changeset 1869 for XIOS/dev/dev_ym/XIOS_COUPLING
- Timestamp:
- 04/15/20 13:23:39 (4 years ago)
- Location:
- XIOS/dev/dev_ym/XIOS_COUPLING/src
- Files:
-
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.cpp
r1637 r1869 396 396 397 397 for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i]; 398 localDataSize_=ssize ; 398 399 399 400 localDataIndex_.resize(ssize); -
XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.hpp
r1637 r1869 47 47 const std::vector<int>& getLocalMaskedDataIndexOnClient(); 48 48 49 size_t getLocalDataSize(void) { if (!isComputed_) createGlobalIndexSendToServer(); return localDataSize_ ;} 49 50 std::vector<int> getNGlob() { return nGlob_; } 50 51 std::vector<int> getDataNIndex() { return dataNIndex_; } … … 99 100 100 101 std::vector<int> localMaskedDataIndex_; 102 //!< the size of local data of the grid 103 size_t localDataSize_ ; 101 104 102 105 private: -
XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/source_filter.cpp
r1794 r1869 34 34 packet->status = CDataPacket::NO_ERROR; 35 35 36 packet->data.resize(grid-> storeIndex_client_.numElements());36 packet->data.resize(grid->getStoreIndex_client().numElements()); 37 37 38 38 if (compression) … … 85 85 << " expected " << grid->storeIndex_fromSrv_.size() << " chunks but " << data.size() << " were given."); 86 86 87 packet->data.resize(grid-> storeIndex_client_.numElements());87 packet->data.resize(grid->getStoreIndex_client().numElements()); 88 88 std::map<int, CArray<double, 1> >::const_iterator it, itEnd = data.end(); 89 89 for (it = data.begin(); it != itEnd; it++) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/spatial_transform_filter.cpp
r1794 r1869 174 174 gridTransformation->computeAll(dataAuxInputs, packet->timestamp); 175 175 } 176 packet->data.resize(gridTransformation->getGridDestination()-> storeIndex_client_.numElements());176 packet->data.resize(gridTransformation->getGridDestination()->getDataSize()); 177 177 if (0 != packet->data.numElements()) 178 178 (packet->data)(0) = defaultValue; -
XIOS/dev/dev_ym/XIOS_COUPLING/src/interface/c/icfield.cpp
r1622 r1869 100 100 { 101 101 CTimer::get("XIOS").resume() ; 102 *domain_hdl_ret = field_hdl->g rid->getDomain(domainIndex);102 *domain_hdl_ret = field_hdl->getGrid()->getDomain(domainIndex); 103 103 CTimer::get("XIOS").suspend(); 104 104 } … … 109 109 { 110 110 CTimer::get("XIOS").resume() ; 111 *axis_hdl_ret = field_hdl->g rid->getAxis(axisIndex);111 *axis_hdl_ret = field_hdl->getGrid()->getAxis(axisIndex); 112 112 CTimer::get("XIOS").suspend(); 113 113 } … … 118 118 { 119 119 CTimer::get("XIOS").resume() ; 120 *scalar_hdl_ret = field_hdl->g rid->getScalar(scalarIndex);120 *scalar_hdl_ret = field_hdl->getGrid()->getScalar(scalarIndex); 121 121 CTimer::get("XIOS").suspend(); 122 122 } -
XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_input.cpp
r1853 r1869 48 48 CContext* context = CContext::getCurrent(); 49 49 50 CGrid* grid = field->g rid;50 CGrid* grid = field->getGrid(); 51 51 52 52 if (!grid->doGridHaveDataToWrite()) … … 130 130 StdString fieldId = field->getFieldOutputName(); 131 131 132 CGrid* grid = field->g rid;132 CGrid* grid = field->getGrid(); 133 133 134 134 std::vector<CDomain*> domainP = grid->getDomains(); -
XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_output.cpp
r1853 r1869 1805 1805 1806 1806 std::vector<StdString> dims, coodinates; 1807 CGrid* grid = field->g rid;1807 CGrid* grid = field->getGrid(); 1808 1808 if (!grid->doGridHaveDataToWrite()) 1809 1809 if (SuperClass::type==MULTI_FILE) return ; … … 2346 2346 { 2347 2347 CContext* context = CContext::getCurrent(); 2348 CGrid* grid = field->g rid;2348 CGrid* grid = field->getGrid(); 2349 2349 2350 2350 if (field->getNStep()<1) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp
r1853 r1869 274 274 TRY 275 275 { 276 if (checkAttributes_done_) return ; 277 276 278 CContext* context=CContext::getCurrent(); 277 279 … … 318 320 if (!this->value.isEmpty()) 319 321 { 320 // Avoid this check at writing because it fails in case of a hole 321 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 322 { 323 StdSize true_size = value.numElements(); 324 if (this->n.getValue() != true_size) 325 ERROR("CAxis::checkAttributes(void)", 326 << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " 327 << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size 328 << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); 329 } 322 StdSize true_size = value.numElements(); 323 if (this->n.getValue() != true_size) 324 ERROR("CAxis::checkAttributes(void)", 325 << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " 326 << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size 327 << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); 330 328 this->hasValue = true; 331 329 } 332 330 333 331 this->checkBounds(); 334 335 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 336 { 337 this->checkMask(); 338 this->checkData(); 339 this->checkLabel(); 340 } 332 this->checkMask(); 333 this->checkData(); 334 this->checkLabel(); 335 336 checkAttributes_done_ = true ; 341 337 } 342 338 CATCH_DUMP_ATTR … … 522 518 Therefore, we should recheck them. 523 519 */ 520 // ym : obsolete to be removed 524 521 void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid, 525 522 CServerDistributionDescription::ServerDistributionType distType) … … 531 528 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 532 529 { 530 /* suppressed because of interface changed 533 531 if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) 534 532 computeConnectedClients(globalDim, orderPositionInGrid, distType); 535 533 else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid, CServerDistributionDescription::ROOT_DISTRIBUTION); 534 */ 536 535 } 537 536 … … 594 593 \param [in] distType distribution type of the server. For now, we only have band distribution. 595 594 */ 596 void CAxis::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 597 CServerDistributionDescription::ServerDistributionType distType) 598 TRY 599 { 595 void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid) 596 TRY 597 { 598 if (computeConnectedClients_done_.count(client)!=0) return ; 599 else computeConnectedClients_done_.insert(client) ; 600 600 601 CContext* context = CContext::getCurrent(); 601 602 set<int> listNbServer ; 603 604 for (auto client : clients) 605 { 606 int nbServer = client->serverSize; 607 int range, clientSize = client->clientSize; 608 int rank = client->clientRank; 609 610 if (listNbServer.find(nbServer)==listNbServer.end()) 611 { 612 listNbServer.insert(nbServer) ; 613 614 if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 615 { 616 nbSenders.erase(nbServer); 617 connectedServerRank_.erase(nbServer); 618 } 619 620 size_t ni = this->n.getValue(); 621 size_t ibegin = this->begin.getValue(); 622 size_t nbIndex = index.numElements(); 623 624 // First of all, we should compute the mapping of the global index and local index of the current client 625 if (globalLocalIndexMap_.empty()) 626 { 627 for (size_t idx = 0; idx < nbIndex; ++idx) 628 { 629 globalLocalIndexMap_[index(idx)] = idx; 630 } 631 } 632 633 // Calculate the compressed index if any 634 // std::set<int> writtenInd; 635 // if (isCompressible_) 636 // { 637 // for (int idx = 0; idx < data_index.numElements(); ++idx) 638 // { 639 // int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni); 640 // 641 // if (ind >= 0 && ind < ni && mask(ind)) 642 // { 643 // ind += ibegin; 644 // writtenInd.insert(ind); 645 // } 646 // } 647 // } 648 649 // Compute the global index of the current client (process) hold 650 std::vector<int> nGlobAxis(1); 651 nGlobAxis[0] = n_glo.getValue(); 652 653 size_t globalSizeIndex = 1, indexBegin, indexEnd; 654 for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; 655 indexBegin = 0; 656 if (globalSizeIndex <= clientSize) 657 { 658 indexBegin = rank%globalSizeIndex; 659 indexEnd = indexBegin; 660 } 661 else 662 { 663 for (int i = 0; i < clientSize; ++i) 664 { 665 range = globalSizeIndex / clientSize; 666 if (i < (globalSizeIndex%clientSize)) ++range; 667 if (i == client->clientRank) break; 668 indexBegin += range; 669 } 670 indexEnd = indexBegin + range - 1; 671 } 672 673 CArray<size_t,1> globalIndex(index.numElements()); 674 for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 675 globalIndex(idx) = index(idx); 676 677 // Describe the distribution of server side 678 679 CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); 680 681 std::vector<int> serverZeroIndex; 682 serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 683 684 std::list<int> serverZeroIndexLeader; 685 std::list<int> serverZeroIndexNotLeader; 686 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 687 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 688 *it = serverZeroIndex[*it]; 689 690 // Find out the connection between client and server side 691 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 692 clientServerMap->computeServerIndexMapping(globalIndex, nbServer); 693 CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer(); 694 695 indSrv_[nbServer].swap(globalIndexAxisOnServer); 696 697 if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) 698 { 699 for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; 700 serverZeroIndexLeader.clear() ; 701 } 702 703 CClientServerMapping::GlobalIndexMap::const_iterator it = indSrv_[nbServer].begin(), 704 ite = indSrv_[nbServer].end(); 705 706 for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 707 708 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 709 connectedServerRank_[nbServer].push_back(*it); 710 711 // Even if a client has no index, it must connect to at least one server and 712 // send an "empty" data to this server 713 if (connectedServerRank_[nbServer].empty()) 714 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 715 716 nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 717 718 delete clientServerMap; 719 } 602 CServerDistributionDescription::ServerDistributionType distType ; 603 int defaultDistributedPos = CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), CServerDistributionDescription::BAND_DISTRIBUTION) ; 604 605 if (orderPositionInGrid == defaultDistributedPos) distType = CServerDistributionDescription::BAND_DISTRIBUTION ; 606 else if (index.numElements() != n_glo) distType = CServerDistributionDescription::ROOT_DISTRIBUTION ; 607 else return ; 608 609 int nbServer = client->serverSize; 610 int range, clientSize = client->clientSize; 611 int rank = client->clientRank; 612 613 if (listNbServer_.count(nbServer) == 0) 614 { 615 listNbServer_.insert(nbServer) ; 616 617 if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 618 { 619 nbSenders.erase(nbServer); 620 connectedServerRank_.erase(nbServer); 621 } 622 623 size_t ni = this->n.getValue(); 624 size_t ibegin = this->begin.getValue(); 625 size_t nbIndex = index.numElements(); 626 627 // First of all, we should compute the mapping of the global index and local index of the current client 628 if (globalLocalIndexMap_.empty()) 629 { 630 for (size_t idx = 0; idx < nbIndex; ++idx) 631 { 632 globalLocalIndexMap_[index(idx)] = idx; 633 } 634 } 635 636 // Calculate the compressed index if any 637 // std::set<int> writtenInd; 638 // if (isCompressible_) 639 // { 640 // for (int idx = 0; idx < data_index.numElements(); ++idx) 641 // { 642 // int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni); 643 // 644 // if (ind >= 0 && ind < ni && mask(ind)) 645 // { 646 // ind += ibegin; 647 // writtenInd.insert(ind); 648 // } 649 // } 650 // } 651 652 // Compute the global index of the current client (process) hold 653 std::vector<int> nGlobAxis(1); 654 nGlobAxis[0] = n_glo.getValue(); 655 656 size_t globalSizeIndex = 1, indexBegin, indexEnd; 657 for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; 658 indexBegin = 0; 659 if (globalSizeIndex <= clientSize) 660 { 661 indexBegin = rank%globalSizeIndex; 662 indexEnd = indexBegin; 663 } 664 else 665 { 666 for (int i = 0; i < clientSize; ++i) 667 { 668 range = globalSizeIndex / clientSize; 669 if (i < (globalSizeIndex%clientSize)) ++range; 670 if (i == client->clientRank) break; 671 indexBegin += range; 672 } 673 indexEnd = indexBegin + range - 1; 674 } 675 676 CArray<size_t,1> globalIndex(index.numElements()); 677 for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 678 globalIndex(idx) = index(idx); 679 680 // Describe the distribution of server side 681 682 CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); 683 684 std::vector<int> serverZeroIndex; 685 serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 686 687 std::list<int> serverZeroIndexLeader; 688 std::list<int> serverZeroIndexNotLeader; 689 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 690 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 691 *it = serverZeroIndex[*it]; 692 693 // Find out the connection between client and server side 694 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 695 clientServerMap->computeServerIndexMapping(globalIndex, nbServer); 696 CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer(); 697 698 indSrv_[nbServer].swap(globalIndexAxisOnServer); 699 700 if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) 701 { 702 for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; 703 serverZeroIndexLeader.clear() ; 704 } 705 706 CClientServerMapping::GlobalIndexMap::const_iterator it = indSrv_[nbServer].begin(), 707 ite = indSrv_[nbServer].end(); 708 709 for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 710 711 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 712 connectedServerRank_[nbServer].push_back(*it); 713 714 // Even if a client has no index, it must connect to at least one server and 715 // send an "empty" data to this server 716 if (connectedServerRank_[nbServer].empty()) 717 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 718 719 nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 720 721 delete clientServerMap; 720 722 } 721 723 } … … 1431 1433 CATCH_DUMP_ATTR 1432 1434 1435 /*! 1436 \brief Check if a axis is completed 1437 Before make any axis processing, we must be sure that all axis informations have 1438 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 1439 other context (coupling). So all direct reference of the axis (axis_ref) must be also completed 1440 \return true if axis and axis reference are completed 1441 */ 1442 bool CAxis::checkIfCompleted(void) 1443 { 1444 if (hasDirectAxisReference()) if (!getDirectAxisReference()->checkIfCompleted()) return false; 1445 return isCompleted_ ; 1446 } 1447 1448 /*! 1449 \brief Set a axis as completed 1450 When all information about a axis have been received, the axis is tagged as completed and is 1451 suitable for processing 1452 */ 1453 void CAxis::setCompleted(void) 1454 { 1455 if (hasDirectAxisReference()) getDirectAxisReference()->setCompleted() ; 1456 isCompleted_=true ; 1457 } 1458 1459 /*! 1460 \brief Set a axis as uncompleted 1461 When informations about a axis are expected from a grid reading from file or coupling, the axis is 1462 tagged as uncompleted and is not suitable for processing 1463 */ 1464 void CAxis::setUncompleted(void) 1465 { 1466 if (hasDirectAxisReference()) getDirectAxisReference()->setUncompleted() ; 1467 isCompleted_=false ; 1468 } 1469 1470 1471 1433 1472 /*! 1434 1473 * Go through the hierarchy to find the axis from which the transformations must be inherited -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp
r1847 r1869 86 86 void addRelFileCompressed(const StdString& filename); 87 87 88 /// Vérifications /// 89 void checkAttributes(void); 88 90 89 91 90 /// Destructeur /// … … 102 101 103 102 static bool dispatchEvent(CEventServer& event); 103 104 /// Vérifications /// 105 void checkAttributes(void); 106 bool checkAttributes_done_ = false ; 104 107 105 108 void checkAttributesOnClient(); … … 121 124 bool isEqual(CAxis* axis); 122 125 126 bool checkIfCompleted(void) ; 127 void setCompleted(void) ; 128 void setUncompleted(void) ; 129 123 130 public: 124 131 bool hasValue; … … 127 134 128 135 CArray<int,1> localIndexToWriteOnServer; 136 137 void computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid); 138 private: std::set<CContextClient*> computeConnectedClients_done_ ; public : 139 /** The number of server of a context client. Avoid to re-compute indice computed in a previous computeConnectedClient */ 140 private: std::set<int> listNbServer_ ; public: 129 141 130 142 private: … … 137 149 void sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid, 138 150 CServerDistributionDescription::ServerDistributionType distType); 139 void computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 140 CServerDistributionDescription::ServerDistributionType distType); 151 141 152 142 153 void sendNonDistributedAttributes(void); … … 157 168 std::list<CContextClient*> clients; 158 169 std::set<CContextClient*> clientsSet; 170 171 /** define if the axis is completed or not ie all attributes have been received before in case 172 of grid reading from file or coupling */ 173 bool isCompleted_=true ; 159 174 160 175 bool isChecked; … … 165 180 //! True if and only if the data defined on the axis can be outputted in a compressed way 166 181 bool isCompressible_; 182 167 183 std::map<int, map<int,int> > nbSenders; // Mapping of number of communicating client to a server 168 184 std::map<int, std::unordered_map<int, vector<size_t> > > indSrv_; // Global index of each client sent to server -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp
r1853 r1869 730 730 731 731 // Distribute files between secondary servers according to the data size 732 distributeFiles( );732 distributeFiles(this->enabledWriteModeFiles); 733 733 734 734 // Check grid and calculate its distribution … … 852 852 and the active fields (fields will be written onto active files) 853 853 */ 854 855 void CContext::closeDefinition(void) 854 void CContext::closeDefinition(void) 856 855 TRY 857 856 { 858 857 CTimer::get("Context : close definition").resume() ; 858 859 // create intercommunicator with servers. 860 // not sure it is the good place to be called here 861 createServerInterComm() ; 862 863 864 // After xml is parsed, there are some more works with post processing 865 // postProcessing(); 866 867 // Make sure the calendar was correctly created 868 if (!calendar) 869 ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"") 870 else if (calendar->getTimeStep() == NoneDu) 871 ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"") 872 // Calendar first update to set the current date equals to the start date 873 calendar->update(0); 874 875 // Résolution des héritages descendants (cà d des héritages de groupes) 876 // pour chacun des contextes. 877 solveDescInheritance(true); 878 879 // Solve inheritance for field to know if enabled or not. 880 for (auto field : CField::getAll()) field->solveRefInheritance(); 881 882 // Check if some axis, domains or grids are eligible to for compressed indexed output. 883 // Warning: This must be done after solving the inheritance and before the rest of post-processing 884 // --> later ???? checkAxisDomainsGridsEligibilityForCompressedOutput(); 885 886 // Check if some automatic time series should be generated 887 // Warning: This must be done after solving the inheritance and before the rest of post-processing 888 889 // The timeseries should only be prepared in client 890 prepareTimeseries(); 891 892 //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. 893 findEnabledFiles(); 894 findEnabledWriteModeFiles(); 895 findEnabledReadModeFiles(); 896 findEnabledCouplerIn(); 897 findEnabledCouplerOut(); 898 createCouplerInterCommunicator() ; 899 900 // Find all enabled fields of each file 901 const vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles); 902 const vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles); 903 const vector<CField*>&& CouplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut); 904 const vector<CField*>&& CouplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn); 905 findFieldsWithReadAccess(); 906 const vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ; 907 908 // find all field potentially at workflow end 909 vector<CField*> endWorkflowFields ; 910 endWorkflowFields.reserve(fileOutField.size()+CouplerOutField.size()+fieldWithReadAccess.size()) ; 911 endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ; 912 endWorkflowFields.insert(endWorkflowFields.end(),CouplerOutField.begin(), CouplerOutField.end()) ; 913 endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ; 914 915 for(auto endWorkflowField : endWorkflowFields) endWorkflowField->buildWorkflowGraph(garbageCollector) ; 859 916 860 // 861 postProcessingGlobalAttributes(); 917 // Distribute files between secondary servers according to the data size => assign a context to a file 918 if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles); 919 else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ; 920 921 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 922 { 923 for(auto field : fileOutField) 924 { 925 field->connectToFileServer(garbageCollector) ; // connect the field to server filter 926 field->computeGridIndexToFileServer() ; // compute grid index for transfer to the server context 927 } 928 } 929 930 931 932 933 934 // For now, only read files with client and only one level server 935 // if (hasClient && !hasServer) findEnabledReadModeFiles(); 936 937 // Find all enabled fields of each file 938 findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 939 findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 940 941 // For now, only read files with client and only one level server 942 // if (hasClient && !hasServer) 943 // findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 944 945 if (serviceType_==CServicesManager::CLIENT) 946 { 947 initReadFiles(); 948 // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis) 949 this->readAttributesOfEnabledFieldsInReadModeFiles(); 950 } 951 952 // Only search and rebuild all reference objects of enable fields, don't transform 953 this->solveOnlyRefOfEnabledFields(); 954 955 // Search and rebuild all reference object of enabled fields, and transform 956 this->solveAllRefOfEnabledFieldsAndTransform(); 957 958 // Find all fields with read access from the public API 959 if (serviceType_==CServicesManager::CLIENT) findFieldsWithReadAccess(); 960 // and solve the all reference for them 961 if (serviceType_==CServicesManager::CLIENT) solveAllRefOfFieldsWithReadAccess(); 962 963 isPostProcessed = true; 964 965 966 967 // Distribute files between secondary servers according to the data size 968 distributeFiles(this->enabledWriteModeFiles); 969 970 // Check grid and calculate its distribution 971 checkGridEnabledFields(); 972 973 setClientServerBuffer(client, (serviceType_==CServicesManager::CLIENT) ) ; 974 for (int i = 0; i < clientPrimServer.size(); ++i) 975 setClientServerBuffer(clientPrimServer[i], true); 976 977 978 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 979 { 980 if (serviceType_==CServicesManager::GATHERER) 981 { 982 for (auto it=clientPrimServer.begin(); it!=clientPrimServer.end();++it) 983 { 984 this->sendAllAttributesToServer(*it); // Send all attributes of current context to server 985 CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(*it); // Send all attributes of current calendar 986 } 987 } 988 else 989 { 990 this->sendAllAttributesToServer(client); // Send all attributes of current context to server 991 CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current calendar 992 } 993 994 // We have enough information to send to server 995 // First of all, send all enabled files 996 sendEnabledFiles(this->enabledWriteModeFiles); 997 // We only use server-level 1 (for now) to read data 998 if (serviceType_==CServicesManager::CLIENT) sendEnabledFiles(this->enabledReadModeFiles); 999 1000 // Then, send all enabled fields 1001 sendEnabledFieldsInFiles(this->enabledWriteModeFiles); 1002 1003 if (serviceType_==CServicesManager::CLIENT) sendEnabledFieldsInFiles(this->enabledReadModeFiles); 1004 1005 // Then, check whether we have domain_ref, axis_ref or scalar_ref attached to the enabled fields 1006 // If any, so send them to server 1007 sendRefDomainsAxisScalars(this->enabledWriteModeFiles); 1008 1009 if (serviceType_==CServicesManager::CLIENT) sendRefDomainsAxisScalars(this->enabledReadModeFiles); 1010 1011 // Check whether enabled fields have grid_ref, if any, send this info to server 1012 sendRefGrid(this->enabledFiles); 1013 // This code may be useful in the future when we want to seperate completely read and write 1014 // sendRefGrid(this->enabledWriteModeFiles); 1015 // if (!hasServer) 1016 // sendRefGrid(this->enabledReadModeFiles); 1017 1018 // A grid of enabled fields composed of several components which must be checked then their 1019 // checked attributes should be sent to server 1020 sendGridComponentEnabledFieldsInFiles(this->enabledFiles); // This code can be seperated in two (one for reading, another for writing) 1021 1022 // We have a xml tree on the server side and now, it should be also processed 1023 sendPostProcessing(); 1024 1025 // Finally, we send information of grid itself to server 1026 sendGridEnabledFieldsInFiles(this->enabledWriteModeFiles); 1027 1028 if (serviceType_==CServicesManager::CLIENT) sendGridEnabledFieldsInFiles(this->enabledReadModeFiles); 1029 } 1030 allProcessed = true; 1031 862 1032 863 1033 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendPostProcessingGlobalAttributes(); … … 884 1054 885 1055 CTimer::get("Context : close definition").suspend() ; 886 } 887 CATCH_DUMP_ATTR 888 889 void CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) 890 TRY 891 { 1056 } 1057 CATCH_DUMP_ATTR 1058 1059 1060 void CContext::closeDefinition_old(void) 1061 TRY 1062 { 1063 CTimer::get("Context : close definition").resume() ; 1064 1065 // 1066 postProcessingGlobalAttributes(); 1067 1068 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendPostProcessingGlobalAttributes(); 1069 1070 // There are some processings that should be done after all of above. For example: check mask or index 1071 this->buildFilterGraphOfEnabledFields(); 1072 1073 if (serviceType_==CServicesManager::CLIENT) 1074 { 1075 buildFilterGraphOfFieldsWithReadAccess(); 1076 postProcessFilterGraph(); // For coupling in, modify this later 1077 } 1078 1079 checkGridEnabledFields(); 1080 1081 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) this->sendProcessingGridOfEnabledFields(); 1082 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) this->sendCloseDefinition(); 1083 1084 // Nettoyage de l'arborescence 1085 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) CleanTree(); // Only on client side?? 1086 1087 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendCreateFileHeader(); 1088 if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles(); 1089 1090 CTimer::get("Context : close definition").suspend() ; 1091 } 1092 CATCH_DUMP_ATTR 1093 1094 vector<CField*> CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) 1095 TRY 1096 { 1097 vector<CField*> fields ; 892 1098 for (unsigned int i = 0; i < activeFiles.size(); i++) 893 (void)activeFiles[i]->getEnabledFields(); 894 } 895 CATCH_DUMP_ATTR 1099 { 1100 const vector<CField*>&& field=activeFiles[i]->getEnabledFields() ; 1101 fields.insert(fields.end(),field.begin(),field.end()); 1102 } 1103 return fields ; 1104 } 1105 CATCH_DUMP_ATTR 1106 1107 vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles) 1108 TRY 1109 { 1110 vector<CField*> fields ; 1111 for(auto file : activeFiles) 1112 { 1113 const vector<CField*>&& fieldList=file->getEnabledFields() ; 1114 for(auto field : fieldList) field->setFileOut(file) ; 1115 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1116 } 1117 return fields ; 1118 } 1119 CATCH_DUMP_ATTR 1120 1121 vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles) 1122 TRY 1123 { 1124 vector<CField*> fields ; 1125 for(auto file : activeFiles) 1126 { 1127 const vector<CField*>&& fieldList=file->getEnabledFields() ; 1128 for(auto field : fieldList) field->setFileIn(file) ; 1129 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1130 } 1131 return fields ; 1132 } 1133 CATCH_DUMP_ATTR 1134 1135 vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut) 1136 TRY 1137 { 1138 vector<CField*> fields ; 1139 for (auto couplerOut :activeCouplerOut) 1140 { 1141 const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ; 1142 for(auto field : fieldList) field->setCouplerOut(couplerOut) ; 1143 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1144 } 1145 return fields ; 1146 } 1147 CATCH_DUMP_ATTR 1148 1149 vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn) 1150 TRY 1151 { 1152 vector<CField*> fields ; 1153 for (auto couplerIn :activeCouplerIn) 1154 { 1155 const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ; 1156 for(auto field : fieldList) field->setCouplerIn(couplerIn) ; 1157 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1158 } 1159 return fields ; 1160 } 1161 CATCH_DUMP_ATTR 1162 1163 896 1164 897 1165 void CContext::readAttributesOfEnabledFieldsInReadModeFiles() … … 1081 1349 TRY 1082 1350 { 1083 fieldsWithReadAccess .clear();1351 fieldsWithReadAccess_.clear(); 1084 1352 const vector<CField*> allFields = CField::getAll(); 1085 1353 for (size_t i = 0; i < allFields.size(); ++i) 1086 1354 { 1087 1355 CField* field = allFields[i]; 1088 1089 if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)1090 field ->read_access = true;1091 else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))1092 fieldsWithReadAccess.push_back(field);1356 if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled)) 1357 { 1358 fieldsWithReadAccess_.push_back(field); 1359 field->setModelOut() ; 1360 } 1093 1361 } 1094 1362 } … … 1098 1366 TRY 1099 1367 { 1100 for (size_t i = 0; i < fieldsWithReadAccess .size(); ++i)1101 fieldsWithReadAccess [i]->solveAllReferenceEnabledField(false);1368 for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i) 1369 fieldsWithReadAccess_[i]->solveAllReferenceEnabledField(false); 1102 1370 } 1103 1371 CATCH_DUMP_ATTR … … 1106 1374 TRY 1107 1375 { 1108 for (size_t i = 0; i < fieldsWithReadAccess .size(); ++i)1109 fieldsWithReadAccess [i]->buildFilterGraph(garbageCollector, true);1376 for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i) 1377 fieldsWithReadAccess_[i]->buildFilterGraph(garbageCollector, true); 1110 1378 } 1111 1379 CATCH_DUMP_ATTR … … 1139 1407 unsigned int i = 0; 1140 1408 for (i = 0; i < vecSize; ++i) 1141 allGrids[i]->solve DomainAxisRefInheritance(apply);1409 allGrids[i]->solveElementsRefInheritance(apply); 1142 1410 1143 1411 } … … 1227 1495 1228 1496 1229 void CContext::distributeFiles( void)1497 void CContext::distributeFiles(const vector<CFile*>& files) 1230 1498 TRY 1231 1499 { … … 1233 1501 distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory); 1234 1502 1235 if (distFileMemory) distributeFileOverMemoryBandwith( ) ;1236 else distributeFileOverBandwith( ) ;1237 } 1238 CATCH_DUMP_ATTR 1239 1240 void CContext::distributeFileOverBandwith( void)1503 if (distFileMemory) distributeFileOverMemoryBandwith(files) ; 1504 else distributeFileOverBandwith(files) ; 1505 } 1506 CATCH_DUMP_ATTR 1507 1508 void CContext::distributeFileOverBandwith(const vector<CFile*>& files) 1241 1509 TRY 1242 1510 { 1243 1511 double eps=std::numeric_limits<double>::epsilon()*10 ; 1244 1512 1245 if (serviceType_==CServicesManager::GATHERER) 1246 { 1247 std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 1248 int nbPools = clientPrimServer.size(); 1249 1250 // (1) Find all enabled files in write mode 1251 // for (int i = 0; i < this->enabledFiles.size(); ++i) 1252 // { 1253 // if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 1254 // enabledWriteModeFiles.push_back(enabledFiles[i]); 1255 // } 1256 1257 // (2) Estimate the data volume for each file 1258 int size = this->enabledWriteModeFiles.size(); 1259 std::vector<std::pair<double, CFile*> > dataSizeMap; 1260 double dataPerPool = 0; 1261 int nfield=0 ; 1262 ofs<<size<<endl ; 1263 for (size_t i = 0; i < size; ++i) 1513 std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 1514 int nbPools = clientPrimServer.size(); 1515 1516 // (1) Find all enabled files in write mode 1517 // for (int i = 0; i < this->enabledFiles.size(); ++i) 1518 // { 1519 // if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 1520 // enabledWriteModeFiles.push_back(enabledFiles[i]); 1521 // } 1522 1523 // (2) Estimate the data volume for each file 1524 int size = files.size(); 1525 std::vector<std::pair<double, CFile*> > dataSizeMap; 1526 double dataPerPool = 0; 1527 int nfield=0 ; 1528 ofs<<size<<endl ; 1529 for (size_t i = 0; i < size; ++i) 1530 { 1531 CFile* file = files[i]; 1532 ofs<<file->getId()<<endl ; 1533 StdSize dataSize=0; 1534 std::vector<CField*> enabledFields = file->getEnabledFields(); 1535 size_t numEnabledFields = enabledFields.size(); 1536 ofs<<numEnabledFields<<endl ; 1537 for (size_t j = 0; j < numEnabledFields; ++j) 1264 1538 { 1265 CFile* file = this->enabledWriteModeFiles[i]; 1266 ofs<<file->getId()<<endl ; 1267 StdSize dataSize=0; 1268 std::vector<CField*> enabledFields = file->getEnabledFields(); 1269 size_t numEnabledFields = enabledFields.size(); 1270 ofs<<numEnabledFields<<endl ; 1271 for (size_t j = 0; j < numEnabledFields; ++j) 1539 dataSize += enabledFields[j]->getGlobalWrittenSize() ; 1540 ofs<<enabledFields[j]->getGrid()->getId()<<endl ; 1541 ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 1542 } 1543 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1544 double dataSizeSec= dataSize/ outFreqSec; 1545 ofs<<dataSizeSec<<endl ; 1546 nfield++ ; 1547 // add epsilon*nField to dataSizeSec in order to preserve reproductive ordering when sorting 1548 dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 1549 dataPerPool += dataSizeSec; 1550 } 1551 dataPerPool /= nbPools; 1552 std::sort(dataSizeMap.begin(), dataSizeMap.end()); 1553 1554 // (3) Assign contextClient to each enabled file 1555 1556 std::multimap<double,int> poolDataSize ; 1557 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 1558 1559 int j; 1560 double dataSize ; 1561 for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 1562 1563 for (int i = dataSizeMap.size()-1; i >= 0; --i) 1564 { 1565 dataSize=(*poolDataSize.begin()).first ; 1566 j=(*poolDataSize.begin()).second ; 1567 dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 1568 dataSize+=dataSizeMap[i].first; 1569 poolDataSize.erase(poolDataSize.begin()) ; 1570 poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 1571 } 1572 1573 for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" : ratio "<<it->first*1./dataPerPool<<endl ; 1574 } 1575 CATCH_DUMP_ATTR 1576 1577 void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList) 1578 TRY 1579 { 1580 int nbPools = clientPrimServer.size(); 1581 double ratio=0.5 ; 1582 ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 1583 1584 int nFiles = filesList.size(); 1585 vector<SDistFile> files(nFiles); 1586 vector<SDistGrid> grids; 1587 map<string,int> gridMap ; 1588 string gridId; 1589 int gridIndex=0 ; 1590 1591 for (size_t i = 0; i < nFiles; ++i) 1592 { 1593 StdSize dataSize=0; 1594 CFile* file = filesList[i]; 1595 std::vector<CField*> enabledFields = file->getEnabledFields(); 1596 size_t numEnabledFields = enabledFields.size(); 1597 1598 files[i].id_=file->getId() ; 1599 files[i].nbGrids_=numEnabledFields; 1600 files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 1601 1602 for (size_t j = 0; j < numEnabledFields; ++j) 1603 { 1604 gridId=enabledFields[j]->getGrid()->getId() ; 1605 if (gridMap.find(gridId)==gridMap.end()) 1272 1606 { 1273 dataSize += enabledFields[j]->getGlobalWrittenSize() ; 1274 ofs<<enabledFields[j]->grid->getId()<<endl ; 1275 ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 1607 gridMap[gridId]=gridIndex ; 1608 SDistGrid newGrid; 1609 grids.push_back(newGrid) ; 1610 gridIndex++ ; 1276 1611 } 1277 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1278 double dataSizeSec= dataSize/ outFreqSec; 1279 ofs<<dataSizeSec<<endl ; 1280 nfield++ ; 1281 // add epsilon*nField to dataSizeSec in order to preserve reproductive ordering when sorting 1282 dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 1283 dataPerPool += dataSizeSec; 1612 files[i].assignedGrid_[j]=gridMap[gridId] ; 1613 grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 1614 dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 1284 1615 } 1285 dataPerPool /= nbPools; 1286 std::sort(dataSizeMap.begin(), dataSizeMap.end()); 1287 1288 // (3) Assign contextClient to each enabled file 1289 1290 std::multimap<double,int> poolDataSize ; 1291 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 1292 1293 int j; 1294 double dataSize ; 1295 for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 1296 1297 for (int i = dataSizeMap.size()-1; i >= 0; --i) 1616 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1617 files[i].bandwith_= dataSize/ outFreqSec ; 1618 } 1619 1620 double bandwith=0 ; 1621 double memory=0 ; 1622 1623 for(int i=0; i<nFiles; i++) bandwith+=files[i].bandwith_ ; 1624 for(int i=0; i<nFiles; i++) files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 1625 1626 for(int i=0; i<grids.size(); i++) memory+=grids[i].size_ ; 1627 for(int i=0; i<grids.size(); i++) grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 1628 1629 distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 1630 1631 vector<double> memorySize(nbPools,0.) ; 1632 vector< set<int> > serverGrids(nbPools) ; 1633 vector<double> bandwithSize(nbPools,0.) ; 1634 1635 for (size_t i = 0; i < nFiles; ++i) 1636 { 1637 bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 1638 for(int j=0 ; j<files[i].nbGrids_;j++) 1298 1639 { 1299 dataSize=(*poolDataSize.begin()).first ; 1300 j=(*poolDataSize.begin()).second ; 1301 dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 1302 dataSize+=dataSizeMap[i].first; 1303 poolDataSize.erase(poolDataSize.begin()) ; 1304 poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 1640 if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 1641 { 1642 memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 1643 serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 1644 } 1305 1645 } 1306 1307 for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" : ratio "<<it->first*1./dataPerPool<<endl ; 1308 1309 for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 1310 { 1311 enabledReadModeFiles[i]->setContextClient(client); 1312 } 1313 } 1314 else 1315 { 1316 for (int i = 0; i < this->enabledFiles.size(); ++i) 1317 enabledFiles[i]->setContextClient(client); 1318 } 1319 } 1320 CATCH_DUMP_ATTR 1321 1322 void CContext::distributeFileOverMemoryBandwith(void) 1323 TRY 1324 { 1325 if (serviceType_==CServicesManager::GATHERER) 1326 { 1327 int nbPools = clientPrimServer.size(); 1328 double ratio=0.5 ; 1329 ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 1330 1331 int nFiles = this->enabledWriteModeFiles.size(); 1332 vector<SDistFile> files(nFiles); 1333 vector<SDistGrid> grids; 1334 map<string,int> gridMap ; 1335 string gridId; 1336 int gridIndex=0 ; 1337 1338 for (size_t i = 0; i < nFiles; ++i) 1339 { 1340 StdSize dataSize=0; 1341 CFile* file = this->enabledWriteModeFiles[i]; 1342 std::vector<CField*> enabledFields = file->getEnabledFields(); 1343 size_t numEnabledFields = enabledFields.size(); 1344 1345 files[i].id_=file->getId() ; 1346 files[i].nbGrids_=numEnabledFields; 1347 files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 1348 1349 for (size_t j = 0; j < numEnabledFields; ++j) 1350 { 1351 gridId=enabledFields[j]->grid->getId() ; 1352 if (gridMap.find(gridId)==gridMap.end()) 1353 { 1354 gridMap[gridId]=gridIndex ; 1355 SDistGrid newGrid; 1356 grids.push_back(newGrid) ; 1357 gridIndex++ ; 1358 } 1359 files[i].assignedGrid_[j]=gridMap[gridId] ; 1360 grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 1361 dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 1362 } 1363 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1364 files[i].bandwith_= dataSize/ outFreqSec ; 1365 } 1366 1367 double bandwith=0 ; 1368 double memory=0 ; 1369 1370 for(int i=0; i<nFiles; i++) bandwith+=files[i].bandwith_ ; 1371 for(int i=0; i<nFiles; i++) files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 1372 1373 for(int i=0; i<grids.size(); i++) memory+=grids[i].size_ ; 1374 for(int i=0; i<grids.size(); i++) grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 1375 1376 distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 1377 1378 vector<double> memorySize(nbPools,0.) ; 1379 vector< set<int> > serverGrids(nbPools) ; 1380 vector<double> bandwithSize(nbPools,0.) ; 1381 1382 for (size_t i = 0; i < nFiles; ++i) 1383 { 1384 bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 1385 for(int j=0 ; j<files[i].nbGrids_;j++) 1386 { 1387 if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 1388 { 1389 memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 1390 serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 1391 } 1392 } 1393 enabledWriteModeFiles[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 1394 delete [] files[i].assignedGrid_ ; 1395 } 1396 1397 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ; 1398 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 1399 1400 1401 for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 1402 { 1403 enabledReadModeFiles[i]->setContextClient(client); 1404 } 1405 1406 } 1407 else 1408 { 1409 for (int i = 0; i < this->enabledFiles.size(); ++i) 1410 enabledFiles[i]->setContextClient(client); 1411 } 1412 } 1646 filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 1647 delete [] files[i].assignedGrid_ ; 1648 } 1649 1650 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ; 1651 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 1652 1653 } 1413 1654 CATCH_DUMP_ATTR 1414 1655 … … 1759 2000 // Check if some axis, domains or grids are eligible to for compressed indexed output. 1760 2001 // Warning: This must be done after solving the inheritance and before the rest of post-processing 1761 checkAxisDomainsGridsEligibilityForCompressedOutput(); 2002 checkAxisDomainsGridsEligibilityForCompressedOutput(); // only for field written on IO_SERVER service ???? 1762 2003 1763 2004 // Check if some automatic time series should be generated 1764 2005 // Warning: This must be done after solving the inheritance and before the rest of post-processing 1765 1766 // The timeseries should only be prepared in client 1767 1768 if (serviceType_==CServicesManager::CLIENT) prepareTimeseries(); 2006 prepareTimeseries(); 1769 2007 1770 2008 //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. … … 1774 2012 findEnabledCouplerIn(); 1775 2013 findEnabledCouplerOut(); 1776 1777 2014 createCouplerInterCommunicator() ; 2015 2016 // Find all enabled fields of each file 2017 const vector<CField*>&& fileOutField = findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 2018 const vector<CField*>&& fileInField = findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 2019 const vector<CField*>&& CouplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut); 2020 const vector<CField*>&& CouplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn); 2021 2022 1778 2023 1779 2024 // For now, only read files with client and only one level server 1780 2025 // if (hasClient && !hasServer) findEnabledReadModeFiles(); 1781 2026 1782 // Find all enabled fields of each file1783 findAllEnabledFieldsInFiles(this->enabledWriteModeFiles);1784 findAllEnabledFieldsInFiles(this->enabledReadModeFiles);1785 2027 1786 2028 // For now, only read files with client and only one level server … … 1974 2216 TRY 1975 2217 { 1976 if (!(serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)) return;1977 1978 2218 const std::vector<CFile*> allFiles = CFile::getAll(); 1979 2219 for (size_t i = 0; i < allFiles.size(); i++) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.hpp
r1848 r1869 114 114 115 115 void closeDefinition(void); 116 116 void closeDefinition_old(void); 117 118 // to be removed 119 std::vector<CField*> findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 117 120 // Some functions to process context 118 void findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 121 std::vector<CField*> findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles); 122 std::vector<CField*> findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles); 123 std::vector<CField*> findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut); 124 std::vector<CField*> findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn); 119 125 // void findAllEnabledFields(void); 120 126 // void findAllEnabledFieldsInReadModeFiles(void); … … 156 162 157 163 // Distribute files (in write mode) among secondary-server pools according to the estimated data flux 158 void distributeFiles( void);159 void distributeFileOverBandwith( ) ;160 void distributeFileOverMemoryBandwith( ) ;164 void distributeFiles(const std::vector<CFile*>& files); 165 void distributeFileOverBandwith(const std::vector<CFile*>& files) ; 166 void distributeFileOverMemoryBandwith(const std::vector<CFile*>& files) ; 161 167 162 168 // Send context close definition … … 244 250 bool setProcessingEvent(void) {isProcessingEvent_=true ;} 245 251 bool unsetProcessingEvent(void) {isProcessingEvent_=false ;} 246 MPI_Comm getIntraComm(void) { return intraComm_ ;} 252 MPI_Comm getIntraComm(void) {return intraComm_ ;} 253 int getIntraCommRank(void) {return intraCommRank_;} 254 int getIntraCommSize(void) {return intraCommSize_;} 247 255 248 256 void addCouplingChanel(const std::string& contextId, bool out) ; … … 265 273 // List of all enabled fields whose instant data is accessible from the public API 266 274 // but which are not part of a file 267 std::vector<CField*> fieldsWithReadAccess ;275 std::vector<CField*> fieldsWithReadAccess_; 268 276 269 277 // Context root -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp
r1853 r1869 1721 1721 CATCH_DUMP_ATTR 1722 1722 1723 void CDomain::checkAttributesOnClientAfterTransformation() 1724 TRY 1725 { 1726 CContext* context=CContext::getCurrent() ; 1727 1728 if (this->isClientAfterTransformationChecked) return; 1729 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 1730 { 1731 this->computeConnectedClients(); 1732 if (hasLonLat) 1733 if (context->getServiceType()==CServicesManager::CLIENT) 1734 this->completeLonLatClient(); 1735 } 1736 1737 this->isClientAfterTransformationChecked = true; 1723 void CDomain::checkAttributes(void) 1724 TRY 1725 { 1726 if (this->checkAttributes_done_) return; 1727 this->checkDomain(); 1728 this->checkLonLat(); 1729 this->checkBounds(); 1730 this->checkArea(); 1731 this->checkMask(); 1732 this->checkDomainData(); 1733 this->checkCompression(); 1734 this->computeLocalMask() ; 1735 this->completeLonLatClient(); 1736 this->checkAttributes_done_ = true; 1738 1737 } 1739 1738 CATCH_DUMP_ATTR … … 1770 1769 } 1771 1770 CATCH_DUMP_ATTR 1772 1773 // Send all checked attributes to server 1771 1772 // ym obselete, to be removed 1773 void CDomain::checkAttributesOnClientAfterTransformation() 1774 TRY 1775 { 1776 CContext* context=CContext::getCurrent() ; 1777 1778 if (this->isClientAfterTransformationChecked) return; 1779 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 1780 { 1781 // this->computeConnectedClients(); 1782 if (hasLonLat) 1783 if (context->getServiceType()==CServicesManager::CLIENT) 1784 this->completeLonLatClient(); 1785 } 1786 1787 this->isClientAfterTransformationChecked = true; 1788 } 1789 CATCH_DUMP_ATTR 1790 1791 // Send all checked attributes to server 1774 1792 void CDomain::sendCheckedAttributes() 1775 1793 TRY … … 1788 1806 CATCH_DUMP_ATTR 1789 1807 1808 /* old version 1790 1809 void CDomain::checkAttributes(void) 1791 1810 TRY … … 1820 1839 } 1821 1840 CATCH_DUMP_ATTR 1822 1841 */ 1842 1823 1843 /*! 1824 1844 Compute the connection of a client to other clients to determine which clients to send attributes to. … … 1827 1847 A client connects to other clients which holds the same global index as it. 1828 1848 */ 1829 void CDomain::computeConnectedClients( )1849 void CDomain::computeConnectedClients(CContextClient* client) 1830 1850 TRY 1831 1851 { 1852 if (computeConnectedClients_done_.count(client)==0) return ; 1853 else computeConnectedClients_done_.insert(client) ; 1854 1832 1855 CContext* context=CContext::getCurrent() ; 1833 set<int> listNbServer ; 1834 1835 for (auto client : clients) 1856 1857 int nbServer = client->serverSize; 1858 int nbClient = client->clientSize; 1859 int rank = client->clientRank; 1860 1861 if (listNbServer_.count(nbServer) == 0) 1836 1862 { 1837 1838 int nbServer = client->serverSize; 1839 int nbClient = client->clientSize; 1840 int rank = client->clientRank; 1841 bool doComputeGlobalIndexServer = true; 1842 1843 if (listNbServer.find(nbServer)==listNbServer.end()) 1844 { 1845 listNbServer.insert(nbServer) ; 1863 listNbServer_.insert(nbServer) ; 1846 1864 1847 if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 1848 { 1849 nbSenders.erase(nbServer); 1850 connectedServerRank_.erase(nbServer); 1851 } 1852 1853 if (indSrv_.find(nbServer) == indSrv_.end()) 1854 { 1855 int i,j,i_ind,j_ind, nbIndex=i_index.numElements(); 1856 int globalIndexCount = i_index.numElements(); 1857 // Fill in index 1858 CArray<size_t,1> globalIndexDomain(nbIndex); 1859 size_t globalIndex; 1860 1861 for (i = 0; i < nbIndex; ++i) 1865 if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 1866 { 1867 nbSenders.erase(nbServer); 1868 connectedServerRank_.erase(nbServer); 1869 } 1870 1871 if (indSrv_.find(nbServer) == indSrv_.end()) 1872 { 1873 int i,j,i_ind,j_ind, nbIndex=i_index.numElements(); 1874 int globalIndexCount = i_index.numElements(); 1875 // Fill in index 1876 CArray<size_t,1> globalIndexDomain(nbIndex); 1877 size_t globalIndex; 1878 1879 for (i = 0; i < nbIndex; ++i) 1880 { 1881 i_ind=i_index(i); 1882 j_ind=j_index(i); 1883 globalIndex = i_ind + j_ind * ni_glo; 1884 globalIndexDomain(i) = globalIndex; 1885 } 1886 1887 if (globalLocalIndexMap_.empty()) 1888 for (i = 0; i < nbIndex; ++i) globalLocalIndexMap_[globalIndexDomain(i)] = i; 1889 1890 1891 size_t globalSizeIndex = 1, indexBegin, indexEnd; 1892 int range, clientSize = client->clientSize; 1893 std::vector<int> nGlobDomain(2); 1894 nGlobDomain[0] = this->ni_glo; 1895 nGlobDomain[1] = this->nj_glo; 1896 for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i]; 1897 indexBegin = 0; 1898 if (globalSizeIndex <= clientSize) 1899 { 1900 indexBegin = rank%globalSizeIndex; 1901 indexEnd = indexBegin; 1902 } 1903 else 1904 { 1905 for (int i = 0; i < clientSize; ++i) 1862 1906 { 1863 i_ind=i_index(i);1864 j_ind=j_index(i);1865 globalIndex = i_ind + j_ind * ni_glo;1866 globalIndexDomain(i) = globalIndex;1907 range = globalSizeIndex / clientSize; 1908 if (i < (globalSizeIndex%clientSize)) ++range; 1909 if (i == client->clientRank) break; 1910 indexBegin += range; 1867 1911 } 1868 1869 if (globalLocalIndexMap_.empty()) 1870 { 1871 for (i = 0; i < nbIndex; ++i) 1872 globalLocalIndexMap_[globalIndexDomain(i)] = i; 1873 } 1874 1875 size_t globalSizeIndex = 1, indexBegin, indexEnd; 1876 int range, clientSize = client->clientSize; 1877 std::vector<int> nGlobDomain(2); 1878 nGlobDomain[0] = this->ni_glo; 1879 nGlobDomain[1] = this->nj_glo; 1880 for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i]; 1881 indexBegin = 0; 1882 if (globalSizeIndex <= clientSize) 1883 { 1884 indexBegin = rank%globalSizeIndex; 1885 indexEnd = indexBegin; 1886 } 1887 else 1888 { 1889 for (int i = 0; i < clientSize; ++i) 1890 { 1891 range = globalSizeIndex / clientSize; 1892 if (i < (globalSizeIndex%clientSize)) ++range; 1893 if (i == client->clientRank) break; 1894 indexBegin += range; 1895 } 1896 indexEnd = indexBegin + range - 1; 1897 } 1898 1899 // Even if servers have no index, they must received something from client 1900 // We only use several client to send "empty" message to these servers 1901 CServerDistributionDescription serverDescription(nGlobDomain, nbServer); 1902 std::vector<int> serverZeroIndex; 1903 if (isUnstructed_) serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 1904 else serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 1); 1905 1906 std::list<int> serverZeroIndexLeader; 1907 std::list<int> serverZeroIndexNotLeader; 1908 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 1909 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 1910 *it = serverZeroIndex[*it]; 1911 1912 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 1913 clientServerMap->computeServerIndexMapping(globalIndexDomain, nbServer); 1914 CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer(); 1915 1916 CClientServerMapping::GlobalIndexMap::const_iterator it = globalIndexDomainOnServer.begin(), 1917 ite = globalIndexDomainOnServer.end(); 1918 indSrv_[nbServer].swap(globalIndexDomainOnServer); 1919 connectedServerRank_[nbServer].clear(); 1920 for (it = indSrv_[nbServer].begin(); it != ite; ++it) 1921 connectedServerRank_[nbServer].push_back(it->first); 1922 1923 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 1924 connectedServerRank_[nbServer].push_back(*it); 1925 1926 // Even if a client has no index, it must connect to at least one server and 1927 // send an "empty" data to this server 1928 if (connectedServerRank_[nbServer].empty()) 1929 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 1930 1931 // Now check if all servers have data to receive. If not, master client will send empty data. 1932 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 1933 std::vector<int> counts (clientSize); 1934 std::vector<int> displs (clientSize); 1935 displs[0] = 0; 1936 int localCount = connectedServerRank_[nbServer].size() ; 1937 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 1938 for (int i = 0; i < clientSize-1; ++i) 1939 { 1940 displs[i+1] = displs[i] + counts[i]; 1941 } 1942 std::vector<int> allConnectedServers(displs[clientSize-1]+counts[clientSize-1]); 1943 MPI_Gatherv(&(connectedServerRank_[nbServer])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 1944 1945 if ((allConnectedServers.size() != nbServer) && (rank == 0)) 1946 { 1947 std::vector<bool> isSrvConnected (nbServer, false); 1948 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 1949 for (int i = 0; i < nbServer; ++i) 1950 { 1951 if (!isSrvConnected[i]) connectedServerRank_[nbServer].push_back(i); 1952 } 1953 } 1954 nbSenders[nbServer] = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 1955 delete clientServerMap; 1956 } 1912 indexEnd = indexBegin + range - 1; 1913 } 1914 1915 // Even if servers have no index, they must received something from client 1916 // We only use several client to send "empty" message to these servers 1917 CServerDistributionDescription serverDescription(nGlobDomain, nbServer); 1918 std::vector<int> serverZeroIndex; 1919 if (isUnstructed_) serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 1920 else serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 1); 1921 1922 std::list<int> serverZeroIndexLeader; 1923 std::list<int> serverZeroIndexNotLeader; 1924 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 1925 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 1926 *it = serverZeroIndex[*it]; 1927 1928 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 1929 clientServerMap->computeServerIndexMapping(globalIndexDomain, nbServer); 1930 CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer(); 1931 1932 CClientServerMapping::GlobalIndexMap::const_iterator it = globalIndexDomainOnServer.begin(), ite = globalIndexDomainOnServer.end(); 1933 indSrv_[nbServer].swap(globalIndexDomainOnServer); 1934 connectedServerRank_[nbServer].clear(); 1935 for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 1936 1937 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 1938 connectedServerRank_[nbServer].push_back(*it); 1939 1940 // Even if a client has no index, it must connect to at least one server and 1941 // send an "empty" data to this server 1942 if (connectedServerRank_[nbServer].empty()) 1943 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 1944 1945 // Now check if all servers have data to receive. If not, master client will send empty data. 1946 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 1947 std::vector<int> counts (clientSize); 1948 std::vector<int> displs (clientSize); 1949 displs[0] = 0; 1950 int localCount = connectedServerRank_[nbServer].size() ; 1951 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 1952 for (int i = 0; i < clientSize-1; ++i) displs[i+1] = displs[i] + counts[i]; 1953 std::vector<int> allConnectedServers(displs[clientSize-1]+counts[clientSize-1]); 1954 MPI_Gatherv(&(connectedServerRank_[nbServer])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 1955 1956 if ((allConnectedServers.size() != nbServer) && (rank == 0)) 1957 { 1958 std::vector<bool> isSrvConnected (nbServer, false); 1959 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 1960 for (int i = 0; i < nbServer; ++i) if (!isSrvConnected[i]) connectedServerRank_[nbServer].push_back(i); 1961 } 1962 nbSenders[nbServer] = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 1963 delete clientServerMap; 1957 1964 } 1958 1965 } … … 3025 3032 3026 3033 /*! 3034 \brief Check if a domain is completed 3035 Before make any domain processing, we must be sure that all domain informations have 3036 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 3037 other context (coupling). So all direct reference of the domain (domain_ref) must be also completed 3038 \return true if domain and domain reference are completed 3039 */ 3040 bool CDomain::checkIfCompleted(void) 3041 { 3042 if (hasDirectDomainReference()) if (!getDirectDomainReference()->checkIfCompleted()) return false; 3043 return isCompleted_ ; 3044 } 3045 3046 /*! 3047 \brief Set a domain as completed 3048 When all information about a domain have been received, the domain is tagged as completed and is 3049 suitable for processing 3050 */ 3051 void CDomain::setCompleted(void) 3052 { 3053 if (hasDirectDomainReference()) getDirectDomainReference()->setCompleted() ; 3054 isCompleted_=true ; 3055 } 3056 3057 /*! 3058 \brief Set a domain as uncompleted 3059 When informations about a domain are expected from a grid reading from file or coupling, the domain is 3060 tagged as uncompleted and is not suitable for processing 3061 */ 3062 void CDomain::setUncompleted(void) 3063 { 3064 if (hasDirectDomainReference()) getDirectDomainReference()->setUncompleted() ; 3065 isCompleted_=false ; 3066 } 3067 3068 /*! 3027 3069 * Go through the hierarchy to find the domain from which the transformations must be inherited 3028 3070 */ -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp
r1847 r1869 76 76 /// Vérifications /// 77 77 void checkAttributes(void); 78 bool checkAttributes_done_ = false ; 79 78 80 void checkAttributesOnClient(); 79 81 void checkAttributesOnClientAfterTransformation(); … … 109 111 110 112 static bool dispatchEvent(CEventServer& event); 113 114 bool checkIfCompleted(void) ; 115 void setCompleted(void) ; 116 void setUncompleted(void) ; 111 117 112 118 public: … … 157 163 158 164 void computeLocalMask(void) ; 165 166 void computeConnectedClients(CContextClient* client); 167 private: std::set<CContextClient*> computeConnectedClients_done_; public: 168 /** The number of server of a context client. Avoid to re-compute indice computed in a previous computeConnectedClient */ 169 private: std::set<int> listNbServer_ ; public: 170 159 171 private: 160 172 void checkDomain(void); … … 197 209 198 210 void completeLonLatClient(void); 199 void computeConnectedClients();200 211 212 201 213 private: 202 214 … … 209 221 bool isClientChecked; // Verify whether all attributes of domain on the client side are good 210 222 bool isClientAfterTransformationChecked; 223 224 /** define if the domain is completed or not ie all attributes have been received before in case 225 of grid reading from file or coupling */ 226 bool isCompleted_=true ; 211 227 212 228 /** global index of the domain on server side, sent by the clients. This is global index for lon, lat, mask elements (ie non masked elements) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.cpp
r1853 r1869 26 26 #include "tracer.hpp" 27 27 28 namespace xios{ 29 30 /// ////////////////////// Définitions ////////////////////// /// 31 32 CField::CField(void) 33 : CObjectTemplate<CField>(), CFieldAttributes() 34 , grid(), file() 35 , written(false) 36 , nstep(0), nstepMax(0) 37 , hasOutputFile(false) 38 , domAxisScalarIds_(vector<StdString>(3,"")) 39 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 40 , isGridChecked(false) 41 , useCompressedOutput(false) 42 , hasTimeInstant(false) 43 , hasTimeCentered(false) 44 , wasDataRequestedFromServer(false) 45 , wasDataAlreadyReceivedFromServer(false) 46 , mustAutoTrigger(false) 47 , isEOF(false), nstepMaxRead(false) 48 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 49 50 CField::CField(const StdString& id) 51 : CObjectTemplate<CField>(id), CFieldAttributes() 52 , grid(), file() 53 , written(false) 54 , nstep(0), nstepMax(0) 55 , hasOutputFile(false) 56 , domAxisScalarIds_(vector<StdString>(3,"")) 57 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 58 , isGridChecked(false) 59 , useCompressedOutput(false) 60 , hasTimeInstant(false) 61 , hasTimeCentered(false) 62 , wasDataRequestedFromServer(false) 63 , wasDataAlreadyReceivedFromServer(false) 64 , mustAutoTrigger(false) 65 , isEOF(false), nstepMaxRead(false) 66 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 67 68 CField::~CField(void) 69 {} 28 namespace xios 29 { 30 31 /// ////////////////////// Définitions ////////////////////// /// 32 33 CField::CField(void) 34 : CObjectTemplate<CField>(), CFieldAttributes() 35 , file() 36 , written(false) 37 , nstep(0), nstepMax(0) 38 , hasOutputFile(false) 39 , domAxisScalarIds_(vector<StdString>(3,"")) 40 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 41 , isGridChecked(false) 42 , useCompressedOutput(false) 43 , hasTimeInstant(false) 44 , hasTimeCentered(false) 45 , wasDataRequestedFromServer(false) 46 , wasDataAlreadyReceivedFromServer(false) 47 , mustAutoTrigger(false) 48 , isEOF(false), nstepMaxRead(false) 49 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 50 51 CField::CField(const StdString& id) 52 : CObjectTemplate<CField>(id), CFieldAttributes() 53 , file() 54 , written(false) 55 , nstep(0), nstepMax(0) 56 , hasOutputFile(false) 57 , domAxisScalarIds_(vector<StdString>(3,"")) 58 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 59 , isGridChecked(false) 60 , useCompressedOutput(false) 61 , hasTimeInstant(false) 62 , hasTimeCentered(false) 63 , wasDataRequestedFromServer(false) 64 , wasDataAlreadyReceivedFromServer(false) 65 , mustAutoTrigger(false) 66 , isEOF(false), nstepMaxRead(false) 67 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 68 69 CField::~CField(void) 70 {} 70 71 71 72 //---------------------------------------------------------------- 72 73 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 74 void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup) 75 TRY 76 { 77 this->vVariableGroup = newVVariableGroup; 78 } 79 CATCH 80 81 CVariableGroup* CField::getVirtualVariableGroup(void) const 82 TRY 83 { 84 return this->vVariableGroup; 85 } 86 CATCH 87 88 std::vector<CVariable*> CField::getAllVariables(void) const 89 TRY 90 { 91 return this->vVariableGroup->getAllChildren(); 92 } 93 CATCH 94 95 void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent) 96 TRY 97 { 98 SuperClassAttribute::setAttributes(parent, apply); 99 this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL); 100 } 101 CATCH_DUMP_ATTR 101 102 102 103 //---------------------------------------------------------------- … … 155 156 list<CArray<double,1> > list_data; 156 157 157 if (!grid ->doGridHaveDataDistributed(client))158 if (!grid_->doGridHaveDataDistributed(client)) 158 159 { 159 160 if (client->isServerLeader()) 160 161 { 161 for (it = grid ->storeIndex_toSrv_[client].begin(); it != grid->storeIndex_toSrv_[client].end(); it++)162 for (it = grid_->storeIndex_toSrv_[client].begin(); it != grid_->storeIndex_toSrv_[client].end(); it++) 162 163 { 163 164 int rank = it->first; … … 179 180 else 180 181 { 181 for (it = grid ->storeIndex_toSrv_[client].begin(); it != grid->storeIndex_toSrv_[client].end(); it++)182 for (it = grid_->storeIndex_toSrv_[client].begin(); it != grid_->storeIndex_toSrv_[client].end(); it++) 182 183 { 183 184 int rank = it->first; … … 191 192 192 193 list_msg.back() << getId() << data_tmp; 193 event.push(rank, grid ->nbSenders_[receiverSize][rank], list_msg.back());194 event.push(rank, grid_->nbSenders_[receiverSize][rank], list_msg.back()); 194 195 } 195 196 client->sendEvent(event); … … 228 229 if (0 == recvDataSrv.numElements()) 229 230 { 230 CArray<int,1>& storeClient = grid ->storeIndex_client_;231 CArray<int,1>& storeClient = grid_->getStoreIndex_client(); 231 232 232 233 // Gather all data from different clients … … 238 239 const CDate& currDate = context->getCalendar()->getCurrentDate(); 239 240 CDuration offsetAllButMonth (freq_offset.getValue().year, 0 , freq_offset.getValue().day, 240 241 241 freq_offset.getValue().hour, freq_offset.getValue().minute, 242 freq_offset.getValue().second, freq_offset.getValue().timestep); 242 243 const CDate opeDate = (last_operation_srv - offsetAllButMonth + context->getCalendar()->getTimeStep()) 243 244 + freq_op + freq_operation_srv - freq_op - context->getCalendar()->getTimeStep() + offsetAllButMonth; 244 245 245 246 if (opeDate <= currDate) 246 247 { 247 for (map<int, CArray<size_t, 1> >::iterator it = grid ->outLocalIndexStoreOnClient_.begin(); it != grid->outLocalIndexStoreOnClient_.end(); ++it)248 for (map<int, CArray<size_t, 1> >::iterator it = grid_->outLocalIndexStoreOnClient_.begin(); it != grid_->outLocalIndexStoreOnClient_.end(); ++it) 248 249 { 249 250 CArray<double,1> tmp; … … 287 288 recvFoperationSrv->final(); 288 289 last_Write_srv = writeDate; 289 grid ->computeWrittenIndex();290 grid_->computeWrittenIndex(); 290 291 writeField(); 291 292 lastlast_Write_srv = last_Write_srv; … … 299 300 if (!getRelFile()->isEmptyZone()) 300 301 { 301 if (grid ->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)302 if (grid_->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 302 303 { 303 304 getRelFile()->checkWriteFile(); … … 338 339 else client->sendEvent(event); 339 340 } 340 else 341 serverSourceFilter->signalEndOfStream(tsDataRequested); 341 else serverSourceFilter->signalEndOfStream(tsDataRequested); 342 342 343 343 wasDataRequestedFromServer = true; … … 398 398 399 399 map<int, CArray<double,1> >::iterator it; 400 if (!grid ->doGridHaveDataDistributed(client))400 if (!grid_->doGridHaveDataDistributed(client)) 401 401 { 402 402 if (client->isServerLeader()) … … 436 436 else 437 437 { 438 for (map<int, CArray<size_t, 1> >::iterator it = grid ->outLocalIndexStoreOnClient_.begin();439 it != grid ->outLocalIndexStoreOnClient_.end(); ++it)438 for (map<int, CArray<size_t, 1> >::iterator it = grid_->outLocalIndexStoreOnClient_.begin(); 439 it != grid_->outLocalIndexStoreOnClient_.end(); ++it) 440 440 { 441 441 CArray<size_t,1>& indexTmp = it->second; … … 463 463 } 464 464 465 event.push(it->first, grid ->nbReadSenders_[client][it->first], msg);465 event.push(it->first, grid_->nbReadSenders_[client][it->first], msg); 466 466 } 467 467 client->sendEvent(event); … … 479 479 { 480 480 CContext* context = CContext::getCurrent(); 481 grid ->computeWrittenIndex();481 grid_->computeWrittenIndex(); 482 482 getRelFile()->initRead(); 483 483 EReadField readState = RF_DATA; … … 485 485 if (!getRelFile()->isEmptyZone()) 486 486 { 487 if (grid ->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)487 if (grid_->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 488 488 { 489 489 if (0 == recvDataSrv.numElements()) 490 490 { 491 CArray<int,1>& storeClient = grid ->storeIndex_client_;491 CArray<int,1>& storeClient = grid_->getStoreIndex_client(); 492 492 recvDataSrv.resize(storeClient.numElements()); 493 493 } … … 660 660 CATCH_DUMP_ATTR 661 661 662 //---------------------------------------------------------------- 663 664 void CField::setRelFile(CFile* _file) 665 TRY 666 { 667 this->file = _file; 668 hasOutputFile = true; 669 } 670 CATCH_DUMP_ATTR 671 672 //---------------------------------------------------------------- 673 674 StdString CField::GetName(void) { return StdString("field"); } 675 StdString CField::GetDefName(void) { return CField::GetName(); } 676 ENodeType CField::GetType(void) { return eField; } 677 678 //---------------------------------------------------------------- 679 680 CGrid* CField::getRelGrid(void) const 681 TRY 682 { 683 return this->grid_; 684 } 685 CATCH 686 687 //---------------------------------------------------------------- 688 689 CFile* CField::getRelFile(void) const 690 TRY 691 { 692 return this->file; 693 } 694 CATCH 695 696 int CField::getNStep(void) const 697 TRY 698 { 699 return this->nstep; 700 } 701 CATCH 702 703 func::CFunctor::ETimeType CField::getOperationTimeType() const 704 TRY 705 { 706 return operationTimeType; 707 } 708 CATCH 709 662 710 //---------------------------------------------------------------- 663 711 664 void CField::setRelFile(CFile* _file) 665 TRY 666 { 667 this->file = _file; 668 hasOutputFile = true; 669 } 670 CATCH_DUMP_ATTR 671 672 //---------------------------------------------------------------- 673 674 StdString CField::GetName(void) { return StdString("field"); } 675 StdString CField::GetDefName(void) { return CField::GetName(); } 676 ENodeType CField::GetType(void) { return eField; } 677 678 //---------------------------------------------------------------- 679 680 CGrid* CField::getRelGrid(void) const 681 TRY 682 { 683 return this->grid; 684 } 685 CATCH 686 687 //---------------------------------------------------------------- 688 689 CFile* CField::getRelFile(void) const 690 TRY 691 { 692 return this->file; 693 } 694 CATCH 695 696 int CField::getNStep(void) const 697 TRY 698 { 699 return this->nstep; 700 } 701 CATCH 702 703 func::CFunctor::ETimeType CField::getOperationTimeType() const 704 TRY 705 { 706 return operationTimeType; 707 } 708 CATCH 709 710 //---------------------------------------------------------------- 711 712 void CField::incrementNStep(void) 713 TRY 714 { 715 this->nstep++; 716 } 717 CATCH_DUMP_ATTR 718 719 void CField::resetNStep(int nstep /*= 0*/) 720 TRY 721 { 722 this->nstep = nstep; 723 } 724 CATCH_DUMP_ATTR 725 726 void CField::resetNStepMax(void) 727 TRY 728 { 729 this->nstepMax = 0; 730 nstepMaxRead = false; 731 } 732 CATCH_DUMP_ATTR 733 734 //---------------------------------------------------------------- 735 736 bool CField::isActive(bool atCurrentTimestep /*= false*/) const 737 TRY 738 { 739 if (clientSourceFilter) 740 return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 741 else if (storeFilter) 742 return true; 743 else if (instantDataFilter) 744 ERROR("bool CField::isActive(bool atCurrentTimestep)", 745 << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 746 747 return false; 748 } 749 CATCH 750 751 //---------------------------------------------------------------- 752 753 bool CField::wasWritten() const 754 TRY 755 { 756 return written; 757 } 758 CATCH 759 760 void CField::setWritten() 761 TRY 762 { 763 written = true; 764 } 765 CATCH_DUMP_ATTR 766 767 //---------------------------------------------------------------- 768 769 bool CField::getUseCompressedOutput() const 770 TRY 771 { 772 return useCompressedOutput; 773 } 774 CATCH 775 776 void CField::setUseCompressedOutput() 777 TRY 778 { 779 useCompressedOutput = true; 780 } 781 CATCH_DUMP_ATTR 782 783 //---------------------------------------------------------------- 784 785 std::shared_ptr<COutputPin> CField::getInstantDataFilter() 786 TRY 787 { 788 return instantDataFilter; 789 } 790 CATCH_DUMP_ATTR 791 792 //---------------------------------------------------------------- 712 void CField::incrementNStep(void) 713 TRY 714 { 715 this->nstep++; 716 } 717 CATCH_DUMP_ATTR 718 719 void CField::resetNStep(int nstep /*= 0*/) 720 TRY 721 { 722 this->nstep = nstep; 723 } 724 CATCH_DUMP_ATTR 725 726 void CField::resetNStepMax(void) 727 TRY 728 { 729 this->nstepMax = 0; 730 nstepMaxRead = false; 731 } 732 CATCH_DUMP_ATTR 733 734 //---------------------------------------------------------------- 735 736 bool CField::isActive(bool atCurrentTimestep /*= false*/) const 737 TRY 738 { 739 if (clientSourceFilter) 740 return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 741 else if (storeFilter) 742 return true; 743 else if (instantDataFilter) 744 ERROR("bool CField::isActive(bool atCurrentTimestep)", 745 << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 746 747 return false; 748 } 749 CATCH 750 751 //---------------------------------------------------------------- 752 753 bool CField::wasWritten() const 754 TRY 755 { 756 return written; 757 } 758 CATCH 759 760 void CField::setWritten() 761 TRY 762 { 763 written = true; 764 } 765 CATCH_DUMP_ATTR 766 767 //---------------------------------------------------------------- 768 769 bool CField::getUseCompressedOutput() const 770 TRY 771 { 772 return useCompressedOutput; 773 } 774 CATCH 775 776 void CField::setUseCompressedOutput() 777 TRY 778 { 779 useCompressedOutput = true; 780 } 781 CATCH_DUMP_ATTR 782 783 //---------------------------------------------------------------- 784 785 std::shared_ptr<COutputPin> CField::getInstantDataFilter() 786 TRY 787 { 788 return instantDataFilter; 789 } 790 CATCH_DUMP_ATTR 791 792 //---------------------------------------------------------------- 793 794 /*! 795 Build up graph of grids which plays role of destination and source in grid transformation 796 This function should be called before \func solveGridReference() 797 */ 798 void CField::buildGridTransformationGraph() 799 TRY 800 { 801 CContext* context = CContext::getCurrent(); 802 if (context->getServiceType()==CServicesManager::CLIENT) 803 { 804 if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 805 { 806 grid_->addTransGridSource(getDirectFieldReference()->grid_); 807 } 808 } 809 } 810 CATCH_DUMP_ATTR 811 812 /*! 813 Generate a new grid destination if there are more than one grid source pointing to a same grid destination 814 */ 815 void CField::generateNewTransformationGridDest() 816 TRY 817 { 818 CContext* context = CContext::getCurrent(); 819 if (context->getServiceType()==CServicesManager::CLIENT) 820 { 821 std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid_->getTransGridSource(); 822 if (1 < gridSrcMap.size()) 823 { 824 // Search for grid source 825 CGrid* gridSrc = grid_; 826 CField* currField = this; 827 std::vector<CField*> hieraField; 828 while (currField->hasDirectFieldReference() && (gridSrc == grid_)) 829 { 830 hieraField.push_back(currField); 831 CField* tmp = currField->getDirectFieldReference(); 832 currField = tmp; 833 gridSrc = currField->grid_; 834 } 835 836 if (gridSrcMap.end() != gridSrcMap.find(gridSrc)) 837 { 838 CGrid* gridTmp; 839 std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc]; 840 if (newGridDest.first) 841 { 842 StdString newIdGridDest = newGridDest.second; 843 if (!CGrid::has(newIdGridDest)) 844 { 845 ERROR("CGrid* CGrid::generateNewTransformationGridDest()", 846 << " Something wrong happened! Grid whose id " << newIdGridDest 847 << "should exist "); 848 } 849 gridTmp = CGrid::get(newIdGridDest); 850 } 851 else 852 { 853 StdString newIdGridDest = CGrid::generateId(gridSrc, grid_); 854 gridTmp = CGrid::cloneGrid(newIdGridDest, grid_); 855 856 (gridSrcMap[gridSrc]).first = true; 857 (gridSrcMap[gridSrc]).second = newIdGridDest; 858 } 859 860 // Update all descendants 861 for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it) 862 { 863 (*it)->grid_ = gridTmp; 864 (*it)->updateRef((*it)->grid_); 865 } 866 } 867 } 868 } 869 } 870 CATCH_DUMP_ATTR 871 872 void CField::updateRef(CGrid* grid) 873 TRY 874 { 875 if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 876 else 877 { 878 std::vector<CAxis*> axisTmp = grid->getAxis(); 879 std::vector<CDomain*> domainTmp = grid->getDomains(); 880 if ((1<axisTmp.size()) || (1<domainTmp.size())) 881 ERROR("void CField::updateRef(CGrid* grid)", 882 << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 883 884 if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 885 ERROR("void CField::updateRef(CGrid* grid)", 886 << "Incoherent between available domain and domain_ref of field " << this->getId()); 887 if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 888 ERROR("void CField::updateRef(CGrid* grid)", 889 << "Incoherent between available axis and axis_ref of field " << this->getId()); 890 891 if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 892 if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 893 } 894 } 895 CATCH_DUMP_ATTR 896 897 /*! 898 Solve reference of all enabled fields even the source fields . 899 In this step, we do transformations. 900 */ 901 void CField::solveAllEnabledFieldsAndTransform() 902 TRY 903 { 904 CContext* context = CContext::getCurrent(); 905 906 if (!isReferenceSolvedAndTransformed) 907 { 908 isReferenceSolvedAndTransformed = true; 909 910 if (context->getServiceType()==CServicesManager::CLIENT) 911 { 912 solveRefInheritance(true); 913 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFieldsAndTransform(); 914 } 915 916 if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 917 solveServerOperation(); 918 919 solveGridReference(); 920 921 if (context->getServiceType()==CServicesManager::CLIENT) 922 { 923 solveGenerateGrid(); 924 buildGridTransformationGraph(); 925 } 926 927 solveGridDomainAxisRef(false); 928 929 if (context->getServiceType()==CServicesManager::CLIENT) 930 { 931 solveTransformedGrid(); 932 } 933 934 solveGridDomainAxisRef(false); 935 } 936 } 937 CATCH_DUMP_ATTR 938 939 void CField::checkGridOfEnabledFields() 940 TRY 941 { 942 if (!isGridChecked) 943 { 944 isGridChecked = true; 945 solveCheckMaskIndex(false); 946 } 947 } 948 CATCH_DUMP_ATTR 949 950 void CField::sendGridComponentOfEnabledFields() 951 TRY 952 { 953 solveGridDomainAxisRef(true); 954 // solveCheckMaskIndex(true); 955 } 956 CATCH_DUMP_ATTR 957 958 void CField::sendGridOfEnabledFields() 959 TRY 960 { 961 // solveGridDomainAxisRef(true); 962 solveCheckMaskIndex(true); 963 } 964 CATCH_DUMP_ATTR 965 966 void CField::solveOnlyReferenceEnabledField(void) 967 TRY 968 { 969 CContext* context = CContext::getCurrent(); 970 if (!isReferenceSolved) 971 { 972 isReferenceSolved = true; 973 974 if (context->getServiceType()==CServicesManager::CLIENT) 975 { 976 solveRefInheritance(true); 977 if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(); 978 } 979 980 if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 981 solveServerOperation(); 982 983 solveGridReference(); 984 grid_->solveElementsRefInheritance(true); // make it again to solve grid reading from file 985 986 if (context->getServiceType()==CServicesManager::CLIENT) 987 { 988 solveGenerateGrid(); 989 buildGridTransformationGraph(); 990 } 991 } 992 } 993 CATCH_DUMP_ATTR 994 995 void CField::solveAllReferenceEnabledField(bool doSending2Server) 996 TRY 997 { 998 CContext* context = CContext::getCurrent(); 999 solveOnlyReferenceEnabledField(); 1000 1001 if (!areAllReferenceSolved) 1002 { 1003 areAllReferenceSolved = true; 1004 1005 if (context->getServiceType()==CServicesManager::CLIENT) 1006 { 1007 solveRefInheritance(true); 1008 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 1009 } 1010 else if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 1011 solveServerOperation(); 1012 1013 solveGridReference(); 1014 } 1015 1016 solveGridDomainAxisRef(doSending2Server); 1017 1018 if (context->getServiceType()==CServicesManager::CLIENT) 1019 { 1020 solveTransformedGrid(); 1021 } 1022 1023 solveCheckMaskIndex(doSending2Server); 1024 } 1025 CATCH_DUMP_ATTR 1026 1027 std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1028 TRY 1029 { 1030 return grid_->getAttributesBufferSize(client, bufferForWriting); 1031 } 1032 CATCH_DUMP_ATTR 1033 1034 std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1035 TRY 1036 { 1037 return grid_->getDataBufferSize(client, getId(), bufferForWriting); 1038 } 1039 CATCH_DUMP_ATTR 1040 1041 size_t CField::getGlobalWrittenSize() 1042 TRY 1043 { 1044 return grid_->getGlobalWrittenSize(); 1045 } 1046 CATCH_DUMP_ATTR 1047 1048 //---------------------------------------------------------------- 1049 1050 void CField::solveServerOperation(void) 1051 TRY 1052 { 1053 CContext* context = CContext::getCurrent(); 1054 1055 if (context->getServiceType()==CServicesManager::CLIENT || !hasOutputFile) return; 1056 1057 if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 1058 1059 if (freq_offset.isEmpty()) freq_offset.setValue(NoneDu); 1060 1061 freq_operation_srv = file->output_freq.getValue(); 1062 freq_write_srv = file->output_freq.getValue(); 1063 1064 lastlast_Write_srv = context->getCalendar()->getInitDate(); 1065 last_Write_srv = context->getCalendar()->getInitDate(); 1066 last_operation_srv = context->getCalendar()->getInitDate(); 1067 1068 const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep(); 1069 last_operation_srv = last_operation_srv - toffset; 1070 1071 if (operation.isEmpty()) 1072 ERROR("void CField::solveServerOperation(void)", 1073 << "An operation must be defined for field \"" << getId() << "\"."); 1074 1075 std::shared_ptr<func::CFunctor> functor; 1076 CArray<double, 1> dummyData; 1077 1078 #define DECLARE_FUNCTOR(MType, mtype) \ 1079 if (operation.getValue().compare(#mtype) == 0) \ 1080 { \ 1081 functor.reset(new func::C##MType(dummyData)); \ 1082 } 1083 1084 #include "functor_type.conf" 1085 1086 if (!functor) 1087 ERROR("void CField::solveServerOperation(void)", 1088 << "\"" << operation << "\" is not a valid operation."); 1089 1090 operationTimeType = functor->timeType(); 1091 } 1092 CATCH_DUMP_ATTR 1093 1094 //---------------------------------------------------------------- 1095 1096 bool CField::buildWorkflowGraph(CGarbageCollector& gc) 1097 { 1098 if (buildWorkflowGraphDone_) return true ; 1099 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1100 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1101 1102 if (!inputFilter) inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc)); 1103 1104 if (hasDirectFieldReference()) 1105 { 1106 CField* fieldRef = getDirectFieldReference(); 1107 bool ret=fieldRef->buildWorkflowGraph(gc); 1108 if (!ret) return false ; // workflow graph cannot be built at this stage 1109 } 1110 1111 // Check if we have an expression to parse 1112 std::shared_ptr<COutputPin> filterExpr ; 1113 if (hasExpression()) 1114 { 1115 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 1116 filterExpr = expr->reduce(gc, *this); 1117 if (!filterExpr) return false ; // workflow graph cannot be built at this stage 1118 } 1119 1120 // now construct grid and check if element are enabled 1121 solveGridReference() ; // grid_ is now defined 1122 1123 // prepare transformation. Need to know before if workflow of auxillary field can be built 1124 if (hasDirectFieldReference()) 1125 { 1126 auto gridPath=getGridPath() ; 1127 gridPath.push_back(grid_) ; 1128 1129 CGrid* gridSrc=getDirectFieldReference()->getGrid() ; 1130 for(auto grid : gridPath) 1131 { 1132 if (!grid->checkIfCompleted()) return false ; 1133 grid->solveElementsRefInheritance() ; 1134 grid_->completeGrid(gridSrc); // grid generation, to be checked 1135 grid->prepareTransformGrid(gridSrc) ; // prepare the grid tranformation 1136 for(auto fieldId : grid->getAuxInputTransformGrid()) // try to build workflow graph for auxillary field tranformation 1137 if (!CField::get(fieldId)->buildWorkflowGraph(gc)) return false ; 1138 gridSrc=grid ; 1139 } 1140 1141 std::shared_ptr<COutputPin> lastFilter ; 1142 if (filterExpr) lastFilter=filterExpr ; 1143 else lastFilter = inputFilter ; 1144 1145 gridSrc=getDirectFieldReference()->getGrid() ; 1146 for(auto grid : gridPath) 1147 { 1148 grid->makeTransformGrid() ; // make the grid transformation 1149 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridSrc, grid, detectMissingValues, defaultValue); 1150 lastFilter->connectOutput(filters.first, 0); 1151 lastFilter = filters.second; 1152 gridSrc=grid ; 1153 } 1154 instantDataFilter = lastFilter ; 1155 1156 // connect the input Filter to the reference 1157 getDirectFieldReference()->getInstantDataFilter()->connectOutput(inputFilter,0); 1158 } 1159 else 1160 { 1161 if (!grid_->checkIfCompleted()) return false ; 1162 grid_->solveElementsRefInheritance() ; 1163 grid_->completeGrid(); // grid generation, to be checked 1164 grid_->checkElementsAttributes() ; 1165 instantDataFilter=inputFilter ; 1166 setModelIn() ; // no reference, the field is potentially a source field from model 1167 } 1168 1169 buildWorkflowGraphDone_ = true ; 1170 workflowEnabled_ = true ; 1171 return true ; 1172 } 1173 1174 1175 void CField::connectToFileServer(CGarbageCollector& gc) 1176 { 1177 // insert temporal filter before sending to files 1178 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 1179 // insert temporal filter before sending to files 1180 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 1181 } 1182 1183 void CField::computeGridIndexToFileServer(void) 1184 { 1185 grid_->computeGridIndexToFileServer(client) ; 1186 } 793 1187 794 1188 /*! 795 Build up graph of grids which plays role of destination and source in grid transformation 796 This function should be called before \func solveGridReference() 1189 * Transform the grid_path attribut into vector of grid. 1190 * \return the vector CGrid* containing the list of grid path for tranformation 1191 */ 1192 vector<CGrid*> CField::getGridPath(void) 1193 { 1194 std::vector<CGrid*> gridPath; 1195 1196 if (hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 1197 { 1198 if (!grid_path.isEmpty()) 1199 { 1200 std::string gridId; 1201 size_t start = 0, end; 1202 1203 do 1204 { 1205 end = grid_path.getValue().find(',', start); 1206 if (end != std::string::npos) 1207 { 1208 gridId = grid_path.getValue().substr(start, end - start); 1209 start = end + 1; 1210 } 1211 else gridId = grid_path.getValue().substr(start); 1212 1213 if (!CGrid::has(gridId)) 1214 ERROR("void CField::solveTransformedGrid()", 1215 << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 1216 1217 gridPath.push_back(CGrid::get(gridId)); 1218 } 1219 while (end != std::string::npos); 1220 } 1221 } 1222 return gridPath ; 1223 } 1224 1225 /*! 1226 * Constructs the graph filter for the field, enabling or not the data output. 1227 * This method should not be called more than once with enableOutput equal to true. 1228 * 1229 * \param gc the garbage collector to use when building the filter graph 1230 * \param enableOutput must be true when the field data is to be 1231 * read by the client or/and written to a file 797 1232 */ 798 void CField::buildGridTransformationGraph() 799 TRY 800 { 801 CContext* context = CContext::getCurrent(); 802 if (context->getServiceType()==CServicesManager::CLIENT) 803 { 804 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 805 { 806 grid->addTransGridSource(getDirectFieldReference()->grid); 807 } 808 } 809 } 810 CATCH_DUMP_ATTR 811 812 /*! 813 Generate a new grid destination if there are more than one grid source pointing to a same grid destination 814 */ 815 void CField::generateNewTransformationGridDest() 816 TRY 817 { 818 CContext* context = CContext::getCurrent(); 819 if (context->getServiceType()==CServicesManager::CLIENT) 820 { 821 std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid->getTransGridSource(); 822 if (1 < gridSrcMap.size()) 823 { 824 // Search for grid source 825 CGrid* gridSrc = grid; 826 CField* currField = this; 827 std::vector<CField*> hieraField; 828 829 while (currField->hasDirectFieldReference() && (gridSrc == grid)) 830 { 831 hieraField.push_back(currField); 832 CField* tmp = currField->getDirectFieldReference(); 833 currField = tmp; 834 gridSrc = currField->grid; 835 } 836 837 if (gridSrcMap.end() != gridSrcMap.find(gridSrc)) 838 { 839 CGrid* gridTmp; 840 std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc]; 841 if (newGridDest.first) 842 { 843 StdString newIdGridDest = newGridDest.second; 844 if (!CGrid::has(newIdGridDest)) 845 { 846 ERROR("CGrid* CGrid::generateNewTransformationGridDest()", 847 << " Something wrong happened! Grid whose id " << newIdGridDest 848 << "should exist "); 849 } 850 gridTmp = CGrid::get(newIdGridDest); 851 } 852 else 853 { 854 StdString newIdGridDest = CGrid::generateId(gridSrc, grid); 855 gridTmp = CGrid::cloneGrid(newIdGridDest, grid); 856 857 (gridSrcMap[gridSrc]).first = true; 858 (gridSrcMap[gridSrc]).second = newIdGridDest; 859 } 860 861 // Update all descendants 862 for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it) 863 { 864 (*it)->grid = gridTmp; 865 (*it)->updateRef((*it)->grid); 866 } 867 } 868 } 869 } 870 } 871 CATCH_DUMP_ATTR 872 873 void CField::updateRef(CGrid* grid) 874 TRY 875 { 876 if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 877 else 878 { 879 std::vector<CAxis*> axisTmp = grid->getAxis(); 880 std::vector<CDomain*> domainTmp = grid->getDomains(); 881 if ((1<axisTmp.size()) || (1<domainTmp.size())) 882 ERROR("void CField::updateRef(CGrid* grid)", 883 << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 884 885 if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 886 ERROR("void CField::updateRef(CGrid* grid)", 887 << "Incoherent between available domain and domain_ref of field " << this->getId()); 888 if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 889 ERROR("void CField::updateRef(CGrid* grid)", 890 << "Incoherent between available axis and axis_ref of field " << this->getId()); 891 892 if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 893 if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 894 } 895 } 896 CATCH_DUMP_ATTR 897 898 /*! 899 Solve reference of all enabled fields even the source fields . 900 In this step, we do transformations. 901 */ 902 void CField::solveAllEnabledFieldsAndTransform() 903 TRY 904 { 905 CContext* context = CContext::getCurrent(); 906 907 if (!isReferenceSolvedAndTransformed) 908 { 909 isReferenceSolvedAndTransformed = true; 910 911 if (context->getServiceType()==CServicesManager::CLIENT) 912 { 913 solveRefInheritance(true); 914 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFieldsAndTransform(); 915 } 916 917 if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 918 solveServerOperation(); 919 920 solveGridReference(); 921 922 if (context->getServiceType()==CServicesManager::CLIENT) 923 { 924 solveGenerateGrid(); 925 buildGridTransformationGraph(); 926 } 927 928 solveGridDomainAxisRef(false); 929 930 if (context->getServiceType()==CServicesManager::CLIENT) 931 { 932 solveTransformedGrid(); 933 } 934 935 solveGridDomainAxisRef(false); 936 } 937 } 938 CATCH_DUMP_ATTR 939 940 void CField::checkGridOfEnabledFields() 941 TRY 942 { 943 if (!isGridChecked) 944 { 945 isGridChecked = true; 946 solveCheckMaskIndex(false); 947 } 948 } 949 CATCH_DUMP_ATTR 950 951 void CField::sendGridComponentOfEnabledFields() 952 TRY 953 { 954 solveGridDomainAxisRef(true); 955 // solveCheckMaskIndex(true); 956 } 957 CATCH_DUMP_ATTR 958 959 void CField::sendGridOfEnabledFields() 960 TRY 961 { 962 // solveGridDomainAxisRef(true); 963 solveCheckMaskIndex(true); 964 } 965 CATCH_DUMP_ATTR 966 967 void CField::solveOnlyReferenceEnabledField(void) 968 TRY 969 { 970 CContext* context = CContext::getCurrent(); 971 if (!isReferenceSolved) 972 { 973 isReferenceSolved = true; 974 975 if (context->getServiceType()==CServicesManager::CLIENT) 976 { 977 solveRefInheritance(true); 978 if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(); 979 } 980 981 if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 982 solveServerOperation(); 983 984 solveGridReference(); 985 grid->solveDomainAxisRefInheritance(true); // make it again to solve grid reading from file 986 987 if (context->getServiceType()==CServicesManager::CLIENT) 988 { 989 solveGenerateGrid(); 990 buildGridTransformationGraph(); 991 } 992 } 993 } 994 CATCH_DUMP_ATTR 995 996 void CField::solveAllReferenceEnabledField(bool doSending2Server) 997 TRY 998 { 999 CContext* context = CContext::getCurrent(); 1000 solveOnlyReferenceEnabledField(); 1001 1002 if (!areAllReferenceSolved) 1003 { 1004 areAllReferenceSolved = true; 1005 1006 if (context->getServiceType()==CServicesManager::CLIENT) 1007 { 1008 solveRefInheritance(true); 1009 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 1010 } 1011 else if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 1012 solveServerOperation(); 1013 1014 solveGridReference(); 1015 } 1016 1017 solveGridDomainAxisRef(doSending2Server); 1018 1019 if (context->getServiceType()==CServicesManager::CLIENT) 1020 { 1021 solveTransformedGrid(); 1022 } 1023 1024 solveCheckMaskIndex(doSending2Server); 1025 } 1026 CATCH_DUMP_ATTR 1027 1028 std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1029 TRY 1030 { 1031 return grid->getAttributesBufferSize(client, bufferForWriting); 1032 } 1033 CATCH_DUMP_ATTR 1034 1035 std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1036 TRY 1037 { 1038 return grid->getDataBufferSize(client, getId(), bufferForWriting); 1039 } 1040 CATCH_DUMP_ATTR 1041 1042 size_t CField::getGlobalWrittenSize() 1043 TRY 1044 { 1045 return grid->getGlobalWrittenSize(); 1046 } 1047 CATCH_DUMP_ATTR 1048 1049 //---------------------------------------------------------------- 1050 1051 void CField::solveServerOperation(void) 1052 TRY 1053 { 1054 CContext* context = CContext::getCurrent(); 1055 1056 if (context->getServiceType()==CServicesManager::CLIENT || !hasOutputFile) return; 1057 1058 if (freq_op.isEmpty()) 1059 freq_op.setValue(TimeStep); 1060 1061 if (freq_offset.isEmpty()) 1062 freq_offset.setValue(NoneDu); 1063 1064 freq_operation_srv = file->output_freq.getValue(); 1065 freq_write_srv = file->output_freq.getValue(); 1066 1067 lastlast_Write_srv = context->getCalendar()->getInitDate(); 1068 last_Write_srv = context->getCalendar()->getInitDate(); 1069 last_operation_srv = context->getCalendar()->getInitDate(); 1070 1071 const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep(); 1072 last_operation_srv = last_operation_srv - toffset; 1073 1074 if (operation.isEmpty()) 1075 ERROR("void CField::solveServerOperation(void)", 1076 << "An operation must be defined for field \"" << getId() << "\"."); 1077 1078 std::shared_ptr<func::CFunctor> functor; 1079 CArray<double, 1> dummyData; 1080 1081 #define DECLARE_FUNCTOR(MType, mtype) \ 1082 if (operation.getValue().compare(#mtype) == 0) \ 1083 { \ 1084 functor.reset(new func::C##MType(dummyData)); \ 1085 } 1086 1087 #include "functor_type.conf" 1088 1089 if (!functor) 1090 ERROR("void CField::solveServerOperation(void)", 1091 << "\"" << operation << "\" is not a valid operation."); 1092 1093 operationTimeType = functor->timeType(); 1094 } 1095 CATCH_DUMP_ATTR 1096 1097 //---------------------------------------------------------------- 1098 1099 /*! 1100 * Constructs the graph filter for the field, enabling or not the data output. 1101 * This method should not be called more than once with enableOutput equal to true. 1102 * 1103 * \param gc the garbage collector to use when building the filter graph 1104 * \param enableOutput must be true when the field data is to be 1105 * read by the client or/and written to a file 1106 */ 1107 void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput) 1108 TRY 1109 { 1233 1234 void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput) 1235 TRY 1236 { 1110 1237 if (!isReferenceSolvedAndTransformed) solveAllEnabledFieldsAndTransform(); 1111 1238 if (!isGridChecked) checkGridOfEnabledFields(); 1112 1239 1113 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1114 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1115 1116 CContext* context = CContext::getCurrent(); 1117 bool hasWriterServer = context->getServiceType()==CServicesManager::OUT_SERVER ; 1118 bool hasIntermediateServer = context->getServiceType()==CServicesManager::GATHERER ; 1119 1120 if (hasWriterServer) 1121 { 1122 if (!instantDataFilter) 1123 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false)); 1124 1125 1126 // If the field data is to be read by the client or/and written to a file 1127 if (enableOutput && !storeFilter && !fileWriterFilter) 1128 { 1129 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1130 { 1131 fileServerWriterFilter = std::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this)); 1132 instantDataFilter->connectOutput(fileServerWriterFilter, 0); 1240 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1241 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1242 1243 CContext* context = CContext::getCurrent(); 1244 bool hasWriterServer = context->getServiceType()==CServicesManager::OUT_SERVER ; 1245 bool hasIntermediateServer = context->getServiceType()==CServicesManager::GATHERER ; 1246 1247 if (hasWriterServer) 1248 { 1249 if (!instantDataFilter) 1250 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false)); 1251 1252 1253 // If the field data is to be read by the client or/and written to a file 1254 if (enableOutput && !storeFilter && !fileWriterFilter) 1255 { 1256 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1257 { 1258 fileServerWriterFilter = std::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this)); 1259 instantDataFilter->connectOutput(fileServerWriterFilter, 0); 1260 } 1261 } 1262 } 1263 else if (hasIntermediateServer) 1264 { 1265 if (!instantDataFilter) 1266 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, false, false)); 1267 1268 // If the field data is to be read by the client or/and written to a file 1269 if (enableOutput && !storeFilter && !fileWriterFilter) 1270 { 1271 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1272 { 1273 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 1274 instantDataFilter->connectOutput(fileWriterFilter, 0); 1275 } 1276 } 1277 } 1278 else 1279 { 1280 // Start by building a filter which can provide the field's instant data 1281 if (!instantDataFilter) 1282 { 1283 // Check if we have an expression to parse 1284 if (hasExpression()) 1285 { 1286 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 1287 std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 1288 1289 // Check if a spatial transformation is needed 1290 if (!field_ref.isEmpty()) 1291 { 1292 CGrid* gridRef = CField::get(field_ref)->grid_; 1293 if (grid_ && grid_ != gridRef && grid_->hasTransform()) 1294 { 1295 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid_, detectMissingValues, defaultValue); 1296 1297 filter->connectOutput(filters.first, 0); 1298 filter = filters.second; 1299 } 1300 } 1301 1302 instantDataFilter = filter; 1303 } 1304 // Check if we have a reference on another field 1305 else if (!field_ref.isEmpty()) instantDataFilter = getFieldReference(gc); 1306 // Check if the data is to be read from a file 1307 else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1308 { 1309 checkTimeAttributes(); 1310 instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false, freq_offset, true, 1311 detectMissingValues, defaultValue)); 1312 } 1313 else // The data might be passed from the model 1314 { 1315 if (check_if_active.isEmpty()) check_if_active = false; 1316 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, false, true, NoneDu, false, 1317 detectMissingValues, defaultValue)); 1318 } 1319 } 1320 1321 // If the field data is to be read by the client or/and written to a file 1322 if (enableOutput && !storeFilter && !fileWriterFilter) 1323 { 1324 if (!read_access.isEmpty() && read_access) 1325 { 1326 storeFilter = std::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid_, 1327 detectMissingValues, defaultValue)); 1328 instantDataFilter->connectOutput(storeFilter, 0); 1329 } 1330 1331 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1332 { 1333 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 1334 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 1335 } 1336 } 1337 } 1338 } 1339 CATCH_DUMP_ATTR 1340 1341 /*! 1342 * Returns the filter needed to handle the field reference. 1343 * This method should only be called when building the filter graph corresponding to the field. 1344 * 1345 * \param gc the garbage collector to use 1346 * \return the output pin corresponding to the field reference 1347 */ 1348 std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 1349 TRY 1350 { 1351 if (instantDataFilter || field_ref.isEmpty()) 1352 ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 1353 "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 1354 1355 CField* fieldRef = CField::get(field_ref); 1356 fieldRef->buildFilterGraph(gc, false); 1357 1358 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters; 1359 // Check if a spatial transformation is needed 1360 if (grid_ && grid_ != fieldRef->grid_ && grid_->hasTransform()) 1361 { 1362 bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1363 double defaultValue = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1364 filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid_, grid_, hasMissingValue, defaultValue); 1365 } 1366 else 1367 filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 1368 1369 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 1370 1371 return filters.second; 1372 } 1373 CATCH_DUMP_ATTR 1374 1375 /*! 1376 * Returns the filter needed to handle a self reference in the field's expression. 1377 * If the needed filter does not exist, it is created, otherwise it is reused. 1378 * This method should only be called when building the filter graph corresponding 1379 * to the field's expression. 1380 * 1381 * \param gc the garbage collector to use 1382 * \return the output pin corresponding to a self reference 1383 */ 1384 1385 /* old version 1386 std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 1387 TRY 1388 { 1389 if (instantDataFilter || !hasExpression()) 1390 ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 1391 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1392 1393 if (!selfReferenceFilter) 1394 { 1395 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1396 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1397 1398 if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1399 { 1400 if (!serverSourceFilter) 1401 { 1402 checkTimeAttributes(); 1403 serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false, freq_offset, true, 1404 detectMissingValues, defaultValue)); 1133 1405 } 1134 } 1135 } 1136 else if (hasIntermediateServer) 1137 { 1138 if (!instantDataFilter) 1139 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, false)); 1140 1141 // If the field data is to be read by the client or/and written to a file 1142 if (enableOutput && !storeFilter && !fileWriterFilter) 1143 { 1144 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1145 { 1146 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 1147 instantDataFilter->connectOutput(fileWriterFilter, 0); 1148 } 1149 } 1150 } 1151 else 1152 { 1153 // Start by building a filter which can provide the field's instant data 1154 if (!instantDataFilter) 1155 { 1156 // Check if we have an expression to parse 1157 if (hasExpression()) 1158 { 1159 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 1160 std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 1161 1162 // Check if a spatial transformation is needed 1163 if (!field_ref.isEmpty()) 1164 { 1165 CGrid* gridRef = CField::get(field_ref)->grid; 1166 1167 if (grid && grid != gridRef && grid->hasTransform()) 1168 { 1169 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, detectMissingValues, defaultValue); 1170 1171 filter->connectOutput(filters.first, 0); 1172 filter = filters.second; 1173 } 1174 } 1175 1176 instantDataFilter = filter; 1177 } 1178 // Check if we have a reference on another field 1179 else if (!field_ref.isEmpty()) 1180 instantDataFilter = getFieldReference(gc); 1181 // Check if the data is to be read from a file 1182 else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1183 { 1184 checkTimeAttributes(); 1185 instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 1186 detectMissingValues, defaultValue)); 1187 } 1188 else // The data might be passed from the model 1189 { 1190 if (check_if_active.isEmpty()) check_if_active = false; 1191 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, true, NoneDu, false, 1192 detectMissingValues, defaultValue)); 1193 } 1194 } 1195 1196 // If the field data is to be read by the client or/and written to a file 1197 if (enableOutput && !storeFilter && !fileWriterFilter) 1198 { 1199 if (!read_access.isEmpty() && read_access) 1200 { 1201 storeFilter = std::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid, 1202 detectMissingValues, defaultValue)); 1203 instantDataFilter->connectOutput(storeFilter, 0); 1204 } 1205 1206 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1207 { 1208 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 1209 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 1210 } 1211 } 1212 } 1213 } 1214 CATCH_DUMP_ATTR 1215 1216 /*! 1217 * Returns the filter needed to handle the field reference. 1218 * This method should only be called when building the filter graph corresponding to the field. 1219 * 1220 * \param gc the garbage collector to use 1221 * \return the output pin corresponding to the field reference 1222 */ 1223 std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 1224 TRY 1225 { 1226 if (instantDataFilter || field_ref.isEmpty()) 1227 ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 1228 "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 1229 1230 CField* fieldRef = CField::get(field_ref); 1231 fieldRef->buildFilterGraph(gc, false); 1232 1233 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters; 1234 // Check if a spatial transformation is needed 1235 if (grid && grid != fieldRef->grid && grid->hasTransform()) 1236 { 1237 bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1238 double defaultValue = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1239 filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, hasMissingValue, defaultValue); 1240 } 1241 else 1242 filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 1243 1244 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 1245 1246 return filters.second; 1247 } 1248 CATCH_DUMP_ATTR 1249 1250 /*! 1251 * Returns the filter needed to handle a self reference in the field's expression. 1252 * If the needed filter does not exist, it is created, otherwise it is reused. 1253 * This method should only be called when building the filter graph corresponding 1254 * to the field's expression. 1255 * 1256 * \param gc the garbage collector to use 1257 * \return the output pin corresponding to a self reference 1258 */ 1259 std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 1260 TRY 1261 { 1262 if (instantDataFilter || !hasExpression()) 1263 ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 1264 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1265 1266 if (!selfReferenceFilter) 1267 { 1268 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1269 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1270 1271 if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1272 { 1273 if (!serverSourceFilter) 1274 { 1275 checkTimeAttributes(); 1276 serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 1277 detectMissingValues, defaultValue)); 1278 } 1279 1280 selfReferenceFilter = serverSourceFilter; 1281 } 1282 else if (!field_ref.isEmpty()) 1283 { 1284 CField* fieldRef = CField::get(field_ref); 1285 fieldRef->buildFilterGraph(gc, false); 1286 selfReferenceFilter = fieldRef->getInstantDataFilter(); 1287 } 1288 else 1289 { 1290 if (!clientSourceFilter) 1291 { 1292 if (check_if_active.isEmpty()) check_if_active = false; 1293 clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, true, NoneDu, false, 1294 detectMissingValues, defaultValue)); 1295 } 1296 1297 selfReferenceFilter = clientSourceFilter; 1298 } 1299 } 1300 1301 return selfReferenceFilter; 1302 } 1303 CATCH_DUMP_ATTR 1304 1305 /*! 1306 * Returns the temporal filter corresponding to the field's temporal operation 1307 * for the specified operation frequency. The filter is created if it does not 1308 * exist, otherwise it is reused. 1309 * 1310 * \param gc the garbage collector to use 1311 * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 1312 * \return the output pin corresponding to the requested temporal filter 1313 */ 1314 std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1315 TRY 1316 { 1317 std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 1318 1319 if (it == temporalDataFilters.end()) 1320 { 1321 if (operation.isEmpty()) 1322 ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1323 << "An operation must be defined for field \"" << getId() << "\"."); 1324 1325 checkTimeAttributes(&outFreq); 1326 1327 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1328 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1406 1407 selfReferenceFilter = serverSourceFilter; 1408 } 1409 else if (!field_ref.isEmpty()) 1410 { 1411 CField* fieldRef = CField::get(field_ref); 1412 fieldRef->buildFilterGraph(gc, false); 1413 selfReferenceFilter = fieldRef->getInstantDataFilter(); 1414 } 1415 else 1416 { 1417 if (!clientSourceFilter) 1418 { 1419 if (check_if_active.isEmpty()) check_if_active = false; 1420 clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, true, NoneDu, false, 1421 detectMissingValues, defaultValue)); 1422 } 1423 1424 selfReferenceFilter = clientSourceFilter; 1425 } 1426 } 1427 1428 return selfReferenceFilter; 1429 } 1430 CATCH_DUMP_ATTR 1431 */ 1432 std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 1433 TRY 1434 { 1435 return inputFilter ; 1436 } 1437 CATCH_DUMP_ATTR 1438 1439 /*! 1440 * Returns the temporal filter corresponding to the field's temporal operation 1441 * for the specified operation frequency. The filter is created if it does not 1442 * exist, otherwise it is reused. 1443 * 1444 * \param gc the garbage collector to use 1445 * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 1446 * \return the output pin corresponding to the requested temporal filter 1447 */ 1448 std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1449 TRY 1450 { 1451 std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 1452 1453 if (it == temporalDataFilters.end()) 1454 { 1455 if (operation.isEmpty()) 1456 ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1457 << "An operation must be defined for field \"" << getId() << "\"."); 1458 1459 checkTimeAttributes(&outFreq); 1460 1461 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1462 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1329 1463 CContext::getCurrent()->getCalendar()->getInitDate(), 1330 1464 freq_op, freq_offset, outFreq, detectMissingValues)); 1331 1465 1332 1333 1334 1335 1336 1337 1338 1339 1466 instantDataFilter->connectOutput(temporalFilter, 0); 1467 1468 it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first; 1469 } 1470 1471 return it->second; 1472 } 1473 CATCH_DUMP_ATTR 1340 1474 1341 1475 /*! … … 1347 1481 * \return the output pin corresponding to the requested temporal filter 1348 1482 */ 1349 1350 std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1351 TRY 1352 { 1353 if (instantDataFilter || !hasExpression()) 1354 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 1355 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1356 1357 if (!selfReferenceFilter) getSelfReference(gc) ; 1358 1359 if (serverSourceFilter || clientSourceFilter) 1360 { 1361 if (operation.isEmpty()) 1362 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1363 << "An operation must be defined for field \"" << getId() << "\"."); 1364 1365 checkTimeAttributes(&outFreq); 1366 1367 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1368 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1369 CContext::getCurrent()->getCalendar()->getInitDate(), 1370 freq_op, freq_offset, outFreq, detectMissingValues)); 1371 1372 selfReferenceFilter->connectOutput(temporalFilter, 0); 1373 return temporalFilter ; 1374 } 1375 else if (!field_ref.isEmpty()) 1376 { 1377 CField* fieldRef = CField::get(field_ref); 1378 fieldRef->buildFilterGraph(gc, false); 1379 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1380 } 1381 } 1382 CATCH_DUMP_ATTR 1383 1384 //---------------------------------------------------------------- 1483 1484 std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1485 TRY 1486 { 1487 if (instantDataFilter || !hasExpression()) 1488 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 1489 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1490 1491 if (selfTemporalDataFilter) return selfTemporalDataFilter; 1492 1493 if (hasDirectFieldReference()) 1494 { 1495 CField* fieldRef=getDirectFieldReference(); 1496 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1497 } 1498 else 1499 { 1500 if (selfTemporalDataFilter) return selfTemporalDataFilter ; 1501 1502 if (operation.isEmpty()) 1503 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1504 << "An operation must be defined for field \"" << getId() << "\"."); 1505 1506 checkTimeAttributes(&outFreq); //bof 1507 1508 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1509 selfTemporalDataFilter = std::shared_ptr<CTemporalFilter>(new CTemporalFilter(gc, operation, 1510 CContext::getCurrent()->getCalendar()->getInitDate(), 1511 freq_op, freq_offset, outFreq, detectMissingValues)); 1512 1513 inputFilter->connectOutput(selfTemporalDataFilter, 0); 1514 return selfTemporalDataFilter ; 1515 } 1516 } 1517 CATCH_DUMP_ATTR 1518 1519 /* old version 1520 std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1521 TRY 1522 { 1523 if (instantDataFilter || !hasExpression()) 1524 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 1525 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1526 1527 if (!selfReferenceFilter) getSelfReference(gc) ; 1528 1529 if (serverSourceFilter || clientSourceFilter) 1530 { 1531 if (operation.isEmpty()) 1532 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1533 << "An operation must be defined for field \"" << getId() << "\"."); 1534 1535 checkTimeAttributes(&outFreq); 1536 1537 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1538 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1539 CContext::getCurrent()->getCalendar()->getInitDate(), 1540 freq_op, freq_offset, outFreq, detectMissingValues)); 1541 1542 selfReferenceFilter->connectOutput(temporalFilter, 0); 1543 return temporalFilter ; 1544 } 1545 else if (!field_ref.isEmpty()) 1546 { 1547 CField* fieldRef = CField::get(field_ref); 1548 fieldRef->buildFilterGraph(gc, false); 1549 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1550 } 1551 } 1552 CATCH_DUMP_ATTR 1553 */ 1554 1555 //---------------------------------------------------------------- 1385 1556 /* 1386 1557 void CField::fromBinary(StdIStream& is) … … 1398 1569 //---------------------------------------------------------------- 1399 1570 1400 void CField::solveGridReference(void) 1401 TRY 1402 { 1403 if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 1404 { 1405 ERROR("CField::solveGridReference(void)", 1406 << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 1407 } 1408 else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 1409 { 1410 ERROR("CField::solveGridReference(void)", 1411 << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 1412 << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 1413 } 1414 1415 if (grid_ref.isEmpty()) 1416 { 1417 std::vector<CDomain*> vecDom; 1418 std::vector<CAxis*> vecAxis; 1419 std::vector<CScalar*> vecScalar; 1420 std::vector<int> axisDomainOrderTmp; 1421 1422 std::vector<CDomain*> vecDomRef; 1423 std::vector<CAxis*> vecAxisRef; 1424 std::vector<CScalar*> vecScalarRef; 1425 1571 void CField::solveGridReference(void) 1572 TRY 1573 { 1574 if (grid_!=nullptr) return ; // already done 1575 1576 if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 1577 { 1578 ERROR("CField::solveGridReference(void)", 1579 << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 1580 } 1581 else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 1582 { 1583 ERROR("CField::solveGridReference(void)", 1584 << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 1585 << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 1586 } 1587 1588 if (grid_ref.isEmpty()) 1589 { 1590 std::vector<CDomain*> vecDom; 1591 std::vector<CAxis*> vecAxis; 1592 std::vector<CScalar*> vecScalar; 1593 std::vector<int> axisDomainOrderTmp; 1594 1595 std::vector<CDomain*> vecDomRef; 1596 std::vector<CAxis*> vecAxisRef; 1597 std::vector<CScalar*> vecScalarRef; 1426 1598 1427 if (!domain_ref.isEmpty()) 1599 if (!domain_ref.isEmpty()) 1600 { 1601 StdString tmp = domain_ref.getValue(); 1602 if (CDomain::has(domain_ref)) 1428 1603 { 1429 StdString tmp = domain_ref.getValue(); 1430 if (CDomain::has(domain_ref)) 1431 { 1432 vecDom.push_back(CDomain::get(domain_ref)); 1433 vecDomRef.push_back(CDomain::createDomain()); 1434 vecDomRef.back()->domain_ref=domain_ref; 1435 axisDomainOrderTmp.push_back(2); 1436 } 1437 else ERROR("CField::solveGridReference(void)", 1438 << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 1604 vecDom.push_back(CDomain::get(domain_ref)); 1605 vecDomRef.push_back(CDomain::createDomain()); 1606 vecDomRef.back()->domain_ref=domain_ref; 1607 axisDomainOrderTmp.push_back(2); 1439 1608 } 1440 1441 if (!axis_ref.isEmpty()) 1609 else ERROR("CField::solveGridReference(void)", 1610 << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 1611 } 1612 1613 if (!axis_ref.isEmpty()) 1614 { 1615 if (CAxis::has(axis_ref)) 1442 1616 { 1443 if (CAxis::has(axis_ref)) 1444 { 1445 vecAxis.push_back(CAxis::get(axis_ref)); 1446 vecAxisRef.push_back(CAxis::createAxis()); 1447 vecAxisRef.back()->axis_ref=axis_ref; 1448 axisDomainOrderTmp.push_back(1); 1449 } 1450 else ERROR("CField::solveGridReference(void)", 1451 << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 1617 vecAxis.push_back(CAxis::get(axis_ref)); 1618 vecAxisRef.push_back(CAxis::createAxis()); 1619 vecAxisRef.back()->axis_ref=axis_ref; 1620 axisDomainOrderTmp.push_back(1); 1452 1621 } 1453 1454 if (!scalar_ref.isEmpty()) 1622 else ERROR("CField::solveGridReference(void)", 1623 << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 1624 } 1625 1626 if (!scalar_ref.isEmpty()) 1627 { 1628 if (CScalar::has(scalar_ref)) 1455 1629 { 1456 if (CScalar::has(scalar_ref)) 1457 { 1458 vecScalar.push_back(CScalar::get(scalar_ref)); 1459 vecScalarRef.push_back(CScalar::createScalar()); 1460 vecScalarRef.back()->scalar_ref=scalar_ref; 1461 axisDomainOrderTmp.push_back(0); 1462 } 1463 else ERROR("CField::solveGridReference(void)", 1464 << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 1630 vecScalar.push_back(CScalar::get(scalar_ref)); 1631 vecScalarRef.push_back(CScalar::createScalar()); 1632 vecScalarRef.back()->scalar_ref=scalar_ref; 1633 axisDomainOrderTmp.push_back(0); 1465 1634 } 1635 else ERROR("CField::solveGridReference(void)", 1636 << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 1637 } 1466 1638 1467 CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 1468 for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 1469 { 1470 axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 1471 } 1472 1473 // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 1474 StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 1475 if (CGrid::has(gridId)) this->grid = CGrid::get(gridId); 1476 else this->grid = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 1477 } 1478 else 1479 { 1480 if (CGrid::has(grid_ref)) this->grid = CGrid::get(grid_ref); 1481 else ERROR("CField::solveGridReference(void)", 1482 << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 1483 } 1484 } 1485 CATCH_DUMP_ATTR 1486 1487 void CField::solveGridDomainAxisRef(bool checkAtt) 1488 TRY 1489 { 1490 grid->solveDomainAxisRef(checkAtt); 1491 } 1492 CATCH_DUMP_ATTR 1493 1494 void CField::solveCheckMaskIndex(bool doSendingIndex) 1495 TRY 1496 { 1497 grid->checkMaskIndex(doSendingIndex); 1498 } 1499 CATCH_DUMP_ATTR 1500 1501 void CField::solveTransformedGrid() 1502 TRY 1503 { 1504 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 1505 { 1506 std::vector<CGrid*> grids; 1507 // Source grid 1508 grids.push_back(getDirectFieldReference()->grid); 1509 // Intermediate grids 1510 if (!grid_path.isEmpty()) 1511 { 1512 std::string gridId; 1513 size_t start = 0, end; 1514 1515 do 1516 { 1517 end = grid_path.getValue().find(',', start); 1518 if (end != std::string::npos) 1519 { 1520 gridId = grid_path.getValue().substr(start, end - start); 1521 start = end + 1; 1522 } 1523 else 1524 gridId = grid_path.getValue().substr(start); 1525 1526 if (!CGrid::has(gridId)) 1527 ERROR("void CField::solveTransformedGrid()", 1528 << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 1529 1530 grids.push_back(CGrid::get(gridId)); 1531 } 1532 while (end != std::string::npos); 1533 } 1534 // Destination grid 1535 grids.push_back(grid); 1536 1537 for (size_t i = 0, count = grids.size() - 1; i < count; ++i) 1538 { 1539 CGrid *gridSrc = grids[i]; 1540 CGrid *gridDest = grids[i + 1]; 1541 if (!gridDest->isTransformed()) 1542 gridDest->transformGrid(gridSrc); 1543 } 1544 } 1545 else if (grid && grid->hasTransform() && !grid->isTransformed()) 1546 { 1547 // Temporarily deactivate the self-transformation of grid 1548 // grid->transformGrid(grid); 1549 } 1550 } 1551 CATCH_DUMP_ATTR 1552 1553 void CField::solveGenerateGrid() 1554 TRY 1555 { 1556 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 1557 grid->completeGrid(getDirectFieldReference()->grid); 1558 else 1559 grid->completeGrid(); 1560 } 1561 CATCH_DUMP_ATTR 1562 1563 void CField::solveGridDomainAxisBaseRef() 1564 TRY 1565 { 1566 grid->solveDomainAxisRef(false); 1567 grid->solveDomainAxisBaseRef(); 1568 } 1569 CATCH_DUMP_ATTR 1570 1571 ///------------------------------------------------------------------- 1572 1573 template <> 1574 void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 1575 TRY 1576 { 1577 if (this->group_ref.isEmpty()) return; 1578 StdString gref = this->group_ref.getValue(); 1579 1580 if (!CFieldGroup::has(gref)) 1581 ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 1582 << "[ gref = " << gref << "]" 1583 << " invalid group name !"); 1584 1585 CFieldGroup* group = CFieldGroup::get(gref); 1586 CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 1587 owner->setAttributes(group); // inherite of attributes of group reference 1639 CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 1640 for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 1641 { 1642 axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 1643 } 1644 1645 // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 1646 StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 1647 if (CGrid::has(gridId)) this->grid_ = CGrid::get(gridId); 1648 else this->grid_ = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 1649 } 1650 else 1651 { 1652 if (CGrid::has(grid_ref)) this->grid_ = CGrid::get(grid_ref); 1653 else ERROR("CField::solveGridReference(void)", 1654 << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 1655 } 1656 } 1657 CATCH_DUMP_ATTR 1658 1659 void CField::solveGridDomainAxisRef(bool checkAtt) 1660 TRY 1661 { 1662 grid_->solveDomainAxisRef(checkAtt); 1663 } 1664 CATCH_DUMP_ATTR 1665 1666 void CField::solveCheckMaskIndex(bool doSendingIndex) 1667 TRY 1668 { 1669 grid_->checkMaskIndex(doSendingIndex); 1670 } 1671 CATCH_DUMP_ATTR 1672 1673 void CField::solveTransformedGrid() 1674 TRY 1675 { 1676 if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 1677 { 1678 std::vector<CGrid*> grids; 1679 // Source grid 1680 grids.push_back(getDirectFieldReference()->grid_); 1681 auto gridPath = getGridPath() ; 1682 grids.insert(grids.begin(), gridPath.begin(), gridPath.end()); 1683 1684 for (size_t i = 0, count = grids.size() - 1; i < count; ++i) 1685 { 1686 CGrid *gridSrc = grids[i]; 1687 CGrid *gridDest = grids[i + 1]; 1688 if (!gridDest->isTransformed()) gridDest->transformGrid(gridSrc); 1689 } 1690 } 1691 else if (grid_ && grid_->hasTransform() && !grid_->isTransformed()) 1692 { 1693 // Temporarily deactivate the self-transformation of grid 1694 // grid_->transformGrid(grid_); 1695 } 1696 } 1697 CATCH_DUMP_ATTR 1698 1699 void CField::solveGenerateGrid() 1700 TRY 1701 { 1702 if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 1703 grid_->completeGrid(getDirectFieldReference()->grid_); 1704 else grid_->completeGrid(); 1705 } 1706 CATCH_DUMP_ATTR 1707 1708 void CField::solveGridDomainAxisBaseRef() 1709 TRY 1710 { 1711 grid_->solveDomainAxisRef(false); 1712 grid_->solveDomainAxisBaseRef(); 1713 } 1714 CATCH_DUMP_ATTR 1715 1716 ///------------------------------------------------------------------- 1717 1718 template <> 1719 void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 1720 TRY 1721 { 1722 if (this->group_ref.isEmpty()) return; 1723 StdString gref = this->group_ref.getValue(); 1724 1725 if (!CFieldGroup::has(gref)) 1726 ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 1727 << "[ gref = " << gref << "]" 1728 << " invalid group name !"); 1729 1730 CFieldGroup* group = CFieldGroup::get(gref); 1731 CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 1732 owner->setAttributes(group); // inherite of attributes of group reference 1588 1733 1589 std::vector<CField*> allChildren = group->getAllChildren(); 1590 std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 1591 1592 for (; it != end; it++) 1593 { 1594 CField* child = *it; 1595 if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 1596 1597 } 1598 } 1599 CATCH_DUMP_ATTR 1600 1601 void CField::scaleFactorAddOffset(double scaleFactor, double addOffset) 1602 TRY 1603 { 1604 recvDataSrv = (recvDataSrv - addOffset) / scaleFactor; 1605 } 1606 CATCH_DUMP_ATTR 1607 1608 void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 1609 TRY 1610 { 1611 recvDataSrv = recvDataSrv * scaleFactor + addOffset; 1612 } 1613 CATCH_DUMP_ATTR 1614 1615 void CField::outputField(CArray<double,1>& fieldOut) 1616 TRY 1617 { 1618 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 1619 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 1620 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1621 { 1622 fieldOut(outIndexServer(idx)) = recvDataSrv(outIndexClient(idx)); 1623 } 1624 } 1625 CATCH_DUMP_ATTR 1626 1627 void CField::inputField(CArray<double,1>& fieldIn) 1628 TRY 1629 { 1630 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 1631 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 1632 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1633 { 1634 recvDataSrv(outIndexClient(idx)) = fieldIn(outIndexServer(idx)); 1635 } 1636 } 1637 CATCH_DUMP_ATTR 1638 1639 void CField::outputCompressedField(CArray<double,1>& fieldOut) 1640 TRY 1641 { 1642 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 1643 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 1644 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1645 { 1646 fieldOut((idx)) = recvDataSrv(outIndexClient(idx)); 1647 } 1648 } 1649 CATCH_DUMP_ATTR 1650 1651 ///------------------------------------------------------------------- 1652 1653 void CField::parse(xml::CXMLNode& node) 1654 TRY 1655 { 1656 string newContent ; 1657 SuperClass::parse(node); 1658 if (node.goToChildElement()) 1659 { 1660 do 1661 { 1662 if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 1663 else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 1664 } while (node.goToNextElement()); 1665 node.goToParentElement(); 1666 } 1667 if (node.getContent(newContent)) content=newContent ; 1668 } 1669 CATCH_DUMP_ATTR 1670 1671 /*! 1672 This function retrieves Id of corresponding domain_ref and axis_ref (if any) 1734 std::vector<CField*> allChildren = group->getAllChildren(); 1735 std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 1736 1737 for (; it != end; it++) 1738 { 1739 CField* child = *it; 1740 if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 1741 } 1742 } 1743 CATCH_DUMP_ATTR 1744 1745 void CField::scaleFactorAddOffset(double scaleFactor, double addOffset) 1746 TRY 1747 { 1748 recvDataSrv = (recvDataSrv - addOffset) / scaleFactor; 1749 } 1750 CATCH_DUMP_ATTR 1751 1752 void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 1753 TRY 1754 { 1755 recvDataSrv = recvDataSrv * scaleFactor + addOffset; 1756 } 1757 CATCH_DUMP_ATTR 1758 1759 void CField::outputField(CArray<double,1>& fieldOut) 1760 TRY 1761 { 1762 CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 1763 CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 1764 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1765 { 1766 fieldOut(outIndexServer(idx)) = recvDataSrv(outIndexClient(idx)); 1767 } 1768 } 1769 CATCH_DUMP_ATTR 1770 1771 void CField::inputField(CArray<double,1>& fieldIn) 1772 TRY 1773 { 1774 CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 1775 CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 1776 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1777 { 1778 recvDataSrv(outIndexClient(idx)) = fieldIn(outIndexServer(idx)); 1779 } 1780 } 1781 CATCH_DUMP_ATTR 1782 1783 void CField::outputCompressedField(CArray<double,1>& fieldOut) 1784 TRY 1785 { 1786 CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 1787 CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 1788 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1789 { 1790 fieldOut((idx)) = recvDataSrv(outIndexClient(idx)); 1791 } 1792 } 1793 CATCH_DUMP_ATTR 1794 1795 ///------------------------------------------------------------------- 1796 1797 void CField::parse(xml::CXMLNode& node) 1798 TRY 1799 { 1800 string newContent ; 1801 SuperClass::parse(node); 1802 if (node.goToChildElement()) 1803 { 1804 do 1805 { 1806 if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 1807 else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 1808 } while (node.goToNextElement()); 1809 node.goToParentElement(); 1810 } 1811 if (node.getContent(newContent)) content=newContent ; 1812 } 1813 CATCH_DUMP_ATTR 1814 1815 /*! 1816 This function retrieves Id of corresponding domain_ref and axis_ref (if any) 1673 1817 of a field. In some cases, only domain exists but axis doesn't 1674 1818 \return pair of Domain and Axis id 1819 */ 1820 const std::vector<StdString>& CField::getRefDomainAxisIds() 1821 TRY 1822 { 1823 CGrid* cgPtr = getRelGrid(); 1824 if (NULL != cgPtr) 1825 { 1826 std::vector<StdString>::iterator it; 1827 if (!domain_ref.isEmpty()) 1828 { 1829 std::vector<StdString> domainList = cgPtr->getDomainList(); 1830 it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue()); 1831 if (domainList.end() != it) domAxisScalarIds_[0] = *it; 1832 } 1833 1834 if (!axis_ref.isEmpty()) 1835 { 1836 std::vector<StdString> axisList = cgPtr->getAxisList(); 1837 it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue()); 1838 if (axisList.end() != it) domAxisScalarIds_[1] = *it; 1839 } 1840 1841 if (!scalar_ref.isEmpty()) 1842 { 1843 std::vector<StdString> scalarList = cgPtr->getScalarList(); 1844 it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue()); 1845 if (scalarList.end() != it) domAxisScalarIds_[2] = *it; 1846 } 1847 } 1848 return (domAxisScalarIds_); 1849 } 1850 CATCH_DUMP_ATTR 1851 1852 CVariable* CField::addVariable(const string& id) 1853 TRY 1854 { 1855 return vVariableGroup->createChild(id); 1856 } 1857 CATCH 1858 1859 CVariableGroup* CField::addVariableGroup(const string& id) 1860 TRY 1861 { 1862 return vVariableGroup->createChildGroup(id); 1863 } 1864 CATCH 1865 1866 void CField::setContextClient(CContextClient* contextClient) 1867 TRY 1868 { 1869 CContext* context = CContext::getCurrent(); 1870 client = contextClient; 1871 1872 // A grid is sent by a client (both for read or write) or by primary server (write only) 1873 if (context->getServiceType()==CServicesManager::GATHERER) 1874 { 1875 if (file->mode.isEmpty() || (!file->mode.isEmpty() && file->mode == CFile::mode_attr::write)) 1876 grid_->setContextClient(contextClient); 1877 } 1878 else if (context->getServiceType()==CServicesManager::CLIENT) 1879 grid_->setContextClient(contextClient); 1880 } 1881 CATCH_DUMP_ATTR 1882 1883 CContextClient* CField::getContextClient() 1884 TRY 1885 { 1886 return client; 1887 } 1888 CATCH 1889 1890 void CField::sendAddAllVariables(CContextClient* client) 1891 TRY 1892 { 1893 std::vector<CVariable*> allVar = getAllVariables(); 1894 std::vector<CVariable*>::const_iterator it = allVar.begin(); 1895 std::vector<CVariable*>::const_iterator itE = allVar.end(); 1896 1897 for (; it != itE; ++it) 1898 { 1899 this->sendAddVariable((*it)->getId(), client); 1900 (*it)->sendAllAttributesToServer(client); 1901 (*it)->sendValue(client); 1902 } 1903 } 1904 CATCH_DUMP_ATTR 1905 1906 /*! 1907 * Send all Attributes to server. This method is overloaded, since only grid_ref attribute 1908 * must be sent to server and not domain_ref/axis_ref/scalar_ref. 1675 1909 */ 1676 const std::vector<StdString>& CField::getRefDomainAxisIds()1677 TRY1678 {1679 CGrid* cgPtr = getRelGrid();1680 if (NULL != cgPtr)1681 {1682 std::vector<StdString>::iterator it;1683 if (!domain_ref.isEmpty())1684 {1685 std::vector<StdString> domainList = cgPtr->getDomainList();1686 it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());1687 if (domainList.end() != it) domAxisScalarIds_[0] = *it;1688 }1689 1690 if (!axis_ref.isEmpty())1691 {1692 std::vector<StdString> axisList = cgPtr->getAxisList();1693 it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());1694 if (axisList.end() != it) domAxisScalarIds_[1] = *it;1695 }1696 1697 if (!scalar_ref.isEmpty())1698 {1699 std::vector<StdString> scalarList = cgPtr->getScalarList();1700 it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue());1701 if (scalarList.end() != it) domAxisScalarIds_[2] = *it;1702 }1703 }1704 return (domAxisScalarIds_);1705 }1706 CATCH_DUMP_ATTR1707 1708 CVariable* CField::addVariable(const string& id)1709 TRY1710 {1711 return vVariableGroup->createChild(id);1712 }1713 CATCH1714 1715 CVariableGroup* CField::addVariableGroup(const string& id)1716 TRY1717 {1718 return vVariableGroup->createChildGroup(id);1719 }1720 CATCH1721 1722 void CField::setContextClient(CContextClient* contextClient)1723 TRY1724 {1725 CContext* context = CContext::getCurrent();1726 client = contextClient;1727 1728 // A grid is sent by a client (both for read or write) or by primary server (write only)1729 if (context->getServiceType()==CServicesManager::GATHERER)1730 {1731 if (file->mode.isEmpty() || (!file->mode.isEmpty() && file->mode == CFile::mode_attr::write))1732 grid->setContextClient(contextClient);1733 }1734 else if (context->getServiceType()==CServicesManager::CLIENT)1735 grid->setContextClient(contextClient);1736 }1737 CATCH_DUMP_ATTR1738 1739 CContextClient* CField::getContextClient()1740 TRY1741 {1742 return client;1743 }1744 CATCH1745 1746 void CField::sendAddAllVariables(CContextClient* client)1747 TRY1748 {1749 std::vector<CVariable*> allVar = getAllVariables();1750 std::vector<CVariable*>::const_iterator it = allVar.begin();1751 std::vector<CVariable*>::const_iterator itE = allVar.end();1752 1753 for (; it != itE; ++it)1754 {1755 this->sendAddVariable((*it)->getId(), client);1756 (*it)->sendAllAttributesToServer(client);1757 (*it)->sendValue(client);1758 }1759 }1760 CATCH_DUMP_ATTR1761 1762 /*!1763 * Send all Attributes to server. This method is overloaded, since only grid_ref attribute1764 * must be sent to server and not domain_ref/axis_ref/scalar_ref.1765 */1766 1910 1767 1768 1769 1770 1771 1772 grid_ref=grid->getId() ;1773 1774 1775 1776 1777 1778 1911 void CField::sendAllAttributesToServer(CContextClient* client) 1912 TRY 1913 { 1914 if (grid_ref.isEmpty()) 1915 { 1916 grid_ref=grid_->getId() ; 1917 SuperClass::sendAllAttributesToServer(client) ; 1918 grid_ref.reset(); 1919 } 1920 else SuperClass::sendAllAttributesToServer(client) ; 1921 } 1922 CATCH_DUMP_ATTR 1779 1923 1780 void CField::sendAddVariable(const string& id, CContextClient* client) 1781 TRY 1782 { 1783 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 1784 } 1785 CATCH_DUMP_ATTR 1786 1787 void CField::sendAddVariableGroup(const string& id, CContextClient* client) 1788 TRY 1789 { 1790 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 1791 } 1792 CATCH_DUMP_ATTR 1793 1794 void CField::recvAddVariable(CEventServer& event) 1795 TRY 1796 { 1797 1798 CBufferIn* buffer = event.subEvents.begin()->buffer; 1799 string id; 1800 *buffer >> id; 1801 get(id)->recvAddVariable(*buffer); 1802 } 1803 CATCH 1804 1805 void CField::recvAddVariable(CBufferIn& buffer) 1806 TRY 1807 { 1808 string id; 1809 buffer >> id; 1810 addVariable(id); 1811 } 1812 CATCH_DUMP_ATTR 1813 1814 void CField::recvAddVariableGroup(CEventServer& event) 1815 TRY 1816 { 1817 1818 CBufferIn* buffer = event.subEvents.begin()->buffer; 1819 string id; 1820 *buffer >> id; 1821 get(id)->recvAddVariableGroup(*buffer); 1822 } 1823 CATCH 1824 1825 void CField::recvAddVariableGroup(CBufferIn& buffer) 1826 TRY 1827 { 1828 string id; 1829 buffer >> id; 1830 addVariableGroup(id); 1831 } 1832 CATCH_DUMP_ATTR 1833 1834 /*! 1835 * Check on freq_off and freq_op attributes. 1836 */ 1837 void CField::checkTimeAttributes(CDuration* freqOp) 1838 TRY 1839 { 1840 bool isFieldRead = file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read; 1841 bool isFieldWrite = file && ( file->mode.isEmpty() || file->mode == CFile::mode_attr::write); 1842 if (isFieldRead && !(operation.getValue() == "instant" || operation.getValue() == "once") ) 1843 ERROR("void CField::checkTimeAttributes(void)", 1844 << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 1845 << "Currently only \"instant\" is supported for fields read from file.") 1846 1847 if (freq_op.isEmpty()) 1848 { 1849 if (operation.getValue() == "instant") 1850 { 1851 if (isFieldRead || isFieldWrite) freq_op.setValue(file->output_freq.getValue()); 1852 else freq_op=*freqOp ; 1853 } 1854 else 1855 freq_op.setValue(TimeStep); 1856 } 1857 if (freq_offset.isEmpty()) 1858 freq_offset.setValue(isFieldRead ? NoneDu : (freq_op.getValue() - TimeStep)); 1859 } 1860 CATCH_DUMP_ATTR 1861 1862 /*! 1863 * Returns string arithmetic expression associated to the field. 1864 * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 1865 */ 1866 const string& CField::getExpression(void) 1867 TRY 1868 { 1869 if (!expr.isEmpty() && content.empty()) 1870 { 1871 content = expr; 1872 expr.reset(); 1873 } 1874 1875 return content; 1876 } 1877 CATCH_DUMP_ATTR 1878 1879 bool CField::hasExpression(void) const 1880 TRY 1881 { 1882 return (!expr.isEmpty() || !content.empty()); 1883 } 1884 CATCH 1885 1886 bool CField::hasGridMask(void) const 1887 TRY 1888 { 1889 return (this->grid->hasMask()); 1890 } 1891 CATCH 1892 1893 DEFINE_REF_FUNC(Field,field) 1924 void CField::sendAddVariable(const string& id, CContextClient* client) 1925 TRY 1926 { 1927 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 1928 } 1929 CATCH_DUMP_ATTR 1930 1931 void CField::sendAddVariableGroup(const string& id, CContextClient* client) 1932 TRY 1933 { 1934 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 1935 } 1936 CATCH_DUMP_ATTR 1937 1938 void CField::recvAddVariable(CEventServer& event) 1939 TRY 1940 { 1941 CBufferIn* buffer = event.subEvents.begin()->buffer; 1942 string id; 1943 *buffer >> id; 1944 get(id)->recvAddVariable(*buffer); 1945 } 1946 CATCH 1947 1948 void CField::recvAddVariable(CBufferIn& buffer) 1949 TRY 1950 { 1951 string id; 1952 buffer >> id; 1953 addVariable(id); 1954 } 1955 CATCH_DUMP_ATTR 1956 1957 void CField::recvAddVariableGroup(CEventServer& event) 1958 TRY 1959 { 1960 CBufferIn* buffer = event.subEvents.begin()->buffer; 1961 string id; 1962 *buffer >> id; 1963 get(id)->recvAddVariableGroup(*buffer); 1964 } 1965 CATCH 1966 1967 void CField::recvAddVariableGroup(CBufferIn& buffer) 1968 TRY 1969 { 1970 string id; 1971 buffer >> id; 1972 addVariableGroup(id); 1973 } 1974 CATCH_DUMP_ATTR 1975 1976 /*! 1977 * Check on freq_off and freq_op attributes. 1978 */ 1979 void CField::checkTimeAttributes(CDuration* freqOp) 1980 TRY 1981 { 1982 bool isFieldRead = file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read; 1983 bool isFieldWrite = file && ( file->mode.isEmpty() || file->mode == CFile::mode_attr::write); 1984 if (isFieldRead && !(operation.getValue() == "instant" || operation.getValue() == "once") ) 1985 ERROR("void CField::checkTimeAttributes(void)", 1986 << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 1987 << "Currently only \"instant\" is supported for fields read from file.") 1988 1989 if (freq_op.isEmpty()) 1990 { 1991 if (operation.getValue() == "instant") 1992 { 1993 if (isFieldRead || isFieldWrite) freq_op.setValue(file->output_freq.getValue()); 1994 else freq_op=*freqOp ; 1995 } 1996 else freq_op.setValue(TimeStep); 1997 } 1998 if (freq_offset.isEmpty()) freq_offset.setValue(isFieldRead ? NoneDu : (freq_op.getValue() - TimeStep)); 1999 } 2000 CATCH_DUMP_ATTR 2001 2002 /*! 2003 * Returns string arithmetic expression associated to the field. 2004 * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 2005 */ 2006 const string& CField::getExpression(void) 2007 TRY 2008 { 2009 if (!expr.isEmpty() && content.empty()) 2010 { 2011 content = expr; 2012 expr.reset(); 2013 } 2014 2015 return content; 2016 } 2017 CATCH_DUMP_ATTR 2018 2019 bool CField::hasExpression(void) const 2020 TRY 2021 { 2022 return (!expr.isEmpty() || !content.empty()); 2023 } 2024 CATCH 2025 2026 bool CField::hasGridMask(void) const 2027 TRY 2028 { 2029 return (this->grid_->hasMask()); 2030 } 2031 CATCH 2032 2033 DEFINE_REF_FUNC(Field,field) 1894 2034 } // namespace xios -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.hpp
r1853 r1869 17 17 #include "variable.hpp" 18 18 #include "context_client.hpp" 19 #include "pass_through_filter.hpp" 20 #include "temporal_filter.hpp" 21 19 22 20 23 … … 28 31 29 32 class CFile; 33 class CCouplerIn ; 34 class CCouplerOut ; 30 35 class CGrid; 31 36 class CContext; … … 47 52 48 53 class CContextClient ; 54 49 55 ///-------------------------------------------------------------- 50 56 class CField … … 141 147 142 148 void buildFilterGraph(CGarbageCollector& gc, bool enableOutput); 149 150 bool buildWorkflowGraph(CGarbageCollector& gc) ; 151 bool buildWorkflowGraphDone_ = false ; 152 143 153 size_t getGlobalWrittenSize(void) ; 144 154 … … 211 221 212 222 bool hasGridMask(void) const; 223 CGrid* getGrid(void) { return grid_; } 224 225 void connectToFileServer(CGarbageCollector& gc) ; 226 void computeGridIndexToFileServer(void) ; 227 private: 228 std::vector<CGrid*> getGridPath(void) ; 213 229 214 230 public: … … 216 232 CVariableGroup* vVariableGroup; 217 233 218 CGrid* grid ;234 CGrid* grid_=nullptr; 219 235 CFile* file; 236 237 CFile* fileIn_ = nullptr ; //<! pointer to input related file 238 bool hasFileIn(void) { fileIn_==nullptr ? false : true ;} 239 CFile* getFileIn(void) {return fileIn_;} 240 void setFileIn(CFile* fileIn) { fileIn_ = fileIn ;} 241 void unsetFileIn(void) { fileIn_ = nullptr ;} 242 243 CFile* fileOut_ = nullptr ; //<! pointer to output related file 244 bool hasFileOut(void) { fileOut_==nullptr ? false : true ;} 245 CFile* getFileOut(void) {return fileOut_;} 246 void setFileOut(CFile* fileOut) { fileOut_ = fileOut ;} 247 void unsetFileOut(void) { fileOut_ = nullptr ;} 248 249 CCouplerIn* couplerIn_ = nullptr ; //<!pointer to input related coupler 250 bool hasCouplerIn(void) { couplerIn_==nullptr ? false : true ;} 251 CCouplerIn* getCouplerIn(void) {return couplerIn_;} 252 void setCouplerIn(CCouplerIn* couplerIn) { couplerIn_ = couplerIn ;} 253 void unsetCouplerIn(void) { couplerIn_ = nullptr ;} 254 255 CCouplerOut* couplerOut_ = nullptr ; //<!pointer to output related coupler 256 bool hasCouplerOut(void) { couplerOut_==nullptr ? false : true ;} 257 CCouplerOut* getCouplerOut(void) {return couplerOut_;} 258 void setCouplerOut(CCouplerOut* couplerOut) { couplerOut_ = couplerOut ;} 259 void unsetCouplerOut(void) { couplerOut_ = nullptr ;} 260 261 bool modelIn_ = false ; //<! field can be received from model == true 262 bool getModelIn(void) { return modelIn_ ;} 263 void setModelIn(void) { modelIn_ = true ;} 264 void unsetModelIn(void) { modelIn_ = false ;} 265 266 bool modelOut_ = false ; //<! field can be retrieve to model == true 267 bool getModelOut(void) { return modelOut_ ;} 268 void setModelOut(void) { modelOut_ = true ;} 269 void unsetModelOut(void) { modelOut_ = false ;} 220 270 221 271 CDuration freq_operation_srv, freq_write_srv; … … 246 296 247 297 DECLARE_REF_FUNC(Field,field) 248 298 249 299 private: 250 300 CContextClient* client; … … 256 306 bool nstepMaxRead; 257 307 308 private: 309 //! define if the field is part of the active workflow. It will be tagged to true when CField::buildWorkflowGraph is successfull 310 bool workflowEnabled_ = false ; 311 public: 312 /*! workflowEnabled_ public accessor 313 * \return Value of workflowEnabled_ */ 314 bool getWorkflowEnabled(void) { return workflowEnabled_; } 315 316 258 317 private: 318 259 319 //! The type of operation attached to the field 260 320 func::CFunctor::ETimeType operationTimeType; 261 321 322 //! The output pin of the input filter of the field 323 std::shared_ptr<CPassThroughFilter> inputFilter; 324 325 //! The self temporal data filter 326 std::shared_ptr<CTemporalFilter> selfTemporalDataFilter ; 327 262 328 //! The output pin of the filter providing the instant data for the field 263 329 std::shared_ptr<COutputPin> instantDataFilter; 330 264 331 //! The output pin of the filters providing the result of the field's temporal operation 265 332 std::map<CDuration, std::shared_ptr<COutputPin>, DurationFakeLessComparator> temporalDataFilters; 333 266 334 //! The output pin of the filter providing the instant data for self references 267 std::shared_ptr<COutputPin> selfReferenceFilter; 335 std::shared_ptr<COutputPin> selfReferenceFilter; // probably redondant with inputFilter 336 268 337 //! The source filter for data provided by the client 269 338 std::shared_ptr<CSourceFilter> clientSourceFilter; 339 270 340 //! The source filter for data provided by the server 271 341 std::shared_ptr<CSourceFilter> serverSourceFilter; 342 272 343 //! The terminal filter which stores the instant data 273 344 std::shared_ptr<CStoreFilter> storeFilter; 345 274 346 //! The terminal filter which writes the data to file 275 347 std::shared_ptr<CFileWriterFilter> fileWriterFilter; 348 276 349 //! The terminal filter which writes data to file 277 350 std::shared_ptr<CFileServerWriterFilter> fileServerWriterFilter; -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/file.cpp
r1853 r1869 145 145 TRY 146 146 { 147 if (!this->enabledFields.empty()) 148 return (this->enabledFields); 149 150 const int _outputlevel = 151 (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel; 147 if (!this->enabledFields.empty()) return (this->enabledFields); 148 149 const int _outputlevel = (!output_level.isEmpty()) ? output_level.getValue() : default_outputlevel; 152 150 std::vector<CField*>::iterator it; 153 151 this->enabledFields = this->getAllFields(); … … 176 174 177 175 newEnabledFields.push_back(*it); 178 // Le champ est finalement actif, on y ajoute la rfrence au champ de base.179 (*it)->setRelFile(CFile::get(this));180 176 } 181 177 enabledFields = newEnabledFields; … … 256 252 { 257 253 CField* field = *it; 258 std::vector<CAxis*> vecAxis = field->g rid->getAxis();254 std::vector<CAxis*> vecAxis = field->getGrid()->getAxis(); 259 255 for (size_t i = 0; i < vecAxis.size(); ++i) 260 256 setAxis.insert(vecAxis[i]->getAxisOutputName()); 261 std::vector<CDomain*> vecDomains = field->g rid->getDomains();257 std::vector<CDomain*> vecDomains = field->getGrid()->getDomains(); 262 258 for (size_t i = 0; i < vecDomains.size(); ++i) 263 259 setDomains.insert(vecDomains[i]->getDomainOutputName()); … … 300 296 { 301 297 CField* field = *it; 302 bool nullGrid = ( 0 == field->grid);303 allZoneEmpty &= nullGrid ? false : !field->g rid->doGridHaveDataToWrite();298 bool nullGrid = (nullptr == field->getGrid()); 299 allZoneEmpty &= nullGrid ? false : !field->getGrid()->doGridHaveDataToWrite(); 304 300 } 305 301 -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp
r1853 r1869 90 90 //--------------------------------------------------------------- 91 91 92 StdSize CGrid::getDataSize(void) const92 StdSize CGrid::getDataSize(void) 93 93 TRY 94 94 { … … 96 96 if (!isScalarGrid()) 97 97 { 98 std::vector<int> dataNindex = clientDistribution_->getDataNIndex();98 std::vector<int> dataNindex = getDistributionClient()->getDataNIndex(); 99 99 for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i]; 100 100 } … … 634 634 635 635 size_t nbWritten = 0, indGlo; 636 CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();636 CDistributionClient::GlobalLocalDataMap& globalDataIndex = getDistributionClient()->getGlobalDataIndexOnClient(); 637 637 CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(), 638 638 ite = globalDataIndex.end(), it; … … 677 677 CATCH_DUMP_ATTR 678 678 679 680 681 /*! 682 Compute the global index of grid to send to server as well as the connected server of the current client. 683 First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know 684 their global index. We can have a map of global index of grid and local index that each client holds 685 Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s) 686 of the current client. 687 */ 688 void CGrid::computeGridIndexToFileServer(CContextClient* client) 689 { 690 if (isScalarGrid()) 691 { 692 computeClientIndexScalarGrid(); 693 computeConnectedClientsScalarGrid(client); 694 } 695 else 696 { 697 computeClientIndex(); 698 computeConnectedClients(client); 699 } 700 701 // compute indices for client/server transfer for domain 702 for (const auto& domainId : domList_) CDomain::get(domainId)->computeConnectedClients(client); 703 704 705 // compute indices for client/server transfer for axis 706 std::vector<CAxis*> axisList = this->getAxis(); 707 std::vector<int> axisPosInGrid ; 708 // compute axis position in grid 709 int idx=0 ; 710 for (int i = 0 ; i < axis_domain_order.numElements(); ++i) 711 { 712 if (axis_domain_order(i) == 0) idx += 0 ; 713 else if (axis_domain_order(i) == 1) { axisPosInGrid.push_back(idx) ; ++idx; } 714 else if (axis_domain_order(i) == 2) idx += 2; 715 } 716 for(int i=0 ; i<axisList.size(); i++) axisList[i] -> computeConnectedClients(client, getGlobalDimension(),axisPositionInGrid_[i]) ; 717 } 679 718 //--------------------------------------------------------------- 719 720 721 void CGrid::computeClientDistribution(void) 722 { 723 if (computeClientDistribution_done_) return ; 724 else computeClientDistribution_done_ = true ; 725 726 CContext* context = CContext::getCurrent(); 727 int rank = context-> getIntraCommRank(); 728 clientDistribution_ = new CDistributionClient(rank, this); 729 } 730 731 void CGrid::computeStoreIndex_client(void) 732 { 733 if (computeStoreIndex_client_done_) return ; 734 else computeStoreIndex_client_done_ = true ; 735 if (isScalarGrid()) 736 { 737 storeIndex_client_.resize(1); 738 storeIndex_client_(0) = 0; 739 } 740 else 741 { 742 CDistributionClient* clientDistribution = getDistributionClient() ; 743 const std::vector<int>& localDataIndex = clientDistribution->getLocalDataIndexOnClient() ; 744 int nbStoreIndex = localDataIndex.size() ; 745 storeIndex_client_.resize(nbStoreIndex); 746 for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = localDataIndex[idx]; 747 } 748 } 749 750 void CGrid::computeStoreMask_client(void) 751 { 752 if (computeStoreMask_client_done_) return ; 753 else computeStoreMask_client_done_ = true ; 754 if (isScalarGrid()) 755 { 756 storeMask_client_.resize(1); 757 storeMask_client_(0) = true; 758 } 759 else 760 { 761 CDistributionClient* clientDistribution = getDistributionClient() ; 762 const std::vector<bool>& localMaskIndex = clientDistribution->getLocalMaskIndexOnClient() ; 763 int nbMaskIndex = localMaskIndex.size() ; 764 storeMask_client_.resize(nbMaskIndex); 765 for (int idx = 0; idx < nbMaskIndex; ++idx) storeMask_client_(idx) = localMaskIndex[idx]; 766 } 767 } 680 768 681 769 /* … … 688 776 TRY 689 777 { 778 if (computeClientIndex_done_) return ; 779 690 780 CContext* context = CContext::getCurrent(); 691 692 CContextClient* client = context->client; 693 int rank = client->clientRank; 694 695 clientDistribution_ = new CDistributionClient(rank, this); 781 int rank = context-> getIntraCommRank(); 782 783 auto clientDistribution = getDistributionClient(); 696 784 // Get local data index on client 697 int nbStoreIndex = clientDistribution _->getLocalDataIndexOnClient().size();698 int nbStoreGridMask = clientDistribution _->getLocalMaskIndexOnClient().size();785 int nbStoreIndex = clientDistribution->getLocalDataIndexOnClient().size(); 786 int nbStoreGridMask = clientDistribution->getLocalMaskIndexOnClient().size(); 699 787 // nbStoreGridMask = nbStoreIndex if grid mask is defined, and 0 otherwise 700 788 storeIndex_client_.resize(nbStoreIndex); 701 789 storeMask_client_.resize(nbStoreGridMask); 702 for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = (clientDistribution _->getLocalDataIndexOnClient())[idx];703 for (int idx = 0; idx < nbStoreGridMask; ++idx) storeMask_client_(idx) = (clientDistribution _->getLocalMaskIndexOnClient())[idx];704 705 if (0 == serverDistribution_) isDataDistributed_= clientDistribution _->isDataDistributed();790 for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = (clientDistribution->getLocalDataIndexOnClient())[idx]; 791 for (int idx = 0; idx < nbStoreGridMask; ++idx) storeMask_client_(idx) = (clientDistribution->getLocalMaskIndexOnClient())[idx]; 792 793 if (0 == serverDistribution_) isDataDistributed_= clientDistribution->isDataDistributed(); 706 794 else 707 795 { 708 796 // Mapping global index received from clients to the storeIndex_client_ 709 CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution _->getGlobalDataIndexOnClient();797 CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution->getGlobalDataIndexOnClient(); 710 798 CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end(); 711 799 map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient_.begin(), … … 746 834 } 747 835 } 836 computeClientIndex_done_ = true ; 748 837 } 749 838 CATCH_DUMP_ATTR … … 752 841 Compute connected receivers and indexes to be sent to these receivers. 753 842 */ 754 void CGrid::computeConnectedClients() 755 TRY 756 { 843 void CGrid::computeConnectedClients(CContextClient* client) 844 TRY 845 { 846 if (computeConnectedClients_done_.count(client)!=0) return ; 847 757 848 CContext* context = CContext::getCurrent(); 758 849 759 850 set<int> listReceiverSize ; 760 for (auto it=clients.begin(); it!=clients.end(); ++it) 851 int receiverSize = client->serverSize; 852 853 if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 761 854 { 762 763 CContextClient* client = *it ; 764 765 int receiverSize = client->serverSize; 766 767 if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 855 listReceiverSize.insert(receiverSize) ; 856 if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 768 857 { 769 listReceiverSize.insert(receiverSize) ; 770 if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 771 { 772 // delete corresponding map in case of recompute, probably because a grid could has been modifiedd 773 // by a transformation 774 connectedServerRank_.erase(receiverSize); 775 connectedDataSize_.erase(receiverSize); 776 globalIndexOnServer_.erase(receiverSize); 777 nbSenders_.erase(receiverSize); 778 } 779 780 if (!doGridHaveDataDistributed(client)) 781 { 782 if (client->isServerLeader()) 858 // delete corresponding map in case of recompute, probably because a grid could has been modifiedd 859 // by a transformation 860 connectedServerRank_.erase(receiverSize); 861 connectedDataSize_.erase(receiverSize); 862 globalIndexOnServer_.erase(receiverSize); 863 nbSenders_.erase(receiverSize); 864 } 865 866 if (!doGridHaveDataDistributed(client)) 867 { 868 if (client->isServerLeader()) 869 { 870 size_t ssize = getDistributionClient()->getLocalDataIndexOnClient().size(); 871 const std::list<int>& ranks = client->getRanksServerLeader(); 872 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 783 873 { 784 size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size(); 785 const std::list<int>& ranks = client->getRanksServerLeader(); 786 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 787 { 788 connectedServerRank_[receiverSize].push_back(*itRank); 789 connectedDataSize_[receiverSize][*itRank] = ssize; 790 } 874 connectedServerRank_[receiverSize].push_back(*itRank); 875 connectedDataSize_[receiverSize][*itRank] = ssize; 791 876 } 792 return; 793 } 794 795 // Compute mapping between client and server 796 std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 797 CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 798 std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 877 } 878 return; 879 } 880 881 // Compute mapping between client and server 882 std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 883 CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 884 std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 799 885 client->clientRank, 800 886 client->clientSize, … … 802 888 getDistributedDimension()); 803 889 804 // Even if servers have no index, they must received something from client 805 // We only use several client to send "empty" message to these servers 806 std::list<int> serverZeroIndexLeader; 807 std::list<int> serverZeroIndexNotLeader; 808 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 809 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 810 *it = serverZeroIndex[*it]; 811 812 if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end()) 813 computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]); 814 815 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer(); 816 CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap; 817 CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap; 818 itbGlobalMap = globalIndexOnServer_[receiverSize].begin(); 819 iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 820 821 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 890 // Even if servers have no index, they must received something from client 891 // We only use several client to send "empty" message to these servers 892 std::list<int> serverZeroIndexLeader; 893 std::list<int> serverZeroIndexNotLeader; 894 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 895 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 896 *it = serverZeroIndex[*it]; 897 898 if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end()) 899 computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]); 900 901 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getDistributionClient()->getGlobalLocalDataSendToServer(); 902 CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap; 903 CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap; 904 itbGlobalMap = globalIndexOnServer_[receiverSize].begin(); 905 iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 906 907 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 908 { 909 int serverRank = itGlobalMap->first; 910 int indexSize = itGlobalMap->second.size(); 911 const std::vector<size_t>& indexVec = itGlobalMap->second; 912 for (int idx = 0; idx < indexSize; ++idx) 822 913 { 823 int serverRank = itGlobalMap->first; 824 int indexSize = itGlobalMap->second.size(); 825 const std::vector<size_t>& indexVec = itGlobalMap->second; 826 for (int idx = 0; idx < indexSize; ++idx) 827 { 828 itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]); 829 if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap) 830 { 831 if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank)) 832 connectedDataSize_[receiverSize][serverRank] = 1; 833 else 834 ++connectedDataSize_[receiverSize][serverRank]; 835 } 836 } 914 itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]); 915 if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap) 916 { 917 if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank)) 918 connectedDataSize_[receiverSize][serverRank] = 1; 919 else 920 ++connectedDataSize_[receiverSize][serverRank]; 921 } 837 922 } 838 839 // Connected servers which really have index840 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {841 connectedServerRank_[receiverSize].push_back(itGlobalMap->first);842 }843 844 // Connected servers which have no index at all845 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)846 connectedServerRank_[receiverSize].push_back(*it);847 848 // Even if a client has no index, it must connect to at least one server and849 // send an "empty" data to this server850 if (connectedServerRank_[receiverSize].empty())851 connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);852 853 // Now check if all servers have data to receive. If not, master client will send empty data.854 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive.855 std::vector<int> counts (client->clientSize);856 std::vector<int> displs (client->clientSize);857 displs[0] = 0;858 int localCount = connectedServerRank_[receiverSize].size() ;859 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ;860 for (int i = 0; i < client->clientSize-1; ++i)861 {862 displs[i+1] = displs[i] + counts[i];863 }864 std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]);865 MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm);866 867 if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0))868 {869 std::vector<bool> isSrvConnected (receiverSize, false);870 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true;871 for (int i = 0; i < receiverSize; ++i)872 {873 if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i);874 }875 }876 877 nbSenders_[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);878 923 } 924 925 // Connected servers which really have index 926 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 927 connectedServerRank_[receiverSize].push_back(itGlobalMap->first); 928 929 // Connected servers which have no index at all 930 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 931 connectedServerRank_[receiverSize].push_back(*it); 932 933 // Even if a client has no index, it must connect to at least one server and 934 // send an "empty" data to this server 935 if (connectedServerRank_[receiverSize].empty()) 936 connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize); 937 938 // Now check if all servers have data to receive. If not, master client will send empty data. 939 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 940 std::vector<int> counts (client->clientSize); 941 std::vector<int> displs (client->clientSize); 942 displs[0] = 0; 943 int localCount = connectedServerRank_[receiverSize].size() ; 944 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 945 for (int i = 0; i < client->clientSize-1; ++i) displs[i+1] = displs[i] + counts[i]; 946 std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]); 947 MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 948 949 if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0)) 950 { 951 std::vector<bool> isSrvConnected (receiverSize, false); 952 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 953 for (int i = 0; i < receiverSize; ++i) if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i); 954 } 955 956 nbSenders_[receiverSize] = CClientServerMapping::computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]); 879 957 } 958 computeConnectedClients_done_.insert(client) ; 880 959 } 881 960 CATCH_DUMP_ATTR … … 888 967 of the current client. 889 968 */ 969 // ym obsolete : to be removed.... 890 970 void CGrid::computeIndex(void) 891 971 TRY 892 972 { 973 // old interface 893 974 CContext* context = CContext::getCurrent(); 894 975 if (isScalarGrid()) … … 897 978 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 898 979 { 899 computeConnectedClientsScalarGrid();980 // ym computeConnectedClientsScalarGrid(); 900 981 } 901 982 } … … 905 986 if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 906 987 { 907 computeConnectedClients();988 //computeConnectedClients(); 908 989 } 909 990 } … … 1178 1259 } 1179 1260 1180 grid->solveDomainAxisRefInheritance(true);1261 // grid->solveElementsRefInheritance(true); 1181 1262 1182 1263 return grid; … … 1310 1391 //---------------------------------------------------------------- 1311 1392 1312 void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const 1313 TRY 1314 { 1315 const StdSize size = storeIndex_client_.numElements(); 1393 void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) 1394 TRY 1395 { 1396 auto& storeIndex_client = getStoreIndex_client() ; 1397 const StdSize size = storeIndex_client.numElements(); 1316 1398 1317 1399 stored.resize(size); 1318 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client _(i)];1400 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 1319 1401 } 1320 1402 CATCH 1321 1403 1322 void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const 1323 TRY 1324 { 1325 const StdSize size = storeIndex_client_.numElements(); 1326 1327 for(StdSize i = 0; i < size; i++) data[storeIndex_client_(i)] = stored(i); 1404 void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) 1405 TRY 1406 { 1407 auto& storeIndex_client=getStoreIndex_client() ; 1408 const StdSize size = storeIndex_client.numElements(); 1409 1410 for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i); 1328 1411 } 1329 1412 CATCH 1330 1413 1331 void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) const 1332 { 1333 const StdSize size = storeIndex_client_.numElements(); 1414 void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) 1415 { 1416 auto& storeIndex_client=getStoreIndex_client() ; 1417 auto& storeMask_client=getStoreMask_client() ; 1418 1419 const StdSize size = storeIndex_client.numElements(); 1334 1420 stored.resize(size); 1335 1421 const double nanValue = std::numeric_limits<double>::quiet_NaN(); 1336 1422 1337 if (storeMask_client _.numElements() != 0)1338 for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client _(i)) ? data[storeIndex_client_(i)] : nanValue;1423 if (storeMask_client.numElements() != 0) 1424 for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client(i)) ? data[storeIndex_client(i)] : nanValue; 1339 1425 else 1340 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client _(i)];1341 } 1342 1343 void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const1344 TRY 1345 { 1346 const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient();1426 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 1427 } 1428 1429 void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) 1430 TRY 1431 { 1432 const std::vector<int>& localMaskedDataIndex = getDistributionClient()->getLocalMaskedDataIndexOnClient(); 1347 1433 const int size = localMaskedDataIndex.size(); 1348 1434 for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i]; … … 1353 1439 TRY 1354 1440 { 1441 if (computeClientIndexScalarGrid_done_) return ; 1442 1355 1443 CContext* context = CContext::getCurrent(); 1356 1444 { 1357 1445 int rank = context->intraCommRank_; 1358 1446 1359 clientDistribution_ = new CDistributionClient(rank, this);1447 auto clientDistribution = getDistributionClient(); 1360 1448 1361 1449 storeIndex_client_.resize(1); … … 1382 1470 } 1383 1471 } 1384 } 1385 CATCH_DUMP_ATTR 1386 1387 void CGrid::computeConnectedClientsScalarGrid() 1388 TRY 1389 { 1472 computeClientIndexScalarGrid_done_ = true ; 1473 } 1474 CATCH_DUMP_ATTR 1475 1476 void CGrid::computeConnectedClientsScalarGrid(CContextClient* client) 1477 TRY 1478 { 1479 if (computeConnectedClientsScalarGrid_done_.count(client)!=0) return ; 1390 1480 1391 1481 CContext* context = CContext::getCurrent(); 1392 1482 1393 1483 set<int> listReceiverSize ; 1394 for (auto it=clients.begin(); it!=clients.end(); ++it) 1395 { 1396 1397 CContextClient* client = *it ; 1398 1399 int receiverSize = client->serverSize; 1484 1485 int receiverSize = client->serverSize; 1400 1486 1401 if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 1402 { 1403 listReceiverSize.insert(receiverSize) ; 1404 if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 1487 if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 1488 { 1489 listReceiverSize.insert(receiverSize) ; 1490 if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 1491 { 1492 // delete corresponding map in case of recompute, probably because a grid could has been modifiedd 1493 // by a transformation 1494 connectedServerRank_.erase(receiverSize); 1495 connectedDataSize_.erase(receiverSize); 1496 globalIndexOnServer_.erase(receiverSize); 1497 nbSenders_.erase(receiverSize); 1498 } 1499 1500 if (client->isServerLeader()) 1501 { 1502 const std::list<int>& ranks = client->getRanksServerLeader(); 1503 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1405 1504 { 1406 // delete corresponding map in case of recompute, probably because a grid could has been modifiedd 1407 // by a transformation 1408 connectedServerRank_.erase(receiverSize); 1409 connectedDataSize_.erase(receiverSize); 1410 globalIndexOnServer_.erase(receiverSize); 1411 nbSenders_.erase(receiverSize); 1412 } 1413 1414 if (client->isServerLeader()) 1505 int rank = *itRank; 1506 int nb = 1; 1507 connectedServerRank_[receiverSize].push_back(rank); 1508 connectedDataSize_[receiverSize][rank] = nb; 1509 nbSenders_[receiverSize][rank] = nb; 1510 } 1511 } 1512 else 1513 { 1514 const std::list<int>& ranks = client->getRanksServerNotLeader(); 1515 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1415 1516 { 1416 const std::list<int>& ranks = client->getRanksServerLeader(); 1417 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1418 { 1419 int rank = *itRank; 1420 int nb = 1; 1421 connectedServerRank_[receiverSize].push_back(rank); 1422 connectedDataSize_[receiverSize][rank] = nb; 1423 nbSenders_[receiverSize][rank] = nb; 1424 } 1425 } 1426 else 1427 { 1428 const std::list<int>& ranks = client->getRanksServerNotLeader(); 1429 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1430 { 1431 int rank = *itRank; 1432 int nb = 1; 1433 connectedServerRank_[receiverSize].push_back(rank); 1434 connectedDataSize_[receiverSize][rank] = nb; 1435 nbSenders_[receiverSize][rank] = nb; 1436 } 1437 } 1438 } 1439 isDataDistributed_ = false; 1440 } 1517 int rank = *itRank; 1518 int nb = 1; 1519 connectedServerRank_[receiverSize].push_back(rank); 1520 connectedDataSize_[receiverSize][rank] = nb; 1521 nbSenders_[receiverSize][rank] = nb; 1522 } 1523 } 1524 } 1525 isDataDistributed_ = false; 1526 computeConnectedClientsScalarGrid_done_.insert(client) ; 1441 1527 } 1442 1528 CATCH_DUMP_ATTR … … 1525 1611 list<CMessage> listMsg; 1526 1612 list<CArray<size_t,1> > listOutIndex; 1527 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();1613 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getDistributionClient()->getGlobalLocalDataSendToServer(); 1528 1614 CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex, 1529 1615 iteIndex = globalLocalIndexSendToServer.end(); … … 1971 2057 TRY 1972 2058 { 2059 if (!computeClientDistribution_done_) computeClientDistribution() ; 1973 2060 return clientDistribution_; 1974 2061 } … … 2209 2296 2210 2297 /*! 2298 \brief Check if all elements of the grid are complete 2299 Before make any grid processing, we must be sure that all grid information elements have 2300 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 2301 other context (coupling) 2302 */ 2303 bool CGrid::checkIfCompleted(void) 2304 { 2305 setDomainList(); 2306 for (auto domainId : domList_) if (!CDomain::get(domainId)->checkIfCompleted()) return false ; 2307 setAxisList() ; 2308 for (auto axisId : axisList_) if (!CAxis::get(axisId)->checkIfCompleted()) return false ; 2309 setScalarList() ; 2310 for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->checkIfCompleted()) return false ; 2311 return true ; 2312 } 2313 2314 /*! 2211 2315 \brief Solve domain and axis references 2212 2316 As field, domain and axis can refer to other domains or axis. In order to inherit correctly … … 2214 2318 \param[in] apply inherit all attributes of parents (true) 2215 2319 */ 2216 void CGrid::solveDomainAxisRefInheritance(bool apply) 2217 TRY 2218 { 2219 CContext* context = CContext::getCurrent(); 2220 unsigned int vecSize, i; 2221 std::vector<StdString>::iterator it, itE; 2320 void CGrid::solveElementsRefInheritance(bool apply) 2321 TRY 2322 { 2222 2323 setDomainList(); 2223 it = domList_.begin(); itE = domList_.end(); 2224 for (; it != itE; ++it) 2225 { 2226 CDomain* pDom = CDomain::get(*it); 2227 if (context->getServiceType()==CServicesManager::CLIENT) 2228 { 2229 pDom->solveRefInheritance(apply); 2230 pDom->solveInheritanceTransformation(); 2231 } 2324 for (auto domainId : domList_) 2325 { 2326 CDomain* pDom = CDomain::get(domainId); 2327 pDom->solveRefInheritance(apply); 2328 pDom->solveInheritanceTransformation(); 2232 2329 } 2233 2330 2234 2331 setAxisList(); 2235 it = axisList_.begin(); itE = axisList_.end(); 2236 for (; it != itE; ++it) 2237 { 2238 CAxis* pAxis = CAxis::get(*it); 2239 if (context->getServiceType()==CServicesManager::CLIENT) 2240 { 2241 pAxis->solveRefInheritance(apply); 2242 pAxis->solveInheritanceTransformation(); 2243 } 2332 for (auto axisId : axisList_) 2333 { 2334 CAxis* pAxis = CAxis::get(axisId); 2335 pAxis->solveRefInheritance(apply); 2336 pAxis->solveInheritanceTransformation(); 2244 2337 } 2245 2338 2246 2339 setScalarList(); 2247 it = scalarList_.begin(); itE = scalarList_.end(); 2248 for (; it != itE; ++it) 2249 { 2250 CScalar* pScalar = CScalar::get(*it); 2251 if (context->getServiceType()==CServicesManager::CLIENT) 2252 { 2253 pScalar->solveRefInheritance(apply); 2254 pScalar->solveInheritanceTransformation(); 2255 } 2256 } 2340 for (auto scalarId : scalarList_) 2341 { 2342 CScalar* pScalar = CScalar::get(scalarId); 2343 pScalar->solveRefInheritance(apply); 2344 pScalar->solveInheritanceTransformation(); 2345 } 2346 } 2347 CATCH_DUMP_ATTR 2348 2349 /*! 2350 \brief check attributes of all elements of the grid 2351 */ 2352 void CGrid::checkElementsAttributes(void) 2353 TRY 2354 { 2355 setDomainList(); 2356 for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes(); 2357 2358 setAxisList(); 2359 for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes(); 2360 2361 setScalarList(); 2362 for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes(); 2257 2363 } 2258 2364 CATCH_DUMP_ATTR … … 2301 2407 TRY 2302 2408 { 2303 if ( 0!= transformGridSrc)2409 if (nullptr != transformGridSrc) 2304 2410 { 2305 2411 if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) … … 2362 2468 } 2363 2469 CATCH_DUMP_ATTR 2470 2471 2472 2473 2474 void CGrid::prepareTransformGrid(CGrid* transformGridSrc) 2475 TRY 2476 { 2477 if (prepareTransformGrid_done_) return ; 2478 2479 if (!transformGridSrc) 2480 ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 2481 << "Impossible to transform grid '" << getId() << "', the source grid is null."); 2482 2483 if (isTransformed()) return; 2484 setTransformed(); 2485 if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) 2486 { 2487 ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 2488 << "Two grids have different number of elements. " << std::endl 2489 << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl 2490 << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements()); 2491 } 2492 else 2493 { 2494 } 2495 2496 transformations_ = new CGridTransformation(this, transformGridSrc); 2497 if (0 < transformations_->getNbAlgo()) hasTransform_ = true; 2498 2499 prepareTransformGrid_done_ = true; 2500 } 2501 CATCH_DUMP_ATTR 2502 2503 2504 void CGrid::makeTransformGrid(void) 2505 TRY 2506 { 2507 if (makeTransformGrid_done_) return ; 2508 transformations_->computeAll(); 2509 2510 makeTransformGrid_done_ = true ; 2511 } 2512 CATCH_DUMP_ATTR 2513 2514 2515 vector<std::string> CGrid::getAuxInputTransformGrid(void) 2516 TRY 2517 { 2518 if (transformations_ != nullptr) return transformations_->getAuxInputs() ; 2519 } 2520 CATCH_DUMP_ATTR 2521 2522 2523 2524 2525 2526 2364 2527 2365 2528 bool CGrid::hasTransform() -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp
r1853 r1869 71 71 void checkEligibilityForCompressedOutput(); 72 72 73 void solveDomainAxisRef(bool areAttributesChecked); 73 74 74 75 75 void checkMaskIndex(bool doCalculateIndex); … … 89 89 StdSize getDimension(void); 90 90 91 StdSize getDataSize(void) const;91 StdSize getDataSize(void) ; 92 92 93 93 /// Entrees-sorties de champs 94 94 template <int n> 95 void inputField(const CArray<double,n>& field, CArray<double,1>& stored) const;95 void inputField(const CArray<double,n>& field, CArray<double,1>& stored) ; 96 96 template <int n> 97 void maskField(const CArray<double,n>& field, CArray<double,1>& stored) const;97 void maskField(const CArray<double,n>& field, CArray<double,1>& stored) ; 98 98 template <int n> 99 void outputField(const CArray<double,1>& stored, CArray<double,n>& field) const;99 void outputField(const CArray<double,1>& stored, CArray<double,n>& field) ; 100 100 template <int n> 101 void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) const;101 void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) ; 102 102 103 103 virtual void parse(xml::CXMLNode& node); … … 133 133 void computeIndexScalarGrid(); 134 134 void computeWrittenIndex(); 135 void solveDomainAxisRef(bool areAttributesChecked); 136 void checkElementsAttributes(void) ; 135 137 136 138 void solveDomainRef(bool checkAtt); 137 139 void solveAxisRef(bool checkAtt); 138 140 void solveScalarRef(bool checkAtt); 139 void solve DomainAxisRefInheritance(bool apply = true);140 void solveTransformations();141 void solveElementsRefInheritance(bool apply = true); 142 // void solveTransformations(); 141 143 void solveDomainAxisBaseRef(); 142 144 … … 195 197 196 198 void transformGrid(CGrid* transformGridSrc); 199 200 void prepareTransformGrid(CGrid* transformGridSrc); 201 bool prepareTransformGrid_done_ = false ; 202 203 void makeTransformGrid(void); 204 bool makeTransformGrid_done_ = false ; 205 206 std::vector<std::string> getAuxInputTransformGrid(void) ; 207 197 208 void completeGrid(CGrid* transformGridSrc = 0); 198 209 void doAutoDistribution(CGrid* transformGridSrc); … … 205 216 bool hasTransform(); 206 217 size_t getGlobalWrittenSize(void) ; 218 bool checkIfCompleted(void) ; 219 207 220 208 221 bool hasMask(void) const; … … 217 230 const CArray<int,1>& axisDomainOrder); 218 231 232 void computeGridIndexToFileServer(CContextClient* client) ; 233 219 234 private: 235 void computeClientDistribution(void) ; 236 bool computeClientDistribution_done_ = false ; 237 220 238 template<int N> 221 239 void checkGridMask(CArray<bool,N>& gridMask, … … 230 248 void modifyGridMaskSize(CArray<bool,N>& gridMask, const std::vector<int>& eachDimSize, bool newValue); 231 249 232 void storeField_arr(const double* const data, CArray<double, 1>& stored) const;233 void restoreField_arr(const CArray<double, 1>& stored, double* const data) const;234 void uncompressField_arr(const double* const data, CArray<double, 1>& outData) const;235 void maskField_arr(const double* const data, CArray<double, 1>& stored) const;250 void storeField_arr(const double* const data, CArray<double, 1>& stored) ; 251 void restoreField_arr(const CArray<double, 1>& stored, double* const data) ; 252 void uncompressField_arr(const double* const data, CArray<double, 1>& outData) ; 253 void maskField_arr(const double* const data, CArray<double, 1>& stored) ; 236 254 237 255 void setVirtualDomainGroup(CDomainGroup* newVDomainGroup); … … 259 277 int getDistributedDimension(); 260 278 279 261 280 void computeClientIndex(); 262 void computeConnectedClients(); 281 bool computeClientIndex_done_ = false ; 282 283 void computeConnectedClients(CContextClient* client); 284 set<CContextClient*> computeConnectedClients_done_ ; 285 263 286 void computeClientIndexScalarGrid(); 264 void computeConnectedClientsScalarGrid(); 265 287 bool computeClientIndexScalarGrid_done_ = false ; 288 289 void computeConnectedClientsScalarGrid(CContextClient* client); 290 set<CContextClient*> computeConnectedClientsScalarGrid_done_ ; 266 291 267 292 public: … … 270 295 * Used to store field from model into the worklow, or to return field into models. 271 296 * The size of the array is the number of local index of the workflow grid */ 272 CArray<int, 1> storeIndex_client_; 297 CArray<int, 1> storeIndex_client_; 298 void computeStoreIndex_client(void) ; 299 bool computeStoreIndex_client_done_ = false ; 300 CArray<int, 1>& getStoreIndex_client(void) { if (!computeStoreIndex_client_done_) computeStoreIndex_client() ; return storeIndex_client_ ;} 273 301 274 302 /** Array containing the grid mask masked defined by the mask_nd grid attribute. 275 303 * The corresponding masked field value provided by the model will be replaced by a NaN value 276 304 * in the workflow. */ 277 CArray<bool, 1> storeMask_client_; 305 CArray<bool, 1> storeMask_client_; 306 void computeStoreMask_client(void) ; 307 bool computeStoreMask_client_done_ = false ; 308 CArray<bool, 1>& getStoreMask_client(void) { if (!computeStoreMask_client_done_) computeStoreMask_client() ; return storeMask_client_ ;} 278 309 279 310 /** Map containing the indexes on client side that will be sent to each connected server. … … 419 450 420 451 template <int n> 421 void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const452 void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) 422 453 TRY 423 454 { … … 435 466 436 467 template <int n> 437 void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) const468 void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) 438 469 { 439 470 //#ifdef __XIOS_DEBUG … … 449 480 450 481 template <int n> 451 void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const482 void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) 452 483 TRY 453 484 { … … 471 502 */ 472 503 template <int N> 473 void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) const504 void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) 474 505 TRY 475 506 { -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp
r1314 r1869 59 59 void CScalar::checkAttributes(void) 60 60 { 61 if (checkAttributes_done_) return ; 62 63 checkAttributes_done_ = true ; 61 64 } 62 65 … … 65 68 66 69 } 70 71 /*! 72 \brief Check if a scalar is completed 73 Before make any scalar processing, we must be sure that all scalar informations have 74 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 75 other context (coupling). So all direct reference of the scalar (scalar_ref) must be also completed 76 \return true if scalar and scalar reference are completed 77 */ 78 bool CScalar::checkIfCompleted(void) 79 { 80 if (hasDirectScalarReference()) if (!getDirectScalarReference()->checkIfCompleted()) return false; 81 return isCompleted_ ; 82 } 83 84 /*! 85 \brief Set a scalar as completed 86 When all information about a scalar have been received, the scalar is tagged as completed and is 87 suitable for processing 88 */ 89 void CScalar::setCompleted(void) 90 { 91 if (hasDirectScalarReference()) getDirectScalarReference()->setCompleted() ; 92 isCompleted_=true ; 93 } 94 95 /*! 96 \brief Set a scalar as uncompleted 97 When informations about a scalar are expected from a grid reading from file or coupling, the scalar is 98 tagged as uncompleted and is not suitable for processing 99 */ 100 void CScalar::setUncompleted(void) 101 { 102 if (hasDirectScalarReference()) getDirectScalarReference()->setUncompleted() ; 103 isCompleted_=false ; 104 } 105 106 107 67 108 68 109 /*! -
XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.hpp
r1436 r1869 66 66 public: 67 67 void checkAttributes(void); 68 bool checkAttributes_done_ = false ; 69 68 70 void addRelFile(const StdString& filename); 69 71 bool IsWritten(const StdString& filename) const; 70 72 void checkAttributesOnClient(); 71 73 virtual void parse(xml::CXMLNode & node); 74 75 bool checkIfCompleted(void) ; 76 void setCompleted(void) ; 77 void setUncompleted(void) ; 72 78 73 79 public: … … 90 96 static bool dummyTransformationMapList_; 91 97 98 /** define if the scalar is completed or not ie all attributes have been received before in case 99 of grid reading from file or coupling */ 100 bool isCompleted_=true ; 92 101 93 102 DECLARE_REF_FUNC(Scalar,scalar) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/object_factory.hpp
r1542 r1869 50 50 template <typename U> 51 51 static std::shared_ptr<U> CreateObject(const StdString & id = StdString("")); 52 52 53 template <typename U> 54 static std::shared_ptr<U> CreateAlias(const StdString& id, const StdString& alias) ; 55 53 56 template <typename U> static const StdString& GetUIdBase(void); 54 57 template <typename U> static StdString GenUId(void); -
XIOS/dev/dev_ym/XIOS_COUPLING/src/object_factory_decl_macro.hpp
r1591 r1869 13 13 template bool CObjectFactory::HasObject<U>(const StdString& context,const StdString& id); \ 14 14 template std::shared_ptr<U> CObjectFactory::CreateObject<U>(const StdString& id ); \ 15 template std::shared_ptr<U> CObjectFactory::CreateAlias<U>(const StdString& id, const StdString& alias ); \ 15 16 template const StdString& CObjectFactory::GetUIdBase<U>(void); \ 16 17 template StdString CObjectFactory::GenUId<U>(void); \ -
XIOS/dev/dev_ym/XIOS_COUPLING/src/object_factory_impl.hpp
r1542 r1869 113 113 114 114 template <typename U> 115 std::shared_ptr<U> CObjectFactory::CreateAlias(const StdString& id, const StdString& alias) 116 { 117 if (CurrContext.empty()) 118 ERROR("CObjectFactory::CreateAlias(const StdString& id, const StdString& alias)", 119 << "[ id = " << id << " alias = "<<alias<<" ] please define current context id !"); 120 121 if (CObjectFactory::HasObject<U>(alias)) 122 { 123 return CObjectFactory::GetObject<U>(alias); 124 } 125 else 126 { 127 if (! CObjectFactory::HasObject<U>(id)) 128 { 129 ERROR("CObjectFactory::CreateAlias(const StdString& id, const StdString& alias)", 130 << "[ id = " << id << " alias = "<<alias<<" ] object id doesn't exist"); 131 } 132 else 133 { 134 std::shared_ptr<U> value = CObjectFactory::GetObject<U>(id); 135 U::AllMapObj[CObjectFactory::CurrContext].insert(std::make_pair(alias, value)); 136 return value; 137 } 138 } 139 } 140 141 template <typename U> 115 142 const std::vector<std::shared_ptr<U> > & 116 143 CObjectFactory::GetObjectVector(const StdString & context) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/object_template.hpp
r1784 r1869 83 83 84 84 static T* create(const string& id=string("")) ; 85 static T* createAlias(const string& id, const string& alias) ; 86 void createAlias(const string& alias) ; 87 85 88 static const vector<T*> getAll() ; 86 89 static const vector<T*> getAll(const string& contextId) ; -
XIOS/dev/dev_ym/XIOS_COUPLING/src/object_template_impl.hpp
r1848 r1869 420 420 } ///-------------------------------------------------------------- 421 421 422 template <typename T> 423 T* CObjectTemplate<T>::createAlias(const string & id, const string& alias) 424 { 425 return CObjectFactory::CreateAlias<T>(id, alias).get(); 426 } ///-------------------------------------------------------------- 427 428 template <typename T> 429 void CObjectTemplate<T>::createAlias(const string& alias) 430 { 431 get()->createAlias(getId(),alias) ; 432 } // 433 422 434 template <typename T> 423 435 T* CObjectTemplate<T>::get(void) -
XIOS/dev/dev_ym/XIOS_COUPLING/src/parse_expr/filter_expr_node.cpp
r1575 r1869 40 40 << "Use the keyword \"this\" if you want to reference the input data sent to this field."); 41 41 42 field->buildFilterGraph(gc, false);43 outputPin = field->getInstantDataFilter();42 bool ret=field->buildWorkflowGraph(gc); 43 if (ret) outputPin = field->getInstantDataFilter(); // if dependency is complete build the graph other return nullptr 44 44 } 45 45 else ERROR("boost::shared_ptr<COutputPin> CFilterFieldExprNode::reduce(CGarbageCollector& gc, CField& thisField) const", … … 84 84 << "Use the keyword \"this\" if you want to reference the input data sent to this field."); 85 85 86 field->buildFilterGraph(gc, false);87 outputPin = field->getTemporalDataFilter(gc, thisField.freq_op.isEmpty() ? TimeStep : thisField.freq_op);86 bool ret=field->buildWorkflowGraph(gc); 87 if (ret) outputPin = field->getTemporalDataFilter(gc, thisField.freq_op.isEmpty() ? TimeStep : thisField.freq_op); 88 88 } 89 89 else … … 107 107 { 108 108 std::shared_ptr<CUnaryArithmeticFilter> filter(new CUnaryArithmeticFilter(gc, opId)); 109 child->reduce(gc, thisField)->connectOutput(filter, 0); 109 auto ret=child->reduce(gc, thisField) ; 110 if (ret) ret->connectOutput(filter, 0); 111 else filter.reset() ; 110 112 return filter; 111 113 } … … 124 126 { 125 127 std::shared_ptr<CScalarFieldArithmeticFilter> filter(new CScalarFieldArithmeticFilter(gc, opId, child1->reduce())); 126 child2->reduce(gc, thisField)->connectOutput(filter, 0); 128 129 auto ret=child2->reduce(gc, thisField) ; 130 if (ret) ret->connectOutput(filter, 0); 131 else filter.reset() ; 127 132 return filter; 128 133 } … … 141 146 { 142 147 std::shared_ptr<CFieldScalarArithmeticFilter> filter(new CFieldScalarArithmeticFilter(gc, opId, child2->reduce())); 143 child1->reduce(gc, thisField)->connectOutput(filter, 0); 148 auto ret=child1->reduce(gc, thisField) ; 149 if (ret) ret->connectOutput(filter, 0); 150 else filter.reset() ; 144 151 return filter; 145 152 } … … 158 165 { 159 166 std::shared_ptr<CFieldFieldArithmeticFilter> filter(new CFieldFieldArithmeticFilter(gc, opId)); 160 child1->reduce(gc, thisField)->connectOutput(filter, 0); 161 child2->reduce(gc, thisField)->connectOutput(filter, 1); 167 auto ret1 = child1->reduce(gc, thisField); 168 auto ret2 = child2->reduce(gc, thisField); 169 if (ret1 && ret2) 170 { 171 ret1->connectOutput(filter, 0) ; 172 ret2->connectOutput(filter, 1) ; 173 } 174 else filter.reset() ; 162 175 return filter; 163 176 } … … 180 193 { 181 194 std::shared_ptr<CScalarScalarFieldArithmeticFilter> filter(new CScalarScalarFieldArithmeticFilter(gc, opId, child1->reduce(),child2->reduce())); 182 child3->reduce(gc, thisField)->connectOutput(filter, 0); 195 auto ret=child3->reduce(gc, thisField) ; 196 if (ret) ret->connectOutput(filter, 0); 197 else filter.reset() ; 183 198 return filter; 184 199 } … … 199 214 { 200 215 std::shared_ptr<CScalarFieldScalarArithmeticFilter> filter(new CScalarFieldScalarArithmeticFilter(gc, opId, child1->reduce(),child3->reduce())); 201 child2->reduce(gc, thisField)->connectOutput(filter, 0); 216 auto ret=child2->reduce(gc, thisField); 217 if (ret) ret->connectOutput(filter, 0); 218 else filter.reset() ; 202 219 return filter; 203 220 } … … 218 235 { 219 236 std::shared_ptr<CScalarFieldFieldArithmeticFilter> filter(new CScalarFieldFieldArithmeticFilter(gc, opId, child1->reduce())); 220 child2->reduce(gc, thisField)->connectOutput(filter, 0); 221 child3->reduce(gc, thisField)->connectOutput(filter, 1); 237 auto ret1=child2->reduce(gc, thisField); 238 auto ret2=child3->reduce(gc, thisField); 239 if (ret1 && ret2) 240 { 241 ret1->connectOutput(filter, 0); 242 ret2->connectOutput(filter, 1); 243 } 244 else filter.reset() ; 222 245 return filter; 223 246 } … … 239 262 { 240 263 std::shared_ptr<CFieldScalarScalarArithmeticFilter> filter(new CFieldScalarScalarArithmeticFilter(gc, opId, child2->reduce(),child3->reduce())); 241 child1->reduce(gc, thisField)->connectOutput(filter, 0); 264 auto ret = child1->reduce(gc, thisField) ; 265 if (ret) ret->connectOutput(filter, 0); 266 else filter.reset() ; 242 267 return filter; 243 268 } … … 259 284 { 260 285 std::shared_ptr<CFieldScalarFieldArithmeticFilter> filter(new CFieldScalarFieldArithmeticFilter(gc, opId, child2->reduce())); 261 child1->reduce(gc, thisField)->connectOutput(filter, 0); 262 child3->reduce(gc, thisField)->connectOutput(filter, 1); 286 auto ret1 = child1->reduce(gc, thisField); 287 auto ret2 = child3->reduce(gc, thisField); 288 if (ret1 && ret2) 289 { 290 ret1 -> connectOutput(filter, 0); 291 ret2 -> connectOutput(filter, 1); 292 } 293 else filter.reset() ; 263 294 return filter; 264 295 } … … 280 311 { 281 312 std::shared_ptr<CFieldFieldScalarArithmeticFilter> filter(new CFieldFieldScalarArithmeticFilter(gc, opId, child3->reduce())); 282 child1->reduce(gc, thisField)->connectOutput(filter, 0); 283 child2->reduce(gc, thisField)->connectOutput(filter, 1); 313 auto ret1 = child1->reduce(gc, thisField); 314 auto ret2 = child2->reduce(gc, thisField); 315 if (ret1 && ret2) 316 { 317 ret1->connectOutput(filter, 0); 318 ret2->connectOutput(filter, 1); 319 } 320 else filter.reset() ; 284 321 return filter; 285 322 } … … 300 337 { 301 338 std::shared_ptr<CFieldFieldFieldArithmeticFilter> filter(new CFieldFieldFieldArithmeticFilter(gc, opId)); 302 child1->reduce(gc, thisField)->connectOutput(filter, 0); 303 child2->reduce(gc, thisField)->connectOutput(filter, 1); 304 child3->reduce(gc, thisField)->connectOutput(filter, 2); 339 auto ret1=child1->reduce(gc, thisField); 340 auto ret2=child2->reduce(gc, thisField); 341 auto ret3=child3->reduce(gc, thisField); 342 if (ret1 && ret2 && ret3) 343 { 344 ret1->connectOutput(filter, 0); 345 ret2->connectOutput(filter, 1); 346 ret3->connectOutput(filter, 2); 347 } 348 else filter.reset() ; 305 349 return filter; 306 350 } -
XIOS/dev/dev_ym/XIOS_COUPLING/src/test/generic_testcase.f90
r1761 r1869 258 258 259 259 ok_field3D_recv_W=xios_is_valid_field("field3D_recv_W").AND.xios_is_valid_field("field3D_resend_W") ; 260 IF (ok_field3D_recv ) THEN260 IF (ok_field3D_recv_W) THEN 261 261 CALL xios_is_defined_field_attr("field3D_recv_W",freq_op=ok) 262 262 IF (ok) THEN … … 463 463 464 464 ok_other_field3D_recv_W=xios_is_valid_field("other_field3D_recv_W").AND.xios_is_valid_field("other_field3D_resend_W") ; 465 IF (ok_other_field3D_recv ) THEN465 IF (ok_other_field3D_recv_W) THEN 466 466 CALL xios_is_defined_field_attr("other_field3D_recv_W",freq_op=ok) 467 467 IF (ok) THEN -
XIOS/dev/dev_ym/XIOS_COUPLING/src/transformation/axis_algorithm_interpolate.cpp
r1784 r1869 313 313 { 314 314 CField* field = CField::get(coordinate_); 315 CGrid* grid = field->g rid;315 CGrid* grid = field->getGrid(); 316 316 317 317 std::vector<CDomain*> domListP = grid->getDomains(); -
XIOS/dev/dev_ym/XIOS_COUPLING/src/transformation/grid_transformation.cpp
r1784 r1869 246 246 } 247 247 248 tmpGridDestination_ = CGrid::createGrid(domainDst, axisDst, scalarDst, elementOrder); 248 tmpGridDestination_ = CGrid::createGrid(domainDst, axisDst, scalarDst, elementOrder); 249 tmpGridDestination_-> solveElementsRefInheritance() ; // ym not sure 249 250 tempGridDests_.push_back(tmpGridDestination_); 250 251 } … … 292 293 domain->domain_ref.setValue(domListDestP[elementIndex]->getId()); 293 294 domain->solveRefInheritance(true); 294 domain->checkAttributes OnClient();295 domain->checkAttributes(); 295 296 domainSrc.push_back(domain); 296 297 } … … 300 301 axis->axis_ref.setValue(axisListDestP[elementIndex]->getId()); 301 302 axis->solveRefInheritance(true); 302 axis->checkAttributes OnClient();303 axis->checkAttributes(); 303 304 axisSrc.push_back(axis); 304 305 } … … 308 309 scalar->scalar_ref.setValue(scalarListDestP[elementIndex]->getId()); 309 310 scalar->solveRefInheritance(true); 310 scalar->checkAttributes OnClient();311 scalar->checkAttributes(); 311 312 scalarSrc.push_back(scalar); 312 313 } … … 334 335 335 336 gridSource_ = CGrid::createGrid(domainSrc, axisSrc, scalarSrc, tmpGridDestination_->axis_domain_order); 337 gridSource_->solveElementsRefInheritance() ; // ym not sure 336 338 337 339 tempGridSrcs_.push_back(gridSource_);
Note: See TracChangeset
for help on using the changeset viewer.