Changeset 2019 for XIOS/dev/dev_trunk_graph/src/node
- Timestamp:
- 01/22/21 12:00:29 (3 years ago)
- Location:
- XIOS/dev/dev_trunk_graph/src/node
- Files:
-
- 5 added
- 60 edited
Legend:
- Unmodified
- Added
- Removed
-
XIOS/dev/dev_trunk_graph/src/node/axis.cpp
r1686 r2019 20 20 CAxis::CAxis(void) 21 21 : CObjectTemplate<CAxis>() 22 , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false) 23 , isClientAfterTransformationChecked(false) 22 , CAxisAttributes(), isChecked(false), relFiles() 24 23 , hasBounds(false), isCompressible_(false) 25 , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()26 24 , transformationMap_(), hasValue(false), hasLabel(false) 27 , computedWrittenIndex_(false) 28 , clients() 25 , clients() 29 26 { 30 27 } … … 32 29 CAxis::CAxis(const StdString & id) 33 30 : CObjectTemplate<CAxis>(id) 34 , CAxisAttributes(), isChecked(false), relFiles(), areClientAttributesChecked_(false) 35 , isClientAfterTransformationChecked(false) 31 , CAxisAttributes(), isChecked(false), relFiles() 36 32 , hasBounds(false), isCompressible_(false) 37 , numberWrittenIndexes_(), totalNumberWrittenIndexes_(), offsetWrittenIndexes_()38 33 , transformationMap_(), hasValue(false), hasLabel(false) 39 , computedWrittenIndex_(false) 40 , clients() 34 , clients() 41 35 { 42 36 } … … 93 87 // A condition to make sure that if there is only one client, axis 94 88 // should be considered to be distributed. This should be a temporary solution 95 distributed |= (1 == CContext::getCurrent()-> client->clientSize);89 distributed |= (1 == CContext::getCurrent()->intraCommSize_); 96 90 return distributed; 97 91 } … … 99 93 100 94 /*! 101 * Test whether the data defined on the axis can be outputted in a compressed way. 102 * 103 * \return true if and only if a mask was defined for this axis 95 * Compute if the axis can be ouput in a compressed way. 96 * In this case the workflow view on server side must be the same 97 * than the full view for all context rank. The result is stored on 98 * internal isCompressible_ attribute. 104 99 */ 105 bool CAxis::isCompressible(void) const 106 TRY 107 { 108 return isCompressible_; 100 void CAxis::computeIsCompressible(void) 101 TRY 102 { 103 // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view. 104 // But now assume that the size of the 2 view must be equal for everybody. True on server side 105 int isSameView = getLocalView(CElementView::FULL)->getSize() == getLocalView(CElementView::WORKFLOW)->getSize(); 106 MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ; 107 if (isSameView) isCompressible_ = false ; 108 else isCompressible_ = true ; 109 isCompressibleComputed_=true ; 109 110 } 110 111 CATCH … … 124 125 CATCH_DUMP_ATTR 125 126 126 //---------------------------------------------------------------- 127 128 /*! 129 Returns the number of indexes written by each server. 130 \return the number of indexes written by each server 131 */ 132 int CAxis::getNumberWrittenIndexes(MPI_Comm writtenCom) 133 TRY 134 { 135 int writtenSize; 136 MPI_Comm_size(writtenCom, &writtenSize); 137 return numberWrittenIndexes_[writtenSize]; 138 } 139 CATCH_DUMP_ATTR 140 141 /*! 142 Returns the total number of indexes written by the servers. 143 \return the total number of indexes written by the servers 144 */ 145 int CAxis::getTotalNumberWrittenIndexes(MPI_Comm writtenCom) 146 TRY 147 { 148 int writtenSize; 149 MPI_Comm_size(writtenCom, &writtenSize); 150 return totalNumberWrittenIndexes_[writtenSize]; 151 } 152 CATCH_DUMP_ATTR 153 154 /*! 155 Returns the offset of indexes written by each server. 156 \return the offset of indexes written by each server 157 */ 158 int CAxis::getOffsetWrittenIndexes(MPI_Comm writtenCom) 159 TRY 160 { 161 int writtenSize; 162 MPI_Comm_size(writtenCom, &writtenSize); 163 return offsetWrittenIndexes_[writtenSize]; 164 } 165 CATCH_DUMP_ATTR 166 167 CArray<int, 1>& CAxis::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom) 168 TRY 169 { 170 int writtenSize; 171 MPI_Comm_size(writtenCom, &writtenSize); 172 return compressedIndexToWriteOnServer[writtenSize]; 173 } 174 CATCH_DUMP_ATTR 175 176 //---------------------------------------------------------------- 127 //---------------------------------------------------------------- 177 128 178 129 /*! … … 274 225 TRY 275 226 { 227 if (checkAttributes_done_) return ; 228 276 229 CContext* context=CContext::getCurrent(); 277 230 … … 318 271 if (!this->value.isEmpty()) 319 272 { 320 // Avoid this check at writing because it fails in case of a hole 321 if (context->hasClient) 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 } 273 StdSize true_size = value.numElements(); 274 if (this->n.getValue() != true_size) 275 ERROR("CAxis::checkAttributes(void)", 276 << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " 277 << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size 278 << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); 330 279 this->hasValue = true; 331 280 } 332 281 333 282 this->checkBounds(); 334 335 if (context->hasClient) 336 { 337 this->checkMask(); 338 this->checkData(); 339 this->checkLabel(); 340 } 283 this->checkMask(); 284 this->checkData(); 285 this->checkLabel(); 286 initializeLocalElement() ; 287 addFullView() ; 288 addWorkflowView() ; 289 addModelView() ; 290 291 checkAttributes_done_ = true ; 341 292 } 342 293 CATCH_DUMP_ATTR 294 295 343 296 344 297 /*! … … 387 340 for (int i = 0; i < data_n; ++i) 388 341 { 389 if ((i+data_begin) >= 0 && (i+data_begin<n) && !mask(i+data_begin))390 data_index(i) = -1;342 if (data_index(i) >= 0 && data_index(i)<n) 343 if (!mask(data_index(i))) data_index(i) = -1; 391 344 } 392 345 } … … 460 413 CATCH_DUMP_ATTR 461 414 462 /*! 463 Check whether we can do compressed output 464 */ 465 void CAxis::checkEligibilityForCompressedOutput() 466 TRY 467 { 468 // We don't check if the mask is valid here, just if a mask has been defined at this point. 469 isCompressible_ = !mask.isEmpty(); 470 } 471 CATCH_DUMP_ATTR 472 415 473 416 /*! 474 417 Dispatch event from the lower communication layer then process event according to its type … … 482 425 switch(event.type) 483 426 { 484 case EVENT_ID_DISTRIBUTION_ATTRIBUTE : 485 recvDistributionAttribute(event); 486 return true; 487 break; 488 case EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES: 489 recvNonDistributedAttributes(event); 427 case EVENT_ID_AXIS_DISTRIBUTION: 428 recvAxisDistribution(event); 490 429 return true; 491 430 break; 492 case EVENT_ID_ DISTRIBUTED_ATTRIBUTES:431 case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE: 493 432 recvDistributedAttributes(event); 494 433 return true; … … 503 442 CATCH 504 443 505 /*! 506 Check attributes on client side (This name is still adequate???) 507 */ 508 void CAxis::checkAttributesOnClient() 509 TRY 510 { 511 if (this->areClientAttributesChecked_) return; 512 513 CContext* context=CContext::getCurrent(); 514 if (context->hasClient && !context->hasServer) this->checkAttributes(); 515 516 this->areClientAttributesChecked_ = true; 517 } 518 CATCH_DUMP_ATTR 519 520 /* 521 The (spatial) transformation sometimes can change attributes of an axis (e.g zoom can change mask or generate can change whole attributes) 522 Therefore, we should recheck them. 523 */ 524 void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid, 525 CServerDistributionDescription::ServerDistributionType distType) 526 TRY 527 { 528 CContext* context=CContext::getCurrent() ; 529 530 if (this->isClientAfterTransformationChecked) return; 531 if (context->hasClient) 532 { 533 if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) 534 computeConnectedClients(globalDim, orderPositionInGrid, distType); 535 else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid, CServerDistributionDescription::ROOT_DISTRIBUTION); 536 } 537 538 this->isClientAfterTransformationChecked = true; 539 } 540 CATCH_DUMP_ATTR 541 542 /* 543 Send all checked attributes to server? (We dont have notion of server any more so client==server) 544 \param [in] globalDim global dimension of grid containing this axis 545 \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) 546 \param [in] distType distribution type of the server. For now, we only have band distribution. 547 548 */ 549 void CAxis::sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, 550 CServerDistributionDescription::ServerDistributionType distType) 551 TRY 552 { 553 if (!this->areClientAttributesChecked_) checkAttributesOnClient(); 554 if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation(globalDim, orderPositionInGrid, distType); 555 CContext* context = CContext::getCurrent(); 556 557 if (this->isChecked) return; 558 if (context->hasClient) sendAttributes(globalDim, orderPositionInGrid, distType); 559 560 this->isChecked = true; 561 } 562 CATCH_DUMP_ATTR 563 564 /*! 565 Send attributes from one client to other clients 566 \param[in] globalDim global dimension of grid which contains this axis 567 \param[in] order 568 */ 569 void CAxis::sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, 570 CServerDistributionDescription::ServerDistributionType distType) 571 TRY 572 { 573 sendDistributionAttribute(globalDim, orderPositionInGrid, distType); 574 575 // if (index.numElements() == n_glo.getValue()) 576 if ((orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) 577 || (index.numElements() != n_glo)) 578 { 579 sendDistributedAttributes(); 580 } 581 else 582 { 583 sendNonDistributedAttributes(); 584 } 585 } 586 CATCH_DUMP_ATTR 587 588 /* 589 Compute the connection between group of clients (or clients/servers). 590 (E.g: Suppose we have 2 group of clients in two model: A (client role) connect to B (server role), 591 this function calculate number of clients B connect to one client of A) 592 \param [in] globalDim global dimension of grid containing this axis 593 \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) 594 \param [in] distType distribution type of the server. For now, we only have band distribution. 595 */ 596 void CAxis::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 597 CServerDistributionDescription::ServerDistributionType distType) 598 TRY 599 { 600 CContext* context = CContext::getCurrent(); 601 602 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; 603 604 connectedServerRank_.clear(); 605 nbSenders.clear(); 606 607 for (int p = 0; p < nbSrvPools; ++p) 608 { 609 CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client; 610 int nbServer = client->serverSize; 611 int range, clientSize = client->clientSize; 612 int rank = client->clientRank; 613 614 if (connectedServerRank_.find(nbServer) == connectedServerRank_.end()) 615 { 616 size_t ni = this->n.getValue(); 617 size_t ibegin = this->begin.getValue(); 618 size_t nbIndex = index.numElements(); 619 620 // First of all, we should compute the mapping of the global index and local index of the current client 621 if (globalLocalIndexMap_.empty()) 622 { 623 for (size_t idx = 0; idx < nbIndex; ++idx) 624 { 625 globalLocalIndexMap_[index(idx)] = idx; 626 } 627 } 628 629 // Calculate the compressed index if any 630 // std::set<int> writtenInd; 631 // if (isCompressible_) 632 // { 633 // for (int idx = 0; idx < data_index.numElements(); ++idx) 634 // { 635 // int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni); 636 // 637 // if (ind >= 0 && ind < ni && mask(ind)) 638 // { 639 // ind += ibegin; 640 // writtenInd.insert(ind); 641 // } 642 // } 643 // } 644 645 // Compute the global index of the current client (process) hold 646 std::vector<int> nGlobAxis(1); 647 nGlobAxis[0] = n_glo.getValue(); 648 649 size_t globalSizeIndex = 1, indexBegin, indexEnd; 650 for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; 651 indexBegin = 0; 652 if (globalSizeIndex <= clientSize) 653 { 654 indexBegin = rank%globalSizeIndex; 655 indexEnd = indexBegin; 656 } 657 else 658 { 659 for (int i = 0; i < clientSize; ++i) 660 { 661 range = globalSizeIndex / clientSize; 662 if (i < (globalSizeIndex%clientSize)) ++range; 663 if (i == client->clientRank) break; 664 indexBegin += range; 665 } 666 indexEnd = indexBegin + range - 1; 667 } 668 669 CArray<size_t,1> globalIndex(index.numElements()); 670 for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 671 globalIndex(idx) = index(idx); 672 673 // Describe the distribution of server side 674 675 CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); 676 677 std::vector<int> serverZeroIndex; 678 serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 679 680 std::list<int> serverZeroIndexLeader; 681 std::list<int> serverZeroIndexNotLeader; 682 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 683 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 684 *it = serverZeroIndex[*it]; 685 686 // Find out the connection between client and server side 687 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 688 clientServerMap->computeServerIndexMapping(globalIndex, nbServer); 689 CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer(); 690 691 indSrv_[nbServer].swap(globalIndexAxisOnServer); 692 693 if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) 694 { 695 for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; 696 serverZeroIndexLeader.clear() ; 697 } 698 699 CClientServerMapping::GlobalIndexMap::const_iterator it = indSrv_[nbServer].begin(), 700 ite = indSrv_[nbServer].end(); 701 702 for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 703 704 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 705 connectedServerRank_[nbServer].push_back(*it); 706 707 // Even if a client has no index, it must connect to at least one server and 708 // send an "empty" data to this server 709 if (connectedServerRank_[nbServer].empty()) 710 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 711 712 nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 713 714 delete clientServerMap; 715 } 716 } 717 } 718 CATCH_DUMP_ATTR 719 720 /* 721 Compute the index of data to write into file 722 (Different from the previous version, this version of XIOS allows data be written into file (classical role), 723 or transfered to another clients) 724 */ 725 void CAxis::computeWrittenIndex() 726 TRY 727 { 728 if (computedWrittenIndex_) return; 729 computedWrittenIndex_ = true; 730 731 CContext* context=CContext::getCurrent(); 732 CContextServer* server = context->server; 733 734 // We describe the distribution of client (server) on which data are written 735 std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1); 736 nBegin[0] = begin; 737 nSize[0] = n; 738 nBeginGlobal[0] = 0; 739 nGlob[0] = n_glo; 740 CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 741 const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex(); 742 743 // Because all written data are local on a client, 744 // we need to compute the local index on the server from its corresponding global index 745 size_t nbWritten = 0, indGlo; 746 std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(), 747 ite = globalLocalIndexMap_.end(), it; 748 CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(), 749 itSrve = writtenGlobalIndex.end(), itSrv; 750 751 localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements()); 752 nbWritten = 0; 753 for (itSrv = itSrvb; itSrv != itSrve; ++itSrv) 754 { 755 indGlo = *itSrv; 756 if (ite != globalLocalIndexMap_.find(indGlo)) 757 { 758 localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo]; 759 } 760 else 761 { 762 localIndexToWriteOnServer(nbWritten) = -1; 763 } 764 ++nbWritten; 765 } 766 767 } 768 CATCH_DUMP_ATTR 769 770 void CAxis::computeWrittenCompressedIndex(MPI_Comm writtenComm) 771 TRY 772 { 773 int writtenCommSize; 774 MPI_Comm_size(writtenComm, &writtenCommSize); 775 if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end()) 776 return; 777 778 if (isCompressible()) 779 { 780 size_t nbWritten = 0, indGlo; 781 CContext* context=CContext::getCurrent(); 782 CContextServer* server = context->server; 783 784 // We describe the distribution of client (server) on which data are written 785 std::vector<int> nBegin(1), nSize(1), nBeginGlobal(1), nGlob(1); 786 nBegin[0] = 0; 787 nSize[0] = n; 788 nBeginGlobal[0] = 0; 789 nGlob[0] = n_glo; 790 CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob); 791 const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex(); 792 std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(), 793 ite = globalLocalIndexMap_.end(), it; 794 795 CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(), 796 itSrve = writtenGlobalIndex.end(), itSrv; 797 std::unordered_map<size_t,size_t> localGlobalIndexMap; 798 for (itSrv = itSrvb; itSrv != itSrve; ++itSrv) 799 { 800 indGlo = *itSrv; 801 if (ite != globalLocalIndexMap_.find(indGlo)) 802 { 803 localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo; 804 ++nbWritten; 805 } 806 } 807 // 808 // nbWritten = 0; 809 // for (int idx = 0; idx < data_index.numElements(); ++idx) 810 // { 811 // if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) 812 // { 813 // ++nbWritten; 814 // } 815 // } 816 // 817 // compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten); 818 // nbWritten = 0; 819 // for (int idx = 0; idx < data_index.numElements(); ++idx) 820 // { 821 // if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) 822 // { 823 // compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)]; 824 // ++nbWritten; 825 // } 826 // } 827 828 nbWritten = 0; 829 for (int idx = 0; idx < data_index.numElements(); ++idx) 830 { 831 if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) 832 { 833 ++nbWritten; 834 } 835 } 836 837 compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten); 838 nbWritten = 0; 839 for (int idx = 0; idx < data_index.numElements(); ++idx) 840 { 841 if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_index(idx))) 842 { 843 compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_index(idx)]; 844 ++nbWritten; 845 } 846 } 847 848 numberWrittenIndexes_[writtenCommSize] = nbWritten; 849 850 bool distributed_glo, distributed=isDistributed() ; 851 MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ; 852 if (distributed_glo) 853 { 854 855 MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm); 856 MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm); 857 offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize]; 858 } 859 else 860 totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize]; 861 } 862 } 863 CATCH_DUMP_ATTR 864 865 /*! 866 Send distribution information from a group of client (client role) to another group of client (server role) 867 The distribution of a group of client (server role) is imposed by the group of client (client role) 868 \param [in] globalDim global dimension of grid containing this axis 869 \param [in] orderPositionInGrid the relative order of this axis in the grid (e.g grid composed of domain+axis -> orderPositionInGrid is 2) 870 \param [in] distType distribution type of the server. For now, we only have band distribution. 871 */ 872 void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid, 873 CServerDistributionDescription::ServerDistributionType distType) 874 TRY 875 { 876 std::list<CContextClient*>::iterator it; 877 for (it=clients.begin(); it!=clients.end(); ++it) 878 { 879 CContextClient* client = *it; 880 int nbServer = client->serverSize; 881 882 CServerDistributionDescription serverDescription(globalDim, nbServer); 883 serverDescription.computeServerDistribution(); 884 885 std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin(); 886 std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes(); 887 888 CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE); 889 if (client->isServerLeader()) 890 { 891 std::list<CMessage> msgs; 892 893 const std::list<int>& ranks = client->getRanksServerLeader(); 894 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 895 { 896 // Use const int to ensure CMessage holds a copy of the value instead of just a reference 897 const int begin = serverIndexBegin[*itRank][orderPositionInGrid]; 898 const int ni = serverDimensionSizes[*itRank][orderPositionInGrid]; 899 900 msgs.push_back(CMessage()); 901 CMessage& msg = msgs.back(); 902 msg << this->getId(); 903 msg << ni << begin; 904 msg << isCompressible_; 905 906 event.push(*itRank,1,msg); 907 } 908 client->sendEvent(event); 909 } 910 else client->sendEvent(event); 911 } 912 } 913 CATCH_DUMP_ATTR 914 915 /* 916 Receive distribution attribute from another client 917 \param [in] event event containing data of these attributes 918 */ 919 void CAxis::recvDistributionAttribute(CEventServer& event) 920 TRY 921 { 922 CBufferIn* buffer = event.subEvents.begin()->buffer; 923 string axisId; 924 *buffer >> axisId; 925 get(axisId)->recvDistributionAttribute(*buffer); 926 } 927 CATCH 928 929 /* 930 Receive distribution attribute from another client 931 \param [in] buffer buffer containing data of these attributes 932 */ 933 void CAxis::recvDistributionAttribute(CBufferIn& buffer) 934 TRY 935 { 936 int ni_srv, begin_srv; 937 buffer >> ni_srv >> begin_srv; 938 buffer >> isCompressible_; 939 940 // Set up new local size of axis on the receiving clients 941 n.setValue(ni_srv); 942 begin.setValue(begin_srv); 943 } 944 CATCH_DUMP_ATTR 945 946 /* 947 Send attributes of axis from a group of client to other group of clients/servers 948 on supposing that these attributes are not distributed among the sending group 949 In the future, if new attributes are added, they should also be processed in this function 950 */ 951 void CAxis::sendNonDistributedAttributes() 952 TRY 953 { 954 std::list<CContextClient*>::iterator it; 955 for (it=clients.begin(); it!=clients.end(); ++it) 956 { 957 CContextClient* client = *it; 958 959 CEventClient event(getType(), EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES); 960 size_t nbIndex = index.numElements(); 961 size_t nbDataIndex = 0; 962 963 for (int idx = 0; idx < data_index.numElements(); ++idx) 964 { 965 int ind = data_index(idx); 966 if (ind >= 0 && ind < nbIndex) ++nbDataIndex; 967 } 968 969 CArray<int,1> dataIndex(nbDataIndex); 970 nbDataIndex = 0; 971 for (int idx = 0; idx < data_index.numElements(); ++idx) 972 { 973 int ind = data_index(idx); 974 if (ind >= 0 && ind < nbIndex) 975 { 976 dataIndex(nbDataIndex) = ind; 977 ++nbDataIndex; 978 } 979 } 980 981 if (client->isServerLeader()) 982 { 983 std::list<CMessage> msgs; 984 985 const std::list<int>& ranks = client->getRanksServerLeader(); 986 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 987 { 988 msgs.push_back(CMessage()); 989 CMessage& msg = msgs.back(); 990 msg << this->getId(); 991 msg << index.getValue() << dataIndex << mask.getValue(); 992 msg << hasValue; 993 if (hasValue) msg << value.getValue(); 994 msg << hasBounds; 995 if (hasBounds) msg << bounds.getValue(); 996 msg << hasLabel; 997 if (hasLabel) msg << label.getValue(); 998 999 event.push(*itRank, 1, msg); 1000 } 1001 client->sendEvent(event); 1002 } 1003 else client->sendEvent(event); 1004 } 1005 } 1006 CATCH_DUMP_ATTR 1007 1008 /* 1009 Receive the non-distributed attributes from another group of clients 1010 \param [in] event event containing data of these attributes 1011 */ 1012 void CAxis::recvNonDistributedAttributes(CEventServer& event) 1013 TRY 1014 { 1015 list<CEventServer::SSubEvent>::iterator it; 1016 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 1017 { 1018 CBufferIn* buffer = it->buffer; 1019 string axisId; 1020 *buffer >> axisId; 1021 get(axisId)->recvNonDistributedAttributes(it->rank, *buffer); 1022 } 1023 } 1024 CATCH 1025 1026 /* 1027 Receive the non-distributed attributes from another group of clients 1028 \param [in] rank rank of the sender 1029 \param [in] buffer buffer containing data sent from the sender 1030 */ 1031 void CAxis::recvNonDistributedAttributes(int rank, CBufferIn& buffer) 1032 TRY 1033 { 1034 CArray<int,1> tmp_index, tmp_data_index; 1035 CArray<bool,1> tmp_mask; 1036 CArray<double,1> tmp_val; 1037 CArray<double,2> tmp_bnds; 1038 CArray<string,1> tmp_label; 1039 1040 buffer >> tmp_index; 1041 index.reference(tmp_index); 1042 buffer >> tmp_data_index; 1043 data_index.reference(tmp_data_index); 1044 buffer >> tmp_mask; 1045 mask.reference(tmp_mask); 1046 1047 buffer >> hasValue; 1048 if (hasValue) 1049 { 1050 buffer >> tmp_val; 1051 value.reference(tmp_val); 1052 } 1053 1054 buffer >> hasBounds; 1055 if (hasBounds) 1056 { 1057 buffer >> tmp_bnds; 1058 bounds.reference(tmp_bnds); 1059 } 1060 1061 buffer >> hasLabel; 1062 if (hasLabel) 1063 { 1064 buffer >> tmp_label; 1065 label.reference(tmp_label); 1066 } 1067 1068 // Some value should be reset here 1069 data_begin.setValue(0); 1070 globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor())); 1071 // for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[idx] = index(idx); 1072 for (int idx = 0; idx < index.numElements(); ++idx) globalLocalIndexMap_[index(idx)] = idx; 1073 } 1074 CATCH_DUMP_ATTR 1075 1076 /* 1077 Send axis attributes from a group of clients to another group of clients/servers 1078 supposing that these attributes are distributed among the clients of the sending group 1079 In future, if new attributes are added, they should also be processed in this function 1080 */ 1081 void CAxis::sendDistributedAttributes(void) 1082 TRY 1083 { 1084 int ind, idx; 1085 std::list<CContextClient*>::iterator it; 1086 1087 for (it=clients.begin(); it!=clients.end(); ++it) 1088 { 1089 CContextClient* client = *it; 1090 int nbServer = client->serverSize; 1091 1092 CEventClient eventData(getType(), EVENT_ID_DISTRIBUTED_ATTRIBUTES); 1093 1094 list<CMessage> listData; 1095 list<CArray<int,1> > list_indi, list_dataInd; 1096 list<CArray<double,1> > list_val; 1097 list<CArray<double,2> > list_bounds; 1098 list<CArray<string,1> > list_label; 1099 1100 // Cut off the ghost points 1101 int nbIndex = index.numElements(); 1102 CArray<int,1> dataIndex(nbIndex); 1103 dataIndex = -1; 1104 for (idx = 0; idx < data_index.numElements(); ++idx) 1105 { 1106 if (0 <= data_index(idx) && data_index(idx) < nbIndex) 1107 dataIndex(data_index(idx)) = 1; 1108 } 1109 1110 std::unordered_map<int, std::vector<size_t> >::const_iterator it, iteMap; 1111 iteMap = indSrv_[nbServer].end(); 1112 for (int k = 0; k < connectedServerRank_[nbServer].size(); ++k) 1113 { 1114 int nbData = 0, nbDataCount = 0; 1115 int rank = connectedServerRank_[nbServer][k]; 1116 it = indSrv_[nbServer].find(rank); 1117 if (iteMap != it) 1118 nbData = it->second.size(); 1119 1120 list_indi.push_back(CArray<int,1>(nbData)); 1121 list_dataInd.push_back(CArray<int,1>(nbData)); 1122 1123 if (hasValue) 1124 list_val.push_back(CArray<double,1>(nbData)); 1125 1126 if (hasBounds) 1127 list_bounds.push_back(CArray<double,2>(2,nbData)); 1128 1129 if (hasLabel) 1130 list_label.push_back(CArray<string,1>(nbData)); 1131 1132 CArray<int,1>& indi = list_indi.back(); 1133 CArray<int,1>& dataIndi = list_dataInd.back(); 1134 dataIndi = -1; 1135 1136 for (int n = 0; n < nbData; ++n) 1137 { 1138 idx = static_cast<int>(it->second[n]); 1139 indi(n) = idx; 1140 1141 ind = globalLocalIndexMap_[idx]; 1142 dataIndi(n) = dataIndex(ind); 1143 1144 if (hasValue) 1145 { 1146 CArray<double,1>& val = list_val.back(); 1147 val(n) = value(ind); 1148 } 1149 1150 if (hasBounds) 1151 { 1152 CArray<double,2>& boundsVal = list_bounds.back(); 1153 boundsVal(0, n) = bounds(0,ind); 1154 boundsVal(1, n) = bounds(1,ind); 1155 } 1156 1157 if (hasLabel) 1158 { 1159 CArray<string,1>& labelVal = list_label.back(); 1160 labelVal(n) = label(ind); 1161 } 1162 } 1163 1164 listData.push_back(CMessage()); 1165 listData.back() << this->getId() 1166 << list_indi.back() << list_dataInd.back(); 1167 1168 listData.back() << hasValue; 1169 if (hasValue) 1170 listData.back() << list_val.back(); 1171 1172 listData.back() << hasBounds; 1173 if (hasBounds) 1174 listData.back() << list_bounds.back(); 1175 1176 listData.back() << hasLabel; 1177 if (hasLabel) 1178 listData.back() << list_label.back(); 1179 1180 eventData.push(rank, nbSenders[nbServer][rank], listData.back()); 1181 } 1182 1183 client->sendEvent(eventData); 1184 } 1185 } 1186 CATCH_DUMP_ATTR 1187 1188 /* 1189 Receive the distributed attributes from another group of clients 1190 \param [in] event event containing data of these attributes 1191 */ 1192 void CAxis::recvDistributedAttributes(CEventServer& event) 1193 TRY 1194 { 1195 string axisId; 1196 vector<int> ranks; 1197 vector<CBufferIn*> buffers; 1198 1199 list<CEventServer::SSubEvent>::iterator it; 1200 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 1201 { 1202 ranks.push_back(it->rank); 1203 CBufferIn* buffer = it->buffer; 1204 *buffer >> axisId; 1205 buffers.push_back(buffer); 1206 } 1207 get(axisId)->recvDistributedAttributes(ranks, buffers); 1208 } 1209 CATCH 1210 1211 /* 1212 Receive the non-distributed attributes from another group of clients 1213 \param [in] ranks rank of the sender 1214 \param [in] buffers buffer containing data sent from the sender 1215 */ 1216 void CAxis::recvDistributedAttributes(vector<int>& ranks, vector<CBufferIn*> buffers) 1217 TRY 1218 { 1219 int nbReceived = ranks.size(), idx, ind, gloInd, locInd; 1220 vector<CArray<int,1> > vec_indi(nbReceived), vec_dataInd(nbReceived); 1221 vector<CArray<double,1> > vec_val(nbReceived); 1222 vector<CArray<double,2> > vec_bounds(nbReceived); 1223 vector<CArray<string,1> > vec_label(nbReceived); 1224 1225 for (idx = 0; idx < nbReceived; ++idx) 1226 { 1227 CBufferIn& buffer = *buffers[idx]; 1228 buffer >> vec_indi[idx]; 1229 buffer >> vec_dataInd[idx]; 1230 1231 buffer >> hasValue; 1232 if (hasValue) 1233 buffer >> vec_val[idx]; 1234 1235 buffer >> hasBounds; 1236 if (hasBounds) 1237 buffer >> vec_bounds[idx]; 1238 1239 buffer >> hasLabel; 1240 if (hasLabel) 1241 buffer >> vec_label[idx]; 1242 } 1243 1244 // Estimate size of index array 1245 int nbIndexGlob = 0; 1246 for (idx = 0; idx < nbReceived; ++idx) 1247 { 1248 nbIndexGlob += vec_indi[idx].numElements(); 1249 } 1250 1251 // Recompute global index 1252 // Take account of the overlapped index 1253 index.resize(nbIndexGlob); 1254 globalLocalIndexMap_.rehash(std::ceil(index.numElements()/globalLocalIndexMap_.max_load_factor())); 1255 nbIndexGlob = 0; 1256 int nbIndLoc = 0; 1257 for (idx = 0; idx < nbReceived; ++idx) 1258 { 1259 CArray<int,1>& tmp = vec_indi[idx]; 1260 for (ind = 0; ind < tmp.numElements(); ++ind) 1261 { 1262 gloInd = tmp(ind); 1263 nbIndLoc = (gloInd % n_glo)-begin; 1264 if (0 == globalLocalIndexMap_.count(gloInd)) 1265 { 1266 index(nbIndexGlob) = gloInd % n_glo; 1267 globalLocalIndexMap_[gloInd] = nbIndexGlob; 1268 ++nbIndexGlob; 1269 } 1270 } 1271 } 1272 1273 // Resize index to its real size 1274 if (nbIndexGlob==0) index.resize(nbIndexGlob) ; 1275 else index.resizeAndPreserve(nbIndexGlob); 1276 1277 int nbData = nbIndexGlob; 1278 CArray<int,1> nonCompressedData(nbData); 1279 nonCompressedData = -1; 1280 // Mask is incorporated into data_index and is not sent/received anymore 1281 mask.resize(0); 1282 if (hasValue) 1283 value.resize(nbData); 1284 if (hasBounds) 1285 bounds.resize(2,nbData); 1286 if (hasLabel) 1287 label.resize(nbData); 1288 1289 nbData = 0; 1290 for (idx = 0; idx < nbReceived; ++idx) 1291 { 1292 CArray<int,1>& indi = vec_indi[idx]; 1293 CArray<int,1>& dataIndi = vec_dataInd[idx]; 1294 int nb = indi.numElements(); 1295 for (int n = 0; n < nb; ++n) 1296 { 1297 locInd = globalLocalIndexMap_[size_t(indi(n))]; 1298 1299 nonCompressedData(locInd) = (-1 == nonCompressedData(locInd)) ? dataIndi(n) : nonCompressedData(locInd); 1300 1301 if (hasValue) 1302 value(locInd) = vec_val[idx](n); 1303 1304 if (hasBounds) 1305 { 1306 bounds(0,locInd) = vec_bounds[idx](0,n); 1307 bounds(1,locInd) = vec_bounds[idx](1,n); 1308 } 1309 1310 if (hasLabel) 1311 label(locInd) = vec_label[idx](n); 1312 } 1313 } 1314 1315 int nbCompressedData = 0; 1316 for (idx = 0; idx < nonCompressedData.numElements(); ++idx) 1317 { 1318 if (0 <= nonCompressedData(idx)) 1319 ++nbCompressedData; 1320 } 1321 1322 data_index.resize(nbCompressedData); 1323 nbCompressedData = 0; 1324 for (idx = 0; idx < nonCompressedData.numElements(); ++idx) 1325 { 1326 if (0 <= nonCompressedData(idx)) 1327 { 1328 data_index(nbCompressedData) = idx % n; 1329 ++nbCompressedData; 1330 } 1331 } 1332 1333 data_begin.setValue(0); 1334 data_n.setValue(data_index.numElements()); 1335 } 1336 CATCH_DUMP_ATTR 1337 444 /* to remove later when reimplementing coupling */ 445 void CAxis::sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid) 446 { 447 if (sendAxisToCouplerOut_done_.count(client)!=0) return ; 448 else sendAxisToCouplerOut_done_.insert(client) ; 449 450 string axisId="_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ; 451 452 } 453 454 void CAxis::makeAliasForCoupling(const string& fieldId, int posInGrid) 455 { 456 const string axisId = "_axis["+std::to_string(posInGrid)+"]_of_"+fieldId ; 457 this->createAlias(axisId) ; 458 } 459 460 1338 461 /*! 1339 462 Compare two axis objects. … … 1432 555 * Go through the hierarchy to find the axis from which the transformations must be inherited 1433 556 */ 1434 void CAxis::solveInheritanceTransformation ()557 void CAxis::solveInheritanceTransformation_old() 1435 558 TRY 1436 559 { … … 1449 572 for (size_t i = 0; i < refAxis.size(); ++i) 1450 573 refAxis[i]->setTransformations(axis->getAllTransformations()); 574 } 575 CATCH_DUMP_ATTR 576 577 void CAxis::solveInheritanceTransformation() 578 TRY 579 { 580 if (solveInheritanceTransformation_done_) return; 581 else solveInheritanceTransformation_done_=true ; 582 583 CAxis* axis = this; 584 std::list<CAxis*> refAxis; 585 bool out=false ; 586 vector<StdString> excludedAttr; 587 excludedAttr.push_back("axis_ref"); 588 589 refAxis.push_front(axis) ; 590 while (axis->hasDirectAxisReference() && !out) 591 { 592 CAxis* lastAxis=axis ; 593 axis = axis->getDirectAxisReference(); 594 axis->solveRefInheritance() ; 595 if (!axis->SuperClass::isEqual(lastAxis,excludedAttr)) out=true ; 596 refAxis.push_front(axis) ; 597 } 598 599 CTransformationPaths::TPath path ; 600 auto& pathList = std::get<2>(path) ; 601 std::get<0>(path) = EElement::AXIS ; 602 std::get<1>(path) = refAxis.front()->getId() ; 603 for (auto& axis : refAxis) 604 { 605 CAxis::TransMapTypes transformations = axis->getAllTransformations(); 606 for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 607 transformation.second->getId()}) ; 608 } 609 transformationPaths_.addPath(path) ; 610 1451 611 } 1452 612 CATCH_DUMP_ATTR … … 1497 657 CATCH_DUMP_ATTR 1498 658 659 660 ////////////////////////////////////////////////////////////////////////////////////// 661 // this part is related to distribution, element definition, views and connectors // 662 ////////////////////////////////////////////////////////////////////////////////////// 663 664 void CAxis::initializeLocalElement(void) 665 { 666 // after checkAttribute index of size n 667 int rank = CContext::getCurrent()->getIntraCommRank() ; 668 669 CArray<size_t,1> ind(n) ; 670 for (int i=0;i<n;i++) ind(i)=index(i) ; 671 672 localElement_ = new CLocalElement(rank, n_glo, ind) ; 673 } 674 675 void CAxis::addFullView(void) 676 { 677 CArray<int,1> index(n) ; 678 for(int i=0; i<n ; i++) index(i)=i ; 679 localElement_ -> addView(CElementView::FULL, index) ; 680 } 681 682 void CAxis::addWorkflowView(void) 683 { 684 // mask + data are included into data_index 685 int nk=data_index.numElements() ; 686 int nMask=0 ; 687 for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ; 688 689 CArray<int,1> index(nMask) ; 690 nMask=0 ; 691 for(int k=0;k<nk;k++) 692 if (data_index(k)>=0 && data_index(k)<n) 693 { 694 index(nMask) = data_index(k) ; 695 nMask++ ; 696 } 697 localElement_ -> addView(CElementView::WORKFLOW, index) ; 698 } 699 700 void CAxis::addModelView(void) 701 { 702 // information for model view is stored in data_index 703 localElement_->addView(CElementView::MODEL, data_index) ; 704 } 705 706 void CAxis::computeModelToWorkflowConnector(void) 707 { 708 CLocalView* srcView=getLocalView(CElementView::MODEL) ; 709 CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ; 710 modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 711 modelToWorkflowConnector_->computeConnector() ; 712 } 713 714 715 void CAxis::computeRemoteElement(CContextClient* client, EDistributionType type) 716 { 717 CContext* context = CContext::getCurrent(); 718 map<int, CArray<size_t,1>> globalIndex ; 719 720 if (type==EDistributionType::BANDS) // Bands distribution to send to file server 721 { 722 int nbServer = client->serverSize; 723 int nbClient = client->clientSize ; 724 int rankClient = client->clientRank ; 725 int size = nbServer / nbClient ; 726 int start ; 727 if (nbServer%nbClient > rankClient) 728 { 729 start = (size+1) * rankClient ; 730 size++ ; 731 } 732 else start = size*rankClient + nbServer%nbClient ; 733 734 for(int i=0; i<size; i++) 735 { 736 int rank=start+i ; 737 size_t indSize = n_glo/nbServer ; 738 size_t indStart ; 739 if (n_glo % nbServer > rank) 740 { 741 indStart = (indSize+1) * rank ; 742 indSize++ ; 743 } 744 else indStart = indSize*rank + n_glo%nbServer ; 745 746 auto& globalInd = globalIndex[rank] ; 747 globalInd.resize(indSize) ; 748 for(size_t n = 0 ; n<indSize; n++) globalInd(n)=indStart+n ; 749 } 750 } 751 else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain 752 { 753 int nbServer = client->serverSize; 754 size_t nglo=n_glo ; 755 CArray<size_t,1> indGlo(nglo) ; 756 for(size_t i=0;i<nglo;i++) indGlo(i) = i ; 757 for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()); 758 } 759 remoteElement_[client] = new CDistributedElement(n_glo, globalIndex) ; 760 remoteElement_[client]->addFullView() ; 761 } 762 763 void CAxis::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 764 CScattererConnector* &scattererConnector, const string& axisId) 765 { 766 string serverAxisId = axisId.empty() ? this->getId() : axisId ; 767 CContext* context = CContext::getCurrent(); 768 769 this->sendAllAttributesToServer(client, serverAxisId) ; 770 771 CDistributedElement scatteredElement(n_glo,globalIndex) ; 772 scatteredElement.addFullView() ; 773 scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 774 context->getIntraComm(), client->getRemoteSize()) ; 775 scattererConnector->computeConnector() ; 776 777 // phase 0 778 // send remote element to construct the full view on server, ie without hole 779 CEventClient event0(getType(), EVENT_ID_AXIS_DISTRIBUTION); 780 CMessage message0 ; 781 message0<<serverAxisId<<0 ; 782 remoteElement_[client]->sendToServer(client,event0,message0) ; 783 784 // phase 1 785 // send the full view of element to construct the connector which connect distributed data coming from client to the full local view 786 CEventClient event1(getType(), EVENT_ID_AXIS_DISTRIBUTION); 787 CMessage message1 ; 788 message1<<serverAxisId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 789 scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ; 790 791 sendDistributedAttributes(client, *scattererConnector, axisId) ; 792 793 // phase 2 send the mask : data index + mask2D 794 CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize()); 795 CArray<bool,1> maskOut ; 796 CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ; 797 workflowToFull.computeConnector() ; 798 maskIn=true ; 799 workflowToFull.transfer(maskIn,maskOut,false) ; 800 801 // phase 3 : prepare grid scatterer connector to send data from client to server 802 map<int,CArray<size_t,1>> workflowGlobalIndex ; 803 map<int,CArray<bool,1>> maskOut2 ; 804 scattererConnector->transfer(maskOut, maskOut2) ; 805 scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ; 806 scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ; 807 // create new workflow view for scattered element 808 CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ; 809 clientToServerElement.addFullView() ; 810 CEventClient event2(getType(), EVENT_ID_AXIS_DISTRIBUTION); 811 CMessage message2 ; 812 message2<<serverAxisId<<2 ; 813 clientToServerElement.sendToServer(client, event2, message2) ; 814 clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 815 context->getIntraComm(), client->getRemoteSize()) ; 816 clientToServerConnector_[client]->computeConnector() ; 817 818 clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)); 819 clientFromServerConnector_[client]->computeConnector() ; 820 821 822 } 823 824 void CAxis::recvAxisDistribution(CEventServer& event) 825 TRY 826 { 827 string axisId; 828 int phasis ; 829 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> phasis ; 830 get(axisId)->receivedAxisDistribution(event, phasis); 831 } 832 CATCH 833 834 835 void CAxis::receivedAxisDistribution(CEventServer& event, int phasis) 836 TRY 837 { 838 CContext* context = CContext::getCurrent(); 839 if (phasis==0) // receive the remote element to construct the full view 840 { 841 localElement_ = new CLocalElement(context->getIntraCommRank(),event) ; 842 localElement_->addFullView() ; 843 // construct the local dimension and indexes 844 auto& globalIndex=localElement_->getGlobalIndex() ; 845 int nk=globalIndex.numElements() ; 846 int minK=n_glo,maxK=-1 ; 847 int nGlo=n_glo ; 848 int indGlo ; 849 for(int k=0;k<nk;k++) 850 { 851 indGlo=globalIndex(k) ; 852 if (indGlo<minK) minK=indGlo ; 853 if (indGlo>maxK) maxK=indGlo ; 854 } 855 if (maxK>=minK) { begin=minK ; n=maxK-minK+1 ; } 856 else {begin=0; n=0 ;} 857 858 } 859 else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server 860 { 861 CContext* context = CContext::getCurrent(); 862 CDistributedElement* elementFrom = new CDistributedElement(event) ; 863 elementFrom->addFullView() ; 864 gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 865 gathererConnector_->computeConnector() ; 866 } 867 else if (phasis==2) 868 { 869 // delete gathererConnector_ ; 870 elementFrom_ = new CDistributedElement(event) ; 871 elementFrom_->addFullView() ; 872 // gathererConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 873 // gathererConnector_ -> computeConnector() ; 874 } 875 876 } 877 CATCH 878 879 void CAxis::setServerMask(CArray<bool,1>& serverMask, CContextClient* client) 880 TRY 881 { 882 CContext* context = CContext::getCurrent(); 883 localElement_->addView(CElementView::WORKFLOW, serverMask) ; 884 mask.reference(serverMask.copy()) ; 885 886 serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ; 887 serverFromClientConnector_->computeConnector() ; 888 889 serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL), 890 context->getIntraComm(), client->getRemoteSize()) ; 891 serverToClientConnector_->computeConnector() ; 892 } 893 CATCH_DUMP_ATTR 894 895 void CAxis::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId) 896 { 897 string serverAxisId = axisId.empty() ? this->getId() : axisId ; 898 CContext* context = CContext::getCurrent(); 899 900 if (hasValue) 901 { 902 { // send level value 903 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 904 CMessage message ; 905 message<<serverAxisId<<string("value") ; 906 scattererConnector.transfer(value, client, event,message) ; 907 } 908 } 909 910 if (hasBounds) 911 { 912 { // send bounds level value 913 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 914 CMessage message ; 915 message<<serverAxisId<<string("bounds") ; 916 scattererConnector.transfer(2, bounds, client, event,message) ; 917 } 918 } 919 920 if (hasLabel) 921 { 922 { // send label 923 // need to transform array of string (no fixed size for string) into array of array of char 924 // to use connector to transfer 925 // the strings must have fixed size which the maximum lenght over the string label. 926 int maxSize=0 ; 927 for(int i=0; i<label.numElements();i++) 928 if (maxSize < label(i).size()) maxSize=label(i).size() ; 929 MPI_Allreduce(MPI_IN_PLACE, &maxSize,1,MPI_INT,MPI_MAX, context->getIntraComm()) ; 930 maxSize=maxSize+1 ; 931 CArray<char,2> charArray(maxSize,label.numElements()) ; 932 for(int j=0; j<label.numElements();j++) 933 { 934 const char* str = label(j).c_str() ; 935 int strSize=label(j).size()+1 ; 936 for(int i=0; i<strSize; i++) charArray(i,j) = str[i] ; 937 } 938 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 939 CMessage message ; 940 message<<serverAxisId<<string("label")<<maxSize ; 941 scattererConnector.transfer(maxSize, charArray, client, event,message) ; 942 } 943 } 944 } 945 946 void CAxis::recvDistributedAttributes(CEventServer& event) 947 TRY 948 { 949 string axisId; 950 string type ; 951 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> axisId >> type ; 952 get(axisId)->recvDistributedAttributes(event, type); 953 } 954 CATCH 955 956 void CAxis::recvDistributedAttributes(CEventServer& event, const string& type) 957 TRY 958 { 959 if (type=="value") 960 { 961 gathererConnector_->transfer(event, value, 0.); 962 } 963 else if (type=="bounds") 964 { 965 CArray<double,1> value ; 966 gathererConnector_->transfer(event, 2, value, 0.); 967 bounds.resize(2,n) ; 968 if (bounds.numElements() > 0 ) bounds=CArray<double,2>(value.dataFirst(),shape(2,n),neverDeleteData) ; 969 } 970 else if (type=="label") 971 { 972 int maxSize ; 973 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> maxSize ; 974 CArray<char,1> value ; 975 gathererConnector_->transfer(event, maxSize, value, '\0'); 976 CArray<char,2> charArray(maxSize,n) ; 977 label.resize(n) ; 978 if (n>0) 979 { 980 charArray=CArray<char,2>(value.dataFirst(),shape(maxSize,n),neverDeleteData) ; 981 for(int j=0;j<n;j++) 982 { 983 int strSize ; 984 for(int i=0;i<maxSize;i++) 985 if (charArray(i,j)=='\0') { strSize=i ; break; } 986 string str(strSize,'\0') ; 987 for(int i=0;i<strSize;i++) str[i]=charArray(i,j) ; 988 label(j)=str ; 989 } 990 } 991 } 992 } 993 CATCH 994 1499 995 DEFINE_REF_FUNC(Axis,axis) 1500 996 -
XIOS/dev/dev_trunk_graph/src/node/axis.hpp
r1653 r2019 16 16 #include "transformation.hpp" 17 17 #include "transformation_enum.hpp" 18 19 namespace xios { 18 #include "transformation_path.hpp" 19 #include "element.hpp" 20 #include "local_connector.hpp" 21 #include "scatterer_connector.hpp" 22 #include "gatherer_connector.hpp" 23 #include "distribution_type.hpp" 24 #include "generic_algorithm_transformation.hpp" 25 26 27 namespace xios 28 { 20 29 /// ////////////////////// Déclarations ////////////////////// /// 21 30 … … 44 53 enum EEventId 45 54 { 46 EVENT_ID_DISTRIBUTION_ATTRIBUTE, 47 EVENT_ID_DISTRIBUTED_VALUE, 48 EVENT_ID_NON_DISTRIBUTED_VALUE, 49 EVENT_ID_NON_DISTRIBUTED_ATTRIBUTES, 50 EVENT_ID_DISTRIBUTED_ATTRIBUTES 55 EVENT_ID_AXIS_DISTRIBUTION, 56 EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE 51 57 } ; 52 58 … … 54 60 typedef CAxisAttributes RelAttributes; 55 61 typedef CAxisGroup RelGroup; 56 typedef CTransformation<CAxis>::TransformationMapTypes TransMapTypes;57 62 58 63 public: … … 67 72 /// Accesseurs /// 68 73 const std::set<StdString> & getRelFiles(void) const; 69 70 int getNumberWrittenIndexes(MPI_Comm writtenCom); 71 int getTotalNumberWrittenIndexes(MPI_Comm writtenCom); 72 int getOffsetWrittenIndexes(MPI_Comm writtenCom); 73 CArray<int, 1>& getCompressedIndexToWriteOnServer(MPI_Comm writtenCom); 74 74 75 75 std::map<int, StdSize> getAttributesBufferSize(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, 76 76 CServerDistributionDescription::ServerDistributionType disType = CServerDistributionDescription::BAND_DISTRIBUTION); … … 80 80 bool isWrittenCompressed(const StdString& filename) const; 81 81 bool isDistributed(void) const; 82 bool isCompressible(void) const; 82 83 public: 84 /*! 85 \brief return if the axis can be written or not in a compressed way. 86 ie if there are some masked or indexed point on the domain. Valid only on server side. 87 \return true if domain can be writtedn in a compressed way 88 */ 89 bool isCompressible(void) { if (!isCompressibleComputed_) computeIsCompressible() ; return isCompressible_ ;} 90 private: 91 bool isCompressible_ ; /** specify if the domain can be written in a compressed way */ 92 bool isCompressibleComputed_=false ; /** Indicate if compressability has been computed*/ 93 void computeIsCompressible() ; 94 95 public: 83 96 84 97 /// Mutateur /// … … 86 99 void addRelFileCompressed(const StdString& filename); 87 100 88 /// Vérifications /// 89 void checkAttributes(void); 101 90 102 91 103 /// Destructeur /// … … 102 114 103 115 static bool dispatchEvent(CEventServer& event); 104 105 void checkAttributesOnClient(); 106 void checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid, 107 CServerDistributionDescription::ServerDistributionType distType = CServerDistributionDescription::BAND_DISTRIBUTION); 108 void sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, 109 CServerDistributionDescription::ServerDistributionType disType = CServerDistributionDescription::BAND_DISTRIBUTION); 110 111 void checkEligibilityForCompressedOutput(); 116 117 /// Vérifications /// 118 void checkAttributes(void); 119 bool checkAttributes_done_ = false ; 120 112 121 size_t getGlobalWrittenSize(void) ; 113 122 114 void computeWrittenIndex(); 115 void computeWrittenCompressedIndex(MPI_Comm); 116 bool hasTransformation(); 117 void solveInheritanceTransformation(); 118 TransMapTypes getAllTransformations(); 119 void duplicateTransformation(CAxis*); 120 CTransformation<CAxis>* addTransformation(ETranformationType transType, const StdString& id=""); 123 ////////////////////////// 124 ///// transformations //// 125 ////////////////////////// 126 public: 127 typedef CTransformation<CAxis>::TransformationMapTypes TransMapTypes; 128 private: 129 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 130 static std::map<StdString, ETranformationType> transformationMapList_; 131 static bool dummyTransformationMapList_; 132 TransMapTypes transformationMap_; 133 134 public: 135 CTransformation<CAxis>* addTransformation(ETranformationType transType, const StdString& id=""); 136 CTransformation<CAxis>* addTransformation(ETranformationType transType, CTransformation<CAxis>* transformation) ; 137 void setTransformations(const TransMapTypes&); 138 void duplicateTransformation(CAxis*); 139 TransMapTypes getAllTransformations(); 140 bool hasTransformation(); 141 void solveInheritanceTransformation_old(); // to remove later 142 void solveInheritanceTransformation(); 143 private: 144 bool solveInheritanceTransformation_done_= false ; 145 private: 146 CGenericAlgorithmTransformation* transformationAlgorithm_ = nullptr ; 147 public: 148 void setTransformationAlgorithm(CGenericAlgorithmTransformation* transformationAlgorithm) { transformationAlgorithm_=transformationAlgorithm ;} 149 CGenericAlgorithmTransformation* getTransformationAlgorithm(void) { return transformationAlgorithm_ ;} 150 private: 151 CTransformationPaths transformationPaths_ ; 152 public: 153 CTransformationPaths getTransformationPaths(void) {return transformationPaths_;} 154 void setTransformationPaths(const CTransformationPaths& transformationPaths) { transformationPaths_=transformationPaths ;} 155 156 //////////////////////////// 121 157 bool isEqual(CAxis* axis); 122 158 … … 126 162 bool hasLabel; 127 163 128 CArray<int,1> localIndexToWriteOnServer;129 130 164 private: 131 165 void checkData(); … … 133 167 void checkBounds(); 134 168 void checkLabel(); 135 void sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid, 136 CServerDistributionDescription::ServerDistributionType distType); 137 void sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid, 138 CServerDistributionDescription::ServerDistributionType distType); 139 void computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 140 CServerDistributionDescription::ServerDistributionType distType); 141 142 void sendNonDistributedAttributes(void); 143 void sendDistributedAttributes(void); 144 145 static void recvNonDistributedAttributes(CEventServer& event); 146 static void recvDistributedAttributes(CEventServer& event); 147 static void recvDistributionAttribute(CEventServer& event); 148 void recvNonDistributedAttributes(int rank, CBufferIn& buffer); 149 void recvDistributedAttributes(vector<int>& rank, vector<CBufferIn*> buffers); 150 void recvDistributionAttribute(CBufferIn& buffer); 151 152 void setTransformations(const TransMapTypes&); 153 154 private: 155 156 /** Clients that have to send a domain. There can be multiple clients in case of secondary server, otherwise only one client. */ 169 170 public: 171 void sendAxisToCouplerOut(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid, const string& fieldId, int posInGrid) ; 172 private: 173 std::set<CContextClient*> sendAxisToCouplerOut_done_ ; 174 175 public: 176 void makeAliasForCoupling(const string& fieldId, int posInGrid) ; 177 178 179 private: 180 181 /** Clients that have to send a axis. There can be multiple clients in case of secondary server, otherwise only one client. */ 157 182 std::list<CContextClient*> clients; 158 183 std::set<CContextClient*> clientsSet; 159 184 185 private: 186 /** define if the axis is completed or not ie all attributes have been received before in case 187 of grid reading from file or coupling */ 188 bool isCompleted_=true ; 189 public: 190 /*! 191 \brief Check if a axis is completed 192 Before make any axis processing, we must be sure that all axis informations have 193 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 194 other context (coupling). So all direct reference of the axis (axis_ref) must be also completed 195 \return true if axis and axis reference are completed 196 */ 197 bool isCompleted(void) 198 { 199 if (hasDirectAxisReference()) if (!getDirectAxisReference()->isCompleted()) return false; 200 else return isCompleted_ ; 201 } 202 void setCompleted(void) { isCompleted_=true ; } 203 void unsetCompleted(void) { isCompleted_=false ; } 204 205 private: 160 206 bool isChecked; 161 bool areClientAttributesChecked_;162 bool isClientAfterTransformationChecked;163 207 std::set<StdString> relFiles, relFilesCompressed; 164 TransMapTypes transformationMap_; 165 //! True if and only if the data defined on the axis can be outputted in a compressed way 166 bool isCompressible_; 167 std::map<int, map<int,int> > nbSenders; // Mapping of number of communicating client to a server 168 std::map<int, std::unordered_map<int, vector<size_t> > > indSrv_; // Global index of each client sent to server 169 // std::map<int, vector<int> > indWrittenSrv_; // Global written index of each client sent to server 170 std::unordered_map<size_t,size_t> globalLocalIndexMap_; 171 std::vector<int> indexesToWrite; 172 std::map<int,int> numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_; 173 std::map<int, CArray<int, 1> > compressedIndexToWriteOnServer; 208 std::map<int, std::unordered_map<int, vector<size_t> > > indSrv_; // Global index of each client sent to server 174 209 std::map<int, std::vector<int> > connectedServerRank_; 175 bool computedWrittenIndex_; 176 177 private: 178 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 179 static std::map<StdString, ETranformationType> transformationMapList_; 180 static bool dummyTransformationMapList_; 210 211 ////////////////////////////////////////////////////////////////////////////////////// 212 // this part is related to distribution, element definition, views and connectors // 213 ////////////////////////////////////////////////////////////////////////////////////// 214 215 private: 216 CLocalElement* localElement_ = nullptr ; 217 void initializeLocalElement(void) ; 218 public: 219 CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; } 220 CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;} 221 private: 222 void addFullView(void) ; 223 void addWorkflowView(void) ; 224 void addModelView(void) ; 225 226 private: 227 CLocalConnector* modelToWorkflowConnector_ ; 228 void computeModelToWorkflowConnector(void) ; 229 public: 230 CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;} 231 232 public: 233 void computeRemoteElement(CContextClient* client, EDistributionType) ; 234 void distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, CScattererConnector* &scattererConnector, 235 const string& axisId="") ; 236 237 static void recvAxisDistribution(CEventServer& event) ; 238 void receivedAxisDistribution(CEventServer& event, int phasis) ; 239 void setServerMask(CArray<bool,1>& serverMask, CContextClient* client ) ; 240 void sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& axisId) ; 241 static void recvDistributedAttributes(CEventServer& event) ; 242 void recvDistributedAttributes(CEventServer& event, const string& type) ; 243 private: 244 map<CContextClient*, CDistributedElement*> remoteElement_ ; 245 public: 246 CDistributedElement* getRemoteElement(CContextClient* client) {return remoteElement_[client] ;} 247 private: 248 map<CContextClient*, CScattererConnector*> clientToServerConnector_ ; 249 public: 250 CScattererConnector* getClientToServerConnector(CContextClient* client) { return clientToServerConnector_[client] ;} 251 private: 252 CGathererConnector* gathererConnector_ ; 253 public: 254 CGathererConnector* getGathererConnector(void) { return gathererConnector_ ;} 255 private: 256 CGathererConnector* serverFromClientConnector_ ; 257 CDistributedElement* elementFrom_ ; 258 public: 259 CGathererConnector* getServerFromClientConnector(void) { return serverFromClientConnector_ ;} 260 261 private: 262 CScattererConnector* serverToClientConnector_ = nullptr ; 263 public: 264 CScattererConnector* getServerToClientConnector(void) { return serverToClientConnector_ ;} 265 266 private: 267 map<CContextClient*,CGathererConnector*> clientFromServerConnector_ ; 268 public: 269 CGathererConnector* getClientFromServerConnector(CContextClient* client) { return clientFromServerConnector_[client] ;} 181 270 182 271 DECLARE_REF_FUNC(Axis,axis) -
XIOS/dev/dev_trunk_graph/src/node/compute_connectivity_domain.cpp
r944 r2019 1 1 #include "compute_connectivity_domain.hpp" 2 #include "domain_algorithm_compute_connectivity.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CComputeConnectivityDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_COMPUTE_CONNECTIVITY_DOMAIN, CComputeConnectivityDomain::create);30 registerTransformation(TRANS_COMPUTE_CONNECTIVITY_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 51 52 } 52 53 54 CGenericAlgorithmTransformation* CComputeConnectivityDomain::createAlgorithm(bool isSource, 55 CGrid* gridDst, CGrid* gridSrc, 56 int elementPositionInGrid, 57 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 58 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 59 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 60 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 61 std::map<int, int>& elementPositionInGridDst2AxisPosition, 62 std::map<int, int>& elementPositionInGridDst2DomainPosition) 63 { 64 return CDomainAlgorithmComputeConnectivity::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 65 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 66 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 67 } 53 68 } -
XIOS/dev/dev_trunk_graph/src/node/compute_connectivity_domain.hpp
r934 r2019 20 20 class CComputeConnectivityDomain; 21 21 class CDomain; 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 22 24 23 25 ///-------------------------------------------------------------- … … 41 43 typedef CObjectTemplate<CComputeConnectivityDomain> SuperClass; 42 44 typedef CComputeConnectivityDomainAttributes SuperClassAttribute; 45 typedef CComputeConnectivityDomain MyClass ; 46 typedef CTransformation<CDomain> SuperTransform ; 43 47 44 48 public : … … 56 60 static StdString GetDefName(void); 57 61 static ENodeType GetType(void); 62 const string& getId(void) { return this->SuperClass::getId();} 63 ETranformationType getTransformationType(void) { return TRANS_COMPUTE_CONNECTIVITY_DOMAIN ;} 64 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 65 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 66 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 67 CGrid* gridDst, CGrid* gridSrc, 68 int elementPositionInGrid, 69 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 70 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 71 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 72 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 73 std::map<int, int>& elementPositionInGridDst2AxisPosition, 74 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 75 private: 59 76 static bool registerTrans(); 60 77 static CTransformation<CDomain>* create(const StdString& id, xml::CXMLNode* node); 61 78 static bool _dummyRegistered; 62 }; // class CComputeConnectivityDomain 79 public: 80 }; // class CComputeConnectivityDomain 63 81 64 82 DECLARE_GROUP(CComputeConnectivityDomain); -
XIOS/dev/dev_trunk_graph/src/node/context.cpp
r1612 r2019 20 20 #include "server.hpp" 21 21 #include "distribute_file_server2.hpp" 22 #include "services_manager.hpp" 23 #include "contexts_manager.hpp" 24 #include "cxios.hpp" 25 #include "client.hpp" 26 #include "coupler_in.hpp" 27 #include "coupler_out.hpp" 22 28 23 29 namespace xios { … … 31 37 , calendar(), hasClient(false), hasServer(false) 32 38 , isPostProcessed(false), finalized(false) 33 , idServer_(), client(0), server(0)34 , allProcessed(false), countChildC tx_(0)39 , client(nullptr), server(nullptr) 40 , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false) 35 41 36 42 { /* Ne rien faire de plus */ } … … 40 46 , calendar(), hasClient(false), hasServer(false) 41 47 , isPostProcessed(false), finalized(false) 42 , idServer_(), client(0), server(0)43 , allProcessed(false), countChildC tx_(0)48 , client(nullptr), server(nullptr) 49 , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false) 44 50 { /* Ne rien faire de plus */ } 45 51 … … 264 270 ///--------------------------------------------------------------- 265 271 266 //! Initialize client side 267 void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/) 268 TRY 269 { 270 271 hasClient = true; 272 MPI_Comm intraCommServer, interCommServer; 272 273 void CContext::setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting) 274 TRY 275 { 276 // Estimated minimum event size for small events (20 is an arbitrary constant just for safety) 277 const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int); 278 // Ensure there is at least some room for 20 of such events in the buffers 279 size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize); 280 281 #define DECLARE_NODE(Name_, name_) \ 282 if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition); 283 #define DECLARE_NODE_PAR(Name_, name_) 284 #include "node_type.conf" 285 #undef DECLARE_NODE 286 #undef DECLARE_NODE_PAR 287 288 289 map<CContextClient*,map<int,size_t>> dataSize ; 290 map<CContextClient*,map<int,size_t>> maxEventSize ; 291 map<CContextClient*,map<int,size_t>> attributesSize ; 292 293 for(auto field : fields) 294 { 295 field->setContextClientDataBufferSize(dataSize, maxEventSize, bufferForWriting) ; 296 field->setContextClientAttributesBufferSize(attributesSize, maxEventSize, bufferForWriting) ; 297 } 273 298 274 299 275 if (CServer::serverLevel != 1) 276 // initClient is called by client 277 { 278 client = new CContextClient(this, intraComm, interComm, cxtServer); 279 if (cxtServer) // Attached mode 300 for(auto& it : attributesSize) 301 { 302 auto contextClient = it.first ; 303 auto& contextDataSize = dataSize[contextClient] ; 304 auto& contextAttributesSize = attributesSize[contextClient] ; 305 auto& contextMaxEventSize = maxEventSize[contextClient] ; 306 307 for (auto& it : contextAttributesSize) 280 308 { 281 intraCommServer = intraComm; 282 interCommServer = interComm; 309 auto serverRank=it.first ; 310 auto& buffer = contextAttributesSize[serverRank] ; 311 if (contextDataSize[serverRank] > buffer) buffer=contextDataSize[serverRank] ; 312 buffer *= CXios::bufferSizeFactor; 313 if (buffer < minBufferSize) buffer = minBufferSize; 314 if (buffer > CXios::maxBufferSize ) buffer = CXios::maxBufferSize; 283 315 } 284 else 285 { 286 MPI_Comm_dup(intraComm, &intraCommServer); 287 comms.push_back(intraCommServer); 288 MPI_Comm_dup(interComm, &interCommServer); 289 comms.push_back(interCommServer); 290 } 291 /* for registry take the id of client context */ 292 /* for servers, supress the _server_ from id */ 293 string contextRegistryId=getId() ; 294 size_t pos=contextRegistryId.find("_server_") ; 295 if (pos!=std::string::npos) contextRegistryId=contextRegistryId.substr(0,pos) ; 296 297 registryIn=new CRegistry(intraComm); 298 registryIn->setPath(contextRegistryId) ; 299 if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ; 300 registryIn->bcastRegistry() ; 301 registryOut=new CRegistry(intraComm) ; 302 303 registryOut->setPath(contextRegistryId) ; 304 305 server = new CContextServer(this, intraCommServer, interCommServer); 306 } 307 else 308 // initClient is called by primary server 309 { 310 clientPrimServer.push_back(new CContextClient(this, intraComm, interComm)); 311 MPI_Comm_dup(intraComm, &intraCommServer); 312 comms.push_back(intraCommServer); 313 MPI_Comm_dup(interComm, &interCommServer); 314 comms.push_back(interCommServer); 315 serverPrimServer.push_back(new CContextServer(this, intraCommServer, interCommServer)); 316 } 317 } 318 CATCH_DUMP_ATTR 319 320 /*! 316 317 // Leaders will have to send some control events so ensure there is some room for those in the buffers 318 if (contextClient->isServerLeader()) 319 for(auto& rank : contextClient->getRanksServerLeader()) 320 if (!contextAttributesSize.count(rank)) 321 { 322 contextAttributesSize[rank] = minBufferSize; 323 contextMaxEventSize[rank] = minEventSize; 324 } 325 326 contextClient->setBufferSize(contextAttributesSize, contextMaxEventSize); 327 } 328 } 329 CATCH_DUMP_ATTR 330 331 332 /*! 321 333 Sets client buffers. 322 334 \param [in] contextClient … … 324 336 This flag is only true for client and server-1 for communication with server-2 325 337 */ 338 // ym obsolete to be removed 326 339 void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting) 327 340 TRY 328 341 { 329 // Estimated minimum event size for small events ( 10 is an arbitrary constant just for safety)330 const size_t minEventSize = CEventClient::headerSize + getIdServer().size() + 10 * sizeof(int);342 // Estimated minimum event size for small events (20 is an arbitrary constant just for safety) 343 const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int); 331 344 332 345 // Ensure there is at least some room for 20 of such events in the buffers … … 375 388 CATCH_DUMP_ATTR 376 389 390 /*! 391 * Compute the required buffer size to send the fields data. 392 * \param maxEventSize [in/out] the size of the bigger event for each connected server 393 * \param [in] contextClient 394 * \param [in] bufferForWriting True if buffers are used for sending data for writing 395 This flag is only true for client and server-1 for communication with server-2 396 */ 397 std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize, 398 CContextClient* contextClient, bool bufferForWriting /*= "false"*/) 399 TRY 400 { 401 std::map<int, StdSize> dataSize; 402 403 // Find all reference domain and axis of all active fields 404 std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles; 405 size_t numEnabledFiles = fileList.size(); 406 for (size_t i = 0; i < numEnabledFiles; ++i) 407 { 408 CFile* file = fileList[i]; 409 if (file->getContextClient() == contextClient) 410 { 411 std::vector<CField*> enabledFields = file->getEnabledFields(); 412 size_t numEnabledFields = enabledFields.size(); 413 for (size_t j = 0; j < numEnabledFields; ++j) 414 { 415 // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient); 416 const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting); 417 std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end(); 418 for (; it != itE; ++it) 419 { 420 // If dataSize[it->first] does not exist, it will be zero-initialized 421 // so we can use it safely without checking for its existance 422 if (CXios::isOptPerformance) 423 dataSize[it->first] += it->second; 424 else if (dataSize[it->first] < it->second) 425 dataSize[it->first] = it->second; 426 427 if (maxEventSize[it->first] < it->second) 428 maxEventSize[it->first] = it->second; 429 } 430 } 431 } 432 } 433 return dataSize; 434 } 435 CATCH_DUMP_ATTR 436 437 /*! 438 * Compute the required buffer size to send the attributes (mostly those grid related). 439 * \param maxEventSize [in/out] the size of the bigger event for each connected server 440 * \param [in] contextClient 441 * \param [in] bufferForWriting True if buffers are used for sending data for writing 442 This flag is only true for client and server-1 for communication with server-2 443 */ 444 std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize, 445 CContextClient* contextClient, bool bufferForWriting /*= "false"*/) 446 TRY 447 { 448 // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes 449 std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient); 450 maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient); 451 452 std::vector<CFile*>& fileList = this->enabledFiles; 453 size_t numEnabledFiles = fileList.size(); 454 for (size_t i = 0; i < numEnabledFiles; ++i) 455 { 456 // CFile* file = this->enabledWriteModeFiles[i]; 457 CFile* file = fileList[i]; 458 std::vector<CField*> enabledFields = file->getEnabledFields(); 459 size_t numEnabledFields = enabledFields.size(); 460 for (size_t j = 0; j < numEnabledFields; ++j) 461 { 462 const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting); 463 std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end(); 464 for (; it != itE; ++it) 465 { 466 // If attributesSize[it->first] does not exist, it will be zero-initialized 467 // so we can use it safely without checking for its existence 468 if (attributesSize[it->first] < it->second) 469 attributesSize[it->first] = it->second; 470 471 if (maxEventSize[it->first] < it->second) 472 maxEventSize[it->first] = it->second; 473 } 474 } 475 } 476 return attributesSize; 477 } 478 CATCH_DUMP_ATTR 479 480 481 377 482 //! Verify whether a context is initialized 378 483 bool CContext::isInitialized(void) … … 383 488 CATCH_DUMP_ATTR 384 489 385 void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/) 490 491 void CContext::init(CServerContext* parentServerContext, MPI_Comm intraComm, int serviceType) 492 TRY 493 { 494 parentServerContext_ = parentServerContext ; 495 if (serviceType==CServicesManager::CLIENT) 496 initClient(intraComm, serviceType) ; 497 else 498 initServer(intraComm, serviceType) ; 499 } 500 CATCH_DUMP_ATTR 501 502 503 504 //! Initialize client side 505 void CContext::initClient(MPI_Comm intraComm, int serviceType) 506 TRY 507 { 508 intraComm_=intraComm ; 509 MPI_Comm_rank(intraComm_, &intraCommRank_) ; 510 MPI_Comm_size(intraComm_, &intraCommSize_) ; 511 512 serviceType_ = CServicesManager::CLIENT ; 513 if (serviceType_==CServicesManager::CLIENT) 514 { 515 hasClient=true ; 516 hasServer=false ; 517 } 518 contextId_ = getId() ; 519 520 attached_mode=true ; 521 if (!CXios::isUsingServer()) attached_mode=false ; 522 523 524 string contextRegistryId=getId() ; 525 registryIn=new CRegistry(intraComm); 526 registryIn->setPath(contextRegistryId) ; 527 528 int commRank ; 529 MPI_Comm_rank(intraComm_,&commRank) ; 530 if (commRank==0) registryIn->fromFile("xios_registry.bin") ; 531 registryIn->bcastRegistry() ; 532 registryOut=new CRegistry(intraComm_) ; 533 registryOut->setPath(contextRegistryId) ; 534 535 } 536 CATCH_DUMP_ATTR 537 538 539 void CContext::initServer(MPI_Comm intraComm, int serviceType) 386 540 TRY 387 541 { 388 542 hasServer=true; 389 server = new CContextServer(this,intraComm,interComm); 390 391 /* for registry take the id of client context */ 392 /* for servers, supress the _server_ from id */ 393 string contextRegistryId=getId() ; 394 size_t pos=contextRegistryId.find("_server_") ; 395 if (pos!=std::string::npos) contextRegistryId=contextRegistryId.substr(0,pos) ; 396 543 intraComm_=intraComm ; 544 MPI_Comm_rank(intraComm_, &intraCommRank_) ; 545 MPI_Comm_size(intraComm_, &intraCommSize_) ; 546 547 serviceType_=serviceType ; 548 549 if (serviceType_==CServicesManager::GATHERER) 550 { 551 hasClient=true ; 552 hasServer=true ; 553 } 554 else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 555 { 556 hasClient=false ; 557 hasServer=true ; 558 } 559 560 CXios::getContextsManager()->getContextId(getId(), contextId_, intraComm) ; 561 397 562 registryIn=new CRegistry(intraComm); 398 registryIn->setPath(contextRegistryId) ; 399 if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ; 563 registryIn->setPath(contextId_) ; 564 565 int commRank ; 566 MPI_Comm_rank(intraComm_,&commRank) ; 567 if (commRank==0) registryIn->fromFile("xios_registry.bin") ; 568 400 569 registryIn->bcastRegistry() ; 401 570 registryOut=new CRegistry(intraComm) ; 402 registryOut->setPath(contextRegistryId) ; 403 404 MPI_Comm intraCommClient, interCommClient; 405 if (cxtClient) // Attached mode 406 { 407 intraCommClient = intraComm; 408 interCommClient = interComm; 409 } 410 else 411 { 412 MPI_Comm_dup(intraComm, &intraCommClient); 413 comms.push_back(intraCommClient); 414 MPI_Comm_dup(interComm, &interCommClient); 415 comms.push_back(interCommClient); 416 } 417 client = new CContextClient(this,intraCommClient,interCommClient, cxtClient); 418 } 419 CATCH_DUMP_ATTR 420 421 //! Try to send the buffers and receive possible answers 422 bool CContext::checkBuffersAndListen(bool enableEventsProcessing /*= true*/) 571 registryOut->setPath(contextId_) ; 572 573 } 574 CATCH_DUMP_ATTR 575 576 577 void CContext::createClientInterComm(MPI_Comm interCommClient, MPI_Comm interCommServer) // for servers 423 578 TRY 424 579 { 425 bool clientReady, serverFinished; 426 427 // Only classical servers are non-blocking 428 if (CServer::serverLevel == 0) 429 { 430 client->checkBuffers(); 431 bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent(); 432 if (hasTmpBufferedEvent) 433 hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent(); 434 // Don't process events if there is a temporarily buffered event 435 return server->eventLoop(!hasTmpBufferedEvent || !enableEventsProcessing); 436 } 437 else if (CServer::serverLevel == 1) 438 { 439 if (!finalized) 440 client->checkBuffers(); 441 bool serverFinished = true; 442 if (!finalized) 443 serverFinished = server->eventLoop(enableEventsProcessing); 444 bool serverPrimFinished = true; 445 for (int i = 0; i < clientPrimServer.size(); ++i) 446 { 447 if (!finalized) 448 clientPrimServer[i]->checkBuffers(); 449 if (!finalized) 450 serverPrimFinished *= serverPrimServer[i]->eventLoop(enableEventsProcessing); 451 } 452 return ( serverFinished && serverPrimFinished); 453 } 454 455 else if (CServer::serverLevel == 2) 456 { 457 client->checkBuffers(); 458 return server->eventLoop(enableEventsProcessing); 459 } 580 MPI_Comm intraCommClient ; 581 MPI_Comm_dup(intraComm_, &intraCommClient); 582 comms.push_back(intraCommClient); 583 // attached_mode=parentServerContext_->isAttachedMode() ; //ym probably inherited from source context 584 server = new CContextServer(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ? 585 client = new CContextClient(this,intraCommClient,interCommClient); 586 client->setAssociatedServer(server) ; 587 server->setAssociatedClient(client) ; 588 460 589 } 461 CATCH_DUMP_ATTR 462 463 //! Terminate a context 590 CATCH_DUMP_ATTR 591 592 void CContext::createServerInterComm(void) 593 TRY 594 { 595 596 MPI_Comm interCommClient, interCommServer ; 597 598 if (serviceType_ == CServicesManager::CLIENT) 599 { 600 601 int commRank ; 602 MPI_Comm_rank(intraComm_,&commRank) ; 603 if (commRank==0) 604 { 605 if (attached_mode) CXios::getContextsManager()->createServerContext(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId()) ; 606 else if (CXios::usingServer2) CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId()) ; 607 else CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId()) ; 608 } 609 610 MPI_Comm interComm ; 611 612 if (attached_mode) 613 { 614 parentServerContext_->createIntercomm(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId(), intraComm_, 615 interCommClient, interCommServer) ; 616 int type ; 617 if (commRank==0) CXios::getServicesManager()->getServiceType(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, type) ; 618 MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ; 619 setCurrent(getId()) ; // getCurrent/setCurrent may be supress, it can cause a lot of trouble 620 } 621 else if (CXios::usingServer2) 622 { 623 // CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_, interComm) ; 624 parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_, 625 interCommClient, interCommServer) ; 626 int type ; 627 if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultGathererId, 0, type) ; 628 MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ; 629 } 630 else 631 { 632 //CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_, interComm) ; 633 parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_, 634 interCommClient, interCommServer) ; 635 int type ; 636 if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ; 637 MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ; 638 } 639 640 // intraComm client is not duplicated. In all the code we use client->intraComm for MPI 641 // in future better to replace it by intracommuncator associated to the context 642 643 MPI_Comm intraCommClient, intraCommServer ; 644 intraCommClient=intraComm_ ; 645 MPI_Comm_dup(intraComm_, &intraCommServer) ; 646 client = new CContextClient(this, intraCommClient, interCommClient); 647 server = new CContextServer(this, intraCommServer, interCommServer); 648 client->setAssociatedServer(server) ; 649 server->setAssociatedClient(client) ; 650 } 651 652 if (serviceType_ == CServicesManager::GATHERER) 653 { 654 int commRank ; 655 MPI_Comm_rank(intraComm_,&commRank) ; 656 657 int nbPartitions ; 658 if (commRank==0) 659 { 660 CXios::getServicesManager()->getServiceNbPartitions(CXios::defaultPoolId, CXios::defaultServerId, 0, nbPartitions) ; 661 for(int i=0 ; i<nbPartitions; i++) 662 CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId()) ; 663 } 664 MPI_Bcast(&nbPartitions, 1, MPI_INT, 0, intraComm_) ; 665 666 MPI_Comm interComm ; 667 for(int i=0 ; i<nbPartitions; i++) 668 { 669 parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId(), intraComm_, interCommClient, interCommServer) ; 670 int type ; 671 if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ; 672 MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ; 673 primServerId_.push_back(CXios::getContextsManager()->getServerContextName(CXios::defaultPoolId, CXios::defaultServerId, i, type, getContextId())) ; 674 675 // intraComm client is not duplicated. In all the code we use client->intraComm for MPI 676 // in future better to replace it by intracommuncator associated to the context 677 678 MPI_Comm intraCommClient, intraCommServer ; 679 680 intraCommClient=intraComm_ ; 681 MPI_Comm_dup(intraComm_, &intraCommServer) ; 682 683 CContextClient* client = new CContextClient(this, intraCommClient, interCommClient) ; 684 CContextServer* server = new CContextServer(this, intraCommServer, interCommServer) ; 685 client->setAssociatedServer(server) ; 686 server->setAssociatedClient(client) ; 687 clientPrimServer.push_back(client); 688 serverPrimServer.push_back(server); 689 690 691 } 692 } 693 } 694 CATCH_DUMP_ATTR 695 696 697 698 bool CContext::eventLoop(bool enableEventsProcessing) 699 { 700 bool finished=true; 701 702 if (client!=nullptr && !finalized) client->checkBuffers(); 703 704 for (int i = 0; i < clientPrimServer.size(); ++i) 705 { 706 if (!finalized) clientPrimServer[i]->checkBuffers(); 707 if (!finalized) finished &= serverPrimServer[i]->eventLoop(enableEventsProcessing); 708 } 709 710 for (auto couplerOut : couplerOutClient_) 711 if (!finalized) couplerOut.second->checkBuffers(); 712 713 for (auto couplerIn : couplerInClient_) 714 if (!finalized) couplerIn.second->checkBuffers(); 715 716 for (auto couplerOut : couplerOutServer_) 717 if (!finalized) couplerOut.second->eventLoop(enableEventsProcessing); 718 719 for (auto couplerIn : couplerInServer_) 720 if (!finalized) couplerIn.second->eventLoop(enableEventsProcessing); 721 722 if (server!=nullptr) if (!finalized) finished &= server->eventLoop(enableEventsProcessing); 723 724 return finalized && finished ; 725 } 726 727 void CContext::addCouplingChanel(const std::string& fullContextId, bool out) 728 { 729 int contextLeader ; 730 731 if (out) 732 { 733 if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 734 { 735 bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ; 736 737 MPI_Comm interComm, interCommClient, interCommServer ; 738 MPI_Comm intraCommClient, intraCommServer ; 739 740 if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ; 741 742 MPI_Comm_dup(intraComm_, &intraCommClient) ; 743 MPI_Comm_dup(intraComm_, &intraCommServer) ; 744 MPI_Comm_dup(interComm, &interCommClient) ; 745 MPI_Comm_dup(interComm, &interCommServer) ; 746 CContextClient* client = new CContextClient(this, intraCommClient, interCommClient); 747 CContextServer* server = new CContextServer(this, intraCommServer, interCommServer); 748 client->setAssociatedServer(server) ; 749 server->setAssociatedClient(client) ; 750 MPI_Comm_free(&interComm) ; 751 couplerOutClient_[fullContextId] = client ; 752 couplerOutServer_[fullContextId] = server ; 753 754 /* 755 // for now, we don't now which beffer size must be used for client coupler 756 // It will be evaluated later. Fix a constant size for now... 757 // set to 10Mb for development 758 map<int,size_t> bufferSize, maxEventSize ; 759 for(int i=0;i<client->getRemoteSize();i++) 760 { 761 bufferSize[i]=10000000 ; 762 maxEventSize[i]=10000000 ; 763 } 764 765 client->setBufferSize(bufferSize, maxEventSize); 766 */ 767 } 768 } 769 else if (couplerInClient_.find(fullContextId)==couplerInClient_.end()) 770 { 771 bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ; 772 773 MPI_Comm interComm, interCommClient, interCommServer ; 774 MPI_Comm intraCommClient, intraCommServer ; 775 776 if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ; 777 778 MPI_Comm_dup(intraComm_, &intraCommClient) ; 779 MPI_Comm_dup(intraComm_, &intraCommServer) ; 780 MPI_Comm_dup(interComm, &interCommServer) ; 781 MPI_Comm_dup(interComm, &interCommClient) ; 782 CContextServer* server = new CContextServer(this, intraCommServer, interCommServer); 783 CContextClient* client = new CContextClient(this, intraCommClient, interCommClient); 784 client->setAssociatedServer(server) ; 785 server->setAssociatedClient(client) ; 786 MPI_Comm_free(&interComm) ; 787 788 map<int,size_t> bufferSize, maxEventSize ; 789 for(int i=0;i<client->getRemoteSize();i++) 790 { 791 bufferSize[i]=10000000 ; 792 maxEventSize[i]=10000000 ; 793 } 794 795 client->setBufferSize(bufferSize, maxEventSize); 796 couplerInClient_[fullContextId] = client ; 797 couplerInServer_[fullContextId] = server ; 798 } 799 } 800 801 void CContext::globalEventLoop(void) 802 { 803 CXios::getDaemonsManager()->eventLoop() ; 804 setCurrent(getId()) ; 805 } 806 807 464 808 void CContext::finalize(void) 465 809 TRY 466 810 { 467 if (hasClient && !hasServer) // For now we only use server level 1 to read data 468 { 469 doPreTimestepOperationsForEnabledReadModeFiles(); 470 } 471 // Send registry upon calling the function the first time 472 if (countChildCtx_ == 0) 473 if (hasClient) sendRegistry() ; 474 475 // Client: 476 // (1) blocking send context finalize to its server 477 // (2) blocking receive context finalize from its server 478 // (3) some memory deallocations 479 if (CXios::isClient) 480 { 481 // Make sure that client (model) enters the loop only once 482 if (countChildCtx_ < 1) 483 { 484 ++countChildCtx_; 485 486 client->finalize(); 487 while (client->havePendingRequests()) 488 client->checkBuffers(); 489 490 while (!server->hasFinished()) 491 server->eventLoop(); 492 493 if (hasServer) // Mode attache 811 registryOut->hierarchicalGatherRegistry() ; 812 if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ; 813 814 if (serviceType_==CServicesManager::CLIENT) 815 { 816 //ym doPreTimestepOperationsForEnabledReadModeFiles(); // For now we only use server level 1 to read data 817 818 triggerLateFields() ; 819 820 // inform couplerIn that I am finished 821 for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ; 822 823 // wait until received message from couplerOut that they have finished 824 bool couplersInFinalized ; 825 do 826 { 827 couplersInFinalized=true ; 828 for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 829 globalEventLoop() ; 830 } while (!couplersInFinalized) ; 831 832 info(100)<<"DEBUG: context "<<getId()<<" Send client finalize"<<endl ; 833 client->finalize(); 834 info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent"<<endl ; 835 while (client->havePendingRequests()) client->checkBuffers(); 836 info(100)<<"DEBUG: context "<<getId()<<" no pending request ok"<<endl ; 837 bool notifiedFinalized=false ; 838 do 839 { 840 notifiedFinalized=client->isNotifiedFinalized() ; 841 } while (!notifiedFinalized) ; 842 client->releaseBuffers(); 843 info(100)<<"DEBUG: context "<<getId()<<" release client ok"<<endl ; 844 } 845 else if (serviceType_==CServicesManager::GATHERER) 846 { 847 for (int i = 0; i < clientPrimServer.size(); ++i) 494 848 { 495 closeAllFile(); 496 registryOut->hierarchicalGatherRegistry() ; 497 if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ; 849 clientPrimServer[i]->finalize(); 850 bool bufferReleased; 851 do 852 { 853 clientPrimServer[i]->checkBuffers(); 854 bufferReleased = !clientPrimServer[i]->havePendingRequests(); 855 } while (!bufferReleased); 856 857 bool notifiedFinalized=false ; 858 do 859 { 860 notifiedFinalized=clientPrimServer[i]->isNotifiedFinalized() ; 861 } while (!notifiedFinalized) ; 862 clientPrimServer[i]->releaseBuffers(); 498 863 } 499 500 //! Deallocate client buffers 501 client->releaseBuffers(); 502 503 //! Free internally allocated communicators 504 for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it) 505 MPI_Comm_free(&(*it)); 506 comms.clear(); 507 508 info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl; 509 } 510 } 511 else if (CXios::isServer) 512 { 513 // First context finalize message received from a model 514 // Send context finalize to its child contexts (if any) 515 if (countChildCtx_ == 0) 516 for (int i = 0; i < clientPrimServer.size(); ++i) 517 clientPrimServer[i]->finalize(); 518 519 // (Last) context finalized message received 520 if (countChildCtx_ == clientPrimServer.size()) 521 { 522 // Blocking send of context finalize message to its client (e.g. primary server or model) 523 info(100)<<"DEBUG: context "<<getId()<<" Send client finalize<<"<<endl ; 524 client->finalize(); 525 bool bufferReleased; 526 do 527 { 528 client->checkBuffers(); 529 bufferReleased = !client->havePendingRequests(); 530 } while (!bufferReleased); 531 finalized = true; 532 533 closeAllFile(); // Just move to here to make sure that server-level 1 can close files 534 if (hasServer && !hasClient) 535 { 536 registryOut->hierarchicalGatherRegistry() ; 537 if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ; 538 } 539 540 //! Deallocate client buffers 541 client->releaseBuffers(); 542 for (int i = 0; i < clientPrimServer.size(); ++i) 543 clientPrimServer[i]->releaseBuffers(); 544 545 //! Free internally allocated communicators 546 for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it) 547 MPI_Comm_free(&(*it)); 548 comms.clear(); 549 550 info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl; 551 } 552 553 ++countChildCtx_; 554 } 864 closeAllFile(); 865 866 } 867 else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 868 { 869 closeAllFile(); 870 } 871 872 freeComms() ; 873 874 parentServerContext_->freeComm() ; 875 finalized = true; 876 info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl; 555 877 } 556 878 CATCH_DUMP_ATTR … … 576 898 CATCH_DUMP_ATTR 577 899 578 void CContext::postProcessingGlobalAttributes() 579 TRY 580 { 581 if (allProcessed) return; 582 583 // After xml is parsed, there are some more works with post processing 584 postProcessing(); 585 586 // Check grid and calculate its distribution 587 checkGridEnabledFields(); 588 589 // Distribute files between secondary servers according to the data size 590 distributeFiles(); 591 592 setClientServerBuffer(client, (hasClient && !hasServer)); 593 for (int i = 0; i < clientPrimServer.size(); ++i) 594 setClientServerBuffer(clientPrimServer[i], true); 595 596 if (hasClient) 597 { 598 // Send all attributes of current context to server 599 this->sendAllAttributesToServer(); 600 601 // Send all attributes of current calendar 602 CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(); 603 604 // We have enough information to send to server 605 // First of all, send all enabled files 606 sendEnabledFiles(this->enabledWriteModeFiles); 607 // We only use server-level 1 (for now) to read data 608 if (!hasServer) 609 sendEnabledFiles(this->enabledReadModeFiles); 610 611 // Then, send all enabled fields 612 sendEnabledFieldsInFiles(this->enabledWriteModeFiles); 613 if (!hasServer) 614 sendEnabledFieldsInFiles(this->enabledReadModeFiles); 615 616 // Then, check whether we have domain_ref, axis_ref or scalar_ref attached to the enabled fields 617 // If any, so send them to server 618 sendRefDomainsAxisScalars(this->enabledWriteModeFiles); 619 if (!hasServer) 620 sendRefDomainsAxisScalars(this->enabledReadModeFiles); 621 622 // Check whether enabled fields have grid_ref, if any, send this info to server 623 sendRefGrid(this->enabledFiles); 624 // This code may be useful in the future when we want to seperate completely read and write 625 // sendRefGrid(this->enabledWriteModeFiles); 626 // if (!hasServer) 627 // sendRefGrid(this->enabledReadModeFiles); 628 629 // A grid of enabled fields composed of several components which must be checked then their 630 // checked attributes should be sent to server 631 sendGridComponentEnabledFieldsInFiles(this->enabledFiles); // This code can be seperated in two (one for reading, another for writing) 632 633 // We have a xml tree on the server side and now, it should be also processed 634 sendPostProcessing(); 635 636 // Finally, we send information of grid itself to server 637 sendGridEnabledFieldsInFiles(this->enabledWriteModeFiles); 638 if (!hasServer) 639 sendGridEnabledFieldsInFiles(this->enabledReadModeFiles); 640 } 641 allProcessed = true; 642 } 643 CATCH_DUMP_ATTR 644 645 void CContext::sendPostProcessingGlobalAttributes() 646 TRY 647 { 648 // Use correct context client to send message 649 // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1; 650 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 651 for (int i = 0; i < nbSrvPools; ++i) 652 { 653 CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client; 654 CEventClient event(getType(),EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES); 655 656 if (contextClientTmp->isServerLeader()) 657 { 658 CMessage msg; 659 if (hasServer) 660 msg<<this->getIdServer(i); 661 else 662 msg<<this->getIdServer(); 663 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 664 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 665 event.push(*itRank,1,msg); 666 contextClientTmp->sendEvent(event); 667 } 668 else contextClientTmp->sendEvent(event); 669 } 670 } 671 CATCH_DUMP_ATTR 672 673 void CContext::recvPostProcessingGlobalAttributes(CEventServer& event) 674 TRY 675 { 676 CBufferIn* buffer=event.subEvents.begin()->buffer; 677 string id; 678 *buffer>>id; 679 get(id)->recvPostProcessingGlobalAttributes(*buffer); 680 } 681 CATCH 682 683 void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer) 684 TRY 685 { 686 postProcessingGlobalAttributes(); 687 } 688 CATCH_DUMP_ATTR 689 900 690 901 /*! 691 902 \brief Close all the context defintion and do processing data … … 697 908 and the active fields (fields will be written onto active files) 698 909 */ 699 700 void CContext::closeDefinition(void) 701 TRY 702 { 703 CTimer::get("Context : close definition").resume() ; 704 postProcessingGlobalAttributes(); 705 706 if (hasClient) sendPostProcessingGlobalAttributes(); 707 708 // There are some processings that should be done after all of above. For example: check mask or index 709 this->buildFilterGraphOfEnabledFields(); 910 void CContext::closeDefinition(void) 911 TRY 912 { 913 CTimer::get("Context : close definition").resume() ; 914 915 // create intercommunicator with servers. 916 // not sure it is the good place to be called here 917 createServerInterComm() ; 918 919 920 // After xml is parsed, there are some more works with post processing 921 // postProcessing(); 922 710 923 711 if (hasClient && !hasServer) 712 { 713 buildFilterGraphOfFieldsWithReadAccess(); 714 postProcessFilterGraph(); 715 } 924 // Make sure the calendar was correctly created 925 if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar(); 926 if (!calendar) 927 ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"") 928 else if (calendar->getTimeStep() == NoneDu) 929 ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"") 930 // Calendar first update to set the current date equals to the start date 931 calendar->update(0); 932 933 // Résolution des héritages descendants (cà d des héritages de groupes) 934 // pour chacun des contextes. 935 solveDescInheritance(true); 936 937 // Solve inheritance for field to know if enabled or not. 938 for (auto field : CField::getAll()) field->solveRefInheritance(); 939 940 // Check if some axis, domains or grids are eligible to for compressed indexed output. 941 // Warning: This must be done after solving the inheritance and before the rest of post-processing 942 // --> later ???? checkAxisDomainsGridsEligibilityForCompressedOutput(); 943 944 // Check if some automatic time series should be generated 945 // Warning: This must be done after solving the inheritance and before the rest of post-processing 946 947 // The timeseries should only be prepared in client 948 prepareTimeseries(); 949 950 //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. 951 findEnabledFiles(); 952 findEnabledWriteModeFiles(); 953 findEnabledReadModeFiles(); 954 findEnabledCouplerIn(); 955 findEnabledCouplerOut(); 956 createCouplerInterCommunicator() ; 957 958 // Find all enabled fields of each file 959 vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles); 960 vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles); 961 vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut); 962 vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn); 963 findFieldsWithReadAccess(); 964 vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ; 965 vector<CField*> fieldModelIn ; // fields potentially from model 966 967 // define if files are on clientSied or serverSide 968 if (serviceType_==CServicesManager::CLIENT) 969 { 970 for (auto& file : enabledWriteModeFiles) file->setClientSide() ; 971 for (auto& file : enabledReadModeFiles) file->setClientSide() ; 972 } 973 else 974 { 975 for (auto& file : enabledWriteModeFiles) file->setServerSide() ; 976 for (auto& file : enabledReadModeFiles) file->setServerSide() ; 977 } 978 716 979 717 checkGridEnabledFields(); 718 719 if (hasClient) this->sendProcessingGridOfEnabledFields(); 720 if (hasClient) this->sendCloseDefinition(); 721 722 // Nettoyage de l'arborescence 723 if (hasClient) CleanTree(); // Only on client side?? 724 725 if (hasClient) 726 { 727 sendCreateFileHeader(); 728 if (!hasServer) startPrefetchingOfEnabledReadModeFiles(); 729 } 730 CTimer::get("Context : close definition").suspend() ; 731 } 732 CATCH_DUMP_ATTR 733 734 void CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) 735 TRY 736 { 737 for (unsigned int i = 0; i < activeFiles.size(); i++) 738 (void)activeFiles[i]->getEnabledFields(); 739 } 740 CATCH_DUMP_ATTR 741 980 for (auto& field : couplerInField) 981 { 982 field->unsetGridCompleted() ; 983 } 984 // find all field potentially at workflow end 985 vector<CField*> endWorkflowFields ; 986 endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ; 987 endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ; 988 endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ; 989 endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ; 990 991 bool workflowGraphIsCompleted ; 992 993 bool first=true ; 994 do 995 { 996 workflowGraphIsCompleted=true; 997 for(auto endWorkflowField : endWorkflowFields) 998 { 999 workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ; 1000 } 1001 1002 for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ; 1003 for(auto field : couplerInField) field->makeGridAliasForCoupling(); 1004 for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ; 1005 1006 1007 // assign context to coupler out and related fields 1008 for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ; 1009 // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation 1010 for(auto field : couplerOutField) 1011 { 1012 // connect to couplerOut -> to do 1013 } 1014 if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check 1015 1016 bool couplersReady ; 1017 do 1018 { 1019 couplersReady=true ; 1020 for(auto field : couplerOutField) 1021 { 1022 bool ready = isCouplerInReady(field->getContextClient()) ; 1023 if (ready) field->sendFieldToCouplerOut() ; 1024 couplersReady &= ready ; 1025 } 1026 if (!couplersReady) this->eventLoop() ; 1027 } while (!couplersReady) ; 1028 1029 first=false ; 1030 this->eventLoop() ; 1031 } while (!workflowGraphIsCompleted) ; 1032 1033 for( auto field : couplerInField) couplerInFields_.push_back(field) ; 1034 1035 // get all field coming potentially from model 1036 for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ; 1037 1038 // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields 1039 if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles); 1040 else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ; 1041 1042 // client side, assign context for file reading 1043 if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ; 1044 1045 // server side, assign context where to send file data read 1046 if (serviceType_==CServicesManager::CServicesManager::GATHERER || serviceType_==CServicesManager::IO_SERVER) 1047 for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ; 1048 1049 // workflow endpoint => sent to IO/SERVER 1050 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 1051 { 1052 for(auto field : fileOutField) 1053 { 1054 field->connectToFileServer(garbageCollector) ; // connect the field to server filter 1055 } 1056 setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review 1057 for(auto field : fileOutField) field->sendFieldToFileServer() ; 1058 } 1059 1060 // workflow endpoint => write to file 1061 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 1062 { 1063 for(auto field : fileOutField) 1064 { 1065 field->connectToFileWriter(garbageCollector) ; // connect the field to server filter 1066 } 1067 } 1068 1069 // workflow endpoint => Send data from server to client 1070 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER) 1071 { 1072 for(auto field : fileInField) 1073 { 1074 field->connectToServerToClient(garbageCollector) ; 1075 } 1076 } 1077 1078 // workflow endpoint => sent to model on client side 1079 if (serviceType_==CServicesManager::CLIENT) 1080 { 1081 for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ; 1082 } 1083 1084 1085 // workflow startpoint => data from model 1086 if (serviceType_==CServicesManager::CLIENT) 1087 { 1088 for(auto field : fieldModelIn) 1089 { 1090 field->connectToModelInput(garbageCollector) ; // connect the field to server filter 1091 // grid index will be computed on the fly 1092 } 1093 } 1094 1095 // workflow startpoint => data from client on server side 1096 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER || serviceType_==CServicesManager::OUT_SERVER) 1097 { 1098 for(auto field : fieldModelIn) 1099 { 1100 field->connectToClientInput(garbageCollector) ; // connect the field to server filter 1101 } 1102 } 1103 1104 1105 for(auto field : couplerInField) 1106 { 1107 field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter 1108 } 1109 1110 1111 for(auto field : couplerOutField) 1112 { 1113 field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server 1114 } 1115 1116 // workflow startpoint => data from server on client side 1117 if (serviceType_==CServicesManager::CLIENT) 1118 { 1119 for(auto field : fileInField) 1120 { 1121 field->sendFieldToInputFileServer() ; 1122 field->connectToServerInput(garbageCollector) ; // connect the field to server filter 1123 fileInFields_.push_back(field) ; 1124 } 1125 } 1126 1127 // workflow startpoint => data read from file on server side 1128 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER) 1129 { 1130 for(auto field : fileInField) 1131 { 1132 field->connectToFileReader(garbageCollector) ; 1133 } 1134 } 1135 1136 // construct slave server list 1137 if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 1138 { 1139 for(auto field : fileOutField) slaveServers_.insert(field->getContextClient()) ; 1140 for(auto field : fileInField) slaveServers_.insert(field->getContextClient()) ; 1141 } 1142 1143 for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ; 1144 1145 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 1146 { 1147 createFileHeader(); 1148 } 1149 1150 if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles(); 1151 1152 // send signal to couplerIn context that definition phasis is done 1153 1154 for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ; 1155 1156 // wait until all couplerIn signal that closeDefition is done. 1157 bool ok; 1158 do 1159 { 1160 ok = true ; 1161 for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ; 1162 this->eventLoop() ; 1163 } while (!ok) ; 1164 1165 CTimer::get("Context : close definition").suspend() ; 1166 } 1167 CATCH_DUMP_ATTR 1168 1169 1170 vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles) 1171 TRY 1172 { 1173 vector<CField*> fields ; 1174 for(auto file : activeFiles) 1175 { 1176 const vector<CField*>&& fieldList=file->getEnabledFields() ; 1177 for(auto field : fieldList) field->setFileOut(file) ; 1178 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1179 } 1180 return fields ; 1181 } 1182 CATCH_DUMP_ATTR 1183 1184 vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles) 1185 TRY 1186 { 1187 vector<CField*> fields ; 1188 for(auto file : activeFiles) 1189 { 1190 const vector<CField*>&& fieldList=file->getEnabledFields() ; 1191 for(auto field : fieldList) field->setFileIn(file) ; 1192 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1193 } 1194 return fields ; 1195 } 1196 CATCH_DUMP_ATTR 1197 1198 vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut) 1199 TRY 1200 { 1201 vector<CField*> fields ; 1202 for (auto couplerOut :activeCouplerOut) 1203 { 1204 const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ; 1205 for(auto field : fieldList) field->setCouplerOut(couplerOut) ; 1206 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1207 } 1208 return fields ; 1209 } 1210 CATCH_DUMP_ATTR 1211 1212 vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn) 1213 TRY 1214 { 1215 vector<CField*> fields ; 1216 for (auto couplerIn :activeCouplerIn) 1217 { 1218 const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ; 1219 for(auto field : fieldList) field->setCouplerIn(couplerIn) ; 1220 fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 1221 } 1222 return fields ; 1223 } 1224 CATCH_DUMP_ATTR 1225 1226 /*! 1227 * Send context attribute and calendar to file server, it must be done once by context file server 1228 * \param[in] client : context client to send 1229 */ 1230 void CContext::sendContextToFileServer(CContextClient* client) 1231 { 1232 if (sendToFileServer_done_.count(client)!=0) return ; 1233 else sendToFileServer_done_.insert(client) ; 1234 1235 this->sendAllAttributesToServer(client); // Send all attributes of current context to server 1236 CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale 1237 } 1238 1239 742 1240 void CContext::readAttributesOfEnabledFieldsInReadModeFiles() 743 1241 TRY … … 748 1246 CATCH_DUMP_ATTR 749 1247 750 void CContext::sendGridComponentEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)751 TRY752 {753 int size = activeFiles.size();754 for (int i = 0; i < size; ++i)755 {756 activeFiles[i]->sendGridComponentOfEnabledFields();757 }758 }759 CATCH_DUMP_ATTR760 761 /*!762 Send active (enabled) fields in file from a client to others763 \param [in] activeFiles files contains enabled fields to send764 */765 void CContext::sendGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)766 TRY767 {768 int size = activeFiles.size();769 for (int i = 0; i < size; ++i)770 {771 activeFiles[i]->sendGridOfEnabledFields();772 }773 }774 CATCH_DUMP_ATTR775 776 void CContext::checkGridEnabledFields()777 TRY778 {779 int size = enabledFiles.size();780 for (int i = 0; i < size; ++i)781 {782 enabledFiles[i]->checkGridOfEnabledFields();783 }784 }785 CATCH_DUMP_ATTR786 787 /*!788 Check grid of active (enabled) fields in file789 \param [in] activeFiles files contains enabled fields whose grid needs checking790 */791 void CContext::checkGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)792 TRY793 {794 int size = activeFiles.size();795 for (int i = 0; i < size; ++i)796 {797 activeFiles[i]->checkGridOfEnabledFields();798 }799 }800 CATCH_DUMP_ATTR801 802 /*!803 Go up the hierachical tree via field_ref and do check of attributes of fields804 This can be done in a client then all computed information will be sent from this client to others805 \param [in] sendToServer Flag to indicate whether calculated information will be sent806 */807 void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)808 TRY809 {810 int size = this->enabledFiles.size();811 for (int i = 0; i < size; ++i)812 {813 this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);814 }815 816 for (int i = 0; i < size; ++i)817 {818 this->enabledFiles[i]->generateNewTransformationGridDest();819 }820 }821 CATCH_DUMP_ATTR822 823 /*!824 Go up the hierachical tree via field_ref and do check of attributes of fields.825 The transformation can be done in this step.826 All computed information will be sent from this client to others.827 \param [in] sendToServer Flag to indicate whether calculated information will be sent828 */829 void CContext::solveAllRefOfEnabledFieldsAndTransform(bool sendToServer)830 TRY831 {832 int size = this->enabledFiles.size();833 for (int i = 0; i < size; ++i)834 {835 this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform(sendToServer);836 }837 }838 CATCH_DUMP_ATTR839 840 void CContext::buildFilterGraphOfEnabledFields()841 TRY842 {843 int size = this->enabledFiles.size();844 for (int i = 0; i < size; ++i)845 {846 this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);847 }848 }849 CATCH_DUMP_ATTR850 1248 851 1249 void CContext::postProcessFilterGraph() … … 896 1294 TRY 897 1295 { 898 fieldsWithReadAccess .clear();1296 fieldsWithReadAccess_.clear(); 899 1297 const vector<CField*> allFields = CField::getAll(); 900 1298 for (size_t i = 0; i < allFields.size(); ++i) 901 1299 { 902 1300 CField* field = allFields[i]; 903 904 if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)905 field ->read_access = true;906 else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))907 fieldsWithReadAccess.push_back(field);1301 if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled)) 1302 { 1303 fieldsWithReadAccess_.push_back(field); 1304 field->setModelOut() ; 1305 } 908 1306 } 909 1307 } 910 1308 CATCH_DUMP_ATTR 911 1309 912 void CContext::solveAllRefOfFieldsWithReadAccess() 913 TRY 914 { 915 for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i) 916 fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false); 917 } 918 CATCH_DUMP_ATTR 919 920 void CContext::buildFilterGraphOfFieldsWithReadAccess() 921 TRY 922 { 923 for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i) 924 fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true); 925 } 926 CATCH_DUMP_ATTR 927 1310 928 1311 void CContext::solveAllInheritance(bool apply) 929 1312 TRY … … 935 1318 // Résolution des héritages par référence au niveau des fichiers. 936 1319 const vector<CFile*> allFiles=CFile::getAll(); 1320 const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll(); 1321 const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll(); 937 1322 const vector<CGrid*> allGrids= CGrid::getAll(); 938 1323 939 if (hasClient && !hasServer) 940 //if (hasClient) 1324 if (serviceType_==CServicesManager::CLIENT) 941 1325 { 942 1326 for (unsigned int i = 0; i < allFiles.size(); i++) 943 1327 allFiles[i]->solveFieldRefInheritance(apply); 1328 1329 for (unsigned int i = 0; i < allCouplerIn.size(); i++) 1330 allCouplerIn[i]->solveFieldRefInheritance(apply); 1331 1332 for (unsigned int i = 0; i < allCouplerOut.size(); i++) 1333 allCouplerOut[i]->solveFieldRefInheritance(apply); 944 1334 } 945 1335 … … 947 1337 unsigned int i = 0; 948 1338 for (i = 0; i < vecSize; ++i) 949 allGrids[i]->solve DomainAxisRefInheritance(apply);1339 allGrids[i]->solveElementsRefInheritance(apply); 950 1340 951 1341 } … … 1004 1394 CATCH_DUMP_ATTR 1005 1395 1006 void CContext::distributeFiles(void) 1396 void CContext::findEnabledCouplerIn(void) 1397 TRY 1398 { 1399 const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll(); 1400 bool enabled ; 1401 for (size_t i = 0; i < allCouplerIn.size(); i++) 1402 { 1403 if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ; 1404 else enabled=allCouplerIn[i]->enabled ; 1405 if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ; 1406 } 1407 } 1408 CATCH_DUMP_ATTR 1409 1410 void CContext::findEnabledCouplerOut(void) 1411 TRY 1412 { 1413 const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll(); 1414 bool enabled ; 1415 for (size_t i = 0; i < allCouplerOut.size(); i++) 1416 { 1417 if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ; 1418 else enabled=allCouplerOut[i]->enabled ; 1419 if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ; 1420 } 1421 } 1422 CATCH_DUMP_ATTR 1423 1424 1425 1426 1427 void CContext::distributeFiles(const vector<CFile*>& files) 1007 1428 TRY 1008 1429 { … … 1010 1431 distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory); 1011 1432 1012 if (distFileMemory) distributeFileOverMemoryBandwith( ) ;1013 else distributeFileOverBandwith( ) ;1014 } 1015 CATCH_DUMP_ATTR 1016 1017 void CContext::distributeFileOverBandwith( void)1433 if (distFileMemory) distributeFileOverMemoryBandwith(files) ; 1434 else distributeFileOverBandwith(files) ; 1435 } 1436 CATCH_DUMP_ATTR 1437 1438 void CContext::distributeFileOverBandwith(const vector<CFile*>& files) 1018 1439 TRY 1019 1440 { 1020 1441 double eps=std::numeric_limits<double>::epsilon()*10 ; 1021 1442 1022 // If primary server 1023 if (hasServer && hasClient) 1024 { 1025 std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 1026 int nbPools = clientPrimServer.size(); 1027 1028 // (1) Find all enabled files in write mode 1029 // for (int i = 0; i < this->enabledFiles.size(); ++i) 1030 // { 1031 // if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 1032 // enabledWriteModeFiles.push_back(enabledFiles[i]); 1033 // } 1034 1035 // (2) Estimate the data volume for each file 1036 int size = this->enabledWriteModeFiles.size(); 1037 std::vector<std::pair<double, CFile*> > dataSizeMap; 1038 double dataPerPool = 0; 1039 int nfield=0 ; 1040 ofs<<size<<endl ; 1041 for (size_t i = 0; i < size; ++i) 1443 std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 1444 int nbPools = clientPrimServer.size(); 1445 1446 // (1) Find all enabled files in write mode 1447 // for (int i = 0; i < this->enabledFiles.size(); ++i) 1448 // { 1449 // if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 1450 // enabledWriteModeFiles.push_back(enabledFiles[i]); 1451 // } 1452 1453 // (2) Estimate the data volume for each file 1454 int size = files.size(); 1455 std::vector<std::pair<double, CFile*> > dataSizeMap; 1456 double dataPerPool = 0; 1457 int nfield=0 ; 1458 ofs<<size<<endl ; 1459 for (size_t i = 0; i < size; ++i) 1460 { 1461 CFile* file = files[i]; 1462 ofs<<file->getId()<<endl ; 1463 StdSize dataSize=0; 1464 std::vector<CField*> enabledFields = file->getEnabledFields(); 1465 size_t numEnabledFields = enabledFields.size(); 1466 ofs<<numEnabledFields<<endl ; 1467 for (size_t j = 0; j < numEnabledFields; ++j) 1042 1468 { 1043 CFile* file = this->enabledWriteModeFiles[i]; 1044 ofs<<file->getId()<<endl ; 1045 StdSize dataSize=0; 1046 std::vector<CField*> enabledFields = file->getEnabledFields(); 1047 size_t numEnabledFields = enabledFields.size(); 1048 ofs<<numEnabledFields<<endl ; 1049 for (size_t j = 0; j < numEnabledFields; ++j) 1469 dataSize += enabledFields[j]->getGlobalWrittenSize() ; 1470 ofs<<enabledFields[j]->getGrid()->getId()<<endl ; 1471 ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 1472 } 1473 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1474 double dataSizeSec= dataSize/ outFreqSec; 1475 ofs<<dataSizeSec<<endl ; 1476 nfield++ ; 1477 // add epsilon*nField to dataSizeSec in order to preserve reproductive ordering when sorting 1478 dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 1479 dataPerPool += dataSizeSec; 1480 } 1481 dataPerPool /= nbPools; 1482 std::sort(dataSizeMap.begin(), dataSizeMap.end()); 1483 1484 // (3) Assign contextClient to each enabled file 1485 1486 std::multimap<double,int> poolDataSize ; 1487 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 1488 1489 int j; 1490 double dataSize ; 1491 for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 1492 1493 for (int i = dataSizeMap.size()-1; i >= 0; --i) 1494 { 1495 dataSize=(*poolDataSize.begin()).first ; 1496 j=(*poolDataSize.begin()).second ; 1497 dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 1498 dataSize+=dataSizeMap[i].first; 1499 poolDataSize.erase(poolDataSize.begin()) ; 1500 poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 1501 } 1502 1503 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 ; 1504 } 1505 CATCH_DUMP_ATTR 1506 1507 void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList) 1508 TRY 1509 { 1510 int nbPools = clientPrimServer.size(); 1511 double ratio=0.5 ; 1512 ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 1513 1514 int nFiles = filesList.size(); 1515 vector<SDistFile> files(nFiles); 1516 vector<SDistGrid> grids; 1517 map<string,int> gridMap ; 1518 string gridId; 1519 int gridIndex=0 ; 1520 1521 for (size_t i = 0; i < nFiles; ++i) 1522 { 1523 StdSize dataSize=0; 1524 CFile* file = filesList[i]; 1525 std::vector<CField*> enabledFields = file->getEnabledFields(); 1526 size_t numEnabledFields = enabledFields.size(); 1527 1528 files[i].id_=file->getId() ; 1529 files[i].nbGrids_=numEnabledFields; 1530 files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 1531 1532 for (size_t j = 0; j < numEnabledFields; ++j) 1533 { 1534 gridId=enabledFields[j]->getGrid()->getId() ; 1535 if (gridMap.find(gridId)==gridMap.end()) 1050 1536 { 1051 dataSize += enabledFields[j]->getGlobalWrittenSize() ; 1052 ofs<<enabledFields[j]->grid->getId()<<endl ; 1053 ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 1537 gridMap[gridId]=gridIndex ; 1538 SDistGrid newGrid; 1539 grids.push_back(newGrid) ; 1540 gridIndex++ ; 1054 1541 } 1055 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1056 double dataSizeSec= dataSize/ outFreqSec; 1057 ofs<<dataSizeSec<<endl ; 1058 nfield++ ; 1059 // add epsilon*nField to dataSizeSec in order to preserve reproductive ordering when sorting 1060 dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 1061 dataPerPool += dataSizeSec; 1542 files[i].assignedGrid_[j]=gridMap[gridId] ; 1543 grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 1544 dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 1062 1545 } 1063 dataPerPool /= nbPools; 1064 std::sort(dataSizeMap.begin(), dataSizeMap.end()); 1065 1066 // (3) Assign contextClient to each enabled file 1067 1068 std::multimap<double,int> poolDataSize ; 1069 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 1070 1071 int j; 1072 double dataSize ; 1073 for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ; 1074 1075 for (int i = dataSizeMap.size()-1; i >= 0; --i) 1546 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1547 files[i].bandwith_= dataSize/ outFreqSec ; 1548 } 1549 1550 double bandwith=0 ; 1551 double memory=0 ; 1552 1553 for(int i=0; i<nFiles; i++) bandwith+=files[i].bandwith_ ; 1554 for(int i=0; i<nFiles; i++) files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 1555 1556 for(int i=0; i<grids.size(); i++) memory+=grids[i].size_ ; 1557 for(int i=0; i<grids.size(); i++) grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 1558 1559 distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 1560 1561 vector<double> memorySize(nbPools,0.) ; 1562 vector< set<int> > serverGrids(nbPools) ; 1563 vector<double> bandwithSize(nbPools,0.) ; 1564 1565 for (size_t i = 0; i < nFiles; ++i) 1566 { 1567 bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 1568 for(int j=0 ; j<files[i].nbGrids_;j++) 1076 1569 { 1077 dataSize=(*poolDataSize.begin()).first ; 1078 j=(*poolDataSize.begin()).second ; 1079 dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 1080 dataSize+=dataSizeMap[i].first; 1081 poolDataSize.erase(poolDataSize.begin()) ; 1082 poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 1570 if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 1571 { 1572 memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 1573 serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 1574 } 1083 1575 } 1084 1085 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 ; 1086 1087 for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 1088 { 1089 enabledReadModeFiles[i]->setContextClient(client); 1090 } 1091 } 1092 else 1093 { 1094 for (int i = 0; i < this->enabledFiles.size(); ++i) 1095 enabledFiles[i]->setContextClient(client); 1096 } 1097 } 1098 CATCH_DUMP_ATTR 1099 1100 void CContext::distributeFileOverMemoryBandwith(void) 1101 TRY 1102 { 1103 // If primary server 1104 if (hasServer && hasClient) 1105 { 1106 int nbPools = clientPrimServer.size(); 1107 double ratio=0.5 ; 1108 ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 1109 1110 int nFiles = this->enabledWriteModeFiles.size(); 1111 vector<SDistFile> files(nFiles); 1112 vector<SDistGrid> grids; 1113 map<string,int> gridMap ; 1114 string gridId; 1115 int gridIndex=0 ; 1116 1117 for (size_t i = 0; i < nFiles; ++i) 1118 { 1119 StdSize dataSize=0; 1120 CFile* file = this->enabledWriteModeFiles[i]; 1121 std::vector<CField*> enabledFields = file->getEnabledFields(); 1122 size_t numEnabledFields = enabledFields.size(); 1123 1124 files[i].id_=file->getId() ; 1125 files[i].nbGrids_=numEnabledFields; 1126 files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 1127 1128 for (size_t j = 0; j < numEnabledFields; ++j) 1129 { 1130 gridId=enabledFields[j]->grid->getId() ; 1131 if (gridMap.find(gridId)==gridMap.end()) 1132 { 1133 gridMap[gridId]=gridIndex ; 1134 SDistGrid newGrid; 1135 grids.push_back(newGrid) ; 1136 gridIndex++ ; 1137 } 1138 files[i].assignedGrid_[j]=gridMap[gridId] ; 1139 grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 1140 dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 1141 } 1142 double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 1143 files[i].bandwith_= dataSize/ outFreqSec ; 1144 } 1145 1146 double bandwith=0 ; 1147 double memory=0 ; 1148 1149 for(int i=0; i<nFiles; i++) bandwith+=files[i].bandwith_ ; 1150 for(int i=0; i<nFiles; i++) files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 1151 1152 for(int i=0; i<grids.size(); i++) memory+=grids[i].size_ ; 1153 for(int i=0; i<grids.size(); i++) grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 1154 1155 distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 1156 1157 vector<double> memorySize(nbPools,0.) ; 1158 vector< set<int> > serverGrids(nbPools) ; 1159 vector<double> bandwithSize(nbPools,0.) ; 1160 1161 for (size_t i = 0; i < nFiles; ++i) 1162 { 1163 bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 1164 for(int j=0 ; j<files[i].nbGrids_;j++) 1165 { 1166 if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 1167 { 1168 memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 1169 serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 1170 } 1171 } 1172 enabledWriteModeFiles[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 1173 delete [] files[i].assignedGrid_ ; 1174 } 1175 1176 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 ; 1177 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 1178 1179 1180 for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 1181 { 1182 enabledReadModeFiles[i]->setContextClient(client); 1183 } 1184 1185 } 1186 else 1187 { 1188 for (int i = 0; i < this->enabledFiles.size(); ++i) 1189 enabledFiles[i]->setContextClient(client); 1190 } 1191 } 1576 filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 1577 delete [] files[i].assignedGrid_ ; 1578 } 1579 1580 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 ; 1581 for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<" assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 1582 1583 } 1192 1584 CATCH_DUMP_ATTR 1193 1585 … … 1265 1657 return true; 1266 1658 break; 1267 case EVENT_ID_POST_PROCESS: 1268 recvPostProcessing(event); 1269 return true; 1270 case EVENT_ID_SEND_REGISTRY: 1659 case EVENT_ID_SEND_REGISTRY: 1271 1660 recvRegistry(event); 1272 1661 return true; 1273 1662 break; 1274 case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:1275 recv PostProcessingGlobalAttributes(event);1663 case EVENT_ID_COUPLER_IN_READY: 1664 recvCouplerInReady(event); 1276 1665 return true; 1277 1666 break; 1278 case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:1279 recv ProcessingGridOfEnabledFields(event);1667 case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION: 1668 recvCouplerInCloseDefinition(event); 1280 1669 return true; 1281 1670 break; 1671 case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED: 1672 recvCouplerInContextFinalized(event); 1673 return true; 1674 break; 1282 1675 default : 1283 1676 ERROR("bool CContext::dispatchEvent(CEventServer& event)", … … 1290 1683 1291 1684 //! Client side: Send a message to server to make it close 1685 // ym obsolete 1292 1686 void CContext::sendCloseDefinition(void) 1293 1687 TRY 1294 1688 { 1295 // Use correct context client to send message 1296 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 1297 for (int i = 0; i < nbSrvPools; ++i) 1298 { 1299 CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client; 1689 int nbSrvPools ; 1690 if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ; 1691 else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ; 1692 else nbSrvPools = 0 ; 1693 CContextClient* contextClientTmp ; 1694 1695 for (int i = 0; i < nbSrvPools; ++i) 1696 { 1697 if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ; 1698 else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ; 1300 1699 CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION); 1301 1700 if (contextClientTmp->isServerLeader()) 1302 1701 { 1303 1702 CMessage msg; 1304 if (hasServer)1305 msg<<this->getIdServer(i);1306 else1307 msg<<this->getIdServer();1308 1703 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 1309 1704 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) … … 1315 1710 } 1316 1711 CATCH_DUMP_ATTR 1712 1713 // ! Client side: Send a message to server to make it close 1714 void CContext::sendCloseDefinition(CContextClient* client) 1715 TRY 1716 { 1717 if (sendCloseDefinition_done_.count(client)!=0) return ; 1718 else sendCloseDefinition_done_.insert(client) ; 1719 1720 CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION); 1721 if (client->isServerLeader()) 1722 { 1723 CMessage msg; 1724 for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg); 1725 client->sendEvent(event); 1726 } 1727 else client->sendEvent(event); 1728 } 1729 CATCH_DUMP_ATTR 1317 1730 1318 1731 //! Server side: Receive a message of client announcing a context close … … 1321 1734 { 1322 1735 CBufferIn* buffer=event.subEvents.begin()->buffer; 1323 string id; 1324 *buffer>>id; 1325 get(id)->closeDefinition(); 1736 getCurrent()->closeDefinition(); 1326 1737 } 1327 1738 CATCH … … 1331 1742 TRY 1332 1743 { 1333 // Use correct context client to send message 1334 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 1335 for (int i = 0; i < nbSrvPools; ++i) 1336 { 1337 CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client; 1338 CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR); 1339 1340 if (contextClientTmp->isServerLeader()) 1341 { 1342 CMessage msg; 1343 if (hasServer) 1344 msg<<this->getIdServer(i)<<step; 1345 else 1346 msg<<this->getIdServer()<<step; 1347 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 1348 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1349 event.push(*itRank,1,msg); 1350 contextClientTmp->sendEvent(event); 1351 } 1352 else contextClientTmp->sendEvent(event); 1744 CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR); 1745 for(auto client : slaveServers_) 1746 { 1747 if (client->isServerLeader()) 1748 { 1749 CMessage msg; 1750 msg<<step; 1751 for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg); 1752 client->sendEvent(event); 1753 } 1754 else client->sendEvent(event); 1353 1755 } 1354 1756 } … … 1360 1762 { 1361 1763 CBufferIn* buffer=event.subEvents.begin()->buffer; 1362 string id; 1363 *buffer>>id; 1364 get(id)->recvUpdateCalendar(*buffer); 1764 getCurrent()->recvUpdateCalendar(*buffer); 1365 1765 } 1366 1766 CATCH … … 1373 1773 buffer>>step; 1374 1774 updateCalendar(step); 1375 if ( hasClient && hasServer)1775 if (serviceType_==CServicesManager::GATHERER) 1376 1776 { 1377 1777 sendUpdateCalendar(step); … … 1384 1784 TRY 1385 1785 { 1386 // Use correct context client to send message 1387 // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1; 1388 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 1786 int nbSrvPools ; 1787 if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ; 1788 else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ; 1789 else nbSrvPools = 0 ; 1790 CContextClient* contextClientTmp ; 1791 1389 1792 for (int i = 0; i < nbSrvPools; ++i) 1390 1793 { 1391 CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client; 1794 if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ; 1795 else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ; 1392 1796 CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER); 1393 1797 … … 1395 1799 { 1396 1800 CMessage msg; 1397 if (hasServer)1398 msg<<this->getIdServer(i);1399 else1400 msg<<this->getIdServer();1401 1801 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 1402 1802 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) … … 1414 1814 { 1415 1815 CBufferIn* buffer=event.subEvents.begin()->buffer; 1416 string id; 1417 *buffer>>id; 1418 get(id)->recvCreateFileHeader(*buffer); 1816 getCurrent()->recvCreateFileHeader(*buffer); 1419 1817 } 1420 1818 CATCH … … 1424 1822 TRY 1425 1823 { 1426 if ( !hasClient && hasServer)1824 if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 1427 1825 createFileHeader(); 1428 1826 } 1429 1827 CATCH_DUMP_ATTR 1430 1828 1431 //! Client side: Send a message to do some post processing on server 1432 void CContext::sendProcessingGridOfEnabledFields() 1433 TRY 1434 { 1435 // Use correct context client to send message 1436 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 1437 for (int i = 0; i < nbSrvPools; ++i) 1438 { 1439 CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client; 1440 CEventClient event(getType(),EVENT_ID_PROCESS_GRID_ENABLED_FIELDS); 1441 1442 if (contextClientTmp->isServerLeader()) 1443 { 1444 CMessage msg; 1445 if (hasServer) 1446 msg<<this->getIdServer(i); 1447 else 1448 msg<<this->getIdServer(); 1449 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 1450 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1451 event.push(*itRank,1,msg); 1452 contextClientTmp->sendEvent(event); 1453 } 1454 else contextClientTmp->sendEvent(event); 1455 } 1456 } 1457 CATCH_DUMP_ATTR 1458 1459 //! Server side: Receive a message to do some post processing 1460 void CContext::recvProcessingGridOfEnabledFields(CEventServer& event) 1461 TRY 1462 { 1463 CBufferIn* buffer=event.subEvents.begin()->buffer; 1464 string id; 1465 *buffer>>id; 1466 } 1467 CATCH 1468 1469 //! Client side: Send a message to do some post processing on server 1470 void CContext::sendPostProcessing() 1471 TRY 1472 { 1473 // Use correct context client to send message 1474 // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1; 1475 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 1476 for (int i = 0; i < nbSrvPools; ++i) 1477 { 1478 CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client; 1479 CEventClient event(getType(),EVENT_ID_POST_PROCESS); 1480 if (contextClientTmp->isServerLeader()) 1481 { 1482 CMessage msg; 1483 if (hasServer) 1484 msg<<this->getIdServer(i); 1485 else 1486 msg<<this->getIdServer(); 1487 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 1488 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1489 event.push(*itRank,1,msg); 1490 contextClientTmp->sendEvent(event); 1491 } 1492 else contextClientTmp->sendEvent(event); 1493 } 1494 } 1495 CATCH_DUMP_ATTR 1496 1497 //! Server side: Receive a message to do some post processing 1498 void CContext::recvPostProcessing(CEventServer& event) 1499 TRY 1500 { 1501 CBufferIn* buffer=event.subEvents.begin()->buffer; 1502 string id; 1503 *buffer>>id; 1504 get(id)->recvPostProcessing(*buffer); 1505 } 1506 CATCH 1507 1508 //! Server side: Receive a message to do some post processing 1509 void CContext::recvPostProcessing(CBufferIn& buffer) 1510 TRY 1511 { 1512 CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar(); 1513 postProcessing(); 1514 } 1515 CATCH_DUMP_ATTR 1516 1517 const StdString& CContext::getIdServer() 1518 TRY 1519 { 1520 if (hasClient) 1521 { 1522 idServer_ = this->getId(); 1523 idServer_ += "_server"; 1524 return idServer_; 1525 } 1526 if (hasServer) return (this->getId()); 1527 } 1528 CATCH_DUMP_ATTR 1529 1530 const StdString& CContext::getIdServer(const int i) 1531 TRY 1532 { 1533 idServer_ = this->getId(); 1534 idServer_ += "_server_"; 1535 idServer_ += std::to_string(static_cast<unsigned long long>(i)); 1536 return idServer_; 1537 } 1538 CATCH_DUMP_ATTR 1539 1540 /*! 1541 \brief Do some simple post processings after parsing xml file 1542 After the xml file (iodef.xml) is parsed, it is necessary to build all relations among 1543 created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields), 1544 which will be written out into netcdf files, are processed 1545 */ 1546 void CContext::postProcessing() 1547 TRY 1548 { 1549 if (isPostProcessed) return; 1550 1551 // Make sure the calendar was correctly created 1552 if (!calendar) 1553 ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"") 1554 else if (calendar->getTimeStep() == NoneDu) 1555 ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"") 1556 // Calendar first update to set the current date equals to the start date 1557 calendar->update(0); 1558 1559 // Find all inheritance in xml structure 1560 this->solveAllInheritance(); 1561 1562 // ShowTree(info(10)); 1563 1564 // Check if some axis, domains or grids are eligible to for compressed indexed output. 1565 // Warning: This must be done after solving the inheritance and before the rest of post-processing 1566 checkAxisDomainsGridsEligibilityForCompressedOutput(); 1567 1568 // Check if some automatic time series should be generated 1569 // Warning: This must be done after solving the inheritance and before the rest of post-processing 1570 1571 // The timeseries should only be prepared in client 1572 if (hasClient && !hasServer) prepareTimeseries(); 1573 1574 //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. 1575 findEnabledFiles(); 1576 findEnabledWriteModeFiles(); 1577 findEnabledReadModeFiles(); 1578 1579 // For now, only read files with client and only one level server 1580 // if (hasClient && !hasServer) findEnabledReadModeFiles(); 1581 1582 // Find all enabled fields of each file 1583 findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 1584 findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 1585 1586 // For now, only read files with client and only one level server 1587 // if (hasClient && !hasServer) 1588 // findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 1589 1590 if (hasClient && !hasServer) 1591 { 1592 initReadFiles(); 1593 // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis) 1594 this->readAttributesOfEnabledFieldsInReadModeFiles(); 1595 } 1596 1597 // Only search and rebuild all reference objects of enable fields, don't transform 1598 this->solveOnlyRefOfEnabledFields(false); 1599 1600 // Search and rebuild all reference object of enabled fields, and transform 1601 this->solveAllRefOfEnabledFieldsAndTransform(false); 1602 1603 // Find all fields with read access from the public API 1604 if (hasClient && !hasServer) findFieldsWithReadAccess(); 1605 // and solve the all reference for them 1606 if (hasClient && !hasServer) solveAllRefOfFieldsWithReadAccess(); 1607 1608 isPostProcessed = true; 1609 } 1610 CATCH_DUMP_ATTR 1611 1612 /*! 1613 * Compute the required buffer size to send the attributes (mostly those grid related). 1614 * \param maxEventSize [in/out] the size of the bigger event for each connected server 1615 * \param [in] contextClient 1616 * \param [in] bufferForWriting True if buffers are used for sending data for writing 1617 This flag is only true for client and server-1 for communication with server-2 1618 */ 1619 std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize, 1620 CContextClient* contextClient, bool bufferForWriting /*= "false"*/) 1621 TRY 1622 { 1623 // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes 1624 std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient); 1625 maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient); 1626 1627 std::vector<CFile*>& fileList = this->enabledFiles; 1628 size_t numEnabledFiles = fileList.size(); 1629 for (size_t i = 0; i < numEnabledFiles; ++i) 1630 { 1631 // CFile* file = this->enabledWriteModeFiles[i]; 1632 CFile* file = fileList[i]; 1633 std::vector<CField*> enabledFields = file->getEnabledFields(); 1634 size_t numEnabledFields = enabledFields.size(); 1635 for (size_t j = 0; j < numEnabledFields; ++j) 1829 void CContext::createCouplerInterCommunicator(void) 1830 TRY 1831 { 1832 int rank=this->getIntraCommRank() ; 1833 map<string,list<CCouplerOut*>> listCouplerOut ; 1834 map<string,list<CCouplerIn*>> listCouplerIn ; 1835 1836 for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ; 1837 for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ; 1838 1839 CCouplerManager* couplerManager = CXios::getCouplerManager() ; 1840 if (rank==0) 1841 { 1842 for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ; 1843 for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ; 1844 } 1845 1846 do 1847 { 1848 for(auto couplerOut : listCouplerOut) 1636 1849 { 1637 const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting); 1638 std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end(); 1639 for (; it != itE; ++it) 1850 bool isNextCoupling ; 1851 if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ; 1852 MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 1853 if (isNextCoupling) 1640 1854 { 1641 // If attributesSize[it->first] does not exist, it will be zero-initialized 1642 // so we can use it safely without checking for its existence 1643 if (attributesSize[it->first] < it->second) 1644 attributesSize[it->first] = it->second; 1645 1646 if (maxEventSize[it->first] < it->second) 1647 maxEventSize[it->first] = it->second; 1648 } 1855 addCouplingChanel(couplerOut.first, true) ; 1856 listCouplerOut.erase(couplerOut.first) ; 1857 break ; 1858 } 1649 1859 } 1650 } 1651 return attributesSize; 1652 } 1653 CATCH_DUMP_ATTR 1654 1655 /*! 1656 * Compute the required buffer size to send the fields data. 1657 * \param maxEventSize [in/out] the size of the bigger event for each connected server 1658 * \param [in] contextClient 1659 * \param [in] bufferForWriting True if buffers are used for sending data for writing 1660 This flag is only true for client and server-1 for communication with server-2 1661 */ 1662 std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize, 1663 CContextClient* contextClient, bool bufferForWriting /*= "false"*/) 1664 TRY 1665 { 1666 std::map<int, StdSize> dataSize; 1667 1668 // Find all reference domain and axis of all active fields 1669 std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles; 1670 size_t numEnabledFiles = fileList.size(); 1671 for (size_t i = 0; i < numEnabledFiles; ++i) 1672 { 1673 CFile* file = fileList[i]; 1674 if (file->getContextClient() == contextClient) 1675 { 1676 std::vector<CField*> enabledFields = file->getEnabledFields(); 1677 size_t numEnabledFields = enabledFields.size(); 1678 for (size_t j = 0; j < numEnabledFields; ++j) 1679 { 1680 // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient); 1681 const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting); 1682 std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end(); 1683 for (; it != itE; ++it) 1684 { 1685 // If dataSize[it->first] does not exist, it will be zero-initialized 1686 // so we can use it safely without checking for its existance 1687 if (CXios::isOptPerformance) 1688 dataSize[it->first] += it->second; 1689 else if (dataSize[it->first] < it->second) 1690 dataSize[it->first] = it->second; 1691 1692 if (maxEventSize[it->first] < it->second) 1693 maxEventSize[it->first] = it->second; 1694 } 1695 } 1696 } 1697 } 1698 return dataSize; 1699 } 1700 CATCH_DUMP_ATTR 1701 1702 //! Client side: Send infomation of active files (files are enabled to write out) 1860 for(auto couplerIn : listCouplerIn) 1861 { 1862 bool isNextCoupling ; 1863 if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId()); 1864 MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 1865 if (isNextCoupling) 1866 { 1867 addCouplingChanel(couplerIn.first, false) ; 1868 listCouplerIn.erase(couplerIn.first) ; 1869 break ; 1870 } 1871 } 1872 1873 } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ; 1874 1875 } 1876 CATCH_DUMP_ATTR 1877 1878 1879 //! Client side: Send infomation of active files (files are enabled to write out) 1703 1880 void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles) 1704 1881 TRY … … 1734 1911 CATCH_DUMP_ATTR 1735 1912 1736 //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output 1737 void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput() 1738 TRY 1739 { 1740 if (!hasClient) return; 1741 1742 const vector<CAxis*> allAxis = CAxis::getAll(); 1743 for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++) 1744 (*it)->checkEligibilityForCompressedOutput(); 1745 1746 const vector<CDomain*> allDomains = CDomain::getAll(); 1747 for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++) 1748 (*it)->checkEligibilityForCompressedOutput(); 1749 1750 const vector<CGrid*> allGrids = CGrid::getAll(); 1751 for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++) 1752 (*it)->checkEligibilityForCompressedOutput(); 1753 } 1754 CATCH_DUMP_ATTR 1755 1913 1756 1914 //! Client side: Prepare the timeseries by adding the necessary files 1757 1915 void CContext::prepareTimeseries() 1758 1916 TRY 1759 1917 { 1760 if (!hasClient) return;1761 1762 1918 const std::vector<CFile*> allFiles = CFile::getAll(); 1763 1919 for (size_t i = 0; i < allFiles.size(); i++) … … 1856 2012 CATCH_DUMP_ATTR 1857 2013 1858 //! Client side: Send information of reference grid of active fields 1859 void CContext::sendRefGrid(const std::vector<CFile*>& activeFiles) 1860 TRY 1861 { 1862 std::set<StdString> gridIds; 1863 int sizeFile = activeFiles.size(); 1864 CFile* filePtr(NULL); 1865 1866 // Firstly, find all reference grids of all active fields 1867 for (int i = 0; i < sizeFile; ++i) 1868 { 1869 filePtr = activeFiles[i]; 1870 std::vector<CField*> enabledFields = filePtr->getEnabledFields(); 1871 int sizeField = enabledFields.size(); 1872 for (int numField = 0; numField < sizeField; ++numField) 1873 { 1874 if (0 != enabledFields[numField]->getRelGrid()) 1875 gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId()); 1876 } 1877 } 1878 1879 // Create all reference grids on server side 1880 StdString gridDefRoot("grid_definition"); 1881 CGridGroup* gridPtr = CGridGroup::get(gridDefRoot); 1882 std::set<StdString>::const_iterator it, itE = gridIds.end(); 1883 for (it = gridIds.begin(); it != itE; ++it) 1884 { 1885 gridPtr->sendCreateChild(*it); 1886 CGrid::get(*it)->sendAllAttributesToServer(); 1887 CGrid::get(*it)->sendAllDomains(); 1888 CGrid::get(*it)->sendAllAxis(); 1889 CGrid::get(*it)->sendAllScalars(); 1890 } 1891 } 1892 CATCH_DUMP_ATTR 1893 2014 1894 2015 //! Client side: Send information of reference domain, axis and scalar of active fields 1895 2016 void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles) 1896 2017 TRY 1897 2018 { 1898 std::set< StdString> domainIds, axisIds, scalarIds;2019 std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds; 1899 2020 1900 2021 // Find all reference domain and axis of all active fields … … 1906 2027 for (int j = 0; j < numEnabledFields; ++j) 1907 2028 { 2029 CContextClient* contextClient=enabledFields[j]->getContextClient() ; 1908 2030 const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds(); 1909 if ("" != prDomAxisScalarId[0]) domainIds.insert( prDomAxisScalarId[0]);1910 if ("" != prDomAxisScalarId[1]) axisIds.insert( prDomAxisScalarId[1]);1911 if ("" != prDomAxisScalarId[2]) scalarIds.insert( prDomAxisScalarId[2]);2031 if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient)); 2032 if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient)); 2033 if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient)); 1912 2034 } 1913 2035 } … … 1919 2041 StdString scalarDefRoot("scalar_definition"); 1920 2042 CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot); 1921 itE = scalarIds.end();1922 for ( itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)1923 { 1924 if (!itScalar-> empty())2043 2044 for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar) 2045 { 2046 if (!itScalar->first.empty()) 1925 2047 { 1926 scalarPtr->sendCreateChild( *itScalar);1927 CScalar::get( *itScalar)->sendAllAttributesToServer();2048 scalarPtr->sendCreateChild(itScalar->first,itScalar->second); 2049 CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second); 1928 2050 } 1929 2051 } … … 1931 2053 StdString axiDefRoot("axis_definition"); 1932 2054 CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot); 1933 itE = axisIds.end();1934 for ( itAxis = axisIds.begin(); itAxis != itE; ++itAxis)1935 { 1936 if (!itAxis-> empty())2055 2056 for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis) 2057 { 2058 if (!itAxis->first.empty()) 1937 2059 { 1938 axisPtr->sendCreateChild( *itAxis);1939 CAxis::get( *itAxis)->sendAllAttributesToServer();2060 axisPtr->sendCreateChild(itAxis->first, itAxis->second); 2061 CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second); 1940 2062 } 1941 2063 } … … 1944 2066 StdString domDefRoot("domain_definition"); 1945 2067 CDomainGroup* domPtr = CDomainGroup::get(domDefRoot); 1946 itE = domainIds.end();1947 for ( itDom = domainIds.begin(); itDom != itE; ++itDom)1948 { 1949 if (!itDom-> empty()) {1950 domPtr->sendCreateChild( *itDom);1951 CDomain::get( *itDom)->sendAllAttributesToServer();2068 2069 for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom) 2070 { 2071 if (!itDom->first.empty()) { 2072 domPtr->sendCreateChild(itDom->first, itDom->second); 2073 CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second); 1952 2074 } 1953 2075 } 2076 } 2077 CATCH_DUMP_ATTR 2078 2079 void CContext::triggerLateFields(void) 2080 TRY 2081 { 2082 for(auto& field : fileInFields_) field->triggerLateField() ; 2083 for(auto& field : couplerInFields_) field->triggerLateField() ; 1954 2084 } 1955 2085 CATCH_DUMP_ATTR … … 1963 2093 if (prevStep < step) 1964 2094 { 1965 if ( hasClient && !hasServer) // For now we only use server level 1 to read data2095 if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data 1966 2096 { 1967 doPreTimestepOperationsForEnabledReadModeFiles();2097 triggerLateFields(); 1968 2098 } 1969 2099 … … 1975 2105 #endif 1976 2106 1977 if ( hasClient && !hasServer) // For now we only use server level 1 to read data2107 if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data 1978 2108 { 1979 2109 doPostTimestepOperationsForEnabledReadModeFiles(); … … 2007 2137 vector<CFile*>::const_iterator it; 2008 2138 2009 for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)2010 //for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)2139 //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++) 2140 for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++) 2011 2141 { 2012 2142 (*it)->initWrite(); … … 2064 2194 { 2065 2195 CBufferIn* buffer=event.subEvents.begin()->buffer; 2066 string id; 2067 *buffer>>id; 2068 get(id)->recvRegistry(*buffer); 2196 getCurrent()->recvRegistry(*buffer); 2069 2197 } 2070 2198 CATCH … … 2087 2215 registryOut->hierarchicalGatherRegistry() ; 2088 2216 2089 // Use correct context client to send message 2090 int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1; 2217 int nbSrvPools ; 2218 if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ; 2219 else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ; 2220 else nbSrvPools = 0 ; 2221 CContextClient* contextClientTmp ; 2222 2091 2223 for (int i = 0; i < nbSrvPools; ++i) 2092 2224 { 2093 CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client; 2225 if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ; 2226 else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ; 2227 2094 2228 CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY); 2095 if (contextClientTmp->isServerLeader()) 2096 { 2097 CMessage msg ; 2098 if (hasServer) 2099 msg<<this->getIdServer(i); 2100 else 2101 msg<<this->getIdServer(); 2102 if (contextClientTmp->clientRank==0) msg<<*registryOut ; 2103 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 2104 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 2229 if (contextClientTmp->isServerLeader()) 2230 { 2231 CMessage msg ; 2232 if (contextClientTmp->clientRank==0) msg<<*registryOut ; 2233 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 2234 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 2105 2235 event.push(*itRank,1,msg); 2106 2107 2108 2236 contextClientTmp->sendEvent(event); 2237 } 2238 else contextClientTmp->sendEvent(event); 2109 2239 } 2110 2240 } 2111 2241 CATCH_DUMP_ATTR 2242 2243 2244 void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId) 2245 TRY 2246 { 2247 CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT); 2248 if (contextClient->isServerLeader()) 2249 { 2250 CMessage msg; 2251 msg<<contextClientId ; 2252 const std::list<int>& ranks = contextClient->getRanksServerLeader(); 2253 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 2254 event.push(*itRank,1,msg); 2255 contextClient->sendEvent(event); 2256 } 2257 else contextClient->sendEvent(event); 2258 } 2259 CATCH_DUMP_ATTR 2260 2261 2262 void CContext::recvFinalizeClient(CEventServer& event) 2263 TRY 2264 { 2265 CBufferIn* buffer=event.subEvents.begin()->buffer; 2266 string id; 2267 *buffer>>id; 2268 get(id)->recvFinalizeClient(*buffer); 2269 } 2270 CATCH 2271 2272 void CContext::recvFinalizeClient(CBufferIn& buffer) 2273 TRY 2274 { 2275 countChildContextFinalized_++ ; 2276 } 2277 CATCH_DUMP_ATTR 2278 2279 2280 2281 2282 //! Client side: Send a message announcing that context can receive grid definition from coupling 2283 void CContext::sendCouplerInReady(CContextClient* client) 2284 TRY 2285 { 2286 if (sendCouplerInReady_done_.count(client)!=0) return ; 2287 else sendCouplerInReady_done_.insert(client) ; 2288 2289 CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY); 2290 2291 if (client->isServerLeader()) 2292 { 2293 CMessage msg; 2294 msg<<this->getId(); 2295 for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg); 2296 client->sendEvent(event); 2297 } 2298 else client->sendEvent(event); 2299 } 2300 CATCH_DUMP_ATTR 2301 2302 //! Server side: Receive a message announcing that context can send grid definition for context coupling 2303 void CContext::recvCouplerInReady(CEventServer& event) 2304 TRY 2305 { 2306 CBufferIn* buffer=event.subEvents.begin()->buffer; 2307 getCurrent()->recvCouplerInReady(*buffer); 2308 } 2309 CATCH 2310 2311 //! Server side: Receive a message announcing that context can send grid definition for context coupling 2312 void CContext::recvCouplerInReady(CBufferIn& buffer) 2313 TRY 2314 { 2315 string contextId ; 2316 buffer>>contextId; 2317 couplerInReady_.insert(getCouplerOutClient(contextId)) ; 2318 } 2319 CATCH_DUMP_ATTR 2320 2321 2322 2323 2324 2325 //! Client side: Send a message announcing that a coupling context have done it closeDefinition, so data can be sent now. 2326 void CContext::sendCouplerInCloseDefinition(CContextClient* client) 2327 TRY 2328 { 2329 if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ; 2330 else sendCouplerInCloseDefinition_done_.insert(client) ; 2331 2332 CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION); 2333 2334 if (client->isServerLeader()) 2335 { 2336 CMessage msg; 2337 msg<<this->getId(); 2338 for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg); 2339 client->sendEvent(event); 2340 } 2341 else client->sendEvent(event); 2342 } 2343 CATCH_DUMP_ATTR 2344 2345 //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now. 2346 void CContext::recvCouplerInCloseDefinition(CEventServer& event) 2347 TRY 2348 { 2349 CBufferIn* buffer=event.subEvents.begin()->buffer; 2350 getCurrent()->recvCouplerInCloseDefinition(*buffer); 2351 } 2352 CATCH 2353 2354 //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now. 2355 void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer) 2356 TRY 2357 { 2358 string contextId ; 2359 buffer>>contextId; 2360 couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ; 2361 } 2362 CATCH_DUMP_ATTR 2363 2364 2365 2366 2367 //! Client side: Send a message announcing that a coupling context have done it contextFinalize, so it can also close it own context. 2368 void CContext::sendCouplerInContextFinalized(CContextClient* client) 2369 TRY 2370 { 2371 if (sendCouplerInContextFinalized_done_.count(client)!=0) return ; 2372 else sendCouplerInContextFinalized_done_.insert(client) ; 2373 2374 CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED); 2375 2376 if (client->isServerLeader()) 2377 { 2378 CMessage msg; 2379 msg<<this->getId(); 2380 for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg); 2381 client->sendEvent(event); 2382 } 2383 else client->sendEvent(event); 2384 } 2385 CATCH_DUMP_ATTR 2386 2387 //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context. 2388 void CContext::recvCouplerInContextFinalized(CEventServer& event) 2389 TRY 2390 { 2391 CBufferIn* buffer=event.subEvents.begin()->buffer; 2392 getCurrent()->recvCouplerInContextFinalized(*buffer); 2393 } 2394 CATCH 2395 2396 //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context. 2397 void CContext::recvCouplerInContextFinalized(CBufferIn& buffer) 2398 TRY 2399 { 2400 string contextId ; 2401 buffer>>contextId; 2402 couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ; 2403 } 2404 CATCH_DUMP_ATTR 2405 2406 2407 2112 2408 2113 2409 /*! -
XIOS/dev/dev_trunk_graph/src/node/context.hpp
r1612 r2019 12 12 #include "registry.hpp" 13 13 #include "mpi.hpp" 14 #include "services_manager.hpp" 15 #include "server_context.hpp" 14 16 15 17 … … 24 26 class CContext; 25 27 class CFile; 28 class CCouplerIn ; 29 class CCouplerOut ; 26 30 ///-------------------------------------------------------------- 27 31 … … 49 53 EVENT_ID_CLOSE_DEFINITION,EVENT_ID_UPDATE_CALENDAR, 50 54 EVENT_ID_CREATE_FILE_HEADER,EVENT_ID_CONTEXT_FINALIZE, 51 EVENT_ID_POST_PROCESS, EVENT_ID_SEND_REGISTRY, 52 EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES, 53 EVENT_ID_PROCESS_GRID_ENABLED_FIELDS 55 EVENT_ID_SEND_REGISTRY, 56 EVENT_ID_CONTEXT_FINALIZE_CLIENT, 57 EVENT_ID_COUPLER_IN_READY, 58 EVENT_ID_COUPLER_IN_CLOSE_DEFINITION, 59 EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED, 54 60 }; 55 61 … … 88 94 public : 89 95 // Initialize server or client 90 void initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer = 0); 91 void initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient = 0); 96 void init(CServerContext* parentServerContext, MPI_Comm intraComm, int serviceType); 97 void initClient(MPI_Comm intraComm, int serviceType); 98 99 void initServer(MPI_Comm intraComm, int serviceType ); 100 void createClientInterComm(MPI_Comm interCommClient, MPI_Comm interCommServer) ; 101 void createServerInterComm(void) ; 102 92 103 bool isInitialized(void); 93 104 … … 95 106 96 107 // Put sever or client into loop state 97 bool checkBuffersAndListen(bool enableEventsProcessing=true); 108 bool eventLoop(bool enableEventsProcessing=true); 109 void globalEventLoop(void); 98 110 99 111 // Finalize a context 100 112 void finalize(void); 113 101 114 bool isFinalized(void); 102 115 103 116 void closeDefinition(void); 104 117 118 // to be removed 119 std::vector<CField*> findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 105 120 // Some functions to process context 106 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); 107 125 // void findAllEnabledFields(void); 108 126 // void findAllEnabledFieldsInReadModeFiles(void); … … 110 128 void solveAllInheritance(bool apply=true); 111 129 void findEnabledFiles(void); 130 void findEnabledCouplerIn(void); 131 void findEnabledCouplerOut(void); 132 void createCouplerInterCommunicator(void) ; 112 133 void findEnabledWriteModeFiles(void); 113 134 void findEnabledReadModeFiles(void); … … 116 137 void createFileHeader(void); 117 138 void initReadFiles(void); 118 void checkAxisDomainsGridsEligibilityForCompressedOutput();119 139 void prepareTimeseries(void); 120 void solveOnlyRefOfEnabledFields(bool sendToServer);121 void buildFilterGraphOfEnabledFields();122 140 void postProcessFilterGraph(); 123 141 void startPrefetchingOfEnabledReadModeFiles(); … … 125 143 void doPostTimestepOperationsForEnabledReadModeFiles(); 126 144 void findFieldsWithReadAccess(void); 127 void solveAllRefOfFieldsWithReadAccess(); 128 void buildFilterGraphOfFieldsWithReadAccess(); 129 void postProcessing(); 130 void postProcessingGlobalAttributes(); 131 132 void solveAllRefOfEnabledFieldsAndTransform(bool sendToServer); 133 void checkGridEnabledFields(); 134 void checkGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 135 void sendGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 136 void sendGridComponentEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) ; 137 145 void triggerLateFields(void) ; 146 138 147 std::map<int, StdSize> getAttributesBufferSize(std::map<int, StdSize>& maxEventSize, CContextClient* contextClient, bool bufferForWriting = false); 139 148 std::map<int, StdSize> getDataBufferSize(std::map<int, StdSize>& maxEventSize, CContextClient* contextClient, bool bufferForWriting = false); 140 void setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting = false); 149 void setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting = false); // old interface to be removed 150 void setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting) ; 141 151 142 152 // Distribute files (in write mode) among secondary-server pools according to the estimated data flux 143 void distributeFiles( void);144 void distributeFileOverBandwith( ) ;145 void distributeFileOverMemoryBandwith( ) ;153 void distributeFiles(const std::vector<CFile*>& files); 154 void distributeFileOverBandwith(const std::vector<CFile*>& files) ; 155 void distributeFileOverMemoryBandwith(const std::vector<CFile*>& files) ; 146 156 147 157 // Send context close definition 148 158 void sendCloseDefinition(void); 159 public: 160 void sendCloseDefinition(CContextClient* client) ; 161 private: 162 set<CContextClient*> sendCloseDefinition_done_ ; 163 public: 149 164 // There are something to send on closing context defintion 150 165 void sendUpdateCalendar(int step); … … 153 168 void sendEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 154 169 void sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles); 155 void sendRefGrid(const std::vector<CFile*>& activeFiles);156 void sendPostProcessing();157 void sendPostProcessingGlobalAttributes();158 void sendProcessingGridOfEnabledFields();159 170 //!< after be gathered to the root process of the context, merged registry is sent to the root process of the servers 160 171 void sendRegistry(void) ; 161 162 const StdString& getIdServer(); 163 const StdString& getIdServer(const int srvPoolNb); 172 void sendFinalizeClient(CContextClient* contextClient, const string& contextClientId); 173 174 public: 175 void sendContextToFileServer(CContextClient* client) ; 176 private: 177 std::set<CContextClient*> sendToFileServer_done_ ; 178 179 public: 180 std::string getContextId() {return contextId_;} 164 181 165 182 // Client side: Receive and process messages … … 171 188 static void recvSolveInheritanceContext(CEventServer& event); 172 189 void recvSolveInheritanceContext(CBufferIn& buffer); 173 static void recvPostProcessing(CEventServer& event);174 void recvPostProcessing(CBufferIn& buffer);175 static void recvProcessingGridOfEnabledFields(CEventServer& event);176 static void recvPostProcessingGlobalAttributes(CEventServer& event);177 void recvPostProcessingGlobalAttributes(CBufferIn& buffer);178 190 static void recvRegistry(CEventServer& event) ; 179 191 void recvRegistry(CBufferIn& buffer) ; //!< registry is received by the servers 180 181 void freeComms(void); //!< Free internally allcoated communicators 182 void releaseClientBuffers(void); //! Deallocate buffers allocated by clientContexts 192 static void recvFinalizeClient(CEventServer& event) ; 193 void recvFinalizeClient(CBufferIn& buffer); 194 195 public: 196 void sendCouplerInReady(CContextClient* client); 197 private: 198 set<CContextClient*> sendCouplerInReady_done_; 199 public: 200 static void recvCouplerInReady(CEventServer& event) ; 201 void recvCouplerInReady(CBufferIn& buffer) ; //!< coupler is ready to receive grid definition. 202 set<CContextClient*> couplerInReady_; 203 bool isCouplerInReady(CContextClient* client) { return couplerInReady_.count(client)!=0 ;} 204 205 public: 206 void sendCouplerInCloseDefinition(CContextClient* client) ; 207 set<CContextClient*> sendCouplerInCloseDefinition_done_; 208 static void recvCouplerInCloseDefinition(CEventServer& event) ; 209 void recvCouplerInCloseDefinition(CBufferIn& buffer) ; //!< coupler has finished it defintion, data can be sent 210 set<CContextClient*> couplerInCloseDefinition_ ; 211 bool isCouplerInCloseDefinition(CContextClient* client) { return couplerInCloseDefinition_.count(client)!=0 ;} 212 213 public: 214 void sendCouplerInContextFinalized(CContextClient* client) ; 215 set<CContextClient*> sendCouplerInContextFinalized_done_; 216 static void recvCouplerInContextFinalized(CEventServer& event) ; 217 void recvCouplerInContextFinalized(CBufferIn& buffer) ; //!< coupler has finished it defintion, data can be sent 218 set<CContextClient*> couplerInContextFinalized_ ; 219 bool isCouplerInContextFinalized(CContextClient* client) { return couplerInContextFinalized_.count(client)!=0 ;} 220 221 public: 222 void freeComms(void); //!< Free internally allcoated communicators 223 void releaseClientBuffers(void); //! Deallocate buffers allocated by clientContexts 183 224 184 225 // dispatch event … … 208 249 static void ShowTree(StdOStream & out = std::clog); 209 250 static void CleanTree(void); 251 int getServiceType(void) {return serviceType_;} 210 252 211 253 public : … … 223 265 virtual bool hasChild(void) const; 224 266 267 bool isProcessingEvent(void) {return isProcessingEvent_;} 268 bool setProcessingEvent(void) {isProcessingEvent_=true ;} 269 bool unsetProcessingEvent(void) {isProcessingEvent_=false ;} 270 MPI_Comm getIntraComm(void) {return intraComm_ ;} 271 int getIntraCommRank(void) {return intraCommRank_;} 272 int getIntraCommSize(void) {return intraCommSize_;} 273 274 void addCouplingChanel(const std::string& contextId, bool out) ; 225 275 226 276 public : … … 235 285 std::vector<CFile*> enabledWriteModeFiles; 236 286 287 std::vector<CCouplerIn*> enabledCouplerIn; 288 std::vector<CCouplerOut*> enabledCouplerOut; 289 290 237 291 // List of all enabled fields whose instant data is accessible from the public API 238 292 // but which are not part of a file 239 std::vector<CField*> fieldsWithReadAccess; 293 std::vector<CField*> fieldsWithReadAccess_; 294 std::vector<CField*> couplerInFields_; 295 std::vector<CField*> fileInFields_; 296 240 297 241 298 // Context root … … 253 310 std::vector<CContextClient*> clientPrimServer; 254 311 312 // list of slave servers (IO server or others) 313 set<CContextClient*> slaveServers_ ; 314 private: 315 // the map containing context client associated to it string id for coupling out ; 316 std::map<std::string, CContextClient*> couplerOutClient_ ; 317 // the map containing context server associated to it string id for coupling out ; 318 std::map<std::string, CContextServer*> couplerOutServer_ ; 319 // the map containing context client associated to it string id for coupling in ; 320 std::map<std::string, CContextClient*> couplerInClient_ ; 321 // the map containing context server associated to it string id for coupling in ; 322 std::map<std::string, CContextServer*> couplerInServer_ ; 323 public: 324 CContextClient* getCouplerInClient(const string& contextId) { return couplerInClient_[contextId] ;} 325 CContextServer* getCouplerInServer(const string& contextId) { return couplerInServer_[contextId] ;} 326 CContextClient* getCouplerOutClient(const string& contextId) { return couplerOutClient_[contextId] ;} 327 CContextServer* getCouplerOutServer(const string& contextId) { return couplerOutServer_[contextId] ;} 328 329 330 std::vector<std::string> primServerId_; 331 255 332 CRegistry* registryIn ; //!< input registry which is read from file 256 333 CRegistry* registryOut ; //!< output registry which will be written into file at the finalize 257 334 335 336 MPI_Comm intraComm_ ; //! context intra communicator 337 int intraCommRank_ ; //! context intra communicator rank 338 int intraCommSize_ ; //! context intra communicator size 339 258 340 private: 259 341 bool isPostProcessed; 260 342 bool allProcessed; 261 343 bool finalized; 262 int countChildCtx_; //!< Counter of child contexts (for now it is the number of secondary server pools) 263 StdString idServer_; 344 int countChildContextFinalized_; //!< Counter of child contexts (for now it is the number of secondary server pools) 264 345 CGarbageCollector garbageCollector; 265 346 std::list<MPI_Comm> comms; //!< Communicators allocated internally 347 348 int serviceType_; //!< service associated to the context 349 string contextId_ ; //!< context client id for the servers. For clients this is same as getId() 350 bool isProcessingEvent_ ; 351 CServerContext* parentServerContext_ ; 266 352 267 353 public: // Some function maybe removed in the near future -
XIOS/dev/dev_trunk_graph/src/node/domain.cpp
r1686 r2019 1 1 #include "domain.hpp" 2 3 2 #include "attribute_template.hpp" 4 3 #include "object_template.hpp" … … 18 17 #include "server_distribution_description.hpp" 19 18 #include "client_server_mapping_distributed.hpp" 19 #include "local_connector.hpp" 20 #include "grid_local_connector.hpp" 21 #include "remote_connector.hpp" 22 #include "gatherer_connector.hpp" 23 #include "scatterer_connector.hpp" 24 #include "grid_scatterer_connector.hpp" 25 #include "grid_gatherer_connector.hpp" 26 #include "transformation_path.hpp" 27 28 29 20 30 21 31 #include <algorithm> … … 27 37 CDomain::CDomain(void) 28 38 : CObjectTemplate<CDomain>(), CDomainAttributes() 29 , isChecked(false), relFiles(), isClientChecked(false), nbSenders(),indSrv_(), connectedServerRank_()39 , isChecked(false), relFiles(), indSrv_(), connectedServerRank_() 30 40 , hasBounds(false), hasArea(false), isCompressible_(false), isUnstructed_(false) 31 , isClientAfterTransformationChecked(false),hasLonLat(false)41 , hasLonLat(false) 32 42 , isRedistributed_(false), hasPole(false) 33 43 , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue() 34 , globalLocalIndexMap_(), computedWrittenIndex_(false)35 44 , clients(), hasLatInReadFile_(false), hasBoundsLatInReadFile_(false) 36 45 , hasLonInReadFile_(false), hasBoundsLonInReadFile_(false) … … 40 49 CDomain::CDomain(const StdString & id) 41 50 : CObjectTemplate<CDomain>(id), CDomainAttributes() 42 , isChecked(false), relFiles(), i sClientChecked(false), nbSenders(), indSrv_(), connectedServerRank_()51 , isChecked(false), relFiles(), indSrv_(), connectedServerRank_() 43 52 , hasBounds(false), hasArea(false), isCompressible_(false), isUnstructed_(false) 44 , isClientAfterTransformationChecked(false),hasLonLat(false)53 , hasLonLat(false) 45 54 , isRedistributed_(false), hasPole(false) 46 55 , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue() 47 , globalLocalIndexMap_(), computedWrittenIndex_(false)48 56 , clients(), hasLatInReadFile_(false), hasBoundsLatInReadFile_(false) 49 57 , hasLonInReadFile_(false), hasBoundsLonInReadFile_(false) … … 72 80 CATCH 73 81 74 std::map<StdString, ETranformationType> CDomain::transformationMapList_ = std::map<StdString, ETranformationType>(); 75 bool CDomain::_dummyTransformationMapList = CDomain::initializeTransformationMap(CDomain::transformationMapList_); 76 77 bool CDomain::initializeTransformationMap(std::map<StdString, ETranformationType>& m) 78 TRY 79 { 80 m["zoom_domain"] = TRANS_ZOOM_DOMAIN; 81 m["interpolate_domain"] = TRANS_INTERPOLATE_DOMAIN; 82 m["generate_rectilinear_domain"] = TRANS_GENERATE_RECTILINEAR_DOMAIN; 83 m["compute_connectivity_domain"] = TRANS_COMPUTE_CONNECTIVITY_DOMAIN; 84 m["expand_domain"] = TRANS_EXPAND_DOMAIN; 85 m["reorder_domain"] = TRANS_REORDER_DOMAIN; 86 m["extract_domain"] = TRANS_EXTRACT_DOMAIN; 82 const std::set<StdString> & CDomain::getRelFiles(void) const 83 TRY 84 { 85 return (this->relFiles); 87 86 } 88 87 CATCH 89 88 90 const std::set<StdString> & CDomain::getRelFiles(void) const 91 TRY 92 { 93 return (this->relFiles); 94 } 95 CATCH 96 97 /*! 98 Returns the number of indexes written by each server. 99 \return the number of indexes written by each server 100 */ 101 int CDomain::getNumberWrittenIndexes(MPI_Comm writtenCom) 102 TRY 103 { 104 int writtenSize; 105 MPI_Comm_size(writtenCom, &writtenSize); 106 return numberWrittenIndexes_[writtenSize]; 107 } 108 CATCH_DUMP_ATTR 109 110 /*! 111 Returns the total number of indexes written by the servers. 112 \return the total number of indexes written by the servers 113 */ 114 int CDomain::getTotalNumberWrittenIndexes(MPI_Comm writtenCom) 115 TRY 116 { 117 int writtenSize; 118 MPI_Comm_size(writtenCom, &writtenSize); 119 return totalNumberWrittenIndexes_[writtenSize]; 120 } 121 CATCH_DUMP_ATTR 122 123 /*! 124 Returns the offset of indexes written by each server. 125 \return the offset of indexes written by each server 126 */ 127 int CDomain::getOffsetWrittenIndexes(MPI_Comm writtenCom) 128 TRY 129 { 130 int writtenSize; 131 MPI_Comm_size(writtenCom, &writtenSize); 132 return offsetWrittenIndexes_[writtenSize]; 133 } 134 CATCH_DUMP_ATTR 135 136 CArray<int, 1>& CDomain::getCompressedIndexToWriteOnServer(MPI_Comm writtenCom) 137 TRY 138 { 139 int writtenSize; 140 MPI_Comm_size(writtenCom, &writtenSize); 141 return compressedIndexToWriteOnServer[writtenSize]; 142 } 143 CATCH_DUMP_ATTR 144 145 //---------------------------------------------------------------- 89 //---------------------------------------------------------------- 146 90 147 91 /*! … … 227 171 (!i_index.isEmpty() && i_index.numElements() == ni_glo*nj_glo)); 228 172 bool distributed_glo ; 229 distributed |= (1 == CContext::getCurrent()-> client->clientSize);173 distributed |= (1 == CContext::getCurrent()->intraCommSize_); 230 174 231 175 return distributed; … … 236 180 237 181 /*! 238 * Test whether the data defined on the domain can be outputted in a compressed way. 239 * 240 * \return true if and only if a mask was defined for this domain 182 * Compute if the domain can be ouput in a compressed way. 183 * In this case the workflow view on server side must be the same 184 * than the full view for all context rank. The result is stored on 185 * internal isCompressible_ attribute. 241 186 */ 242 bool CDomain::isCompressible(void) const 243 TRY 244 { 245 return isCompressible_; 187 void CDomain::computeIsCompressible(void) 188 TRY 189 { 190 // mesh is compressible contains some masked or indexed value, ie if full view is different of workflow view. 191 // But now assume that the size of the 2 view must be equal for everybody. True on server side 192 int isSameView = getLocalView(CElementView::FULL)->getSize() == getLocalView(CElementView::WORKFLOW)->getSize(); 193 MPI_Allreduce(MPI_IN_PLACE, &isSameView, 1, MPI_INT, MPI_LAND, CContext::getCurrent()->getIntraComm()) ; 194 if (isSameView) isCompressible_ = false ; 195 else isCompressible_ = true ; 196 isCompressibleComputed_=true ; 246 197 } 247 198 CATCH … … 302 253 // For now the assumption is that secondary server pools consist of the same number of procs. 303 254 // CHANGE the line below if the assumption changes. 304 CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[0] : context->client; 305 int rankClient = c lient->clientRank;255 256 int rankClient = context->intraCommRank_; 306 257 int rankOnDomain = rankClient%nbLocalDomain; 307 258 … … 680 631 // For now the assumption is that secondary server pools consist of the same number of procs. 681 632 // CHANGE the line below if the assumption changes. 682 CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[0] : context->client;633 int clientSize = context->intraCommSize_ ; 683 634 lon_g.resize(ni_glo) ; 684 635 lat_g.resize(nj_glo) ; 685 636 686 637 687 int* ibegin_g = new int[client ->clientSize] ;688 int* jbegin_g = new int[client ->clientSize] ;689 int* ni_g = new int[client ->clientSize] ;690 int* nj_g = new int[client ->clientSize] ;638 int* ibegin_g = new int[clientSize] ; 639 int* jbegin_g = new int[clientSize] ; 640 int* ni_g = new int[clientSize] ; 641 int* nj_g = new int[clientSize] ; 691 642 int v ; 692 643 v=ibegin ; 693 MPI_Allgather(&v,1,MPI_INT,ibegin_g,1,MPI_INT,c lient->intraComm) ;644 MPI_Allgather(&v,1,MPI_INT,ibegin_g,1,MPI_INT,context->intraComm_) ; 694 645 v=jbegin ; 695 MPI_Allgather(&v,1,MPI_INT,jbegin_g,1,MPI_INT,c lient->intraComm) ;646 MPI_Allgather(&v,1,MPI_INT,jbegin_g,1,MPI_INT,context->intraComm_) ; 696 647 v=ni ; 697 MPI_Allgather(&v,1,MPI_INT,ni_g,1,MPI_INT,c lient->intraComm) ;648 MPI_Allgather(&v,1,MPI_INT,ni_g,1,MPI_INT,context->intraComm_) ; 698 649 v=nj ; 699 MPI_Allgather(&v,1,MPI_INT,nj_g,1,MPI_INT,c lient->intraComm) ;700 701 MPI_Allgatherv(lon.dataFirst(),ni,MPI_DOUBLE,lon_g.dataFirst(),ni_g, ibegin_g,MPI_DOUBLE,c lient->intraComm) ;702 MPI_Allgatherv(lat.dataFirst(),nj,MPI_DOUBLE,lat_g.dataFirst(),nj_g, jbegin_g,MPI_DOUBLE,c lient->intraComm) ;650 MPI_Allgather(&v,1,MPI_INT,nj_g,1,MPI_INT,context->intraComm_) ; 651 652 MPI_Allgatherv(lon.dataFirst(),ni,MPI_DOUBLE,lon_g.dataFirst(),ni_g, ibegin_g,MPI_DOUBLE,context->intraComm_) ; 653 MPI_Allgatherv(lat.dataFirst(),nj,MPI_DOUBLE,lat_g.dataFirst(),nj_g, jbegin_g,MPI_DOUBLE,context->intraComm_) ; 703 654 704 655 delete[] ibegin_g ; … … 1297 1248 CATCH_DUMP_ATTR 1298 1249 1299 void CDomain::checkEligibilityForCompressedOutput(void)1300 TRY1301 {1302 // We don't check if the mask or the indexes are valid here, just if they have been defined at this point.1303 isCompressible_ = !mask_1d.isEmpty() || !mask_2d.isEmpty() || !data_i_index.isEmpty();1304 }1305 CATCH_DUMP_ATTR1306 1250 1307 1251 //---------------------------------------------------------------- … … 1721 1665 CATCH_DUMP_ATTR 1722 1666 1723 void CDomain::checkAttributesOnClientAfterTransformation()1724 TRY1725 {1726 CContext* context=CContext::getCurrent() ;1727 1728 if (this->isClientAfterTransformationChecked) return;1729 if (context->hasClient)1730 {1731 this->computeConnectedClients();1732 if (hasLonLat)1733 if (!context->hasServer)1734 this->completeLonLatClient();1735 }1736 1737 this->isClientAfterTransformationChecked = true;1738 }1739 CATCH_DUMP_ATTR1740 1741 //----------------------------------------------------------------1742 // Divide function checkAttributes into 2 seperate ones1743 // This function only checks all attributes of current domain1744 void CDomain::checkAttributesOnClient()1745 TRY1746 {1747 if (this->isClientChecked) return;1748 CContext* context=CContext::getCurrent();1749 1750 if (context->hasClient && !context->hasServer)1751 {1752 this->checkDomain();1753 this->checkBounds();1754 this->checkArea();1755 this->checkLonLat();1756 }1757 1758 if (context->hasClient && !context->hasServer)1759 { // Ct client uniquement1760 this->checkMask();1761 this->checkDomainData();1762 this->checkCompression();1763 this->computeLocalMask() ;1764 }1765 else1766 { // Ct serveur uniquement1767 }1768 1769 this->isClientChecked = true;1770 }1771 CATCH_DUMP_ATTR1772 1773 // Send all checked attributes to server1774 void CDomain::sendCheckedAttributes()1775 TRY1776 {1777 if (!this->isClientChecked) checkAttributesOnClient();1778 if (!this->isClientAfterTransformationChecked) checkAttributesOnClientAfterTransformation();1779 CContext* context=CContext::getCurrent() ;1780 1781 if (this->isChecked) return;1782 if (context->hasClient)1783 {1784 sendAttributes();1785 }1786 this->isChecked = true;1787 }1788 CATCH_DUMP_ATTR1789 1790 1667 void CDomain::checkAttributes(void) 1791 1668 TRY 1792 1669 { 1793 if (this->isChecked) return; 1794 CContext* context=CContext::getCurrent() ; 1795 1670 if (this->checkAttributes_done_) return; 1796 1671 this->checkDomain(); 1797 1672 this->checkLonLat(); 1798 1673 this->checkBounds(); 1799 1674 this->checkArea(); 1800 1801 if (context->hasClient) 1802 { // Ct client uniquement 1803 this->checkMask(); 1804 this->checkDomainData(); 1805 this->checkCompression(); 1806 this->computeLocalMask() ; 1807 1808 } 1809 else 1810 { // Ct serveur uniquement 1811 } 1812 1813 if (context->hasClient) 1814 { 1815 this->computeConnectedClients(); 1816 this->completeLonLatClient(); 1817 } 1818 1819 this->isChecked = true; 1675 this->checkMask(); 1676 this->checkDomainData(); 1677 this->checkCompression(); 1678 this->computeLocalMask() ; 1679 this->completeLonLatClient(); 1680 this->initializeLocalElement() ; 1681 this->addFullView() ; // probably do not automatically add View, but only if requested 1682 this->addWorkflowView() ; // probably do not automatically add View, but only if requested 1683 this->addModelView() ; // probably do not automatically add View, but only if requested 1684 // testing ? 1685 /* 1686 CLocalView* local = localElement_->getView(CElementView::WORKFLOW) ; 1687 CLocalView* model = localElement_->getView(CElementView::MODEL) ; 1688 1689 CLocalConnector test1(model, local) ; 1690 test1.computeConnector() ; 1691 CLocalConnector test2(local, model) ; 1692 test2.computeConnector() ; 1693 CGridLocalConnector gridTest1(vector<CLocalConnector*>{&test1}) ; 1694 CGridLocalConnector gridTest2(vector<CLocalConnector*>{&test2}) ; 1695 1696 1697 CArray<int,1> out1 ; 1698 CArray<int,1> out2 ; 1699 test1.transfer(data_i_index,out1,-111) ; 1700 test2.transfer(out1,out2,-111) ; 1701 1702 out1 = 0 ; 1703 out2 = 0 ; 1704 gridTest1.transfer(data_i_index,out1,-111) ; 1705 gridTest2.transfer(out1, out2,-111) ; 1706 */ 1707 this->checkAttributes_done_ = true; 1820 1708 } 1821 1709 CATCH_DUMP_ATTR 1822 1710 1823 /*! 1824 Compute the connection of a client to other clients to determine which clients to send attributes to. 1825 The sending clients are supposed to already know the distribution of receiving clients (In simple cases, it's band) 1826 The connection among clients is calculated by using global index. 1827 A client connects to other clients which holds the same global index as it. 1828 */ 1829 void CDomain::computeConnectedClients() 1711 1712 void CDomain::initializeLocalElement(void) 1713 { 1714 // after checkDomain i_index and j_index of size (ni*nj) 1715 int nij = ni*nj ; 1716 CArray<size_t, 1> ij_index(ni*nj) ; 1717 for(int ij=0; ij<nij ; ij++) ij_index(ij) = i_index(ij)+j_index(ij)*ni_glo ; 1718 int rank = CContext::getCurrent()->getIntraCommRank() ; 1719 localElement_ = new CLocalElement(rank, ni_glo*nj_glo, ij_index) ; 1720 } 1721 1722 void CDomain::addFullView(void) 1723 { 1724 CArray<int,1> index(ni*nj) ; 1725 int nij=ni*nj ; 1726 for(int ij=0; ij<nij ; ij++) index(ij)=ij ; 1727 localElement_ -> addView(CElementView::FULL, index) ; 1728 } 1729 1730 void CDomain::addWorkflowView(void) 1731 { 1732 // information for workflow view is stored in localMask 1733 int nij=ni*nj ; 1734 int nMask=0 ; 1735 for(int ij=0; ij<nij ; ij++) if (localMask(ij)) nMask++ ; 1736 CArray<int,1> index(nMask) ; 1737 1738 nMask=0 ; 1739 for(int ij=0; ij<nij ; ij++) 1740 if (localMask(ij)) 1741 { 1742 index(nMask)=ij ; 1743 nMask++ ; 1744 } 1745 localElement_ -> addView(CElementView::WORKFLOW, index) ; 1746 } 1747 1748 void CDomain::addModelView(void) 1749 { 1750 // information for model view is stored in data_i_index/data_j_index 1751 // very weird, do not mix data_i_index and data_i_begin => in future only keep data_i_index 1752 int dataSize = data_i_index.numElements() ; 1753 CArray<int,1> index(dataSize) ; 1754 int i,j ; 1755 for(int k=0;k<dataSize;k++) 1756 { 1757 if (data_dim==2) 1758 { 1759 i=data_i_index(k)+data_ibegin ; // bad 1760 j=data_j_index(k)+data_jbegin ; // bad 1761 if (i>=0 && i<ni && j>=0 && j<nj) index(k)=i+j*ni ; 1762 else index(k)=-1 ; 1763 } 1764 else if (data_dim==1) 1765 { 1766 i=data_i_index(k)+data_ibegin ; // bad 1767 if (i>=0 && i<ni*nj) index(k)=i ; 1768 else index(k)=-1 ; 1769 } 1770 } 1771 localElement_->addView(CElementView::MODEL, index) ; 1772 } 1773 1774 void CDomain::computeModelToWorkflowConnector(void) 1775 { 1776 CLocalView* srcView=getLocalView(CElementView::MODEL) ; 1777 CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ; 1778 modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 1779 modelToWorkflowConnector_->computeConnector() ; 1780 } 1781 1782 1783 1784 /* to be removed later when coupling will be reimplemented, just to not forget */ 1785 void CDomain::sendDomainToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid) 1786 { 1787 if (sendDomainToFileServer_done_.count(client)!=0) return ; 1788 else sendDomainToFileServer_done_.insert(client) ; 1789 1790 const string domainId = "_domain["+std::to_string(posInGrid)+"]_of_"+fieldId ; 1791 1792 if (!domain_ref.isEmpty()) 1793 { 1794 auto domain_ref_tmp=domain_ref.getValue() ; 1795 domain_ref.reset() ; // remove the reference, find an other way to do that more cleanly 1796 this->sendAllAttributesToServer(client, domainId) ; 1797 domain_ref = domain_ref_tmp ; 1798 } 1799 else this->sendAllAttributesToServer(client, domainId) ; 1800 } 1801 1802 1803 1804 1805 void CDomain::makeAliasForCoupling(const string& fieldId, int posInGrid) 1806 { 1807 const string domainId = "_domain["+std::to_string(posInGrid)+"]_of_"+fieldId ; 1808 this->createAlias(domainId) ; 1809 } 1810 1811 1812 void CDomain::computeRemoteElement(CContextClient* client, EDistributionType type) 1830 1813 TRY 1831 1814 { 1832 CContext* context=CContext::getCurrent() ; 1833 1834 // This line should be changed soon. 1835 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1; 1836 1837 nbSenders.clear(); 1838 connectedServerRank_.clear(); 1839 1840 for (int p = 0; p < nbSrvPools; ++p) 1815 CContext* context = CContext::getCurrent(); 1816 map<int, CArray<size_t,1>> globalIndex ; 1817 1818 if (type==EDistributionType::BANDS) // Bands distribution to send to file server 1841 1819 { 1842 CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;1843 int nbServer = client->serverSize;1844 int nbClient = client->clientSize;1845 int rank = client->clientRank;1846 bool doComputeGlobalIndexServer = true;1847 1848 if (connectedServerRank_.find(nbServer) == connectedServerRank_.end())1849 {1850 1851 if (indSrv_.find(nbServer) == indSrv_.end())1852 {1853 int i,j,i_ind,j_ind, nbIndex=i_index.numElements();1854 int globalIndexCount = i_index.numElements();1855 // Fill in index1856 CArray<size_t,1> globalIndexDomain(nbIndex);1857 size_t globalIndex;1858 1859 for (i = 0; i < nbIndex; ++i)1860 {1861 i_ind=i_index(i);1862 j_ind=j_index(i);1863 globalIndex = i_ind + j_ind * ni_glo;1864 globalIndexDomain(i) = globalIndex;1865 }1866 1867 if (globalLocalIndexMap_.empty())1868 {1869 for (i = 0; i < nbIndex; ++i)1870 globalLocalIndexMap_[globalIndexDomain(i)] = i;1871 }1872 1873 size_t globalSizeIndex = 1, indexBegin, indexEnd;1874 int range, clientSize = client->clientSize;1875 std::vector<int> nGlobDomain(2);1876 nGlobDomain[0] = this->ni_glo;1877 nGlobDomain[1] = this->nj_glo;1878 for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i];1879 indexBegin = 0;1880 if (globalSizeIndex <= clientSize)1881 {1882 indexBegin = rank%globalSizeIndex;1883 indexEnd = indexBegin;1884 }1885 else1886 {1887 for (int i = 0; i < clientSize; ++i)1888 {1889 range = globalSizeIndex / clientSize;1890 if (i < (globalSizeIndex%clientSize)) ++range;1891 if (i == client->clientRank) break;1892 indexBegin += range;1893 }1894 indexEnd = indexBegin + range - 1;1895 }1896 1897 // Even if servers have no index, they must received something from client1898 // We only use several client to send "empty" message to these servers1899 CServerDistributionDescription serverDescription(nGlobDomain, nbServer);1900 std::vector<int> serverZeroIndex;1901 if (isUnstructed_) serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0);1902 else serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 1);1903 1904 std::list<int> serverZeroIndexLeader;1905 std::list<int> serverZeroIndexNotLeader;1906 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);1907 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)1908 *it = serverZeroIndex[*it];1909 1910 CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm);1911 clientServerMap->computeServerIndexMapping(globalIndexDomain, nbServer);1912 CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer();1913 1914 CClientServerMapping::GlobalIndexMap::const_iterator it = globalIndexDomainOnServer.begin(),1915 ite = globalIndexDomainOnServer.end();1916 indSrv_[nbServer].swap(globalIndexDomainOnServer);1917 connectedServerRank_[nbServer].clear();1918 for (it = indSrv_[nbServer].begin(); it != ite; ++it)1919 connectedServerRank_[nbServer].push_back(it->first);1920 1921 for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)1922 connectedServerRank_[nbServer].push_back(*it);1923 1924 // Even if a client has no index, it must connect to at least one server and1925 // send an "empty" data to this server1926 if (connectedServerRank_[nbServer].empty())1927 connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize);1928 1929 // Now check if all servers have data to receive. If not, master client will send empty data.1930 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive.1931 std::vector<int> counts (clientSize);1932 std::vector<int> displs (clientSize);1933 displs[0] = 0;1934 int localCount = connectedServerRank_[nbServer].size() ;1935 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ;1936 for (int i = 0; i < clientSize-1; ++i)1937 {1938 displs[i+1] = displs[i] + counts[i];1939 }1940 std::vector<int> allConnectedServers(displs[clientSize-1]+counts[clientSize-1]);1941 MPI_Gatherv(&(connectedServerRank_[nbServer])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm);1942 1943 if ((allConnectedServers.size() != nbServer) && (rank == 0))1944 {1945 std::vector<bool> isSrvConnected (nbServer, false);1946 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true;1947 for (int i = 0; i < nbServer; ++i)1948 {1949 if (!isSrvConnected[i]) connectedServerRank_[nbServer].push_back(i);1950 }1951 }1952 nbSenders[nbServer] = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]);1953 delete clientServerMap;1954 }1955 }1956 }1957 }1958 CATCH_DUMP_ATTR1959 1960 /*!1961 Compute index to write data. We only write data on the zoomed region, therefore, there should1962 be a map between the complete grid and the reduced grid where we write data.1963 By using global index we can easily create this kind of mapping.1964 */1965 void CDomain::computeWrittenIndex()1966 TRY1967 {1968 if (computedWrittenIndex_) return;1969 computedWrittenIndex_ = true;1970 1971 CContext* context=CContext::getCurrent();1972 CContextServer* server = context->server;1973 1974 std::vector<int> nBegin(2), nSize(2), nBeginGlobal(2), nGlob(2);1975 nBegin[0] = ibegin; nBegin[1] = jbegin;1976 nSize[0] = ni; nSize[1] = nj;1977 nBeginGlobal[0] = 0; nBeginGlobal[1] = 0;1978 nGlob[0] = ni_glo; nGlob[1] = nj_glo;1979 CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob);1980 const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex();1981 1982 size_t nbWritten = 0, indGlo;1983 std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),1984 ite = globalLocalIndexMap_.end(), it;1985 CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),1986 itSrve = writtenGlobalIndex.end(), itSrv;1987 1988 localIndexToWriteOnServer.resize(writtenGlobalIndex.numElements());1989 nbWritten = 0;1990 for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)1991 {1992 indGlo = *itSrv;1993 if (ite != globalLocalIndexMap_.find(indGlo))1994 {1995 localIndexToWriteOnServer(nbWritten) = globalLocalIndexMap_[indGlo];1996 }1997 else1998 {1999 localIndexToWriteOnServer(nbWritten) = -1;2000 }2001 ++nbWritten;2002 }2003 }2004 CATCH_DUMP_ATTR2005 2006 void CDomain::computeWrittenCompressedIndex(MPI_Comm writtenComm)2007 TRY2008 {2009 int writtenCommSize;2010 MPI_Comm_size(writtenComm, &writtenCommSize);2011 if (compressedIndexToWriteOnServer.find(writtenCommSize) != compressedIndexToWriteOnServer.end())2012 return;2013 2014 if (isCompressible())2015 {2016 size_t nbWritten = 0, indGlo;2017 CContext* context=CContext::getCurrent();2018 CContextServer* server = context->server;2019 2020 std::vector<int> nBegin(2), nSize(2), nBeginGlobal(2), nGlob(2);2021 nBegin[0] = ibegin; nBegin[1] = jbegin;2022 nSize[0] = ni; nSize[1] = nj;2023 nBeginGlobal[0] = 0; nBeginGlobal[1] = 0;2024 nGlob[0] = ni_glo; nGlob[1] = nj_glo;2025 CDistributionServer srvDist(server->intraCommSize, nBegin, nSize, nBeginGlobal, nGlob);2026 const CArray<size_t,1>& writtenGlobalIndex = srvDist.getGlobalIndex();2027 2028 std::unordered_map<size_t,size_t>::const_iterator itb = globalLocalIndexMap_.begin(),2029 ite = globalLocalIndexMap_.end(), it;2030 CArray<size_t,1>::const_iterator itSrvb = writtenGlobalIndex.begin(),2031 itSrve = writtenGlobalIndex.end(), itSrv;2032 std::unordered_map<size_t,size_t> localGlobalIndexMap;2033 for (itSrv = itSrvb; itSrv != itSrve; ++itSrv)2034 {2035 indGlo = *itSrv;2036 if (ite != globalLocalIndexMap_.find(indGlo))2037 {2038 localGlobalIndexMap[localIndexToWriteOnServer(nbWritten)] = indGlo;2039 ++nbWritten;2040 }2041 }2042 2043 nbWritten = 0;2044 for (int idx = 0; idx < data_i_index.numElements(); ++idx)2045 {2046 if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_i_index(idx)))2047 {2048 ++nbWritten;2049 }2050 }2051 2052 compressedIndexToWriteOnServer[writtenCommSize].resize(nbWritten);2053 nbWritten = 0;2054 for (int idx = 0; idx < data_i_index.numElements(); ++idx)2055 {2056 if (localGlobalIndexMap.end() != localGlobalIndexMap.find(data_i_index(idx)))2057 {2058 compressedIndexToWriteOnServer[writtenCommSize](nbWritten) = localGlobalIndexMap[data_i_index(idx)];2059 ++nbWritten;2060 }2061 }2062 2063 numberWrittenIndexes_[writtenCommSize] = nbWritten;2064 bool distributed_glo, distributed=isDistributed() ;2065 MPI_Allreduce(&distributed,&distributed_glo, 1, MPI_INT, MPI_LOR, writtenComm) ;2066 2067 if (distributed_glo)2068 {2069 2070 MPI_Allreduce(&numberWrittenIndexes_[writtenCommSize], &totalNumberWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);2071 MPI_Scan(&numberWrittenIndexes_[writtenCommSize], &offsetWrittenIndexes_[writtenCommSize], 1, MPI_INT, MPI_SUM, writtenComm);2072 offsetWrittenIndexes_[writtenCommSize] -= numberWrittenIndexes_[writtenCommSize];2073 }2074 else2075 totalNumberWrittenIndexes_[writtenCommSize] = numberWrittenIndexes_[writtenCommSize];2076 }2077 }2078 CATCH_DUMP_ATTR2079 2080 /*!2081 Send all attributes from client to connected clients2082 The attributes will be rebuilt on receiving side2083 */2084 void CDomain::sendAttributes()2085 TRY2086 {2087 sendDistributionAttributes();2088 sendIndex();2089 sendLonLat();2090 sendArea();2091 sendDataIndex();2092 }2093 CATCH2094 /*!2095 Send global index from client to connected client(s)2096 */2097 void CDomain::sendIndex()2098 TRY2099 {2100 int ns, n, i, j, ind, nv, idx;2101 std::list<CContextClient*>::iterator it;2102 for (it=clients.begin(); it!=clients.end(); ++it)2103 {2104 CContextClient* client = *it;2105 2106 int serverSize = client->serverSize;2107 CEventClient eventIndex(getType(), EVENT_ID_INDEX);2108 2109 list<CMessage> list_msgsIndex;2110 list<CArray<int,1> > list_indGlob;2111 2112 std::unordered_map<int, vector<size_t> >::const_iterator itIndex, iteIndex;2113 iteIndex = indSrv_[serverSize].end();2114 for (int k = 0; k < connectedServerRank_[serverSize].size(); ++k)2115 {2116 int nbIndGlob = 0;2117 int rank = connectedServerRank_[serverSize][k];2118 itIndex = indSrv_[serverSize].find(rank);2119 if (iteIndex != itIndex)2120 nbIndGlob = itIndex->second.size();2121 2122 list_indGlob.push_back(CArray<int,1>(nbIndGlob));2123 2124 CArray<int,1>& indGlob = list_indGlob.back();2125 for (n = 0; n < nbIndGlob; ++n)2126 {2127 indGlob(n) = static_cast<int>(itIndex->second[n]);2128 }2129 2130 list_msgsIndex.push_back(CMessage());2131 list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix2132 list_msgsIndex.back() << isCurvilinear;2133 list_msgsIndex.back() << list_indGlob.back(); //list_indi.back() << list_indj.back();2134 2135 eventIndex.push(rank, nbSenders[serverSize][rank], list_msgsIndex.back());2136 }2137 2138 client->sendEvent(eventIndex);2139 }2140 }2141 CATCH_DUMP_ATTR2142 2143 /*!2144 Send distribution from client to other clients2145 Because a client in a level knows correctly the grid distribution of client on the next level2146 it calculates this distribution then sends it to the corresponding clients on the next level2147 */2148 void CDomain::sendDistributionAttributes(void)2149 TRY2150 {2151 std::list<CContextClient*>::iterator it;2152 for (it=clients.begin(); it!=clients.end(); ++it)2153 {2154 CContextClient* client = *it;2155 1820 int nbServer = client->serverSize; 2156 1821 std::vector<int> nGlobDomain(2); … … 2158 1823 nGlobDomain[1] = this->nj_glo; 2159 1824 1825 // to be changed in future, need to rewrite more simply domain distribution 2160 1826 CServerDistributionDescription serverDescription(nGlobDomain, nbServer); 2161 if (isUnstructed_) serverDescription.computeServerDistribution(false, 0); 2162 else serverDescription.computeServerDistribution(false, 1); 2163 1827 int distributedPosition ; 1828 if (isUnstructed_) distributedPosition = 0 ; 1829 else distributedPosition = 1 ; 1830 2164 1831 std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin(); 2165 1832 std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes(); 2166 2167 CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT); 2168 if (client->isServerLeader()) 2169 { 2170 std::list<CMessage> msgs; 2171 2172 const std::list<int>& ranks = client->getRanksServerLeader(); 2173 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 2174 { 2175 // Use const int to ensure CMessage holds a copy of the value instead of just a reference 2176 const int ibegin_srv = serverIndexBegin[*itRank][0]; 2177 const int jbegin_srv = serverIndexBegin[*itRank][1]; 2178 const int ni_srv = serverDimensionSizes[*itRank][0]; 2179 const int nj_srv = serverDimensionSizes[*itRank][1]; 2180 2181 msgs.push_back(CMessage()); 2182 CMessage& msg = msgs.back(); 2183 msg << this->getId() ; 2184 msg << isUnstructed_; 2185 msg << ni_srv << ibegin_srv << nj_srv << jbegin_srv; 2186 msg << ni_glo.getValue() << nj_glo.getValue(); 2187 msg << isCompressible_; 2188 2189 event.push(*itRank,1,msg); 2190 } 2191 client->sendEvent(event); 2192 } 2193 else client->sendEvent(event); 1833 vector<unordered_map<size_t,vector<int>>> indexServerOnElement ; 1834 CArray<int,1> axisDomainOrder(1) ; axisDomainOrder(0)=2 ; 1835 auto zeroIndex=serverDescription.computeServerGlobalByElement(indexServerOnElement, context->getIntraCommRank(), context->getIntraCommSize(), 1836 axisDomainOrder,distributedPosition) ; 1837 // distribution is very bad => to redo 1838 // convert indexServerOnElement => map<int,CArray<size_t,1>> - need to be changed later 1839 map<int, vector<size_t>> vectGlobalIndex ; 1840 for(auto& indexRanks : indexServerOnElement[0]) 1841 { 1842 size_t index=indexRanks.first ; 1843 auto& ranks=indexRanks.second ; 1844 for(int rank : ranks) vectGlobalIndex[rank].push_back(index) ; 1845 } 1846 for(auto& vect : vectGlobalIndex ) globalIndex.emplace(vect.first, CArray<size_t,1>(vect.second.data(), shape(vect.second.size()),duplicateData)) ; 1847 // some servers receves no index (zeroIndex array) => root process take them into account. 1848 if (context->getIntraCommRank()==0) 1849 for(auto& rank : zeroIndex) globalIndex[rank] = CArray<size_t,1>() ; 2194 1850 } 1851 else if (type==EDistributionType::NONE) // domain is not distributed ie all servers get the same local domain 1852 { 1853 int nbServer = client->serverSize; 1854 int nglo=ni_glo*nj_glo ; 1855 CArray<size_t,1> indGlo ; 1856 for(size_t i=0;i<nglo;i++) indGlo(i) = i ; 1857 for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer] = indGlo ; 1858 } 1859 remoteElement_[client] = new CDistributedElement(ni_glo*nj_glo, globalIndex) ; 1860 remoteElement_[client]->addFullView() ; 2195 1861 } 2196 CATCH _DUMP_ATTR2197 2198 /*!2199 Send area from client to connected client(s) 2200 */2201 void CDomain::sendArea()1862 CATCH 1863 1864 1865 1866 void CDomain::distributeToServer(CContextClient* client, map<int, CArray<size_t,1>>& globalIndex, 1867 CScattererConnector* &scattererConnector, const string& domainId) 2202 1868 TRY 2203 1869 { 2204 if (!hasArea) return; 2205 2206 int ns, n, i, j, ind, nv, idx; 2207 std::list<CContextClient*>::iterator it; 2208 2209 for (it=clients.begin(); it!=clients.end(); ++it) 2210 { 2211 CContextClient* client = *it; 2212 int serverSize = client->serverSize; 2213 2214 // send area for each connected server 2215 CEventClient eventArea(getType(), EVENT_ID_AREA); 2216 2217 list<CMessage> list_msgsArea; 2218 list<CArray<double,1> > list_area; 2219 2220 std::unordered_map<int, vector<size_t> >::const_iterator it, iteMap; 2221 iteMap = indSrv_[serverSize].end(); 2222 for (int k = 0; k < connectedServerRank_[serverSize].size(); ++k) 2223 { 2224 int nbData = 0; 2225 int rank = connectedServerRank_[serverSize][k]; 2226 it = indSrv_[serverSize].find(rank); 2227 if (iteMap != it) 2228 nbData = it->second.size(); 2229 list_area.push_back(CArray<double,1>(nbData)); 2230 2231 const std::vector<size_t>& temp = it->second; 2232 for (n = 0; n < nbData; ++n) 2233 { 2234 idx = static_cast<int>(it->second[n]); 2235 list_area.back()(n) = areavalue(globalLocalIndexMap_[idx]); 2236 } 2237 2238 list_msgsArea.push_back(CMessage()); 2239 list_msgsArea.back() << this->getId() << hasArea; 2240 list_msgsArea.back() << list_area.back(); 2241 eventArea.push(rank, nbSenders[serverSize][rank], list_msgsArea.back()); 2242 } 2243 client->sendEvent(eventArea); 2244 } 1870 string serverDomainId = domainId.empty() ? this->getId() : domainId ; 1871 CContext* context = CContext::getCurrent(); 1872 1873 this->sendAllAttributesToServer(client, serverDomainId) ; 1874 1875 CDistributedElement scatteredElement(ni_glo*nj_glo, globalIndex) ; 1876 scatteredElement.addFullView() ; 1877 scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 1878 context->getIntraComm(), client->getRemoteSize()) ; 1879 scattererConnector->computeConnector() ; 1880 1881 // phase 0 1882 // send remote element to construct the full view on server, ie without hole 1883 CEventClient event0(getType(), EVENT_ID_DOMAIN_DISTRIBUTION); 1884 CMessage message0 ; 1885 message0<<serverDomainId<<0 ; 1886 remoteElement_[client]->sendToServer(client,event0,message0) ; 1887 1888 // phase 1 1889 // send the full view of element to construct the connector which connect distributed data coming from client to the full local view 1890 CEventClient event1(getType(), EVENT_ID_DOMAIN_DISTRIBUTION); 1891 CMessage message1 ; 1892 message1<<serverDomainId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 1893 scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ; 1894 1895 sendDistributedAttributes(client, *scattererConnector, domainId) ; 1896 1897 1898 // phase 2 send the mask : data index + mask2D 1899 CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize()); 1900 CArray<bool,1> maskOut ; 1901 CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ; 1902 workflowToFull.computeConnector() ; 1903 maskIn=true ; 1904 workflowToFull.transfer(maskIn,maskOut,false) ; 1905 1906 1907 // phase 3 : prepare grid scatterer connector to send data from client to server 1908 map<int,CArray<size_t,1>> workflowGlobalIndex ; 1909 map<int,CArray<bool,1>> maskOut2 ; 1910 scattererConnector->transfer(maskOut, maskOut2, false) ; 1911 scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ; 1912 scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ; 1913 // create new workflow view for scattered element 1914 CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ; 1915 clientToServerElement.addFullView() ; 1916 CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION); 1917 CMessage message2 ; 1918 message2<<serverDomainId<<2 ; 1919 clientToServerElement.sendToServer(client, event2, message2) ; 1920 clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 1921 context->getIntraComm(), client->getRemoteSize()) ; 1922 clientToServerConnector_[client]->computeConnector() ; 1923 1924 clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)); 1925 clientFromServerConnector_[client]->computeConnector() ; 1926 2245 1927 } 2246 CATCH_DUMP_ATTR 2247 2248 /*! 2249 Send longitude and latitude from client to servers 2250 Each client send long and lat information to corresponding connected clients(s). 2251 Because longitude and latitude are optional, this function only called if latitude and longitude exist 2252 */ 2253 void CDomain::sendLonLat() 1928 CATCH 1929 1930 void CDomain::recvDomainDistribution(CEventServer& event) 2254 1931 TRY 2255 1932 { 2256 if (!hasLonLat) return; 2257 2258 int ns, n, i, j, ind, nv, idx; 2259 std::list<CContextClient*>::iterator it; 2260 for (it=clients.begin(); it!=clients.end(); ++it) 2261 { 2262 CContextClient* client = *it; 2263 int serverSize = client->serverSize; 2264 2265 // send lon lat for each connected server 2266 CEventClient eventLon(getType(), EVENT_ID_LON); 2267 CEventClient eventLat(getType(), EVENT_ID_LAT); 2268 2269 list<CMessage> list_msgsLon, list_msgsLat; 2270 list<CArray<double,1> > list_lon, list_lat; 2271 list<CArray<double,2> > list_boundslon, list_boundslat; 2272 2273 std::unordered_map<int, vector<size_t> >::const_iterator it, iteMap; 2274 iteMap = indSrv_[serverSize].end(); 2275 for (int k = 0; k < connectedServerRank_[serverSize].size(); ++k) 2276 { 2277 int nbData = 0; 2278 int rank = connectedServerRank_[serverSize][k]; 2279 it = indSrv_[serverSize].find(rank); 2280 if (iteMap != it) 2281 nbData = it->second.size(); 2282 2283 list_lon.push_back(CArray<double,1>(nbData)); 2284 list_lat.push_back(CArray<double,1>(nbData)); 2285 2286 if (hasBounds) 2287 { 2288 list_boundslon.push_back(CArray<double,2>(nvertex, nbData)); 2289 list_boundslat.push_back(CArray<double,2>(nvertex, nbData)); 2290 } 2291 2292 CArray<double,1>& lon = list_lon.back(); 2293 CArray<double,1>& lat = list_lat.back(); 2294 const std::vector<size_t>& temp = it->second; 2295 for (n = 0; n < nbData; ++n) 2296 { 2297 idx = static_cast<int>(it->second[n]); 2298 int localInd = globalLocalIndexMap_[idx]; 2299 lon(n) = lonvalue(localInd); 2300 lat(n) = latvalue(localInd); 2301 2302 if (hasBounds) 2303 { 2304 CArray<double,2>& boundslon = list_boundslon.back(); 2305 CArray<double,2>& boundslat = list_boundslat.back(); 2306 2307 for (nv = 0; nv < nvertex; ++nv) 2308 { 2309 boundslon(nv, n) = bounds_lonvalue(nv, localInd); 2310 boundslat(nv, n) = bounds_latvalue(nv, localInd); 2311 } 2312 } 2313 } 2314 2315 list_msgsLon.push_back(CMessage()); 2316 list_msgsLat.push_back(CMessage()); 2317 2318 list_msgsLon.back() << this->getId() << hasLonLat; 2319 if (hasLonLat) 2320 list_msgsLon.back() << list_lon.back(); 2321 list_msgsLon.back() << hasBounds; 2322 if (hasBounds) 2323 { 2324 list_msgsLon.back() << list_boundslon.back(); 2325 } 2326 2327 list_msgsLat.back() << this->getId() << hasLonLat; 2328 if (hasLonLat) 2329 list_msgsLat.back() << list_lat.back(); 2330 list_msgsLat.back() << hasBounds; 2331 if (hasBounds) 2332 { 2333 list_msgsLat.back() << list_boundslat.back(); 2334 } 2335 2336 eventLon.push(rank, nbSenders[serverSize][rank], list_msgsLon.back()); 2337 eventLat.push(rank, nbSenders[serverSize][rank], list_msgsLat.back()); 2338 } 2339 client->sendEvent(eventLon); 2340 client->sendEvent(eventLat); 2341 } 1933 string domainId; 1934 int phasis ; 1935 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> phasis ; 1936 get(domainId)->receivedDomainDistribution(event, phasis); 2342 1937 } 2343 CATCH_DUMP_ATTR 2344 2345 /*! 2346 Send data index to corresponding connected clients. 2347 Data index can be compressed however, we always send decompressed data index 2348 and they will be compressed on receiving. 2349 The compressed index are represented with 1 and others are represented with -1 2350 */ 2351 void CDomain::sendDataIndex() 1938 CATCH 1939 1940 void CDomain::receivedDomainDistribution(CEventServer& event, int phasis) 2352 1941 TRY 2353 1942 { 2354 int ns, n, i, j, ind, nv, idx; 2355 std::list<CContextClient*>::iterator it; 2356 for (it=clients.begin(); it!=clients.end(); ++it) 1943 CContext* context = CContext::getCurrent(); 1944 if (phasis==0) // receive the remote element to construct the full view 2357 1945 { 2358 CContextClient* client = *it; 2359 2360 int serverSize = client->serverSize; 2361 2362 // send area for each connected server 2363 CEventClient eventDataIndex(getType(), EVENT_ID_DATA_INDEX); 2364 2365 list<CMessage> list_msgsDataIndex; 2366 list<CArray<int,1> > list_data_i_index, list_data_j_index; 2367 2368 int nbIndex = i_index.numElements(); 2369 int niByIndex = max(i_index) - min(i_index) + 1; 2370 int njByIndex = max(j_index) - min(j_index) + 1; 2371 int dataIindexBound = (1 == data_dim) ? (niByIndex * njByIndex) : niByIndex; 2372 int dataJindexBound = (1 == data_dim) ? (niByIndex * njByIndex) : njByIndex; 2373 2374 2375 CArray<int,1> dataIIndex(nbIndex), dataJIndex(nbIndex); 2376 dataIIndex = -1; 2377 dataJIndex = -1; 2378 ind = 0; 2379 2380 for (idx = 0; idx < data_i_index.numElements(); ++idx) 2381 { 2382 int dataIidx = data_i_index(idx) + data_ibegin; 2383 int dataJidx = data_j_index(idx) + data_jbegin; 2384 if ((0 <= dataIidx) && (dataIidx < dataIindexBound) && 2385 (0 <= dataJidx) && (dataJidx < dataJindexBound)) 2386 { 2387 dataIIndex((1 == data_dim) ? dataIidx : dataJidx * ni + dataIidx) = 1; //i_index(dataIidx);//dataIidx; 2388 dataJIndex((1 == data_dim) ? dataIidx : dataJidx * ni + dataIidx) = 1; //j_index(dataJidx);// 2389 } 2390 } 2391 2392 std::unordered_map<int, vector<size_t> >::const_iterator it, iteMap; 2393 iteMap = indSrv_[serverSize].end(); 2394 for (int k = 0; k < connectedServerRank_[serverSize].size(); ++k) 2395 { 2396 int nbData = 0; 2397 int rank = connectedServerRank_[serverSize][k]; 2398 it = indSrv_[serverSize].find(rank); 2399 if (iteMap != it) 2400 nbData = it->second.size(); 2401 list_data_i_index.push_back(CArray<int,1>(nbData)); 2402 list_data_j_index.push_back(CArray<int,1>(nbData)); 2403 2404 const std::vector<size_t>& temp = it->second; 2405 for (n = 0; n < nbData; ++n) 2406 { 2407 idx = static_cast<int>(it->second[n]); 2408 i = globalLocalIndexMap_[idx]; 2409 list_data_i_index.back()(n) = dataIIndex(i); 2410 list_data_j_index.back()(n) = dataJIndex(i); 2411 } 2412 2413 list_msgsDataIndex.push_back(CMessage()); 2414 list_msgsDataIndex.back() << this->getId(); 2415 list_msgsDataIndex.back() << list_data_i_index.back() << list_data_j_index.back(); 2416 eventDataIndex.push(rank, nbSenders[serverSize][rank], list_msgsDataIndex.back()); 2417 } 2418 client->sendEvent(eventDataIndex); 1946 localElement_ = new CLocalElement(context->getIntraCommRank(),event) ; 1947 localElement_->addFullView() ; 1948 // construct the local dimension and indexes 1949 auto& globalIndex=localElement_->getGlobalIndex() ; 1950 int nij=globalIndex.numElements() ; 1951 int minI=ni_glo,maxI=-1,minJ=nj_glo,maxJ=-1 ; 1952 int i,j ; 1953 int niGlo=ni_glo, njGlo=njGlo ; 1954 for(int ij=0;ij<nij;ij++) 1955 { 1956 j=globalIndex(ij)/niGlo ; 1957 i=globalIndex(ij)%niGlo ; 1958 if (i<minI) minI=i ; 1959 if (i>maxI) maxI=i ; 1960 if (j<minJ) minJ=j ; 1961 if (j>maxJ) maxJ=j ; 1962 } 1963 if (maxI>=minI) { ibegin=minI ; ni=maxI-minI+1 ; } 1964 else {ibegin=0; ni=0 ;} 1965 if (maxJ>=minJ) { jbegin=minJ ; nj=maxJ-minJ+1 ; } 1966 else {jbegin=0; nj=0 ;} 1967 1968 } 1969 else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server 1970 { 1971 CContext* context = CContext::getCurrent(); 1972 CDistributedElement* elementFrom = new CDistributedElement(event) ; 1973 elementFrom->addFullView() ; 1974 gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 1975 gathererConnector_->computeConnector() ; 1976 } 1977 else if (phasis==2) 1978 { 1979 // delete gathererConnector_ ; 1980 elementFrom_ = new CDistributedElement(event) ; 1981 elementFrom_->addFullView() ; 1982 // gathererConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 1983 // gathererConnector_ -> computeConnector() ; 2419 1984 } 2420 1985 } 2421 1986 CATCH 2422 1987 1988 void CDomain::setServerMask(CArray<bool,1>& serverMask, CContextClient* client) 1989 TRY 1990 { 1991 // nota : the client is needed to get the remote size for the scatterer connector. Maybe it is not the good place for this 1992 // Later, server to client connector can be computed on demand, with "client" as argument 1993 CContext* context = CContext::getCurrent(); 1994 localElement_->addView(CElementView::WORKFLOW, serverMask) ; 1995 mask_1d.reference(serverMask.copy()) ; 1996 1997 serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ; 1998 serverFromClientConnector_->computeConnector() ; 1999 2000 serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL), 2001 context->getIntraComm(), client->getRemoteSize()) ; 2002 serverToClientConnector_->computeConnector() ; 2003 } 2004 CATCH_DUMP_ATTR 2005 2006 2007 void CDomain::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& domainId) 2008 { 2009 string serverDomainId = domainId.empty() ? this->getId() : domainId ; 2010 CContext* context = CContext::getCurrent(); 2011 2012 if (hasLonLat) 2013 { 2014 { // send longitude 2015 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 2016 CMessage message ; 2017 message<<serverDomainId<<string("lon") ; 2018 scattererConnector.transfer(lonvalue, client, event,message) ; 2019 } 2020 2021 { // send latitude 2022 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 2023 CMessage message ; 2024 message<<serverDomainId<<string("lat") ; 2025 scattererConnector.transfer(latvalue, client, event, message) ; 2026 } 2027 } 2028 2029 if (hasBounds) 2030 { 2031 { // send longitude boudaries 2032 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 2033 CMessage message ; 2034 message<<serverDomainId<<string("boundslon") ; 2035 scattererConnector.transfer(nvertex, bounds_lonvalue, client, event, message ) ; 2036 } 2037 2038 { // send latitude boudaries 2039 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 2040 CMessage message ; 2041 message<<serverDomainId<<string("boundslat") ; 2042 scattererConnector.transfer(nvertex, bounds_latvalue, client, event, message ) ; 2043 } 2044 } 2045 2046 if (hasArea) 2047 { // send area 2048 CEventClient event(getType(), EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE); 2049 CMessage message ; 2050 message<<serverDomainId<<string("area") ; 2051 scattererConnector.transfer(areavalue, client, event,message) ; 2052 } 2053 } 2054 2055 void CDomain::recvDistributedAttributes(CEventServer& event) 2056 TRY 2057 { 2058 string domainId; 2059 string type ; 2060 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> type ; 2061 get(domainId)->recvDistributedAttributes(event, type); 2062 } 2063 CATCH 2064 2065 void CDomain::recvDistributedAttributes(CEventServer& event, const string& type) 2066 TRY 2067 { 2068 if (type=="lon") 2069 { 2070 CArray<double,1> value ; 2071 gathererConnector_->transfer(event, value, 0.); 2072 lonvalue_2d.resize(ni,nj) ; 2073 if (lonvalue_2d.numElements()>0) lonvalue_2d=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 2074 } 2075 else if (type=="lat") 2076 { 2077 CArray<double,1> value ; 2078 gathererConnector_->transfer(event, value, 0.); 2079 latvalue_2d.resize(ni,nj) ; 2080 if (latvalue_2d.numElements()>0) latvalue_2d=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 2081 } 2082 else if (type=="boundslon") 2083 { 2084 CArray<double,1> value ; 2085 gathererConnector_->transfer(event, nvertex, value, 0.); 2086 bounds_lon_2d.resize(nvertex,ni,nj) ; 2087 if (bounds_lon_2d.numElements()>0) bounds_lon_2d=CArray<double,3>(value.dataFirst(),shape(nvertex,ni,nj),neverDeleteData) ; 2088 } 2089 else if (type=="boundslat") 2090 { 2091 CArray<double,1> value ; 2092 gathererConnector_->transfer(event, nvertex, value, 0.); 2093 bounds_lat_2d.resize(nvertex,ni,nj) ; 2094 if (bounds_lat_2d.numElements()>0) bounds_lat_2d=CArray<double,3>(value.dataFirst(),shape(nvertex,ni,nj),neverDeleteData) ; 2095 } 2096 else if (type=="area") 2097 { 2098 CArray<double,1> value ; 2099 gathererConnector_->transfer(event, value, 0.); 2100 area.resize(ni,nj) ; 2101 if (area.numElements()>0) area=CArray<double,2>(value.dataFirst(),shape(ni,nj),neverDeleteData) ; 2102 } 2103 } 2104 CATCH 2105 2423 2106 bool CDomain::dispatchEvent(CEventServer& event) 2424 2107 TRY … … 2429 2112 switch(event.type) 2430 2113 { 2431 case EVENT_ID_ SERVER_ATTRIBUT:2432 recvD istributionAttributes(event);2114 case EVENT_ID_DOMAIN_DISTRIBUTION: 2115 recvDomainDistribution(event); 2433 2116 return true; 2434 2117 break; 2435 case EVENT_ID_INDEX: 2436 recvIndex(event); 2437 return true; 2438 break; 2439 case EVENT_ID_LON: 2440 recvLon(event); 2441 return true; 2442 break; 2443 case EVENT_ID_LAT: 2444 recvLat(event); 2445 return true; 2446 break; 2447 case EVENT_ID_AREA: 2448 recvArea(event); 2118 case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE: 2119 recvDistributedAttributes(event); 2449 2120 return true; 2450 2121 break; 2451 case EVENT_ID_DATA_INDEX:2452 recvDataIndex(event);2453 return true;2454 break;2455 2122 default: 2456 2123 ERROR("bool CDomain::dispatchEvent(CEventServer& event)", … … 2462 2129 CATCH 2463 2130 2464 /*! 2465 Receive index event from clients(s) 2466 \param[in] event event contain info about rank and associated index 2467 */ 2468 void CDomain::recvIndex(CEventServer& event) 2469 TRY 2470 { 2471 string domainId; 2472 std::map<int, CBufferIn*> rankBuffers; 2473 2474 list<CEventServer::SSubEvent>::iterator it; 2475 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 2476 { 2477 CBufferIn* buffer = it->buffer; 2478 *buffer >> domainId; 2479 rankBuffers[it->rank] = buffer; 2480 } 2481 get(domainId)->recvIndex(rankBuffers); 2482 } 2483 CATCH 2484 2485 /*! 2486 Receive index information from client(s). We use the global index for mapping index between 2487 sending clients and receiving clients. 2488 \param[in] rankBuffers rank of sending client and the corresponding receive buffer 2489 */ 2490 void CDomain::recvIndex(std::map<int, CBufferIn*>& rankBuffers) 2491 TRY 2492 { 2493 int nbReceived = rankBuffers.size(), i, ind, index, type_int, iIndex, jIndex; 2494 recvClientRanks_.resize(nbReceived); 2495 2496 std::map<int, CBufferIn*>::iterator it = rankBuffers.begin(), ite = rankBuffers.end(); 2497 ind = 0; 2498 for (ind = 0; it != ite; ++it, ++ind) 2499 { 2500 recvClientRanks_[ind] = it->first; 2501 CBufferIn& buffer = *(it->second); 2502 buffer >> type_int >> isCurvilinear >> indGlob_[it->first]; 2503 type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix 2504 } 2505 int nbIndGlob = 0; 2506 for (i = 0; i < nbReceived; ++i) 2507 { 2508 nbIndGlob += indGlob_[recvClientRanks_[i]].numElements(); 2509 } 2510 2511 globalLocalIndexMap_.rehash(std::ceil(nbIndGlob/globalLocalIndexMap_.max_load_factor())); 2512 i_index.resize(nbIndGlob); 2513 j_index.resize(nbIndGlob); 2514 int nbIndexGlobMax = nbIndGlob, nbIndLoc; 2515 2516 nbIndGlob = 0; 2517 for (i = 0; i < nbReceived; ++i) 2518 { 2519 CArray<int,1>& tmp = indGlob_[recvClientRanks_[i]]; 2520 for (ind = 0; ind < tmp.numElements(); ++ind) 2521 { 2522 index = tmp(ind); 2523 if (0 == globalLocalIndexMap_.count(index)) 2524 { 2525 iIndex = (index%ni_glo)-ibegin; 2526 iIndex = (iIndex < 0) ? 0 : iIndex; 2527 jIndex = (index/ni_glo)-jbegin; 2528 jIndex = (jIndex < 0) ? 0 : jIndex; 2529 nbIndLoc = iIndex + ni * jIndex; 2530 i_index(nbIndGlob) = index % ni_glo; 2531 j_index(nbIndGlob) = index / ni_glo; 2532 globalLocalIndexMap_[index] = nbIndGlob; 2533 ++nbIndGlob; 2534 } 2535 } 2536 } 2537 2538 if (nbIndGlob==0) 2539 { 2540 i_index.resize(nbIndGlob); 2541 j_index.resize(nbIndGlob); 2542 } 2543 else 2544 { 2545 i_index.resizeAndPreserve(nbIndGlob); 2546 j_index.resizeAndPreserve(nbIndGlob); 2547 } 2548 2549 domainMask.resize(0); // Mask is not defined anymore on servers 2550 } 2551 CATCH 2552 2553 /*! 2554 Receive attributes event from clients(s) 2555 \param[in] event event contain info about rank and associated attributes 2556 */ 2557 void CDomain::recvDistributionAttributes(CEventServer& event) 2558 TRY 2559 { 2560 CBufferIn* buffer=event.subEvents.begin()->buffer; 2561 string domainId ; 2562 *buffer>>domainId ; 2563 get(domainId)->recvDistributionAttributes(*buffer); 2564 } 2565 CATCH 2566 2567 /*! 2568 Receive attributes from client(s) 2569 \param[in] rank rank of client source 2570 \param[in] buffer message containing attributes info 2571 */ 2572 void CDomain::recvDistributionAttributes(CBufferIn& buffer) 2573 TRY 2574 { 2575 int ni_tmp, ibegin_tmp, nj_tmp, jbegin_tmp; 2576 int ni_glo_tmp, nj_glo_tmp; 2577 buffer >> isUnstructed_ >> ni_tmp >> ibegin_tmp >> nj_tmp >> jbegin_tmp 2578 >> ni_glo_tmp >> nj_glo_tmp 2579 >> isCompressible_; 2580 2581 ni.setValue(ni_tmp); 2582 ibegin.setValue(ibegin_tmp); 2583 nj.setValue(nj_tmp); 2584 jbegin.setValue(jbegin_tmp); 2585 ni_glo.setValue(ni_glo_tmp); 2586 nj_glo.setValue(nj_glo_tmp); 2587 2588 } 2589 CATCH_DUMP_ATTR 2590 /*! 2591 Receive longitude event from clients(s) 2592 \param[in] event event contain info about rank and associated longitude 2593 */ 2594 void CDomain::recvLon(CEventServer& event) 2595 TRY 2596 { 2597 string domainId; 2598 std::map<int, CBufferIn*> rankBuffers; 2599 2600 list<CEventServer::SSubEvent>::iterator it; 2601 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 2602 { 2603 CBufferIn* buffer = it->buffer; 2604 *buffer >> domainId; 2605 rankBuffers[it->rank] = buffer; 2606 } 2607 get(domainId)->recvLon(rankBuffers); 2608 } 2609 CATCH 2610 2611 /*! 2612 Receive longitude information from client(s) 2613 \param[in] rankBuffers rank of sending client and the corresponding receive buffer 2614 */ 2615 void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers) 2616 TRY 2617 { 2618 int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex, lInd; 2619 if (nbReceived != recvClientRanks_.size()) 2620 ERROR("void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)", 2621 << "The number of sending clients is not correct." 2622 << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived); 2623 2624 vector<CArray<double,1> > recvLonValue(nbReceived); 2625 vector<CArray<double,2> > recvBoundsLonValue(nbReceived); 2626 for (i = 0; i < recvClientRanks_.size(); ++i) 2627 { 2628 int rank = recvClientRanks_[i]; 2629 CBufferIn& buffer = *(rankBuffers[rank]); 2630 buffer >> hasLonLat; 2631 if (hasLonLat) 2632 buffer >> recvLonValue[i]; 2633 buffer >> hasBounds; 2634 if (hasBounds) 2635 buffer >> recvBoundsLonValue[i]; 2636 } 2637 2638 if (hasLonLat) 2639 { 2640 int nbLonInd = 0; 2641 for (i = 0; i < nbReceived; ++i) 2642 { 2643 nbLonInd += recvLonValue[i].numElements(); 2644 } 2645 2646 if (nbLonInd != globalLocalIndexMap_.size()) 2647 info (0) << "If domain " << this->getDomainOutputName() <<" does not have overlapped regions between processes " 2648 << "something must be wrong with longitude index "<< std::endl; 2649 2650 nbLonInd = globalLocalIndexMap_.size(); 2651 lonvalue.resize(nbLonInd); 2652 if (hasBounds) 2653 { 2654 bounds_lonvalue.resize(nvertex,nbLonInd); 2655 bounds_lonvalue = 0.; 2656 } 2657 2658 nbLonInd = 0; 2659 for (i = 0; i < nbReceived; ++i) 2660 { 2661 CArray<int,1>& tmpInd = indGlob_[recvClientRanks_[i]]; 2662 CArray<double,1>& tmp = recvLonValue[i]; 2663 for (ind = 0; ind < tmp.numElements(); ++ind) 2664 { 2665 lInd = globalLocalIndexMap_[size_t(tmpInd(ind))]; 2666 lonvalue(lInd) = tmp(ind); 2667 if (hasBounds) 2668 { 2669 for (int nv = 0; nv < nvertex; ++nv) 2670 bounds_lonvalue(nv, lInd) = recvBoundsLonValue[i](nv, ind); 2671 } 2672 } 2673 } 2674 } 2675 } 2676 CATCH_DUMP_ATTR 2677 2678 /*! 2679 Receive latitude event from clients(s) 2680 \param[in] event event contain info about rank and associated latitude 2681 */ 2682 void CDomain::recvLat(CEventServer& event) 2683 TRY 2684 { 2685 string domainId; 2686 std::map<int, CBufferIn*> rankBuffers; 2687 2688 list<CEventServer::SSubEvent>::iterator it; 2689 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 2690 { 2691 CBufferIn* buffer = it->buffer; 2692 *buffer >> domainId; 2693 rankBuffers[it->rank] = buffer; 2694 } 2695 get(domainId)->recvLat(rankBuffers); 2696 } 2697 CATCH 2698 2699 /*! 2700 Receive latitude information from client(s) 2701 \param[in] rankBuffers rank of sending client and the corresponding receive buffer 2702 */ 2703 void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers) 2704 TRY 2705 { 2706 int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex, lInd; 2707 if (nbReceived != recvClientRanks_.size()) 2708 ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)", 2709 << "The number of sending clients is not correct." 2710 << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived); 2711 2712 vector<CArray<double,1> > recvLatValue(nbReceived); 2713 vector<CArray<double,2> > recvBoundsLatValue(nbReceived); 2714 for (i = 0; i < recvClientRanks_.size(); ++i) 2715 { 2716 int rank = recvClientRanks_[i]; 2717 CBufferIn& buffer = *(rankBuffers[rank]); 2718 buffer >> hasLonLat; 2719 if (hasLonLat) 2720 buffer >> recvLatValue[i]; 2721 buffer >> hasBounds; 2722 if (hasBounds) 2723 buffer >> recvBoundsLatValue[i]; 2724 } 2725 2726 if (hasLonLat) 2727 { 2728 int nbLatInd = 0; 2729 for (i = 0; i < nbReceived; ++i) 2730 { 2731 nbLatInd += recvLatValue[i].numElements(); 2732 } 2733 2734 if (nbLatInd != globalLocalIndexMap_.size()) 2735 info (0) << "If domain " << this->getDomainOutputName() <<" does not have overlapped regions between processes " 2736 << "something must be wrong with latitude index "<< std::endl; 2737 2738 nbLatInd = globalLocalIndexMap_.size(); 2739 latvalue.resize(nbLatInd); 2740 if (hasBounds) 2741 { 2742 bounds_latvalue.resize(nvertex,nbLatInd); 2743 bounds_latvalue = 0. ; 2744 } 2745 2746 nbLatInd = 0; 2747 for (i = 0; i < nbReceived; ++i) 2748 { 2749 CArray<int,1>& tmpInd = indGlob_[recvClientRanks_[i]]; 2750 CArray<double,1>& tmp = recvLatValue[i]; 2751 for (ind = 0; ind < tmp.numElements(); ++ind) 2752 { 2753 lInd = globalLocalIndexMap_[size_t(tmpInd(ind))]; 2754 latvalue(lInd) = tmp(ind); 2755 if (hasBounds) 2756 { 2757 CArray<double,2>& boundslat = recvBoundsLatValue[i]; 2758 for (int nv = 0; nv < nvertex; ++nv) 2759 bounds_latvalue(nv, lInd) = boundslat(nv, ind); 2760 } 2761 ++nbLatInd; 2762 } 2763 } 2764 } 2765 } 2766 CATCH_DUMP_ATTR 2767 2768 /*! 2769 Receive area event from clients(s) 2770 \param[in] event event contain info about rank and associated area 2771 */ 2772 void CDomain::recvArea(CEventServer& event) 2773 TRY 2774 { 2775 string domainId; 2776 std::map<int, CBufferIn*> rankBuffers; 2777 2778 list<CEventServer::SSubEvent>::iterator it; 2779 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 2780 { 2781 CBufferIn* buffer = it->buffer; 2782 *buffer >> domainId; 2783 rankBuffers[it->rank] = buffer; 2784 } 2785 get(domainId)->recvArea(rankBuffers); 2786 } 2787 CATCH 2788 2789 /*! 2790 Receive area information from client(s) 2791 \param[in] rankBuffers rank of sending client and the corresponding receive buffer 2792 */ 2793 void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers) 2794 TRY 2795 { 2796 int nbReceived = rankBuffers.size(), i, ind, index, lInd; 2797 if (nbReceived != recvClientRanks_.size()) 2798 ERROR("void CDomain::recvArea(std::map<int, CBufferIn*>& rankBuffers)", 2799 << "The number of sending clients is not correct." 2800 << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived); 2801 2802 vector<CArray<double,1> > recvAreaValue(nbReceived); 2803 for (i = 0; i < recvClientRanks_.size(); ++i) 2804 { 2805 int rank = recvClientRanks_[i]; 2806 CBufferIn& buffer = *(rankBuffers[rank]); 2807 buffer >> hasArea; 2808 if (hasArea) 2809 buffer >> recvAreaValue[i]; 2810 } 2811 2812 if (hasArea) 2813 { 2814 int nbAreaInd = 0; 2815 for (i = 0; i < nbReceived; ++i) 2816 { 2817 nbAreaInd += recvAreaValue[i].numElements(); 2818 } 2819 2820 if (nbAreaInd != globalLocalIndexMap_.size()) 2821 info (0) << "If domain " << this->getDomainOutputName() <<" does not have overlapped regions between processes " 2822 << "something must be wrong with area index "<< std::endl; 2823 2824 nbAreaInd = globalLocalIndexMap_.size(); 2825 areavalue.resize(nbAreaInd); 2826 nbAreaInd = 0; 2827 for (i = 0; i < nbReceived; ++i) 2828 { 2829 CArray<int,1>& tmpInd = indGlob_[recvClientRanks_[i]]; 2830 CArray<double,1>& tmp = recvAreaValue[i]; 2831 for (ind = 0; ind < tmp.numElements(); ++ind) 2832 { 2833 lInd = globalLocalIndexMap_[size_t(tmpInd(ind))]; 2834 areavalue(lInd) = tmp(ind); 2835 } 2836 } 2837 2838 } 2839 } 2840 CATCH_DUMP_ATTR 2841 2131 2842 2132 /*! 2843 2133 Compare two domain objects. … … 2873 2163 CATCH_DUMP_ATTR 2874 2164 2875 /*! 2876 Receive data index event from clients(s) 2877 \param[in] event event contain info about rank and associated index 2878 */ 2879 void CDomain::recvDataIndex(CEventServer& event) 2165 ///////////////////////////////////////////////////////////////////////// 2166 /////////////// TRANSFORMATIONS ////////// 2167 ///////////////////////////////////////////////////////////////////////// 2168 2169 std::map<StdString, ETranformationType> CDomain::transformationMapList_ = std::map<StdString, ETranformationType>(); 2170 bool CDomain::dummyTransformationMapList_ = CDomain::initializeTransformationMap(CDomain::transformationMapList_); 2171 2172 bool CDomain::initializeTransformationMap(std::map<StdString, ETranformationType>& m) 2880 2173 TRY 2881 2174 { 2882 string domainId; 2883 std::map<int, CBufferIn*> rankBuffers; 2884 2885 list<CEventServer::SSubEvent>::iterator it; 2886 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 2887 { 2888 CBufferIn* buffer = it->buffer; 2889 *buffer >> domainId; 2890 rankBuffers[it->rank] = buffer; 2891 } 2892 get(domainId)->recvDataIndex(rankBuffers); 2175 m["zoom_domain"] = TRANS_ZOOM_DOMAIN; 2176 m["interpolate_domain"] = TRANS_INTERPOLATE_DOMAIN; 2177 m["generate_rectilinear_domain"] = TRANS_GENERATE_RECTILINEAR_DOMAIN; 2178 m["compute_connectivity_domain"] = TRANS_COMPUTE_CONNECTIVITY_DOMAIN; 2179 m["expand_domain"] = TRANS_EXPAND_DOMAIN; 2180 m["reorder_domain"] = TRANS_REORDER_DOMAIN; 2181 m["extract_domain"] = TRANS_EXTRACT_DOMAIN; 2893 2182 } 2894 2183 CATCH 2895 2184 2896 /*!2897 Receive data index information from client(s)2898 A client receives data index from different clients to rebuild its own data index.2899 Because we use global index + mask info to calculate the sending data to client(s),2900 this data index must be updated with mask info (maybe it will change in the future)2901 Because the data index is local, to rebuild data index of received client, we should use global index along with.2902 2903 \param[in] rankBuffers rank of sending client and the corresponding receive buffer2904 */2905 void CDomain::recvDataIndex(std::map<int, CBufferIn*>& rankBuffers)2906 TRY2907 {2908 int nbReceived = rankBuffers.size(), i, ind, index, indexI, indexJ, type_int, lInd;2909 if (nbReceived != recvClientRanks_.size())2910 ERROR("void CDomain::recvDataIndex(std::map<int, CBufferIn*>& rankBuffers)",2911 << "The number of sending clients is not correct."2912 << "Expected number: " << recvClientRanks_.size() << " but received " << nbReceived);2913 2914 vector<CArray<int,1> > recvDataIIndex(nbReceived),recvDataJIndex(nbReceived);2915 for (i = 0; i < recvClientRanks_.size(); ++i)2916 {2917 int rank = recvClientRanks_[i];2918 CBufferIn& buffer = *(rankBuffers[rank]);2919 buffer >> recvDataIIndex[i];2920 buffer >> recvDataJIndex[i];2921 }2922 2923 int nbIndex = i_index.numElements();2924 CArray<int,1> dataIIndex(nbIndex), dataJIndex(nbIndex);2925 dataIIndex = -1; dataJIndex = -1;2926 2927 nbIndex = 0;2928 for (i = 0; i < nbReceived; ++i)2929 {2930 CArray<int,1>& tmpInd = indGlob_[recvClientRanks_[i]];2931 CArray<int,1>& tmpI = recvDataIIndex[i];2932 CArray<int,1>& tmpJ = recvDataJIndex[i];2933 if ((tmpI.numElements() != tmpInd.numElements()) || (tmpJ.numElements() != tmpInd.numElements()))2934 ERROR("void CDomain::recvDataIndex(std::map<int, CBufferIn*>& rankBuffers)",2935 << "The number of global received index is not coherent with the number of received data index."2936 << "Expected number of global index: " << tmpI.numElements() << " but received " << tmpInd.numElements());2937 2938 for (ind = 0; ind < tmpI.numElements(); ++ind)2939 {2940 lInd = globalLocalIndexMap_[size_t(tmpInd(ind))];2941 dataIIndex(lInd) = (-1 == dataIIndex(lInd)) ? tmpI(ind) : dataIIndex(lInd); // Only fill in dataIndex if there is no data2942 dataJIndex(lInd) = (-1 == dataJIndex(lInd)) ? tmpJ(ind) : dataJIndex(lInd);2943 }2944 }2945 2946 int nbCompressedData = 0;2947 for (ind = 0; ind < dataIIndex.numElements(); ++ind)2948 {2949 indexI = dataIIndex(ind); indexJ = dataJIndex(ind);2950 if ((0 <= indexI) && (0 <= indexJ))2951 ++nbCompressedData;2952 }2953 2954 data_i_index.resize(nbCompressedData);2955 data_j_index.resize(nbCompressedData);2956 2957 nbCompressedData = 0;2958 for (ind = 0; ind < dataIIndex.numElements(); ++ind)2959 {2960 indexI = dataIIndex(ind); indexJ = dataJIndex(ind);2961 if ((0 <= indexI) && (0 <= indexJ))2962 {2963 data_i_index(nbCompressedData) = (1 == data_dim) ? ind : ind % ni;2964 data_j_index(nbCompressedData) = (1 == data_dim) ? 0 : ind / ni;2965 ++nbCompressedData;2966 }2967 }2968 2969 // Reset data_ibegin, data_jbegin2970 data_ibegin.setValue(0);2971 data_jbegin.setValue(0);2972 }2973 CATCH_DUMP_ATTR2974 2185 2975 2186 CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, const StdString& id) … … 2981 2192 CATCH_DUMP_ATTR 2982 2193 2194 CTransformation<CDomain>* CDomain::addTransformation(ETranformationType transType, CTransformation<CDomain>* transformation) 2195 TRY 2196 { 2197 transformationMap_.push_back(std::make_pair(transType, transformation)); 2198 return transformationMap_.back().second; 2199 } 2200 CATCH_DUMP_ATTR 2983 2201 /*! 2984 2202 Check whether a domain has transformation … … 3023 2241 } 3024 2242 CATCH_DUMP_ATTR 3025 2243 3026 2244 /*! 3027 2245 * Go through the hierarchy to find the domain from which the transformations must be inherited 3028 2246 */ 3029 void CDomain::solveInheritanceTransformation ()2247 void CDomain::solveInheritanceTransformation_old() 3030 2248 TRY 3031 2249 { … … 3046 2264 } 3047 2265 CATCH_DUMP_ATTR 2266 2267 2268 void CDomain::solveInheritanceTransformation() 2269 TRY 2270 { 2271 if (solveInheritanceTransformation_done_) return; 2272 else solveInheritanceTransformation_done_=true ; 2273 2274 CDomain* domain = this; 2275 CDomain* Lastdomain ; 2276 std::list<CDomain*> refDomains; 2277 bool out=false ; 2278 vector<StdString> excludedAttr; 2279 excludedAttr.push_back("domain_ref"); 2280 2281 refDomains.push_front(domain) ; 2282 while (domain->hasDirectDomainReference() && !out) 2283 { 2284 CDomain* lastDomain=domain ; 2285 domain = domain->getDirectDomainReference(); 2286 domain->solveRefInheritance() ; 2287 if (!domain->SuperClass::isEqual(lastDomain,excludedAttr)) out=true ; 2288 refDomains.push_front(domain) ; 2289 } 2290 2291 CTransformationPaths::TPath path ; 2292 auto& pathList = std::get<2>(path) ; 2293 std::get<0>(path) = EElement::DOMAIN ; 2294 std::get<1>(path) = refDomains.front()->getId() ; 2295 for (auto& domain : refDomains) 2296 { 2297 CDomain::TransMapTypes transformations = domain->getAllTransformations(); 2298 for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 2299 transformation.second->getId()}) ; 2300 } 2301 transformationPaths_.addPath(path) ; 2302 2303 } 2304 CATCH_DUMP_ATTR 2305 2306 ///////////////////////////////////////////////////////////////////////////////////////////// 2307 ///////////////////////////////////////////////////////////////////////////////////////////// 3048 2308 3049 2309 void CDomain::setContextClient(CContextClient* contextClient) -
XIOS/dev/dev_trunk_graph/src/node/domain.hpp
r1600 r2019 16 16 #include "transformation.hpp" 17 17 #include "transformation_enum.hpp" 18 #include "transformation_path.hpp" 18 19 #include "server_distribution_description.hpp" 19 20 #include "mesh.hpp" 20 21 namespace xios { 21 #include "element.hpp" 22 #include "local_connector.hpp" 23 #include "scatterer_connector.hpp" 24 #include "gatherer_connector.hpp" 25 #include "distribution_type.hpp" 26 #include "generic_algorithm_transformation.hpp" 27 28 29 namespace xios 30 { 22 31 23 32 /// ////////////////////// Déclarations ////////////////////// /// … … 48 57 enum EEventId 49 58 { 50 EVENT_ID_INDEX, EVENT_ID_LON, EVENT_ID_LAT, 51 EVENT_ID_AREA, 52 EVENT_ID_DATA_INDEX, EVENT_ID_SERVER_ATTRIBUT 59 EVENT_ID_DOMAIN_DISTRIBUTION, EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE 53 60 } ; 54 61 … … 57 64 typedef CDomainAttributes RelAttributes; 58 65 typedef CDomainGroup RelGroup; 59 typedef CTransformation<CDomain>::TransformationMapTypes TransMapTypes; 60 66 61 67 /// Constructeurs /// 62 68 CDomain(void); … … 76 82 /// Vérifications /// 77 83 void checkAttributes(void); 78 void checkAttributesOnClient(); 79 void checkAttributesOnClientAfterTransformation(); 80 void checkEligibilityForCompressedOutput(void); 81 82 void sendCheckedAttributes(); 83 84 bool hasTransformation(); 85 void solveInheritanceTransformation(); 86 TransMapTypes getAllTransformations(); 84 bool checkAttributes_done_ = false ; 85 86 87 ////////////////////////// 88 ///// transformations //// 89 ////////////////////////// 90 public: 91 typedef CTransformation<CDomain>::TransformationMapTypes TransMapTypes; 92 private: 93 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 94 static std::map<StdString, ETranformationType> transformationMapList_; 95 static bool dummyTransformationMapList_; 96 TransMapTypes transformationMap_; 97 98 public: 99 CTransformation<CDomain>* addTransformation(ETranformationType transType, const StdString& id=""); 100 CTransformation<CDomain>* addTransformation(ETranformationType transType, CTransformation<CDomain>* transformation) ; 101 void setTransformations(const TransMapTypes&); 102 void duplicateTransformation(CDomain*); 103 TransMapTypes getAllTransformations(); 104 bool hasTransformation(); 105 void solveInheritanceTransformation_old(); // to remove later 106 void solveInheritanceTransformation(); 107 private: 108 bool solveInheritanceTransformation_done_= false ; 109 private: 110 CGenericAlgorithmTransformation* transformationAlgorithm_ = nullptr ; 111 public: 112 void setTransformationAlgorithm(CGenericAlgorithmTransformation* transformationAlgorithm) { transformationAlgorithm_=transformationAlgorithm ;} 113 CGenericAlgorithmTransformation* getTransformationAlgorithm(void) { return transformationAlgorithm_ ;} 114 private: 115 CTransformationPaths transformationPaths_ ; 116 public: 117 CTransformationPaths getTransformationPaths(void) {return transformationPaths_;} 118 void setTransformationPaths(const CTransformationPaths& transformationPaths) { transformationPaths_=transformationPaths ;} 119 120 //////////////////////////// 121 87 122 void redistribute(int nbLocalDomain); 88 void duplicateTransformation(CDomain*);89 CTransformation<CDomain>* addTransformation(ETranformationType transType, const StdString& id="");90 123 91 124 public: … … 94 127 bool isWrittenCompressed(const StdString& filename) const; 95 128 96 int getNumberWrittenIndexes(MPI_Comm writtenCom);97 int getTotalNumberWrittenIndexes(MPI_Comm writtenCom);98 int getOffsetWrittenIndexes(MPI_Comm writtenCom);99 CArray<int,1>& getCompressedIndexToWriteOnServer(MPI_Comm writtenCom);100 101 129 std::map<int, StdSize> getAttributesBufferSize(CContextClient* client, bool bufferForWriting = false); 102 130 103 131 bool isEmpty(void) const; 104 132 bool isDistributed(void) const; 105 bool isCompressible(void) const; 106 107 std::vector<int> getNbGlob(); 133 134 public : 135 /*! 136 \brief return if the domain can be written or not in a compressed way. 137 ie if there are some masked or indexed point on the domain. Valid only on server side. 138 \return true if domain can be writtedn in a compressed way 139 */ 140 bool isCompressible(void) { if (!isCompressibleComputed_) computeIsCompressible() ; return isCompressible_ ;} 141 private : 142 bool isCompressible_ ; /** specify if the domain can be written in a compressed way */ 143 bool isCompressibleComputed_=false ; /** Indicate if compressability has been computed*/ 144 void computeIsCompressible() ; 145 146 public : 108 147 bool isEqual(CDomain* domain); 109 148 110 149 static bool dispatchEvent(CEventServer& event); 150 151 private: 152 /** define if the domain is completed or not ie all attributes have been received before in case 153 of grid reading from file or coupling */ 154 bool isCompleted_=true ; 155 public: 156 /*! 157 \brief Check if a domain is completed 158 Before make any domain processing, we must be sure that all domain informations have 159 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 160 other context (coupling). So all direct reference of the domain (domain_ref) must be also completed 161 \return true if domain and domain reference are completed 162 */ 163 bool isCompleted(void) 164 { 165 if (hasDirectDomainReference()) if (!getDirectDomainReference()->isCompleted()) return false; 166 else return isCompleted_ ; 167 } 168 void setCompleted(void) { isCompleted_=true ; } 169 void unsetCompleted(void) { isCompleted_=false ; } 111 170 112 171 public: … … 115 174 void addRelFileCompressed(const StdString& filename); 116 175 117 void computeWrittenIndex();118 void computeWrittenCompressedIndex(MPI_Comm);119 120 176 void AllgatherRectilinearLonLat(CArray<double,1>& lon, CArray<double,1>& lat, 121 177 CArray<double,1>& lon_g, CArray<double,1>& lat_g); … … 142 198 CArray<double, 1> areavalue; 143 199 144 CArray<int,1> localIndexToWriteOnServer;145 200 146 201 CArray<bool, 1> domainMask; // mask_1d, mask_2d -> domainMask … … 157 212 158 213 void computeLocalMask(void) ; 214 215 /** The number of server of a context client. Avoid to re-compute indice computed in a previous computeConnectedClient */ 216 private: std::set<int> listNbServer_ ; 217 159 218 private: 160 219 void checkDomain(void); … … 169 228 void checkArea(void); 170 229 void checkLonLat(); 171 172 void setTransformations(const TransMapTypes&); 173 void computeNGlobDomain(); 174 void sendAttributes(); 175 void sendIndex(); 176 void sendDistributionAttributes(); 177 void sendArea(); 178 void sendLonLat(); 179 void sendDataIndex(); 230 231 public: 232 void sendDomainToFileServer(CContextClient* client) ; 233 private: 234 std::set<CContextClient*> sendDomainToFileServer_done_ ; 235 public: 236 void sendDomainToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid) ; 237 private: 238 std::set<CContextClient*> sendDomainToCouplerOut_done_ ; 239 240 public: 241 void makeAliasForCoupling(const string& fieldId, int posInGrid) ; 242 243 private: 244 180 245 void convertLonLatValue(); 181 246 void fillInRectilinearLonLat(); 182 247 void fillInCurvilinearLonLat(); 183 248 void fillInUnstructuredLonLat(); 184 185 static void recvDistributionAttributes(CEventServer& event);186 static void recvIndex(CEventServer& event);187 static void recvLon(CEventServer& event);188 static void recvLat(CEventServer& event);189 static void recvArea(CEventServer& event);190 static void recvDataIndex(CEventServer& event);191 void recvDistributionAttributes(CBufferIn& buffer);192 void recvIndex(std::map<int, CBufferIn*>& rankBuffers);193 void recvLon(std::map<int, CBufferIn*>& rankBuffers);194 void recvLat(std::map<int, CBufferIn*>& rankBuffers);195 void recvArea(std::map<int, CBufferIn*>& rankBuffers);196 void recvDataIndex(std::map<int, CBufferIn*>& rankBuffers);197 198 249 void completeLonLatClient(void); 199 void computeConnectedClients();200 250 251 201 252 private: 202 253 … … 205 256 std::set<CContextClient*> clientsSet; 206 257 207 bool isChecked , computedWrittenIndex_;258 bool isChecked ; 208 259 std::set<StdString> relFiles, relFilesCompressed; 209 bool isClientChecked; // Verify whether all attributes of domain on the client side are good 210 bool isClientAfterTransformationChecked; 211 std::map<int, CArray<int,1> > indGlob_;212 std::map<int, map<int,int> > nbSenders; // Mapping of number of communicating client to a server213 214 /** Global index of each client sent to server: map<serverSize, map<serverRank, indexes>>*/260 261 /** only on client side : Global index of each client sent to server: map<serverSize, map<serverRank, indexes>> 262 indSrv_[nbServers] --> first map is related to the server distribution (ie associated with the contextClient) 263 indSrv_[nbServers][server_rank] -> array of global index sent to the server of rank "server_rank" 264 indSrv_[nbServers][server_rank](ind) --> global index on server of the local element "ind" sent (for lon, lat, mask, etc...) 265 */ 215 266 std::map<int, std::unordered_map<int, vector<size_t> > > indSrv_; 216 // std::map<CContextClient*, std::map<int, vector<int> > > indWrittenSrv_; // Global written index of each client sent to server 217 std::vector<int> indexesToWrite; 218 std::vector<int> recvClientRanks_; 219 std::map<int,int> numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_; 220 std::map<int, CArray<int, 1> > compressedIndexToWriteOnServer; 221 std::map<int, std::map<int,size_t> > connectedDataSize_; 267 222 268 std::map<int, std::vector<int> > connectedServerRank_; 223 269 224 //! True if and only if the data defined on the domain can be outputted in a compressed way225 bool isCompressible_;226 270 bool isRedistributed_; 227 TransMapTypes transformationMap_;228 271 bool isUnstructed_; 229 std::unordered_map<size_t,size_t> globalLocalIndexMap_; 272 230 273 231 private: 232 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 233 static std::map<StdString, ETranformationType> transformationMapList_; 234 static bool _dummyTransformationMapList; 274 ////////////////////////////////////////////////////////////////////////////////////// 275 // this part is related to distribution, element definition, views and connectors // 276 ////////////////////////////////////////////////////////////////////////////////////// 277 private: 278 CLocalElement* localElement_ = nullptr ; 279 void initializeLocalElement(void) ; 280 281 public: 282 CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; } 283 CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;} 284 285 private: 286 void addFullView(void) ; 287 void addWorkflowView(void) ; 288 void addModelView(void) ; 289 290 private: 291 CLocalConnector* modelToWorkflowConnector_ ; 292 void computeModelToWorkflowConnector(void) ; 293 public: 294 CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;} 295 296 public: 297 void computeRemoteElement(CContextClient* client, EDistributionType) ; 298 void distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, CScattererConnector* &scattererConnector, 299 const string& domainId="") ; 300 301 static void recvDomainDistribution(CEventServer& event) ; 302 void receivedDomainDistribution(CEventServer& event, int phasis) ; 303 304 void sendDistributedAttributes(CContextClient* client, CScattererConnector& scaterrerConnector, const string& domainId) ; 305 static void recvDistributedAttributes(CEventServer& event) ; 306 void recvDistributedAttributes(CEventServer& event, const string& type) ; 307 void setServerMask(CArray<bool,1>& serverMask, CContextClient* client) ; 308 309 private: 310 map<CContextClient*, CDistributedElement*> remoteElement_ ; 311 public: 312 CDistributedElement* getRemoteElement(CContextClient* client) {return remoteElement_[client] ;} 313 private: 314 map<CContextClient*, CScattererConnector*> clientToServerConnector_ ; 315 public: 316 CScattererConnector* getClientToServerConnector(CContextClient* client) { return clientToServerConnector_[client] ;} 317 318 private: 319 CGathererConnector* gathererConnector_ ; 320 public: 321 CGathererConnector* getGathererConnector(void) { return gathererConnector_ ;} 322 private: 323 CGathererConnector* serverFromClientConnector_ ; 324 CDistributedElement* elementFrom_ ; 325 public: 326 CGathererConnector* getServerFromClientConnector(void) { return serverFromClientConnector_ ;} 327 328 private: 329 CScattererConnector* serverToClientConnector_ = nullptr ; 330 public: 331 CScattererConnector* getServerToClientConnector(void) { return serverToClientConnector_ ;} 332 333 private: 334 map<CContextClient*,CGathererConnector*> clientFromServerConnector_ ; 335 public: 336 CGathererConnector* getClientFromServerConnector(CContextClient* client) { return clientFromServerConnector_[client] ;} 337 235 338 236 339 DECLARE_REF_FUNC(Domain,domain) -
XIOS/dev/dev_trunk_graph/src/node/duplicate_scalar_to_axis.cpp
r1314 r2019 1 1 #include "duplicate_scalar_to_axis.hpp" 2 #include "axis_algorithm_duplicate_scalar.hpp" 2 3 #include "type.hpp" 3 4 #include "axis.hpp" … … 28 29 bool CDuplicateScalarToAxis::registerTrans() 29 30 { 30 return registerTransformation(TRANS_DUPLICATE_SCALAR_TO_AXIS, CDuplicateScalarToAxis::create);31 return registerTransformation(TRANS_DUPLICATE_SCALAR_TO_AXIS, {create, getTransformation}); 31 32 } 32 33 … … 43 44 44 45 } 45 46 47 CGenericAlgorithmTransformation* CDuplicateScalarToAxis::createAlgorithm(bool isSource, 48 CGrid* gridDst, CGrid* gridSrc, 49 int elementPositionInGrid, 50 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 51 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 52 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 53 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 54 std::map<int, int>& elementPositionInGridDst2AxisPosition, 55 std::map<int, int>& elementPositionInGridDst2DomainPosition) 56 { 57 return CAxisAlgorithmDuplicateScalar::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 58 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 59 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 60 } 46 61 } -
XIOS/dev/dev_trunk_graph/src/node/duplicate_scalar_to_axis.hpp
r1314 r2019 20 20 class CAxis; 21 21 class CScalar; 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 22 24 23 25 ///-------------------------------------------------------------- … … 41 43 typedef CObjectTemplate<CDuplicateScalarToAxis> SuperClass; 42 44 typedef CDuplicateScalarToAxisAttributes SuperClassAttribute; 45 typedef CDuplicateScalarToAxis MyClass ; 46 typedef CTransformation<CAxis> SuperTransform ; 43 47 44 48 public : … … 56 60 static StdString GetDefName(void); 57 61 static ENodeType GetType(void); 62 const string& getId(void) { return this->SuperClass::getId();} 63 ETranformationType getTransformationType(void) { return TRANS_DUPLICATE_SCALAR_TO_AXIS ;} 64 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 65 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 66 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 67 CGrid* gridDst, CGrid* gridSrc, 68 int elementPositionInGrid, 69 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 70 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 71 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 72 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 73 std::map<int, int>& elementPositionInGridDst2AxisPosition, 74 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 75 private: 59 76 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/expand_domain.cpp
r1158 r2019 1 1 #include "expand_domain.hpp" 2 #include "domain_algorithm_expand.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CExpandDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_EXPAND_DOMAIN, CExpandDomain::create);30 registerTransformation(TRANS_EXPAND_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 47 48 if (this->type.isEmpty()) this->type.setValue(CExpandDomain::type_attr::edge); 48 49 } 49 50 51 CGenericAlgorithmTransformation* CExpandDomain::createAlgorithm(bool isSource, 52 CGrid* gridDst, CGrid* gridSrc, 53 int elementPositionInGrid, 54 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 55 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 56 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 57 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 58 std::map<int, int>& elementPositionInGridDst2AxisPosition, 59 std::map<int, int>& elementPositionInGridDst2DomainPosition) 60 { 61 return CDomainAlgorithmExpand::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 62 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 63 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 64 } 50 65 } -
XIOS/dev/dev_trunk_graph/src/node/expand_domain.hpp
r935 r2019 20 20 class CExpandDomain; 21 21 class CDomain; 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 22 24 23 25 ///-------------------------------------------------------------- … … 41 43 typedef CObjectTemplate<CExpandDomain> SuperClass; 42 44 typedef CExpandDomainAttributes SuperClassAttribute; 45 typedef CExpandDomain MyClass ; 46 typedef CTransformation<CDomain> SuperTransform ; 43 47 44 48 public : … … 56 60 static StdString GetDefName(void); 57 61 static ENodeType GetType(void); 62 const string& getId(void) { return this->SuperClass::getId();} 63 ETranformationType getTransformationType(void) { return TRANS_EXPAND_DOMAIN ;} 64 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 65 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 66 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 67 CGrid* gridDst, CGrid* gridSrc, 68 int elementPositionInGrid, 69 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 70 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 71 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 72 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 73 std::map<int, int>& elementPositionInGridDst2AxisPosition, 74 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 75 private: 59 76 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/extract_axis.cpp
r1558 r2019 1 1 #include "extract_axis.hpp" 2 #include "axis_algorithm_extract.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CExtractAxis::registerTrans() 27 28 { 28 return registerTransformation(TRANS_EXTRACT_AXIS, CExtractAxis::create);29 return registerTransformation(TRANS_EXTRACT_AXIS, {create, getTransformation}); 29 30 } 30 31 … … 77 78 } 78 79 80 CGenericAlgorithmTransformation* CExtractAxis::createAlgorithm(bool isSource, 81 CGrid* gridDst, CGrid* gridSrc, 82 int elementPositionInGrid, 83 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 84 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 85 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 86 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 87 std::map<int, int>& elementPositionInGridDst2AxisPosition, 88 std::map<int, int>& elementPositionInGridDst2DomainPosition) 89 { 90 return CAxisAlgorithmExtract::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 91 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 92 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 93 } 79 94 } -
XIOS/dev/dev_trunk_graph/src/node/extract_axis.hpp
r1558 r2019 20 20 class CExtractAxis; 21 21 class CAxis; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CExtractAxis> SuperClass; 42 43 typedef CExtractAxisAttributes SuperClassAttribute; 44 typedef CExtractAxis MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_EXTRACT_AXIS ;} 63 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/extract_axis_to_scalar.cpp
r960 r2019 1 1 #include "extract_axis_to_scalar.hpp" 2 #include "scalar_algorithm_extract_axis.hpp" 3 2 4 #include "type.hpp" 3 5 #include "axis.hpp" … … 28 30 bool CExtractAxisToScalar::registerTrans() 29 31 { 30 return registerTransformation(TRANS_EXTRACT_AXIS_TO_SCALAR, CExtractAxisToScalar::create);32 return registerTransformation(TRANS_EXTRACT_AXIS_TO_SCALAR, {create, getTransformation}); 31 33 } 32 34 … … 57 59 } 58 60 61 CGenericAlgorithmTransformation* CExtractAxisToScalar::createAlgorithm(bool isSource, 62 CGrid* gridDst, CGrid* gridSrc, 63 int elementPositionInGrid, 64 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 65 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 66 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 67 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 68 std::map<int, int>& elementPositionInGridDst2AxisPosition, 69 std::map<int, int>& elementPositionInGridDst2DomainPosition) 70 { 71 return CScalarAlgorithmExtractAxis::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 72 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 73 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 74 } 59 75 } -
XIOS/dev/dev_trunk_graph/src/node/extract_axis_to_scalar.hpp
r960 r2019 20 20 class CAxis; 21 21 class CScalar; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CExtractAxisToScalar> SuperClass; 42 43 typedef CExtractAxisToScalarAttributes SuperClassAttribute; 44 typedef CExtractAxisToScalar MyClass ; 45 typedef CTransformation<CScalar> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_EXTRACT_AXIS_TO_SCALAR ;} 63 static CTransformation<CScalar>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/extract_domain.cpp
r1549 r2019 1 1 #include "extract_domain.hpp" 2 #include "domain_algorithm_extract.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CExtractDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_EXTRACT_DOMAIN, CExtractDomain::create);30 registerTransformation(TRANS_EXTRACT_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 72 73 } 73 74 75 CGenericAlgorithmTransformation* CExtractDomain::createAlgorithm(bool isSource, 76 CGrid* gridDst, CGrid* gridSrc, 77 int elementPositionInGrid, 78 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 79 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 80 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 81 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 82 std::map<int, int>& elementPositionInGridDst2AxisPosition, 83 std::map<int, int>& elementPositionInGridDst2DomainPosition) 84 { 85 return CDomainAlgorithmExtract::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 86 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 87 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 88 } 74 89 } -
XIOS/dev/dev_trunk_graph/src/node/extract_domain.hpp
r1549 r2019 20 20 class CExtractDomain; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CExtractDomain> SuperClass; 42 43 typedef CExtractDomainAttributes SuperClassAttribute; 44 typedef CExtractDomain MyClass ; 45 typedef CTransformation<CDomain> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 58 private: 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_EXTRACT_DOMAIN ;} 63 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 74 private: 59 75 static bool registerTrans(); 60 76 static CTransformation<CDomain>* create(const StdString& id, xml::CXMLNode* node); 61 77 static bool _dummyRegistered; 62 78 }; // class CExtractDomain 63 79 -
XIOS/dev/dev_trunk_graph/src/node/extract_domain_to_axis.cpp
r980 r2019 1 1 #include "extract_domain_to_axis.hpp" 2 #include "axis_algorithm_extract_domain.hpp" 2 3 #include "type.hpp" 3 4 #include "axis.hpp" … … 28 29 bool CExtractDomainToAxis::registerTrans() 29 30 { 30 return registerTransformation(TRANS_EXTRACT_DOMAIN_TO_AXIS, CExtractDomainToAxis::create);31 return registerTransformation(TRANS_EXTRACT_DOMAIN_TO_AXIS, {create, getTransformation}); 31 32 } 32 33 … … 98 99 } 99 100 101 CGenericAlgorithmTransformation* CExtractDomainToAxis::createAlgorithm(bool isSource, 102 CGrid* gridDst, CGrid* gridSrc, 103 int elementPositionInGrid, 104 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 105 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 106 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 107 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 108 std::map<int, int>& elementPositionInGridDst2AxisPosition, 109 std::map<int, int>& elementPositionInGridDst2DomainPosition) 110 { 111 return CAxisAlgorithmExtractDomain::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 112 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 113 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 114 } 100 115 } -
XIOS/dev/dev_trunk_graph/src/node/extract_domain_to_axis.hpp
r895 r2019 20 20 class CAxis; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CExtractDomainToAxis> SuperClass; 42 43 typedef CExtractDomainToAxisAttributes SuperClassAttribute; 43 44 typedef CExtractDomainToAxis MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 46 44 47 public : 45 48 /// Constructeurs /// … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_EXTRACT_DOMAIN_TO_AXIS ;} 63 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/field.cpp
r1688 r2019 15 15 #include <set> 16 16 #include "garbage_collector.hpp" 17 #include "source_filter.hpp"18 #include "store_filter.hpp"19 #include "file_writer_filter.hpp"20 17 #include "pass_through_filter.hpp" 21 18 #include "filter_expr_node.hpp" 22 19 #include "lex_parser.hpp" 23 20 #include "temporal_filter.hpp" 24 #include "spatial_transform_filter.hpp" 25 #include "file_server_writer_filter.hpp" 26 #include "workflow_graph.hpp" 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 field_graph_start = -2; 50 field_graph_end = -2; 51 } 52 53 CField::CField(const StdString& id) 54 : CObjectTemplate<CField>(id), CFieldAttributes() 55 , grid(), file() 56 , written(false) 57 , nstep(0), nstepMax(0) 58 , hasOutputFile(false) 59 , domAxisScalarIds_(vector<StdString>(3,"")) 60 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 61 , isGridChecked(false) 62 , useCompressedOutput(false) 63 , hasTimeInstant(false) 64 , hasTimeCentered(false) 65 , wasDataRequestedFromServer(false) 66 , wasDataAlreadyReceivedFromServer(false) 67 , mustAutoTrigger(false) 68 , isEOF(false), nstepMaxRead(false) 69 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); 70 field_graph_start = -2; 71 field_graph_end = -2; 72 } 73 74 75 CField::~CField(void) 76 {} 21 #include "server_from_client_source_filter.hpp" 22 #include "file_reader_source_filter.hpp" 23 #include "tracer.hpp" 24 #include "graph_package.hpp" 25 26 namespace xios 27 { 28 29 /// ////////////////////// Définitions ////////////////////// /// 30 31 CField::CField(void) 32 : CObjectTemplate<CField>(), CFieldAttributes() 33 , written(false) 34 , hasOutputFile(false) 35 , domAxisScalarIds_(vector<StdString>(3,"")) 36 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 37 , isGridChecked(false) 38 , useCompressedOutput(false) 39 , hasTimeInstant(false) 40 , hasTimeCentered(false) 41 , mustAutoTrigger(false) 42 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 43 44 CField::CField(const StdString& id) 45 : CObjectTemplate<CField>(id), CFieldAttributes() 46 , written(false) 47 , hasOutputFile(false) 48 , domAxisScalarIds_(vector<StdString>(3,"")) 49 , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 50 , isGridChecked(false) 51 , useCompressedOutput(false) 52 , hasTimeInstant(false) 53 , hasTimeCentered(false) 54 , mustAutoTrigger(false) 55 { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 56 57 CField::~CField(void) 58 {} 77 59 78 60 //---------------------------------------------------------------- 79 61 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 62 void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup) 63 TRY 64 { 65 this->vVariableGroup = newVVariableGroup; 66 } 67 CATCH 68 69 CVariableGroup* CField::getVirtualVariableGroup(void) const 70 TRY 71 { 72 return this->vVariableGroup; 73 } 74 CATCH 75 76 std::vector<CVariable*> CField::getAllVariables(void) const 77 TRY 78 { 79 return this->vVariableGroup->getAllChildren(); 80 } 81 CATCH 82 83 void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent) 84 TRY 85 { 86 SuperClassAttribute::setAttributes(parent, apply); 87 this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL); 88 } 89 CATCH_DUMP_ATTR 108 90 109 91 //---------------------------------------------------------------- … … 141 123 return true; 142 124 break; 143 125 126 case EVENT_ID_GRID_COMPLETED : 127 recvGridCompleted(event); 128 return true; 129 break; 144 130 default : 145 131 ERROR("bool CField::dispatchEvent(CEventServer& event)", << "Unknown Event"); … … 150 136 CATCH 151 137 152 void CField::sendUpdateData(const CArray<double,1>& data)153 TRY154 {155 CTimer::get("Field : send data").resume();156 157 CContext* context = CContext::getCurrent();158 CContextClient* client = (!context->hasServer) ? context->client : this->file->getContextClient();159 int receiverSize = client->serverSize;160 161 CEventClient event(getType(), EVENT_ID_UPDATE_DATA);162 163 map<int, CArray<int,1> >::iterator it;164 list<CMessage> list_msg;165 list<CArray<double,1> > list_data;166 167 if (!grid->doGridHaveDataDistributed(client))168 {169 if (client->isServerLeader())170 {171 for (it = grid->storeIndex_toSrv[client].begin(); it != grid->storeIndex_toSrv[client].end(); it++)172 {173 int rank = it->first;174 CArray<int,1>& index = it->second;175 176 list_msg.push_back(CMessage());177 list_data.push_back(CArray<double,1>(index.numElements()));178 179 CArray<double,1>& data_tmp = list_data.back();180 for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));181 182 list_msg.back() << getId() << data_tmp;183 event.push(rank, 1, list_msg.back());184 }185 client->sendEvent(event);186 }187 else client->sendEvent(event);188 }189 else190 {191 for (it = grid->storeIndex_toSrv[client].begin(); it != grid->storeIndex_toSrv[client].end(); it++)192 {193 int rank = it->first;194 CArray<int,1>& index = it->second;195 196 list_msg.push_back(CMessage());197 list_data.push_back(CArray<double,1>(index.numElements()));198 199 CArray<double,1>& data_tmp = list_data.back();200 for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));201 202 list_msg.back() << getId() << data_tmp;203 event.push(rank, grid->nbSenders[receiverSize][rank], list_msg.back());204 }205 client->sendEvent(event);206 }207 208 CTimer::get("Field : send data").suspend();209 }210 CATCH_DUMP_ATTR211 138 212 139 void CField::recvUpdateData(CEventServer& event) 213 140 TRY 214 141 { 215 std::map<int,CBufferIn*> rankBuffers;216 217 list<CEventServer::SSubEvent>::iterator it;218 142 string fieldId; 219 CTimer::get("Field : recv data").resume(); 220 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 221 { 222 int rank = it->rank; 223 CBufferIn* buffer = it->buffer; 224 *buffer >> fieldId; 225 rankBuffers[rank] = buffer; 226 } 227 get(fieldId)->recvUpdateData(rankBuffers); 228 CTimer::get("Field : recv data").suspend(); 229 } 230 CATCH 231 232 void CField::recvUpdateData(std::map<int,CBufferIn*>& rankBuffers) 233 TRY 234 { 235 CContext* context = CContext::getCurrent(); 236 237 size_t sizeData = 0; 238 if (0 == recvDataSrv.numElements()) 239 { 240 CArray<int,1>& storeClient = grid->storeIndex_client; 241 242 // Gather all data from different clients 243 recvDataSrv.resize(storeClient.numElements()); 244 recvFoperationSrv = std::shared_ptr<func::CFunctor>(new func::CInstant(recvDataSrv)); 245 } 246 247 CArray<double,1> recv_data_tmp(recvDataSrv.numElements()); 248 const CDate& currDate = context->getCalendar()->getCurrentDate(); 249 CDuration offsetAllButMonth (freq_offset.getValue().year, 0 , freq_offset.getValue().day, 250 freq_offset.getValue().hour, freq_offset.getValue().minute, 251 freq_offset.getValue().second, freq_offset.getValue().timestep); 252 const CDate opeDate = (last_operation_srv - offsetAllButMonth + context->getCalendar()->getTimeStep()) 253 + freq_op + freq_operation_srv - freq_op - context->getCalendar()->getTimeStep() + offsetAllButMonth; 254 255 if (opeDate <= currDate) 256 { 257 for (map<int, CArray<size_t, 1> >::iterator it = grid->outLocalIndexStoreOnClient.begin(); it != grid->outLocalIndexStoreOnClient.end(); ++it) 258 { 259 CArray<double,1> tmp; 260 CArray<size_t,1>& indexTmp = it->second; 261 *(rankBuffers[it->first]) >> tmp; 262 for (int idx = 0; idx < indexTmp.numElements(); ++idx) 263 { 264 recv_data_tmp(indexTmp(idx)) = tmp(idx); 265 } 266 } 267 } 268 269 this->setData(recv_data_tmp); 270 // delete incomming flux for server only 271 recvFoperationSrv.reset() ; 272 recvDataSrv.reset() ; 273 } 274 CATCH_DUMP_ATTR 275 276 void CField::writeUpdateData(const CArray<double,1>& data) 277 TRY 278 { 279 CContext* context = CContext::getCurrent(); 280 281 const CDate& currDate = context->getCalendar()->getCurrentDate(); 282 CDuration offsetAllButMonth (freq_offset.getValue().year, 0 , freq_offset.getValue().day, 283 freq_offset.getValue().hour, freq_offset.getValue().minute, 284 freq_offset.getValue().second, freq_offset.getValue().timestep); 285 const CDate opeDate = (last_operation_srv - offsetAllButMonth + context->getCalendar()->getTimeStep()) 286 + freq_op + freq_operation_srv - freq_op - context->getCalendar()->getTimeStep() + offsetAllButMonth; 287 const CDate writeDate = last_Write_srv + freq_write_srv; 288 289 if (opeDate <= currDate) 290 { 291 (*recvFoperationSrv)(data); 292 last_operation_srv = currDate; 293 } 294 295 if (writeDate < (currDate + freq_operation_srv)) 296 { 297 recvFoperationSrv->final(); 298 last_Write_srv = writeDate; 299 grid->computeWrittenIndex(); 300 writeField(); 301 lastlast_Write_srv = last_Write_srv; 302 } 303 } 304 CATCH_DUMP_ATTR 305 306 void CField::writeField(void) 307 TRY 308 { 309 if (!getRelFile()->isEmptyZone()) 310 { 311 if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 312 { 313 getRelFile()->checkWriteFile(); 314 this->incrementNStep(); 315 getRelFile()->getDataOutput()->writeFieldData(CField::get(this)); 316 } 317 } 318 } 319 CATCH_DUMP_ATTR 143 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> fieldId ; 144 get(fieldId)->receiveUpdateData(event); 145 } 146 CATCH 147 148 void CField::receiveUpdateData(CEventServer& event) 149 TRY 150 { 151 if (hasCouplerIn()) clientFromClientSourceFilter_->streamData(event) ; 152 else serverFromClientSourceFilter_->streamData(event) ; 153 } 154 CATCH 320 155 321 156 /* … … 329 164 TRY 330 165 { 331 CContext* context = CContext::getCurrent(); 332 // CContextClient* client = context->client; 333 334 // This code is for future: If we want to read file with level-2 servers 335 CContextClient* client = (!context->hasServer) ? context->client : this->file->getContextClient(); 336 337 lastDataRequestedFromServer = tsDataRequested; 338 339 // No need to send the request if we are sure that we are already at EOF 340 if (!isEOF || context->getCalendar()->getCurrentDate() <= dateEOF) 341 { 342 CEventClient event(getType(), EVENT_ID_READ_DATA); 343 if (client->isServerLeader()) 344 { 345 CMessage msg; 346 msg << getId(); 347 const std::list<int>& ranks = client->getRanksServerLeader(); 348 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 349 event.push(*itRank, 1, msg); 350 client->sendEvent(event); 351 } 352 else client->sendEvent(event); 353 } 354 else 355 serverSourceFilter->signalEndOfStream(tsDataRequested); 356 357 wasDataRequestedFromServer = true; 358 359 return !isEOF; 360 } 361 CATCH_DUMP_ATTR 362 166 return clientFromServerSourceFilter_->sendReadDataRequest(tsDataRequested) ; 167 } 168 CATCH_DUMP_ATTR 169 170 363 171 /*! 364 172 Send request new data read from file if need be, that is the current data is out-of-date. … … 368 176 TRY 369 177 { 370 const CDate& currentDate = CContext::getCurrent()->getCalendar()->getCurrentDate(); 371 372 bool dataRequested = false; 373 374 while (currentDate >= lastDataRequestedFromServer) 375 { 376 info(20) << "currentDate : " << currentDate << endl ; 377 info(20) << "lastDataRequestedFromServer : " << lastDataRequestedFromServer << endl ; 378 info(20) << "file->output_freq.getValue() : " << file->output_freq.getValue() << endl ; 379 info(20) << "lastDataRequestedFromServer + file->output_freq.getValue() : " << lastDataRequestedFromServer + file->output_freq << endl ; 380 381 dataRequested |= sendReadDataRequest(lastDataRequestedFromServer + file->output_freq); 382 } 383 384 return dataRequested; 385 } 386 CATCH_DUMP_ATTR 178 return clientFromServerSourceFilter_->sendReadDataRequestIfNeeded() ; 179 } 180 CATCH_DUMP_ATTR 181 387 182 388 183 void CField::recvReadDataRequest(CEventServer& event) … … 395 190 } 396 191 CATCH 397 192 398 193 /*! 399 194 Receive data request sent from client and process it … … 405 200 TRY 406 201 { 407 CContext* context = CContext::getCurrent(); 408 CContextClient* client = context->client; 409 410 CEventClient event(getType(), EVENT_ID_READ_DATA_READY); 411 std::list<CMessage> msgs; 412 413 EReadField hasData = readField(); 414 415 map<int, CArray<double,1> >::iterator it; 416 if (!grid->doGridHaveDataDistributed(client)) 417 { 418 if (client->isServerLeader()) 419 { 420 if (0 != recvDataSrv.numElements()) 421 { 422 const std::list<int>& ranks = client->getRanksServerLeader(); 423 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 424 { 425 msgs.push_back(CMessage()); 426 CMessage& msg = msgs.back(); 427 msg << getId(); 428 switch (hasData) 429 { 430 case RF_DATA: 431 msg << getNStep() - 1 << recvDataSrv; 432 break; 433 case RF_NODATA: 434 msg << int(-2) << recvDataSrv; 435 break; 436 case RF_EOF: 437 default: 438 msg << int(-1); 439 break; 440 } 441 442 event.push(*itRank, 1, msg); 443 } 444 } 445 client->sendEvent(event); 446 } 447 else 448 { 449 client->sendEvent(event); 450 } 451 } 452 else 453 { 454 for (map<int, CArray<size_t, 1> >::iterator it = grid->outLocalIndexStoreOnClient.begin(); 455 it != grid->outLocalIndexStoreOnClient.end(); ++it) 456 { 457 CArray<size_t,1>& indexTmp = it->second; 458 CArray<double,1> tmp(indexTmp.numElements()); 459 for (int idx = 0; idx < indexTmp.numElements(); ++idx) 460 { 461 tmp(idx) = recvDataSrv(indexTmp(idx)); 462 } 463 464 msgs.push_back(CMessage()); 465 CMessage& msg = msgs.back(); 466 msg << getId(); 467 switch (hasData) 468 { 469 case RF_DATA: 470 msg << getNStep() - 1 << tmp; 471 break; 472 case RF_NODATA: 473 msg << int(-2) << tmp; 474 break; 475 case RF_EOF: 476 default: 477 msg << int(-1); 478 break; 479 } 480 481 event.push(it->first, grid->nbReadSenders[client][it->first], msg); 482 } 483 client->sendEvent(event); 484 } 485 } 486 CATCH_DUMP_ATTR 487 488 /*! 489 Read field from a file. 490 A field is read with the distribution of data on the server side 491 \return State of field can be read from a file 492 */ 493 CField::EReadField CField::readField(void) 494 TRY 495 { 496 CContext* context = CContext::getCurrent(); 497 grid->computeWrittenIndex(); 498 getRelFile()->initRead(); 499 EReadField readState = RF_DATA; 500 501 if (!getRelFile()->isEmptyZone()) 502 { 503 if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 504 { 505 if (0 == recvDataSrv.numElements()) 506 { 507 CArray<int,1>& storeClient = grid->storeIndex_client; 508 recvDataSrv.resize(storeClient.numElements()); 509 } 510 511 getRelFile()->checkReadFile(); 512 513 if (!nstepMax) 514 { 515 nstepMax = getRelFile()->getDataInput()->getFieldNbRecords(CField::get(this)); 516 } 517 518 this->incrementNStep(); 519 520 if (getNStep() > nstepMax && (getRelFile()->cyclic.isEmpty() || !getRelFile()->cyclic) ) 521 readState = RF_EOF; 522 523 if (RF_EOF != readState) 524 getRelFile()->getDataInput()->readFieldData(CField::get(this)); 525 } 526 } 527 else 528 { 529 this->incrementNStep(); 530 if (getNStep() > nstepMax && (getRelFile()->cyclic.isEmpty() || !getRelFile()->cyclic) ) 531 readState = RF_EOF; 532 else 533 readState = RF_NODATA; 534 535 if (!nstepMaxRead) // This can be a bug if we try to read field from zero time record 536 readState = RF_NODATA; 537 } 538 539 if (!nstepMaxRead) 540 { 541 MPI_Allreduce(MPI_IN_PLACE, &nstepMax, 1, MPI_INT, MPI_MAX, context->server->intraComm); 542 nstepMaxRead = true; 543 } 544 545 return readState; 546 } 547 CATCH_DUMP_ATTR 548 202 fileReaderSourceFilter_->streamData() ; 203 } 204 CATCH_DUMP_ATTR 205 206 549 207 /* 550 208 Receive read data from server. … … 557 215 { 558 216 string fieldId; 559 vector<int> ranks; 560 vector<CBufferIn*> buffers; 561 562 list<CEventServer::SSubEvent>::iterator it; 563 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 564 { 565 ranks.push_back(it->rank); 566 CBufferIn* buffer = it->buffer; 567 *buffer >> fieldId; 568 buffers.push_back(buffer); 569 } 570 get(fieldId)->recvReadDataReady(ranks, buffers); 571 } 572 CATCH 573 574 /*! 575 Receive read data from server 576 \param [in] ranks Ranks of sending processes 577 \param [in] buffers buffers containing read data 578 */ 579 void CField::recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers) 580 TRY 581 { 582 CContext* context = CContext::getCurrent(); 583 std::map<int, CArray<double,1> > data; 584 const bool wasEOF = isEOF; 585 586 for (int i = 0; i < ranks.size(); i++) 587 { 588 int rank = ranks[i]; 589 int record; 590 *buffers[i] >> record; 591 isEOF = (record == int(-1)); 592 593 if (!isEOF) 594 *buffers[i] >> data[rank]; 595 else 596 break; 597 } 598 599 if (wasDataAlreadyReceivedFromServer) 600 lastDataReceivedFromServer = lastDataReceivedFromServer + file->output_freq; 601 else 602 { 603 lastDataReceivedFromServer = context->getCalendar()->getInitDate(); 604 wasDataAlreadyReceivedFromServer = true; 605 } 606 607 if (isEOF) 608 { 609 if (!wasEOF) 610 dateEOF = lastDataReceivedFromServer; 611 612 serverSourceFilter->signalEndOfStream(lastDataReceivedFromServer); 613 } 614 else 615 serverSourceFilter->streamDataFromServer(lastDataReceivedFromServer, data); 616 } 617 CATCH_DUMP_ATTR 618 619 void CField::checkForLateDataFromServer(void) 217 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> fieldId ; 218 get(fieldId)->receiveReadDataReady(event); 219 } 220 CATCH 221 222 void CField::receiveReadDataReady(CEventServer& event) 223 TRY 224 { 225 clientFromServerSourceFilter_->streamData(event) ; 226 } 227 CATCH_DUMP_ATTR 228 229 230 void CField::checkForLateDataFromCoupler(void) 620 231 TRY 621 232 { … … 623 234 const CDate& currentDate = context->getCalendar()->getCurrentDate(); 624 235 625 // Check if data previously requested has been received as expected 626 if (wasDataRequestedFromServer && !isEOF) 627 { 628 CTimer timer("CField::checkForLateDataFromServer"); 629 630 bool isDataLate; 631 do 632 { 633 const CDate nextDataDue = wasDataAlreadyReceivedFromServer ? (lastDataReceivedFromServer + file->output_freq) : context->getCalendar()->getInitDate(); 634 isDataLate = (nextDataDue <= currentDate); 635 636 if (isDataLate) 236 CTimer timer("CField::checkForLateDataFromCoupler"); 237 timer.resume(); 238 traceOff() ; 239 timer.suspend(); 240 241 bool isDataLate; 242 do 243 { 244 isDataLate=clientFromClientSourceFilter_->isDataLate() ; 245 if (isDataLate) 246 { 247 timer.resume(); 248 context->globalEventLoop(); 249 timer.suspend(); 250 } 251 } while (isDataLate && timer.getCumulatedTime() < CXios::recvFieldTimeout); 252 253 timer.resume(); 254 traceOn() ; 255 timer.suspend() ; 256 257 if (isDataLate) ERROR("void CField::checkForLateDataFromCoupler(void)", 258 << "Late data at timestep = " << currentDate); 259 } 260 CATCH_DUMP_ATTR 261 262 void CField::checkForLateDataFromServer(void) 263 TRY 264 { 265 clientFromServerSourceFilter_->checkForLateData() ; 266 } 267 CATCH_DUMP_ATTR 268 269 270 void CField::triggerLateField(void) 271 TRY 272 { 273 if (hasFileIn()) 274 { 275 checkForLateDataFromServer() ; 276 clientFromServerSourceFilter_->trigger(CContext::getCurrent()->getCalendar()->getCurrentDate()) ; 277 } 278 else if (hasCouplerIn()) 279 { 280 checkForLateDataFromCoupler() ; 281 clientFromClientSourceFilter_->trigger(CContext::getCurrent()->getCalendar()->getCurrentDate()) ; 282 } 283 } 284 CATCH_DUMP_ATTR 285 286 287 void CField::checkIfMustAutoTrigger(void) 288 TRY 289 { 290 mustAutoTrigger = clientFromServerSourceFilter_ ? clientFromServerSourceFilter_->mustAutoTrigger() : false; 291 } 292 CATCH_DUMP_ATTR 293 294 void CField::autoTriggerIfNeeded(void) 295 TRY 296 { 297 if (mustAutoTrigger) 298 clientFromServerSourceFilter_->trigger(CContext::getCurrent()->getCalendar()->getCurrentDate()); 299 } 300 CATCH_DUMP_ATTR 301 302 303 //---------------------------------------------------------------- 304 305 StdString CField::GetName(void) { return StdString("field"); } 306 StdString CField::GetDefName(void) { return CField::GetName(); } 307 ENodeType CField::GetType(void) { return eField; } 308 309 //---------------------------------------------------------------- 310 311 CGrid* CField::getRelGrid(void) const 312 TRY 313 { 314 return this->grid_; 315 } 316 CATCH 317 318 //---------------------------------------------------------------- 319 320 CFile* CField::getRelFile(void) const 321 TRY 322 { 323 if (hasFileIn()) return this->fileIn_; 324 else if (hasFileOut()) return this->fileOut_ ; 325 else return nullptr ; 326 } 327 CATCH 328 329 func::CFunctor::ETimeType CField::getOperationTimeType() const 330 TRY 331 { 332 return operationTimeType; 333 } 334 CATCH 335 336 337 //---------------------------------------------------------------- 338 339 bool CField::isActive(bool atCurrentTimestep /*= false*/) const 340 TRY 341 { 342 if (modelToClientSourceFilter_) 343 return atCurrentTimestep ? modelToClientSourceFilter_->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 344 else if (clientToModelStoreFilter_) return true; 345 else if (instantDataFilter) 346 ERROR("bool CField::isActive(bool atCurrentTimestep)", 347 << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 348 349 return false; 350 } 351 CATCH 352 353 //---------------------------------------------------------------- 354 355 bool CField::wasWritten() const 356 TRY 357 { 358 return written; 359 } 360 CATCH 361 362 void CField::setWritten() 363 TRY 364 { 365 written = true; 366 } 367 CATCH_DUMP_ATTR 368 369 //---------------------------------------------------------------- 370 371 bool CField::getUseCompressedOutput() const 372 TRY 373 { 374 return useCompressedOutput; 375 } 376 CATCH 377 378 void CField::setUseCompressedOutput() 379 TRY 380 { 381 useCompressedOutput = true; 382 } 383 CATCH_DUMP_ATTR 384 385 //---------------------------------------------------------------- 386 387 void CField::updateRef(CGrid* grid) 388 TRY 389 { 390 if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 391 else 392 { 393 std::vector<CAxis*> axisTmp = grid->getAxis(); 394 std::vector<CDomain*> domainTmp = grid->getDomains(); 395 if ((1<axisTmp.size()) || (1<domainTmp.size())) 396 ERROR("void CField::updateRef(CGrid* grid)", 397 << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 398 399 if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 400 ERROR("void CField::updateRef(CGrid* grid)", 401 << "Incoherent between available domain and domain_ref of field " << this->getId()); 402 if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 403 ERROR("void CField::updateRef(CGrid* grid)", 404 << "Incoherent between available axis and axis_ref of field " << this->getId()); 405 406 if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 407 if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 408 } 409 } 410 CATCH_DUMP_ATTR 411 412 413 void CField::checkGridOfEnabledFields() 414 TRY 415 { 416 if (!isGridChecked) 417 { 418 isGridChecked = true; 419 solveCheckMaskIndex(false); 420 } 421 } 422 CATCH_DUMP_ATTR 423 424 void CField::sendGridComponentOfEnabledFields() 425 TRY 426 { 427 solveGridDomainAxisRef(true); 428 // solveCheckMaskIndex(true); 429 } 430 CATCH_DUMP_ATTR 431 432 void CField::sendGridOfEnabledFields() 433 TRY 434 { 435 // solveGridDomainAxisRef(true); 436 solveCheckMaskIndex(true); 437 } 438 CATCH_DUMP_ATTR 439 440 /*! 441 * Compute the required buffer size to send the fields data. 442 * \param [in/out] bufferSize Modifying the bufferSize for the client context 443 * \param [in/out] maxEventSize Modifying the maximum event size for the client context 444 * \param [in] bufferForWriting True if buffers are used for sending data for writing 445 */ 446 void CField::setContextClientDataBufferSize(map<CContextClient*,map<int,size_t>>& bufferSize, 447 map<CContextClient*,map<int,size_t>>& maxEventSize, 448 bool bufferForWriting) 449 { 450 auto& contextBufferSize = bufferSize[client] ; 451 auto& contextMaxEventSize = maxEventSize[client] ; 452 const std::map<int, size_t> mapSize = grid_->getDataBufferSize(client, getId(), bufferForWriting); 453 for(auto& it : mapSize ) 454 { 455 // If contextBufferSize[it.first] does not exist, it will be zero-initialized 456 // so we can use it safely without checking for its existance 457 if (CXios::isOptPerformance) contextBufferSize[it.first] += it.second; 458 else if (contextBufferSize[it.first] < it.second) contextBufferSize[it.first] = it.second; 459 460 if (contextMaxEventSize[it.first] < it.second) contextMaxEventSize[it.first] = it.second; 461 } 462 463 } 464 465 void CField::setContextClientAttributesBufferSize(map<CContextClient*,map<int,size_t>>& bufferSize, 466 map<CContextClient*,map<int,size_t>>& maxEventSize, 467 bool bufferForWriting) 468 { 469 auto& contextBufferSize = bufferSize[client] ; 470 auto& contextMaxEventSize = maxEventSize[client] ; 471 const std::map<int, size_t> mapSize = grid_->getAttributesBufferSize(client, bufferForWriting); 472 for(auto& it : mapSize ) 473 { 474 // If contextBufferSize[it.first] does not exist, it will be zero-initialized 475 // so we can use it safely without checking for its existance 476 if (contextBufferSize[it.first] < it.second) contextBufferSize[it.first] = it.second; 477 if (contextMaxEventSize[it.first] < it.second) contextMaxEventSize[it.first] = it.second; 478 } 479 480 } 481 482 483 // ym obsolete to be removed 484 std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 485 TRY 486 { 487 return grid_->getAttributesBufferSize(client, bufferForWriting); 488 } 489 CATCH_DUMP_ATTR 490 491 // ym obsolete to be removed 492 std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 493 TRY 494 { 495 return grid_->getDataBufferSize(client, getId(), bufferForWriting); 496 } 497 CATCH_DUMP_ATTR 498 499 500 501 size_t CField::getGlobalWrittenSize() 502 TRY 503 { 504 return grid_->getGlobalWrittenSize(); 505 } 506 CATCH_DUMP_ATTR 507 508 //---------------------------------------------------------------- 509 510 void CField::solveServerOperation(void) 511 TRY 512 { 513 CContext* context = CContext::getCurrent(); 514 515 if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 516 517 if (freq_offset.isEmpty()) freq_offset.setValue(NoneDu); 518 519 if (operation.isEmpty()) 520 ERROR("void CField::solveServerOperation(void)", 521 << "An operation must be defined for field \"" << getId() << "\"."); 522 523 std::shared_ptr<func::CFunctor> functor; 524 CArray<double, 1> dummyData; 525 526 #define DECLARE_FUNCTOR(MType, mtype) \ 527 if (operation.getValue().compare(#mtype) == 0) \ 528 { \ 529 functor.reset(new func::C##MType(dummyData)); \ 530 } 531 532 #include "functor_type.conf" 533 534 if (!functor) 535 ERROR("void CField::solveServerOperation(void)", 536 << "\"" << operation << "\" is not a valid operation."); 537 538 operationTimeType = functor->timeType(); 539 } 540 CATCH_DUMP_ATTR 541 542 //---------------------------------------------------------------- 543 544 bool CField::buildWorkflowGraph(CGarbageCollector& gc) 545 { 546 if (buildWorkflowGraphDone_) return true ; 547 548 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 549 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 550 bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 551 std::cout<<"field id="<<this->getId()<<" build_workflow_graph="<<buildGraph_<<std::endl; 552 553 if (!inputFilter) 554 { 555 inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc)); 556 if(buildGraph_) 557 { 558 std::cout<<"============== field "<<this->getId()<<" calls a pass through filter ============== "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 559 inputFilter->graphEnabled = true; 560 inputFilter->graphPackage = new CGraphPackage; 561 inputFilter->graphPackage->inFields.push_back(this); 562 } 563 } 564 565 if (hasDirectFieldReference()) 566 { 567 568 CField* fieldRef = getDirectFieldReference(); 569 if(buildGraph_) 570 { 571 (*fieldRef).build_workflow_graph.set(build_workflow_graph); 572 } 573 else 574 { 575 this->build_workflow_graph.set(fieldRef->build_workflow_graph); 576 buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 577 } 578 579 580 if(buildGraph_) this->build_workflow_graph.set(build_workflow_graph); 581 bool ret=fieldRef->buildWorkflowGraph(gc); 582 if (!ret) return false ; // workflow graph cannot be built at this stage 583 } 584 585 // now construct grid and check if element are enabled 586 solveGridReference() ; // grid_ is now defined 587 if (!isGridCompleted()) return false; 588 589 // Check if we have an expression to parse 590 std::shared_ptr<COutputPin> filterExpr ; 591 if (hasExpression()) 592 { 593 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 594 filterExpr = expr->reduce(gc, *this); 595 if (!filterExpr) return false ; // workflow graph cannot be built at this stage 596 } 597 598 // prepare transformation. Need to know before if workflow of auxillary field can be built 599 if (hasDirectFieldReference()) 600 { 601 auto gridPath=getGridPath() ; 602 gridPath.push_back(grid_) ; 603 604 CGrid* gridSrc=getDirectFieldReference()->getGrid() ; 605 std::shared_ptr<COutputPin> lastFilter ; 606 if (filterExpr) lastFilter=filterExpr ; 607 else lastFilter = inputFilter ; 608 CGrid* newGrid ; 609 610 for(auto grid : gridPath) 611 { 612 grid->solveElementsRefInheritance() ; 613 614 // new 615 616 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = grid->buildTransformationGraph(gc, false, gridSrc, detectMissingValues, defaultValue, newGrid, buildGraph_) ; 617 lastFilter->connectOutput(filters.first, 0); 618 if(buildGraph_) 637 619 { 638 timer.resume(); 639 640 context->checkBuffersAndListen(); 641 642 timer.suspend(); 620 std::cout<<"============== field "<<this->getId()<<" calls a transformation filter 1 ============== "<<lastFilter<<" _ "<<filters.first<<" ***** "<<CXios::isClient<<std::endl; 621 filters.first->graphEnabled=true; 622 filters.first->graphPackage = new CGraphPackage; 623 filters.first->graphPackage->inFields.push_back(this); 643 624 } 644 } 645 while (isDataLate && timer.getCumulatedTime() < CXios::recvFieldTimeout); 646 647 if (isDataLate) 648 ERROR("void CField::checkForLateDataFromServer(void)", 649 << "Late data at timestep = " << currentDate); 650 } 651 } 652 CATCH_DUMP_ATTR 653 654 void CField::checkIfMustAutoTrigger(void) 655 TRY 656 { 657 mustAutoTrigger = serverSourceFilter ? serverSourceFilter->mustAutoTrigger() : false; 658 } 659 CATCH_DUMP_ATTR 660 661 void CField::autoTriggerIfNeeded(void) 662 TRY 663 { 664 if (mustAutoTrigger) 665 serverSourceFilter->trigger(CContext::getCurrent()->getCalendar()->getCurrentDate()); 666 } 667 CATCH_DUMP_ATTR 668 669 //---------------------------------------------------------------- 670 671 void CField::setRelFile(CFile* _file) 672 TRY 673 { 674 this->file = _file; 675 hasOutputFile = true; 676 } 677 CATCH_DUMP_ATTR 678 679 //---------------------------------------------------------------- 680 681 StdString CField::GetName(void) { return StdString("field"); } 682 StdString CField::GetDefName(void) { return CField::GetName(); } 683 ENodeType CField::GetType(void) { return eField; } 684 685 //---------------------------------------------------------------- 686 687 CGrid* CField::getRelGrid(void) const 688 TRY 689 { 690 return this->grid; 691 } 692 CATCH 693 694 //---------------------------------------------------------------- 695 696 CFile* CField::getRelFile(void) const 697 TRY 698 { 699 return this->file; 700 } 701 CATCH 702 703 int CField::getNStep(void) const 704 TRY 705 { 706 return this->nstep; 707 } 708 CATCH 709 710 func::CFunctor::ETimeType CField::getOperationTimeType() const 711 TRY 712 { 713 return operationTimeType; 714 } 715 CATCH 716 717 //---------------------------------------------------------------- 718 719 void CField::incrementNStep(void) 720 TRY 721 { 722 this->nstep++; 723 } 724 CATCH_DUMP_ATTR 725 726 void CField::resetNStep(int nstep /*= 0*/) 727 TRY 728 { 729 this->nstep = nstep; 730 } 731 CATCH_DUMP_ATTR 732 733 void CField::resetNStepMax(void) 734 TRY 735 { 736 this->nstepMax = 0; 737 nstepMaxRead = false; 738 } 739 CATCH_DUMP_ATTR 740 741 //---------------------------------------------------------------- 742 743 bool CField::isActive(bool atCurrentTimestep /*= false*/) const 744 TRY 745 { 746 if (clientSourceFilter) 747 return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 748 else if (storeFilter) 749 return true; 750 else if (instantDataFilter) 751 ERROR("bool CField::isActive(bool atCurrentTimestep)", 752 << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 753 754 return false; 755 } 756 CATCH 757 758 //---------------------------------------------------------------- 759 760 bool CField::wasWritten() const 761 TRY 762 { 763 return written; 764 } 765 CATCH 766 767 void CField::setWritten() 768 TRY 769 { 770 written = true; 771 } 772 CATCH_DUMP_ATTR 773 774 //---------------------------------------------------------------- 775 776 bool CField::getUseCompressedOutput() const 777 TRY 778 { 779 return useCompressedOutput; 780 } 781 CATCH 782 783 void CField::setUseCompressedOutput() 784 TRY 785 { 786 useCompressedOutput = true; 787 } 788 CATCH_DUMP_ATTR 789 790 //---------------------------------------------------------------- 791 792 std::shared_ptr<COutputPin> CField::getInstantDataFilter() 793 TRY 794 { 795 return instantDataFilter; 796 } 797 CATCH_DUMP_ATTR 798 799 //---------------------------------------------------------------- 800 801 /*! 802 Build up graph of grids which plays role of destination and source in grid transformation 803 This function should be called before \func solveGridReference() 625 lastFilter = filters.second; 626 gridSrc = newGrid ; 627 628 // end new 629 } 630 631 grid_=newGrid ; 632 grid_ref=grid_->getId() ; // for server 633 instantDataFilter = lastFilter ; 634 635 // connect the input Filter to the reference 636 getDirectFieldReference()->getInstantDataFilter()->connectOutput(inputFilter,0); 637 if(buildGraph_) 638 { 639 std::cout<<"============== field "<<this->getId()<<" calls a transformation filter 2 ============== "<<getDirectFieldReference()->getInstantDataFilter()<<" _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 640 inputFilter->graphEnabled=true; 641 inputFilter->graphPackage = new CGraphPackage; 642 inputFilter->graphPackage->inFields.push_back(this); 643 } 644 } 645 else 646 { 647 if (hasFileIn()) // input file, attemp to read the grid from file 648 { 649 // must be checked 650 fileIn_->initRead() ; 651 fileIn_->checkReadFile(); 652 grid_->solveElementsRefInheritance() ; 653 if (fileIn_->isClientSide()) fileIn_->readFieldAttributesMetaData(this); 654 CGrid* newGrid ; 655 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = grid_->buildTransformationGraph(gc, true, nullptr, detectMissingValues, defaultValue, newGrid, buildGraph_) ; 656 grid_ = newGrid ; 657 grid_ref=grid_->getId() ; // for server 658 if (fileIn_->isClientSide()) fileIn_->readFieldAttributesValues(this); 659 grid_->checkElementsAttributes() ; 660 // probably in future tag grid incomplete if coming from a reading 661 instantDataFilter=inputFilter ; 662 } 663 else if (hasCouplerIn()) 664 { 665 grid_->checkElementsAttributes() ; 666 instantDataFilter=inputFilter ; 667 } 668 else 669 { 670 setModelIn() ; // no reference, the field is potentially a source field from model 671 672 grid_->solveElementsRefInheritance() ; 673 CGrid* newGrid ; 674 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = grid_->buildTransformationGraph(gc, true, nullptr, detectMissingValues, defaultValue, newGrid, buildGraph_) ; 675 newGrid->duplicateAttributes(grid_) ; // for grid attributes (mask) 676 grid_ = newGrid ; 677 grid_ref=grid_->getId() ; // for server 678 grid_->checkElementsAttributes() ; 679 instantDataFilter=inputFilter ; 680 } 681 } 682 683 if (hasFileOut()) 684 { 685 if (fileOut_->isServerSide()) 686 { 687 this->solveServerOperation() ; 688 } 689 } 690 691 buildWorkflowGraphDone_ = true ; 692 workflowEnabled_ = true ; 693 return true ; 694 } 695 696 /*! 697 * Connect field to filter to send data to server. A temporal filter is inserted before accordingly to the 698 * output frequency of the file 699 * \param gc the garbage collector to use when building the filter graph 804 700 */ 805 void CField::buildGridTransformationGraph() 806 TRY 807 { 808 CContext* context = CContext::getCurrent(); 809 if (context->hasClient && !context->hasServer) 810 { 811 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 812 { 813 grid->addTransGridSource(getDirectFieldReference()->grid); 814 } 815 } 816 } 817 CATCH_DUMP_ATTR 818 819 /*! 820 Generate a new grid destination if there are more than one grid source pointing to a same grid destination 701 void CField::connectToFileServer(CGarbageCollector& gc) 702 { 703 // insert temporal filter before sending to files 704 clientToServerStoreFilter_ = std::shared_ptr<CClientToServerStoreFilter>(new CClientToServerStoreFilter(gc, this, client)); 705 // insert temporal filter before sending to files 706 getTemporalDataFilter(gc, fileOut_->output_freq)->connectOutput(clientToServerStoreFilter_, 0); 707 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 708 if(buildGraph_) 709 { 710 std::cout<<"============== field "<<this->getId()<<" calls a connectToFileServer ============== "<<getTemporalDataFilter(gc, fileOut_->output_freq)<<" _ "<<clientToServerStoreFilter_<<" ***** "<<CXios::isClient<<std::endl; 711 clientToServerStoreFilter_->graphPackage = new CGraphPackage; 712 clientToServerStoreFilter_->graphEnabled = true; 713 clientToServerStoreFilter_->graphPackage->inFields.push_back(this); 714 } 715 } 716 717 void CField::connectToCouplerOut(CGarbageCollector& gc) 718 { 719 // insert temporal filter before sending to files 720 clientToServerStoreFilter_ = std::shared_ptr<CClientToServerStoreFilter>(new CClientToServerStoreFilter(gc, this, client)); 721 instantDataFilter->connectOutput(clientToServerStoreFilter_, 0); 722 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 723 if(buildGraph_) 724 { 725 std::cout<<"============== field "<<this->getId()<<" calls a connectToCouplerOut ============== "<<instantDataFilter<<" _ "<<clientToServerStoreFilter_<<" ***** "<<CXios::isClient<<std::endl; 726 clientToServerStoreFilter_->graphPackage = new CGraphPackage; 727 clientToServerStoreFilter_->graphEnabled = true; 728 clientToServerStoreFilter_->graphPackage->inFields.push_back(this); 729 } 730 } 731 732 733 /*! 734 * Connect field to a source filter to receive data from model. 821 735 */ 822 void CField::generateNewTransformationGridDest() 823 TRY 824 { 825 CContext* context = CContext::getCurrent(); 826 if (context->hasClient && !context->hasServer) 827 { 828 std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid->getTransGridSource(); 829 if (1 < gridSrcMap.size()) 830 { 831 // Search for grid source 832 CGrid* gridSrc = grid; 833 CField* currField = this; 834 std::vector<CField*> hieraField; 835 836 while (currField->hasDirectFieldReference() && (gridSrc == grid)) 837 { 838 hieraField.push_back(currField); 839 CField* tmp = currField->getDirectFieldReference(); 840 currField = tmp; 841 gridSrc = currField->grid; 842 } 843 844 if (gridSrcMap.end() != gridSrcMap.find(gridSrc)) 845 { 846 CGrid* gridTmp; 847 std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc]; 848 if (newGridDest.first) 849 { 850 StdString newIdGridDest = newGridDest.second; 851 if (!CGrid::has(newIdGridDest)) 852 { 853 ERROR("CGrid* CGrid::generateNewTransformationGridDest()", 854 << " Something wrong happened! Grid whose id " << newIdGridDest 855 << "should exist "); 856 } 857 gridTmp = CGrid::get(newIdGridDest); 858 } 859 else 860 { 861 StdString newIdGridDest = CGrid::generateId(gridSrc, grid); 862 gridTmp = CGrid::cloneGrid(newIdGridDest, grid); 863 864 (gridSrcMap[gridSrc]).first = true; 865 (gridSrcMap[gridSrc]).second = newIdGridDest; 866 } 867 868 // Update all descendants 869 for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it) 870 { 871 (*it)->grid = gridTmp; 872 (*it)->updateRef((*it)->grid); 873 } 874 } 875 } 876 } 877 } 878 CATCH_DUMP_ATTR 879 880 void CField::updateRef(CGrid* grid) 881 TRY 882 { 883 if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 884 else 885 { 886 std::vector<CAxis*> axisTmp = grid->getAxis(); 887 std::vector<CDomain*> domainTmp = grid->getDomains(); 888 if ((1<axisTmp.size()) || (1<domainTmp.size())) 889 ERROR("void CField::updateRef(CGrid* grid)", 890 << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 891 892 if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 893 ERROR("void CField::updateRef(CGrid* grid)", 894 << "Incoherent between available domain and domain_ref of field " << this->getId()); 895 if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 896 ERROR("void CField::updateRef(CGrid* grid)", 897 << "Incoherent between available axis and axis_ref of field " << this->getId()); 898 899 if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 900 if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 901 } 902 } 903 CATCH_DUMP_ATTR 904 905 /*! 906 Solve reference of all enabled fields even the source fields . 907 In this step, we do transformations. 736 void CField::connectToModelInput(CGarbageCollector& gc) 737 { 738 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 739 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 740 741 if (check_if_active.isEmpty()) check_if_active = false; 742 modelToClientSourceFilter_ = std::shared_ptr<CModelToClientSourceFilter>(new CModelToClientSourceFilter(gc, grid_, detectMissingValues, defaultValue)); 743 modelToClientSourceFilter_ -> connectOutput(inputFilter,0) ; 744 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 745 if(buildGraph_ ) 746 { 747 std::cout<<"============== field "<<this->getId()<<" calls a connectToModelInput ============== "<<modelToClientSourceFilter_<<" _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 748 modelToClientSourceFilter_->graphPackage = new CGraphPackage; 749 modelToClientSourceFilter_->graphEnabled = true; 750 modelToClientSourceFilter_->graphPackage->inFields.push_back(this); 751 } 752 } 753 754 /*! 755 * Connect field to a source filter to receive data from a client (on server side). 908 756 */ 909 void CField::solveAllEnabledFieldsAndTransform() 910 TRY 911 { 912 CContext* context = CContext::getCurrent(); 913 bool hasClient = context->hasClient; 914 bool hasServer = context->hasServer; 915 916 if (!isReferenceSolvedAndTransformed) 917 { 918 isReferenceSolvedAndTransformed = true; 919 920 if (hasClient && !hasServer) 757 void CField::connectToClientInput(CGarbageCollector& gc) 758 { 759 serverFromClientSourceFilter_ = std::shared_ptr<CServerFromClientSourceFilter>(new CServerFromClientSourceFilter(gc, grid_)); 760 serverFromClientSourceFilter_ -> connectOutput(inputFilter,0) ; 761 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 762 if(buildGraph_) 763 { 764 std::cout<<"============== field "<<this->getId()<<" calls a connectToClientInput ============== "<<serverFromClientSourceFilter_ << " _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 765 serverFromClientSourceFilter_->graphPackage = new CGraphPackage; 766 serverFromClientSourceFilter_->graphEnabled = true; 767 serverFromClientSourceFilter_->graphPackage->inFields.push_back(this); 768 } 769 } 770 771 772 /*! 773 * Connect field to a source filter to receive data from a server (on client side). 774 */ 775 void CField::connectToServerInput(CGarbageCollector& gc) 776 { 777 checkTimeAttributes(); 778 clientFromServerSourceFilter_ = std::shared_ptr<CClientFromServerSourceFilter>(new CClientFromServerSourceFilter(gc,this)) ; 779 clientFromServerSourceFilter_ -> connectOutput(inputFilter,0) ; 780 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 781 if(buildGraph_) 782 { 783 std::cout<<"============== field "<<this->getId()<<" calls a connectToServerInput ============== "<<clientFromServerSourceFilter_ << " _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 784 clientFromServerSourceFilter_->graphPackage = new CGraphPackage; 785 clientFromServerSourceFilter_->graphEnabled = true; 786 clientFromServerSourceFilter_->graphPackage->inFields.push_back(this); 787 } 788 } 789 790 /*! 791 * Connect field to a source filter to receive data from coupler (on client side). 792 */ 793 void CField::connectToCouplerIn(CGarbageCollector& gc) 794 { 795 CContext* context = CContext::getCurrent(); 796 797 if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 798 if (freq_offset.isEmpty()) freq_offset.setValue(freq_op.getValue() - TimeStep); 799 clientFromClientSourceFilter_ = std::shared_ptr<CClientFromClientSourceFilter>(new CClientFromClientSourceFilter(gc, this)) ; 800 clientFromClientSourceFilter_ -> connectOutput(inputFilter,0) ; 801 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 802 if(buildGraph_) 803 { 804 std::cout<<"============== field "<<this->getId()<<" calls a connectToCouplerIn ============== "<<clientFromClientSourceFilter_ << " _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 805 clientFromClientSourceFilter_->graphPackage = new CGraphPackage; 806 clientFromClientSourceFilter_->graphEnabled = true; 807 clientFromClientSourceFilter_->graphPackage->inFields.push_back(this); 808 } 809 } 810 811 /*! 812 * Connect field to a file writer filter to write data in file (on server side). 813 */ 814 void CField::connectToFileWriter(CGarbageCollector& gc) 815 { 816 fileWriterStoreFilter_ = std::shared_ptr<CFileWriterStoreFilter>(new CFileWriterStoreFilter(gc, this)); 817 instantDataFilter->connectOutput(fileWriterStoreFilter_, 0); 818 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 819 if(buildGraph_) 820 { 821 std::cout<<"============== field "<<this->getId()<<" calls a connectToFileWriter ============== "<<instantDataFilter << " _ "<<fileWriterStoreFilter_<<" ***** "<<CXios::isClient<<std::endl; 822 fileWriterStoreFilter_->graphPackage = new CGraphPackage; 823 fileWriterStoreFilter_->graphEnabled = true; 824 fileWriterStoreFilter_->graphPackage->inFields.push_back(this); 825 } 826 } 827 828 /*! 829 * Connect field to a file reader filter to read data from file (on server side). 830 */ 831 void CField::connectToFileReader(CGarbageCollector& gc) 832 { 833 fileReaderSourceFilter_ = std::shared_ptr<CFileReaderSourceFilter>(new CFileReaderSourceFilter(gc, this)); 834 fileReaderSourceFilter_->connectOutput(inputFilter, 0); 835 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 836 if(buildGraph_) 837 { 838 std::cout<<"============== field "<<this->getId()<<" calls a connectToFileReader ============== "<<fileReaderSourceFilter_ << " _ "<<inputFilter<<" ***** "<<CXios::isClient<<std::endl; 839 fileReaderSourceFilter_->graphPackage = new CGraphPackage; 840 fileReaderSourceFilter_->graphEnabled = true; 841 fileReaderSourceFilter_->graphPackage->inFields.push_back(this); 842 } 843 } 844 845 846 /*! 847 * Connect field to a store filter to output data to model on client Side 848 */ 849 void CField::connectToModelOutput(CGarbageCollector& gc) 850 { 851 clientToModelStoreFilter_ = std::shared_ptr<CClientToModelStoreFilter>(new CClientToModelStoreFilter(gc, this)); 852 instantDataFilter->connectOutput(clientToModelStoreFilter_, 0); 853 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 854 if(buildGraph_) 855 { 856 std::cout<<"============== field "<<this->getId()<<" calls a connectToModelOutput ============== "<<instantDataFilter << " _ "<<clientToModelStoreFilter_<<" ***** "<<CXios::isClient<<std::endl; 857 clientToModelStoreFilter_->graphPackage = new CGraphPackage; 858 clientToModelStoreFilter_->graphEnabled = true; 859 clientToModelStoreFilter_->graphPackage->inFields.push_back(this); 860 } 861 } 862 863 864 865 void CField::connectToServerToClient(CGarbageCollector& gc) 866 { 867 serverToClientStoreFilter_ = std::shared_ptr<CServerToClientStoreFilter>(new CServerToClientStoreFilter(gc, this, client)); 868 instantDataFilter->connectOutput(serverToClientStoreFilter_, 0); 869 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 870 if(buildGraph_) 871 { 872 std::cout<<"============== field "<<this->getId()<<" calls a connectToServerToClient ============== "<<instantDataFilter << " _ "<<serverToClientStoreFilter_<<" ***** "<<CXios::isClient<<std::endl; 873 serverToClientStoreFilter_->graphPackage = new CGraphPackage; 874 serverToClientStoreFilter_->graphEnabled = true; 875 serverToClientStoreFilter_->graphPackage->inFields.push_back(this); 876 } 877 } 878 879 /*! 880 * Transform the grid_path attribut into vector of grid. 881 * \return the vector CGrid* containing the list of grid path for tranformation 882 */ 883 vector<CGrid*> CField::getGridPath(void) 884 { 885 std::vector<CGrid*> gridPath; 886 887 if (hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 888 { 889 if (!grid_path.isEmpty()) 890 { 891 std::string gridId; 892 size_t start = 0, end; 893 894 do 921 895 { 922 solveRefInheritance(true); 923 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFieldsAndTransform(); 896 end = grid_path.getValue().find(',', start); 897 if (end != std::string::npos) 898 { 899 gridId = grid_path.getValue().substr(start, end - start); 900 start = end + 1; 901 } 902 else gridId = grid_path.getValue().substr(start); 903 904 if (!CGrid::has(gridId)) 905 ERROR("void CField::solveTransformedGrid()", 906 << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 907 908 gridPath.push_back(CGrid::get(gridId)); 924 909 } 925 926 if (hasServer) 927 solveServerOperation(); 928 929 solveGridReference(); 930 931 if (hasClient && !hasServer) 932 { 933 solveGenerateGrid(); 934 buildGridTransformationGraph(); 935 } 936 937 solveGridDomainAxisRef(false); 938 939 if (hasClient && !hasServer) 940 { 941 solveTransformedGrid(); 942 } 943 944 solveGridDomainAxisRef(false); 945 } 946 } 947 CATCH_DUMP_ATTR 948 949 void CField::checkGridOfEnabledFields() 950 TRY 951 { 952 if (!isGridChecked) 953 { 954 isGridChecked = true; 955 solveCheckMaskIndex(false); 956 } 957 } 958 CATCH_DUMP_ATTR 959 960 void CField::sendGridComponentOfEnabledFields() 961 TRY 962 { 963 solveGridDomainAxisRef(true); 964 // solveCheckMaskIndex(true); 965 } 966 CATCH_DUMP_ATTR 967 968 void CField::sendGridOfEnabledFields() 969 TRY 970 { 971 // solveGridDomainAxisRef(true); 972 solveCheckMaskIndex(true); 973 } 974 CATCH_DUMP_ATTR 975 976 void CField::solveOnlyReferenceEnabledField(bool doSending2Server) 977 TRY 978 { 979 CContext* context = CContext::getCurrent(); 980 if (!isReferenceSolved) 981 { 982 isReferenceSolved = true; 983 984 if (context->hasClient && !context->hasServer) 985 { 986 solveRefInheritance(true); 987 if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(false); 988 } 989 990 if (context->hasServer) 991 solveServerOperation(); 992 993 solveGridReference(); 994 grid->solveDomainAxisRefInheritance(true); // make it again to solve grid reading from file 995 996 if (context->hasClient && !context->hasServer) 997 { 998 solveGenerateGrid(); 999 buildGridTransformationGraph(); 1000 } 1001 } 1002 } 1003 CATCH_DUMP_ATTR 1004 1005 void CField::solveAllReferenceEnabledField(bool doSending2Server) 1006 TRY 1007 { 1008 CContext* context = CContext::getCurrent(); 1009 solveOnlyReferenceEnabledField(doSending2Server); 1010 1011 if (!areAllReferenceSolved) 1012 { 1013 areAllReferenceSolved = true; 1014 1015 if (context->hasClient && !context->hasServer) 1016 { 1017 solveRefInheritance(true); 1018 if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 1019 } 1020 else if (context->hasServer) 1021 solveServerOperation(); 1022 1023 solveGridReference(); 1024 } 1025 1026 solveGridDomainAxisRef(doSending2Server); 1027 1028 if (context->hasClient && !context->hasServer) 1029 { 1030 solveTransformedGrid(); 1031 } 1032 1033 solveCheckMaskIndex(doSending2Server); 1034 } 1035 CATCH_DUMP_ATTR 1036 1037 std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1038 TRY 1039 { 1040 return grid->getAttributesBufferSize(client, bufferForWriting); 1041 } 1042 CATCH_DUMP_ATTR 1043 1044 std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 1045 TRY 1046 { 1047 return grid->getDataBufferSize(client, getId(), bufferForWriting); 1048 } 1049 CATCH_DUMP_ATTR 1050 1051 size_t CField::getGlobalWrittenSize() 1052 TRY 1053 { 1054 return grid->getGlobalWrittenSize(); 1055 } 1056 CATCH_DUMP_ATTR 1057 1058 //---------------------------------------------------------------- 1059 1060 void CField::solveServerOperation(void) 1061 TRY 1062 { 1063 CContext* context = CContext::getCurrent(); 1064 1065 if (!context->hasServer || !hasOutputFile) return; 1066 1067 if (freq_op.isEmpty()) 1068 freq_op.setValue(TimeStep); 1069 1070 if (freq_offset.isEmpty()) 1071 freq_offset.setValue(NoneDu); 1072 1073 freq_operation_srv = file->output_freq.getValue(); 1074 freq_write_srv = file->output_freq.getValue(); 1075 1076 lastlast_Write_srv = context->getCalendar()->getInitDate(); 1077 last_Write_srv = context->getCalendar()->getInitDate(); 1078 last_operation_srv = context->getCalendar()->getInitDate(); 1079 1080 const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep(); 1081 last_operation_srv = last_operation_srv - toffset; 1082 910 while (end != std::string::npos); 911 } 912 } 913 return gridPath ; 914 } 915 916 917 918 /*! 919 * Returns the filter needed to handle a self reference in the field's expression. 920 * If the needed filter does not exist, it is created, otherwise it is reused. 921 * This method should only be called when building the filter graph corresponding 922 * to the field's expression. 923 * 924 * \param gc the garbage collector to use 925 * \return the output pin corresponding to a self reference 926 */ 927 std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 928 TRY 929 { 930 return inputFilter ; 931 } 932 CATCH_DUMP_ATTR 933 934 /*! 935 * Returns the temporal filter corresponding to the field's temporal operation 936 * for the specified operation frequency. The filter is created if it does not 937 * exist, otherwise it is reused. 938 * 939 * \param gc the garbage collector to use 940 * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 941 * \return the output pin corresponding to the requested temporal filter 942 */ 943 std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 944 TRY 945 { 946 std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 947 948 if (it == temporalDataFilters.end()) 949 { 1083 950 if (operation.isEmpty()) 1084 ERROR("void CField:: solveServerOperation(void)",951 ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1085 952 << "An operation must be defined for field \"" << getId() << "\"."); 1086 953 1087 std::shared_ptr<func::CFunctor> functor; 1088 CArray<double, 1> dummyData; 1089 1090 #define DECLARE_FUNCTOR(MType, mtype) \ 1091 if (operation.getValue().compare(#mtype) == 0) \ 1092 { \ 1093 functor.reset(new func::C##MType(dummyData)); \ 1094 } 1095 1096 #include "functor_type.conf" 1097 1098 if (!functor) 1099 ERROR("void CField::solveServerOperation(void)", 1100 << "\"" << operation << "\" is not a valid operation."); 1101 1102 operationTimeType = functor->timeType(); 1103 } 1104 CATCH_DUMP_ATTR 1105 1106 //---------------------------------------------------------------- 1107 1108 /*! 1109 * Constructs the graph filter for the field, enabling or not the data output. 1110 * This method should not be called more than once with enableOutput equal to true. 1111 * 1112 * \param gc the garbage collector to use when building the filter graph 1113 * \param enableOutput must be true when the field data is to be 1114 * read by the client or/and written to a file 1115 */ 1116 void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput, Time start_graph, Time end_graph) 1117 TRY 1118 { 1119 if (!isReferenceSolvedAndTransformed) solveAllEnabledFieldsAndTransform(); 1120 if (!isGridChecked) checkGridOfEnabledFields(); 1121 1122 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1123 1124 const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true); 1125 1126 1127 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1128 1129 CContext* context = CContext::getCurrent(); 1130 1131 Time filter_start; 1132 if(!build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = context->calendar->getInitDate()+build_workflow_graph_start; 1133 else if(build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = 0; 1134 else filter_start = -1; 1135 1136 Time filter_end; 1137 if(!build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = context->calendar->getInitDate()+build_workflow_graph_end; 1138 else if(build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = 9223372036854775807; 1139 else filter_end = -1; 1140 1141 if(this->field_graph_start==-2) this->field_graph_start = filter_start; 1142 if(this->field_graph_end==-2) this->field_graph_end = filter_end; // init 1143 1144 // if(CXios::isClient) std::cout<<"****************** buildFilterGraph : field_id = "<<this->getId()<<" BEFORE: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl; 1145 1146 if(start_graph == -1) 1147 { 1148 //nothing 1149 // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case1: this->field_graph_start = "<<this->field_graph_start<<std::endl; 1150 } 1151 else //if(start_graph != -1) 1152 { 1153 if(this->field_graph_start == -1) this->field_graph_start = start_graph; 1154 else this->field_graph_start = min(this->field_graph_start, start_graph); 1155 1156 // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case2: this->field_graph_start = "<<this->field_graph_start<<std::endl; 1157 } 1158 1159 1160 if(end_graph == -1) 1161 { 1162 //nothing 1163 // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case1: this->field_graph_end = "<<this->field_graph_end<<std::endl; 1164 } 1165 else 1166 { 1167 if(this->field_graph_end == -1) this->field_graph_end = end_graph; 1168 else this->field_graph_end = max(this->field_graph_end, end_graph); 1169 1170 // if(CXios::isClient) std::cout<<"buildFilterGraph field_id = "<<this->getId()<<" case2: this->field_graph_end = "<<this->field_graph_end<<std::endl; 1171 } 1172 1173 1174 filter_start = this->field_graph_start; 1175 filter_end = this->field_graph_end; 1176 1177 1178 // if(CXios::isClient) std::cout<<"****************** buildFilterGraph : field_id = "<<this->getId()<<" AFTER: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl; 1179 1180 1181 1182 1183 1184 bool hasWriterServer = context->hasServer && !context->hasClient; 1185 bool hasIntermediateServer = context->hasServer && context->hasClient; 1186 1187 if (hasWriterServer) 1188 { 1189 if (!instantDataFilter) 1190 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false)); 1191 1192 1193 // If the field data is to be read by the client or/and written to a file 1194 if (enableOutput && !storeFilter && !fileWriterFilter) 1195 { 1196 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1197 { 1198 fileServerWriterFilter = std::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this)); 1199 instantDataFilter->connectOutput(fileServerWriterFilter, 0); 1200 } 1201 } 1202 } 1203 else if (hasIntermediateServer) 1204 { 1205 if (!instantDataFilter) 1206 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, false)); 1207 1208 // If the field data is to be read by the client or/and written to a file 1209 if (enableOutput && !storeFilter && !fileWriterFilter) 1210 { 1211 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1212 { 1213 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this)); 1214 instantDataFilter->connectOutput(fileWriterFilter, 0); 1215 } 1216 } 1217 } 1218 else 1219 { 1220 // Start by building a filter which can provide the field's instant data 1221 if (!instantDataFilter) 1222 { 1223 // Check if we have an expression to parse 1224 if (hasExpression()) 1225 { 1226 boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 1227 std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this, filter_start, filter_end); 1228 1229 // Check if a spatial transformation is needed 1230 if (!field_ref.isEmpty()) 1231 { 1232 CGrid* gridRef = CField::get(field_ref)->grid; 1233 1234 if (grid && grid != gridRef && grid->hasTransform()) 1235 { 1236 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, detectMissingValues, defaultValue); 1237 1238 filter->connectOutput(filters.first, 0); 1239 filter = filters.second; 1240 } 1241 } 1242 1243 instantDataFilter = filter; 1244 instantDataFilter->field = this; 1245 filter->tag = buildWorkflowGraph; 1246 1247 filter->start_graph = filter_start; 1248 filter->end_graph = filter_end; 1249 1250 for(int i=0; i<filter->parent_filters.size(); i++) 1251 { 1252 filter->tag = filter->tag || filter->parent_filters[i]->tag; 1253 } 1254 } 1255 // Check if we have a reference on another field 1256 else if (!field_ref.isEmpty()) 1257 { 1258 instantDataFilter = getFieldReference(gc, filter_start, filter_end); 1259 instantDataFilter->tag = buildWorkflowGraph; 1260 instantDataFilter->start_graph = filter_start; 1261 instantDataFilter->end_graph = filter_end; 1262 } 1263 // Check if the data is to be read from a file 1264 else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1265 { 1266 checkTimeAttributes(); 1267 instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 1268 detectMissingValues, defaultValue)); 1269 instantDataFilter->tag = buildWorkflowGraph; 1270 instantDataFilter->start_graph = filter_start; 1271 instantDataFilter->end_graph = filter_end; 1272 instantDataFilter->field = this; 1273 1274 } 1275 else // The data might be passed from the model 1276 { 1277 if (check_if_active.isEmpty()) check_if_active = false; 1278 instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, true, NoneDu, false, 1279 detectMissingValues, defaultValue)); 1280 instantDataFilter->tag = buildWorkflowGraph; 1281 instantDataFilter->start_graph = filter_start; 1282 instantDataFilter->end_graph = filter_end; 1283 instantDataFilter->field = this; 1284 // if(CXios::isClient) std::cout<<"***********************buildFilterGraph init source filter : field_id = "<<this->getId()<<" sourcefilter->start_graph = "<<clientSourceFilter->start_graph<<" sourcefilter->end_graph = "<<clientSourceFilter->end_graph<<std::endl; 1285 } 1286 } 1287 1288 // If the field data is to be read by the client or/and written to a file 1289 if (enableOutput && !storeFilter && !fileWriterFilter) 1290 { 1291 if (!read_access.isEmpty() && read_access) 1292 { 1293 storeFilter = std::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid, 1294 detectMissingValues, defaultValue)); 1295 instantDataFilter->connectOutput(storeFilter, 0); 1296 1297 storeFilter->tag = (instantDataFilter->tag || buildWorkflowGraph); 1298 instantDataFilter->start_graph = filter_start; 1299 instantDataFilter->end_graph = filter_end; 1300 1301 instantDataFilter->setParentFiltersTag(); 1302 storeFilter->start_graph = filter_start; 1303 storeFilter->end_graph = filter_end; 1304 storeFilter->field = this; 1305 storeFilter->distance = instantDataFilter->distance+1; 1306 } 1307 1308 if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 1309 { 1310 fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this)); 1311 getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 1312 1313 fileWriterFilter->tag = (getTemporalDataFilter(gc, file->output_freq)->tag || buildWorkflowGraph); 1314 getTemporalDataFilter(gc, file->output_freq)->start_graph = filter_start; 1315 getTemporalDataFilter(gc, file->output_freq)->end_graph = filter_end; 1316 getTemporalDataFilter(gc, file->output_freq)->tag = buildWorkflowGraph; 1317 getTemporalDataFilter(gc, file->output_freq)->setParentFiltersTag(); 1318 fileWriterFilter->start_graph = filter_start; 1319 fileWriterFilter->end_graph = filter_end; 1320 fileWriterFilter->distance = getTemporalDataFilter(gc, file->output_freq)->distance+1; 1321 1322 // std::cout<<"CFileWriterFilter filter start = "<<filter_start<<" end = "<<filter_end<<" field = "<<this->getId()<<std::endl; 1323 1324 } 1325 } 1326 } 1327 } 1328 CATCH_DUMP_ATTR 1329 1330 /*! 1331 * Returns the filter needed to handle the field reference. 1332 * This method should only be called when building the filter graph corresponding to the field. 1333 * 1334 * \param gc the garbage collector to use 1335 * \return the output pin corresponding to the field reference 1336 */ 1337 std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc, Time start_graph, Time end_graph) 1338 TRY 1339 { 1340 if (instantDataFilter || field_ref.isEmpty()) 1341 ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 1342 "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 1343 1344 CField* fieldRef = CField::get(field_ref); 1345 fieldRef->buildFilterGraph(gc, false, start_graph, end_graph); 1346 const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true); 1347 1348 CContext* context = CContext::getCurrent(); 1349 1350 Time filter_start; 1351 if(!build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = context->calendar->getInitDate()+build_workflow_graph_start; 1352 else if(build_workflow_graph_start.isEmpty() && buildWorkflowGraph) filter_start = 0; 1353 else filter_start = -1; 1354 1355 Time filter_end; 1356 if(!build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = context->calendar->getInitDate()+build_workflow_graph_end; 1357 else if(build_workflow_graph_end.isEmpty() && buildWorkflowGraph) filter_end = 9223372036854775807; 1358 else filter_end = -1; 1359 1360 if(this->field_graph_start==-2) this->field_graph_start = filter_start; 1361 if(this->field_graph_end==-2) this->field_graph_end = filter_end; // init 1362 1363 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" BEFORE: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl; 1364 1365 if(start_graph == -1) 1366 { 1367 //nothing 1368 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case1: this->field_graph_start = "<<this->field_graph_start<<std::endl; 1369 } 1370 else //if(start_graph != -1) 1371 { 1372 if(this->field_graph_start == -1) this->field_graph_start = start_graph; 1373 else this->field_graph_start = min(this->field_graph_start, start_graph); 1374 1375 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case2: this->field_graph_start = "<<this->field_graph_start<<std::endl; 1376 } 1377 1378 if(end_graph == -1) 1379 { 1380 //nothing 1381 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case1: this->field_graph_end = "<<this->field_graph_end<<std::endl; 1382 } 1383 else 1384 { 1385 if(this->field_graph_end == -1) this->field_graph_end = end_graph; 1386 else this->field_graph_end = max(this->field_graph_end, end_graph); 1387 1388 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" case2: this->field_graph_end = "<<this->field_graph_end<<std::endl; 1389 } 1390 1391 filter_start = this->field_graph_start; 1392 filter_end = this->field_graph_end; 1393 1394 // if(CXios::isClient) std::cout<<"getFieldReference field_id = "<<this->getId()<<" AFTER: this->field_graph_start = "<<this->field_graph_start<<" this->field_graph_end = "<<this->field_graph_end<<std::endl; 1395 1396 1397 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters; 1398 // Check if a spatial transformation is needed 1399 if (grid && grid != fieldRef->grid && grid->hasTransform()) 1400 { 1401 bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1402 double defaultValue = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1403 filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, hasMissingValue, defaultValue); 1404 1405 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 1406 1407 1408 1409 filters.second->parent_filters.resize(1); 1410 filters.second->parent_filters[0]= fieldRef->getInstantDataFilter(); 1411 1412 filters.second->tag = (buildWorkflowGraph || filters.second->parent_filters[0]->tag); 1413 1414 filters.second->start_graph = filter_start; 1415 filters.second->end_graph = filter_end; 1416 filters.second->field = this; 1417 1418 } 1419 else 1420 { 1421 filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 1422 1423 fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 1424 1425 1426 filters.second->parent_filters.resize(1); 1427 filters.second->parent_filters[0]= fieldRef->getInstantDataFilter(); 1428 1429 filters.second->tag = (buildWorkflowGraph || filters.second->parent_filters[0]->tag); 1430 1431 filters.second->start_graph = filter_start; 1432 filters.second->end_graph = filter_end; 1433 filters.second->field = this; 1434 1435 } 1436 1437 return filters.second; 1438 } 1439 CATCH_DUMP_ATTR 1440 1441 /*! 1442 * Returns the filter needed to handle a self reference in the field's expression. 1443 * If the needed filter does not exist, it is created, otherwise it is reused. 1444 * This method should only be called when building the filter graph corresponding 1445 * to the field's expression. 1446 * 1447 * \param gc the garbage collector to use 1448 * \return the output pin corresponding to a self reference 1449 */ 1450 std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc, Time start_graph, Time end_graph) 1451 TRY 1452 { 1453 if(CXios::isClient) std::cout<<"getSelfReference field_id = "<<this->getId()<<" start_graph = "<<start_graph<<" end_graph = "<<end_graph<<std::endl; 1454 1455 if (instantDataFilter || !hasExpression()) 1456 ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 1457 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1458 1459 bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true); 1460 1461 if (!selfReferenceFilter) 1462 { 1463 const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 1464 const double defaultValue = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 1465 1466 if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 1467 { 1468 if (!serverSourceFilter) 1469 { 1470 checkTimeAttributes(); 1471 serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 1472 detectMissingValues, defaultValue)); 1473 } 1474 1475 selfReferenceFilter = serverSourceFilter; 1476 } 1477 else if (!field_ref.isEmpty()) 1478 { 1479 CField* fieldRef = CField::get(field_ref); 1480 fieldRef->buildFilterGraph(gc, false); 1481 selfReferenceFilter = fieldRef->getInstantDataFilter(); 1482 } 1483 else 1484 { 1485 if (!clientSourceFilter) 1486 { 1487 if (check_if_active.isEmpty()) check_if_active = false; 1488 clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, true, NoneDu, false, 1489 detectMissingValues, defaultValue)); 1490 } 1491 1492 selfReferenceFilter = clientSourceFilter; 1493 } 1494 } 1495 1496 selfReferenceFilter->tag = buildWorkflowGraph; 1497 selfReferenceFilter->field = this; 1498 return selfReferenceFilter; 1499 } 1500 CATCH_DUMP_ATTR 1501 1502 /*! 1503 * Returns the temporal filter corresponding to the field's temporal operation 1504 * for the specified operation frequency. The filter is created if it does not 1505 * exist, otherwise it is reused. 1506 * 1507 * \param gc the garbage collector to use 1508 * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 1509 * \return the output pin corresponding to the requested temporal filter 1510 */ 1511 std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1512 TRY 1513 { 1514 std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 1515 const bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true); 1516 1517 CContext* context = CContext::getCurrent(); 1518 1519 1520 if (it == temporalDataFilters.end()) 1521 { 1522 if (operation.isEmpty()) 1523 ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1524 << "An operation must be defined for field \"" << getId() << "\"."); 1525 1526 checkTimeAttributes(&outFreq); 1527 1528 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1529 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 954 checkTimeAttributes(&outFreq); 955 956 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 957 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1530 958 CContext::getCurrent()->getCalendar()->getInitDate(), 1531 959 freq_op, freq_offset, outFreq, detectMissingValues)); 1532 960 1533 instantDataFilter->connectOutput(temporalFilter, 0); 1534 // temporalFilter->tag = buildWorkflowGraph; 1535 1536 temporalFilter->parent_filters.resize(1); 1537 temporalFilter->parent_filters[0] = instantDataFilter; 1538 1539 1540 if(temporalFilter->parent_filters[0]->tag) temporalFilter->tag=true; 1541 1542 // temporalFilter->start_graph = filter_start; 1543 // temporalFilter->end_graph = filter_end; 1544 temporalFilter->field = this; 1545 1546 it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first; 1547 } 1548 1549 return it->second; 1550 } 1551 CATCH_DUMP_ATTR 961 instantDataFilter->connectOutput(temporalFilter, 0); 962 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 963 if(buildGraph_) 964 { 965 std::cout<<"============== field "<<this->getId()<<" calls a getTemporalDataFilter ============== "<<instantDataFilter << " _ "<<temporalFilter<<" ***** "<<CXios::isClient<<std::endl; 966 temporalFilter->graphPackage = new CGraphPackage; 967 temporalFilter->graphEnabled = true; 968 temporalFilter->graphPackage->inFields.push_back(this); 969 } 970 971 it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first; 972 } 973 974 return it->second; 975 } 976 CATCH_DUMP_ATTR 1552 977 1553 978 /*! … … 1559 984 * \return the output pin corresponding to the requested temporal filter 1560 985 */ 1561 1562 std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 1563 TRY 1564 { 1565 if (instantDataFilter || !hasExpression()) 1566 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 1567 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 1568 1569 if (!selfReferenceFilter) getSelfReference(gc) ; 1570 1571 if (serverSourceFilter || clientSourceFilter) 1572 { 1573 if (operation.isEmpty()) 1574 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1575 << "An operation must be defined for field \"" << getId() << "\"."); 1576 1577 checkTimeAttributes(&outFreq); 1578 1579 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1580 bool buildWorkflowGraph = (!build_workflow_graph.isEmpty() && build_workflow_graph == true); 1581 std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 1582 CContext::getCurrent()->getCalendar()->getInitDate(), 1583 freq_op, freq_offset, outFreq, detectMissingValues)); 1584 1585 selfReferenceFilter->connectOutput(temporalFilter, 0); 1586 temporalFilter->tag = buildWorkflowGraph; 1587 temporalFilter->field = this; 1588 1589 return temporalFilter ; 1590 } 1591 else if (!field_ref.isEmpty()) 1592 { 1593 CField* fieldRef = CField::get(field_ref); 1594 fieldRef->buildFilterGraph(gc, false); 1595 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1596 } 1597 } 1598 CATCH_DUMP_ATTR 1599 1600 //---------------------------------------------------------------- 986 987 std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 988 TRY 989 { 990 if (instantDataFilter || !hasExpression()) 991 ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 992 "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 993 994 if (selfTemporalDataFilter) return selfTemporalDataFilter; 995 996 if (hasDirectFieldReference()) 997 { 998 CField* fieldRef=getDirectFieldReference(); 999 return fieldRef->getTemporalDataFilter(gc, outFreq) ; 1000 } 1001 else 1002 { 1003 if (selfTemporalDataFilter) return selfTemporalDataFilter ; 1004 1005 if (operation.isEmpty()) 1006 ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 1007 << "An operation must be defined for field \"" << getId() << "\"."); 1008 1009 checkTimeAttributes(&outFreq); //bof 1010 1011 const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 1012 selfTemporalDataFilter = std::shared_ptr<CTemporalFilter>(new CTemporalFilter(gc, operation, 1013 CContext::getCurrent()->getCalendar()->getInitDate(), 1014 freq_op, freq_offset, outFreq, detectMissingValues)); 1015 1016 inputFilter->connectOutput(selfTemporalDataFilter, 0); 1017 const bool buildGraph_ = !build_workflow_graph.isEmpty() && build_workflow_graph == true ; 1018 if(buildGraph_) 1019 { 1020 std::cout<<"============== field "<<this->getId()<<" calls a getSelfTemporalDataFilter ============== "<<inputFilter << " _ "<<selfTemporalDataFilter<<" ***** "<<CXios::isClient<<std::endl; 1021 selfTemporalDataFilter->graphPackage = new CGraphPackage; 1022 selfTemporalDataFilter->graphEnabled = true; 1023 selfTemporalDataFilter->graphPackage->inFields.push_back(this); 1024 } 1025 return selfTemporalDataFilter ; 1026 } 1027 } 1028 CATCH_DUMP_ATTR 1029 1030 1031 //---------------------------------------------------------------- 1601 1032 /* 1602 1033 void CField::fromBinary(StdIStream& is) … … 1614 1045 //---------------------------------------------------------------- 1615 1046 1616 void CField::solveGridReference(void) 1047 void CField::solveGridReference(void) 1048 TRY 1049 { 1050 if (grid_!=nullptr) return ; // already done 1051 1052 if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 1053 { 1054 ERROR("CField::solveGridReference(void)", 1055 << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 1056 } 1057 else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 1058 { 1059 ERROR("CField::solveGridReference(void)", 1060 << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 1061 << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 1062 } 1063 1064 if (grid_ref.isEmpty()) 1065 { 1066 std::vector<CDomain*> vecDom; 1067 std::vector<CAxis*> vecAxis; 1068 std::vector<CScalar*> vecScalar; 1069 std::vector<int> axisDomainOrderTmp; 1070 1071 std::vector<CDomain*> vecDomRef; 1072 std::vector<CAxis*> vecAxisRef; 1073 std::vector<CScalar*> vecScalarRef; 1074 1075 if (!domain_ref.isEmpty()) 1076 { 1077 StdString tmp = domain_ref.getValue(); 1078 if (CDomain::has(domain_ref)) 1079 { 1080 vecDom.push_back(CDomain::get(domain_ref)); 1081 vecDomRef.push_back(CDomain::createDomain()); 1082 vecDomRef.back()->domain_ref=domain_ref; 1083 axisDomainOrderTmp.push_back(2); 1084 } 1085 else ERROR("CField::solveGridReference(void)", 1086 << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 1087 } 1088 1089 if (!axis_ref.isEmpty()) 1090 { 1091 if (CAxis::has(axis_ref)) 1092 { 1093 vecAxis.push_back(CAxis::get(axis_ref)); 1094 vecAxisRef.push_back(CAxis::createAxis()); 1095 vecAxisRef.back()->axis_ref=axis_ref; 1096 axisDomainOrderTmp.push_back(1); 1097 } 1098 else ERROR("CField::solveGridReference(void)", 1099 << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 1100 } 1101 1102 if (!scalar_ref.isEmpty()) 1103 { 1104 if (CScalar::has(scalar_ref)) 1105 { 1106 vecScalar.push_back(CScalar::get(scalar_ref)); 1107 vecScalarRef.push_back(CScalar::createScalar()); 1108 vecScalarRef.back()->scalar_ref=scalar_ref; 1109 axisDomainOrderTmp.push_back(0); 1110 } 1111 else ERROR("CField::solveGridReference(void)", 1112 << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 1113 } 1114 1115 CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 1116 for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 1117 { 1118 axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 1119 } 1120 1121 // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 1122 StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 1123 if (CGrid::has(gridId)) this->grid_ = CGrid::get(gridId); 1124 else this->grid_ = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 1125 } 1126 else 1127 { 1128 if (CGrid::has(grid_ref)) this->grid_ = CGrid::get(grid_ref); 1129 else ERROR("CField::solveGridReference(void)", 1130 << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 1131 } 1132 } 1133 CATCH_DUMP_ATTR 1134 1135 void CField::solveGridDomainAxisRef(bool checkAtt) 1136 TRY 1137 { 1138 grid_->solveDomainAxisRef(checkAtt); 1139 } 1140 CATCH_DUMP_ATTR 1141 1142 void CField::solveCheckMaskIndex(bool doSendingIndex) 1143 TRY 1144 { 1145 grid_->checkMaskIndex(doSendingIndex); 1146 } 1147 CATCH_DUMP_ATTR 1148 1149 1150 void CField::solveGridDomainAxisBaseRef() 1151 TRY 1152 { 1153 grid_->solveDomainAxisRef(false); 1154 grid_->solveDomainAxisBaseRef(); 1155 } 1156 CATCH_DUMP_ATTR 1157 1158 ///------------------------------------------------------------------- 1159 1160 template <> 1161 void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 1162 TRY 1163 { 1164 if (this->group_ref.isEmpty()) return; 1165 StdString gref = this->group_ref.getValue(); 1166 1167 if (!CFieldGroup::has(gref)) 1168 ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 1169 << "[ gref = " << gref << "]" 1170 << " invalid group name !"); 1171 1172 CFieldGroup* group = CFieldGroup::get(gref); 1173 CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 1174 owner->setAttributes(group); // inherite of attributes of group reference 1175 1176 std::vector<CField*> allChildren = group->getAllChildren(); 1177 std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 1178 1179 for (; it != end; it++) 1180 { 1181 CField* child = *it; 1182 if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 1183 } 1184 } 1185 CATCH_DUMP_ATTR 1186 1187 ///------------------------------------------------------------------- 1188 1189 void CField::parse(xml::CXMLNode& node) 1190 TRY 1191 { 1192 string newContent ; 1193 SuperClass::parse(node); 1194 if (node.goToChildElement()) 1195 { 1196 do 1197 { 1198 if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 1199 else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 1200 } while (node.goToNextElement()); 1201 node.goToParentElement(); 1202 } 1203 if (node.getContent(newContent)) content=newContent ; 1204 } 1205 CATCH_DUMP_ATTR 1206 1207 /*! 1208 This function retrieves Id of corresponding domain_ref and axis_ref (if any) 1209 of a field. In some cases, only domain exists but axis doesn't 1210 \return pair of Domain and Axis id 1211 */ 1212 const std::vector<StdString>& CField::getRefDomainAxisIds() 1213 TRY 1214 { 1215 CGrid* cgPtr = getRelGrid(); 1216 if (NULL != cgPtr) 1217 { 1218 std::vector<StdString>::iterator it; 1219 if (!domain_ref.isEmpty()) 1220 { 1221 std::vector<StdString> domainList = cgPtr->getDomainList(); 1222 it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue()); 1223 if (domainList.end() != it) domAxisScalarIds_[0] = *it; 1224 } 1225 1226 if (!axis_ref.isEmpty()) 1227 { 1228 std::vector<StdString> axisList = cgPtr->getAxisList(); 1229 it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue()); 1230 if (axisList.end() != it) domAxisScalarIds_[1] = *it; 1231 } 1232 1233 if (!scalar_ref.isEmpty()) 1234 { 1235 std::vector<StdString> scalarList = cgPtr->getScalarList(); 1236 it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue()); 1237 if (scalarList.end() != it) domAxisScalarIds_[2] = *it; 1238 } 1239 } 1240 return (domAxisScalarIds_); 1241 } 1242 CATCH_DUMP_ATTR 1243 1244 CVariable* CField::addVariable(const string& id) 1245 TRY 1246 { 1247 return vVariableGroup->createChild(id); 1248 } 1249 CATCH 1250 1251 CVariableGroup* CField::addVariableGroup(const string& id) 1252 TRY 1253 { 1254 return vVariableGroup->createChildGroup(id); 1255 } 1256 CATCH 1257 1258 void CField::setContextClient(CContextClient* contextClient) 1259 TRY 1260 { 1261 CContext* context = CContext::getCurrent(); 1262 client = contextClient; 1263 1264 // A grid is sent by a client (both for read or write) or by primary server (write only) 1265 if (context->getServiceType()==CServicesManager::GATHERER) 1266 { 1267 if (getRelFile()->mode.isEmpty() || (!getRelFile()->mode.isEmpty() && getRelFile()->mode == CFile::mode_attr::write)) 1268 grid_->setContextClient(contextClient); 1269 } 1270 else if (context->getServiceType()==CServicesManager::CLIENT) 1271 grid_->setContextClient(contextClient); 1272 } 1273 CATCH_DUMP_ATTR 1274 1275 void CField::sendCloseDefinition(void) 1276 { 1277 CContext::getCurrent()->sendCloseDefinition(client) ; 1278 } 1279 1280 void CField::sendFieldToFileServer(void) 1281 { 1282 CContext::getCurrent()->sendContextToFileServer(client); 1283 getRelFile()->sendFileToFileServer(client); 1284 sentGrid_ = grid_-> duplicateSentGrid() ; 1285 sentGrid_->sendGridToFileServer(client); 1286 name = getFieldOutputName() ; 1287 this->sendAllAttributesToServer(client); 1288 this->sendAddAllVariables(client); 1289 } 1290 1291 void CField::sendFieldToInputFileServer(void) 1292 { 1293 CContext::getCurrent()->sendContextToFileServer(client); 1294 getRelFile()->sendFileToFileServer(client); 1295 sentGrid_ = grid_-> duplicateSentGrid() ; 1296 sentGrid_->sendGridToFileServer(client); 1297 read_access=true ; // not the best solution, but on server side, the field must be a starting point of the workflow 1298 // must be replace by a better solution when implementing filters for reading and send to client 1299 // on server side 1300 this->sendAllAttributesToServer(client); 1301 this->sendAddAllVariables(client); 1302 } 1303 1304 void CField::sendFieldToCouplerOut(void) 1305 { 1306 if (sendFieldToCouplerOut_done_) return ; 1307 else sendFieldToCouplerOut_done_=true ; 1308 grid_->sendGridToCouplerOut(client, this->getId()); 1309 this->sendGridCompleted(); 1310 1311 } 1312 1313 void CField::makeGridAliasForCoupling(void) 1314 { 1315 grid_->makeAliasForCoupling(this->getId()); 1316 } 1317 1318 //! Client side: Send a message announcing that the grid definition has been received from a coupling context 1319 void CField::sendGridCompleted(void) 1617 1320 TRY 1618 1321 { 1619 if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 1620 { 1621 ERROR("CField::solveGridReference(void)", 1622 << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 1623 } 1624 else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 1625 { 1626 ERROR("CField::solveGridReference(void)", 1627 << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 1628 << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 1629 } 1630 1631 if (grid_ref.isEmpty()) 1632 { 1633 std::vector<CDomain*> vecDom; 1634 std::vector<CAxis*> vecAxis; 1635 std::vector<CScalar*> vecScalar; 1636 std::vector<int> axisDomainOrderTmp; 1637 1638 std::vector<CDomain*> vecDomRef; 1639 std::vector<CAxis*> vecAxisRef; 1640 std::vector<CScalar*> vecScalarRef; 1641 1642 1643 if (!domain_ref.isEmpty()) 1644 { 1645 StdString tmp = domain_ref.getValue(); 1646 if (CDomain::has(domain_ref)) 1647 { 1648 vecDom.push_back(CDomain::get(domain_ref)); 1649 vecDomRef.push_back(CDomain::createDomain()); 1650 vecDomRef.back()->domain_ref=domain_ref; 1651 axisDomainOrderTmp.push_back(2); 1652 } 1653 else ERROR("CField::solveGridReference(void)", 1654 << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 1655 } 1656 1657 if (!axis_ref.isEmpty()) 1658 { 1659 if (CAxis::has(axis_ref)) 1660 { 1661 vecAxis.push_back(CAxis::get(axis_ref)); 1662 vecAxisRef.push_back(CAxis::createAxis()); 1663 vecAxisRef.back()->axis_ref=axis_ref; 1664 axisDomainOrderTmp.push_back(1); 1665 } 1666 else ERROR("CField::solveGridReference(void)", 1667 << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 1668 } 1669 1670 if (!scalar_ref.isEmpty()) 1671 { 1672 if (CScalar::has(scalar_ref)) 1673 { 1674 vecScalar.push_back(CScalar::get(scalar_ref)); 1675 vecScalarRef.push_back(CScalar::createScalar()); 1676 vecScalarRef.back()->scalar_ref=scalar_ref; 1677 axisDomainOrderTmp.push_back(0); 1678 } 1679 else ERROR("CField::solveGridReference(void)", 1680 << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 1681 } 1682 1683 CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 1684 for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 1685 { 1686 axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 1687 } 1688 1689 // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 1690 StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 1691 if (CGrid::has(gridId)) this->grid = CGrid::get(gridId); 1692 else this->grid = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 1693 } 1694 else 1695 { 1696 if (CGrid::has(grid_ref)) this->grid = CGrid::get(grid_ref); 1697 else ERROR("CField::solveGridReference(void)", 1698 << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 1699 } 1322 CEventClient event(getType(),EVENT_ID_GRID_COMPLETED); 1323 1324 if (client->isServerLeader()) 1325 { 1326 CMessage msg; 1327 msg<<this->getId(); 1328 for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg); 1329 client->sendEvent(event); 1330 } 1331 else client->sendEvent(event); 1700 1332 } 1701 1333 CATCH_DUMP_ATTR 1702 1334 1703 void CField::solveGridDomainAxisRef(bool checkAtt) 1335 //! Server side: Receive a message announcing that the grid definition has been received from a coupling context 1336 void CField::recvGridCompleted(CEventServer& event) 1704 1337 TRY 1705 1338 { 1706 grid->solveDomainAxisRef(checkAtt); 1339 CBufferIn* buffer=event.subEvents.begin()->buffer; 1340 string id; 1341 *buffer>>id ; 1342 get(id)->recvGridCompleted(*buffer); 1343 } 1344 CATCH 1345 1346 //! Server side: Receive a message message announcing that the grid definition has been received from a coupling context 1347 void CField::recvGridCompleted(CBufferIn& buffer) 1348 TRY 1349 { 1350 setGridCompleted() ; 1707 1351 } 1708 1352 CATCH_DUMP_ATTR 1709 1353 1710 void CField::solveCheckMaskIndex(bool doSendingIndex) 1711 TRY 1712 { 1713 grid->checkMaskIndex(doSendingIndex); 1714 } 1715 CATCH_DUMP_ATTR 1716 1717 void CField::solveTransformedGrid() 1718 TRY 1719 { 1720 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 1721 { 1722 std::vector<CGrid*> grids; 1723 // Source grid 1724 grids.push_back(getDirectFieldReference()->grid); 1725 // Intermediate grids 1726 if (!grid_path.isEmpty()) 1727 { 1728 std::string gridId; 1729 size_t start = 0, end; 1730 1731 do 1732 { 1733 end = grid_path.getValue().find(',', start); 1734 if (end != std::string::npos) 1735 { 1736 gridId = grid_path.getValue().substr(start, end - start); 1737 start = end + 1; 1738 } 1739 else 1740 gridId = grid_path.getValue().substr(start); 1741 1742 if (!CGrid::has(gridId)) 1743 ERROR("void CField::solveTransformedGrid()", 1744 << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 1745 1746 grids.push_back(CGrid::get(gridId)); 1747 } 1748 while (end != std::string::npos); 1749 } 1750 // Destination grid 1751 grids.push_back(grid); 1752 1753 for (size_t i = 0, count = grids.size() - 1; i < count; ++i) 1754 { 1755 CGrid *gridSrc = grids[i]; 1756 CGrid *gridDest = grids[i + 1]; 1757 if (!gridDest->isTransformed()) 1758 gridDest->transformGrid(gridSrc); 1759 } 1760 } 1761 else if (grid && grid->hasTransform() && !grid->isTransformed()) 1762 { 1763 // Temporarily deactivate the self-transformation of grid 1764 // grid->transformGrid(grid); 1765 } 1766 } 1767 CATCH_DUMP_ATTR 1768 1769 void CField::solveGenerateGrid() 1770 TRY 1771 { 1772 if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 1773 grid->completeGrid(getDirectFieldReference()->grid); 1774 else 1775 grid->completeGrid(); 1776 } 1777 CATCH_DUMP_ATTR 1778 1779 void CField::solveGridDomainAxisBaseRef() 1780 TRY 1781 { 1782 grid->solveDomainAxisRef(false); 1783 grid->solveDomainAxisBaseRef(); 1784 } 1785 CATCH_DUMP_ATTR 1786 1787 ///------------------------------------------------------------------- 1788 1789 template <> 1790 void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 1791 TRY 1792 { 1793 if (this->group_ref.isEmpty()) return; 1794 StdString gref = this->group_ref.getValue(); 1795 1796 if (!CFieldGroup::has(gref)) 1797 ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 1798 << "[ gref = " << gref << "]" 1799 << " invalid group name !"); 1800 1801 CFieldGroup* group = CFieldGroup::get(gref); 1802 CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 1803 owner->setAttributes(group); // inherite of attributes of group reference 1804 1805 std::vector<CField*> allChildren = group->getAllChildren(); 1806 std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 1807 1808 for (; it != end; it++) 1809 { 1810 CField* child = *it; 1811 if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 1812 1813 } 1814 } 1815 CATCH_DUMP_ATTR 1816 1817 void CField::scaleFactorAddOffset(double scaleFactor, double addOffset) 1818 TRY 1819 { 1820 recvDataSrv = (recvDataSrv - addOffset) / scaleFactor; 1821 } 1822 CATCH_DUMP_ATTR 1823 1824 void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 1825 TRY 1826 { 1827 recvDataSrv = recvDataSrv * scaleFactor + addOffset; 1828 } 1829 CATCH_DUMP_ATTR 1830 1831 void CField::outputField(CArray<double,1>& fieldOut) 1832 TRY 1833 { 1834 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient; 1835 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer; 1836 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1837 { 1838 fieldOut(outIndexServer(idx)) = recvDataSrv(outIndexClient(idx)); 1839 } 1840 } 1841 CATCH_DUMP_ATTR 1842 1843 void CField::inputField(CArray<double,1>& fieldIn) 1844 TRY 1845 { 1846 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient; 1847 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer; 1848 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1849 { 1850 recvDataSrv(outIndexClient(idx)) = fieldIn(outIndexServer(idx)); 1851 } 1852 } 1853 CATCH_DUMP_ATTR 1854 1855 void CField::outputCompressedField(CArray<double,1>& fieldOut) 1856 TRY 1857 { 1858 CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient; 1859 CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer; 1860 for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 1861 { 1862 fieldOut((idx)) = recvDataSrv(outIndexClient(idx)); 1863 } 1864 } 1865 CATCH_DUMP_ATTR 1866 1867 ///------------------------------------------------------------------- 1868 1869 void CField::parse(xml::CXMLNode& node) 1870 TRY 1871 { 1872 string newContent ; 1873 SuperClass::parse(node); 1874 if (node.goToChildElement()) 1875 { 1876 do 1877 { 1878 if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 1879 else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 1880 } while (node.goToNextElement()); 1881 node.goToParentElement(); 1882 } 1883 if (node.getContent(newContent)) content=newContent ; 1884 } 1885 CATCH_DUMP_ATTR 1886 1887 /*! 1888 This function retrieves Id of corresponding domain_ref and axis_ref (if any) 1889 of a field. In some cases, only domain exists but axis doesn't 1890 \return pair of Domain and Axis id 1354 1355 void CField::sendAddAllVariables(CContextClient* client) 1356 TRY 1357 { 1358 std::vector<CVariable*> allVar = getAllVariables(); 1359 std::vector<CVariable*>::const_iterator it = allVar.begin(); 1360 std::vector<CVariable*>::const_iterator itE = allVar.end(); 1361 1362 for (; it != itE; ++it) 1363 { 1364 this->sendAddVariable((*it)->getId(), client); 1365 (*it)->sendAllAttributesToServer(client); 1366 (*it)->sendValue(client); 1367 } 1368 } 1369 CATCH_DUMP_ATTR 1370 1371 /*! 1372 * Send all Attributes to server. This method is overloaded, since only grid_ref attribute 1373 * must be sent to server and not domain_ref/axis_ref/scalar_ref. 1891 1374 */ 1892 const std::vector<StdString>& CField::getRefDomainAxisIds()1893 TRY1894 {1895 CGrid* cgPtr = getRelGrid();1896 if (NULL != cgPtr)1897 {1898 std::vector<StdString>::iterator it;1899 if (!domain_ref.isEmpty())1900 {1901 std::vector<StdString> domainList = cgPtr->getDomainList();1902 it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue());1903 if (domainList.end() != it) domAxisScalarIds_[0] = *it;1904 }1905 1906 if (!axis_ref.isEmpty())1907 {1908 std::vector<StdString> axisList = cgPtr->getAxisList();1909 it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue());1910 if (axisList.end() != it) domAxisScalarIds_[1] = *it;1911 }1912 1913 if (!scalar_ref.isEmpty())1914 {1915 std::vector<StdString> scalarList = cgPtr->getScalarList();1916 it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue());1917 if (scalarList.end() != it) domAxisScalarIds_[2] = *it;1918 }1919 }1920 return (domAxisScalarIds_);1921 }1922 CATCH_DUMP_ATTR1923 1924 CVariable* CField::addVariable(const string& id)1925 TRY1926 {1927 return vVariableGroup->createChild(id);1928 }1929 CATCH1930 1931 CVariableGroup* CField::addVariableGroup(const string& id)1932 TRY1933 {1934 return vVariableGroup->createChildGroup(id);1935 }1936 CATCH1937 1938 void CField::setContextClient(CContextClient* contextClient)1939 TRY1940 {1941 CContext* context = CContext::getCurrent();1942 client = contextClient;1943 if (context->hasClient)1944 {1945 // A grid is sent by a client (both for read or write) or by primary server (write only)1946 if (context->hasServer)1947 {1948 if (file->mode.isEmpty() || (!file->mode.isEmpty() && file->mode == CFile::mode_attr::write))1949 grid->setContextClient(contextClient);1950 }1951 else1952 grid->setContextClient(contextClient);1953 }1954 }1955 CATCH_DUMP_ATTR1956 1957 CContextClient* CField::getContextClient()1958 TRY1959 {1960 return client;1961 }1962 CATCH1963 1964 void CField::sendAddAllVariables(CContextClient* client)1965 TRY1966 {1967 std::vector<CVariable*> allVar = getAllVariables();1968 std::vector<CVariable*>::const_iterator it = allVar.begin();1969 std::vector<CVariable*>::const_iterator itE = allVar.end();1970 1971 for (; it != itE; ++it)1972 {1973 this->sendAddVariable((*it)->getId(), client);1974 (*it)->sendAllAttributesToServer(client);1975 (*it)->sendValue(client);1976 }1977 }1978 CATCH_DUMP_ATTR1979 1980 /*!1981 * Send all Attributes to server. This method is overloaded, since only grid_ref attribute1982 * must be sent to server and not domain_ref/axis_ref/scalar_ref.1983 */1984 1375 1985 void CField::sendAllAttributesToServer(CContextClient* client) 1986 TRY 1987 { 1988 if (grid_ref.isEmpty()) 1989 { 1990 grid_ref=grid->getId() ; 1991 SuperClass::sendAllAttributesToServer(client) ; 1992 grid_ref.reset(); 1993 } 1994 else SuperClass::sendAllAttributesToServer(client) ; 1995 } 1996 CATCH_DUMP_ATTR 1376 void CField::sendAllAttributesToServer(CContextClient* client) 1377 TRY 1378 { 1379 if (grid_ref.isEmpty()) 1380 { 1381 grid_ref=sentGrid_->getId() ; 1382 SuperClass::sendAllAttributesToServer(client) ; 1383 domain_ref.reset() ; 1384 axis_ref.reset() ; 1385 scalar_ref.reset() ; 1386 grid_ref.reset(); 1387 } 1388 else 1389 { 1390 string tmp = grid_ref; 1391 grid_ref = sentGrid_->getId() ; 1392 SuperClass::sendAllAttributesToServer(client) ; 1393 grid_ref = tmp ; 1394 } 1395 } 1396 CATCH_DUMP_ATTR 1997 1397 1998 void CField::sendAddVariable(const string& id, CContextClient* client) 1999 TRY 2000 { 2001 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 2002 } 2003 CATCH_DUMP_ATTR 2004 2005 void CField::sendAddVariableGroup(const string& id, CContextClient* client) 2006 TRY 2007 { 2008 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 2009 } 2010 CATCH_DUMP_ATTR 2011 2012 void CField::recvAddVariable(CEventServer& event) 2013 TRY 2014 { 2015 2016 CBufferIn* buffer = event.subEvents.begin()->buffer; 2017 string id; 2018 *buffer >> id; 2019 get(id)->recvAddVariable(*buffer); 2020 } 2021 CATCH 2022 2023 void CField::recvAddVariable(CBufferIn& buffer) 2024 TRY 2025 { 2026 string id; 2027 buffer >> id; 2028 addVariable(id); 2029 } 2030 CATCH_DUMP_ATTR 2031 2032 void CField::recvAddVariableGroup(CEventServer& event) 2033 TRY 2034 { 2035 2036 CBufferIn* buffer = event.subEvents.begin()->buffer; 2037 string id; 2038 *buffer >> id; 2039 get(id)->recvAddVariableGroup(*buffer); 2040 } 2041 CATCH 2042 2043 void CField::recvAddVariableGroup(CBufferIn& buffer) 2044 TRY 2045 { 2046 string id; 2047 buffer >> id; 2048 addVariableGroup(id); 2049 } 2050 CATCH_DUMP_ATTR 2051 2052 /*! 2053 * Check on freq_off and freq_op attributes. 2054 */ 2055 void CField::checkTimeAttributes(CDuration* freqOp) 2056 TRY 2057 { 2058 bool isFieldRead = file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read; 2059 bool isFieldWrite = file && ( file->mode.isEmpty() || file->mode == CFile::mode_attr::write); 2060 if (isFieldRead && !(operation.getValue() == "instant" || operation.getValue() == "once") ) 2061 ERROR("void CField::checkTimeAttributes(void)", 2062 << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 2063 << "Currently only \"instant\" is supported for fields read from file.") 2064 2065 if (freq_op.isEmpty()) 2066 { 2067 if (operation.getValue() == "instant") 2068 { 2069 if (isFieldRead || isFieldWrite) freq_op.setValue(file->output_freq.getValue()); 2070 else freq_op=*freqOp ; 2071 } 2072 else 2073 freq_op.setValue(TimeStep); 2074 } 2075 if (freq_offset.isEmpty()) 2076 freq_offset.setValue(isFieldRead ? NoneDu : (freq_op.getValue() - TimeStep)); 2077 } 2078 CATCH_DUMP_ATTR 2079 2080 /*! 2081 * Returns string arithmetic expression associated to the field. 2082 * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 2083 */ 2084 const string& CField::getExpression(void) 2085 TRY 2086 { 2087 if (!expr.isEmpty() && content.empty()) 2088 { 2089 content = expr; 2090 expr.reset(); 2091 } 2092 2093 return content; 2094 } 2095 CATCH_DUMP_ATTR 2096 2097 bool CField::hasExpression(void) const 2098 TRY 2099 { 2100 return (!expr.isEmpty() || !content.empty()); 2101 } 2102 CATCH 2103 2104 bool CField::hasGridMask(void) const 2105 TRY 2106 { 2107 return (this->grid->hasMask()); 2108 } 2109 CATCH 2110 2111 DEFINE_REF_FUNC(Field,field) 1398 void CField::sendAddVariable(const string& id, CContextClient* client) 1399 TRY 1400 { 1401 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 1402 } 1403 CATCH_DUMP_ATTR 1404 1405 void CField::sendAddVariableGroup(const string& id, CContextClient* client) 1406 TRY 1407 { 1408 sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 1409 } 1410 CATCH_DUMP_ATTR 1411 1412 void CField::recvAddVariable(CEventServer& event) 1413 TRY 1414 { 1415 CBufferIn* buffer = event.subEvents.begin()->buffer; 1416 string id; 1417 *buffer >> id; 1418 get(id)->recvAddVariable(*buffer); 1419 } 1420 CATCH 1421 1422 void CField::recvAddVariable(CBufferIn& buffer) 1423 TRY 1424 { 1425 string id; 1426 buffer >> id; 1427 addVariable(id); 1428 } 1429 CATCH_DUMP_ATTR 1430 1431 void CField::recvAddVariableGroup(CEventServer& event) 1432 TRY 1433 { 1434 CBufferIn* buffer = event.subEvents.begin()->buffer; 1435 string id; 1436 *buffer >> id; 1437 get(id)->recvAddVariableGroup(*buffer); 1438 } 1439 CATCH 1440 1441 void CField::recvAddVariableGroup(CBufferIn& buffer) 1442 TRY 1443 { 1444 string id; 1445 buffer >> id; 1446 addVariableGroup(id); 1447 } 1448 CATCH_DUMP_ATTR 1449 1450 /*! 1451 * Check on freq_off and freq_op attributes. 1452 */ 1453 void CField::checkTimeAttributes(CDuration* freqOp) 1454 TRY 1455 { 1456 if (hasFileIn() && !(operation.getValue() == "instant" || operation.getValue() == "once") ) 1457 ERROR("void CField::checkTimeAttributes(void)", 1458 << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 1459 << "Currently only \"instant\" is supported for fields read from file.") 1460 1461 if (freq_op.isEmpty()) 1462 { 1463 if (operation.getValue() == "instant") 1464 { 1465 if (hasFileIn() || hasFileOut()) freq_op.setValue(getRelFile()->output_freq.getValue()); 1466 else freq_op=*freqOp ; 1467 } 1468 else freq_op.setValue(TimeStep); 1469 } 1470 if (freq_offset.isEmpty()) freq_offset.setValue(hasFileIn() ? NoneDu : (freq_op.getValue() - TimeStep)); 1471 } 1472 CATCH_DUMP_ATTR 1473 1474 /*! 1475 * Returns string arithmetic expression associated to the field. 1476 * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 1477 */ 1478 const string& CField::getExpression(void) 1479 TRY 1480 { 1481 if (!expr.isEmpty() && content.empty()) 1482 { 1483 content = expr; 1484 expr.reset(); 1485 } 1486 1487 return content; 1488 } 1489 CATCH_DUMP_ATTR 1490 1491 bool CField::hasExpression(void) const 1492 TRY 1493 { 1494 return (!expr.isEmpty() || !content.empty()); 1495 } 1496 CATCH 1497 1498 bool CField::hasGridMask(void) const 1499 TRY 1500 { 1501 return (this->grid_->hasMask()); 1502 } 1503 CATCH 1504 1505 DEFINE_REF_FUNC(Field,field) 2112 1506 } // namespace xios -
XIOS/dev/dev_trunk_graph/src/node/field.hpp
r1686 r2019 7 7 #include "functor.hpp" 8 8 #include "functor_type.hpp" 9 #include "filter.hpp"10 9 #include "duration.hpp" 11 10 #include "date.hpp" … … 18 17 #include "variable.hpp" 19 18 #include "context_client.hpp" 20 21 22 namespace xios { 19 #include "pass_through_filter.hpp" 20 #include "temporal_filter.hpp" 21 #include "model_to_client_source_filter.hpp" 22 #include "client_from_client_source_filter.hpp" 23 #include "client_from_server_source_filter.hpp" 24 #include "client_to_model_store_filter.hpp" 25 #include "server_to_client_store_filter.hpp" 26 #include "server_from_client_source_filter.hpp" 27 #include "file_writer_store_filter.hpp" 28 #include "client_to_server_store_filter.hpp" 29 #include "file_reader_source_filter.hpp" 30 31 32 33 34 35 namespace xios 36 { 23 37 24 38 /// ////////////////////// Déclarations ////////////////////// /// … … 29 43 30 44 class CFile; 45 class CCouplerIn ; 46 class CCouplerOut ; 31 47 class CGrid; 32 48 class CContext; … … 36 52 class COutputPin; 37 53 class CSourceFilter; 38 class CStoreFilter; 39 class CFileWriterFilter; 40 class CFileServerWriterFilter; 41 54 class CServerToClientFilter; 42 55 ///-------------------------------------------------------------- 43 56 … … 46 59 # include "field_attribute.conf" 47 60 END_DECLARE_ATTRIBUTE_MAP(CField) 61 62 class CContextClient ; 48 63 49 64 ///-------------------------------------------------------------- … … 59 74 typedef CFieldAttributes SuperClassAttribute; 60 75 76 public : 61 77 enum EReadField 62 78 { … … 72 88 { 73 89 EVENT_ID_UPDATE_DATA, EVENT_ID_READ_DATA, EVENT_ID_READ_DATA_READY, 74 EVENT_ID_ADD_VARIABLE, EVENT_ID_ADD_VARIABLE_GROUP 90 EVENT_ID_ADD_VARIABLE, EVENT_ID_ADD_VARIABLE_GROUP, EVENT_ID_GRID_COMPLETED 75 91 }; 76 92 … … 89 105 90 106 public: 91 int getNStep(void) const;92 93 107 template <int N> void getData(CArray<double, N>& _data) const; 94 95 std::shared_ptr<COutputPin> getInstantDataFilter();96 97 /// Mutateur ///98 void setRelFile(CFile* _file);99 void incrementNStep(void);100 void resetNStep(int nstep = 0);101 void resetNStepMax();102 108 103 109 std::map<int, StdSize> getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting = false); … … 105 111 std::map<int, StdSize> getGridDataBufferSize(CContextClient* client, bool bufferForWriting = false); 106 112 107 void setContextClient(CContextClient* newContextClient); 108 CContextClient* getContextClient(); 109 113 public: 114 void makeGridAliasForCoupling(void) ; 110 115 public: 111 116 bool isActive(bool atCurrentTimestep = false) const; … … 122 127 void solveServerOperation(void); 123 128 void solveCheckMaskIndex(bool doSendingIndex); 124 void solveAllReferenceEnabledField(bool doSending2Server);125 void solveOnlyReferenceEnabledField(bool doSending2Server);126 void generateNewTransformationGridDest();127 129 void updateRef(CGrid* grid); 128 void buildGridTransformationGraph();129 130 void solveGridDomainAxisRef(bool checkAtt); 130 void solveTransformedGrid();131 void solveGenerateGrid();132 131 void solveGridDomainAxisBaseRef(); 133 132 134 void solveAllEnabledFieldsAndTransform();135 133 void checkGridOfEnabledFields(); 136 134 void sendGridOfEnabledFields(); 137 135 void sendGridComponentOfEnabledFields(); 138 136 137 void sendFieldToFileServer(void) ; 138 void sendCloseDefinition(void) ; 139 140 public: 141 void sendFieldToCouplerOut(void) ; 142 private: 143 bool sendFieldToCouplerOut_done_=false; 144 public: 145 146 void sendFieldToInputFileServer(void) ; 147 139 148 /// Vérifications /// 140 149 void checkTimeAttributes(CDuration* freqOp=NULL); 141 150 142 void buildFilterGraph(CGarbageCollector& gc, bool enableOutput, Time start_graph=-1, Time end_graph=-1); 151 bool buildWorkflowGraph(CGarbageCollector& gc) ; 152 bool buildWorkflowGraphDone_ = false ; 153 143 154 size_t getGlobalWrittenSize(void) ; 144 155 145 156 146 std::shared_ptr<COutputPin> getFieldReference(CGarbageCollector& gc, Time start_graph=-1, Time end_graph=-1); 147 std::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc, Time start_graph=-1, Time end_graph=-1); 157 std::shared_ptr<COutputPin> getSelfReference(CGarbageCollector& gc); 148 158 std::shared_ptr<COutputPin> getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq); 149 159 std::shared_ptr<COutputPin> getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq); … … 163 173 static bool dispatchEvent(CEventServer& event); 164 174 void sendAllAttributesToServer(CContextClient* client) ; 165 void sendUpdateData(const CArray<double,1>& data); 166 void sendUpdateData(const CArray<double,1>& data, CContextClient* client); 175 167 176 static void recvUpdateData(CEventServer& event); 168 void rec vUpdateData(std::map<int,CBufferIn*>& rankBuffers);169 void writeField(void); 177 void receiveUpdateData(CEventServer& event); 178 170 179 bool sendReadDataRequest(const CDate& tsDataRequested); 171 180 bool sendReadDataRequestIfNeeded(void); 172 181 static void recvReadDataRequest(CEventServer& event); 173 182 void recvReadDataRequest(void); 174 EReadField readField(void);175 183 static void recvReadDataReady(CEventServer& event); 176 void recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers); 184 void receiveReadDataReady(CEventServer& event); 185 void recvReadDataReady(vector<int> ranks, vector<CBufferIn*> buffers); // old interface to remove 186 void recvDataFromCoupler(vector<int> ranks, vector<CBufferIn*> buffers) ; // old interface to remove 177 187 void checkForLateDataFromServer(void); 178 void checkIfMustAutoTrigger(void); 179 void autoTriggerIfNeeded(void); 180 void outputField(CArray<double,3>& fieldOut); 181 void outputField(CArray<double,2>& fieldOut); 182 void outputField(CArray<double,1>& fieldOut); 183 void inputField(CArray<double,3>& fieldOut); 184 void inputField(CArray<double,2>& fieldOut); 185 void inputField(CArray<double,1>& fieldOut); 186 void outputCompressedField(CArray<double, 1>& fieldOut); 187 void scaleFactorAddOffset(double scaleFactor, double addOffset); 188 void invertScaleFactorAddOffset(double scaleFactor, double addOffset); 188 void checkForLateDataFromCoupler(void) ; 189 190 void checkIfMustAutoTrigger(void); // ym obsolete 191 void autoTriggerIfNeeded(void); //ym obsolete 192 void triggerLateField(void) ; 193 189 194 void parse(xml::CXMLNode& node); 190 195 … … 203 208 void recvAddVariableGroup(CBufferIn& buffer); 204 209 void sendAddAllVariables(CContextClient* client); 205 void writeUpdateData(const CArray<double,1>& data);206 210 207 211 const std::vector<StdString>& getRefDomainAxisIds(); … … 211 215 212 216 bool hasGridMask(void) const; 217 218 void connectToFileServer(CGarbageCollector& gc) ; 219 void connectToCouplerOut(CGarbageCollector& gc) ; 220 void connectToCouplerIn(CGarbageCollector& gc) ; 221 void connectToModelInput(CGarbageCollector& gc) ; 222 void connectToFileWriter(CGarbageCollector& gc) ; 223 void connectToClientInput(CGarbageCollector& gc) ; 224 void connectToServerInput(CGarbageCollector& gc) ; 225 void connectToModelOutput(CGarbageCollector& gc); 226 void connectToFileReader(CGarbageCollector& gc) ; 227 void connectToServerToClient(CGarbageCollector& gc) ; 228 229 void setContextClientDataBufferSize(map<CContextClient*,map<int,size_t>>& bufferSize, 230 map<CContextClient*,map<int,size_t>>& maxEventSize, 231 bool bufferForWriting) ; 232 void setContextClientAttributesBufferSize(map<CContextClient*,map<int,size_t>>& bufferSize, 233 map<CContextClient*,map<int,size_t>>& maxEventSize, 234 bool bufferForWriting) ; 235 private: 236 bool isGridCompleted_ = true ; 237 public: 238 bool isGridCompleted() { return isGridCompleted_ ;} 239 void setGridCompleted(void) { isGridCompleted_= true; } 240 void unsetGridCompleted(void) { isGridCompleted_ = false ;} 241 242 public: 243 void sendGridCompleted(void) ; 244 private: 245 static void recvGridCompleted(CEventServer& event); 246 void recvGridCompleted(CBufferIn& buffer); 247 248 249 private: 250 std::vector<CGrid*> getGridPath(void) ; 213 251 214 252 public: … … 216 254 CVariableGroup* vVariableGroup; 217 255 218 CGrid* grid; 219 CFile* file; 220 221 CDuration freq_operation_srv, freq_write_srv; 222 256 CGrid* grid_=nullptr; 257 CGrid* getGrid(void) { return grid_; } 258 259 private: 260 CGrid* sentGrid_=nullptr ; 261 public: 262 CGrid* getSentGrid(void) { return sentGrid_; } 263 264 public: 265 // CFile* file; 266 267 CFile* fileIn_ = nullptr ; //<! pointer to input related file 268 bool hasFileIn(void) const { return fileIn_==nullptr ? false : true ;} 269 CFile* getFileIn(void) {return fileIn_;} 270 void setFileIn(CFile* fileIn) { fileIn_ = fileIn ;} 271 void unsetFileIn(void) { fileIn_ = nullptr ;} 272 273 CFile* fileOut_ = nullptr ; //<! pointer to output related file 274 bool hasFileOut(void) const { return fileOut_==nullptr ? false : true ;} 275 CFile* getFileOut(void) {return fileOut_;} 276 void setFileOut(CFile* fileOut) { fileOut_ = fileOut ;} 277 void unsetFileOut(void) { fileOut_ = nullptr ;} 278 279 CCouplerIn* couplerIn_ = nullptr ; //<!pointer to input related coupler 280 bool hasCouplerIn(void) const { return couplerIn_==nullptr ? false : true ;} 281 CCouplerIn* getCouplerIn(void) {return couplerIn_;} 282 void setCouplerIn(CCouplerIn* couplerIn) { couplerIn_ = couplerIn ;} 283 void unsetCouplerIn(void) { couplerIn_ = nullptr ;} 284 285 CCouplerOut* couplerOut_ = nullptr ; //<!pointer to output related coupler 286 bool hasCouplerOut(void) const { return couplerOut_==nullptr ? false : true ;} 287 CCouplerOut* getCouplerOut(void) {return couplerOut_;} 288 void setCouplerOut(CCouplerOut* couplerOut) { couplerOut_ = couplerOut ;} 289 void unsetCouplerOut(void) { couplerOut_ = nullptr ;} 290 291 bool modelIn_ = false ; //<! field can be received from model == true 292 bool getModelIn(void) { return modelIn_ ;} 293 void setModelIn(void) { modelIn_ = true ;} 294 void unsetModelIn(void) { modelIn_ = false ;} 295 296 bool modelOut_ = false ; //<! field can be retrieve to model == true 297 bool getModelOut(void) { return modelOut_ ;} 298 void setModelOut(void) { modelOut_ = true ;} 299 void unsetModelOut(void) { modelOut_ = false ;} 300 301 223 302 bool written; //<! Was the field written at least once 224 int nstep, nstepMax;225 bool isEOF;226 CDate lastlast_Write_srv, last_Write_srv, last_operation_srv;227 CDate lastDataRequestedFromServer, lastDataReceivedFromServer, dateEOF;228 bool wasDataRequestedFromServer, wasDataAlreadyReceivedFromServer;229 303 bool mustAutoTrigger; 230 304 231 map<int,std::shared_ptr<func::CFunctor> > foperation_srv;232 233 // map<int, CArray<double,1> > data_srv;234 CArray<double,1> recvDataSrv;235 236 std::shared_ptr<func::CFunctor> recvFoperationSrv;237 305 string content; 238 306 … … 244 312 bool hasTimeCentered; 245 313 246 Time field_graph_start;247 Time field_graph_end;248 249 314 250 315 DECLARE_REF_FUNC(Field,field) 251 316 252 317 private: 253 318 CContextClient* client; 319 public: 320 void setContextClient(CContextClient* newContextClient); 321 CContextClient* getContextClient(void) {return client;} 322 323 private: 254 324 255 325 bool areAllReferenceSolved; … … 257 327 bool isReferenceSolvedAndTransformed; 258 328 bool isGridChecked; 259 bool nstepMaxRead; 260 261 private: 329 330 private: 331 //! define if the field is part of the active workflow. It will be tagged to true when CField::buildWorkflowGraph is successfull 332 bool workflowEnabled_ = false ; 333 public: 334 /*! workflowEnabled_ public accessor 335 * \return Value of workflowEnabled_ */ 336 bool getWorkflowEnabled(void) { return workflowEnabled_; } 337 338 339 private: 340 262 341 //! The type of operation attached to the field 263 342 func::CFunctor::ETimeType operationTimeType; 264 343 344 //! The output pin of the input filter of the field 345 std::shared_ptr<CPassThroughFilter> inputFilter; 346 347 //! The self temporal data filter 348 std::shared_ptr<CTemporalFilter> selfTemporalDataFilter ; 349 265 350 //! The output pin of the filter providing the instant data for the field 266 351 std::shared_ptr<COutputPin> instantDataFilter; 352 public: 353 std::shared_ptr<COutputPin> getInstantDataFilter(void) { return instantDataFilter;} 354 355 private: 356 267 357 //! The output pin of the filters providing the result of the field's temporal operation 268 358 std::map<CDuration, std::shared_ptr<COutputPin>, DurationFakeLessComparator> temporalDataFilters; 359 269 360 //! The output pin of the filter providing the instant data for self references 270 std::shared_ptr<COutputPin> selfReferenceFilter; 361 std::shared_ptr<COutputPin> selfReferenceFilter; // probably redondant with inputFilter 362 271 363 //! The source filter for data provided by the client 272 std::shared_ptr<CSourceFilter> clientSourceFilter; 364 // std::shared_ptr<CSourceFilter> clientSourceFilter; // obsolete to remove 365 366 //! The source filter for data provided by the model to enter the client workflow 367 std::shared_ptr<CModelToClientSourceFilter> modelToClientSourceFilter_; 368 369 //! The source filter for data provided by the model to enter the client workflow 370 std::shared_ptr<CClientToModelStoreFilter> clientToModelStoreFilter_; 371 372 //! The source filter for data provided by the client that send data to server workflow 373 std::shared_ptr<CServerFromClientSourceFilter> serverFromClientSourceFilter_; 374 375 //! The source filter for data provided by an other to enter the current client workflow (coupling mode) 376 std::shared_ptr<CClientFromClientSourceFilter> clientFromClientSourceFilter_; 377 378 //! The source filter for data provided by server to enter the current client workflow (reading mode) 379 std::shared_ptr<CClientFromServerSourceFilter> clientFromServerSourceFilter_; 380 381 //! The source filter for data read from file on server side 382 std::shared_ptr<CFileReaderSourceFilter> fileReaderSourceFilter_; 383 273 384 //! The source filter for data provided by the server 274 std::shared_ptr<CSourceFilter> serverSourceFilter; 275 //! The terminal filter which stores the instant data276 std::shared_ptr<CStoreFilter> storeFilter;277 //! The terminal filter which writes the data to file278 std::shared_ptr<CFileWriterFilter> fileWriterFilter;385 // std::shared_ptr<CSourceFilter> serverSourceFilter; // obsolete to remove 386 387 //! The terminal filter which send data to server for writing 388 std::shared_ptr<CClientToServerStoreFilter> clientToServerStoreFilter_; 389 279 390 //! The terminal filter which writes data to file 280 std::shared_ptr<CFileServerWriterFilter> fileServerWriterFilter; 391 std::shared_ptr<CFileWriterStoreFilter> fileWriterStoreFilter_; 392 393 //! The terminal filter which send data from server to client 394 std::shared_ptr<CServerToClientStoreFilter> serverToClientStoreFilter_; 395 396 281 397 }; // class CField 282 398 -
XIOS/dev/dev_trunk_graph/src/node/field_impl.hpp
r1653 r2019 9 9 #include "timer.hpp" 10 10 #include "array_new.hpp" 11 #include "source_filter.hpp"12 #include "store_filter.hpp"13 11 14 12 … … 19 17 TRY 20 18 { 21 if ( clientSourceFilter)19 if (modelToClientSourceFilter_) 22 20 { 23 21 if (check_if_active.isEmpty() || (!check_if_active.isEmpty() && (!check_if_active) || isActive(true))) 24 clientSourceFilter->streamData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data);22 modelToClientSourceFilter_->streamData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); 25 23 } 26 24 else if (instantDataFilter) … … 34 32 TRY 35 33 { 36 if ( storeFilter)34 if (clientToModelStoreFilter_) 37 35 { 38 CDataPacket::StatusCode status = storeFilter->getData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data);36 CDataPacket::StatusCode status = clientToModelStoreFilter_->getData(CContext::getCurrent()->getCalendar()->getCurrentDate(), _data); 39 37 40 38 if (status == CDataPacket::END_OF_STREAM) -
XIOS/dev/dev_trunk_graph/src/node/file.cpp
r1612 r2019 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; … … 226 222 CContext* context = CContext::getCurrent(); 227 223 const CDate& currentDate = context->calendar->getCurrentDate(); 228 CContextServer* server = context->server;229 224 230 225 lastSync = currentDate; … … 245 240 isOpen = false; 246 241 247 // if (!record_offset.isEmpty() && record_offset < 0)248 // ERROR("void CFile::initFile(void)",249 // "Invalid 'record_offset', this attribute cannot be negative.");250 const int recordOffset = record_offset.isEmpty() ? 0 : record_offset;251 252 242 set<StdString> setAxis; 253 243 set<StdString> setDomains; … … 257 247 { 258 248 CField* field = *it; 259 std::vector<CAxis*> vecAxis = field->g rid->getAxis();249 std::vector<CAxis*> vecAxis = field->getGrid()->getAxis(); 260 250 for (size_t i = 0; i < vecAxis.size(); ++i) 261 251 setAxis.insert(vecAxis[i]->getAxisOutputName()); 262 std::vector<CDomain*> vecDomains = field->g rid->getDomains();252 std::vector<CDomain*> vecDomains = field->getGrid()->getDomains(); 263 253 for (size_t i = 0; i < vecDomains.size(); ++i) 264 254 setDomains.insert(vecDomains[i]->getDomainOutputName()); 265 266 field->resetNStep(recordOffset);267 255 } 268 256 nbAxis = setAxis.size(); … … 272 260 createSubComFile(); 273 261 274 // if (time_counter.isEmpty()) time_counter.setValue(time_counter_attr::centered);275 262 if (time_counter_name.isEmpty()) time_counter_name = "time_counter"; 276 263 } … … 281 268 TRY 282 269 { 270 CContext* context = CContext::getCurrent(); 283 271 if (checkRead) return; 284 createSubComFile(); 272 //createSubComFile(); 273 allZoneEmpty = false; 274 MPI_Comm_dup(context->intraComm_, &fileComm) ; 285 275 checkRead = true; 286 276 } … … 294 284 { 295 285 CContext* context = CContext::getCurrent(); 296 CContextServer* server = context->server;297 286 298 287 // create sub communicator for file … … 302 291 { 303 292 CField* field = *it; 304 bool nullGrid = ( 0 == field->grid);305 allZoneEmpty &= nullGrid ? false : !field->g rid->doGridHaveDataToWrite();293 bool nullGrid = (nullptr == field->getGrid()); 294 allZoneEmpty &= nullGrid ? false : !field->getGrid()->doGridHaveDataToWrite(); 306 295 } 307 296 308 297 int color = allZoneEmpty ? 0 : 1; 309 MPI_Comm_split( server->intraComm, color, server->intraCommRank, &fileComm);298 MPI_Comm_split(context->intraComm_, color, context->intraCommRank_, &fileComm); 310 299 if (allZoneEmpty) MPI_Comm_free(&fileComm); 311 300 } … … 321 310 { 322 311 CContext* context = CContext::getCurrent(); 323 // Done by classical server or secondary server 324 // This condition should be changed soon 325 if (CServer::serverLevel == 0 || CServer::serverLevel == 2) 312 313 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 326 314 { 327 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 328 { 329 CTimer::get("Files : create headers").resume(); 330 if (!isOpen) createHeader(); 331 CTimer::get("Files : create headers").suspend(); 332 checkSync(); 333 } 334 checkSplit(); // REally need this? 335 } 315 CTimer::get("Files : create headers").resume(); 316 if (!isOpen) createHeader(); 317 CTimer::get("Files : create headers").suspend(); 318 checkSync(); 319 } 320 checkSplit(); 336 321 } 337 322 CATCH_DUMP_ATTR … … 349 334 // Done by classical server or secondary server 350 335 // TODO: This condition should be changed soon. It only works with maximum number of level as 2 351 if (CServer::serverLevel == 0 || CServer::serverLevel == 1) 352 { 336 337 //ym if (CServer::serverLevel == 0 || CServer::serverLevel == 1) 338 // ym client must doing it also 339 // if (context->getServiceType()==CServicesManager::IO_SERVER || context->getServiceType()==CServicesManager::GATHERER) 340 // { 353 341 if (!mode.isEmpty() && mode.getValue() == mode_attr::read) 354 342 { … … 360 348 } 361 349 //checkSplit(); // Really need for reading? 362 }350 // } 363 351 } 364 352 CATCH_DUMP_ATTR … … 416 404 lastSplit = lastSplit + split_freq.getValue(); 417 405 std::vector<CField*>::iterator it, end = this->enabledFields.end(); 418 for (it = this->enabledFields.begin(); it != end; it++)406 /* for (it = this->enabledFields.begin(); it != end; it++) 419 407 { 420 408 (*it)->resetNStep(); 421 409 (*it)->resetNStepMax(); 422 } 410 }*/ 423 411 if (mode.isEmpty() || mode.getValue() == mode_attr::write) 424 412 createHeader(); … … 432 420 CATCH_DUMP_ATTR 433 421 422 434 423 /*! 435 424 \brief Create header of netcdf file … … 440 429 { 441 430 CContext* context = CContext::getCurrent(); 442 CContextServer* server = context->server; 443 431 444 432 if (!allZoneEmpty) 445 433 { … … 557 545 MPI_Comm_rank(fileComm, &commRank); 558 546 559 if ( server->intraCommSize> 1)547 if (context->intraCommSize_ > 1) 560 548 { 561 549 oss << "_" ; … … 633 621 { 634 622 CContext* context = CContext::getCurrent(); 635 CContextServer* server = context->server;636 623 MPI_Comm readComm = this->fileComm; 637 624 … … 680 667 MPI_Comm_rank(readComm, &commRank); 681 668 682 if ( server->intraCommSize> 1)669 if (context->intraCommSize_ > 1) 683 670 { 684 671 oss << "_"; … … 696 683 bool isCollective = par_access.isEmpty() || par_access == par_access_attr::collective; 697 684 bool readMetaDataPar = true; 698 if ( !context->hasServer) readMetaDataPar = (read_metadata_par.isEmpty()) ? false : read_metadata_par;685 if (context->getServiceType()==CServicesManager::CLIENT) readMetaDataPar = (read_metadata_par.isEmpty()) ? false : read_metadata_par; 699 686 700 687 if (isOpen) data_out->closeFile(); … … 747 734 748 735 // Now complete domain and axis associated with this field 749 enabledFields[idx]->solveGenerateGrid(); 736 737 //ym => this a problem in wich order are done the grid generation. Probably metadata are read in file and after the grid is ditributed by the filter 738 // => must be checked in detail. But solveGenerated grid is not existing any more with new transformation framework 739 // enabledFields[idx]->solveGenerateGrid(); 750 740 751 741 // Read necessary value from file … … 761 751 CATCH_DUMP_ATTR 762 752 753 void CFile::readFieldAttributesMetaData(CField* field) 754 { 755 this->data_in->readFieldAttributesMetaData(field); 756 } 757 758 void CFile::readFieldAttributesValues(CField* field) 759 { 760 this->data_in->readFieldAttributesValues(field); 761 } 763 762 /*! 764 763 \brief Parse xml file and write information into file object … … 822 821 823 822 //---------------------------------------------------------------- 824 825 /*!826 \brief Resolve all reference of active fields.827 In order to know exactly which data each active field has, a search for all its828 reference to find its parents or/and its base reference object must be done. Moreover829 during this search, there are some information that can only be sent to server AFTER830 all information of active fields are created on server side, e.g: checking mask or index831 \param [in] sendToServer: Send all info to server (true) or only a part of it (false)832 */833 void CFile::solveOnlyRefOfEnabledFields(bool sendToServer)834 TRY835 {836 int size = this->enabledFields.size();837 for (int i = 0; i < size; ++i)838 {839 this->enabledFields[i]->solveOnlyReferenceEnabledField(sendToServer);840 }841 }842 CATCH_DUMP_ATTR843 823 844 824 void CFile::checkGridOfEnabledFields() … … 931 911 CATCH_DUMP_ATTR 932 912 933 void CFile::generateNewTransformationGridDest()934 TRY935 {936 int size = this->enabledFields.size();937 for (int i = 0; i < size; ++i)938 {939 this->enabledFields[i]->generateNewTransformationGridDest();940 }941 }942 CATCH_DUMP_ATTR943 944 /*!945 \brief Resolve all reference of active fields.946 In order to know exactly which data each active field has, a search for all its947 reference to find its parents or/and its base reference object must be done. Moreover948 during this search, there are some information that can only be sent to server AFTER949 all information of active fields are created on server side, e.g: checking mask or index950 \param [in] sendToServer: Send all info to server (true) or only a part of it (false)951 */952 void CFile::solveAllRefOfEnabledFieldsAndTransform(bool sendToServer)953 TRY954 {955 int size = this->enabledFields.size();956 for (int i = 0; i < size; ++i)957 {958 this->enabledFields[i]->solveAllEnabledFieldsAndTransform();959 }960 }961 CATCH_DUMP_ATTR962 963 /*!964 * Constructs the filter graph for each active field.965 *966 * \param gc the garbage collector to use when building the filter graph967 */968 void CFile::buildFilterGraphOfEnabledFields(CGarbageCollector& gc)969 TRY970 {971 int size = this->enabledFields.size();972 for (int i = 0; i < size; ++i)973 {974 this->enabledFields[i]->buildFilterGraph(gc, true);975 }976 }977 CATCH_DUMP_ATTR978 913 979 914 /*! … … 1350 1285 CATCH_DUMP_ATTR 1351 1286 1287 1288 1289 /*! 1290 * Send file attribute, related variable and chield field tree to a given file server. 1291 * \param[in] client : the context client where to send file 1292 */ 1293 void CFile::sendFileToFileServer(CContextClient* client) 1294 TRY 1295 { 1296 if (sendFileToFileServer_done_.count(client)!=0) return ; 1297 else sendFileToFileServer_done_.insert(client) ; 1298 1299 StdString fileDefRoot("file_definition"); 1300 CFileGroup* cfgrpPtr = CFileGroup::get(fileDefRoot); 1301 cfgrpPtr->sendCreateChild(this->getId(), client); 1302 this->sendAllAttributesToServer(client); 1303 this->sendAddAllVariables(client); 1304 for(auto field : enabledFields) this->sendAddField(field->getId(), client); 1305 } 1306 CATCH_DUMP_ATTR 1352 1307 /*! 1353 1308 \brief Dispatch event received from client -
XIOS/dev/dev_trunk_graph/src/node/file.hpp
r1612 r2019 104 104 void close(void); 105 105 void readAttributesOfEnabledFieldsInReadMode(); 106 106 void readFieldAttributesMetaData(CField* field) ; 107 void readFieldAttributesValues(CField* field) ; 107 108 // Some processing on file 108 109 void solveFieldRefInheritance(bool apply); 109 110 void processEnabledFile(void); 110 void solveOnlyRefOfEnabledFields(bool sendToServer);111 void generateNewTransformationGridDest();112 111 113 void buildFilterGraphOfEnabledFields(CGarbageCollector& gc);114 112 void postProcessFilterGraph(); 115 113 void prefetchEnabledReadModeFields(); … … 117 115 void doPostTimestepOperationsForEnabledReadModeFields(); 118 116 119 void solveAllRefOfEnabledFieldsAndTransform(bool sendToServer);120 117 void checkGridOfEnabledFields(); 121 118 void sendGridOfEnabledFields(); … … 142 139 void sendAddVariableGroup(const string& id, CContextClient* client); 143 140 void sendAddAllVariables(CContextClient* client); 144 141 public: 142 void sendFileToFileServer(CContextClient* client) ; 143 private: 144 std::set<CContextClient*> sendFileToFileServer_done_ ; 145 146 public: 145 147 // Receive info from client 146 148 static void recvAddField(CEventServer& event); … … 173 175 CDate lastSync; 174 176 CDate lastSplit; 177 178 const CDate& getLastSplit(void) { return lastSplit ; } 179 175 180 int nbAxis, nbDomains; 176 181 bool isOpen; … … 192 197 std::vector<CField*> enabledFields; 193 198 199 private: 200 bool isClientSide_ ; // the file is on client side or on server side ? 201 public: 202 bool isClientSide(void) { return isClientSide_ ;} 203 bool isServerSide(void) { return !isClientSide_ ;} 204 void setClientSide(void) { isClientSide_=true ;} 205 void setServerSide(void) { isClientSide_=false ;} 206 207 private: 208 194 209 195 210 public: -
XIOS/dev/dev_trunk_graph/src/node/generate_rectilinear_domain.cpp
r838 r2019 1 1 #include "generate_rectilinear_domain.hpp" 2 #include "domain_algorithm_generate_rectilinear.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CGenerateRectilinearDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_GENERATE_RECTILINEAR_DOMAIN, create);30 registerTransformation(TRANS_GENERATE_RECTILINEAR_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 138 139 } 139 140 141 CGenericAlgorithmTransformation* CGenerateRectilinearDomain::createAlgorithm(bool isSource, 142 CGrid* gridDst, CGrid* gridSrc, 143 int elementPositionInGrid, 144 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 145 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 146 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 147 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 148 std::map<int, int>& elementPositionInGridDst2AxisPosition, 149 std::map<int, int>& elementPositionInGridDst2DomainPosition) 150 { 151 return CDomainAlgorithmGenerateRectilinear::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 152 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 153 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 154 } 140 155 } -
XIOS/dev/dev_trunk_graph/src/node/generate_rectilinear_domain.hpp
r836 r2019 20 20 class CGenerateRectilinearDomain; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CGenerateRectilinearDomain> SuperClass; 42 43 typedef CGenerateRectilinearDomainAttributes SuperClassAttribute; 44 typedef CGenerateRectilinearDomain MyClass ; 45 typedef CTransformation<CDomain> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_GENERATE_RECTILINEAR_DOMAIN ;} 63 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/grid.cpp
r1612 r2019 16 16 #include "client_server_mapping_distributed.hpp" 17 17 #include "distribution_client.hpp" 18 #include "grid_transformation.hpp"19 #include "grid_generate.hpp"20 18 #include "server.hpp" 21 22 namespace xios { 19 #include "distribution_type.hpp" 20 #include "grid_remote_connector.hpp" 21 #include "grid_elements.hpp" 22 #include "grid_local_view.hpp" 23 #include "grid_mask_connector.hpp" 24 #include "transformation_path.hpp" 25 #include "grid_transformation_factory_impl.hpp" 26 #include "transform_filter.hpp" 27 #include "grid_algorithm.hpp" 28 #include "grid_algorithm_generic.hpp" 29 #include "generic_algorithm_transformation.hpp" 30 #include "algo_types.hpp" 31 32 33 namespace xios 34 { 23 35 24 36 /// ////////////////////// Dfinitions ////////////////////// /// … … 30 42 , vAxisGroup_(), axisList_(), isAxisListSet(false) 31 43 , vScalarGroup_(), scalarList_(), isScalarListSet(false) 32 , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0) 33 , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 44 , clientDistribution_(0), isIndexSent(false) 34 45 , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_() 35 , isDataDistributed_(true), isCompressible_(false) 36 , transformations_(0), isTransformed_(false) 46 , isCompressible_(false) 37 47 , axisPositionInGrid_(), hasDomainAxisBaseRef_(false) 38 , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_() 39 , computedWrittenIndex_(false) 48 , gridSrc_(), order_() 40 49 , clients() 41 50 { … … 51 60 , vAxisGroup_(), axisList_(), isAxisListSet(false) 52 61 , vScalarGroup_(), scalarList_(), isScalarListSet(false) 53 , clientDistribution_(0), isIndexSent(false) , serverDistribution_(0), clientServerMap_(0) 54 , writtenDataSize_(0), numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0) 62 , clientDistribution_(0), isIndexSent(false) 55 63 , connectedDataSize_(), connectedServerRank_(), connectedServerRankRead_(), connectedDataSizeRead_() 56 , isDataDistributed_(true), isCompressible_(false) 57 , transformations_(0), isTransformed_(false) 64 , isCompressible_(false) 58 65 , axisPositionInGrid_(), hasDomainAxisBaseRef_(false) 59 , gridSrc_(), hasTransform_(false), isGenerated_(false), order_(), globalIndexOnServer_() 60 , computedWrittenIndex_(false) 66 , gridSrc_(), order_() 61 67 , clients() 62 68 { … … 69 75 { 70 76 if (0 != clientDistribution_) delete clientDistribution_; 71 if (0 != serverDistribution_) delete serverDistribution_;72 if (0 != clientServerMap_) delete clientServerMap_;73 if (0 != transformations_) delete transformations_;74 77 } 75 78 … … 81 84 82 85 86 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 87 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 88 ///////// MEMBER FUNCTION RELATED TO GRID CONSTRUCTION by ELEMNTS AND MANAGEMENT ///// 89 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 90 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 91 92 93 CGrid* CGrid::createGrid(CDomain* domain) 94 TRY 95 { 96 std::vector<CDomain*> vecDom(1, domain); 97 std::vector<CAxis*> vecAxis; 98 return createGrid(vecDom, vecAxis); 99 } 100 CATCH 101 102 CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis) 103 TRY 104 { 105 std::vector<CDomain*> vecDom(1, domain); 106 std::vector<CAxis*> vecAxis(1, axis); 107 108 return createGrid(vecDom, vecAxis); 109 } 110 CATCH 111 112 CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 113 const CArray<int,1>& axisDomainOrder) 114 TRY 115 { 116 std::vector<CScalar*> vecScalar; 117 return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder); 118 } 119 CATCH 120 121 CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 122 const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder) 123 TRY 124 { 125 return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder); 126 } 127 CATCH 128 129 CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 130 const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder) 131 TRY 132 { 133 if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size())) 134 ERROR("CGrid* CGrid::createGrid(...)", 135 << "The size of axisDomainOrder (" << axisDomainOrder.numElements() 136 << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<")."); 137 138 CGrid* grid = CGridGroup::get("grid_definition")->createChild(id); 139 grid->setDomainList(domains); 140 grid->setAxisList(axis); 141 grid->setScalarList(scalars); 142 143 // By default, domains are always the first elements of a grid 144 if (0 == axisDomainOrder.numElements()) 145 { 146 int size = domains.size() + axis.size() + scalars.size(); 147 int nb = 0; 148 grid->axis_domain_order.resize(size); 149 for (int i = 0; i < size; ++i) 150 { 151 if (i < domains.size()) 152 { 153 grid->axis_domain_order(i) = 2; 154 grid->order_.push_back(2) ; 155 } 156 else if ((scalars.size() < (size-nb)) < size) 157 { 158 grid->axis_domain_order(i) = 1; 159 grid->order_.push_back(1) ; 160 } 161 else 162 { 163 grid->axis_domain_order(i) = 0; 164 grid->order_.push_back(0) ; 165 } 166 ++nb; 167 } 168 } 169 else 170 { 171 grid->axis_domain_order.resize(axisDomainOrder.numElements()); 172 grid->axis_domain_order = axisDomainOrder; 173 grid->order_.clear() ; 174 for(int i=0; i<axisDomainOrder.numElements();i++) grid->order_.push_back(axisDomainOrder(i)) ; 175 176 } 177 178 // grid->solveElementsRefInheritance(true); 179 grid->computeElements() ; 180 return grid; 181 } 182 CATCH 183 184 //---------------------------------------------------------------- 185 186 //! Change virtual field group to a new one 187 void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup) 188 TRY 189 { 190 this->vDomainGroup_ = newVDomainGroup; 191 } 192 CATCH_DUMP_ATTR 193 194 //! Change virtual variable group to new one 195 void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup) 196 TRY 197 { 198 this->vAxisGroup_ = newVAxisGroup; 199 } 200 CATCH_DUMP_ATTR 201 202 //! Change virtual variable group to new one 203 void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup) 204 TRY 205 { 206 this->vScalarGroup_ = newVScalarGroup; 207 } 208 CATCH_DUMP_ATTR 209 210 //---------------------------------------------------------------- 211 212 CDomainGroup* CGrid::getVirtualDomainGroup() const 213 TRY 214 { 215 return this->vDomainGroup_; 216 } 217 CATCH 218 219 CAxisGroup* CGrid::getVirtualAxisGroup() const 220 TRY 221 { 222 return this->vAxisGroup_; 223 } 224 CATCH 225 226 CScalarGroup* CGrid::getVirtualScalarGroup() const 227 TRY 228 { 229 return this->vScalarGroup_; 230 } 231 CATCH 232 233 ///--------------------------------------------------------------- 234 235 CDomain* CGrid::addDomain(const std::string& id) 236 TRY 237 { 238 order_.push_back(2); 239 axis_domain_order.resize(order_.size()); 240 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 241 CDomain* domain = vDomainGroup_->createChild(id); 242 isDomListSet=false ; 243 computeElements(); 244 return domain ; 245 } 246 CATCH_DUMP_ATTR 247 248 CAxis* CGrid::addAxis(const std::string& id) 249 TRY 250 { 251 order_.push_back(1); 252 axis_domain_order.resize(order_.size()); 253 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 254 CAxis* axis=vAxisGroup_->createChild(id); 255 isAxisListSet=false ; 256 computeElements(); 257 return axis ; 258 } 259 CATCH_DUMP_ATTR 260 261 CScalar* CGrid::addScalar(const std::string& id) 262 TRY 263 { 264 order_.push_back(0); 265 axis_domain_order.resize(order_.size()); 266 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 267 CScalar* scalar = vScalarGroup_->createChild(id); 268 isScalarListSet=false ; 269 computeElements(); 270 return scalar; 271 } 272 CATCH_DUMP_ATTR 273 274 275 276 277 /*! 278 \brief Get the list of domain pointers 279 \return list of domain pointers 280 */ 281 std::vector<CDomain*> CGrid::getDomains() 282 TRY 283 { 284 setDomainList(); 285 std::vector<CDomain*> domList; 286 if (!domList_.empty()) 287 { 288 for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i])); 289 } 290 return domList; 291 } 292 CATCH_DUMP_ATTR 293 294 /*! 295 \brief Get the list of axis pointers 296 \return list of axis pointers 297 */ 298 std::vector<CAxis*> CGrid::getAxis() 299 TRY 300 { 301 setAxisList(); 302 std::vector<CAxis*> aList; 303 if (!axisList_.empty()) 304 for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i])); 305 306 return aList; 307 } 308 CATCH_DUMP_ATTR 309 310 /*! 311 \brief Get the list of axis pointers 312 \return list of axis pointers 313 */ 314 std::vector<CScalar*> CGrid::getScalars() 315 TRY 316 { 317 setScalarList() ; 318 std::vector<CScalar*> sList; 319 if (!scalarList_.empty()) 320 for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i])); 321 322 return sList; 323 } 324 CATCH_DUMP_ATTR 325 326 /*! 327 \brief Get domain pointer with index 328 \return domain pointer 329 */ 330 CDomain* CGrid::getDomain(int domainIndex) 331 TRY 332 { 333 std::vector<CDomain*> domainListP = this->getDomains(); 334 if (domainListP.empty()) 335 { 336 ERROR("CGrid::getDomain(int domainIndex)", 337 << "No domain associated to this grid. " << std::endl 338 << "Grid id = " << this->getId()); 339 } 340 341 if (domainIndex >= domainListP.size() || (domainIndex < 0)) 342 ERROR("CGrid::getDomain(int domainIndex)", 343 << "Domain with the index doesn't exist " << std::endl 344 << "Grid id = " << this->getId() << std::endl 345 << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl); 346 347 return domainListP[domainIndex]; 348 } 349 CATCH_DUMP_ATTR 350 351 /*! 352 \brief Get the axis pointer with index 353 \return axis pointer 354 */ 355 CAxis* CGrid::getAxis(int axisIndex) 356 TRY 357 { 358 std::vector<CAxis*> axisListP = this->getAxis(); 359 if (axisListP.empty()) 360 { 361 ERROR("CGrid::getDomain(int axisIndex)", 362 << "No axis associated to this grid. " << std::endl 363 << "Grid id = " << this->getId()); 364 } 365 366 if (axisIndex >= axisListP.size() || (axisIndex < 0)) 367 ERROR("CGrid::getDomain(int axisIndex)", 368 << "Domain with the index doesn't exist " << std::endl 369 << "Grid id = " << this->getId() << std::endl 370 << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl); 371 372 return axisListP[axisIndex]; 373 } 374 CATCH_DUMP_ATTR 375 376 /*! 377 \brief Get the a scalar pointer 378 \return scalar pointer 379 */ 380 CScalar* CGrid::getScalar(int scalarIndex) 381 TRY 382 { 383 std::vector<CScalar*> scalarListP = this->getScalars(); 384 if (scalarListP.empty()) 385 { 386 ERROR("CGrid::getScalar(int scalarIndex)", 387 << "No scalar associated to this grid. " << std::endl 388 << "Grid id = " << this->getId()); 389 } 390 391 if (scalarIndex >= scalarListP.size() || (scalarIndex < 0)) 392 ERROR("CGrid::getScalar(int scalarIndex)", 393 << "Scalar with the index doesn't exist " << std::endl 394 << "Grid id = " << this->getId() << std::endl 395 << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl); 396 397 return scalarListP[scalarIndex]; 398 } 399 CATCH_DUMP_ATTR 400 401 /*! 402 \brief Set domain(s) of a grid from a list 403 \param[in] domains list of domains 404 */ 405 void CGrid::setDomainList(const std::vector<CDomain*> domains) 406 TRY 407 { 408 if (isDomListSet) return; 409 std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren(); 410 if (!domains.empty() && domList.empty()) 411 { 412 for (int i = 0; i < domains.size(); ++i) 413 this->getVirtualDomainGroup()->addChild(domains[i]); 414 domList = this->getVirtualDomainGroup()->getAllChildren(); 415 } 416 417 if (!domList.empty()) 418 { 419 int sizeDom = domList.size(); 420 domList_.resize(sizeDom); 421 for (int i = 0; i < sizeDom; ++i) 422 { 423 domList_[i] = domList[i]->getId(); 424 } 425 isDomListSet = true; 426 } 427 } 428 CATCH_DUMP_ATTR 429 430 /*! 431 \brief Set axis(s) of a grid from a list 432 \param[in] axis list of axis 433 */ 434 void CGrid::setAxisList(const std::vector<CAxis*> axis) 435 TRY 436 { 437 if (isAxisListSet) return; 438 std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren(); 439 if (!axis.empty() && aList.empty()) 440 { 441 for (int i = 0; i < axis.size(); ++i) 442 this->getVirtualAxisGroup()->addChild(axis[i]); 443 aList = this->getVirtualAxisGroup()->getAllChildren(); 444 } 445 446 if (!aList.empty()) 447 { 448 int sizeAxis = aList.size(); 449 axisList_.resize(sizeAxis); 450 for (int i = 0; i < sizeAxis; ++i) 451 { 452 axisList_[i] = aList[i]->getId(); 453 } 454 isAxisListSet = true; 455 } 456 } 457 CATCH_DUMP_ATTR 458 459 /*! 460 \brief Set scalar(s) of a grid from a list 461 \param[in] scalars list of scalars 462 */ 463 void CGrid::setScalarList(const std::vector<CScalar*> scalars) 464 TRY 465 { 466 if (isScalarListSet) return; 467 std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren(); 468 if (!scalars.empty() && sList.empty()) 469 { 470 for (int i = 0; i < scalars.size(); ++i) 471 this->getVirtualScalarGroup()->addChild(scalars[i]); 472 sList = this->getVirtualScalarGroup()->getAllChildren(); 473 } 474 475 if (!sList.empty()) 476 { 477 int sizeScalar = sList.size(); 478 scalarList_.resize(sizeScalar); 479 for (int i = 0; i < sizeScalar; ++i) 480 { 481 scalarList_[i] = sList[i]->getId(); 482 } 483 isScalarListSet = true; 484 } 485 } 486 CATCH_DUMP_ATTR 487 488 /*! 489 \brief Get list of id of domains 490 \return id list of domains 491 */ 492 std::vector<StdString> CGrid::getDomainList() 493 TRY 494 { 495 setDomainList(); 496 return domList_; 497 } 498 CATCH 499 500 /*! 501 \brief Get list of id of axis 502 \return id list of axis 503 */ 504 std::vector<StdString> CGrid::getAxisList() 505 TRY 506 { 507 setAxisList(); 508 return axisList_; 509 } 510 CATCH 511 512 /*! 513 \brief Get list of id of scalar 514 \return id list of scalar 515 */ 516 std::vector<StdString> CGrid::getScalarList() 517 TRY 518 { 519 setScalarList(); 520 return scalarList_; 521 } 522 CATCH 523 524 525 void CGrid::computeElements(void) 526 { 527 const auto& domains = getDomains() ; 528 const auto& axis = getAxis() ; 529 const auto& scalars = getScalars() ; 530 int idxDomain = 0, idxAxis=0 , idxScalar=0 ; 531 532 elements_.clear() ; 533 for(auto type : order_) 534 { 535 if (type == 0) { elements_.push_back({scalars[idxScalar], TYPE_SCALAR, scalars[idxScalar], nullptr, nullptr } ) ; idxScalar++;} 536 else if (type == 1) { elements_.push_back({axis[idxAxis], TYPE_AXIS, nullptr, axis[idxAxis], nullptr}) ; idxAxis++;} 537 else if (type == 2) { elements_.push_back({domains[idxDomain], TYPE_DOMAIN, nullptr, nullptr, domains[idxDomain] }) ; idxDomain++;} 538 } 539 elementsComputed_ = true ; 540 } 541 542 543 /*! 544 Parse a grid, for now, it contains only domain, axis and scalar 545 */ 546 void CGrid::parse(xml::CXMLNode& node) 547 TRY 548 { 549 SuperClass::parse(node); 550 551 if (node.goToChildElement()) 552 { 553 StdString domainName("domain"); 554 StdString axisName("axis"); 555 StdString scalarName("scalar"); 556 do 557 { 558 if (node.getElementName() == domainName) { 559 order_.push_back(2); 560 this->getVirtualDomainGroup()->parseChild(node); 561 } 562 if (node.getElementName() == axisName) { 563 order_.push_back(1); 564 this->getVirtualAxisGroup()->parseChild(node); 565 } 566 if (node.getElementName() == scalarName) { 567 order_.push_back(0); 568 this->getVirtualScalarGroup()->parseChild(node); 569 } 570 } while (node.goToNextElement()); 571 node.goToParentElement(); 572 } 573 574 if (!order_.empty()) 575 { 576 int sizeOrd = order_.size(); 577 axis_domain_order.resize(sizeOrd); 578 for (int i = 0; i < sizeOrd; ++i) 579 { 580 axis_domain_order(i) = order_[i]; 581 } 582 } 583 584 setDomainList(); 585 setAxisList(); 586 setScalarList(); 587 computeElements() ; 588 } 589 CATCH_DUMP_ATTR 590 591 592 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 593 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 594 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 595 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 596 597 598 83 599 StdSize CGrid::getDimension(void) 84 600 TRY … … 90 606 //--------------------------------------------------------------- 91 607 92 StdSize CGrid::getDataSize(void) const608 StdSize CGrid::getDataSize(void) 93 609 TRY 94 610 { … … 96 612 if (!isScalarGrid()) 97 613 { 98 std::vector<int> dataNindex = clientDistribution_->getDataNIndex();614 std::vector<int> dataNindex = getClientDistribution()->getDataNIndex(); 99 615 for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i]; 100 616 } … … 102 618 } 103 619 CATCH 620 621 /*! 622 * Get the local data grid size, ie the size of the compressed grid (inside the workflow) 623 * \return The size od the compressed grid 624 */ 625 StdSize CGrid::getLocalDataSize(void) { return getClientDistribution()->getLocalDataSize();} 626 104 627 105 628 /*! … … 128 651 for (size_t i = 0; i < axisList.size(); ++i) 129 652 { 130 std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(), axisPositionInGrid_[i]);653 std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize(client, getGlobalDimension(),getAxisPositionInGrid()[i]); 131 654 for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it) 132 655 { … … 202 725 CATCH_DUMP_ATTR 203 726 204 void CGrid::checkAttributesAfterTransformation() 205 TRY 206 { 207 setAxisList(); 208 std::vector<CAxis*> axisListP = this->getAxis(); 209 if (!axisListP.empty()) 210 { 211 int idx = 0; 212 axisPositionInGrid_.resize(0); 213 for (int i = 0; i < axis_domain_order.numElements(); ++i) 214 { 215 int elementDimension = axis_domain_order(i); 216 if (1 == elementDimension) 217 { 218 axisPositionInGrid_.push_back(idx); 219 ++idx; 220 } 221 else if (2 == elementDimension) idx += 2; 222 } 223 224 for (int i = 0; i < axisListP.size(); ++i) 225 { 226 axisListP[i]->checkAttributesOnClientAfterTransformation(getGlobalDimension(),axisPositionInGrid_[i]); 227 } 228 } 229 230 setDomainList(); 231 std::vector<CDomain*> domListP = this->getDomains(); 232 if (!domListP.empty()) 233 { 234 for (int i = 0; i < domListP.size(); ++i) 235 { 236 domListP[i]->checkAttributesOnClientAfterTransformation(); 237 } 238 } 239 } 240 CATCH_DUMP_ATTR 241 242 //--------------------------------------------------------------- 243 727 728 void CGrid::computeAxisPositionInGrid(void) 729 { 730 axisPositionInGrid_.resize(0); 731 int idx = 0; 732 for (int i = 0; i < axis_domain_order.numElements(); ++i) 733 { 734 int elementDimension = axis_domain_order(i); 735 if (1 == elementDimension) 736 { 737 axisPositionInGrid_.push_back(idx); 738 ++idx; 739 } 740 else if (2 == elementDimension) idx += 2; 741 } 742 } 743 744 244 745 /*! 245 746 * Test whether the data defined on the grid can be outputted in a compressed way. … … 327 828 CATCH_DUMP_ATTR 328 829 830 //ym obsolete -> to be removed later 329 831 void CGrid::checkMaskIndex(bool doSendingIndex) 330 832 TRY 331 833 { 332 834 CContext* context = CContext::getCurrent(); 333 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1; 334 nbSrvPools = 1; 335 for (int p = 0; p < nbSrvPools; ++p) 336 { 337 if (context->hasClient && this->isChecked && doSendingIndex && !isIndexSent) 338 { 339 if (isScalarGrid()) 340 sendIndexScalarGrid(); 341 else 342 sendIndex(); 343 this->isIndexSent = true; 344 } 345 346 // Not sure about this 347 //if (!(this->hasTransform() && !this->isTransformed())) 348 // this->isChecked = true; 349 //return; 350 } 351 835 352 836 if (this->isChecked) return; 353 this->checkAttributesAfterTransformation(); 354 355 // TODO: Transfer grid attributes 356 //if (!context->hasClient && context->hasServer) this->createMask(); 357 this->computeIndex(); 358 359 if (!(this->hasTransform() && !this->isTransformed())) 360 this->isChecked = true; 361 362 if (!(this->hasTransform() && (!this->isGenerated()))) 363 this->isChecked = true; 364 } 365 CATCH_DUMP_ATTR 837 this->checkElementsAttributes(); 838 this->isChecked = true; 839 } 840 CATCH_DUMP_ATTR 841 842 366 843 bool CGrid::hasMask() const 367 844 TRY … … 372 849 CATCH 373 850 374 /* 375 Create mask of grid from mask of its components 376 */ 377 void CGrid::createMask(void) 378 TRY 379 { 380 using namespace std; 381 std::vector<CDomain*> domainP = this->getDomains(); 382 std::vector<CAxis*> axisP = this->getAxis(); 383 int dim = domainP.size() * 2 + axisP.size(); 384 385 std::vector<CArray<bool,1>* > domainMasks(domainP.size()); 386 for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask); 387 std::vector<CArray<bool,1>* > axisMasks(axisP.size()); 388 for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask); 389 390 switch (dim) { 391 case 1: 392 checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order, true); 393 break; 394 case 2: 395 checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order, true); 396 break; 397 case 3: 398 checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order, true); 399 break; 400 case 4: 401 checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order, true); 402 break; 403 case 5: 404 checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order, true); 405 break; 406 case 6: 407 checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order, true); 408 break; 409 case 7: 410 checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order, true); 411 break; 412 default: 413 break; 414 } 415 } 416 CATCH_DUMP_ATTR 417 418 /* 419 Check validity of grid's mask by using the masks of its components 420 */ 421 void CGrid::checkMask(void) 422 TRY 423 { 424 using namespace std; 425 std::vector<CDomain*> domainP = this->getDomains(); 426 std::vector<CAxis*> axisP = this->getAxis(); 427 int dim = domainP.size() * 2 + axisP.size(); 428 429 std::vector<CArray<bool,1>* > domainMasks(domainP.size()); 430 for (int i = 0; i < domainMasks.size(); ++i) domainMasks[i] = &(domainP[i]->domainMask); 431 std::vector<CArray<bool,1>* > axisMasks(axisP.size()); 432 for (int i = 0; i < axisMasks.size(); ++i) axisMasks[i] = &(axisP[i]->mask); 433 434 switch (dim) { 435 case 1: 436 checkGridMask(mask_1d, domainMasks, axisMasks, axis_domain_order); 437 break; 438 case 2: 439 checkGridMask(mask_2d, domainMasks, axisMasks, axis_domain_order); 440 break; 441 case 3: 442 checkGridMask(mask_3d, domainMasks, axisMasks, axis_domain_order); 443 break; 444 case 4: 445 checkGridMask(mask_4d, domainMasks, axisMasks, axis_domain_order); 446 break; 447 case 5: 448 checkGridMask(mask_5d, domainMasks, axisMasks, axis_domain_order); 449 break; 450 case 6: 451 checkGridMask(mask_6d, domainMasks, axisMasks, axis_domain_order); 452 break; 453 case 7: 454 checkGridMask(mask_7d, domainMasks, axisMasks, axis_domain_order); 455 break; 456 default: 457 break; 458 } 459 } 460 CATCH_DUMP_ATTR 461 462 /* 463 Modify value of mask in a certain index 464 This function can be used to correct the mask of grid after being constructed with createMask 465 \param [in] indexToModify 466 \param [in] modifyValue 467 */ 468 void CGrid::modifyMask(const CArray<int,1>& indexToModify, bool modifyValue) 469 TRY 470 { 471 using namespace std; 472 std::vector<CDomain*> domainP = this->getDomains(); 473 std::vector<CAxis*> axisP = this->getAxis(); 474 int dim = domainP.size() * 2 + axisP.size(); 475 476 switch (dim) { 477 case 0: 478 modifyGridMask(mask_0d, indexToModify, modifyValue); 479 break; 480 case 1: 481 modifyGridMask(mask_1d, indexToModify, modifyValue); 482 break; 483 case 2: 484 modifyGridMask(mask_2d, indexToModify, modifyValue); 485 break; 486 case 3: 487 modifyGridMask(mask_3d, indexToModify, modifyValue); 488 break; 489 case 4: 490 modifyGridMask(mask_4d, indexToModify, modifyValue); 491 break; 492 case 5: 493 modifyGridMask(mask_5d, indexToModify, modifyValue); 494 break; 495 case 6: 496 modifyGridMask(mask_6d, indexToModify, modifyValue); 497 break; 498 case 7: 499 modifyGridMask(mask_7d, indexToModify, modifyValue); 500 break; 501 default: 502 break; 503 } 504 } 505 CATCH_DUMP_ATTR 506 507 /* 508 Change the mask size. This function is used on reconstructing mask in server side 509 \param [in] newDimensionSize 510 \param [in] newValue 511 */ 512 void CGrid::modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue) 513 TRY 514 { 515 std::vector<CDomain*> domainP = this->getDomains(); 516 std::vector<CAxis*> axisP = this->getAxis(); 517 int dim = domainP.size() * 2 + axisP.size(); 518 519 switch (dim) { 520 case 0: 521 modifyGridMaskSize(mask_0d, newDimensionSize, newValue); 522 break; 523 case 1: 524 modifyGridMaskSize(mask_1d, newDimensionSize, newValue); 525 break; 526 case 2: 527 modifyGridMaskSize(mask_2d, newDimensionSize, newValue); 528 break; 529 case 3: 530 modifyGridMaskSize(mask_3d, newDimensionSize, newValue); 531 break; 532 case 4: 533 modifyGridMaskSize(mask_4d, newDimensionSize, newValue); 534 break; 535 case 5: 536 modifyGridMaskSize(mask_5d, newDimensionSize, newValue); 537 break; 538 case 6: 539 modifyGridMaskSize(mask_6d, newDimensionSize, newValue); 540 break; 541 case 7: 542 modifyGridMaskSize(mask_7d, newDimensionSize, newValue); 543 break; 544 default: 545 break; 546 } 547 } 548 CATCH_DUMP_ATTR 549 851 852 CArray<bool,1>& CGrid::getMask(void) 853 { 854 855 if (mask_.isEmpty()) 856 { 857 if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ; 858 if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ; 859 if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ; 860 if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ; 861 if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ; 862 if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ; 863 if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ; 864 if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ; 865 } 866 return mask_ ; 867 } 868 869 550 870 //--------------------------------------------------------------- 551 871 … … 556 876 std::vector<CDomain*> domListP = this->getDomains(); 557 877 if (!domListP.empty()) 558 { 559 for (int i = 0; i < domListP.size(); ++i) 560 { 561 if (sendAtt) domListP[i]->sendCheckedAttributes(); 562 else domListP[i]->checkAttributesOnClient(); 563 } 564 } 878 for (int i = 0; i < domListP.size(); ++i) domListP[i]->checkAttributes(); 565 879 } 566 880 CATCH_DUMP_ATTR … … 574 888 std::vector<CAxis*> axisListP = this->getAxis(); 575 889 if (!axisListP.empty()) 576 { 577 int idx = 0; 578 axisPositionInGrid_.resize(0); 579 for (int i = 0; i < axis_domain_order.numElements(); ++i) 580 { 581 int elementDimension = axis_domain_order(i); 582 if (1 == elementDimension) 583 { 584 axisPositionInGrid_.push_back(idx); 585 ++idx; 586 } 587 else if (2 == elementDimension) idx += 2; 588 } 589 590 for (int i = 0; i < axisListP.size(); ++i) 591 { 592 if (sendAtt) 593 axisListP[i]->sendCheckedAttributes(getGlobalDimension(),axisPositionInGrid_[i]); 594 else 595 axisListP[i]->checkAttributesOnClient(); 596 } 597 } 890 for (int i = 0; i < axisListP.size(); ++i) axisListP[i]->checkAttributes(); 598 891 } 599 892 CATCH_DUMP_ATTR … … 607 900 std::vector<CScalar*> scalarListP = this->getScalars(); 608 901 if (!scalarListP.empty()) 609 { 610 for (int i = 0; i < scalarListP.size(); ++i) 611 { 612 /*Nothing to do for now */ 613 // if (sendAtt) scalarListP[i]->sendCheckedAttributes(); 614 // else scalarListP[i]->checkAttributesOnClient(); 615 } 616 } 617 } 618 CATCH_DUMP_ATTR 619 620 /*! 621 Compute the index to for write data into a file 622 */ 623 void CGrid::computeWrittenIndex() 624 TRY 625 { 626 if (computedWrittenIndex_) return; 627 computedWrittenIndex_ = true; 628 629 if (isScalarGrid()) 630 { 631 size_t nbWritten = 1; 632 int writtenIndex = 0; 633 634 localIndexToWriteOnClient.resize(nbWritten); 635 localIndexToWriteOnServer.resize(nbWritten); 636 localIndexToWriteOnServer(0) = writtenIndex; 637 localIndexToWriteOnClient(0) = writtenIndex; 638 639 return; 640 } 641 642 size_t nbWritten = 0, indGlo; 643 CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient(); 644 CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(), 645 ite = globalDataIndex.end(), it; 646 const CDistributionServer::GlobalLocalMap& globalLocalIndex = serverDistribution_->getGlobalLocalIndex(); 647 CDistributionServer::GlobalLocalMap::const_iterator itSrvb = globalLocalIndex.begin(), 648 itSrve = globalLocalIndex.end(), itSrv; 649 for (it = itb; it != ite; ++it) 650 { 651 indGlo = it->first; 652 if (globalLocalIndex.end() != globalLocalIndex.find(indGlo)) ++nbWritten; 653 } 654 655 localIndexToWriteOnClient.resize(nbWritten); 656 localIndexToWriteOnServer.resize(nbWritten); 657 658 { 659 numberWrittenIndexes_ = nbWritten; 660 if (isDataDistributed_) 661 { 662 CContextServer* server = CContext::getCurrent()->server; 663 MPI_Allreduce(&numberWrittenIndexes_, &totalNumberWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm); 664 MPI_Scan(&numberWrittenIndexes_, &offsetWrittenIndexes_, 1, MPI_INT, MPI_SUM, server->intraComm); 665 offsetWrittenIndexes_ -= numberWrittenIndexes_; 666 } 667 else 668 totalNumberWrittenIndexes_ = numberWrittenIndexes_; 669 } 670 671 nbWritten = 0; 672 for (it = itb; it != ite; ++it) 673 { 674 indGlo = it->first; 675 itSrv = globalLocalIndex.find(indGlo); 676 if (itSrve != itSrv) 677 { 678 localIndexToWriteOnServer(nbWritten) = itSrv->second; 679 localIndexToWriteOnClient(nbWritten) = it->second; 680 ++nbWritten; 681 } 682 } 683 } 684 CATCH_DUMP_ATTR 685 686 //--------------------------------------------------------------- 687 688 /* 689 Compute the global index and its local index taking account mask and data index. 690 These global indexes will be used to compute the connection of this client (sender) to its servers (receivers) 691 (via function computeConnectedClient) 692 These global indexes also correspond to data sent to servers (if any) 693 */ 694 void CGrid::computeClientIndex() 695 TRY 696 { 902 for (int i = 0; i < scalarListP.size(); ++i) scalarListP[i]->checkAttributes() ; 903 } 904 CATCH_DUMP_ATTR 905 906 907 //--------------------------------------------------------------- 908 CDistributionClient* CGrid::getClientDistribution() 909 TRY 910 { 911 if (!computeClientDistribution_done_) computeClientDistribution() ; 912 return clientDistribution_; 913 } 914 CATCH_DUMP_ATTR 915 916 void CGrid::computeClientDistribution(void) 917 { 918 if (computeClientDistribution_done_) return ; 919 else computeClientDistribution_done_ = true ; 920 697 921 CContext* context = CContext::getCurrent(); 698 699 CContextClient* client = context->client; 700 int rank = client->clientRank; 701 922 int rank = context-> getIntraCommRank(); 702 923 clientDistribution_ = new CDistributionClient(rank, this); 703 // Get local data index on client 704 int nbStoreIndex = clientDistribution_->getLocalDataIndexOnClient().size(); 705 int nbStoreGridMask = clientDistribution_->getLocalMaskIndexOnClient().size(); 706 // nbStoreGridMask = nbStoreIndex if grid mask is defined, and 0 otherwise 707 storeIndex_client.resize(nbStoreIndex); 708 storeMask_client.resize(nbStoreGridMask); 709 for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx]; 710 for (int idx = 0; idx < nbStoreGridMask; ++idx) storeMask_client(idx) = (clientDistribution_->getLocalMaskIndexOnClient())[idx]; 711 712 if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed(); 713 else 714 { 715 // Mapping global index received from clients to the storeIndex_client 716 CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient(); 717 CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end(); 718 map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(), 719 ite = outGlobalIndexFromClient.end(), it; 720 721 for (it = itb; it != ite; ++it) 722 { 723 int rank = it->first; 724 CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank]; 725 outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements()))); 726 CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank]; 727 size_t nbIndex = 0; 728 729 // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance 730 for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 731 { 732 if (itGloe != globalDataIndex.find(globalIndex(idx))) 733 { 734 ++nbIndex; 735 } 736 } 737 738 if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements())) 739 ERROR("void CGrid::computeClientIndex()", 740 << "Number of local index on client is different from number of received global index" 741 << "Rank of sent client " << rank <<"." 742 << "Number of local index " << nbIndex << ". " 743 << "Number of received global index " << localIndex.numElements() << "."); 744 745 nbIndex = 0; 746 for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 747 { 748 if (itGloe != globalDataIndex.find(globalIndex(idx))) 749 { 750 localIndex(idx) = globalDataIndex[globalIndex(idx)]; 751 } 752 } 753 } 754 } 755 } 756 CATCH_DUMP_ATTR 757 758 /*! 759 Compute connected receivers and indexes to be sent to these receivers. 760 */ 761 void CGrid::computeConnectedClients() 762 TRY 763 { 764 CContext* context = CContext::getCurrent(); 765 int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size(); 766 connectedServerRank_.clear(); 767 connectedDataSize_.clear(); 768 globalIndexOnServer_.clear(); 769 nbSenders.clear(); 770 771 for (int p = 0; p < nbSrvPools; ++p) 772 { 773 CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p]; 774 int receiverSize = client->serverSize; 775 // connectedServerRank_[client].clear(); 776 777 if (connectedServerRank_.find(receiverSize) == connectedServerRank_.end()) 778 { 779 if (!doGridHaveDataDistributed(client)) 780 { 781 if (client->isServerLeader()) 782 { 783 size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size(); 784 const std::list<int>& ranks = client->getRanksServerLeader(); 785 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 786 { 787 connectedServerRank_[receiverSize].push_back(*itRank); 788 connectedDataSize_[receiverSize][*itRank] = ssize; 789 } 790 } 791 return; 792 } 793 794 // Compute mapping between client and server 795 std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 796 CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 797 std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 798 client->clientRank, 799 client->clientSize, 800 axis_domain_order, 801 getDistributedDimension()); 802 803 // Even if servers have no index, they must received something from client 804 // We only use several client to send "empty" message to these servers 805 std::list<int> serverZeroIndexLeader; 806 std::list<int> serverZeroIndexNotLeader; 807 CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 808 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 809 *it = serverZeroIndex[*it]; 810 811 if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end()) 812 computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]); 813 814 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer(); 815 CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap; 816 CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap; 817 itbGlobalMap = globalIndexOnServer_[receiverSize].begin(); 818 iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 819 820 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 821 { 822 int serverRank = itGlobalMap->first; 823 int indexSize = itGlobalMap->second.size(); 824 const std::vector<size_t>& indexVec = itGlobalMap->second; 825 for (int idx = 0; idx < indexSize; ++idx) 826 { 827 itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]); 828 if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap) 829 { 830 if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank)) 831 connectedDataSize_[receiverSize][serverRank] = 1; 832 else 833 ++connectedDataSize_[receiverSize][serverRank]; 834 } 835 } 836 } 837 838 // Connected servers which really have index 839 for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) { 840 connectedServerRank_[receiverSize].push_back(itGlobalMap->first); 841 } 842 843 // Connected servers which have no index at all 844 for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 845 connectedServerRank_[receiverSize].push_back(*it); 846 847 // Even if a client has no index, it must connect to at least one server and 848 // send an "empty" data to this server 849 if (connectedServerRank_[receiverSize].empty()) 850 connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize); 851 852 // Now check if all servers have data to receive. If not, master client will send empty data. 853 // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 854 std::vector<int> counts (client->clientSize); 855 std::vector<int> displs (client->clientSize); 856 displs[0] = 0; 857 int localCount = connectedServerRank_[receiverSize].size() ; 858 MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 859 for (int i = 0; i < client->clientSize-1; ++i) 860 { 861 displs[i+1] = displs[i] + counts[i]; 862 } 863 std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]); 864 MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 865 866 if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0)) 867 { 868 std::vector<bool> isSrvConnected (receiverSize, false); 869 for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 870 for (int i = 0; i < receiverSize; ++i) 871 { 872 if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i); 873 } 874 } 875 876 nbSenders[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]); 877 } 878 } 879 } 880 CATCH_DUMP_ATTR 881 882 /*! 883 Compute the global index of grid to send to server as well as the connected server of the current client. 884 First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know 885 their global index. We can have a map of global index of grid and local index that each client holds 886 Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s) 887 of the current client. 888 */ 889 void CGrid::computeIndex(void) 890 TRY 891 { 892 CContext* context = CContext::getCurrent(); 893 if (isScalarGrid()) 894 { 895 computeClientIndexScalarGrid(); 896 if (context->hasClient) 897 { 898 computeConnectedClientsScalarGrid(); 899 } 900 } 901 else 902 { 903 computeClientIndex(); 904 if (context->hasClient) 905 { 906 computeConnectedClients(); 907 } 908 } 909 if (CServer::serverLevel==2) 910 { 911 computeWrittenIndex() ; 912 if (serverDistribution_!=0) serverDistribution_->partialClear() ; 913 if (clientDistribution_!=0) clientDistribution_->partialClear() ; 914 outGlobalIndexFromClient.clear() ; 915 } 916 } 917 CATCH_DUMP_ATTR 918 919 /*! 920 Compute the global of (client) grid to send to server with the global index of each element of grid 921 Each element of grid has its own global index associated to a groups of server. We only search for the global index of each element whose 922 server is the same, then calculate the global index of grid. This way can reduce so much the time for executing DHT, which only needs to run 923 on each element whose size is much smaller than one of whole grid. 924 \param [in] indexServerOnElement global index of each element and the rank of server associated with these index 925 \param [in] client contextClient 926 \param [out] globalIndexOnServer global index of grid and its corresponding rank of server. 927 */ 928 void CGrid::computeIndexByElement(const std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement, 929 const CContextClient* client, 930 CClientServerMapping::GlobalIndexMap& globalIndexOnServer) 931 TRY 932 { 933 int serverSize = client->serverSize; 934 935 std::vector<CDomain*> domList = getDomains(); 936 std::vector<CAxis*> axisList = getAxis(); 937 938 // Some pre-calculations of global index on each element of current grid. 939 int nbElement = axis_domain_order.numElements(); 940 std::vector<CArray<size_t,1> > globalIndexElement(nbElement); 941 int domainIdx = 0, axisIdx = 0, scalarIdx = 0; 942 std::vector<size_t> elementNGlobal(nbElement); 943 elementNGlobal[0] = 1; 944 size_t globalSize = 1; 945 for (int idx = 0; idx < nbElement; ++idx) 946 { 947 elementNGlobal[idx] = globalSize; 948 size_t elementSize; 949 size_t elementGlobalSize = 1; 950 if (2 == axis_domain_order(idx)) // This is domain 951 { 952 elementSize = domList[domainIdx]->i_index.numElements(); 953 globalIndexElement[idx].resize(elementSize); 954 for (int jdx = 0; jdx < elementSize; ++jdx) 955 { 956 globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx); 957 } 958 elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue(); 959 ++domainIdx; 960 } 961 else if (1 == axis_domain_order(idx)) // This is axis 962 { 963 elementSize = axisList[axisIdx]->index.numElements(); 964 globalIndexElement[idx].resize(elementSize); 965 for (int jdx = 0; jdx < elementSize; ++jdx) 966 { 967 globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx); 968 } 969 elementGlobalSize = axisList[axisIdx]->n_glo.getValue(); 970 ++axisIdx; 971 } 972 else // Of course, this is scalar 973 { 974 globalIndexElement[idx].resize(1); 975 globalIndexElement[idx](0) = 0; 976 elementGlobalSize = 1; 977 } 978 globalSize *= elementGlobalSize; 979 } 980 981 std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false)); 982 std::vector<std::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement); 983 CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server 984 // Number of temporary distributed global index held by each client for each server 985 // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank 986 CArray<int,1> nbIndexOnServerTmp(serverSize); 987 for (int idx = 0; idx < nbElement; ++idx) 988 { 989 nbIndexOnServer = 0; 990 const std::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx]; 991 const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx]; 992 CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm); 993 clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient); 994 const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap(); 995 CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(), 996 ite = globalIndexElementOnServerMap.end(), it; 997 for (it = itb; it != ite; ++it) 998 { 999 const std::vector<int>& tmp = it->second; 1000 nbIndexOnServerTmp = 0; 1001 for (int i = 0; i < tmp.size(); ++i) 1002 { 1003 if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]); 1004 } 1005 nbIndexOnServer += nbIndexOnServerTmp; 1006 } 1007 1008 for (int i = 0; i < serverSize; ++i) 1009 { 1010 if (0 != nbIndexOnServer(i)) 1011 { 1012 globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i)); 1013 elementOnServer[idx][i] = true; 1014 } 1015 } 1016 1017 nbIndexOnServer = 0; 1018 for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j) 1019 { 1020 it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j)); 1021 if (it != ite) 1022 { 1023 const std::vector<int>& tmp = it->second; 1024 nbIndexOnServerTmp = 0; 1025 for (int i = 0; i < tmp.size(); ++i) 1026 { 1027 if (0 == nbIndexOnServerTmp(tmp[i])) 1028 { 1029 globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first; 1030 ++nbIndexOnServerTmp(tmp[i]); 1031 } 1032 } 1033 nbIndexOnServer += nbIndexOnServerTmp; 1034 } 1035 } 1036 } 1037 1038 // Determine server which contain global source index 1039 std::vector<bool> intersectedProc(serverSize, true); 1040 for (int idx = 0; idx < nbElement; ++idx) 1041 { 1042 std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(), 1043 intersectedProc.begin(), intersectedProc.begin(), 1044 std::logical_and<bool>()); 1045 } 1046 1047 std::vector<int> srcRank; 1048 for (int idx = 0; idx < serverSize; ++idx) 1049 { 1050 if (intersectedProc[idx]) srcRank.push_back(idx); 1051 } 1052 1053 // Compute the global index of grid from global index of each element. 1054 for (int i = 0; i < srcRank.size(); ++i) 1055 { 1056 size_t ssize = 1; 1057 int rankSrc = srcRank[i]; 1058 std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement); 1059 std::vector<size_t> currentIndex(nbElement,0); 1060 for (int idx = 0; idx < nbElement; ++idx) 1061 { 1062 ssize *= (globalElementIndexOnServer[idx][rankSrc]).size(); 1063 globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]); 1064 } 1065 globalIndexOnServer[rankSrc].resize(ssize); 1066 1067 std::vector<int> idxLoop(nbElement,0); 1068 int innnerLoopSize = (globalIndexOfElementTmp[0])->size(); 1069 size_t idx = 0; 1070 while (idx < ssize) 1071 { 1072 for (int ind = 0; ind < nbElement; ++ind) 1073 { 1074 if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size()) 1075 { 1076 idxLoop[ind] = 0; 1077 ++idxLoop[ind+1]; 1078 } 1079 1080 currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]]; 1081 } 1082 1083 for (int ind = 0; ind < innnerLoopSize; ++ind) 1084 { 1085 currentIndex[0] = (*globalIndexOfElementTmp[0])[ind]; 1086 size_t globalSrcIndex = 0; 1087 for (int idxElement = 0; idxElement < nbElement; ++idxElement) 1088 { 1089 globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement]; 1090 } 1091 globalIndexOnServer[rankSrc][idx] = globalSrcIndex; 1092 ++idx; 1093 ++idxLoop[0]; 1094 } 1095 } 1096 } 1097 } 1098 CATCH_DUMP_ATTR 1099 //---------------------------------------------------------------- 1100 1101 CGrid* CGrid::createGrid(CDomain* domain) 1102 TRY 1103 { 1104 std::vector<CDomain*> vecDom(1, domain); 1105 std::vector<CAxis*> vecAxis; 1106 1107 return createGrid(vecDom, vecAxis); 1108 } 1109 CATCH 1110 1111 CGrid* CGrid::createGrid(CDomain* domain, CAxis* axis) 1112 TRY 1113 { 1114 std::vector<CDomain*> vecDom(1, domain); 1115 std::vector<CAxis*> vecAxis(1, axis); 1116 1117 return createGrid(vecDom, vecAxis); 1118 } 1119 CATCH 1120 1121 CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 1122 const CArray<int,1>& axisDomainOrder) 1123 TRY 1124 { 1125 std::vector<CScalar*> vecScalar; 1126 return createGrid(generateId(domains, axis, vecScalar, axisDomainOrder), domains, axis, vecScalar, axisDomainOrder); 1127 } 1128 CATCH 1129 1130 CGrid* CGrid::createGrid(const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 1131 const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder) 1132 TRY 1133 { 1134 return createGrid(generateId(domains, axis, scalars, axisDomainOrder), domains, axis, scalars, axisDomainOrder); 1135 } 1136 CATCH 1137 1138 CGrid* CGrid::createGrid(StdString id, const std::vector<CDomain*>& domains, const std::vector<CAxis*>& axis, 1139 const std::vector<CScalar*>& scalars, const CArray<int,1>& axisDomainOrder) 1140 TRY 1141 { 1142 if (axisDomainOrder.numElements() > 0 && axisDomainOrder.numElements() != (domains.size() + axis.size() + scalars.size())) 1143 ERROR("CGrid* CGrid::createGrid(...)", 1144 << "The size of axisDomainOrder (" << axisDomainOrder.numElements() 1145 << ") is not coherent with the number of elements (" << domains.size() + axis.size() <<")."); 1146 1147 CGrid* grid = CGridGroup::get("grid_definition")->createChild(id); 1148 grid->setDomainList(domains); 1149 grid->setAxisList(axis); 1150 grid->setScalarList(scalars); 1151 1152 // By default, domains are always the first elements of a grid 1153 if (0 == axisDomainOrder.numElements()) 1154 { 1155 int size = domains.size() + axis.size() + scalars.size(); 1156 int nb = 0; 1157 grid->axis_domain_order.resize(size); 1158 for (int i = 0; i < size; ++i) 1159 { 1160 if (i < domains.size()) { 1161 grid->axis_domain_order(i) = 2; 1162 1163 } 1164 else if ((scalars.size() < (size-nb)) < size) { 1165 grid->axis_domain_order(i) = 1; 1166 } 1167 else 1168 grid->axis_domain_order(i) = 0; 1169 ++nb; 1170 } 1171 } 1172 else 1173 { 1174 grid->axis_domain_order.resize(axisDomainOrder.numElements()); 1175 grid->axis_domain_order = axisDomainOrder; 1176 } 1177 1178 grid->solveDomainAxisRefInheritance(true); 1179 1180 return grid; 1181 } 1182 CATCH 924 } 925 926 927 bool CGrid::isDataDistributed(void) 928 { 929 return getClientDistribution()->isDataDistributed() ; 930 } 931 932 1183 933 1184 934 CGrid* CGrid::cloneGrid(const StdString& idNewGrid, CGrid* gridSrc) … … 1283 1033 CATCH 1284 1034 1035 1285 1036 //---------------------------------------------------------------- 1286 1037 1287 CDomainGroup* CGrid::getVirtualDomainGroup() const 1288 TRY 1289 { 1290 return this->vDomainGroup_; 1291 } 1292 CATCH 1293 1294 CAxisGroup* CGrid::getVirtualAxisGroup() const 1295 TRY 1296 { 1297 return this->vAxisGroup_; 1298 } 1299 CATCH 1300 1301 CScalarGroup* CGrid::getVirtualScalarGroup() const 1302 TRY 1303 { 1304 return this->vScalarGroup_; 1305 } 1306 CATCH 1307 1308 /* 1309 void CGrid::outputField(int rank, const CArray<double, 1>& stored, double* field) 1310 { 1311 const CArray<size_t,1>& out_i = outIndexFromClient[rank]; 1312 StdSize numElements = stored.numElements(); 1313 for (StdSize n = 0; n < numElements; ++n) 1314 { 1315 field[out_i(n)] = stored(n); 1316 } 1317 } 1318 1319 void CGrid::inputField(int rank, const double* const field, CArray<double,1>& stored) 1320 { 1321 const CArray<size_t,1>& out_i = outIndexFromClient[rank]; 1322 StdSize numElements = stored.numElements(); 1323 for (StdSize n = 0; n < numElements; ++n) 1324 { 1325 stored(n) = field[out_i(n)]; 1326 } 1327 } 1328 1329 void CGrid::outputCompressedField(int rank, const CArray<double,1>& stored, double* field) 1330 { 1331 const CArray<size_t,1>& out_i = compressedOutIndexFromClient[rank]; 1332 StdSize numElements = stored.numElements(); 1333 for (StdSize n = 0; n < numElements; ++n) 1334 { 1335 field[out_i(n)] = stored(n); 1336 } 1337 } 1338 */ 1339 //---------------------------------------------------------------- 1340 1341 void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const 1342 TRY 1343 { 1344 const StdSize size = storeIndex_client.numElements(); 1345 1346 stored.resize(size); 1347 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 1348 } 1349 CATCH 1350 1351 void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const 1352 TRY 1353 { 1354 const StdSize size = storeIndex_client.numElements(); 1355 1356 for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i); 1357 } 1358 CATCH 1359 1360 void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) const 1361 { 1362 const StdSize size = storeIndex_client.numElements(); 1363 stored.resize(size); 1364 const double nanValue = std::numeric_limits<double>::quiet_NaN(); 1365 1366 if (storeMask_client.numElements() != 0) 1367 for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client(i)) ? data[storeIndex_client(i)] : nanValue; 1368 else 1369 for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 1370 } 1371 1372 void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const 1373 TRY 1374 { 1375 const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient(); 1376 const int size = localMaskedDataIndex.size(); 1377 for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i]; 1378 } 1379 CATCH 1380 1381 void CGrid::computeClientIndexScalarGrid() 1382 TRY 1383 { 1384 CContext* context = CContext::getCurrent(); 1385 { 1386 CContextClient* client = context->client; 1387 1388 int rank = client->clientRank; 1389 1390 clientDistribution_ = new CDistributionClient(rank, this); 1391 1392 storeIndex_client.resize(1); 1393 storeIndex_client(0) = 0; 1394 1395 if (0 != serverDistribution_) 1396 { 1397 map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(), 1398 ite = outGlobalIndexFromClient.end(), it; 1399 for (it = itb; it != ite; ++it) 1400 { 1401 int rank = it->first; 1402 CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank]; 1403 outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements()))); 1404 CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank]; 1405 if (1 != globalIndex.numElements()) 1406 ERROR("void CGrid::computeClientIndexScalarGrid()", 1407 << "Something wrong happened. " 1408 << "Number of received global index on scalar grid should equal to 1" 1409 << "Number of received global index " << globalIndex.numElements() << "."); 1410 1411 localIndex(0) = globalIndex(0); 1412 } 1413 } 1414 } 1415 } 1416 CATCH_DUMP_ATTR 1417 1418 void CGrid::computeConnectedClientsScalarGrid() 1419 TRY 1420 { 1421 CContext* context = CContext::getCurrent(); 1422 int nbSrvPools = (context->clientPrimServer.size()==0) ? 1 : context->clientPrimServer.size(); 1423 connectedServerRank_.clear(); 1424 connectedDataSize_.clear(); 1425 nbSenders.clear(); 1426 1427 for (int p = 0; p < nbSrvPools; ++p) 1428 { 1429 CContextClient* client = (context->clientPrimServer.size()==0) ? context->client : context->clientPrimServer[p]; 1430 int receiverSize = client->serverSize; 1431 1432 // connectedServerRank_[client].clear(); 1433 1434 if (connectedServerRank_.find(receiverSize)==connectedServerRank_.end()) 1435 { 1436 if (client->isServerLeader()) 1437 { 1438 const std::list<int>& ranks = client->getRanksServerLeader(); 1439 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1440 { 1441 int rank = *itRank; 1442 int nb = 1; 1443 connectedServerRank_[receiverSize].push_back(rank); 1444 connectedDataSize_[receiverSize][rank] = nb; 1445 nbSenders[receiverSize][rank] = nb; 1446 } 1447 } 1448 else 1449 { 1450 const std::list<int>& ranks = client->getRanksServerNotLeader(); 1451 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1452 { 1453 int rank = *itRank; 1454 int nb = 1; 1455 connectedServerRank_[receiverSize].push_back(rank); 1456 connectedDataSize_[receiverSize][rank] = nb; 1457 nbSenders[receiverSize][rank] = nb; 1458 } 1459 } 1460 } 1461 isDataDistributed_ = false; 1462 } 1463 } 1464 CATCH_DUMP_ATTR 1465 1466 void CGrid::sendIndexScalarGrid() 1467 TRY 1468 { 1469 CContext* context = CContext::getCurrent(); 1470 storeIndex_toSrv.clear(); 1471 std::list<CContextClient*>::iterator it; 1472 1473 for (it=clients.begin(); it!=clients.end(); ++it) 1474 { 1475 CContextClient* client = *it; 1476 int receiverSize = client->serverSize; 1477 1478 CEventClient event(getType(), EVENT_ID_INDEX); 1479 list<CMessage> listMsg; 1480 list<CArray<size_t,1> > listOutIndex; 1481 1482 if (client->isServerLeader()) 1483 { 1484 const std::list<int>& ranks = client->getRanksServerLeader(); 1485 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1486 { 1487 int rank = *itRank; 1488 int nb = 1; 1489 storeIndex_toSrv[client].insert(std::make_pair(rank, CArray<int,1>(nb))); 1490 listOutIndex.push_back(CArray<size_t,1>(nb)); 1491 1492 CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank]; 1493 CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back(); 1494 1495 for (int k = 0; k < nb; ++k) 1496 { 1497 outGlobalIndexOnServer(k) = 0; 1498 outLocalIndexToServer(k) = 0; 1499 } 1500 1501 if (context->hasClient && !context->hasServer) 1502 storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer))); 1503 1504 listMsg.push_back(CMessage()); 1505 listMsg.back() << getId( )<< isDataDistributed_ << isCompressible_ << listOutIndex.back(); 1506 1507 event.push(rank, 1, listMsg.back()); 1508 } 1509 client->sendEvent(event); 1510 } 1511 else 1512 { 1513 const std::list<int>& ranks = client->getRanksServerNotLeader(); 1514 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1515 { 1516 int rank = *itRank; 1517 int nb = 1; 1518 CArray<int, 1> outLocalIndexToServer(nb); 1519 for (int k = 0; k < nb; ++k) 1520 { 1521 outLocalIndexToServer(k) = 0; 1522 } 1523 1524 if (context->hasClient && !context->hasServer) 1525 storeIndex_fromSrv.insert(std::make_pair(rank, CArray<int,1>(outLocalIndexToServer))); 1526 } 1527 client->sendEvent(event); 1528 } 1529 } 1530 } 1531 CATCH_DUMP_ATTR 1532 1533 void CGrid::sendIndex(void) 1534 TRY 1535 { 1536 CContext* context = CContext::getCurrent(); 1537 storeIndex_toSrv.clear(); 1538 std::list<CContextClient*>::iterator it; 1539 1540 for (it=clients.begin(); it!=clients.end(); ++it) 1541 { 1542 CContextClient* client = *it; 1543 int receiverSize = client->serverSize; 1544 1545 CEventClient event(getType(), EVENT_ID_INDEX); 1546 int rank; 1547 list<CMessage> listMsg; 1548 list<CArray<size_t,1> > listOutIndex; 1549 const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer(); 1550 CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex, 1551 iteIndex = globalLocalIndexSendToServer.end(); 1552 itIndex = itbIndex; 1553 1554 if (!doGridHaveDataDistributed(client)) 1555 { 1556 if (client->isServerLeader()) 1557 { 1558 int indexSize = globalLocalIndexSendToServer.size(); 1559 CArray<size_t,1> outGlobalIndexOnServer(indexSize); 1560 CArray<int,1> outLocalIndexToServer(indexSize); 1561 for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx) 1562 { 1563 outGlobalIndexOnServer(idx) = itIndex->first; 1564 outLocalIndexToServer(idx) = itIndex->second; 1565 } 1566 1567 const std::list<int>& ranks = client->getRanksServerLeader(); 1568 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1569 { 1570 storeIndex_toSrv[client].insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer))); 1571 if (context->hasClient && !context->hasServer) 1572 storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer))); 1573 1574 listOutIndex.push_back(CArray<size_t,1>(outGlobalIndexOnServer)); 1575 1576 listMsg.push_back(CMessage()); 1577 listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back(); 1578 1579 event.push(*itRank, 1, listMsg.back()); 1580 } 1581 client->sendEvent(event); 1582 } 1583 else 1584 { 1585 int indexSize = globalLocalIndexSendToServer.size(); 1586 CArray<int,1> outLocalIndexToServer(indexSize); 1587 for (int idx = 0; itIndex != iteIndex; ++itIndex, ++idx) 1588 { 1589 outLocalIndexToServer(idx) = itIndex->second; 1590 } 1591 1592 const std::list<int>& ranks = client->getRanksServerNotLeader(); 1593 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 1594 { 1595 storeIndex_fromSrv.insert(std::make_pair(*itRank, CArray<int,1>(outLocalIndexToServer))); 1596 } 1597 client->sendEvent(event); 1598 } 1599 } 1600 else 1601 { 1602 CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap; 1603 itGlobalMap = globalIndexOnServer_[receiverSize].begin(); 1604 iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 1605 1606 std::map<int,std::vector<int> >localIndexTmp; 1607 std::map<int,std::vector<size_t> > globalIndexTmp; 1608 for (; itGlobalMap != iteGlobalMap; ++itGlobalMap) 1609 { 1610 int serverRank = itGlobalMap->first; 1611 int indexSize = itGlobalMap->second.size(); 1612 const std::vector<size_t>& indexVec = itGlobalMap->second; 1613 for (int idx = 0; idx < indexSize; ++idx) 1614 { 1615 itIndex = globalLocalIndexSendToServer.find(indexVec[idx]); 1616 if (iteIndex != itIndex) 1617 { 1618 globalIndexTmp[serverRank].push_back(itIndex->first); 1619 localIndexTmp[serverRank].push_back(itIndex->second); 1620 } 1621 } 1622 } 1623 1624 for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns) 1625 { 1626 rank = connectedServerRank_[receiverSize][ns]; 1627 int nb = 0; 1628 if (globalIndexTmp.end() != globalIndexTmp.find(rank)) 1629 nb = globalIndexTmp[rank].size(); 1630 1631 storeIndex_toSrv[client].insert(make_pair(rank, CArray<int,1>(nb))); 1632 listOutIndex.push_back(CArray<size_t,1>(nb)); 1633 1634 CArray<int, 1>& outLocalIndexToServer = storeIndex_toSrv[client][rank]; 1635 CArray<size_t, 1>& outGlobalIndexOnServer = listOutIndex.back(); 1636 1637 for (int k = 0; k < nb; ++k) 1638 { 1639 outGlobalIndexOnServer(k) = globalIndexTmp[rank].at(k); 1640 outLocalIndexToServer(k) = localIndexTmp[rank].at(k); 1641 } 1642 1643 storeIndex_fromSrv.insert(make_pair(rank, CArray<int,1>(outLocalIndexToServer))); 1644 listMsg.push_back(CMessage()); 1645 listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back(); 1646 1647 event.push(rank, nbSenders[receiverSize][rank], listMsg.back()); 1648 } 1649 1650 client->sendEvent(event); 1651 } 1652 } 1653 } 1654 CATCH_DUMP_ATTR 1655 1656 void CGrid::recvIndex(CEventServer& event) 1657 TRY 1658 { 1659 string gridId; 1660 vector<int> ranks; 1661 vector<CBufferIn*> buffers; 1662 1663 list<CEventServer::SSubEvent>::iterator it; 1664 for (it = event.subEvents.begin(); it != event.subEvents.end(); ++it) 1665 { 1666 ranks.push_back(it->rank); 1667 CBufferIn* buffer = it->buffer; 1668 *buffer >> gridId; 1669 buffers.push_back(buffer); 1670 } 1671 get(gridId)->recvIndex(ranks, buffers); 1672 } 1673 CATCH 1674 1675 void CGrid::recvIndex(vector<int> ranks, vector<CBufferIn*> buffers) 1676 TRY 1677 { 1678 CContext* context = CContext::getCurrent(); 1679 connectedServerRankRead_ = ranks; 1680 1681 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; 1682 nbSrvPools = 1; 1683 nbReadSenders.clear(); 1684 for (int p = 0; p < nbSrvPools; ++p) 1685 { 1686 CContextServer* server = (!context->hasClient) ? context->server : context->serverPrimServer[p]; 1687 CContextClient* client = context->client; //(!context->hasClient) ? context->client : context->clientPrimServer[p]; 1688 1689 int idx = 0, numElement = axis_domain_order.numElements(); 1690 int ssize = numElement; 1691 std::vector<int> indexMap(numElement); 1692 for (int i = 0; i < numElement; ++i) 1693 { 1694 indexMap[i] = idx; 1695 if (2 == axis_domain_order(i)) 1696 { 1697 ++ssize; 1698 idx += 2; 1699 } 1700 else 1701 ++idx; 1702 } 1703 1704 for (int n = 0; n < ranks.size(); n++) 1705 { 1706 int rank = ranks[n]; 1707 CBufferIn& buffer = *buffers[n]; 1708 1709 buffer >> isDataDistributed_ >> isCompressible_; 1710 size_t dataSize = 0; 1711 1712 if (0 == serverDistribution_) 1713 { 1714 int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1; 1715 std::vector<CDomain*> domainList = getDomains(); 1716 std::vector<CAxis*> axisList = getAxis(); 1717 std::vector<int> nBegin(ssize), nSize(ssize), nGlob(ssize), nBeginGlobal(ssize), nGlobElement(numElement); 1718 std::vector<CArray<int,1> > globalIndex(numElement); 1719 for (int i = 0; i < numElement; ++i) 1720 { 1721 nGlobElement[i] = globalSize; 1722 if (2 == axis_domain_order(i)) //domain 1723 { 1724 nBegin[indexMap[i]] = domainList[domainId]->ibegin; 1725 nSize[indexMap[i]] = domainList[domainId]->ni; 1726 nBeginGlobal[indexMap[i]] = 0; 1727 nGlob[indexMap[i]] = domainList[domainId]->ni_glo; 1728 1729 nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin; 1730 nSize[indexMap[i] + 1] = domainList[domainId]->nj; 1731 nBeginGlobal[indexMap[i] + 1] = 0; 1732 nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo; 1733 1734 { 1735 int count = 0; 1736 globalIndex[i].resize(nSize[indexMap[i]]*nSize[indexMap[i]+1]); 1737 for (int jdx = 0; jdx < nSize[indexMap[i]+1]; ++jdx) 1738 for (int idx = 0; idx < nSize[indexMap[i]]; ++idx) 1739 { 1740 globalIndex[i](count) = (nBegin[indexMap[i]] + idx) + (nBegin[indexMap[i]+1] + jdx) * nGlob[indexMap[i]]; 1741 ++count; 1742 } 1743 } 1744 1745 ++domainId; 1746 } 1747 else if (1 == axis_domain_order(i)) // axis 1748 { 1749 nBegin[indexMap[i]] = axisList[axisId]->begin; 1750 nSize[indexMap[i]] = axisList[axisId]->n; 1751 nBeginGlobal[indexMap[i]] = 0; 1752 nGlob[indexMap[i]] = axisList[axisId]->n_glo; 1753 globalIndex[i].resize(nSize[indexMap[i]]); 1754 for (int idx = 0; idx < nSize[indexMap[i]]; ++idx) 1755 globalIndex[i](idx) = nBegin[indexMap[i]] + idx; 1756 1757 ++axisId; 1758 } 1759 else // scalar 1760 { 1761 nBegin[indexMap[i]] = 0; 1762 nSize[indexMap[i]] = 1; 1763 nBeginGlobal[indexMap[i]] = 0; 1764 nGlob[indexMap[i]] = 1; 1765 globalIndex[i].resize(1); 1766 globalIndex[i](0) = 0; 1767 ++scalarId; 1768 } 1769 } 1770 dataSize = 1; 1771 1772 for (int i = 0; i < nSize.size(); ++i) 1773 dataSize *= nSize[i]; 1774 serverDistribution_ = new CDistributionServer(server->intraCommRank, 1775 globalIndex, axis_domain_order, 1776 nBegin, nSize, nBeginGlobal, nGlob); 1777 } 1778 1779 CArray<size_t,1> outIndex; 1780 buffer >> outIndex; 1781 outGlobalIndexFromClient.insert(std::make_pair(rank, outIndex)); 1782 connectedDataSizeRead_[rank] = outIndex.numElements(); 1783 1784 if (doGridHaveDataDistributed(client)) 1785 {} 1786 else 1787 { 1788 // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER 1789 // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar) 1790 dataSize = serverDistribution_->getGridSize(); 1791 } 1792 writtenDataSize_ += dataSize; 1793 } 1794 1795 1796 // Compute mask of the current grid 1797 { 1798 int axisId = 0, domainId = 0, scalarId = 0, globalSize = 1; 1799 std::vector<CDomain*> domainList = getDomains(); 1800 std::vector<CAxis*> axisList = getAxis(); 1801 int dimSize = 2 * domainList.size() + axisList.size(); 1802 std::vector<int> nBegin(dimSize), nSize(dimSize), nGlob(dimSize), nBeginGlobal(dimSize); 1803 for (int i = 0; i < numElement; ++i) 1804 { 1805 if (2 == axis_domain_order(i)) //domain 1806 { 1807 nBegin[indexMap[i]] = domainList[domainId]->ibegin; 1808 nSize[indexMap[i]] = domainList[domainId]->ni; 1809 nBeginGlobal[indexMap[i]] = 0; 1810 nGlob[indexMap[i]] = domainList[domainId]->ni_glo; 1811 1812 nBegin[indexMap[i] + 1] = domainList[domainId]->jbegin; 1813 nSize[indexMap[i] + 1] = domainList[domainId]->nj; 1814 nBeginGlobal[indexMap[i] + 1] = 0; 1815 nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo; 1816 1817 ++domainId; 1818 } 1819 else if (1 == axis_domain_order(i)) // axis 1820 { 1821 nBegin[indexMap[i]] = axisList[axisId]->begin; 1822 nSize[indexMap[i]] = axisList[axisId]->n; 1823 nBeginGlobal[indexMap[i]] = 0; 1824 nGlob[indexMap[i]] = axisList[axisId]->n_glo; 1825 ++axisId; 1826 } 1827 else // scalar 1828 { 1829 } 1830 } 1831 1832 if (nSize.empty()) // Scalar grid 1833 { 1834 nBegin.push_back(0); 1835 nSize.push_back(1); 1836 nBeginGlobal.push_back(0); 1837 nGlob.push_back(1); 1838 } 1839 } 1840 1841 if (isScalarGrid()) return; 1842 1843 nbReadSenders[client] = CClientServerMappingDistributed::computeConnectedClients(context->client->serverSize, context->client->clientSize, context->client->intraComm, ranks); 1844 } 1845 } 1846 CATCH_DUMP_ATTR 1847 1038 1039 1040 1848 1041 /* 1849 1042 Compute on the fly the global dimension of a grid with its elements … … 1938 1131 TRY 1939 1132 { 1940 return (0 != writtenDataSize_);1133 return (0 != getGridLocalElements()->getView(CElementView::FULL)->getSize()); 1941 1134 } 1942 1135 CATCH_DUMP_ATTR 1943 1136 1944 /*! 1945 Return size of data which is written on each server 1946 Whatever dimension of a grid, data which are written on server must be presented as 1947 an one dimension array. 1948 \return size of data written on server 1949 */ 1950 size_t CGrid::getWrittenDataSize() const 1951 TRY 1952 { 1953 return writtenDataSize_; 1954 } 1955 CATCH 1956 1957 /*! 1958 Returns the number of indexes written by each server. 1959 \return the number of indexes written by each server 1960 */ 1961 int CGrid::getNumberWrittenIndexes() const 1962 TRY 1963 { 1964 return numberWrittenIndexes_; 1965 } 1966 CATCH 1967 1968 /*! 1969 Returns the total number of indexes written by the servers. 1970 \return the total number of indexes written by the servers 1971 */ 1972 int CGrid::getTotalNumberWrittenIndexes() const 1973 TRY 1974 { 1975 return totalNumberWrittenIndexes_; 1976 } 1977 CATCH 1978 1979 /*! 1980 Returns the offset of indexes written by each server. 1981 \return the offset of indexes written by each server 1982 */ 1983 int CGrid::getOffsetWrittenIndexes() const 1984 TRY 1985 { 1986 return offsetWrittenIndexes_; 1987 } 1988 CATCH 1989 1990 CDistributionServer* CGrid::getDistributionServer() 1991 TRY 1992 { 1993 return serverDistribution_; 1994 } 1995 CATCH_DUMP_ATTR 1996 1997 CDistributionClient* CGrid::getDistributionClient() 1998 TRY 1999 { 2000 return clientDistribution_; 2001 } 2002 CATCH_DUMP_ATTR 2003 1137 2004 1138 bool CGrid::doGridHaveDataDistributed(CContextClient* client) 2005 1139 TRY 2006 1140 { 1141 // This function is now useless because it will return false only if server and client size are equal to 1 1142 // to be seriously check in future 1143 2007 1144 if (isScalarGrid()) return false; 2008 1145 else if (0 != client) 2009 1146 { 2010 return (isDataDistributed _|| (1 != client->clientSize) || (1 != client->serverSize));1147 return (isDataDistributed() || (1 != client->clientSize) || (1 != client->serverSize)); 2011 1148 } 2012 1149 else 2013 return isDataDistributed _;1150 return isDataDistributed(); 2014 1151 } 2015 1152 CATCH_DUMP_ATTR … … 2031 1168 switch(event.type) 2032 1169 { 2033 case EVENT_ID_INDEX :2034 recvIndex(event);2035 return true;2036 break;2037 2038 1170 case EVENT_ID_ADD_DOMAIN : 2039 1171 recvAddDomain(event); … … 2050 1182 return true; 2051 1183 break; 1184 1185 case EVENT_ID_SEND_MASK : 1186 recvMask(event); 1187 return true; 1188 break; 2052 1189 default : 2053 ERROR("bool C Domain::dispatchEvent(CEventServer& event)",1190 ERROR("bool CGrid::dispatchEvent(CEventServer& event)", 2054 1191 << "Unknown Event"); 2055 1192 return false; … … 2059 1196 CATCH 2060 1197 2061 ///--------------------------------------------------------------- 2062 2063 CDomain* CGrid::addDomain(const std::string& id) 2064 TRY 2065 { 2066 order_.push_back(2); 2067 axis_domain_order.resize(order_.size()); 2068 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 2069 return vDomainGroup_->createChild(id); 2070 } 2071 CATCH_DUMP_ATTR 2072 2073 CAxis* CGrid::addAxis(const std::string& id) 2074 TRY 2075 { 2076 order_.push_back(1); 2077 axis_domain_order.resize(order_.size()); 2078 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 2079 return vAxisGroup_->createChild(id); 2080 } 2081 CATCH_DUMP_ATTR 2082 2083 CScalar* CGrid::addScalar(const std::string& id) 2084 TRY 2085 { 2086 order_.push_back(0); 2087 axis_domain_order.resize(order_.size()); 2088 for (int idx = 0; idx < order_.size(); ++idx) axis_domain_order(idx)=order_[idx]; 2089 return vScalarGroup_->createChild(id); 2090 } 2091 CATCH_DUMP_ATTR 2092 2093 //! Change virtual field group to a new one 2094 void CGrid::setVirtualDomainGroup(CDomainGroup* newVDomainGroup) 2095 TRY 2096 { 2097 this->vDomainGroup_ = newVDomainGroup; 2098 } 2099 CATCH_DUMP_ATTR 2100 2101 //! Change virtual variable group to new one 2102 void CGrid::setVirtualAxisGroup(CAxisGroup* newVAxisGroup) 2103 TRY 2104 { 2105 this->vAxisGroup_ = newVAxisGroup; 2106 } 2107 CATCH_DUMP_ATTR 2108 2109 //! Change virtual variable group to new one 2110 void CGrid::setVirtualScalarGroup(CScalarGroup* newVScalarGroup) 2111 TRY 2112 { 2113 this->vScalarGroup_ = newVScalarGroup; 2114 } 2115 CATCH_DUMP_ATTR 1198 1199 1200 void CGrid::sendGridToFileServer(CContextClient* client) 1201 { 1202 if (sendGridToFileServer_done_.count(client)!=0) return ; 1203 else sendGridToFileServer_done_.insert(client) ; 1204 1205 StdString gridDefRoot("grid_definition"); 1206 CGridGroup* gridPtr = CGridGroup::get(gridDefRoot); 1207 gridPtr->sendCreateChild(this->getId(),client); 1208 this->sendAllAttributesToServer(client); 1209 distributeGridToFileServer(client) ; 1210 } 1211 1212 1213 void CGrid::distributeGridToFileServer(CContextClient* client) 1214 { 1215 CContext* context = CContext::getCurrent(); 1216 // simple Distribution for now 1217 // distribute over the fisrt element except if it is a scalar 1218 auto& elements = getElements() ; 1219 int posDistributed = 0 ; 1220 for(auto& element : elements) 1221 { 1222 if (element.type==TYPE_DOMAIN) break ; 1223 else if (element.type==TYPE_AXIS) break ; 1224 else if (element.type==TYPE_SCALAR) posDistributed++ ; 1225 } 1226 1227 vector<CLocalView*> localViews ; 1228 vector<CDistributedView*> remoteViews ; 1229 1230 for(int i=0 ; i<elements.size() ; i++) 1231 { 1232 if (elements[i].type==TYPE_DOMAIN) 1233 { 1234 CDomain* domain = (CDomain*) elements[i].ptr ; 1235 domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1236 remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ; 1237 localViews.push_back(domain->getLocalView(CElementView::FULL)) ; 1238 } 1239 else if (elements[i].type==TYPE_AXIS) 1240 { 1241 CAxis* axis = (CAxis*) elements[i].ptr ; 1242 axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1243 remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ; 1244 localViews.push_back(axis->getLocalView(CElementView::FULL)) ; 1245 } 1246 else if (elements[i].type==TYPE_SCALAR) 1247 { 1248 CScalar* scalar = (CScalar*) elements[i].ptr ; 1249 scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1250 remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ; 1251 localViews.push_back(scalar->getLocalView(CElementView::FULL)) ; 1252 } 1253 } 1254 CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm(), client->getRemoteSize()) ; 1255 gridRemoteConnector.computeConnector() ; 1256 1257 vector<CScattererConnector*> scattererConnectors ; 1258 CScattererConnector* scattererConnector; 1259 for(int i=0 ; i<elements.size() ; i++) 1260 { 1261 if (elements[i].type==TYPE_DOMAIN) 1262 { 1263 CDomain* domain = (CDomain*) elements[i].ptr ; 1264 sendAddDomain(domain->getId(),client) ; 1265 domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i), scattererConnector) ; 1266 scattererConnectors.push_back(scattererConnector) ; 1267 } 1268 else if (elements[i].type==TYPE_AXIS) 1269 { 1270 CAxis* axis = (CAxis*) elements[i].ptr ; 1271 sendAddAxis(axis->getId(),client) ; 1272 axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i), scattererConnector) ; 1273 scattererConnectors.push_back(scattererConnector) ; 1274 } 1275 else if (elements[i].type==TYPE_SCALAR) 1276 { 1277 CScalar* scalar = (CScalar*) elements[i].ptr ; 1278 sendAddScalar(scalar->getId(),client) ; 1279 scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i), scattererConnector) ; 1280 scattererConnectors.push_back(scattererConnector) ; 1281 } 1282 } 1283 1284 CGridScattererConnector gridScattererConnector(scattererConnectors) ; 1285 CGridLocalConnector* workflowToFull = getGridLocalElements()->getConnector(CElementView::WORKFLOW, CElementView::FULL) ; 1286 CArray<bool,1> maskIn(workflowToFull->getSrcSize()) ; 1287 CArray<bool,1> maskOut(workflowToFull->getDstSize()) ; 1288 maskIn = true ; 1289 workflowToFull->transfer(maskIn,maskOut,false) ; 1290 1291 CEventClient event(getType(), EVENT_ID_SEND_MASK); 1292 CMessage message ; 1293 message<<getId() ; 1294 gridScattererConnector.transfer(maskOut, client, event, message) ; 1295 for(auto& it : scattererConnectors) delete it ; 1296 1297 vector<CScattererConnector*> clientToServerConnectors ; 1298 vector<CGathererConnector*> clientFromServerConnectors ; 1299 for(auto& element : elements) 1300 { 1301 if (element.type==TYPE_DOMAIN) 1302 { 1303 clientToServerConnectors.push_back(element.domain->getClientToServerConnector(client)) ; 1304 clientFromServerConnectors.push_back(element.domain->getClientFromServerConnector(client)) ; 1305 } 1306 else if (element.type==TYPE_AXIS) 1307 { 1308 clientToServerConnectors.push_back(element.axis->getClientToServerConnector(client)) ; 1309 clientFromServerConnectors.push_back(element.axis->getClientFromServerConnector(client)) ; 1310 1311 } 1312 else if (element.type==TYPE_SCALAR) 1313 { 1314 clientToServerConnectors.push_back(element.scalar->getClientToServerConnector(client)) ; 1315 clientFromServerConnectors.push_back(element.scalar->getClientFromServerConnector(client)) ; 1316 } 1317 } 1318 1319 // compute the grid clientToServerConnector to send flux from client to servers 1320 clientToServerConnector_[client] = new CGridScattererConnector(clientToServerConnectors) ; 1321 clientFromServerConnector_[client] = new CGridGathererConnector(clientFromServerConnectors) ; 1322 1323 1324 } 1325 1326 void CGrid::recvMask(CEventServer& event) 1327 { 1328 string gridId; 1329 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> gridId ; 1330 get(gridId)->receiveMask(event); 1331 } 1332 1333 void CGrid::receiveMask(CEventServer& event) 1334 { 1335 vector<CGathererConnector*> gathererConnectors ; 1336 vector<CLocalView*> fullViews ; 1337 1338 for(auto& element : getElements()) 1339 { 1340 if (element.type==TYPE_DOMAIN) 1341 { 1342 gathererConnectors.push_back(element.domain->getGathererConnector()); 1343 fullViews.push_back(element.domain->getLocalElement()->getView(CElementView::FULL)); 1344 1345 } 1346 else if (element.type==TYPE_AXIS) 1347 { 1348 gathererConnectors.push_back(element.axis->getGathererConnector()); 1349 fullViews.push_back(element.axis->getLocalElement()->getView(CElementView::FULL)); 1350 } 1351 else if (element.type==TYPE_SCALAR) 1352 { 1353 gathererConnectors.push_back(element.scalar->getGathererConnector()); 1354 fullViews.push_back(element.scalar->getLocalElement()->getView(CElementView::FULL)); 1355 } 1356 } 1357 CGridGathererConnector gridGathererConnector(gathererConnectors) ; 1358 CGridMaskConnector gridMaskConnector(fullViews) ; 1359 1360 CArray<bool,1> maskOut ; 1361 gridGathererConnector.transfer_or(event,maskOut) ; 1362 gridMaskConnector.computeConnector(maskOut) ; 1363 1364 CContextClient* client = event.getContextServer()->getAssociatedClient() ; 1365 int i=0 ; 1366 for(auto& element : getElements()) 1367 { 1368 if (element.type==TYPE_DOMAIN) element.domain->setServerMask(gridMaskConnector.getElementMask(i),client); 1369 else if (element.type==TYPE_AXIS) element.axis->setServerMask(gridMaskConnector.getElementMask(i),client); 1370 else if (element.type==TYPE_SCALAR) element.scalar->setServerMask(gridMaskConnector.getElementMask(i),client); 1371 i++ ; 1372 } 1373 } 1374 1375 1376 void CGrid::sendGridToCouplerOut(CContextClient* client, const string& fieldId) 1377 { 1378 /* if (sendGridToCouplerOut_done_.count(client)!=0) return ; 1379 else sendGridToCouplerOut_done_.insert(client) ; 1380 1381 CContext* context = CContext::getCurrent(); 1382 // simple Distribution for now 1383 // distribute over the fisrt element except if it is a scalar 1384 auto& elements = getElements() ; 1385 int posDistributed = 0 ; 1386 for(auto& element : elements) 1387 { 1388 if (element.type==TYPE_DOMAIN) break ; 1389 else if (element.type==TYPE_AXIS) break ; 1390 else if (element.type==TYPE_SCALAR) posDistributed++ ; 1391 } 1392 1393 vector<CLocalView*> localViews ; 1394 vector<CDistributedView*> remoteViews ; 1395 1396 for(int i=0 ; i<elements.size() ; i++) 1397 { 1398 if (elements[i].type==TYPE_DOMAIN) 1399 { 1400 CDomain* domain = (CDomain*) elements[i].ptr ; 1401 domain->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1402 remoteViews.push_back(domain->getRemoteElement(client)->getView(CElementView::FULL)) ; 1403 localViews.push_back(domain->getLocalView(CElementView::FULL)) ; 1404 } 1405 else if (elements[i].type==TYPE_AXIS) 1406 { 1407 CAxis* axis = (CAxis*) elements[i].ptr ; 1408 axis->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1409 remoteViews.push_back(axis->getRemoteElement(client)->getView(CElementView::FULL)) ; 1410 localViews.push_back(axis->getLocalView(CElementView::FULL)) ; 1411 } 1412 else if (elements[i].type==TYPE_SCALAR) 1413 { 1414 CScalar* scalar = (CScalar*) elements[i].ptr ; 1415 scalar->computeRemoteElement(client, posDistributed==i ? EDistributionType::BANDS : EDistributionType::NONE) ; 1416 remoteViews.push_back(scalar->getRemoteElement(client)->getView(CElementView::FULL)) ; 1417 localViews.push_back(scalar->getLocalView(CElementView::FULL)) ; 1418 } 1419 } 1420 CGridRemoteConnector gridRemoteConnector(localViews, remoteViews, context->getIntraComm(), client->getRemoteSize()) ; 1421 gridRemoteConnector.computeConnector() ; 1422 1423 vector<CScattererConnector*> clientToClientConnectors ; 1424 for(int i=0 ; i<elements.size() ; i++) 1425 { 1426 if (elements[i].type==TYPE_DOMAIN) 1427 { 1428 CDomain* domain = (CDomain*) elements[i].ptr ; 1429 sendAddDomain(domain->getId(),client) ; 1430 domain->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ; 1431 clientToClientConnectors.push_back(domain->getClientToServerConnector(client)) ; 1432 } 1433 else if (elements[i].type==TYPE_AXIS) 1434 { 1435 CAxis* axis = (CAxis*) elements[i].ptr ; 1436 sendAddAxis(axis->getId(),client) ; 1437 axis->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ; 1438 clientToClientConnectors.push_back(axis->getClientToServerConnector(client)) ; 1439 } 1440 else if (elements[i].type==TYPE_SCALAR) 1441 { 1442 CScalar* scalar = (CScalar*) elements[i].ptr ; 1443 sendAddScalar(scalar->getId(),client) ; 1444 scalar->distributeToServer(client, gridRemoteConnector.getDistributedGlobalIndex(i)) ; 1445 clientToClientConnectors.push_back(scalar->getClientToServerConnector(client)) ; 1446 } 1447 } 1448 1449 // compute the grid clientToServerConnector to send flux from client to servers 1450 clientToClientConnector_[client] = new CGridScattererConnector(clientToClientConnectors) ;*/ 1451 } 1452 1453 void CGrid::makeAliasForCoupling(const string& fieldId) 1454 { 1455 string gridId="_grid_of_"+fieldId ; 1456 createAlias(gridId) ; 1457 1458 const auto& domVect = getDomains() ; 1459 for (int pos=0; pos<domVect.size();pos++) domVect[pos]->makeAliasForCoupling(fieldId, pos); 1460 1461 const auto& axisVect=getAxis() ; 1462 for (int pos=0; pos<axisVect.size();pos++) axisVect[pos]->makeAliasForCoupling(fieldId, pos); 1463 1464 const auto& scalVect=getScalars() ; 1465 for (int pos=0; pos<scalVect.size();pos++) scalVect[pos]->makeAliasForCoupling(fieldId, pos); 1466 } 2116 1467 2117 1468 /*! … … 2119 1470 \param[in] id String identity of domain that will be created on server 2120 1471 */ 2121 void CGrid::sendAddDomain(const string& id )2122 TRY 2123 { 2124 sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN );1472 void CGrid::sendAddDomain(const string& id, CContextClient* contextClient) 1473 TRY 1474 { 1475 sendAddItem(id, (int)EVENT_ID_ADD_DOMAIN, contextClient); 2125 1476 } 2126 1477 CATCH_DUMP_ATTR … … 2130 1481 \param[in] id String identity of axis that will be created on server 2131 1482 */ 2132 void CGrid::sendAddAxis(const string& id )2133 TRY 2134 { 2135 sendAddItem(id, (int)EVENT_ID_ADD_AXIS );1483 void CGrid::sendAddAxis(const string& id, CContextClient* contextClient) 1484 TRY 1485 { 1486 sendAddItem(id, (int)EVENT_ID_ADD_AXIS, contextClient); 2136 1487 } 2137 1488 CATCH_DUMP_ATTR … … 2141 1492 \param[in] id String identity of scalar that will be created on server 2142 1493 */ 2143 void CGrid::sendAddScalar(const string& id )2144 TRY 2145 { 2146 sendAddItem(id, (int)EVENT_ID_ADD_SCALAR );1494 void CGrid::sendAddScalar(const string& id, CContextClient* contextClient) 1495 TRY 1496 { 1497 sendAddItem(id, (int)EVENT_ID_ADD_SCALAR, contextClient); 2147 1498 } 2148 1499 CATCH_DUMP_ATTR … … 2231 1582 } 2232 1583 CATCH_DUMP_ATTR 1584 1585 /*! 1586 \brief Check if all elements of the grid are complete 1587 Before make any grid processing, we must be sure that all grid information elements have 1588 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 1589 other context (coupling) 1590 */ 1591 bool CGrid::isCompleted(void) 1592 { 1593 setDomainList(); 1594 for (auto domainId : domList_) if (!CDomain::get(domainId)->isCompleted()) return false ; 1595 setAxisList() ; 1596 for (auto axisId : axisList_) if (!CAxis::get(axisId)->isCompleted()) return false ; 1597 setScalarList() ; 1598 for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->isCompleted()) return false ; 1599 return true ; 1600 } 1601 1602 /*! 1603 \brief impose that all elements of the grid are complete 1604 Before make any grid processing, we must be sure that all grid information elements have 1605 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 1606 other context (coupling) 1607 */ 1608 void CGrid::setCompleted(void) 1609 { 1610 setDomainList(); 1611 for (auto domainId : domList_) CDomain::get(domainId)->setCompleted() ; 1612 setAxisList() ; 1613 for (auto axisId : axisList_) CAxis::get(axisId)->setCompleted() ; 1614 setScalarList() ; 1615 for (auto scalarId : scalarList_) CScalar::get(scalarId)->setCompleted() ; 1616 } 1617 1618 /*! 1619 \brief impose that all elements of the grid are incomplete 1620 Before make any grid processing, we must be sure that all grid information elements have 1621 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 1622 other context (coupling) 1623 */ 1624 void CGrid::unsetCompleted(void) 1625 { 1626 setDomainList(); 1627 for (auto domainId : domList_) CDomain::get(domainId)->unsetCompleted() ; 1628 setAxisList() ; 1629 for (auto axisId : axisList_) CAxis::get(axisId)->unsetCompleted() ; 1630 setScalarList() ; 1631 for (auto scalarId : scalarList_) CScalar::get(scalarId)->unsetCompleted() ; 1632 } 2233 1633 2234 1634 /*! … … 2238 1638 \param[in] apply inherit all attributes of parents (true) 2239 1639 */ 2240 void CGrid::solveDomainAxisRefInheritance(bool apply) 2241 TRY 2242 { 2243 CContext* context = CContext::getCurrent(); 2244 unsigned int vecSize, i; 2245 std::vector<StdString>::iterator it, itE; 1640 void CGrid::solveElementsRefInheritance(bool apply) 1641 TRY 1642 { 2246 1643 setDomainList(); 2247 it = domList_.begin(); itE = domList_.end(); 2248 for (; it != itE; ++it) 2249 { 2250 CDomain* pDom = CDomain::get(*it); 2251 if (context->hasClient && !context->hasServer) 2252 { 2253 pDom->solveRefInheritance(apply); 2254 pDom->solveInheritanceTransformation(); 2255 } 1644 for (auto domainId : domList_) 1645 { 1646 CDomain* pDom = CDomain::get(domainId); 1647 pDom->solveRefInheritance(apply); 1648 pDom->solveInheritanceTransformation(); 2256 1649 } 2257 1650 2258 1651 setAxisList(); 2259 it = axisList_.begin(); itE = axisList_.end(); 2260 for (; it != itE; ++it) 2261 { 2262 CAxis* pAxis = CAxis::get(*it); 2263 if (context->hasClient && !context->hasServer) 2264 { 2265 pAxis->solveRefInheritance(apply); 2266 pAxis->solveInheritanceTransformation(); 2267 } 1652 for (auto axisId : axisList_) 1653 { 1654 CAxis* pAxis = CAxis::get(axisId); 1655 pAxis->solveRefInheritance(apply); 1656 pAxis->solveInheritanceTransformation(); 2268 1657 } 2269 1658 2270 1659 setScalarList(); 2271 it = scalarList_.begin(); itE = scalarList_.end(); 2272 for (; it != itE; ++it) 2273 { 2274 CScalar* pScalar = CScalar::get(*it); 2275 if (context->hasClient && !context->hasServer) 2276 { 2277 pScalar->solveRefInheritance(apply); 2278 pScalar->solveInheritanceTransformation(); 2279 } 1660 for (auto scalarId : scalarList_) 1661 { 1662 CScalar* pScalar = CScalar::get(scalarId); 1663 pScalar->solveRefInheritance(apply); 1664 pScalar->solveInheritanceTransformation(); 2280 1665 } 2281 1666 } 2282 1667 CATCH_DUMP_ATTR 2283 1668 2284 bool CGrid::isTransformed() 2285 TRY 2286 { 2287 return isTransformed_; 1669 /*! 1670 \brief check attributes of all elements of the grid 1671 */ 1672 void CGrid::checkElementsAttributes(void) 1673 TRY 1674 { 1675 setDomainList(); 1676 for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes(); 1677 1678 setAxisList(); 1679 for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes(); 1680 1681 setScalarList(); 1682 for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes(); 2288 1683 } 2289 1684 CATCH_DUMP_ATTR 2290 1685 2291 void CGrid::setTransformed() 2292 TRY 2293 { 2294 isTransformed_ = true; 1686 1687 1688 //********************************************************** 1689 //************** New transformation method ************** 1690 //********************************************************** 1691 1692 std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > 1693 CGrid::buildTransformationGraph(CGarbageCollector& gc, bool isSource, CGrid* gridSrc, double detectMissingValues, double defaultValue, CGrid*& newGrid, bool graphEnabled) 1694 TRY 1695 { 1696 registerAlgorithmTransformation() ; // needed to enable self-registration of the transformations 1697 // big mystery why it doesn't work witout that... 1698 // problem with the linker ?? 1699 1700 std::shared_ptr<CFilter> inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc)); 1701 std::shared_ptr<CFilter> outputFilter = inputFilter ; 1702 1703 1704 string newId ; 1705 if (gridSrc!=nullptr) newId = gridSrc->getId() + " --> " + this->getId() ; 1706 else newId = " --> " + this->getId() ; 1707 bool isNewGrid ; 1708 if (CGrid::has(newId)) 1709 { 1710 cout<<"Retrive existing grid : "<<newId<<endl ; 1711 newGrid = CGrid::get(newId); 1712 isNewGrid = false ; 1713 } 1714 else 1715 { 1716 cout<<"Create new grid : "<<newId<<endl ; 1717 newGrid = CGrid::create(newId) ; 1718 isNewGrid = true ; 1719 } 1720 1721 bool hadTransform=false ; 1722 bool hasTransform=false ; 1723 bool hasRemainTransform=false ; 1724 CGenericAlgorithmTransformation* algo ; 1725 int pos ; 1726 1727 for(int i=0 ; i<elements_.size(); i++) 1728 { 1729 CTransformationPaths transformationPath ; 1730 auto dstElement = elements_[i] ; 1731 1732 if (dstElement.type==TYPE_DOMAIN) transformationPath = dstElement.domain->getTransformationPaths() ; 1733 else if (dstElement.type==TYPE_AXIS) transformationPath = dstElement.axis->getTransformationPaths() ; 1734 else if (dstElement.type==TYPE_SCALAR) transformationPath = dstElement.scalar->getTransformationPaths() ; 1735 1736 SElement srcElement ; 1737 if (gridSrc==nullptr) srcElement = this->elements_[i] ; 1738 else srcElement = gridSrc->elements_[i] ; 1739 1740 if (gridSrc==nullptr) transformationPath.mergePaths() ; 1741 else 1742 { 1743 if (srcElement.type==TYPE_DOMAIN) transformationPath.mergePaths(srcElement.domain->getTransformationPaths()) ; 1744 else if (srcElement.type==TYPE_AXIS) transformationPath.mergePaths(srcElement.axis->getTransformationPaths()) ; 1745 else if (srcElement.type==TYPE_SCALAR) transformationPath.mergePaths(srcElement.scalar->getTransformationPaths()) ; 1746 } 1747 1748 hasTransform=transformationPath.hasTransform() ; 1749 1750 if (hasTransform && !hadTransform) 1751 { 1752 pos=i ; 1753 EElement dstElementType=transformationPath.getNextElementType() ; 1754 string dstElementId=transformationPath.getNextElementId() ; 1755 string srcElementId=transformationPath.getNextElementSrcId() ; 1756 auto transType = transformationPath.getNextTransformationType() ; 1757 auto transId = transformationPath.getNextTransformationId() ; 1758 1759 CGrid* tmpGridSrc=CGrid::create(); // source grid 1760 if (srcElement.type==TYPE_DOMAIN) tmpGridSrc->addDomain(srcElement.domain->getId()) ; 1761 else if (srcElement.type==TYPE_AXIS) tmpGridSrc->addAxis(srcElement.axis->getId()) ; 1762 else if (srcElement.type==TYPE_SCALAR) tmpGridSrc->addScalar(srcElement.scalar->getId()) ; 1763 tmpGridSrc->checkElementsAttributes() ; 1764 CGrid* tmpGridDst=CGrid::create(); // destination Grid 1765 map<int,int> posInGrid={{0,0}} ; 1766 1767 cout<<"--> New transform from "<<srcElementId<<" to "<<dstElementId<<endl ; 1768 if (dstElementType==EElement::DOMAIN) 1769 { 1770 CDomain* dstDomain ; 1771 CDomain* lastDstDomain ; 1772 bool isGenerate=false ; 1773 1774 do 1775 { 1776 1777 if (CDomain::has(dstElementId)) 1778 { 1779 dstDomain = CDomain::get(dstElementId) ; 1780 cout<<"Retrive existing domain : "<<dstElementId<<endl ; 1781 } 1782 else 1783 { 1784 dstDomain = CDomain::create() ; 1785 dstDomain->createAlias(dstElementId) ; 1786 cout<<"Create new domain : "<<dstDomain->getId()<<" with alias : "<<dstElementId<<endl ; 1787 1788 if (isGenerate) dstDomain->duplicateAttributes(lastDstDomain) ; 1789 else if (srcElementId=="" && srcElement.type==TYPE_DOMAIN) dstDomain->duplicateAttributes(srcElement.domain) ; // make a copy 1790 else dstDomain->duplicateAttributes(dstElement.domain) ; // make a copy 1791 CTransformation<CDomain>* transformation = CTransformation<CDomain>::createTransformation(transType,"") ; 1792 auto srcTransform = CTransformation<CDomain>::getTransformation(transType, transId) ; 1793 transformation->inheritFrom(srcTransform) ; 1794 CGrid* tmpGridDst=CGrid::create(); // destination Grid 1795 tmpGridDst->addDomain(dstDomain->getId()) ; 1796 1797 algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 1798 posInGrid,posInGrid,posInGrid, 1799 posInGrid,posInGrid,posInGrid ); 1800 1801 1802 dstDomain->setTransformationAlgorithm(algo) ; 1803 dstDomain->setTransformationPaths(transformationPath) ; 1804 } 1805 algo=dstDomain->getTransformationAlgorithm() ; 1806 isGenerate = algo->isGenerateTransformation() ; 1807 transformationPath.removeNextTransform() ; 1808 dstElementId=transformationPath.getNextElementId() ; 1809 srcElementId=transformationPath.getNextElementSrcId() ; 1810 transType = transformationPath.getNextTransformationType() ; 1811 transId = transformationPath.getNextTransformationId() ; 1812 lastDstDomain=dstDomain ; 1813 dstDomain->setTransformationPaths(transformationPath) ; 1814 } while(transformationPath.hasTransform() && isGenerate) ; 1815 1816 if (isNewGrid) newGrid->addDomain(dstDomain->getId()) ; 1817 algo = dstDomain->getTransformationAlgorithm() ; 1818 } 1819 else if (dstElementType==EElement::AXIS) 1820 { 1821 CAxis* dstAxis ; 1822 CAxis* lastDstAxis ; 1823 bool isGenerate=false ; 1824 1825 do 1826 { 1827 if (CAxis::has(dstElementId)) 1828 { 1829 dstAxis = CAxis::get(dstElementId) ; 1830 cout<<"Retrive existing axis : "<<dstElementId<<endl ; 1831 } 1832 else 1833 { 1834 dstAxis = CAxis::create() ; 1835 dstAxis->createAlias(dstElementId) ; 1836 cout<<"Create new axis : "<<dstAxis->getId()<<" with alias : "<<dstElementId<<endl ; 1837 1838 if (isGenerate) dstAxis->duplicateAttributes(lastDstAxis) ; 1839 else if (srcElementId=="" && srcElement.type==TYPE_AXIS) dstAxis->duplicateAttributes(srcElement.axis) ; // make a copy 1840 else dstAxis->duplicateAttributes(dstElement.axis) ; // make a copy 1841 CTransformation<CAxis>* transformation = CTransformation<CAxis>::createTransformation(transType,"") ; 1842 auto srcTransform = CTransformation<CAxis>::getTransformation(transType, transId) ; 1843 transformation->inheritFrom(srcTransform) ; 1844 tmpGridDst->addAxis(dstAxis->getId()) ; 1845 1846 algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 1847 posInGrid,posInGrid,posInGrid, 1848 posInGrid,posInGrid,posInGrid ); 1849 1850 dstAxis->setTransformationAlgorithm(algo) ; 1851 dstAxis->setTransformationPaths(transformationPath) ; 1852 } 1853 1854 algo=dstAxis->getTransformationAlgorithm() ; 1855 isGenerate = algo->isGenerateTransformation() ; 1856 transformationPath.removeNextTransform() ; 1857 dstElementId=transformationPath.getNextElementId() ; 1858 srcElementId=transformationPath.getNextElementSrcId() ; 1859 transType = transformationPath.getNextTransformationType() ; 1860 transId = transformationPath.getNextTransformationId() ; 1861 lastDstAxis=dstAxis ; 1862 dstAxis->setTransformationPaths(transformationPath) ; 1863 } while(transformationPath.hasTransform() && isGenerate) ; 1864 1865 if (isNewGrid) newGrid->addAxis(dstAxis->getId()) ; 1866 algo = dstAxis->getTransformationAlgorithm() ; 1867 } 1868 else if (dstElementType==EElement::SCALAR) 1869 { 1870 CScalar* dstScalar ; 1871 CScalar* lastDstScalar ; 1872 bool isGenerate=false ; 1873 1874 do 1875 { 1876 if (CScalar::has(dstElementId)) 1877 { 1878 dstScalar = CScalar::get(dstElementId) ; 1879 cout<<"Retrive existing scalar : "<<dstElementId<<endl ; 1880 } 1881 else 1882 { 1883 dstScalar = CScalar::create() ; 1884 dstScalar->createAlias(dstElementId) ; 1885 cout<<"Create new scalar : "<<dstScalar->getId()<<" with alias : "<<dstElementId<<endl ; 1886 1887 if (isGenerate) dstScalar->duplicateAttributes(lastDstScalar) ; 1888 else if (srcElementId=="" && srcElement.type==TYPE_SCALAR) dstScalar->duplicateAttributes(srcElement.scalar) ; // make a copy 1889 else dstScalar->duplicateAttributes(dstElement.scalar) ; // make a copy 1890 CTransformation<CScalar>* transformation = CTransformation<CScalar>::createTransformation(transType,"") ; 1891 auto srcTransform = CTransformation<CScalar>::getTransformation(transType, transId) ; 1892 transformation->inheritFrom(srcTransform) ; 1893 tmpGridDst->addScalar(dstScalar->getId()) ; 1894 1895 algo = transformation -> createAlgorithm(false, tmpGridDst, tmpGridSrc, 0, 1896 posInGrid,posInGrid,posInGrid, 1897 posInGrid,posInGrid,posInGrid ); 1898 1899 dstScalar->setTransformationAlgorithm(algo) ; 1900 dstScalar->setTransformationPaths(transformationPath) ; 1901 } 1902 algo=dstScalar->getTransformationAlgorithm() ; 1903 isGenerate = algo->isGenerateTransformation() ; 1904 transformationPath.removeNextTransform() ; 1905 dstElementId=transformationPath.getNextElementId() ; 1906 srcElementId=transformationPath.getNextElementSrcId() ; 1907 transType = transformationPath.getNextTransformationType() ; 1908 transId = transformationPath.getNextTransformationId() ; 1909 lastDstScalar=dstScalar ; 1910 dstScalar->setTransformationPaths(transformationPath) ; 1911 } while(transformationPath.hasTransform() && isGenerate) ; 1912 1913 if (isNewGrid) newGrid->addScalar(dstScalar->getId()) ; 1914 algo = dstScalar->getTransformationAlgorithm() ; 1915 } 1916 // here create a new spatial filter with algo 1917 1918 hadTransform=true ; 1919 hasTransform=false ; 1920 } 1921 else 1922 { 1923 string srcElementId=transformationPath.getNextElementSrcId() ; 1924 1925 if (srcElement.type==TYPE_DOMAIN) 1926 { 1927 CDomain* domain ; 1928 if (srcElementId=="") srcElementId=srcElement.domain->getId() ; 1929 if (!CDomain::has(srcElementId)) 1930 { 1931 domain=srcElement.domain ; 1932 domain->createAlias(srcElementId) ; 1933 } 1934 else domain = CDomain::get(srcElementId) ; 1935 domain->checkAttributes() ; 1936 1937 if (isNewGrid) newGrid->addDomain(srcElementId) ; 1938 } 1939 else if (srcElement.type==TYPE_AXIS) 1940 { 1941 CAxis* axis ; 1942 if (srcElementId=="") srcElementId=srcElement.axis->getId() ; 1943 if (!CAxis::has(srcElementId)) 1944 { 1945 axis=srcElement.axis ; 1946 axis->createAlias(srcElementId) ; 1947 } 1948 else axis = CAxis::get(srcElementId) ; 1949 axis->checkAttributes() ; 1950 1951 if (isNewGrid) newGrid->addAxis(srcElementId) ; 1952 } 1953 else if (srcElement.type==TYPE_SCALAR) 1954 { 1955 CScalar* scalar ; 1956 if (srcElementId=="") srcElementId=srcElement.scalar->getId() ; 1957 if (!CScalar::has(srcElementId)) 1958 { 1959 scalar=srcElement.scalar ; 1960 scalar->createAlias(srcElementId) ; 1961 } 1962 else scalar = CScalar::get(srcElementId) ; 1963 scalar->checkAttributes() ; 1964 1965 if (isNewGrid) newGrid->addScalar(srcElementId) ; 1966 } 1967 } 1968 1969 if (transformationPath.hasTransform() && hadTransform) hasRemainTransform=true ; 1970 } 1971 1972 1973 if (hadTransform) 1974 { 1975 1976 if (!isSource) 1977 { 1978 CGridAlgorithm* gridAlgorithm ; 1979 if (isNewGrid) 1980 { 1981 gridAlgorithm = algo->createGridAlgorithm(gridSrc, newGrid, pos) ; 1982 newGrid->setGridAlgorithm(gridAlgorithm); 1983 } 1984 else gridAlgorithm = newGrid->getGridAlgorithm() ; 1985 1986 shared_ptr<CTransformFilter> transformFilter = shared_ptr<CTransformFilter>(gridAlgorithm->createTransformFilter(gc, detectMissingValues, defaultValue)) ; 1987 outputFilter->connectOutput(transformFilter,0) ; 1988 vector<string> auxFieldId = algo->getAuxFieldId() ; // better to do that at transformation not algo ?? 1989 int i=1; 1990 for (auto& it : auxFieldId) 1991 { 1992 CField* auxField = CField::get(it) ; 1993 auxField->buildWorkflowGraph(gc) ; 1994 auxField->getInstantDataFilter()->connectOutput(transformFilter,i) ; 1995 i++ ; 1996 } 1997 outputFilter = transformFilter ; 1998 } 1999 2000 if (hasRemainTransform) 2001 { 2002 gridSrc=newGrid ; 2003 pair<shared_ptr<CFilter>, shared_ptr<CFilter> > filters = this->buildTransformationGraph(gc, isSource, gridSrc, detectMissingValues, defaultValue, newGrid) ; 2004 outputFilter->connectOutput(filters.first,0) ; 2005 outputFilter=filters.second ; 2006 } 2007 } 2008 2009 return {inputFilter,outputFilter} ; 2295 2010 } 2296 2011 CATCH_DUMP_ATTR 2297 2012 2298 CGridTransformation* CGrid::getTransformations() 2299 TRY 2300 { 2301 return transformations_; 2302 } 2303 CATCH_DUMP_ATTR 2304 2305 void CGrid::addTransGridSource(CGrid* gridSrc) 2306 TRY 2307 { 2308 if (gridSrc_.end() == gridSrc_.find(gridSrc)) 2309 gridSrc_.insert(make_pair(gridSrc,make_pair(false,""))); 2310 } 2311 CATCH_DUMP_ATTR 2312 2313 std::map<CGrid*,std::pair<bool,StdString> >& CGrid::getTransGridSource() 2314 TRY 2315 { 2316 return gridSrc_; 2317 } 2318 CATCH_DUMP_ATTR 2319 2320 /*! 2321 Complete all the necessary (and lacking) attributes of a grid 2322 This function is similar to gridTransformation but works only (till now) on generate_rectilinear_domain transformation 2323 */ 2324 void CGrid::completeGrid(CGrid* transformGridSrc) 2325 TRY 2326 { 2327 if (0 != transformGridSrc) 2328 { 2329 if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) 2330 { 2331 ERROR("CGrid::completeGrid(CGrid* transformGridSrc)", 2332 << "Two grids have different number of elements. " << std::endl 2333 << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl 2334 << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements()); 2335 } 2336 } 2337 2338 if (isGenerated()) return; 2339 setGenerated(); 2340 2341 CGridGenerate gridGenerate(this, transformGridSrc); 2342 gridGenerate.completeGrid(); 2343 } 2344 CATCH_DUMP_ATTR 2345 2346 bool CGrid::isGenerated() 2347 TRY 2348 { 2349 return isGenerated_; 2350 } 2351 CATCH 2352 2353 void CGrid::setGenerated() 2354 TRY 2355 { 2356 isGenerated_ = true; 2357 } 2358 CATCH_DUMP_ATTR 2359 2360 void CGrid::transformGrid(CGrid* transformGridSrc) 2361 TRY 2362 { 2363 if (!transformGridSrc) 2364 ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 2365 << "Impossible to transform grid '" << getId() << "', the source grid is null."); 2366 2367 if (isTransformed()) return; 2368 setTransformed(); 2369 if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) 2370 { 2371 ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 2372 << "Two grids have different number of elements. " << std::endl 2373 << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl 2374 << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements()); 2375 } 2013 2014 //**************************************************************** 2015 //**************************************************************** 2016 2017 //---------------------------------------------------------------- 2018 2019 CGrid* CGrid::duplicateSentGrid(void) 2020 { 2021 CGrid* newGrid ; 2022 string sentGridId="sent__"+getId() ; 2023 if (has(sentGridId)) newGrid = get(sentGridId) ; 2376 2024 else 2377 2025 { 2378 } 2379 2380 transformations_ = new CGridTransformation(this, transformGridSrc); 2381 transformations_->computeAll(); 2382 if (0 < transformations_->getNbAlgo()) hasTransform_ = true; 2383 2384 // Ok, now need to compute index of grid source 2385 transformGridSrc->checkMaskIndex(false); 2386 } 2387 CATCH_DUMP_ATTR 2388 2389 bool CGrid::hasTransform() 2390 TRY 2391 { 2392 if (hasTransform_) return hasTransform_; 2393 2394 std::vector<CDomain*> domList = getDomains(); 2395 std::vector<CAxis*> axisList = getAxis(); 2396 std::vector<CScalar*> scalarList = getScalars(); 2397 2398 for (int idx = 0; idx < domList.size(); ++idx) hasTransform_ |= domList[idx]->hasTransformation(); 2399 for (int idx = 0; idx < axisList.size(); ++idx) hasTransform_ |= axisList[idx]->hasTransformation(); 2400 for (int idx = 0; idx < scalarList.size(); ++idx) hasTransform_ |= scalarList[idx]->hasTransformation(); 2401 2402 return hasTransform_; 2403 } 2404 CATCH_DUMP_ATTR 2405 2406 /*! 2407 \brief Get the list of domain pointers 2408 \return list of domain pointers 2409 */ 2410 std::vector<CDomain*> CGrid::getDomains() 2411 TRY 2412 { 2413 std::vector<CDomain*> domList; 2414 if (!domList_.empty()) 2415 { 2416 for (int i = 0; i < domList_.size(); ++i) domList.push_back(CDomain::get(domList_[i])); 2417 } 2418 return domList; 2419 } 2420 CATCH_DUMP_ATTR 2421 2422 /*! 2423 \brief Get the list of axis pointers 2424 \return list of axis pointers 2425 */ 2426 std::vector<CAxis*> CGrid::getAxis() 2427 TRY 2428 { 2429 std::vector<CAxis*> aList; 2430 if (!axisList_.empty()) 2431 for (int i =0; i < axisList_.size(); ++i) aList.push_back(CAxis::get(axisList_[i])); 2432 2433 return aList; 2434 } 2435 CATCH_DUMP_ATTR 2436 2437 /*! 2438 \brief Get the list of axis pointers 2439 \return list of axis pointers 2440 */ 2441 std::vector<CScalar*> CGrid::getScalars() 2442 TRY 2443 { 2444 std::vector<CScalar*> sList; 2445 if (!scalarList_.empty()) 2446 for (int i =0; i < scalarList_.size(); ++i) sList.push_back(CScalar::get(scalarList_[i])); 2447 2448 return sList; 2449 } 2450 CATCH_DUMP_ATTR 2451 2452 /*! 2453 \brief Get domain pointer with index 2454 \return domain pointer 2455 */ 2456 CDomain* CGrid::getDomain(int domainIndex) 2457 TRY 2458 { 2459 std::vector<CDomain*> domainListP = this->getDomains(); 2460 if (domainListP.empty()) 2461 { 2462 ERROR("CGrid::getDomain(int domainIndex)", 2463 << "No domain associated to this grid. " << std::endl 2464 << "Grid id = " << this->getId()); 2465 } 2466 2467 if (domainIndex >= domainListP.size() || (domainIndex < 0)) 2468 ERROR("CGrid::getDomain(int domainIndex)", 2469 << "Domain with the index doesn't exist " << std::endl 2470 << "Grid id = " << this->getId() << std::endl 2471 << "Grid has only " << domainListP.size() << " domain but domain index required is " << domainIndex << std::endl); 2472 2473 return domainListP[domainIndex]; 2474 } 2475 CATCH_DUMP_ATTR 2476 2477 /*! 2478 \brief Get the axis pointer with index 2479 \return axis pointer 2480 */ 2481 CAxis* CGrid::getAxis(int axisIndex) 2482 TRY 2483 { 2484 std::vector<CAxis*> axisListP = this->getAxis(); 2485 if (axisListP.empty()) 2486 { 2487 ERROR("CGrid::getDomain(int axisIndex)", 2488 << "No axis associated to this grid. " << std::endl 2489 << "Grid id = " << this->getId()); 2490 } 2491 2492 if (axisIndex >= axisListP.size() || (axisIndex < 0)) 2493 ERROR("CGrid::getDomain(int axisIndex)", 2494 << "Domain with the index doesn't exist " << std::endl 2495 << "Grid id = " << this->getId() << std::endl 2496 << "Grid has only " << axisListP.size() << " axis but axis index required is " << axisIndex << std::endl); 2497 2498 return axisListP[axisIndex]; 2499 } 2500 CATCH_DUMP_ATTR 2501 2502 /*! 2503 \brief Get the a scalar pointer 2504 \return scalar pointer 2505 */ 2506 CScalar* CGrid::getScalar(int scalarIndex) 2507 TRY 2508 { 2509 std::vector<CScalar*> scalarListP = this->getScalars(); 2510 if (scalarListP.empty()) 2511 { 2512 ERROR("CGrid::getScalar(int scalarIndex)", 2513 << "No scalar associated to this grid. " << std::endl 2514 << "Grid id = " << this->getId()); 2515 } 2516 2517 if (scalarIndex >= scalarListP.size() || (scalarIndex < 0)) 2518 ERROR("CGrid::getScalar(int scalarIndex)", 2519 << "Scalar with the index doesn't exist " << std::endl 2520 << "Grid id = " << this->getId() << std::endl 2521 << "Grid has only " << scalarListP.size() << " scalar but scalar index required is " << scalarIndex << std::endl); 2522 2523 return scalarListP[scalarIndex]; 2524 } 2525 CATCH_DUMP_ATTR 2526 2527 /*! 2528 \brief Set domain(s) of a grid from a list 2529 \param[in] domains list of domains 2530 */ 2531 void CGrid::setDomainList(const std::vector<CDomain*> domains) 2532 TRY 2533 { 2534 if (isDomListSet) return; 2535 std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren(); 2536 if (!domains.empty() && domList.empty()) 2537 { 2538 for (int i = 0; i < domains.size(); ++i) 2539 this->getVirtualDomainGroup()->addChild(domains[i]); 2540 domList = this->getVirtualDomainGroup()->getAllChildren(); 2541 } 2542 2543 if (!domList.empty()) 2544 { 2545 int sizeDom = domList.size(); 2546 domList_.resize(sizeDom); 2547 for (int i = 0; i < sizeDom; ++i) 2548 { 2549 domList_[i] = domList[i]->getId(); 2550 } 2551 isDomListSet = true; 2552 } 2553 } 2554 CATCH_DUMP_ATTR 2555 2556 /*! 2557 \brief Set axis(s) of a grid from a list 2558 \param[in] axis list of axis 2559 */ 2560 void CGrid::setAxisList(const std::vector<CAxis*> axis) 2561 TRY 2562 { 2563 if (isAxisListSet) return; 2564 std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren(); 2565 if (!axis.empty() && aList.empty()) 2566 { 2567 for (int i = 0; i < axis.size(); ++i) 2568 this->getVirtualAxisGroup()->addChild(axis[i]); 2569 aList = this->getVirtualAxisGroup()->getAllChildren(); 2570 } 2571 2572 if (!aList.empty()) 2573 { 2574 int sizeAxis = aList.size(); 2575 axisList_.resize(sizeAxis); 2576 for (int i = 0; i < sizeAxis; ++i) 2577 { 2578 axisList_[i] = aList[i]->getId(); 2579 } 2580 isAxisListSet = true; 2581 } 2582 } 2583 CATCH_DUMP_ATTR 2584 2585 /*! 2586 \brief Set scalar(s) of a grid from a list 2587 \param[in] scalars list of scalars 2588 */ 2589 void CGrid::setScalarList(const std::vector<CScalar*> scalars) 2590 TRY 2591 { 2592 if (isScalarListSet) return; 2593 std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren(); 2594 if (!scalars.empty() && sList.empty()) 2595 { 2596 for (int i = 0; i < scalars.size(); ++i) 2597 this->getVirtualScalarGroup()->addChild(scalars[i]); 2598 sList = this->getVirtualScalarGroup()->getAllChildren(); 2599 } 2600 2601 if (!sList.empty()) 2602 { 2603 int sizeScalar = sList.size(); 2604 scalarList_.resize(sizeScalar); 2605 for (int i = 0; i < sizeScalar; ++i) 2606 { 2607 scalarList_[i] = sList[i]->getId(); 2608 } 2609 isScalarListSet = true; 2610 } 2611 } 2612 CATCH_DUMP_ATTR 2613 2614 /*! 2615 \brief Get list of id of domains 2616 \return id list of domains 2617 */ 2618 std::vector<StdString> CGrid::getDomainList() 2619 TRY 2620 { 2621 setDomainList(); 2622 return domList_; 2623 } 2624 CATCH 2625 2626 /*! 2627 \brief Get list of id of axis 2628 \return id list of axis 2629 */ 2630 std::vector<StdString> CGrid::getAxisList() 2631 TRY 2632 { 2633 setAxisList(); 2634 return axisList_; 2635 } 2636 CATCH 2637 2638 /*! 2639 \brief Get list of id of scalar 2640 \return id list of scalar 2641 */ 2642 std::vector<StdString> CGrid::getScalarList() 2643 TRY 2644 { 2645 setScalarList(); 2646 return scalarList_; 2647 } 2648 CATCH 2649 2650 /*! 2651 Send all attributes of domains from client to server 2652 */ 2653 void CGrid::sendAllDomains() 2654 TRY 2655 { 2656 std::vector<CDomain*> domList = this->getVirtualDomainGroup()->getAllChildren(); 2657 int dSize = domList.size(); 2658 for (int i = 0; i < dSize; ++i) 2659 { 2660 sendAddDomain(domList[i]->getId()); 2661 domList[i]->sendAllAttributesToServer(); 2662 } 2663 } 2664 CATCH_DUMP_ATTR 2665 2666 /*! 2667 Send all attributes of axis from client to server 2668 */ 2669 void CGrid::sendAllAxis() 2670 TRY 2671 { 2672 std::vector<CAxis*> aList = this->getVirtualAxisGroup()->getAllChildren(); 2673 int aSize = aList.size(); 2674 2675 for (int i = 0; i < aSize; ++i) 2676 { 2677 sendAddAxis(aList[i]->getId()); 2678 aList[i]->sendAllAttributesToServer(); 2679 } 2680 } 2681 CATCH_DUMP_ATTR 2682 2683 /*! 2684 Send all attributes of scalars from client to server 2685 */ 2686 void CGrid::sendAllScalars() 2687 TRY 2688 { 2689 std::vector<CScalar*> sList = this->getVirtualScalarGroup()->getAllChildren(); 2690 int sSize = sList.size(); 2691 2692 for (int i = 0; i < sSize; ++i) 2693 { 2694 sendAddScalar(sList[i]->getId()); 2695 sList[i]->sendAllAttributesToServer(); 2696 } 2697 } 2698 CATCH_DUMP_ATTR 2026 newGrid = CGrid::create(sentGridId) ; 2027 for(auto element : elements_) 2028 { 2029 if (element.type==TYPE_DOMAIN) 2030 { 2031 CDomain* domain = CDomain::create(); 2032 domain->duplicateAttributes(element.domain) ; 2033 domain->name = element.domain->getId() ; 2034 newGrid->addDomain(domain->getId()) ; 2035 } 2036 else if (element.type==TYPE_AXIS) 2037 { 2038 CAxis* axis = CAxis::create(); 2039 axis->duplicateAttributes(element.axis) ; 2040 axis->name = element.axis->getId() ; 2041 newGrid->addAxis(axis->getId()) ; 2042 } 2043 else if (element.type==TYPE_SCALAR) 2044 { 2045 CScalar* scalar = CScalar::create(); 2046 scalar->duplicateAttributes(element.scalar) ; 2047 scalar->name = element.scalar->getId() ; 2048 newGrid->addScalar(scalar->getId()) ; 2049 } 2050 } 2051 newGrid->checkElementsAttributes() ; 2052 } 2053 return newGrid ; 2054 } 2055 2699 2056 2700 2057 void CGrid::setContextClient(CContextClient* contextClient) … … 2706 2063 clientsSet.insert(contextClient); 2707 2064 } 2708 for ( int i=0; i<this->getDomains().size(); i++)2709 this->getDomains()[i]->setContextClient(contextClient);2710 for ( int i=0; i<this->getAxis().size(); i++)2711 this->getAxis()[i]->setContextClient(contextClient);2065 for (auto domain : getDomains()) domain->setContextClient(contextClient); 2066 for (auto axis : getAxis()) axis->setContextClient(contextClient); 2067 for (auto scalar : getScalars()) scalar->setContextClient(contextClient); 2068 2712 2069 } 2713 2070 CATCH_DUMP_ATTR 2714 2071 2715 /*! 2716 Parse a grid, for now, it contains only domain, axis and scalar 2717 */ 2718 void CGrid::parse(xml::CXMLNode& node) 2719 TRY 2720 { 2721 SuperClass::parse(node); 2722 2723 if (node.goToChildElement()) 2724 { 2725 StdString domainName("domain"); 2726 StdString axisName("axis"); 2727 StdString scalarName("scalar"); 2728 do 2729 { 2730 if (node.getElementName() == domainName) { 2731 order_.push_back(2); 2732 this->getVirtualDomainGroup()->parseChild(node); 2733 } 2734 if (node.getElementName() == axisName) { 2735 order_.push_back(1); 2736 this->getVirtualAxisGroup()->parseChild(node); 2737 } 2738 if (node.getElementName() == scalarName) { 2739 order_.push_back(0); 2740 this->getVirtualScalarGroup()->parseChild(node); 2741 } 2742 } while (node.goToNextElement()); 2743 node.goToParentElement(); 2744 } 2745 2746 if (!order_.empty()) 2747 { 2748 int sizeOrd = order_.size(); 2749 axis_domain_order.resize(sizeOrd); 2750 for (int i = 0; i < sizeOrd; ++i) 2751 { 2752 axis_domain_order(i) = order_[i]; 2753 } 2754 } 2755 2756 setDomainList(); 2757 setAxisList(); 2758 setScalarList(); 2759 } 2760 CATCH_DUMP_ATTR 2761 2072 2073 void CGrid::computeGridLocalElements() 2074 { 2075 std::vector<CDomain*> domainList = this->getDomains(); 2076 std::vector<CAxis*> axisList = this->getAxis(); 2077 std::vector<CScalar*> scalarList = this->getScalars(); 2078 auto domain=domainList.begin() ; 2079 auto axis=axisList.begin() ; 2080 auto scalar=scalarList.begin() ; 2081 vector<CLocalElement*> elements; 2082 for(auto order : order_) 2083 { 2084 if (order==2) 2085 { 2086 elements.push_back((*domain)->getLocalElement()); 2087 domain++ ; 2088 } 2089 else if (order==1) 2090 { 2091 elements.push_back((*axis)->getLocalElement()); 2092 axis++ ; 2093 } 2094 else if (order==0) 2095 { 2096 elements.push_back((*scalar)->getLocalElement()); 2097 scalar++ ; 2098 } 2099 } 2100 if (hasMask()) 2101 { 2102 vector<bool> mask(getMask().getVector()) ; 2103 gridLocalElements_ = new CGridLocalElements(elements, mask) ; 2104 } 2105 else gridLocalElements_ = new CGridLocalElements(elements) ; 2106 } 2107 2108 void CGrid::computeModelToWorkflowConnector(void) 2109 { 2110 modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW,true) ; 2111 } 2112 2113 void CGrid::computeWorkflowToFullConnector(void) 2114 { 2115 workflowToFullConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::FULL) ; 2116 } 2117 2118 void CGrid::computeWorkflowToModelConnector(void) 2119 { 2120 workflowToModelConnector_ = getGridLocalElements()->getConnector(CElementView::WORKFLOW,CElementView::MODEL,true) ; 2121 } 2122 2123 void CGrid::computeFullToWorkflowConnector(void) 2124 { 2125 fullToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::FULL,CElementView::WORKFLOW) ; 2126 } 2127 2128 void CGrid::computeServerFromClientConnector(void) 2129 { 2130 vector<CGathererConnector*> connectors ; 2131 for(auto& element : getElements()) 2132 { 2133 if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ; 2134 else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 2135 else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 2136 } 2137 serverFromClientConnector_ = new CGridGathererConnector(connectors) ; 2138 } 2139 2140 void CGrid::computeServerToClientConnector(void) 2141 { 2142 vector<CScattererConnector*> connectors ; 2143 for(auto& element : getElements()) 2144 { 2145 if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerToClientConnector()) ; 2146 else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerToClientConnector()) ; 2147 else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerToClientConnector()) ; 2148 } 2149 serverToClientConnector_ = new CGridScattererConnector(connectors) ; 2150 } 2151 2152 void CGrid::computeClientFromClientConnector(void) 2153 { 2154 vector<CGathererConnector*> connectors ; 2155 for(auto& element : getElements()) 2156 { 2157 if (element.type==TYPE_DOMAIN) connectors.push_back(element.domain->getServerFromClientConnector()) ; 2158 else if (element.type==TYPE_AXIS) connectors.push_back(element.axis->getServerFromClientConnector()) ; 2159 else if (element.type==TYPE_SCALAR) connectors.push_back(element.scalar->getServerFromClientConnector()) ; 2160 } 2161 clientFromClientConnector_ = new CGridGathererConnector(connectors) ; 2162 } 2163 2164 2762 2165 } // namespace xios -
XIOS/dev/dev_trunk_graph/src/node/grid.hpp
r1653 r2019 16 16 #include "utils.hpp" 17 17 #include "transformation_enum.hpp" 18 #include "grid_local_connector.hpp" 19 #include "grid_elements.hpp" 20 #include "grid_scatterer_connector.hpp" 21 #include "grid_gatherer_connector.hpp" 22 #include "transformation_path.hpp" 23 #include "filter.hpp" 24 #include "grid_algorithm.hpp" 25 18 26 19 27 namespace xios { … … 31 39 class CServerDistributionDescription; 32 40 class CClientServerMapping; 33 class CGridTransformation; 34 41 35 42 ///-------------------------------------------------------------- 36 43 … … 50 57 typedef CGridAttributes SuperClassAttribute; 51 58 59 private: 60 61 // define a structure to store elements (CDomain, CAxis, CScalar) using a void* and a type to cast the pointer 62 enum EElementType { TYPE_SCALAR, TYPE_AXIS, TYPE_DOMAIN } ; 63 struct SElement {void* ptr ; EElementType type ; CScalar* scalar ; CAxis* axis ; CDomain* domain ; } ; 64 vector<SElement> elements_ ; 65 bool elementsComputed_ = false ; 66 /** retrieve the vector of elements as a structure containing a void* and the type of pointer */ 67 vector<SElement>& getElements(void) { if (!elementsComputed_) computeElements() ; return elements_ ; } 68 void computeElements(void) ; 69 /** List order of axis and domain in a grid, if there is a domain, it will take value 2, axis 1, scalar 0 */ 70 std::vector<int> order_; 71 52 72 public: 53 73 … … 57 77 enum EEventId 58 78 { 59 EVENT_ID_INDEX, EVENT_ID_ADD_DOMAIN, EVENT_ID_ADD_AXIS, EVENT_ID_ADD_SCALAR 79 EVENT_ID_ADD_DOMAIN, EVENT_ID_ADD_AXIS, EVENT_ID_ADD_SCALAR, 80 EVENT_ID_SEND_MASK, 81 60 82 }; 61 83 … … 70 92 71 93 void checkEligibilityForCompressedOutput(); 72 73 void solveDomainAxisRef(bool areAttributesChecked); 94 95 74 96 75 97 void checkMaskIndex(bool doCalculateIndex); … … 89 111 StdSize getDimension(void); 90 112 91 StdSize getDataSize(void) const; 92 93 /// Entrees-sorties de champs 94 template <int n> 95 void inputField(const CArray<double,n>& field, CArray<double,1>& stored) const; 96 template <int n> 97 void maskField(const CArray<double,n>& field, CArray<double,1>& stored) const; 98 template <int n> 99 void outputField(const CArray<double,1>& stored, CArray<double,n>& field) const; 100 template <int n> 101 void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) const; 102 113 StdSize getDataSize(void) ; 114 115 /** 116 * Get the local data grid size, ie the size of the compressed grid (inside the workflow) 117 * \return The size od the compressed grid 118 */ 119 StdSize getLocalDataSize(void) ; 120 121 103 122 virtual void parse(xml::CXMLNode& node); 104 123 … … 129 148 130 149 public: 131 void computeIndexServer(void); 132 void computeIndex(void); 133 void computeIndexScalarGrid(); 134 void computeWrittenIndex(); 150 void solveDomainAxisRef(bool areAttributesChecked); 151 void checkElementsAttributes(void) ; 135 152 136 153 void solveDomainRef(bool checkAtt); 137 154 void solveAxisRef(bool checkAtt); 138 155 void solveScalarRef(bool checkAtt); 139 void solve DomainAxisRefInheritance(bool apply = true);140 void solveTransformations();156 void solveElementsRefInheritance(bool apply = true); 157 // void solveTransformations(); 141 158 void solveDomainAxisBaseRef(); 142 159 … … 144 161 CAxis* addAxis(const std::string& id=StdString()); 145 162 CScalar* addScalar(const std::string& id=StdString()); 146 void sendAddDomain(const std::string& id=""); 147 void sendAddAxis(const std::string& id=""); 148 void sendAddScalar(const std::string& id=""); 149 void sendAllDomains(); 150 void sendAllAxis(); 151 void sendAllScalars(); 152 163 164 public: 165 void sendGridToFileServer(CContextClient* client) ; 166 private: 167 std::set<CContextClient*> sendGridToFileServer_done_ ; 168 169 public: 170 void sendGridToCouplerOut(CContextClient* client, const string& fieldId) ; 171 private: 172 std::set<CContextClient*> sendGridToCouplerOut_done_ ; 173 174 public: 175 void makeAliasForCoupling(const string& fieldId) ; 176 177 public: 178 void sendAddDomain(const std::string& id,CContextClient* contextClient); 179 void sendAddAxis(const std::string& id,CContextClient* contextClient); 180 void sendAddScalar(const std::string& id,CContextClient* contextClient); 181 153 182 static void recvAddDomain(CEventServer& event); 154 183 void recvAddDomain(CBufferIn& buffer); … … 159 188 160 189 static bool dispatchEvent(CEventServer& event); 161 static void recvIndex(CEventServer& event); 162 void recvIndex(vector<int> ranks, vector<CBufferIn*> buffers); 163 void sendIndex(void); 164 void sendIndexScalarGrid(); 165 190 191 public: 166 192 void setContextClient(CContextClient* contextClient); 167 193 168 void computeDomConServer();169 std::map<int, int> getDomConServerSide();170 194 std::map<int, StdSize> getAttributesBufferSize(CContextClient* client, bool bufferForWriting = false); 171 195 std::map<int, StdSize> getDataBufferSize(CContextClient* client, const std::string& id = "", bool bufferForWriting = false); … … 185 209 bool doGridHaveDataToWrite(); 186 210 bool doGridHaveDataDistributed(CContextClient* client = 0); 187 size_t getWrittenDataSize() const; 188 int getNumberWrittenIndexes() const; 189 int getTotalNumberWrittenIndexes() const; 190 int getOffsetWrittenIndexes() const; 191 192 CDistributionServer* getDistributionServer(); 193 CDistributionClient* getDistributionClient(); 194 CGridTransformation* getTransformations(); 195 196 void transformGrid(CGrid* transformGridSrc); 197 void completeGrid(CGrid* transformGridSrc = 0); 198 void doAutoDistribution(CGrid* transformGridSrc); 199 bool isTransformed(); 200 void setTransformed(); 201 bool isGenerated(); 202 void setGenerated(); 203 void addTransGridSource(CGrid* gridSrc); 204 std::map<CGrid*, std::pair<bool,StdString> >& getTransGridSource(); 205 bool hasTransform(); 206 size_t getGlobalWrittenSize(void) ; 207 public: 208 CArray<int, 1> storeIndex_client; 209 CArray<bool, 1> storeMask_client; 210 211 /** Map containing indexes that will be sent in sendIndex(). */ 212 std::map<CContextClient*, map<int, CArray<int, 1> > > storeIndex_toSrv; 213 214 /** Map storing the number of senders. Key = size of receiver's intracomm */ 215 std::map<int, std::map<int,int> > nbSenders; 216 217 std::map<CContextClient*, std::map<int,int> > nbReadSenders; 218 219 map<int, CArray<int, 1> > storeIndex_fromSrv; // Support, for now, reading with level-1 server 220 221 map<int, CArray<size_t, 1> > outIndexFromClient; // Deprecated 222 223 map<int, CArray<size_t, 1> > compressedOutIndexFromClient; 224 225 /** Map storing received indexes. Key = sender rank, value = index array. */ 226 map<int, CArray<size_t, 1> > outGlobalIndexFromClient; 227 228 // Manh Ha's comment: " A client receives global index from other clients (via recvIndex) 229 // then does mapping these index into local index of STORE_CLIENTINDEX 230 // In this way, store_clientIndex can be used as an input of a source filter 231 // Maybe we need a flag to determine whether a client wants to write. TODO " 232 233 /** Map storing received data. Key = sender rank, value = data array. 234 * The map is created in CGrid::computeClientIndex and filled upon receiving data in CField::recvUpdateData() */ 235 map<int, CArray<size_t, 1> > outLocalIndexStoreOnClient; 236 237 /** Indexes calculated based on server-like distribution. 238 * They are used for writing/reading data and only calculated for server level that does the writing/reading. 239 * Along with localIndexToWriteOnClient, these indexes are used to correctly place incoming data. */ 240 CArray<size_t,1> localIndexToWriteOnServer; 241 242 /** Indexes calculated based on client-like distribution. 243 * They are used for writing/reading data and only calculated for server level that does the writing/reading. 244 * Along with localIndexToWriteOnServer, these indexes are used to correctly place incoming data. */ 245 CArray<size_t,1> localIndexToWriteOnClient; 246 247 CArray<size_t,1> indexFromClients; 211 212 /////////////////////////////////////////// 213 //////// TRANSFORMATIONS ///// 214 /////////////////////////////////////////// 215 public: 216 pair<shared_ptr<CFilter>, shared_ptr<CFilter> > buildTransformationGraph(CGarbageCollector& gc, bool isSource, CGrid* gridSrc, double detectMissingValues, 217 double defaultValue, CGrid*& newGrid, bool graphEnabled=false) ; 218 private: 219 CGridAlgorithm* gridAlgorithm_ = nullptr ; 220 public: 221 void setGridAlgorithm(CGridAlgorithm* gridAlgorithm) {gridAlgorithm_ = gridAlgorithm;} 222 CGridAlgorithm* getGridAlgorithm(void) { return gridAlgorithm_ ;} 223 224 /////////////////////////////////////////// 225 public: 226 227 size_t getGlobalWrittenSize(void) ; 228 229 bool isCompleted(void) ; 230 void setCompleted(void) ; 231 void unsetCompleted(void) ; 232 248 233 249 234 bool hasMask(void) const; 250 void checkMask(void); 251 void createMask(void); 252 void modifyMask(const CArray<int,1>& indexToModify, bool valueToModify = false); 253 void modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue = false); 254 255 void computeGridGlobalDimension(const std::vector<CDomain*>& domains, 256 const std::vector<CAxis*>& axis, 257 const std::vector<CScalar*>& scalars, 258 const CArray<int,1>& axisDomainOrder); 259 260 private: 261 template<int N> 262 void checkGridMask(CArray<bool,N>& gridMask, 263 const std::vector<CArray<bool,1>* >& domainMasks, 264 const std::vector<CArray<bool,1>* >& axisMasks, 265 const CArray<int,1>& axisDomainOrder, 266 bool createMask = false); 267 template<int N> 268 void modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify); 269 270 template<int N> 271 void modifyGridMaskSize(CArray<bool,N>& gridMask, const std::vector<int>& eachDimSize, bool newValue); 272 273 void storeField_arr(const double* const data, CArray<double, 1>& stored) const; 274 void restoreField_arr(const CArray<double, 1>& stored, double* const data) const; 275 void uncompressField_arr(const double* const data, CArray<double, 1>& outData) const; 276 void maskField_arr(const double* const data, CArray<double, 1>& stored) const; 277 235 /** get mask pointer stored in mask_1d, or mask_2d, or..., or mask_7d */ 236 CArray<bool,1> mask_ ; 237 CArray<bool,1>& getMask(void) ; 238 239 private: 240 /** Client-like distribution calculated based on the knowledge of the entire grid */ 241 CDistributionClient* clientDistribution_; 242 public: 243 void computeClientDistribution(void) ; 244 private: 245 bool computeClientDistribution_done_ = false ; 246 public: 247 CDistributionClient* getClientDistribution(void); 248 249 private: 278 250 void setVirtualDomainGroup(CDomainGroup* newVDomainGroup); 279 251 void setVirtualAxisGroup(CAxisGroup* newVAxisGroup); … … 288 260 CScalarGroup* getVirtualScalarGroup() const; 289 261 290 void checkAttributesAfterTransformation();291 void setTransformationAlgorithms();292 void computeIndexByElement(const std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,293 const CContextClient* client,294 CClientServerMapping::GlobalIndexMap& globalIndexOnServer);295 262 int computeGridGlobalDimension(std::vector<int>& globalDim, 296 263 const std::vector<CDomain*> domains, … … 299 266 const CArray<int,1>& axisDomainOrder); 300 267 int getDistributedDimension(); 301 302 void computeClientIndex(); 303 void computeConnectedClients(); 304 void computeClientIndexScalarGrid(); 305 void computeConnectedClientsScalarGrid(); 306 268 public: 269 270 bool isDataDistributed(void) ; 307 271 private: 308 272 … … 311 275 std::set<CContextClient*> clientsSet; 312 276 277 private: 313 278 bool isChecked; 314 279 bool isDomainAxisChecked; … … 321 286 bool isAxisListSet, isDomListSet, isScalarListSet; 322 287 323 /** Client-like distribution calculated based on the knowledge of the entire grid */324 CDistributionClient* clientDistribution_;325 326 /** Server-like distribution calculated upon receiving indexes */327 CDistributionServer* serverDistribution_;328 329 CClientServerMapping* clientServerMap_;330 size_t writtenDataSize_;331 int numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_;332 333 288 /** Map storing local ranks of connected receivers. Key = size of receiver's intracomm. 334 289 * It is calculated in computeConnectedClients(). */ … … 344 299 /** Size of data to be send in case of reading. It is calculated in recvIndex(). */ 345 300 std::map<int,size_t> connectedDataSizeRead_; 346 347 bool isDataDistributed_; 301 348 302 //! True if and only if the data defined on the grid can be outputted in a compressed way 349 303 bool isCompressible_; 350 304 std::set<std::string> relFilesCompressed; 351 305 352 bool isTransformed_, isGenerated_; 353 bool computedWrittenIndex_; 306 354 307 std::vector<int> axisPositionInGrid_; 355 CGridTransformation* transformations_; 308 void computeAxisPositionInGrid(void) ; 309 bool computeAxisPositionInGrid_done_ = false ; 310 std::vector<int>& getAxisPositionInGrid(void) { if (!computeAxisPositionInGrid_done_) computeAxisPositionInGrid() ; return axisPositionInGrid_ ;} 311 356 312 bool hasDomainAxisBaseRef_; 357 313 std::map<CGrid*, std::pair<bool,StdString> > gridSrc_; 358 bool hasTransform_; 359 360 /** Map storing global indexes of server-like (band-wise) distribution for sending to receivers. 361 * Key = size of receiver's intracomm. 362 */ 363 // std::map<CContextClient*, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_; 364 std::map<int, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_; 365 366 367 /** List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false) */ 368 std::vector<int> order_; 314 315 ////////////////////////////////////////////////////////////////////////////////////// 316 // this part is related to distribution, element definition, views and connectors // 317 ////////////////////////////////////////////////////////////////////////////////////// 318 public: 319 CGrid* duplicateSentGrid(void) ; 320 private: 321 static void recvMask(CEventServer& event) ; 322 void receiveMask(CEventServer& event) ; 323 324 private: 325 CGridLocalElements* gridLocalElements_= nullptr ; 326 void computeGridLocalElements(void) ; 327 public: 328 CGridLocalElements* getGridLocalElements(void) { if (gridLocalElements_==nullptr) computeGridLocalElements() ; return gridLocalElements_ ;} 329 330 private: 331 CGridLocalConnector* modelToWorkflowConnector_ = nullptr ; 332 public: 333 void computeModelToWorkflowConnector(void) ; 334 CGridLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_;} 335 336 private: 337 CGridLocalConnector* workflowToModelConnector_ ; 338 public: 339 void computeWorkflowToModelConnector(void) ; 340 CGridLocalConnector* getWorkflowToModelConnector(void) { if (workflowToModelConnector_==nullptr) computeWorkflowToModelConnector() ; return workflowToModelConnector_;} 341 342 public: //? 343 void distributeGridToFileServer(CContextClient* client); 344 345 346 private: 347 CGridLocalConnector* workflowToFullConnector_ = nullptr; 348 public: 349 void computeWorkflowToFullConnector(void) ; 350 CGridLocalConnector* getWorkflowToFullConnector(void) { if (workflowToFullConnector_==nullptr) computeWorkflowToFullConnector() ; return workflowToFullConnector_;} 351 352 private: 353 CGridLocalConnector* fullToWorkflowConnector_ = nullptr; 354 public: 355 void computeFullToWorkflowConnector(void) ; 356 CGridLocalConnector* getFullToWorkflowConnector(void) { if (fullToWorkflowConnector_==nullptr) computeFullToWorkflowConnector() ; return fullToWorkflowConnector_;} 357 358 359 360 private: 361 CGridGathererConnector* clientFromClientConnector_ = nullptr ; 362 public: 363 CGridGathererConnector* getClientFromClientConnector(void) { if (clientFromClientConnector_==nullptr) computeClientFromClientConnector() ; return clientFromClientConnector_;} 364 void computeClientFromClientConnector(void) ; 365 366 private: 367 map<CContextClient*, CGridScattererConnector*> clientToClientConnector_ ; 368 public: 369 CGridScattererConnector* getClientToClientConnector(CContextClient* client) { return clientToClientConnector_[client] ;} // make some test to see if connector exits for the given client 370 371 372 private: 373 map<CContextClient*,CGridGathererConnector*> clientFromServerConnector_ ; 374 public: 375 CGridGathererConnector* getClientFromServerConnector(CContextClient* client) { return clientFromServerConnector_[client];} 376 void computeClientFromServerConnector(void) ; 377 378 private: 379 CGridScattererConnector* serverToClientConnector_=nullptr ; 380 public: 381 CGridScattererConnector* getServerToClientConnector(void) { if (serverToClientConnector_==nullptr) computeServerToClientConnector() ; return serverToClientConnector_;} 382 void computeServerToClientConnector(void) ; 383 private: 384 map<CContextClient*, CGridScattererConnector*> clientToServerConnector_ ; 385 public: 386 CGridScattererConnector* getClientToServerConnector(CContextClient* client) { return clientToServerConnector_[client] ;} // make some test to see if connector exits for the given client 387 388 private: 389 CGridGathererConnector* serverFromClientConnector_ = nullptr ; 390 public: 391 CGridGathererConnector* getServerFromClientConnector(void) { if (serverFromClientConnector_==nullptr) computeServerFromClientConnector() ; return serverFromClientConnector_;} 392 void computeServerFromClientConnector(void) ; 369 393 370 394 }; // class CGrid 371 372 ///--------------------------------------------------------------373 374 template <int n>375 void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const376 TRY377 {378 //#ifdef __XIOS_DEBUG379 if (this->getDataSize() != field.numElements())380 ERROR("void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const",381 << "[ Awaiting data of size = " << this->getDataSize() << ", "382 << "Received data size = " << field.numElements() << " ] "383 << "The data array does not have the right size! "384 << "Grid = " << this->getId())385 //#endif386 this->storeField_arr(field.dataFirst(), stored);387 }388 CATCH389 390 template <int n>391 void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) const392 {393 //#ifdef __XIOS_DEBUG394 if (this->getDataSize() != field.numElements())395 ERROR("void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const",396 << "[ Awaiting data of size = " << this->getDataSize() << ", "397 << "Received data size = " << field.numElements() << " ] "398 << "The data array does not have the right size! "399 << "Grid = " << this->getId())400 //#endif401 this->maskField_arr(field.dataFirst(), stored);402 }403 404 template <int n>405 void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const406 TRY407 {408 //#ifdef __XIOS_DEBUG409 if (this->getDataSize() != field.numElements())410 ERROR("void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const",411 << "[ Size of the data = " << this->getDataSize() << ", "412 << "Output data size = " << field.numElements() << " ] "413 << "The ouput array does not have the right size! "414 << "Grid = " << this->getId())415 //#endif416 this->restoreField_arr(stored, field.dataFirst());417 }418 CATCH419 420 /*!421 This function removes the effect of mask on received data on the server.422 This function only serve for the checking purpose. TODO: Something must be done to seperate mask and data_index from each other in received data423 \data data received data with masking effect on the server424 \outData data without masking effect425 */426 template <int N>427 void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) const428 TRY429 {430 uncompressField_arr(data.dataFirst(), outData);431 }432 CATCH433 434 template<int N>435 void CGrid::checkGridMask(CArray<bool,N>& gridMask,436 const std::vector<CArray<bool,1>* >& domainMasks,437 const std::vector<CArray<bool,1>* >& axisMasks,438 const CArray<int,1>& axisDomainOrder,439 bool createMask)440 TRY441 {442 int idx = 0;443 int numElement = axisDomainOrder.numElements();444 int dim = domainMasks.size() * 2 + axisMasks.size();445 std::vector<CDomain*> domainP = this->getDomains();446 std::vector<CAxis*> axisP = this->getAxis();447 448 std::vector<int> idxLoop(dim,0), indexMap(numElement), eachDimSize(dim);449 std::vector<int> currentIndex(dim);450 int idxDomain = 0, idxAxis = 0;451 for (int i = 0; i < numElement; ++i)452 {453 indexMap[i] = idx;454 if (2 == axisDomainOrder(i)) {455 eachDimSize[indexMap[i]] = domainP[idxDomain]->ni;456 eachDimSize[indexMap[i]+1] = domainP[idxDomain]->nj;457 idx += 2; ++idxDomain;458 }459 else if (1 == axisDomainOrder(i)) {460 // eachDimSize[indexMap[i]] = axisMasks[idxAxis]->numElements();461 eachDimSize[indexMap[i]] = axisP[idxAxis]->n;462 ++idx; ++idxAxis;463 }464 else {};465 }466 467 if (!gridMask.isEmpty() && !createMask)468 {469 for (int i = 0; i < dim; ++i)470 {471 if (gridMask.extent(i) != eachDimSize[i])472 ERROR("CGrid::checkMask(void)",473 << "The mask has one dimension whose size is different from the one of the local grid." << std::endl474 << "Local size of dimension " << i << " is " << eachDimSize[i] << "." << std::endl475 << "Mask size for dimension " << i << " is " << gridMask.extent(i) << "." << std::endl476 << "Grid = " << this->getId())477 }478 }479 else {480 CArrayBoolTraits<CArray<bool,N> >::resizeArray(gridMask,eachDimSize);481 gridMask = true;482 }483 484 int ssize = gridMask.numElements();485 idx = 0;486 while (idx < ssize)487 {488 for (int i = 0; i < dim-1; ++i)489 {490 if (idxLoop[i] == eachDimSize[i])491 {492 idxLoop[i] = 0;493 ++idxLoop[i+1];494 }495 }496 497 // Find out outer index498 idxDomain = idxAxis = 0;499 bool maskValue = true;500 for (int i = 0; i < numElement; ++i)501 {502 if (2 == axisDomainOrder(i))503 {504 int idxTmp = idxLoop[indexMap[i]] + idxLoop[indexMap[i]+1] * eachDimSize[indexMap[i]];505 if (idxTmp < (*domainMasks[idxDomain]).numElements())506 maskValue = maskValue && (*domainMasks[idxDomain])(idxTmp);507 else508 maskValue = false;509 ++idxDomain;510 }511 else if (1 == axisDomainOrder(i))512 {513 int idxTmp = idxLoop[indexMap[i]];514 if (idxTmp < (*axisMasks[idxAxis]).numElements())515 maskValue = maskValue && (*axisMasks[idxAxis])(idxTmp);516 else517 maskValue = false;518 519 ++idxAxis;520 }521 }522 523 int maskIndex = idxLoop[0];524 int mulDim = 1;525 for (int k = 1; k < dim; ++k)526 {527 mulDim *= eachDimSize[k-1];528 maskIndex += idxLoop[k]*mulDim;529 }530 *(gridMask.dataFirst()+maskIndex) &= maskValue;531 532 ++idxLoop[0];533 ++idx;534 }535 }536 CATCH_DUMP_ATTR537 538 template<int N>539 void CGrid::modifyGridMaskSize(CArray<bool,N>& gridMask,540 const std::vector<int>& eachDimSize,541 bool newValue)542 TRY543 {544 if (N != eachDimSize.size())545 {546 // ERROR("CGrid::modifyGridMaskSize(CArray<bool,N>& gridMask,547 // const std::vector<int>& eachDimSize,548 // bool newValue)",549 // << "Dimension size of the mask is different from input dimension size." << std::endl550 // << "Mask dimension is " << N << "." << std::endl551 // << "Input dimension is " << eachDimSize.size() << "." << std::endl552 // << "Grid = " << this->getId())553 }554 CArrayBoolTraits<CArray<bool,N> >::resizeArray(gridMask,eachDimSize);555 gridMask = newValue;556 }557 CATCH_DUMP_ATTR558 559 560 /*!561 Modify the current mask of grid, the local index to be modified will take value false562 \param [in/out] gridMask current mask of grid563 \param [in] indexToModify local index to modify564 */565 template<int N>566 void CGrid::modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify)567 TRY568 {569 int num = indexToModify.numElements();570 for (int idx = 0; idx < num; ++idx)571 {572 *(gridMask.dataFirst()+indexToModify(idx)) = valueToModify;573 }574 }575 CATCH_DUMP_ATTR576 577 ///--------------------------------------------------------------578 579 580 395 581 396 // Declare/Define CGridGroup and CGridDefinition -
XIOS/dev/dev_trunk_graph/src/node/interpolate_axis.cpp
r937 r2019 1 1 #include "interpolate_axis.hpp" 2 #include "axis_algorithm_interpolate_coordinate.hpp" 3 #include "axis_algorithm_interpolate.hpp" 2 4 #include "type.hpp" 3 5 #include "field.hpp" … … 27 29 bool CInterpolateAxis::registerTrans() 28 30 { 29 return registerTransformation(TRANS_INTERPOLATE_AXIS, CInterpolateAxis::create);31 return registerTransformation(TRANS_INTERPOLATE_AXIS, {create, getTransformation}); 30 32 } 31 33 … … 84 86 return auxInputs; 85 87 } 88 89 CGenericAlgorithmTransformation* CInterpolateAxis::createAlgorithm(bool isSource, 90 CGrid* gridDst, CGrid* gridSrc, 91 int elementPositionInGrid, 92 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 93 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 94 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 95 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 96 std::map<int, int>& elementPositionInGridDst2AxisPosition, 97 std::map<int, int>& elementPositionInGridDst2DomainPosition) 98 { 99 if (!coordinate.isEmpty()) return CAxisAlgorithmInterpolateCoordinate::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 100 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 101 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 102 else return CAxisAlgorithmInterpolate::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 103 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 104 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 105 } 86 106 } -
XIOS/dev/dev_trunk_graph/src/node/interpolate_axis.hpp
r836 r2019 20 20 class CInterpolateAxis; 21 21 class CAxis; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CInterpolateAxis> SuperClass; 42 43 typedef CInterpolateAxisAttributes SuperClassAttribute; 44 typedef CInterpolateAxis MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 43 46 44 47 public : … … 58 61 static StdString GetDefName(void); 59 62 static ENodeType GetType(void); 63 const string& getId(void) { return this->SuperClass::getId();} 64 ETranformationType getTransformationType(void) { return TRANS_INTERPOLATE_AXIS ;} 65 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 66 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 67 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 68 CGrid* gridDst, CGrid* gridSrc, 69 int elementPositionInGrid, 70 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 71 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 72 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 73 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 74 std::map<int, int>& elementPositionInGridDst2AxisPosition, 75 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 60 76 private: 61 77 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/interpolate_domain.cpp
r1653 r2019 1 1 #include "interpolate_domain.hpp" 2 #include "domain_algorithm_interpolate.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CInterpolateDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_INTERPOLATE_DOMAIN, create);30 registerTransformation(TRANS_INTERPOLATE_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 68 69 } 69 70 71 CGenericAlgorithmTransformation* CInterpolateDomain::createAlgorithm(bool isSource, 72 CGrid* gridDst, CGrid* gridSrc, 73 int elementPositionInGrid, 74 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 75 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 76 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 77 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 78 std::map<int, int>& elementPositionInGridDst2AxisPosition, 79 std::map<int, int>& elementPositionInGridDst2DomainPosition) 80 { 81 return CDomainAlgorithmInterpolate::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 82 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 83 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 84 } 70 85 } -
XIOS/dev/dev_trunk_graph/src/node/interpolate_domain.hpp
r1021 r2019 20 20 class CInterpolateDomain; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CInterpolateDomain> SuperClass; 42 43 typedef CInterpolateDomainAttributes SuperClassAttribute; 44 typedef CInterpolateDomain MyClass ; 45 typedef CTransformation<CDomain> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_INTERPOLATE_DOMAIN ;} 63 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/inverse_axis.cpp
r836 r2019 1 1 #include "inverse_axis.hpp" 2 #include "axis_algorithm_inverse.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CInverseAxis::registerTrans() 27 28 { 28 return registerTransformation(TRANS_INVERSE_AXIS, CInverseAxis::create);29 return registerTransformation(TRANS_INVERSE_AXIS, {create, getTransformation}); 29 30 } 30 31 … … 39 40 {} 40 41 42 CGenericAlgorithmTransformation* CInverseAxis::createAlgorithm(bool isSource, 43 CGrid* gridDst, CGrid* gridSrc, 44 int elementPositionInGrid, 45 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 46 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 47 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 48 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 49 std::map<int, int>& elementPositionInGridDst2AxisPosition, 50 std::map<int, int>& elementPositionInGridDst2DomainPosition) 51 { 52 return CAxisAlgorithmInverse::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 53 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 54 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 55 } 41 56 } -
XIOS/dev/dev_trunk_graph/src/node/inverse_axis.hpp
r836 r2019 19 19 class CInverseAxis; 20 20 class CAxis; 21 class CGenericAlgorithmTransformation ; 22 class CGrid; 21 23 ///-------------------------------------------------------------- 22 24 … … 39 41 typedef CObjectTemplate<CInverseAxis> SuperClass; 40 42 typedef CInverseAxisAttributes SuperClassAttribute; 43 typedef CInverseAxis MyClass ; 44 typedef CTransformation<CAxis> SuperTransform ; 41 45 42 46 public : … … 54 58 static StdString GetDefName(void); 55 59 static ENodeType GetType(void); 56 60 const string& getId(void) { return this->SuperClass::getId();} 61 ETranformationType getTransformationType(void) { return TRANS_INVERSE_AXIS ;} 62 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 63 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 64 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 65 CGrid* gridDst, CGrid* gridSrc, 66 int elementPositionInGrid, 67 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 68 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 69 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 70 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 71 std::map<int, int>& elementPositionInGridDst2AxisPosition, 72 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 57 73 private: 58 74 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/mesh.cpp
r1542 r2019 539 539 } 540 540 } 541 nodeHashList.resizeAndPreserve(nbHash); 541 if (nbHash==0) nodeHashList.resize(nbHash); 542 else nodeHashList.resizeAndPreserve(nbHash); 542 543 543 544 // (2.2) Generating global node indexes … … 986 987 } 987 988 } 988 edgeHashList.resizeAndPreserve(nEdgeHash); 989 if (nEdgeHash==0) edgeHashList.resize(nEdgeHash); 990 else edgeHashList.resizeAndPreserve(nEdgeHash); 989 991 990 992 // (2.3) Generating global edge indexes … … 1327 1329 } 1328 1330 } 1329 nodeIdxList.resizeAndPreserve(nIdx); 1331 if (nIdx==0) nodeIdxList.resize(nIdx); 1332 else nodeIdxList.resizeAndPreserve(nIdx); 1330 1333 CClientClientDHTSizet dhtNodeIdx(nodeIdx2Idx, comm); 1331 1334 dhtNodeIdx.computeIndexInfoMapping(nodeIdxList); … … 1377 1380 } 1378 1381 } 1379 edgeHashList.resizeAndPreserve(nEdgeHash); 1382 if (nEdgeHash==0) edgeHashList.resize(nEdgeHash); 1383 else edgeHashList.resizeAndPreserve(nEdgeHash); 1380 1384 1381 1385 // (3.4) Generating global edge indexes … … 1754 1758 } 1755 1759 } 1756 nghbFaces.resizeAndPreserve(2, nbNghb); 1760 if (nbNghb==0) nghbFaces.resize(2, nbNghb); 1761 else nghbFaces.resizeAndPreserve(2, nbNghb); 1757 1762 } // getGloNghbFacesNodeType 1758 1763 … … 1806 1811 } 1807 1812 } 1808 nodeHashList.resizeAndPreserve(iIdx); 1813 if (iIdx==0) nodeHashList.resize(iIdx); 1814 else nodeHashList.resizeAndPreserve(iIdx); 1809 1815 1810 1816 // (1.2) Generating node indexes … … 1934 1940 } 1935 1941 } 1936 nghbFaces.resizeAndPreserve(2, nbNghb); 1942 if (nbNghb==0) nghbFaces.resize(2, nbNghb); 1943 else nghbFaces.resizeAndPreserve(2, nbNghb); 1937 1944 } // getGloNghbFacesEdgeType 1938 1945 -
XIOS/dev/dev_trunk_graph/src/node/node_enum.hpp
r1558 r2019 15 15 eField,gField, 16 16 eFile,gFile, 17 eCouplerIn,gCouplerIn, 18 eCouplerOut,gCouplerOut, 17 19 eGrid,gGrid, 18 20 eVariable,gVariable, -
XIOS/dev/dev_trunk_graph/src/node/node_type.hpp
r1558 r2019 6 6 #include "field.hpp" 7 7 #include "file.hpp" 8 #include "coupler_in.hpp" 9 #include "coupler_out.hpp" 8 10 #include "grid.hpp" 9 11 #include "variable.hpp" -
XIOS/dev/dev_trunk_graph/src/node/reduce_axis_to_axis.cpp
r1314 r2019 1 1 #include "reduce_axis_to_axis.hpp" 2 #include "axis_algorithm_reduce_axis.hpp" 2 3 #include "type.hpp" 3 4 #include "axis.hpp" … … 27 28 bool CReduceAxisToAxis::registerTrans() 28 29 { 29 return registerTransformation(TRANS_REDUCE_AXIS_TO_AXIS, CReduceAxisToAxis::create);30 return registerTransformation(TRANS_REDUCE_AXIS_TO_AXIS, {create, getTransformation}); 30 31 } 31 32 … … 56 57 } 57 58 59 CGenericAlgorithmTransformation* CReduceAxisToAxis::createAlgorithm(bool isSource, 60 CGrid* gridDst, CGrid* gridSrc, 61 int elementPositionInGrid, 62 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 63 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 64 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 65 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 66 std::map<int, int>& elementPositionInGridDst2AxisPosition, 67 std::map<int, int>& elementPositionInGridDst2DomainPosition) 68 { 69 return CAxisAlgorithmReduceAxis::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 70 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 71 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 72 } 58 73 } -
XIOS/dev/dev_trunk_graph/src/node/reduce_axis_to_axis.hpp
r1301 r2019 19 19 class CReduceAxisToAxis; 20 20 class CAxis; 21 21 class CGenericAlgorithmTransformation ; 22 class CGrid; 22 23 ///-------------------------------------------------------------- 23 24 … … 40 41 typedef CObjectTemplate<CReduceAxisToAxis> SuperClass; 41 42 typedef CReduceAxisToAxisAttributes SuperClassAttribute; 43 typedef CReduceAxisToAxis MyClass ; 44 typedef CTransformation<CAxis> SuperTransform ; 42 45 43 46 public : … … 55 58 static StdString GetDefName(void); 56 59 static ENodeType GetType(void); 57 private: 60 const string& getId(void) { return this->SuperClass::getId();} 61 ETranformationType getTransformationType(void) { return TRANS_REDUCE_AXIS_TO_AXIS ;} 62 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 63 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 64 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 65 CGrid* gridDst, CGrid* gridSrc, 66 int elementPositionInGrid, 67 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 68 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 69 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 70 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 71 std::map<int, int>& elementPositionInGridDst2AxisPosition, 72 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 73 private: 58 74 static bool registerTrans(); 59 75 static CTransformation<CAxis>* create(const StdString& id, xml::CXMLNode* node); -
XIOS/dev/dev_trunk_graph/src/node/reduce_axis_to_scalar.cpp
r980 r2019 1 1 #include "reduce_axis_to_scalar.hpp" 2 #include "scalar_algorithm_reduce_axis.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CReduceAxisToScalar::registerTrans() 27 28 { 28 return registerTransformation(TRANS_REDUCE_AXIS_TO_SCALAR, CReduceAxisToScalar::create);29 return registerTransformation(TRANS_REDUCE_AXIS_TO_SCALAR, {create, getTransformation}); 29 30 } 30 31 … … 41 42 } 42 43 44 CGenericAlgorithmTransformation* CReduceAxisToScalar::createAlgorithm(bool isSource, 45 CGrid* gridDst, CGrid* gridSrc, 46 int elementPositionInGrid, 47 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 48 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 49 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 50 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 51 std::map<int, int>& elementPositionInGridDst2AxisPosition, 52 std::map<int, int>& elementPositionInGridDst2DomainPosition) 53 { 54 return CScalarAlgorithmReduceAxis::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 55 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 56 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 57 } 43 58 } -
XIOS/dev/dev_trunk_graph/src/node/reduce_axis_to_scalar.hpp
r888 r2019 19 19 class CReduceAxisToScalar; 20 20 class CScalar; 21 21 class CGenericAlgorithmTransformation ; 22 class CGrid; 22 23 ///-------------------------------------------------------------- 23 24 … … 40 41 typedef CObjectTemplate<CReduceAxisToScalar> SuperClass; 41 42 typedef CReduceAxisToScalarAttributes SuperClassAttribute; 43 typedef CReduceAxisToScalar MyClass ; 44 typedef CTransformation<CScalar> SuperTransform ; 42 45 43 46 public : … … 55 58 static StdString GetDefName(void); 56 59 static ENodeType GetType(void); 60 const string& getId(void) { return this->SuperClass::getId();} 61 ETranformationType getTransformationType(void) { return TRANS_REDUCE_AXIS_TO_SCALAR ;} 62 static CTransformation<CScalar>* getTransformation(const StdString& id) { return SuperClass::get(id);} 63 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 64 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 65 CGrid* gridDst, CGrid* gridSrc, 66 int elementPositionInGrid, 67 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 68 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 69 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 70 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 71 std::map<int, int>& elementPositionInGridDst2AxisPosition, 72 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 57 73 private: 58 74 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/reduce_domain_to_axis.cpp
r1299 r2019 1 1 #include "reduce_domain_to_axis.hpp" 2 #include "axis_algorithm_reduce_domain.hpp" 2 3 #include "type.hpp" 3 4 #include "axis.hpp" … … 28 29 bool CReduceDomainToAxis::registerTrans() 29 30 { 30 return registerTransformation(TRANS_REDUCE_DOMAIN_TO_AXIS, CReduceDomainToAxis::create);31 return registerTransformation(TRANS_REDUCE_DOMAIN_TO_AXIS, {create, getTransformation}); 31 32 } 32 33 … … 87 88 } 88 89 90 CGenericAlgorithmTransformation* CReduceDomainToAxis::createAlgorithm(bool isSource, 91 CGrid* gridDst, CGrid* gridSrc, 92 int elementPositionInGrid, 93 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 94 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 95 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 96 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 97 std::map<int, int>& elementPositionInGridDst2AxisPosition, 98 std::map<int, int>& elementPositionInGridDst2DomainPosition) 99 { 100 return CAxisAlgorithmReduceDomain::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 101 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 102 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 103 } 89 104 } -
XIOS/dev/dev_trunk_graph/src/node/reduce_domain_to_axis.hpp
r895 r2019 20 20 class CAxis; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CReduceDomainToAxis> SuperClass; 42 43 typedef CReduceDomainToAxisAttributes SuperClassAttribute; 44 typedef CReduceDomainToAxis MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 58 private: 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_REDUCE_DOMAIN_TO_AXIS ;} 63 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 74 private: 59 75 static bool registerTrans(); 60 76 static CTransformation<CAxis>* create(const StdString& id, xml::CXMLNode* node); -
XIOS/dev/dev_trunk_graph/src/node/reduce_domain_to_scalar.cpp
r1313 r2019 1 1 #include "reduce_domain_to_scalar.hpp" 2 #include "scalar_algorithm_reduce_domain.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CReduceDomainToScalar::registerTrans() 27 28 { 28 return registerTransformation(TRANS_REDUCE_DOMAIN_TO_SCALAR, CReduceDomainToScalar::create);29 return registerTransformation(TRANS_REDUCE_DOMAIN_TO_SCALAR, {create, getTransformation}); 29 30 } 30 31 … … 42 43 } 43 44 45 CGenericAlgorithmTransformation* CReduceDomainToScalar::createAlgorithm(bool isSource, 46 CGrid* gridDst, CGrid* gridSrc, 47 int elementPositionInGrid, 48 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 49 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 50 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 51 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 52 std::map<int, int>& elementPositionInGridDst2AxisPosition, 53 std::map<int, int>& elementPositionInGridDst2DomainPosition) 54 { 55 return CScalarAlgorithmReduceDomain::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 56 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 57 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition) ; 58 } 44 59 } -
XIOS/dev/dev_trunk_graph/src/node/reduce_domain_to_scalar.hpp
r976 r2019 20 20 class CDomain; 21 21 class CScalar; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CReduceDomainToScalar> SuperClass; 42 43 typedef CReduceDomainToScalarAttributes SuperClassAttribute; 44 typedef CReduceDomainToScalar MyClass ; 45 typedef CTransformation<CScalar> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_REDUCE_DOMAIN_TO_SCALAR ;} 63 static CTransformation<CScalar>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/reduce_scalar_to_scalar.cpp
r1314 r2019 1 1 #include "reduce_scalar_to_scalar.hpp" 2 #include "scalar_algorithm_reduce_scalar.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CReduceScalarToScalar::registerTrans() 27 28 { 28 return registerTransformation(TRANS_REDUCE_SCALAR_TO_SCALAR, CReduceScalarToScalar::create);29 return registerTransformation(TRANS_REDUCE_SCALAR_TO_SCALAR, {create, getTransformation}); 29 30 } 30 31 … … 41 42 } 42 43 44 CGenericAlgorithmTransformation* CReduceScalarToScalar::createAlgorithm(bool isSource, 45 CGrid* gridDst, CGrid* gridSrc, 46 int elementPositionInGrid, 47 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 48 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 49 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 50 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 51 std::map<int, int>& elementPositionInGridDst2AxisPosition, 52 std::map<int, int>& elementPositionInGridDst2DomainPosition) 53 { 54 return CScalarAlgorithmReduceScalar::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 55 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 56 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 57 } 43 58 } -
XIOS/dev/dev_trunk_graph/src/node/reduce_scalar_to_scalar.hpp
r1314 r2019 19 19 class CReduceScalarToScalar; 20 20 class CScalar; 21 21 class CGenericAlgorithmTransformation ; 22 class CGrid; 22 23 ///-------------------------------------------------------------- 23 24 … … 40 41 typedef CObjectTemplate<CReduceScalarToScalar> SuperClass; 41 42 typedef CReduceScalarToScalarAttributes SuperClassAttribute; 43 typedef CReduceScalarToScalar MyClass ; 44 typedef CTransformation<CScalar> SuperTransform ; 42 45 43 46 public : … … 55 58 static StdString GetDefName(void); 56 59 static ENodeType GetType(void); 60 const string& getId(void) { return this->SuperClass::getId();} 61 ETranformationType getTransformationType(void) { return TRANS_REDUCE_SCALAR_TO_SCALAR ;} 62 static CTransformation<CScalar>* getTransformation(const StdString& id) { return SuperClass::get(id);} 63 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 64 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 65 CGrid* gridDst, CGrid* gridSrc, 66 int elementPositionInGrid, 67 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 68 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 69 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 70 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 71 std::map<int, int>& elementPositionInGridDst2AxisPosition, 72 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 57 73 private: 58 74 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/reorder_domain.cpp
r1457 r2019 1 1 #include "reorder_domain.hpp" 2 #include "domain_algorithm_reorder.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CReorderDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_REORDER_DOMAIN, CReorderDomain::create);30 registerTransformation(TRANS_REORDER_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 41 42 } 42 43 44 CGenericAlgorithmTransformation* CReorderDomain::createAlgorithm(bool isSource, 45 CGrid* gridDst, CGrid* gridSrc, 46 int elementPositionInGrid, 47 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 48 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 49 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 50 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 51 std::map<int, int>& elementPositionInGridDst2AxisPosition, 52 std::map<int, int>& elementPositionInGridDst2DomainPosition) 53 { 54 return CDomainAlgorithmReorder::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 55 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 56 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 57 } 43 58 } -
XIOS/dev/dev_trunk_graph/src/node/reorder_domain.hpp
r1457 r2019 20 20 class CReorderDomain; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CReorderDomain> SuperClass; 42 43 typedef CReorderDomainAttributes SuperClassAttribute; 44 typedef CReorderDomain MyClass ; 45 typedef CTransformation<CDomain> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 58 private: 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_REORDER_DOMAIN ;} 63 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 74 private: 59 75 static bool registerTrans(); 60 76 static CTransformation<CDomain>* create(const StdString& id, xml::CXMLNode* node); -
XIOS/dev/dev_trunk_graph/src/node/scalar.cpp
r1314 r2019 7 7 #include "xios_spl.hpp" 8 8 #include "type.hpp" 9 10 namespace xios { 11 12 /// ////////////////////// Définitions ////////////////////// /// 13 14 CScalar::CScalar(void) 15 : CObjectTemplate<CScalar>() 16 , CScalarAttributes() 17 , relFiles() 18 { /* Ne rien faire de plus */ } 19 20 CScalar::CScalar(const StdString & id) 21 : CObjectTemplate<CScalar>(id) 22 , CScalarAttributes() 23 , relFiles() 24 { /* Ne rien faire de plus */ } 25 26 CScalar::~CScalar(void) 27 { /* Ne rien faire de plus */ } 28 29 std::map<StdString, ETranformationType> CScalar::transformationMapList_ = std::map<StdString, ETranformationType>(); 30 bool CScalar::dummyTransformationMapList_ = CScalar::initializeTransformationMap(CScalar::transformationMapList_); 31 bool CScalar::initializeTransformationMap(std::map<StdString, ETranformationType>& m) 32 { 33 m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_SCALAR; 34 m["extract_axis"] = TRANS_EXTRACT_AXIS_TO_SCALAR; 35 m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_SCALAR; 36 m["reduce_scalar"] = TRANS_REDUCE_SCALAR_TO_SCALAR; 37 } 38 39 StdString CScalar::GetName(void) { return (StdString("scalar")); } 40 StdString CScalar::GetDefName(void){ return (CScalar::GetName()); } 41 ENodeType CScalar::GetType(void) { return (eScalar); } 42 43 CScalar* CScalar::createScalar() 44 { 45 CScalar* scalar = CScalarGroup::get("scalar_definition")->createChild(); 46 return scalar; 47 } 48 49 bool CScalar::IsWritten(const StdString & filename) const 50 { 51 return (this->relFiles.find(filename) != this->relFiles.end()); 52 } 53 54 void CScalar::addRelFile(const StdString& filename) 55 { 9 #include "context.hpp" 10 11 namespace xios 12 { 13 14 /// ////////////////////// Définitions ////////////////////// /// 15 16 CScalar::CScalar(void) 17 : CObjectTemplate<CScalar>() 18 , CScalarAttributes() 19 , relFiles() 20 { /* Ne rien faire de plus */ } 21 22 CScalar::CScalar(const StdString & id) 23 : CObjectTemplate<CScalar>(id) 24 , CScalarAttributes() 25 , relFiles() 26 { /* Ne rien faire de plus */ } 27 28 CScalar::~CScalar(void) 29 { /* Ne rien faire de plus */ } 30 31 std::map<StdString, ETranformationType> CScalar::transformationMapList_ = std::map<StdString, ETranformationType>(); 32 bool CScalar::dummyTransformationMapList_ = CScalar::initializeTransformationMap(CScalar::transformationMapList_); 33 bool CScalar::initializeTransformationMap(std::map<StdString, ETranformationType>& m) 34 { 35 m["reduce_axis"] = TRANS_REDUCE_AXIS_TO_SCALAR; 36 m["extract_axis"] = TRANS_EXTRACT_AXIS_TO_SCALAR; 37 m["reduce_domain"] = TRANS_REDUCE_DOMAIN_TO_SCALAR; 38 m["reduce_scalar"] = TRANS_REDUCE_SCALAR_TO_SCALAR; 39 } 40 41 StdString CScalar::GetName(void) { return (StdString("scalar")); } 42 StdString CScalar::GetDefName(void){ return (CScalar::GetName()); } 43 ENodeType CScalar::GetType(void) { return (eScalar); } 44 45 CScalar* CScalar::createScalar() 46 { 47 CScalar* scalar = CScalarGroup::get("scalar_definition")->createChild(); 48 return scalar; 49 } 50 51 bool CScalar::IsWritten(const StdString & filename) const 52 { 53 return (this->relFiles.find(filename) != this->relFiles.end()); 54 } 55 56 void CScalar::addRelFile(const StdString& filename) 57 { 56 58 this->relFiles.insert(filename); 57 } 58 59 void CScalar::checkAttributes(void) 60 { 61 } 62 63 void CScalar::checkAttributesOnClient() 64 { 65 59 } 60 61 void CScalar::checkAttributes(void) 62 { 63 if (checkAttributes_done_) return ; 64 checkAttributes_done_ = true ; 65 66 if (mask.isEmpty()) mask=true ; 67 68 initializeLocalElement() ; 69 addFullView() ; 70 addWorkflowView() ; 71 addModelView() ; 66 72 } 67 73 … … 129 135 * Go through the hierarchy to find the scalar from which the transformations must be inherited 130 136 */ 131 void CScalar::solveInheritanceTransformation ()137 void CScalar::solveInheritanceTransformation_old() 132 138 { 133 139 if (hasTransformation() || !hasDirectScalarReference()) … … 146 152 refScalar[i]->setTransformations(scalar->getAllTransformations()); 147 153 } 148 154 155 void CScalar::solveInheritanceTransformation() 156 TRY 157 { 158 if (solveInheritanceTransformation_done_) return; 159 else solveInheritanceTransformation_done_=true ; 160 161 CScalar* scalar = this; 162 CScalar* Lastscalar ; 163 std::list<CScalar*> refScalars; 164 bool out=false ; 165 vector<StdString> excludedAttr; 166 excludedAttr.push_back("scalar_ref"); 167 168 refScalars.push_front(scalar) ; 169 while (scalar->hasDirectScalarReference() && !out) 170 { 171 CScalar* lastScalar=scalar ; 172 scalar = scalar->getDirectScalarReference(); 173 scalar->solveRefInheritance() ; 174 if (!scalar->SuperClass::isEqual(lastScalar,excludedAttr)) out=true ; 175 refScalars.push_front(scalar) ; 176 } 177 178 CTransformationPaths::TPath path ; 179 auto& pathList = std::get<2>(path) ; 180 std::get<0>(path) = EElement::SCALAR ; 181 std::get<1>(path) = refScalars.front()->getId() ; 182 for (auto& scalar : refScalars) 183 { 184 CScalar::TransMapTypes transformations = scalar->getAllTransformations(); 185 for(auto& transformation : transformations) pathList.push_back({transformation.second->getTransformationType(), 186 transformation.second->getId()}) ; 187 } 188 transformationPaths_.addPath(path) ; 189 190 } 191 CATCH_DUMP_ATTR 192 193 /* obsolete, to remove after reimplementing coupling */ 194 void CScalar::sendScalarToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid) 195 { 196 if (sendScalarToCouplerOut_done_.count(client)!=0) return ; 197 else sendScalarToCouplerOut_done_.insert(client) ; 198 199 string scalarId="_scalar["+std::to_string(posInGrid)+"]_of_"+fieldId ; 200 201 this->sendAllAttributesToServer(client, scalarId); 202 } 203 204 void CScalar::makeAliasForCoupling(const string& fieldId, int posInGrid) 205 { 206 const string scalarId = "_scalar["+std::to_string(posInGrid)+"]_of_"+fieldId ; 207 this->createAlias(scalarId) ; 208 } 209 210 void CScalar::setContextClient(CContextClient* contextClient) 211 TRY 212 { 213 if (clientsSet.find(contextClient)==clientsSet.end()) 214 { 215 clients.push_back(contextClient) ; 216 clientsSet.insert(contextClient); 217 } 218 } 219 CATCH_DUMP_ATTR 149 220 /*! 150 221 Parse children nodes of a scalar in xml file. … … 183 254 } 184 255 256 ////////////////////////////////////////////////////////////////////////////////////// 257 // this part is related to distribution, element definition, views and connectors // 258 ////////////////////////////////////////////////////////////////////////////////////// 259 260 void CScalar::initializeLocalElement(void) 261 { 262 // after checkAttribute index of size n 263 int rank = CContext::getCurrent()->getIntraCommRank() ; 264 265 CArray<size_t,1> ind(1) ; 266 ind(0)=0 ; 267 localElement_ = new CLocalElement(rank, 1, ind) ; 268 } 269 270 void CScalar::addFullView(void) 271 { 272 CArray<int,1> index(1) ; 273 for(int i=0; i<1 ; i++) index(0)=0 ; 274 localElement_ -> addView(CElementView::FULL, index) ; 275 } 276 277 void CScalar::addWorkflowView(void) 278 { 279 CArray<int,1> index ; 280 if (mask) 281 { 282 index.resize(1) ; 283 index(0)=0 ; 284 } 285 else index.resize(0) ; 286 localElement_ -> addView(CElementView::WORKFLOW, index) ; 287 } 288 289 void CScalar::addModelView(void) 290 { 291 CArray<int,1> index(1) ; 292 for(int i=0; i<1 ; i++) index(0)=0 ; 293 localElement_->addView(CElementView::MODEL, index) ; 294 } 295 296 void CScalar::computeModelToWorkflowConnector(void) 297 { 298 CLocalView* srcView=getLocalView(CElementView::MODEL) ; 299 CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ; 300 modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 301 modelToWorkflowConnector_->computeConnector() ; 302 } 303 304 305 void CScalar::computeRemoteElement(CContextClient* client, EDistributionType type) 306 { 307 CContext* context = CContext::getCurrent(); 308 map<int, CArray<size_t,1>> globalIndex ; 309 310 int nbServer = client->serverSize; 311 size_t nglo=1 ; 312 CArray<size_t,1> indGlo(nglo) ; 313 for(size_t i=0;i<nglo;i++) indGlo(i) = i ; 314 for (auto& rankServer : client->getRanksServerLeader()) globalIndex[rankServer].reference(indGlo.copy()) ; 315 316 remoteElement_[client] = new CDistributedElement(nglo, globalIndex) ; 317 remoteElement_[client]->addFullView() ; 318 } 319 320 void CScalar::distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, 321 CScattererConnector* &scattererConnector, const string& scalarId) 322 { 323 string serverScalarId = scalarId.empty() ? this->getId() : scalarId ; 324 CContext* context = CContext::getCurrent(); 325 326 this->sendAllAttributesToServer(client, serverScalarId) ; 327 328 CDistributedElement scatteredElement(1,globalIndex) ; 329 scatteredElement.addFullView() ; 330 scattererConnector = new CScattererConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), 331 context->getIntraComm(), client->getRemoteSize()) ; 332 scattererConnector->computeConnector() ; 333 334 // phase 0 335 // send remote element to construct the full view on server, ie without hole 336 CEventClient event0(getType(), EVENT_ID_SCALAR_DISTRIBUTION); 337 CMessage message0 ; 338 message0<<serverScalarId<<0 ; 339 remoteElement_[client]->sendToServer(client,event0,message0) ; 340 341 // phase 1 342 // send the full view of element to construct the connector which connect distributed data coming from client to the full local view 343 CEventClient event1(getType(), EVENT_ID_SCALAR_DISTRIBUTION); 344 CMessage message1 ; 345 message1<<serverScalarId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 346 scattererConnector->transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ; 347 348 sendDistributedAttributes(client, *scattererConnector, scalarId) ; 349 350 // phase 2 send the mask : data index + mask2D 351 CArray<bool,1> maskIn(localElement_->getView(CElementView::WORKFLOW)->getSize()); 352 CArray<bool,1> maskOut ; 353 CLocalConnector workflowToFull(localElement_->getView(CElementView::WORKFLOW), localElement_->getView(CElementView::FULL)) ; 354 workflowToFull.computeConnector() ; 355 maskIn=true ; 356 workflowToFull.transfer(maskIn,maskOut,false) ; 357 358 // phase 3 : prepare grid scatterer connector to send data from client to server 359 map<int,CArray<size_t,1>> workflowGlobalIndex ; 360 map<int,CArray<bool,1>> maskOut2 ; 361 scattererConnector->transfer(maskOut, maskOut2) ; 362 scatteredElement.addView(CElementView::WORKFLOW, maskOut2) ; 363 scatteredElement.getView(CElementView::WORKFLOW)->getGlobalIndexView(workflowGlobalIndex) ; 364 // create new workflow view for scattered element 365 CDistributedElement clientToServerElement(scatteredElement.getGlobalSize(), workflowGlobalIndex) ; 366 clientToServerElement.addFullView() ; 367 CEventClient event2(getType(), EVENT_ID_SCALAR_DISTRIBUTION); 368 CMessage message2 ; 369 message2<<serverScalarId<<2 ; 370 clientToServerElement.sendToServer(client, event2, message2) ; 371 clientToServerConnector_[client] = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), clientToServerElement.getView(CElementView::FULL), 372 context->getIntraComm(), client->getRemoteSize()) ; 373 clientToServerConnector_[client]->computeConnector() ; 374 375 clientFromServerConnector_[client] = new CGathererConnector(clientToServerElement.getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)); 376 clientFromServerConnector_[client]->computeConnector() ; 377 378 } 379 380 void CScalar::recvScalarDistribution(CEventServer& event) 381 TRY 382 { 383 string scalarId; 384 int phasis ; 385 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> phasis ; 386 get(scalarId)->receivedScalarDistribution(event, phasis); 387 } 388 CATCH 389 390 void CScalar::receivedScalarDistribution(CEventServer& event, int phasis) 391 TRY 392 { 393 CContext* context = CContext::getCurrent(); 394 if (phasis==0) // receive the remote element to construct the full view 395 { 396 localElement_ = new CLocalElement(context->getIntraCommRank(),event) ; 397 localElement_->addFullView() ; 398 // construct the local dimension and indexes 399 auto& globalIndex=localElement_->getGlobalIndex() ; 400 int nk=globalIndex.numElements() ; 401 // no distribution for scalar => nk ==1 or maybe 0 ? 402 } 403 else if (phasis==1) // receive the sent view from client to construct the full distributed full view on server 404 { 405 CContext* context = CContext::getCurrent(); 406 CDistributedElement* elementFrom = new CDistributedElement(event) ; 407 elementFrom->addFullView() ; 408 gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 409 gathererConnector_->computeConnector() ; 410 } 411 else if (phasis==2) 412 { 413 // delete gathererConnector_ ; 414 elementFrom_ = new CDistributedElement(event) ; 415 elementFrom_->addFullView() ; 416 // gathererConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ; 417 // gathererConnector_ -> computeConnector() ; 418 } 419 } 420 CATCH 421 422 void CScalar::setServerMask(CArray<bool,1>& serverMask, CContextClient* client) 423 TRY 424 { 425 CContext* context = CContext::getCurrent(); 426 localElement_->addView(CElementView::WORKFLOW, serverMask) ; 427 mask = serverMask(0) ; 428 429 serverFromClientConnector_ = new CGathererConnector(elementFrom_->getView(CElementView::FULL), localElement_->getView(CElementView::WORKFLOW)) ; 430 serverFromClientConnector_->computeConnector() ; 431 432 serverToClientConnector_ = new CScattererConnector(localElement_->getView(CElementView::WORKFLOW), elementFrom_->getView(CElementView::FULL), 433 context->getIntraComm(), client->getRemoteSize()) ; 434 serverToClientConnector_->computeConnector() ; 435 } 436 CATCH_DUMP_ATTR 437 438 void CScalar::sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& scalarId) 439 { 440 string serverScalarId = scalarId.empty() ? this->getId() : scalarId ; 441 CContext* context = CContext::getCurrent(); 442 443 // nothing for now 444 } 445 446 void CScalar::recvDistributedAttributes(CEventServer& event) 447 TRY 448 { 449 string scalarId; 450 string type ; 451 for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> scalarId >> type ; 452 get(scalarId)->recvDistributedAttributes(event, type); 453 } 454 CATCH 455 456 void CScalar::recvDistributedAttributes(CEventServer& event, const string& type) 457 TRY 458 { 459 // nothing for now 460 } 461 CATCH 462 463 bool CScalar::dispatchEvent(CEventServer& event) 464 TRY 465 { 466 if (SuperClass::dispatchEvent(event)) return true; 467 else 468 { 469 switch(event.type) 470 { 471 case EVENT_ID_SCALAR_DISTRIBUTION: 472 recvScalarDistribution(event); 473 return true; 474 break; 475 case EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE: 476 recvDistributedAttributes(event); 477 return true; 478 break; 479 default : 480 ERROR("bool CScalar::dispatchEvent(CEventServer& event)", 481 << "Unknown Event"); 482 return false; 483 } 484 } 485 } 486 CATCH 487 488 185 489 // Definition of some macros 186 490 DEFINE_REF_FUNC(Scalar,scalar) -
XIOS/dev/dev_trunk_graph/src/node/scalar.hpp
r1436 r2019 13 13 #include "transformation.hpp" 14 14 #include "transformation_enum.hpp" 15 #include "transformation_path.hpp" 16 #include "element.hpp" 17 #include "local_connector.hpp" 18 #include "scatterer_connector.hpp" 19 #include "gatherer_connector.hpp" 20 #include "distribution_type.hpp" 21 #include "generic_algorithm_transformation.hpp" 22 15 23 16 24 namespace xios 17 25 { 18 19 20 21 22 23 24 25 26 26 /// ////////////////////// Déclarations ////////////////////// /// 27 28 class CScalarGroup; 29 class CScalarAttributes; 30 class CScalar; 31 ///-------------------------------------------------------------- 32 33 // Declare/Define CVarAttribute 34 BEGIN_DECLARE_ATTRIBUTE_MAP(CScalar) 27 35 #include "scalar_attribute.conf" 28 END_DECLARE_ATTRIBUTE_MAP(CScalar) 29 30 ///-------------------------------------------------------------- 31 32 class CScalar 33 : public CObjectTemplate<CScalar> 34 , public CScalarAttributes 36 END_DECLARE_ATTRIBUTE_MAP(CScalar) 37 38 ///-------------------------------------------------------------- 39 40 class CScalar: public CObjectTemplate<CScalar> 41 , public CScalarAttributes 42 { 43 friend class CScalarGroup; 44 45 /// typedef /// 46 typedef CObjectTemplate<CScalar> SuperClass; 47 typedef CScalarAttributes SuperClassAttribute; 48 49 public: 50 enum EEventId 35 51 { 36 /// typedef /// 37 typedef CObjectTemplate<CScalar> SuperClass; 38 typedef CScalarAttributes SuperClassAttribute; 39 40 friend class CScalarGroup; 41 42 public : 43 44 typedef CScalarAttributes RelAttributes; 45 typedef CScalarGroup RelGroup; 46 typedef CTransformation<CScalar>::TransformationMapTypes TransMapTypes; 47 48 /// Constructeurs /// 49 CScalar(void); 50 explicit CScalar(const StdString & id); 51 CScalar(const CScalar & var); // Not implemented yet. 52 CScalar(const CScalar * const var); // Not implemented yet. 53 54 /// Destructeur /// 55 virtual ~CScalar(void); 56 57 public : 58 /// Accesseurs statiques /// 59 static StdString GetName(void); 60 static StdString GetDefName(void); 61 static ENodeType GetType(void); 62 63 public: 64 static CScalar* createScalar(); 65 66 public: 67 void checkAttributes(void); 68 void addRelFile(const StdString& filename); 69 bool IsWritten(const StdString& filename) const; 70 void checkAttributesOnClient(); 71 virtual void parse(xml::CXMLNode & node); 72 73 public: 74 bool hasTransformation(); 75 void solveInheritanceTransformation(); 76 TransMapTypes getAllTransformations(); 77 void duplicateTransformation(CScalar*); 78 CTransformation<CScalar>* addTransformation(ETranformationType transType, const StdString& id=""); 79 bool isEqual(CScalar* scalar); 80 81 private: 82 std::set<StdString> relFiles; 83 TransMapTypes transformationMap_; 84 85 void setTransformations(const TransMapTypes&); 86 87 private: 88 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 89 static std::map<StdString, ETranformationType> transformationMapList_; 90 static bool dummyTransformationMapList_; 91 92 93 DECLARE_REF_FUNC(Scalar,scalar) 94 95 }; // class CVar 96 ///-------------------------------------------------------------- 97 98 // Declare/Define CScalarGroup and CScalarDefinition 99 DECLARE_GROUP(CScalar); 52 EVENT_ID_SCALAR_DISTRIBUTION, 53 EVENT_ID_SEND_DISTRIBUTED_ATTRIBUTE, 54 } ; 55 static bool dispatchEvent(CEventServer& event); 56 57 58 public : 59 60 typedef CScalarAttributes RelAttributes; 61 typedef CScalarGroup RelGroup; 62 63 /// Constructeurs /// 64 CScalar(void); 65 explicit CScalar(const StdString & id); 66 CScalar(const CScalar & var); // Not implemented yet. 67 CScalar(const CScalar * const var); // Not implemented yet. 68 69 /// Destructeur /// 70 virtual ~CScalar(void); 71 72 public : 73 /// Accesseurs statiques /// 74 static StdString GetName(void); 75 static StdString GetDefName(void); 76 static ENodeType GetType(void); 77 78 public: 79 static CScalar* createScalar(); 80 81 public: 82 void checkAttributes(void); 83 bool checkAttributes_done_ = false ; 84 85 void addRelFile(const StdString& filename); 86 bool IsWritten(const StdString& filename) const; 87 virtual void parse(xml::CXMLNode & node); 88 89 public: 90 void sendScalarToCouplerOut(CContextClient* client, const string& fieldId, int posInGrid) ; 91 private: 92 std::set<CContextClient*> sendScalarToCouplerOut_done_ ; 93 94 public: 95 void makeAliasForCoupling(const string& fieldId, int posInGrid) ; 96 97 //////////////////////////////// 98 //// TRANSFORMATIONS //// 99 //////////////////////////////// 100 public: 101 typedef CTransformation<CScalar>::TransformationMapTypes TransMapTypes; 102 private: 103 static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m); 104 static std::map<StdString, ETranformationType> transformationMapList_; 105 static bool dummyTransformationMapList_; TransMapTypes transformationMap_; 106 void setTransformations(const TransMapTypes&); 107 108 public: 109 bool hasTransformation(); 110 TransMapTypes getAllTransformations(); 111 void duplicateTransformation(CScalar*); 112 CTransformation<CScalar>* addTransformation(ETranformationType transType, const StdString& id=""); 113 114 void solveInheritanceTransformation_old(); 115 void solveInheritanceTransformation(); 116 private: 117 bool solveInheritanceTransformation_done_= false ; 118 private: 119 CGenericAlgorithmTransformation* transformationAlgorithm_ = nullptr ; 120 public: 121 void setTransformationAlgorithm(CGenericAlgorithmTransformation* transformationAlgorithm) { transformationAlgorithm_=transformationAlgorithm ;} 122 CGenericAlgorithmTransformation* getTransformationAlgorithm(void) { return transformationAlgorithm_ ;} 123 private: 124 CTransformationPaths transformationPaths_ ; 125 public: 126 CTransformationPaths getTransformationPaths(void) {return transformationPaths_;} 127 void setTransformationPaths(const CTransformationPaths& transformationPaths) { transformationPaths_=transformationPaths ;} 128 //////////////////////////////// 129 //////////////////////////////// 130 131 bool isEqual(CScalar* scalar); 132 private: 133 /** Clients that have to send a scalar. There can be multiple clients in case of secondary server, otherwise only one client. */ 134 std::list<CContextClient*> clients; 135 std::set<CContextClient*> clientsSet; 136 public: 137 void setContextClient(CContextClient* contextClient) ; 138 139 private: 140 std::set<StdString> relFiles; 141 142 private: 143 /** define if the scalar is completed or not ie all attributes have been received before in case 144 of grid reading from file or coupling */ 145 bool isCompleted_=true ; 146 public: 147 /*! 148 \brief Check if a scalar is completed 149 Before make any scalar processing, we must be sure that all scalar informations have 150 been sent, for exemple when reading a grid in a file or when grid elements are sent by an 151 other context (coupling). So all direct reference of the scalar (scalar_ref) must be also completed 152 \return true if scalar and scalar reference are completed 153 */ 154 bool isCompleted(void) 155 { 156 if (hasDirectScalarReference()) if (!getDirectScalarReference()->isCompleted()) return false; 157 else return isCompleted_ ; 158 } 159 void setCompleted(void) { isCompleted_=true ; } 160 void unsetCompleted(void) { isCompleted_=false ; } 161 162 163 164 ////////////////////////////////////////////////////////////////////////////////////// 165 // this part is related to distribution, element definition, views and connectors // 166 ////////////////////////////////////////////////////////////////////////////////////// 167 private: 168 CLocalElement* localElement_ = nullptr ; 169 void initializeLocalElement(void) ; 170 171 public: 172 CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; } 173 CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;} 174 175 private: 176 void addFullView(void) ; 177 void addWorkflowView(void) ; 178 void addModelView(void) ; 179 180 private: 181 CLocalConnector* modelToWorkflowConnector_ ; 182 void computeModelToWorkflowConnector(void) ; 183 public: 184 CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;} 185 186 public: 187 void computeRemoteElement(CContextClient* client, EDistributionType) ; 188 void distributeToServer(CContextClient* client, std::map<int, CArray<size_t,1>>& globalIndex, CScattererConnector* &scattererConnector, 189 const string& scalarId="") ; 190 191 static void recvScalarDistribution(CEventServer& event) ; 192 void receivedScalarDistribution(CEventServer& event, int phasis) ; 193 void setServerMask(CArray<bool,1>& serverMask, CContextClient* client) ; 194 void sendDistributedAttributes(CContextClient* client, CScattererConnector& scattererConnector, const string& scalarId) ; 195 static void recvDistributedAttributes(CEventServer& event) ; 196 void recvDistributedAttributes(CEventServer& event, const string& type) ; 197 198 private: 199 map<CContextClient*, CDistributedElement*> remoteElement_ ; 200 public: 201 CDistributedElement* getRemoteElement(CContextClient* client) {return remoteElement_[client] ;} 202 private: 203 map<CContextClient*, CScattererConnector*> clientToServerConnector_ ; 204 public: 205 CScattererConnector* getClientToServerConnector(CContextClient* client) { return clientToServerConnector_[client] ;} 206 207 private: 208 CGathererConnector* gathererConnector_ ; 209 public: 210 CGathererConnector* getGathererConnector(void) { return gathererConnector_ ;} 211 private: 212 CGathererConnector* serverFromClientConnector_ ; 213 CDistributedElement* elementFrom_ ; 214 public: 215 CGathererConnector* getServerFromClientConnector(void) { return serverFromClientConnector_ ;} 216 217 private: 218 CScattererConnector* serverToClientConnector_ = nullptr ; 219 public: 220 CScattererConnector* getServerToClientConnector(void) { return serverToClientConnector_ ;} 221 222 private: 223 map<CContextClient*,CGathererConnector*> clientFromServerConnector_ ; 224 public: 225 CGathererConnector* getClientFromServerConnector(CContextClient* client) { return clientFromServerConnector_[client] ;} 226 227 private: 228 DECLARE_REF_FUNC(Scalar,scalar) 229 230 }; // class CVar 231 ///-------------------------------------------------------------- 232 233 // Declare/Define CScalarGroup and CScalarDefinition 234 DECLARE_GROUP(CScalar); 100 235 } // namespace xios 101 236 -
XIOS/dev/dev_trunk_graph/src/node/temporal_splitting.cpp
r1275 r2019 1 1 #include "temporal_splitting.hpp" 2 #include "axis_algorithm_temporal_splitting.hpp" 2 3 #include "type.hpp" 3 4 #include "axis.hpp" … … 29 30 bool CTemporalSplitting::registerTrans() 30 31 { 31 return registerTransformation(TRANS_TEMPORAL_SPLITTING, CTemporalSplitting::create);32 return registerTransformation(TRANS_TEMPORAL_SPLITTING, {create, getTransformation}); 32 33 } 33 34 … … 45 46 } 46 47 48 CGenericAlgorithmTransformation* CTemporalSplitting::createAlgorithm(bool isSource, 49 CGrid* gridDst, CGrid* gridSrc, 50 int elementPositionInGrid, 51 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 52 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 53 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 54 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 55 std::map<int, int>& elementPositionInGridDst2AxisPosition, 56 std::map<int, int>& elementPositionInGridDst2DomainPosition) 57 { 58 return CAxisAlgorithmTemporalSplitting::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 59 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 60 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 61 } 47 62 } -
XIOS/dev/dev_trunk_graph/src/node/temporal_splitting.hpp
r1275 r2019 20 20 class CAxis; 21 21 class CScalar; 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 22 24 ///-------------------------------------------------------------- 23 25 … … 40 42 typedef CObjectTemplate<CTemporalSplitting> SuperClass; 41 43 typedef CTemporalSplittingAttributes SuperClassAttribute; 44 typedef CTemporalSplitting MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 42 46 43 47 public : … … 55 59 static StdString GetDefName(void); 56 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_TEMPORAL_SPLITTING ;} 63 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 57 74 private: 58 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/variable.cpp
r1158 r2019 94 94 * 95 95 */ 96 void CVariable::sendValue() 97 { 98 CContext* context=CContext::getCurrent() ; 99 100 if (context->hasClient) 101 { 102 // Use correct context client to send message 103 // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1; 104 int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1; 105 for (int i = 0; i < nbSrvPools; ++i) 106 { 107 // CContextClient* contextClientTmp = (0 != context->clientPrimServer) ? context->clientPrimServer 108 CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i] 109 : context->client; 110 111 CEventClient event(this->getType(),EVENT_ID_VARIABLE_VALUE) ; 112 if (contextClientTmp->isServerLeader()) 113 { 114 CMessage msg ; 115 msg<<this->getId() ; 116 msg<<content ; 117 const std::list<int>& ranks = contextClientTmp->getRanksServerLeader(); 118 for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 119 event.push(*itRank,1,msg); 120 contextClientTmp->sendEvent(event) ; 121 } 122 else contextClientTmp->sendEvent(event) ; 123 } 124 } 125 } 126 127 void CVariable::sendValue(CContextClient* client, bool clientPrim /*= false*/) 96 97 void CVariable::sendValue(CContextClient* client) 128 98 { 129 99 CEventClient event(this->getType(),EVENT_ID_VARIABLE_VALUE) ; -
XIOS/dev/dev_trunk_graph/src/node/variable.hpp
r1158 r2019 79 79 80 80 //! Sending a request to set up variable data 81 void sendValue(); 82 void sendValue(CContextClient* client, bool clientPrim = false); 81 void sendValue(CContextClient* client); 83 82 84 83 static void recvValue(CEventServer& event) ; -
XIOS/dev/dev_trunk_graph/src/node/zoom_axis.cpp
r1201 r2019 1 1 #include "zoom_axis.hpp" 2 #include "axis_algorithm_zoom.hpp" 2 3 #include "type.hpp" 3 4 … … 26 27 bool CZoomAxis::registerTrans() 27 28 { 28 return registerTransformation(TRANS_ZOOM_AXIS, CZoomAxis::create);29 return registerTransformation(TRANS_ZOOM_AXIS, {create, getTransformation}); 29 30 } 30 31 … … 77 78 } 78 79 80 CGenericAlgorithmTransformation* CZoomAxis::createAlgorithm(bool isSource, 81 CGrid* gridDst, CGrid* gridSrc, 82 int elementPositionInGrid, 83 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 84 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 85 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 86 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 87 std::map<int, int>& elementPositionInGridDst2AxisPosition, 88 std::map<int, int>& elementPositionInGridDst2DomainPosition) 89 { 90 return CAxisAlgorithmZoom::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 91 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 92 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 93 } 79 94 } -
XIOS/dev/dev_trunk_graph/src/node/zoom_axis.hpp
r836 r2019 20 20 class CZoomAxis; 21 21 class CAxis; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CZoomAxis> SuperClass; 42 43 typedef CZoomAxisAttributes SuperClassAttribute; 44 typedef CZoomAxis MyClass ; 45 typedef CTransformation<CAxis> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_ZOOM_AXIS ;} 63 static CTransformation<CAxis>* getTransformation(const StdString& id) { return SuperClass::get(id);} 64 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); -
XIOS/dev/dev_trunk_graph/src/node/zoom_domain.cpp
r836 r2019 1 1 #include "zoom_domain.hpp" 2 #include "domain_algorithm_zoom.hpp" 2 3 #include "type.hpp" 3 4 … … 27 28 bool CZoomDomain::registerTrans() 28 29 { 29 registerTransformation(TRANS_ZOOM_DOMAIN, CZoomDomain::create);30 registerTransformation(TRANS_ZOOM_DOMAIN, {create, getTransformation}); 30 31 } 31 32 … … 72 73 } 73 74 75 CGenericAlgorithmTransformation* CZoomDomain::createAlgorithm(bool isSource, 76 CGrid* gridDst, CGrid* gridSrc, 77 int elementPositionInGrid, 78 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 79 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 80 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 81 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 82 std::map<int, int>& elementPositionInGridDst2AxisPosition, 83 std::map<int, int>& elementPositionInGridDst2DomainPosition) 84 { 85 return CDomainAlgorithmZoom::create(isSource, gridDst, gridSrc, this, elementPositionInGrid, 86 elementPositionInGridSrc2ScalarPosition, elementPositionInGridSrc2AxisPosition, elementPositionInGridSrc2DomainPosition, 87 elementPositionInGridDst2ScalarPosition, elementPositionInGridDst2AxisPosition, elementPositionInGridDst2DomainPosition); 88 } 74 89 } -
XIOS/dev/dev_trunk_graph/src/node/zoom_domain.hpp
r836 r2019 20 20 class CZoomDomain; 21 21 class CDomain; 22 22 class CGenericAlgorithmTransformation ; 23 class CGrid; 23 24 ///-------------------------------------------------------------- 24 25 … … 41 42 typedef CObjectTemplate<CZoomDomain> SuperClass; 42 43 typedef CZoomDomainAttributes SuperClassAttribute; 44 typedef CZoomDomain MyClass ; 45 typedef CTransformation<CDomain> SuperTransform ; 43 46 44 47 public : … … 56 59 static StdString GetDefName(void); 57 60 static ENodeType GetType(void); 61 const string& getId(void) { return this->SuperClass::getId();} 62 ETranformationType getTransformationType(void) { return TRANS_ZOOM_DOMAIN ;} 63 virtual void inheritFrom(SuperTransform* srcTransform) { solveDescInheritance(true, this->SuperClass::get((MyClass*)srcTransform)) ;} 64 static CTransformation<CDomain>* getTransformation(const StdString& id) { return SuperClass::get(id);} 65 virtual CGenericAlgorithmTransformation* createAlgorithm(bool isSource, 66 CGrid* gridDst, CGrid* gridSrc, 67 int elementPositionInGrid, 68 std::map<int, int>& elementPositionInGridSrc2ScalarPosition, 69 std::map<int, int>& elementPositionInGridSrc2AxisPosition, 70 std::map<int, int>& elementPositionInGridSrc2DomainPosition, 71 std::map<int, int>& elementPositionInGridDst2ScalarPosition, 72 std::map<int, int>& elementPositionInGridDst2AxisPosition, 73 std::map<int, int>& elementPositionInGridDst2DomainPosition) ; 58 74 private: 59 75 static bool registerTrans(); 60 76 static CTransformation<CDomain>* create(const StdString& id, xml::CXMLNode* node); 77 61 78 static bool _dummyRegistered; 62 79 }; // class CZoomDomain
Note: See TracChangeset
for help on using the changeset viewer.