Changeset 1869


Ignore:
Timestamp:
04/15/20 13:23:39 (18 months ago)
Author:
ymipsl
Message:

Some update...

YM

Location:
XIOS/dev/dev_ym/XIOS_COUPLING/src
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.cpp

    r1637 r1869  
    396396 
    397397  for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i]; 
     398  localDataSize_=ssize ; 
    398399 
    399400  localDataIndex_.resize(ssize); 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.hpp

    r1637 r1869  
    4747    const std::vector<int>& getLocalMaskedDataIndexOnClient(); 
    4848 
     49    size_t getLocalDataSize(void) { if (!isComputed_) createGlobalIndexSendToServer(); return localDataSize_ ;} 
    4950    std::vector<int> getNGlob() { return nGlob_; } 
    5051    std::vector<int> getDataNIndex() { return dataNIndex_; } 
     
    99100 
    100101    std::vector<int> localMaskedDataIndex_; 
     102    //!< the size of local data of the grid 
     103    size_t localDataSize_ ; 
    101104 
    102105  private: 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/source_filter.cpp

    r1794 r1869  
    3434    packet->status = CDataPacket::NO_ERROR; 
    3535 
    36     packet->data.resize(grid->storeIndex_client_.numElements());     
     36    packet->data.resize(grid->getStoreIndex_client().numElements());     
    3737     
    3838    if (compression) 
     
    8585            << " expected " << grid->storeIndex_fromSrv_.size() << " chunks but " << data.size() << " were given."); 
    8686 
    87     packet->data.resize(grid->storeIndex_client_.numElements()); 
     87    packet->data.resize(grid->getStoreIndex_client().numElements()); 
    8888    std::map<int, CArray<double, 1> >::const_iterator it, itEnd = data.end(); 
    8989    for (it = data.begin(); it != itEnd; it++) 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/spatial_transform_filter.cpp

    r1794 r1869  
    174174        gridTransformation->computeAll(dataAuxInputs, packet->timestamp); 
    175175      } 
    176       packet->data.resize(gridTransformation->getGridDestination()->storeIndex_client_.numElements()); 
     176      packet->data.resize(gridTransformation->getGridDestination()->getDataSize()); 
    177177      if (0 != packet->data.numElements()) 
    178178        (packet->data)(0) = defaultValue; 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/interface/c/icfield.cpp

    r1622 r1869  
    100100  { 
    101101     CTimer::get("XIOS").resume() ; 
    102      *domain_hdl_ret = field_hdl->grid->getDomain(domainIndex); 
     102     *domain_hdl_ret = field_hdl->getGrid()->getDomain(domainIndex); 
    103103     CTimer::get("XIOS").suspend(); 
    104104  } 
     
    109109  { 
    110110     CTimer::get("XIOS").resume() ; 
    111      *axis_hdl_ret = field_hdl->grid->getAxis(axisIndex); 
     111     *axis_hdl_ret = field_hdl->getGrid()->getAxis(axisIndex); 
    112112     CTimer::get("XIOS").suspend(); 
    113113  } 
     
    118118  { 
    119119     CTimer::get("XIOS").resume() ; 
    120      *scalar_hdl_ret = field_hdl->grid->getScalar(scalarIndex); 
     120     *scalar_hdl_ret = field_hdl->getGrid()->getScalar(scalarIndex); 
    121121     CTimer::get("XIOS").suspend(); 
    122122  } 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_input.cpp

    r1853 r1869  
    4848    CContext* context = CContext::getCurrent(); 
    4949 
    50     CGrid* grid = field->grid; 
     50    CGrid* grid = field->getGrid(); 
    5151 
    5252    if (!grid->doGridHaveDataToWrite()) 
     
    130130    StdString fieldId = field->getFieldOutputName(); 
    131131 
    132     CGrid* grid = field->grid; 
     132    CGrid* grid = field->getGrid(); 
    133133 
    134134    std::vector<CDomain*> domainP = grid->getDomains(); 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/io/nc4_data_output.cpp

    r1853 r1869  
    18051805 
    18061806        std::vector<StdString> dims, coodinates; 
    1807         CGrid* grid = field->grid; 
     1807        CGrid* grid = field->getGrid(); 
    18081808        if (!grid->doGridHaveDataToWrite()) 
    18091809          if (SuperClass::type==MULTI_FILE) return ; 
     
    23462346      { 
    23472347        CContext* context = CContext::getCurrent(); 
    2348         CGrid* grid = field->grid; 
     2348        CGrid* grid = field->getGrid(); 
    23492349 
    23502350        if (field->getNStep()<1)  
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp

    r1853 r1869  
    274274   TRY 
    275275   { 
     276     if (checkAttributes_done_) return ; 
     277 
    276278     CContext* context=CContext::getCurrent(); 
    277279 
     
    318320      if (!this->value.isEmpty()) 
    319321      { 
    320         // Avoid this check at writing because it fails in case of a hole 
    321         if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    322         { 
    323           StdSize true_size = value.numElements(); 
    324           if (this->n.getValue() != true_size) 
    325             ERROR("CAxis::checkAttributes(void)", 
    326                 << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " 
    327                 << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size 
    328                 << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); 
    329         } 
     322        StdSize true_size = value.numElements(); 
     323        if (this->n.getValue() != true_size) 
     324          ERROR("CAxis::checkAttributes(void)", 
     325              << "[ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] " 
     326              << "The axis is wrongly defined, attribute 'value' has a different size (" << true_size 
     327              << ") than the one defined by the \'size\' attribute (" << n.getValue() << ")."); 
    330328        this->hasValue = true; 
    331329      } 
    332330 
    333331      this->checkBounds(); 
    334  
    335       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    336       { 
    337         this->checkMask(); 
    338         this->checkData(); 
    339         this->checkLabel(); 
    340       } 
     332      this->checkMask(); 
     333      this->checkData(); 
     334      this->checkLabel(); 
     335       
     336      checkAttributes_done_ = true ; 
    341337   } 
    342338   CATCH_DUMP_ATTR 
     
    522518     Therefore, we should recheck them. 
    523519   */ 
     520   // ym : obsolete to be removed 
    524521   void CAxis::checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid, 
    525522                                                          CServerDistributionDescription::ServerDistributionType distType) 
     
    531528     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    532529     {         
     530       /* suppressed because of interface changed 
    533531       if (orderPositionInGrid == CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), distType)) 
    534532         computeConnectedClients(globalDim, orderPositionInGrid, distType); 
    535533       else if (index.numElements() != n_glo) computeConnectedClients(globalDim, orderPositionInGrid,  CServerDistributionDescription::ROOT_DISTRIBUTION); 
     534       */ 
    536535     } 
    537536 
     
    594593     \param [in] distType distribution type of the server. For now, we only have band distribution. 
    595594  */ 
    596   void CAxis::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 
    597                                      CServerDistributionDescription::ServerDistributionType distType) 
    598   TRY 
    599   { 
     595  void CAxis::computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid) 
     596  TRY 
     597  { 
     598    if (computeConnectedClients_done_.count(client)!=0) return ; 
     599    else computeConnectedClients_done_.insert(client) ; 
     600 
    600601    CContext* context = CContext::getCurrent(); 
    601  
    602     set<int> listNbServer ; 
    603  
    604     for (auto client : clients) 
    605     { 
    606       int nbServer = client->serverSize; 
    607       int range, clientSize = client->clientSize; 
    608       int rank = client->clientRank; 
    609  
    610       if (listNbServer.find(nbServer)==listNbServer.end()) 
    611       { 
    612         listNbServer.insert(nbServer) ; 
    613   
    614         if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 
    615         { 
    616           nbSenders.erase(nbServer); 
    617           connectedServerRank_.erase(nbServer); 
    618         } 
    619  
    620         size_t ni = this->n.getValue(); 
    621         size_t ibegin = this->begin.getValue(); 
    622         size_t nbIndex = index.numElements(); 
    623  
    624         // First of all, we should compute the mapping of the global index and local index of the current client 
    625         if (globalLocalIndexMap_.empty()) 
    626         { 
    627           for (size_t idx = 0; idx < nbIndex; ++idx) 
    628           { 
    629             globalLocalIndexMap_[index(idx)] = idx; 
    630           } 
    631         } 
    632  
    633         // Calculate the compressed index if any 
    634 //        std::set<int> writtenInd; 
    635 //        if (isCompressible_) 
    636 //        { 
    637 //          for (int idx = 0; idx < data_index.numElements(); ++idx) 
    638 //          { 
    639 //            int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni); 
    640 // 
    641 //            if (ind >= 0 && ind < ni && mask(ind)) 
    642 //            { 
    643 //              ind += ibegin; 
    644 //              writtenInd.insert(ind); 
    645 //            } 
    646 //          } 
    647 //        } 
    648  
    649         // Compute the global index of the current client (process) hold 
    650         std::vector<int> nGlobAxis(1); 
    651         nGlobAxis[0] = n_glo.getValue(); 
    652  
    653         size_t globalSizeIndex = 1, indexBegin, indexEnd; 
    654         for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; 
    655         indexBegin = 0; 
    656         if (globalSizeIndex <= clientSize) 
    657         { 
    658           indexBegin = rank%globalSizeIndex; 
    659           indexEnd = indexBegin; 
    660         } 
    661         else 
    662         { 
    663           for (int i = 0; i < clientSize; ++i) 
    664           { 
    665             range = globalSizeIndex / clientSize; 
    666             if (i < (globalSizeIndex%clientSize)) ++range; 
    667             if (i == client->clientRank) break; 
    668             indexBegin += range; 
    669           } 
    670           indexEnd = indexBegin + range - 1; 
    671         } 
    672  
    673         CArray<size_t,1> globalIndex(index.numElements()); 
    674         for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 
    675           globalIndex(idx) = index(idx); 
    676  
    677         // Describe the distribution of server side 
    678  
    679         CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); 
    680        
    681         std::vector<int> serverZeroIndex; 
    682         serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 
    683  
    684         std::list<int> serverZeroIndexLeader; 
    685         std::list<int> serverZeroIndexNotLeader;  
    686         CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
    687         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    688           *it = serverZeroIndex[*it]; 
    689  
    690         // Find out the connection between client and server side 
    691         CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 
    692         clientServerMap->computeServerIndexMapping(globalIndex, nbServer); 
    693         CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer();       
    694  
    695         indSrv_[nbServer].swap(globalIndexAxisOnServer); 
    696  
    697         if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) 
    698         { 
    699           for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; 
    700           serverZeroIndexLeader.clear() ; 
    701         } 
    702           
    703         CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(), 
    704                                                              ite = indSrv_[nbServer].end(); 
    705  
    706         for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 
    707  
    708         for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    709           connectedServerRank_[nbServer].push_back(*it); 
    710  
    711          // Even if a client has no index, it must connect to at least one server and  
    712          // send an "empty" data to this server 
    713          if (connectedServerRank_[nbServer].empty()) 
    714           connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 
    715  
    716         nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 
    717  
    718         delete clientServerMap; 
    719       } 
     602    CServerDistributionDescription::ServerDistributionType distType ; 
     603    int defaultDistributedPos = CServerDistributionDescription::defaultDistributedDimension(globalDim.size(), CServerDistributionDescription::BAND_DISTRIBUTION) ; 
     604     
     605    if (orderPositionInGrid == defaultDistributedPos) distType =  CServerDistributionDescription::BAND_DISTRIBUTION ; 
     606    else if (index.numElements() != n_glo) distType =  CServerDistributionDescription::ROOT_DISTRIBUTION ; 
     607    else return ; 
     608 
     609    int nbServer = client->serverSize; 
     610    int range, clientSize = client->clientSize; 
     611    int rank = client->clientRank; 
     612 
     613    if (listNbServer_.count(nbServer) == 0) 
     614    { 
     615      listNbServer_.insert(nbServer) ; 
     616 
     617      if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 
     618      { 
     619        nbSenders.erase(nbServer); 
     620        connectedServerRank_.erase(nbServer); 
     621      } 
     622 
     623      size_t ni = this->n.getValue(); 
     624      size_t ibegin = this->begin.getValue(); 
     625      size_t nbIndex = index.numElements(); 
     626 
     627      // First of all, we should compute the mapping of the global index and local index of the current client 
     628      if (globalLocalIndexMap_.empty()) 
     629      { 
     630        for (size_t idx = 0; idx < nbIndex; ++idx) 
     631        { 
     632          globalLocalIndexMap_[index(idx)] = idx; 
     633        } 
     634      } 
     635 
     636      // Calculate the compressed index if any 
     637      //        std::set<int> writtenInd; 
     638      //        if (isCompressible_) 
     639      //        { 
     640      //          for (int idx = 0; idx < data_index.numElements(); ++idx) 
     641      //          { 
     642      //            int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);  
     643      // 
     644      //            if (ind >= 0 && ind < ni && mask(ind)) 
     645      //            { 
     646      //              ind += ibegin; 
     647      //              writtenInd.insert(ind); 
     648      //            } 
     649      //          } 
     650      //        } 
     651 
     652      // Compute the global index of the current client (process) hold 
     653      std::vector<int> nGlobAxis(1); 
     654      nGlobAxis[0] = n_glo.getValue(); 
     655 
     656      size_t globalSizeIndex = 1, indexBegin, indexEnd; 
     657      for (int i = 0; i < nGlobAxis.size(); ++i) globalSizeIndex *= nGlobAxis[i]; 
     658      indexBegin = 0; 
     659      if (globalSizeIndex <= clientSize) 
     660      { 
     661        indexBegin = rank%globalSizeIndex; 
     662        indexEnd = indexBegin; 
     663      } 
     664      else 
     665      { 
     666        for (int i = 0; i < clientSize; ++i) 
     667        { 
     668          range = globalSizeIndex / clientSize; 
     669          if (i < (globalSizeIndex%clientSize)) ++range; 
     670          if (i == client->clientRank) break; 
     671          indexBegin += range; 
     672        } 
     673        indexEnd = indexBegin + range - 1; 
     674      } 
     675 
     676      CArray<size_t,1> globalIndex(index.numElements()); 
     677      for (size_t idx = 0; idx < globalIndex.numElements(); ++idx) 
     678        globalIndex(idx) = index(idx); 
     679 
     680      // Describe the distribution of server side 
     681 
     682      CServerDistributionDescription serverDescription(nGlobAxis, nbServer, distType); 
     683     
     684      std::vector<int> serverZeroIndex; 
     685      serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 
     686 
     687      std::list<int> serverZeroIndexLeader; 
     688      std::list<int> serverZeroIndexNotLeader;  
     689      CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
     690      for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     691        *it = serverZeroIndex[*it]; 
     692 
     693      // Find out the connection between client and server side 
     694      CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 
     695      clientServerMap->computeServerIndexMapping(globalIndex, nbServer); 
     696      CClientServerMapping::GlobalIndexMap& globalIndexAxisOnServer = clientServerMap->getGlobalIndexOnServer();       
     697 
     698      indSrv_[nbServer].swap(globalIndexAxisOnServer); 
     699 
     700      if (distType==CServerDistributionDescription::ROOT_DISTRIBUTION) 
     701      { 
     702        for(int i=1; i<nbServer; ++i) indSrv_[nbServer].insert(pair<int, vector<size_t> >(i,indSrv_[nbServer][0]) ) ; 
     703        serverZeroIndexLeader.clear() ; 
     704      } 
     705        
     706      CClientServerMapping::GlobalIndexMap::const_iterator it  = indSrv_[nbServer].begin(), 
     707                                                           ite = indSrv_[nbServer].end(); 
     708 
     709      for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 
     710 
     711      for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     712        connectedServerRank_[nbServer].push_back(*it); 
     713 
     714       // Even if a client has no index, it must connect to at least one server and  
     715       // send an "empty" data to this server 
     716       if (connectedServerRank_[nbServer].empty()) 
     717        connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 
     718 
     719      nbSenders[nbServer] = CClientServerMapping::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 
     720 
     721      delete clientServerMap; 
    720722    } 
    721723  } 
     
    14311433  CATCH_DUMP_ATTR 
    14321434 
     1435/*! 
     1436  \brief Check if a axis is completed 
     1437  Before make any axis processing, we must be sure that all axis informations have 
     1438  been sent, for exemple when reading a grid in a file or when grid elements are sent by an 
     1439  other context (coupling). So all direct reference of the axis (axis_ref) must be also completed 
     1440  \return true if axis and axis reference are completed 
     1441  */ 
     1442  bool CAxis::checkIfCompleted(void) 
     1443  { 
     1444    if (hasDirectAxisReference()) if (!getDirectAxisReference()->checkIfCompleted()) return false; 
     1445    return isCompleted_ ; 
     1446  } 
     1447 
     1448  /*! 
     1449  \brief Set a axis as completed 
     1450   When all information about a axis have been received, the axis is tagged as completed and is 
     1451   suitable for processing 
     1452  */ 
     1453  void CAxis::setCompleted(void) 
     1454  { 
     1455    if (hasDirectAxisReference()) getDirectAxisReference()->setCompleted() ; 
     1456    isCompleted_=true ; 
     1457  } 
     1458 
     1459  /*! 
     1460  \brief Set a axis as uncompleted 
     1461   When informations about a axis are expected from a grid reading from file or coupling, the axis is  
     1462   tagged as uncompleted and is not suitable for processing 
     1463  */ 
     1464  void CAxis::setUncompleted(void) 
     1465  { 
     1466    if (hasDirectAxisReference()) getDirectAxisReference()->setUncompleted() ; 
     1467    isCompleted_=false ; 
     1468  } 
     1469 
     1470 
     1471 
    14331472  /*! 
    14341473   * Go through the hierarchy to find the axis from which the transformations must be inherited 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp

    r1847 r1869  
    8686         void addRelFileCompressed(const StdString& filename); 
    8787 
    88          /// Vérifications /// 
    89          void checkAttributes(void); 
     88          
    9089 
    9190         /// Destructeur /// 
     
    102101 
    103102         static bool dispatchEvent(CEventServer& event);          
     103         
     104         /// Vérifications /// 
     105         void checkAttributes(void); 
     106         bool checkAttributes_done_ = false ; 
    104107          
    105108         void checkAttributesOnClient(); 
     
    121124         bool isEqual(CAxis* axis); 
    122125 
     126         bool checkIfCompleted(void) ; 
     127         void setCompleted(void) ; 
     128         void setUncompleted(void) ; 
     129 
    123130      public:  
    124131        bool hasValue;         
     
    127134 
    128135        CArray<int,1> localIndexToWriteOnServer; 
     136          
     137         void computeConnectedClients(CContextClient* client, const std::vector<int>& globalDim, int orderPositionInGrid); 
     138         private: std::set<CContextClient*> computeConnectedClients_done_ ; public : 
     139         /** The number of server of a context client. Avoid to re-compute indice computed in a previous computeConnectedClient */ 
     140         private: std::set<int> listNbServer_ ; public: 
    129141 
    130142      private: 
     
    137149         void sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid, 
    138150                                        CServerDistributionDescription::ServerDistributionType distType); 
    139          void computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid, 
    140                                      CServerDistributionDescription::ServerDistributionType distType); 
     151          
    141152 
    142153         void sendNonDistributedAttributes(void); 
     
    157168         std::list<CContextClient*> clients; 
    158169         std::set<CContextClient*> clientsSet; 
     170 
     171         /** define if the axis is completed or not ie all attributes have been received before in case  
     172             of grid reading from file or coupling */  
     173         bool isCompleted_=true ;   
    159174 
    160175         bool isChecked; 
     
    165180         //! True if and only if the data defined on the axis can be outputted in a compressed way 
    166181         bool isCompressible_; 
     182 
    167183         std::map<int, map<int,int> > nbSenders; // Mapping of number of communicating client to a server 
    168184         std::map<int, std::unordered_map<int, vector<size_t> > > indSrv_; // Global index of each client sent to server 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp

    r1853 r1869  
    730730 
    731731     // Distribute files between secondary servers according to the data size 
    732      distributeFiles(); 
     732     distributeFiles(this->enabledWriteModeFiles); 
    733733 
    734734     // Check grid and calculate its distribution 
     
    852852   and the active fields (fields will be written onto active files) 
    853853   */ 
    854  
    855    void CContext::closeDefinition(void) 
     854  void CContext::closeDefinition(void) 
    856855   TRY 
    857856   { 
    858857     CTimer::get("Context : close definition").resume() ; 
     858      
     859     // create intercommunicator with servers.  
     860     // not sure it is the good place to be called here  
     861     createServerInterComm() ; 
     862 
     863 
     864     // After xml is parsed, there are some more works with post processing 
     865//     postProcessing(); 
     866 
     867    // Make sure the calendar was correctly created 
     868    if (!calendar) 
     869      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"") 
     870    else if (calendar->getTimeStep() == NoneDu) 
     871      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"") 
     872    // Calendar first update to set the current date equals to the start date 
     873    calendar->update(0); 
     874 
     875    // Résolution des héritages descendants (càd des héritages de groupes) 
     876    // pour chacun des contextes. 
     877    solveDescInheritance(true); 
     878  
     879    // Solve inheritance for field to know if enabled or not. 
     880    for (auto field : CField::getAll()) field->solveRefInheritance(); 
     881 
     882    // Check if some axis, domains or grids are eligible to for compressed indexed output. 
     883    // Warning: This must be done after solving the inheritance and before the rest of post-processing 
     884    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();       
     885 
     886      // Check if some automatic time series should be generated 
     887      // Warning: This must be done after solving the inheritance and before the rest of post-processing       
     888 
     889    // The timeseries should only be prepared in client 
     890    prepareTimeseries(); 
     891 
     892    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. 
     893    findEnabledFiles(); 
     894    findEnabledWriteModeFiles(); 
     895    findEnabledReadModeFiles(); 
     896    findEnabledCouplerIn(); 
     897    findEnabledCouplerOut(); 
     898    createCouplerInterCommunicator() ; 
     899 
     900    // Find all enabled fields of each file       
     901    const vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles); 
     902    const vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles); 
     903    const vector<CField*>&& CouplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut); 
     904    const vector<CField*>&& CouplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn); 
     905    findFieldsWithReadAccess(); 
     906    const vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ; 
     907       
     908// find all field potentially at workflow end 
     909    vector<CField*> endWorkflowFields ; 
     910    endWorkflowFields.reserve(fileOutField.size()+CouplerOutField.size()+fieldWithReadAccess.size()) ; 
     911    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ; 
     912    endWorkflowFields.insert(endWorkflowFields.end(),CouplerOutField.begin(), CouplerOutField.end()) ; 
     913    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ; 
     914 
     915    for(auto endWorkflowField : endWorkflowFields) endWorkflowField->buildWorkflowGraph(garbageCollector) ; 
    859916     
    860     // 
    861     postProcessingGlobalAttributes(); 
     917    // Distribute files between secondary servers according to the data size => assign a context to a file 
     918    if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles); 
     919    else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ; 
     920 
     921    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
     922    { 
     923      for(auto field : fileOutField)  
     924      { 
     925        field->connectToFileServer(garbageCollector) ; // connect the field to server filter 
     926        field->computeGridIndexToFileServer() ; // compute grid index for transfer to the server context 
     927      } 
     928    } 
     929     
     930 
     931 
     932 
     933 
     934    // For now, only read files with client and only one level server 
     935    // if (hasClient && !hasServer) findEnabledReadModeFiles();       
     936 
     937    // Find all enabled fields of each file       
     938    findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 
     939    findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 
     940 
     941    // For now, only read files with client and only one level server 
     942    // if (hasClient && !hasServer)  
     943    //   findAllEnabledFieldsInFiles(this->enabledReadModeFiles);       
     944 
     945    if (serviceType_==CServicesManager::CLIENT) 
     946    { 
     947      initReadFiles(); 
     948      // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis) 
     949      this->readAttributesOfEnabledFieldsInReadModeFiles(); 
     950    } 
     951 
     952    // Only search and rebuild all reference objects of enable fields, don't transform 
     953    this->solveOnlyRefOfEnabledFields(); 
     954 
     955    // Search and rebuild all reference object of enabled fields, and transform 
     956    this->solveAllRefOfEnabledFieldsAndTransform(); 
     957 
     958    // Find all fields with read access from the public API 
     959    if (serviceType_==CServicesManager::CLIENT) findFieldsWithReadAccess(); 
     960    // and solve the all reference for them 
     961    if (serviceType_==CServicesManager::CLIENT) solveAllRefOfFieldsWithReadAccess(); 
     962 
     963    isPostProcessed = true; 
     964 
     965 
     966 
     967    // Distribute files between secondary servers according to the data size 
     968    distributeFiles(this->enabledWriteModeFiles); 
     969 
     970    // Check grid and calculate its distribution 
     971    checkGridEnabledFields(); 
     972 
     973    setClientServerBuffer(client, (serviceType_==CServicesManager::CLIENT) ) ; 
     974    for (int i = 0; i < clientPrimServer.size(); ++i) 
     975         setClientServerBuffer(clientPrimServer[i], true); 
     976 
     977     
     978    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
     979    {  
     980      if (serviceType_==CServicesManager::GATHERER) 
     981      {  
     982        for (auto it=clientPrimServer.begin(); it!=clientPrimServer.end();++it)  
     983        { 
     984          this->sendAllAttributesToServer(*it); // Send all attributes of current context to server 
     985          CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(*it); // Send all attributes of current calendar 
     986        } 
     987      } 
     988      else  
     989      { 
     990        this->sendAllAttributesToServer(client);   // Send all attributes of current context to server 
     991        CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current calendar 
     992      } 
     993 
     994      // We have enough information to send to server 
     995      // First of all, send all enabled files 
     996      sendEnabledFiles(this->enabledWriteModeFiles); 
     997      // We only use server-level 1 (for now) to read data 
     998      if (serviceType_==CServicesManager::CLIENT)  sendEnabledFiles(this->enabledReadModeFiles); 
     999 
     1000      // Then, send all enabled fields       
     1001      sendEnabledFieldsInFiles(this->enabledWriteModeFiles); 
     1002       
     1003      if (serviceType_==CServicesManager::CLIENT) sendEnabledFieldsInFiles(this->enabledReadModeFiles); 
     1004 
     1005      // Then, check whether we have domain_ref, axis_ref or scalar_ref attached to the enabled fields 
     1006      // If any, so send them to server 
     1007      sendRefDomainsAxisScalars(this->enabledWriteModeFiles);  
     1008      
     1009      if (serviceType_==CServicesManager::CLIENT) sendRefDomainsAxisScalars(this->enabledReadModeFiles);         
     1010 
     1011      // Check whether enabled fields have grid_ref, if any, send this info to server 
     1012      sendRefGrid(this->enabledFiles); 
     1013      // This code may be useful in the future when we want to seperate completely read and write 
     1014      // sendRefGrid(this->enabledWriteModeFiles); 
     1015      // if (!hasServer) 
     1016      //   sendRefGrid(this->enabledReadModeFiles); 
     1017       
     1018      // A grid of enabled fields composed of several components which must be checked then their 
     1019      // checked attributes should be sent to server 
     1020      sendGridComponentEnabledFieldsInFiles(this->enabledFiles); // This code can be seperated in two (one for reading, another for writing) 
     1021 
     1022      // We have a xml tree on the server side and now, it should be also processed 
     1023      sendPostProcessing(); 
     1024        
     1025      // Finally, we send information of grid itself to server  
     1026      sendGridEnabledFieldsInFiles(this->enabledWriteModeFiles);        
     1027      
     1028      if (serviceType_==CServicesManager::CLIENT) sendGridEnabledFieldsInFiles(this->enabledReadModeFiles);        
     1029    } 
     1030    allProcessed = true; 
     1031 
    8621032 
    8631033    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendPostProcessingGlobalAttributes(); 
     
    8841054     
    8851055    CTimer::get("Context : close definition").suspend() ; 
    886    } 
    887    CATCH_DUMP_ATTR 
    888  
    889    void CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) 
    890    TRY 
    891    { 
     1056  } 
     1057  CATCH_DUMP_ATTR 
     1058 
     1059 
     1060   void CContext::closeDefinition_old(void) 
     1061   TRY 
     1062   { 
     1063     CTimer::get("Context : close definition").resume() ; 
     1064     
     1065    // 
     1066    postProcessingGlobalAttributes(); 
     1067 
     1068    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendPostProcessingGlobalAttributes(); 
     1069 
     1070    // There are some processings that should be done after all of above. For example: check mask or index 
     1071    this->buildFilterGraphOfEnabledFields(); 
     1072     
     1073     if (serviceType_==CServicesManager::CLIENT) 
     1074    { 
     1075      buildFilterGraphOfFieldsWithReadAccess(); 
     1076      postProcessFilterGraph(); // For coupling in, modify this later 
     1077    } 
     1078     
     1079    checkGridEnabledFields();    
     1080 
     1081    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) this->sendProcessingGridOfEnabledFields(); 
     1082    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) this->sendCloseDefinition(); 
     1083 
     1084    // Nettoyage de l'arborescence 
     1085    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) CleanTree(); // Only on client side?? 
     1086 
     1087    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) sendCreateFileHeader(); 
     1088    if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles(); 
     1089     
     1090    CTimer::get("Context : close definition").suspend() ; 
     1091   } 
     1092   CATCH_DUMP_ATTR 
     1093 
     1094   vector<CField*> CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles) 
     1095   TRY 
     1096   { 
     1097     vector<CField*> fields ; 
    8921098     for (unsigned int i = 0; i < activeFiles.size(); i++) 
    893      (void)activeFiles[i]->getEnabledFields(); 
    894    } 
    895    CATCH_DUMP_ATTR 
     1099     { 
     1100        const vector<CField*>&& field=activeFiles[i]->getEnabledFields() ; 
     1101        fields.insert(fields.end(),field.begin(),field.end()); 
     1102     } 
     1103     return fields ; 
     1104   } 
     1105   CATCH_DUMP_ATTR 
     1106 
     1107   vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles) 
     1108   TRY 
     1109   { 
     1110     vector<CField*> fields ; 
     1111     for(auto file : activeFiles) 
     1112     { 
     1113        const vector<CField*>&& fieldList=file->getEnabledFields() ; 
     1114        for(auto field : fieldList) field->setFileOut(file) ; 
     1115        fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 
     1116     } 
     1117     return fields ; 
     1118   } 
     1119   CATCH_DUMP_ATTR 
     1120 
     1121   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles) 
     1122   TRY 
     1123   { 
     1124     vector<CField*> fields ; 
     1125     for(auto file : activeFiles) 
     1126     { 
     1127        const vector<CField*>&& fieldList=file->getEnabledFields() ; 
     1128        for(auto field : fieldList) field->setFileIn(file) ; 
     1129        fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 
     1130     } 
     1131     return fields ; 
     1132   } 
     1133   CATCH_DUMP_ATTR 
     1134 
     1135   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut) 
     1136   TRY 
     1137   { 
     1138     vector<CField*> fields ; 
     1139     for (auto couplerOut :activeCouplerOut) 
     1140     { 
     1141        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ; 
     1142        for(auto field : fieldList) field->setCouplerOut(couplerOut) ; 
     1143        fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 
     1144     } 
     1145     return fields ; 
     1146   } 
     1147   CATCH_DUMP_ATTR 
     1148 
     1149   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn) 
     1150   TRY 
     1151   { 
     1152     vector<CField*> fields ; 
     1153     for (auto couplerIn :activeCouplerIn) 
     1154     { 
     1155        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ; 
     1156        for(auto field : fieldList) field->setCouplerIn(couplerIn) ; 
     1157        fields.insert(fields.end(),fieldList.begin(),fieldList.end()); 
     1158     } 
     1159     return fields ; 
     1160   } 
     1161   CATCH_DUMP_ATTR 
     1162 
     1163 
    8961164 
    8971165   void CContext::readAttributesOfEnabledFieldsInReadModeFiles() 
     
    10811349  TRY 
    10821350  { 
    1083     fieldsWithReadAccess.clear(); 
     1351    fieldsWithReadAccess_.clear(); 
    10841352    const vector<CField*> allFields = CField::getAll(); 
    10851353    for (size_t i = 0; i < allFields.size(); ++i) 
    10861354    { 
    10871355      CField* field = allFields[i]; 
    1088  
    1089       if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read) 
    1090         field->read_access = true; 
    1091       else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled)) 
    1092         fieldsWithReadAccess.push_back(field); 
     1356      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled)) 
     1357      { 
     1358        fieldsWithReadAccess_.push_back(field); 
     1359        field->setModelOut() ; 
     1360      } 
    10931361    } 
    10941362  } 
     
    10981366  TRY 
    10991367  { 
    1100     for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i) 
    1101       fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false); 
     1368    for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i) 
     1369      fieldsWithReadAccess_[i]->solveAllReferenceEnabledField(false); 
    11021370  } 
    11031371  CATCH_DUMP_ATTR 
     
    11061374  TRY 
    11071375  { 
    1108     for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i) 
    1109       fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true); 
     1376    for (size_t i = 0; i < fieldsWithReadAccess_.size(); ++i) 
     1377      fieldsWithReadAccess_[i]->buildFilterGraph(garbageCollector, true); 
    11101378  } 
    11111379  CATCH_DUMP_ATTR 
     
    11391407      unsigned int i = 0; 
    11401408      for (i = 0; i < vecSize; ++i) 
    1141         allGrids[i]->solveDomainAxisRefInheritance(apply); 
     1409        allGrids[i]->solveElementsRefInheritance(apply); 
    11421410 
    11431411   } 
     
    12271495 
    12281496 
    1229    void CContext::distributeFiles(void) 
     1497   void CContext::distributeFiles(const vector<CFile*>& files) 
    12301498   TRY 
    12311499   { 
     
    12331501     distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory); 
    12341502 
    1235      if (distFileMemory) distributeFileOverMemoryBandwith() ; 
    1236      else distributeFileOverBandwith() ; 
    1237    } 
    1238    CATCH_DUMP_ATTR 
    1239  
    1240    void CContext::distributeFileOverBandwith(void) 
     1503     if (distFileMemory) distributeFileOverMemoryBandwith(files) ; 
     1504     else distributeFileOverBandwith(files) ; 
     1505   } 
     1506   CATCH_DUMP_ATTR 
     1507 
     1508   void CContext::distributeFileOverBandwith(const vector<CFile*>& files) 
    12411509   TRY 
    12421510   { 
    12431511     double eps=std::numeric_limits<double>::epsilon()*10 ; 
    12441512      
    1245      if (serviceType_==CServicesManager::GATHERER) 
    1246      { 
    1247        std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 
    1248        int nbPools = clientPrimServer.size(); 
    1249  
    1250        // (1) Find all enabled files in write mode 
    1251        // for (int i = 0; i < this->enabledFiles.size(); ++i) 
    1252        // { 
    1253        //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 
    1254        //    enabledWriteModeFiles.push_back(enabledFiles[i]); 
    1255        // } 
    1256  
    1257        // (2) Estimate the data volume for each file 
    1258        int size = this->enabledWriteModeFiles.size(); 
    1259        std::vector<std::pair<double, CFile*> > dataSizeMap; 
    1260        double dataPerPool = 0; 
    1261        int nfield=0 ; 
    1262        ofs<<size<<endl ; 
    1263        for (size_t i = 0; i < size; ++i) 
     1513     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out); 
     1514     int nbPools = clientPrimServer.size(); 
     1515 
     1516     // (1) Find all enabled files in write mode 
     1517     // for (int i = 0; i < this->enabledFiles.size(); ++i) 
     1518     // { 
     1519     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write )) 
     1520     //    enabledWriteModeFiles.push_back(enabledFiles[i]); 
     1521     // } 
     1522 
     1523     // (2) Estimate the data volume for each file 
     1524     int size = files.size(); 
     1525     std::vector<std::pair<double, CFile*> > dataSizeMap; 
     1526     double dataPerPool = 0; 
     1527     int nfield=0 ; 
     1528     ofs<<size<<endl ; 
     1529     for (size_t i = 0; i < size; ++i) 
     1530     { 
     1531       CFile* file = files[i]; 
     1532       ofs<<file->getId()<<endl ; 
     1533       StdSize dataSize=0; 
     1534       std::vector<CField*> enabledFields = file->getEnabledFields(); 
     1535       size_t numEnabledFields = enabledFields.size(); 
     1536       ofs<<numEnabledFields<<endl ; 
     1537       for (size_t j = 0; j < numEnabledFields; ++j) 
    12641538       { 
    1265          CFile* file = this->enabledWriteModeFiles[i]; 
    1266          ofs<<file->getId()<<endl ; 
    1267          StdSize dataSize=0; 
    1268          std::vector<CField*> enabledFields = file->getEnabledFields(); 
    1269          size_t numEnabledFields = enabledFields.size(); 
    1270          ofs<<numEnabledFields<<endl ; 
    1271          for (size_t j = 0; j < numEnabledFields; ++j) 
     1539         dataSize += enabledFields[j]->getGlobalWrittenSize() ; 
     1540         ofs<<enabledFields[j]->getGrid()->getId()<<endl ; 
     1541         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 
     1542       } 
     1543       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 
     1544       double dataSizeSec= dataSize/ outFreqSec; 
     1545       ofs<<dataSizeSec<<endl ; 
     1546       nfield++ ; 
     1547// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting 
     1548       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 
     1549       dataPerPool += dataSizeSec; 
     1550     } 
     1551     dataPerPool /= nbPools; 
     1552     std::sort(dataSizeMap.begin(), dataSizeMap.end()); 
     1553 
     1554     // (3) Assign contextClient to each enabled file 
     1555 
     1556     std::multimap<double,int> poolDataSize ; 
     1557// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 
     1558 
     1559     int j; 
     1560     double dataSize ; 
     1561     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ;   
     1562              
     1563     for (int i = dataSizeMap.size()-1; i >= 0; --i) 
     1564     { 
     1565       dataSize=(*poolDataSize.begin()).first ; 
     1566       j=(*poolDataSize.begin()).second ; 
     1567       dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 
     1568       dataSize+=dataSizeMap[i].first; 
     1569       poolDataSize.erase(poolDataSize.begin()) ; 
     1570       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ;  
     1571     } 
     1572 
     1573     for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ; 
     1574   } 
     1575   CATCH_DUMP_ATTR 
     1576 
     1577   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList) 
     1578   TRY 
     1579   { 
     1580     int nbPools = clientPrimServer.size(); 
     1581     double ratio=0.5 ; 
     1582     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 
     1583 
     1584     int nFiles = filesList.size(); 
     1585     vector<SDistFile> files(nFiles); 
     1586     vector<SDistGrid> grids; 
     1587     map<string,int> gridMap ; 
     1588     string gridId;  
     1589     int gridIndex=0 ; 
     1590 
     1591     for (size_t i = 0; i < nFiles; ++i) 
     1592     { 
     1593       StdSize dataSize=0; 
     1594       CFile* file = filesList[i]; 
     1595       std::vector<CField*> enabledFields = file->getEnabledFields(); 
     1596       size_t numEnabledFields = enabledFields.size(); 
     1597 
     1598       files[i].id_=file->getId() ; 
     1599       files[i].nbGrids_=numEnabledFields; 
     1600       files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 
     1601          
     1602       for (size_t j = 0; j < numEnabledFields; ++j) 
     1603       { 
     1604         gridId=enabledFields[j]->getGrid()->getId() ; 
     1605         if (gridMap.find(gridId)==gridMap.end()) 
    12721606         { 
    1273            dataSize += enabledFields[j]->getGlobalWrittenSize() ; 
    1274            ofs<<enabledFields[j]->grid->getId()<<endl ; 
    1275            ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ; 
     1607            gridMap[gridId]=gridIndex  ; 
     1608            SDistGrid newGrid;  
     1609            grids.push_back(newGrid) ; 
     1610            gridIndex++ ; 
    12761611         } 
    1277          double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 
    1278          double dataSizeSec= dataSize/ outFreqSec; 
    1279          ofs<<dataSizeSec<<endl ; 
    1280          nfield++ ; 
    1281 // add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting 
    1282          dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file)); 
    1283          dataPerPool += dataSizeSec; 
     1612         files[i].assignedGrid_[j]=gridMap[gridId] ; 
     1613         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 
     1614         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 
    12841615       } 
    1285        dataPerPool /= nbPools; 
    1286        std::sort(dataSizeMap.begin(), dataSizeMap.end()); 
    1287  
    1288        // (3) Assign contextClient to each enabled file 
    1289  
    1290        std::multimap<double,int> poolDataSize ; 
    1291 // multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11 
    1292  
    1293        int j; 
    1294        double dataSize ; 
    1295        for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ;   
    1296                
    1297        for (int i = dataSizeMap.size()-1; i >= 0; --i) 
     1616       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 
     1617       files[i].bandwith_= dataSize/ outFreqSec ; 
     1618     } 
     1619 
     1620     double bandwith=0 ; 
     1621     double memory=0 ; 
     1622    
     1623     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ; 
     1624     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 
     1625 
     1626     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ; 
     1627     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 
     1628        
     1629     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 
     1630 
     1631     vector<double> memorySize(nbPools,0.) ; 
     1632     vector< set<int> > serverGrids(nbPools) ; 
     1633     vector<double> bandwithSize(nbPools,0.) ; 
     1634        
     1635     for (size_t i = 0; i < nFiles; ++i) 
     1636     { 
     1637       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 
     1638       for(int j=0 ; j<files[i].nbGrids_;j++) 
    12981639       { 
    1299          dataSize=(*poolDataSize.begin()).first ; 
    1300          j=(*poolDataSize.begin()).second ; 
    1301          dataSizeMap[i].second->setContextClient(clientPrimServer[j]); 
    1302          dataSize+=dataSizeMap[i].first; 
    1303          poolDataSize.erase(poolDataSize.begin()) ; 
    1304          poolDataSize.insert(std::pair<double,int>(dataSize,j)) ;  
     1640         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 
     1641         { 
     1642           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 
     1643           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 
     1644         } 
    13051645       } 
    1306  
    1307        for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ; 
    1308   
    1309        for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 
    1310        { 
    1311          enabledReadModeFiles[i]->setContextClient(client);           
    1312        } 
    1313      } 
    1314      else 
    1315      { 
    1316        for (int i = 0; i < this->enabledFiles.size(); ++i) 
    1317          enabledFiles[i]->setContextClient(client); 
    1318      } 
    1319    } 
    1320    CATCH_DUMP_ATTR 
    1321  
    1322    void CContext::distributeFileOverMemoryBandwith(void) 
    1323    TRY 
    1324    { 
    1325      if (serviceType_==CServicesManager::GATHERER) 
    1326      { 
    1327        int nbPools = clientPrimServer.size(); 
    1328        double ratio=0.5 ; 
    1329        ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio); 
    1330  
    1331        int nFiles = this->enabledWriteModeFiles.size(); 
    1332        vector<SDistFile> files(nFiles); 
    1333        vector<SDistGrid> grids; 
    1334        map<string,int> gridMap ; 
    1335        string gridId;  
    1336        int gridIndex=0 ; 
    1337  
    1338        for (size_t i = 0; i < nFiles; ++i) 
    1339        { 
    1340          StdSize dataSize=0; 
    1341          CFile* file = this->enabledWriteModeFiles[i]; 
    1342          std::vector<CField*> enabledFields = file->getEnabledFields(); 
    1343          size_t numEnabledFields = enabledFields.size(); 
    1344  
    1345          files[i].id_=file->getId() ; 
    1346          files[i].nbGrids_=numEnabledFields; 
    1347          files[i].assignedGrid_ = new int[files[i].nbGrids_] ; 
    1348           
    1349          for (size_t j = 0; j < numEnabledFields; ++j) 
    1350          { 
    1351            gridId=enabledFields[j]->grid->getId() ; 
    1352            if (gridMap.find(gridId)==gridMap.end()) 
    1353            { 
    1354               gridMap[gridId]=gridIndex  ; 
    1355               SDistGrid newGrid;  
    1356               grids.push_back(newGrid) ; 
    1357               gridIndex++ ; 
    1358            } 
    1359            files[i].assignedGrid_[j]=gridMap[gridId] ; 
    1360            grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ; 
    1361            dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull 
    1362          } 
    1363          double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ; 
    1364          files[i].bandwith_= dataSize/ outFreqSec ; 
    1365        } 
    1366  
    1367        double bandwith=0 ; 
    1368        double memory=0 ; 
    1369     
    1370        for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ; 
    1371        for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ; 
    1372  
    1373        for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ; 
    1374        for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ; 
    1375         
    1376        distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ; 
    1377  
    1378        vector<double> memorySize(nbPools,0.) ; 
    1379        vector< set<int> > serverGrids(nbPools) ; 
    1380        vector<double> bandwithSize(nbPools,0.) ; 
    1381         
    1382        for (size_t i = 0; i < nFiles; ++i) 
    1383        { 
    1384          bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ; 
    1385          for(int j=0 ; j<files[i].nbGrids_;j++) 
    1386          { 
    1387            if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end()) 
    1388            { 
    1389              memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio); 
    1390              serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ; 
    1391            } 
    1392          } 
    1393          enabledWriteModeFiles[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 
    1394          delete [] files[i].assignedGrid_ ; 
    1395        } 
    1396  
    1397        for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ; 
    1398        for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 
    1399  
    1400  
    1401        for (int i = 0; i < this->enabledReadModeFiles.size(); ++i) 
    1402        { 
    1403          enabledReadModeFiles[i]->setContextClient(client);           
    1404        } 
    1405  
    1406    } 
    1407    else 
    1408    { 
    1409      for (int i = 0; i < this->enabledFiles.size(); ++i) 
    1410         enabledFiles[i]->setContextClient(client); 
    1411    } 
    1412 } 
     1646       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ; 
     1647       delete [] files[i].assignedGrid_ ; 
     1648     } 
     1649 
     1650     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ; 
     1651     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ; 
     1652 
     1653   } 
    14131654   CATCH_DUMP_ATTR 
    14141655 
     
    17592000      // Check if some axis, domains or grids are eligible to for compressed indexed output. 
    17602001      // Warning: This must be done after solving the inheritance and before the rest of post-processing 
    1761       checkAxisDomainsGridsEligibilityForCompressedOutput();       
     2002      checkAxisDomainsGridsEligibilityForCompressedOutput();      // only for field written on IO_SERVER service ???? 
    17622003 
    17632004      // Check if some automatic time series should be generated 
    17642005      // Warning: This must be done after solving the inheritance and before the rest of post-processing       
    1765  
    1766       // The timeseries should only be prepared in client 
    1767  
    1768       if (serviceType_==CServicesManager::CLIENT) prepareTimeseries(); 
     2006      prepareTimeseries(); 
    17692007 
    17702008      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers à sortir. 
     
    17742012      findEnabledCouplerIn(); 
    17752013      findEnabledCouplerOut(); 
    1776        
    17772014      createCouplerInterCommunicator() ; 
     2015 
     2016      // Find all enabled fields of each file       
     2017      const vector<CField*>&& fileOutField = findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 
     2018      const vector<CField*>&& fileInField = findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 
     2019      const vector<CField*>&& CouplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut); 
     2020      const vector<CField*>&& CouplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn); 
     2021 
     2022 
    17782023 
    17792024      // For now, only read files with client and only one level server 
    17802025      // if (hasClient && !hasServer) findEnabledReadModeFiles();       
    17812026 
    1782       // Find all enabled fields of each file       
    1783       findAllEnabledFieldsInFiles(this->enabledWriteModeFiles); 
    1784       findAllEnabledFieldsInFiles(this->enabledReadModeFiles); 
    17852027 
    17862028      // For now, only read files with client and only one level server 
     
    19742216   TRY 
    19752217   { 
    1976      if (!(serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)) return; 
    1977  
    19782218     const std::vector<CFile*> allFiles = CFile::getAll(); 
    19792219     for (size_t i = 0; i < allFiles.size(); i++) 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.hpp

    r1848 r1869  
    114114 
    115115         void closeDefinition(void); 
    116  
     116         void closeDefinition_old(void); 
     117 
     118         // to be removed      
     119         std::vector<CField*> findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 
    117120         // Some functions to process context 
    118          void findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles); 
     121         std::vector<CField*> findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles); 
     122         std::vector<CField*> findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles); 
     123         std::vector<CField*> findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut); 
     124         std::vector<CField*> findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn); 
    119125         // void findAllEnabledFields(void); 
    120126         // void findAllEnabledFieldsInReadModeFiles(void); 
     
    156162 
    157163         // Distribute files (in write mode) among secondary-server pools according to the estimated data flux 
    158          void distributeFiles(void); 
    159          void distributeFileOverBandwith() ; 
    160          void distributeFileOverMemoryBandwith() ; 
     164         void distributeFiles(const std::vector<CFile*>& files); 
     165         void distributeFileOverBandwith(const std::vector<CFile*>& files) ; 
     166         void distributeFileOverMemoryBandwith(const std::vector<CFile*>& files) ; 
    161167          
    162168         // Send context close definition 
     
    244250         bool setProcessingEvent(void) {isProcessingEvent_=true ;} 
    245251         bool unsetProcessingEvent(void) {isProcessingEvent_=false ;} 
    246          MPI_Comm getIntraComm(void) { return intraComm_ ;} 
     252         MPI_Comm getIntraComm(void) {return intraComm_ ;} 
     253         int getIntraCommRank(void) {return intraCommRank_;} 
     254         int getIntraCommSize(void) {return intraCommSize_;} 
    247255 
    248256         void addCouplingChanel(const std::string& contextId, bool out) ; 
     
    265273         // List of all enabled fields whose instant data is accessible from the public API 
    266274         // but which are not part of a file 
    267          std::vector<CField*> fieldsWithReadAccess; 
     275         std::vector<CField*> fieldsWithReadAccess_; 
    268276 
    269277         // Context root 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp

    r1853 r1869  
    17211721   CATCH_DUMP_ATTR 
    17221722 
    1723    void CDomain::checkAttributesOnClientAfterTransformation() 
    1724    TRY 
    1725    { 
    1726      CContext* context=CContext::getCurrent() ; 
    1727  
    1728      if (this->isClientAfterTransformationChecked) return; 
    1729      if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    1730      { 
    1731       this->computeConnectedClients(); 
    1732        if (hasLonLat) 
    1733          if (context->getServiceType()==CServicesManager::CLIENT) 
    1734            this->completeLonLatClient(); 
    1735      } 
    1736  
    1737      this->isClientAfterTransformationChecked = true; 
     1723   void CDomain::checkAttributes(void) 
     1724   TRY 
     1725   { 
     1726      if (this->checkAttributes_done_) return; 
     1727      this->checkDomain(); 
     1728      this->checkLonLat(); 
     1729      this->checkBounds(); 
     1730      this->checkArea(); 
     1731      this->checkMask(); 
     1732      this->checkDomainData(); 
     1733      this->checkCompression(); 
     1734      this->computeLocalMask() ; 
     1735      this->completeLonLatClient(); 
     1736      this->checkAttributes_done_ = true; 
    17381737   } 
    17391738   CATCH_DUMP_ATTR 
     
    17701769   } 
    17711770   CATCH_DUMP_ATTR 
    1772  
    1773    // Send all checked attributes to server 
     1771    
     1772   // ym obselete, to be removed 
     1773   void CDomain::checkAttributesOnClientAfterTransformation() 
     1774   TRY 
     1775   { 
     1776     CContext* context=CContext::getCurrent() ; 
     1777 
     1778     if (this->isClientAfterTransformationChecked) return; 
     1779     if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
     1780     { 
     1781       // this->computeConnectedClients(); 
     1782       if (hasLonLat) 
     1783         if (context->getServiceType()==CServicesManager::CLIENT) 
     1784           this->completeLonLatClient(); 
     1785     } 
     1786 
     1787     this->isClientAfterTransformationChecked = true; 
     1788   } 
     1789   CATCH_DUMP_ATTR 
     1790 
     1791      // Send all checked attributes to server 
    17741792   void CDomain::sendCheckedAttributes() 
    17751793   TRY 
     
    17881806   CATCH_DUMP_ATTR 
    17891807 
     1808/* old version 
    17901809   void CDomain::checkAttributes(void) 
    17911810   TRY 
     
    18201839   } 
    18211840   CATCH_DUMP_ATTR 
    1822  
     1841*/ 
     1842    
    18231843  /*! 
    18241844     Compute the connection of a client to other clients to determine which clients to send attributes to. 
     
    18271847     A client connects to other clients which holds the same global index as it.      
    18281848  */ 
    1829   void CDomain::computeConnectedClients() 
     1849  void CDomain::computeConnectedClients(CContextClient* client) 
    18301850  TRY 
    18311851  { 
     1852    if (computeConnectedClients_done_.count(client)==0) return ; 
     1853    else computeConnectedClients_done_.insert(client) ; 
     1854     
    18321855    CContext* context=CContext::getCurrent() ; 
    1833     set<int> listNbServer ; 
    1834  
    1835     for (auto client : clients) 
     1856    
     1857    int nbServer = client->serverSize; 
     1858    int nbClient = client->clientSize; 
     1859    int rank     = client->clientRank; 
     1860         
     1861    if (listNbServer_.count(nbServer) == 0) 
    18361862    { 
    1837  
    1838       int nbServer = client->serverSize; 
    1839       int nbClient = client->clientSize; 
    1840       int rank     = client->clientRank; 
    1841       bool doComputeGlobalIndexServer = true; 
    1842     
    1843       if (listNbServer.find(nbServer)==listNbServer.end()) 
    1844       { 
    1845         listNbServer.insert(nbServer) ; 
     1863      listNbServer_.insert(nbServer) ; 
    18461864  
    1847         if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 
    1848         { 
    1849           nbSenders.erase(nbServer); 
    1850           connectedServerRank_.erase(nbServer); 
    1851         } 
    1852  
    1853         if (indSrv_.find(nbServer) == indSrv_.end()) 
    1854         { 
    1855           int i,j,i_ind,j_ind, nbIndex=i_index.numElements(); 
    1856           int globalIndexCount = i_index.numElements(); 
    1857           // Fill in index 
    1858           CArray<size_t,1> globalIndexDomain(nbIndex); 
    1859           size_t globalIndex; 
    1860  
    1861           for (i = 0; i < nbIndex; ++i) 
     1865      if (connectedServerRank_.find(nbServer) != connectedServerRank_.end()) 
     1866      { 
     1867        nbSenders.erase(nbServer); 
     1868        connectedServerRank_.erase(nbServer); 
     1869      } 
     1870 
     1871      if (indSrv_.find(nbServer) == indSrv_.end()) 
     1872      { 
     1873        int i,j,i_ind,j_ind, nbIndex=i_index.numElements(); 
     1874        int globalIndexCount = i_index.numElements(); 
     1875        // Fill in index 
     1876        CArray<size_t,1> globalIndexDomain(nbIndex); 
     1877        size_t globalIndex; 
     1878 
     1879        for (i = 0; i < nbIndex; ++i) 
     1880        { 
     1881          i_ind=i_index(i); 
     1882          j_ind=j_index(i); 
     1883          globalIndex = i_ind + j_ind * ni_glo; 
     1884          globalIndexDomain(i) = globalIndex; 
     1885        } 
     1886 
     1887        if (globalLocalIndexMap_.empty())  
     1888          for (i = 0; i < nbIndex; ++i)  globalLocalIndexMap_[globalIndexDomain(i)] = i; 
     1889           
     1890 
     1891        size_t globalSizeIndex = 1, indexBegin, indexEnd; 
     1892        int range, clientSize = client->clientSize; 
     1893        std::vector<int> nGlobDomain(2); 
     1894        nGlobDomain[0] = this->ni_glo; 
     1895        nGlobDomain[1] = this->nj_glo; 
     1896        for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i]; 
     1897        indexBegin = 0; 
     1898        if (globalSizeIndex <= clientSize) 
     1899        { 
     1900          indexBegin = rank%globalSizeIndex; 
     1901          indexEnd = indexBegin; 
     1902        } 
     1903        else 
     1904        { 
     1905          for (int i = 0; i < clientSize; ++i) 
    18621906          { 
    1863             i_ind=i_index(i); 
    1864             j_ind=j_index(i); 
    1865             globalIndex = i_ind + j_ind * ni_glo; 
    1866             globalIndexDomain(i) = globalIndex; 
     1907            range = globalSizeIndex / clientSize; 
     1908            if (i < (globalSizeIndex%clientSize)) ++range; 
     1909            if (i == client->clientRank) break; 
     1910            indexBegin += range; 
    18671911          } 
    1868  
    1869           if (globalLocalIndexMap_.empty()) 
    1870           { 
    1871             for (i = 0; i < nbIndex; ++i) 
    1872               globalLocalIndexMap_[globalIndexDomain(i)] = i; 
    1873           } 
    1874  
    1875           size_t globalSizeIndex = 1, indexBegin, indexEnd; 
    1876           int range, clientSize = client->clientSize; 
    1877           std::vector<int> nGlobDomain(2); 
    1878           nGlobDomain[0] = this->ni_glo; 
    1879           nGlobDomain[1] = this->nj_glo; 
    1880           for (int i = 0; i < nGlobDomain.size(); ++i) globalSizeIndex *= nGlobDomain[i]; 
    1881           indexBegin = 0; 
    1882           if (globalSizeIndex <= clientSize) 
    1883           { 
    1884             indexBegin = rank%globalSizeIndex; 
    1885             indexEnd = indexBegin; 
    1886           } 
    1887           else 
    1888           { 
    1889             for (int i = 0; i < clientSize; ++i) 
    1890             { 
    1891               range = globalSizeIndex / clientSize; 
    1892               if (i < (globalSizeIndex%clientSize)) ++range; 
    1893               if (i == client->clientRank) break; 
    1894               indexBegin += range; 
    1895             } 
    1896             indexEnd = indexBegin + range - 1; 
    1897           } 
    1898  
    1899           // Even if servers have no index, they must received something from client 
    1900           // We only use several client to send "empty" message to these servers 
    1901           CServerDistributionDescription serverDescription(nGlobDomain, nbServer); 
    1902           std::vector<int> serverZeroIndex; 
    1903           if (isUnstructed_) serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 
    1904           else serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 1); 
    1905  
    1906           std::list<int> serverZeroIndexLeader; 
    1907           std::list<int> serverZeroIndexNotLeader; 
    1908           CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
    1909           for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    1910             *it = serverZeroIndex[*it]; 
    1911  
    1912           CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 
    1913           clientServerMap->computeServerIndexMapping(globalIndexDomain, nbServer); 
    1914           CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer(); 
    1915  
    1916           CClientServerMapping::GlobalIndexMap::const_iterator it  = globalIndexDomainOnServer.begin(), 
    1917                  ite = globalIndexDomainOnServer.end(); 
    1918           indSrv_[nbServer].swap(globalIndexDomainOnServer); 
    1919           connectedServerRank_[nbServer].clear(); 
    1920           for (it = indSrv_[nbServer].begin(); it != ite; ++it) 
    1921             connectedServerRank_[nbServer].push_back(it->first); 
    1922  
    1923           for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    1924             connectedServerRank_[nbServer].push_back(*it); 
    1925  
    1926           // Even if a client has no index, it must connect to at least one server and 
    1927           // send an "empty" data to this server 
    1928           if (connectedServerRank_[nbServer].empty()) 
    1929             connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 
    1930  
    1931           // Now check if all servers have data to receive. If not, master client will send empty data. 
    1932           // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 
    1933           std::vector<int> counts (clientSize); 
    1934           std::vector<int> displs (clientSize); 
    1935           displs[0] = 0; 
    1936           int localCount = connectedServerRank_[nbServer].size() ; 
    1937           MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 
    1938           for (int i = 0; i < clientSize-1; ++i) 
    1939           { 
    1940             displs[i+1] = displs[i] + counts[i]; 
    1941           } 
    1942           std::vector<int> allConnectedServers(displs[clientSize-1]+counts[clientSize-1]); 
    1943           MPI_Gatherv(&(connectedServerRank_[nbServer])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 
    1944  
    1945           if ((allConnectedServers.size() != nbServer) && (rank == 0)) 
    1946           { 
    1947             std::vector<bool> isSrvConnected (nbServer, false); 
    1948             for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 
    1949             for (int i = 0; i < nbServer; ++i) 
    1950             { 
    1951               if (!isSrvConnected[i]) connectedServerRank_[nbServer].push_back(i); 
    1952             } 
    1953           } 
    1954           nbSenders[nbServer] = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 
    1955           delete clientServerMap; 
    1956         } 
     1912          indexEnd = indexBegin + range - 1; 
     1913        } 
     1914 
     1915        // Even if servers have no index, they must received something from client 
     1916        // We only use several client to send "empty" message to these servers 
     1917        CServerDistributionDescription serverDescription(nGlobDomain, nbServer); 
     1918        std::vector<int> serverZeroIndex; 
     1919        if (isUnstructed_) serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 0); 
     1920        else serverZeroIndex = serverDescription.computeServerGlobalIndexInRange(std::make_pair<size_t&,size_t&>(indexBegin, indexEnd), 1); 
     1921 
     1922        std::list<int> serverZeroIndexLeader; 
     1923        std::list<int> serverZeroIndexNotLeader; 
     1924        CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
     1925        for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     1926          *it = serverZeroIndex[*it]; 
     1927 
     1928        CClientServerMapping* clientServerMap = new CClientServerMappingDistributed(serverDescription.getGlobalIndexRange(), client->intraComm); 
     1929        clientServerMap->computeServerIndexMapping(globalIndexDomain, nbServer); 
     1930        CClientServerMapping::GlobalIndexMap& globalIndexDomainOnServer = clientServerMap->getGlobalIndexOnServer(); 
     1931 
     1932        CClientServerMapping::GlobalIndexMap::const_iterator it  = globalIndexDomainOnServer.begin(), ite = globalIndexDomainOnServer.end(); 
     1933        indSrv_[nbServer].swap(globalIndexDomainOnServer); 
     1934        connectedServerRank_[nbServer].clear(); 
     1935        for (it = indSrv_[nbServer].begin(); it != ite; ++it) connectedServerRank_[nbServer].push_back(it->first); 
     1936 
     1937        for (std::list<int>::const_iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     1938          connectedServerRank_[nbServer].push_back(*it); 
     1939 
     1940        // Even if a client has no index, it must connect to at least one server and 
     1941        // send an "empty" data to this server 
     1942        if (connectedServerRank_[nbServer].empty()) 
     1943          connectedServerRank_[nbServer].push_back(client->clientRank % client->serverSize); 
     1944 
     1945        // Now check if all servers have data to receive. If not, master client will send empty data. 
     1946        // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 
     1947        std::vector<int> counts (clientSize); 
     1948        std::vector<int> displs (clientSize); 
     1949        displs[0] = 0; 
     1950        int localCount = connectedServerRank_[nbServer].size() ; 
     1951        MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 
     1952        for (int i = 0; i < clientSize-1; ++i) displs[i+1] = displs[i] + counts[i]; 
     1953        std::vector<int> allConnectedServers(displs[clientSize-1]+counts[clientSize-1]); 
     1954        MPI_Gatherv(&(connectedServerRank_[nbServer])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 
     1955 
     1956        if ((allConnectedServers.size() != nbServer) && (rank == 0)) 
     1957        { 
     1958          std::vector<bool> isSrvConnected (nbServer, false); 
     1959          for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 
     1960          for (int i = 0; i < nbServer; ++i) if (!isSrvConnected[i]) connectedServerRank_[nbServer].push_back(i); 
     1961        } 
     1962        nbSenders[nbServer] = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[nbServer]); 
     1963        delete clientServerMap; 
    19571964      } 
    19581965    } 
     
    30253032 
    30263033  /*! 
     3034  \brief Check if a domain is completed 
     3035  Before make any domain processing, we must be sure that all domain informations have 
     3036  been sent, for exemple when reading a grid in a file or when grid elements are sent by an 
     3037  other context (coupling). So all direct reference of the domain (domain_ref) must be also completed 
     3038  \return true if domain and domain reference are completed 
     3039  */ 
     3040  bool CDomain::checkIfCompleted(void) 
     3041  { 
     3042    if (hasDirectDomainReference()) if (!getDirectDomainReference()->checkIfCompleted()) return false; 
     3043    return isCompleted_ ; 
     3044  } 
     3045 
     3046  /*! 
     3047  \brief Set a domain as completed 
     3048   When all information about a domain have been received, the domain is tagged as completed and is 
     3049   suitable for processing 
     3050  */ 
     3051  void CDomain::setCompleted(void) 
     3052  { 
     3053    if (hasDirectDomainReference()) getDirectDomainReference()->setCompleted() ; 
     3054    isCompleted_=true ; 
     3055  } 
     3056 
     3057  /*! 
     3058  \brief Set a domain as uncompleted 
     3059   When informations about a domain are expected from a grid reading from file or coupling, the domain is  
     3060   tagged as uncompleted and is not suitable for processing 
     3061  */ 
     3062  void CDomain::setUncompleted(void) 
     3063  { 
     3064    if (hasDirectDomainReference()) getDirectDomainReference()->setUncompleted() ; 
     3065    isCompleted_=false ; 
     3066  } 
     3067   
     3068  /*! 
    30273069   * Go through the hierarchy to find the domain from which the transformations must be inherited 
    30283070   */ 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp

    r1847 r1869  
    7676         /// Vérifications /// 
    7777         void checkAttributes(void); 
     78         bool checkAttributes_done_ = false ; 
     79 
    7880         void checkAttributesOnClient(); 
    7981         void checkAttributesOnClientAfterTransformation(); 
     
    109111 
    110112         static bool dispatchEvent(CEventServer& event); 
     113 
     114         bool checkIfCompleted(void) ; 
     115         void setCompleted(void) ; 
     116         void setUncompleted(void) ; 
    111117 
    112118      public: 
     
    157163 
    158164         void computeLocalMask(void) ; 
     165       
     166         void computeConnectedClients(CContextClient* client);   
     167         private: std::set<CContextClient*> computeConnectedClients_done_; public: 
     168         /** The number of server of a context client. Avoid to re-compute indice computed in a previous computeConnectedClient */ 
     169         private: std::set<int> listNbServer_ ; public: 
     170          
    159171      private: 
    160172         void checkDomain(void); 
     
    197209 
    198210         void completeLonLatClient(void);   
    199          void computeConnectedClients();     
    200  
     211          
     212          
    201213       private:          
    202214 
     
    209221         bool isClientChecked; // Verify whether all attributes of domain on the client side are good 
    210222         bool isClientAfterTransformationChecked; 
     223          
     224         /** define if the domain is completed or not ie all attributes have been received before in case  
     225             of grid reading from file or coupling */  
     226         bool isCompleted_=true ;   
    211227 
    212228/** global index of the domain on server side, sent by the clients. This is global index for lon, lat, mask elements (ie non masked elements) 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.cpp

    r1853 r1869  
    2626#include "tracer.hpp" 
    2727 
    28 namespace xios{ 
    29  
    30    /// ////////////////////// Définitions ////////////////////// /// 
    31  
    32    CField::CField(void) 
    33       : CObjectTemplate<CField>(), CFieldAttributes() 
    34       , grid(), file() 
    35       , written(false) 
    36       , nstep(0), nstepMax(0) 
    37       , hasOutputFile(false) 
    38       , domAxisScalarIds_(vector<StdString>(3,"")) 
    39       , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 
    40       , isGridChecked(false) 
    41       , useCompressedOutput(false) 
    42       , hasTimeInstant(false) 
    43       , hasTimeCentered(false) 
    44       , wasDataRequestedFromServer(false) 
    45       , wasDataAlreadyReceivedFromServer(false) 
    46       , mustAutoTrigger(false) 
    47       , isEOF(false), nstepMaxRead(false) 
    48    { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 
    49  
    50    CField::CField(const StdString& id) 
    51       : CObjectTemplate<CField>(id), CFieldAttributes() 
    52       , grid(), file() 
    53       , written(false) 
    54       , nstep(0), nstepMax(0) 
    55       , hasOutputFile(false) 
    56       , domAxisScalarIds_(vector<StdString>(3,"")) 
    57       , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 
    58       , isGridChecked(false) 
    59       , useCompressedOutput(false) 
    60       , hasTimeInstant(false) 
    61       , hasTimeCentered(false) 
    62       , wasDataRequestedFromServer(false) 
    63       , wasDataAlreadyReceivedFromServer(false) 
    64       , mustAutoTrigger(false) 
    65       , isEOF(false), nstepMaxRead(false) 
    66    { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 
    67  
    68    CField::~CField(void) 
    69    {} 
     28namespace xios 
     29{ 
     30 
     31  /// ////////////////////// Définitions ////////////////////// /// 
     32 
     33  CField::CField(void) 
     34    : CObjectTemplate<CField>(), CFieldAttributes() 
     35    , file() 
     36    , written(false) 
     37    , nstep(0), nstepMax(0) 
     38    , hasOutputFile(false) 
     39    , domAxisScalarIds_(vector<StdString>(3,"")) 
     40    , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 
     41    , isGridChecked(false) 
     42    , useCompressedOutput(false) 
     43    , hasTimeInstant(false) 
     44    , hasTimeCentered(false) 
     45    , wasDataRequestedFromServer(false) 
     46    , wasDataAlreadyReceivedFromServer(false) 
     47    , mustAutoTrigger(false) 
     48    , isEOF(false), nstepMaxRead(false) 
     49  { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 
     50 
     51  CField::CField(const StdString& id) 
     52    : CObjectTemplate<CField>(id), CFieldAttributes() 
     53    , file() 
     54    , written(false) 
     55    , nstep(0), nstepMax(0) 
     56    , hasOutputFile(false) 
     57    , domAxisScalarIds_(vector<StdString>(3,"")) 
     58    , areAllReferenceSolved(false), isReferenceSolved(false), isReferenceSolvedAndTransformed(false) 
     59    , isGridChecked(false) 
     60    , useCompressedOutput(false) 
     61    , hasTimeInstant(false) 
     62    , hasTimeCentered(false) 
     63    , wasDataRequestedFromServer(false) 
     64    , wasDataAlreadyReceivedFromServer(false) 
     65    , mustAutoTrigger(false) 
     66    , isEOF(false), nstepMaxRead(false) 
     67  { setVirtualVariableGroup(CVariableGroup::create(getId() + "_virtual_variable_group")); } 
     68 
     69  CField::~CField(void) 
     70  {} 
    7071 
    7172  //---------------------------------------------------------------- 
    7273 
    73    void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup) 
    74    TRY 
    75    { 
    76       this->vVariableGroup = newVVariableGroup; 
    77    } 
    78    CATCH 
    79  
    80    CVariableGroup* CField::getVirtualVariableGroup(void) const 
    81    TRY 
    82    { 
    83       return this->vVariableGroup; 
    84    } 
    85    CATCH 
    86  
    87    std::vector<CVariable*> CField::getAllVariables(void) const 
    88    TRY 
    89    { 
    90       return this->vVariableGroup->getAllChildren(); 
    91    } 
    92    CATCH 
    93  
    94    void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent) 
    95    TRY 
    96    { 
    97       SuperClassAttribute::setAttributes(parent, apply); 
    98       this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL); 
    99    } 
    100    CATCH_DUMP_ATTR 
     74  void CField::setVirtualVariableGroup(CVariableGroup* newVVariableGroup) 
     75  TRY 
     76  { 
     77    this->vVariableGroup = newVVariableGroup; 
     78  } 
     79  CATCH 
     80 
     81  CVariableGroup* CField::getVirtualVariableGroup(void) const 
     82  TRY 
     83  { 
     84     return this->vVariableGroup; 
     85  } 
     86  CATCH 
     87 
     88  std::vector<CVariable*> CField::getAllVariables(void) const 
     89  TRY 
     90  { 
     91    return this->vVariableGroup->getAllChildren(); 
     92  } 
     93  CATCH 
     94 
     95  void CField::solveDescInheritance(bool apply, const CAttributeMap* const parent) 
     96  TRY 
     97  { 
     98    SuperClassAttribute::setAttributes(parent, apply); 
     99    this->getVirtualVariableGroup()->solveDescInheritance(apply, NULL); 
     100  } 
     101  CATCH_DUMP_ATTR 
    101102 
    102103  //---------------------------------------------------------------- 
     
    155156    list<CArray<double,1> > list_data; 
    156157 
    157     if (!grid->doGridHaveDataDistributed(client)) 
     158    if (!grid_->doGridHaveDataDistributed(client)) 
    158159    { 
    159160       if (client->isServerLeader()) 
    160161       { 
    161           for (it = grid->storeIndex_toSrv_[client].begin(); it != grid->storeIndex_toSrv_[client].end(); it++) 
     162          for (it = grid_->storeIndex_toSrv_[client].begin(); it != grid_->storeIndex_toSrv_[client].end(); it++) 
    162163          { 
    163164            int rank = it->first; 
     
    179180    else 
    180181    { 
    181       for (it = grid->storeIndex_toSrv_[client].begin(); it != grid->storeIndex_toSrv_[client].end(); it++) 
     182      for (it = grid_->storeIndex_toSrv_[client].begin(); it != grid_->storeIndex_toSrv_[client].end(); it++) 
    182183      { 
    183184        int rank = it->first; 
     
    191192 
    192193        list_msg.back() << getId() << data_tmp; 
    193         event.push(rank, grid->nbSenders_[receiverSize][rank], list_msg.back()); 
     194        event.push(rank, grid_->nbSenders_[receiverSize][rank], list_msg.back()); 
    194195      } 
    195196      client->sendEvent(event); 
     
    228229    if (0 == recvDataSrv.numElements()) 
    229230    {             
    230       CArray<int,1>& storeClient = grid->storeIndex_client_; 
     231      CArray<int,1>& storeClient = grid_->getStoreIndex_client(); 
    231232 
    232233      // Gather all data from different clients       
     
    238239    const CDate& currDate = context->getCalendar()->getCurrentDate(); 
    239240    CDuration offsetAllButMonth (freq_offset.getValue().year, 0 , freq_offset.getValue().day, 
    240                                    freq_offset.getValue().hour, freq_offset.getValue().minute, 
    241                                    freq_offset.getValue().second, freq_offset.getValue().timestep); 
     241                                 freq_offset.getValue().hour, freq_offset.getValue().minute, 
     242                                 freq_offset.getValue().second, freq_offset.getValue().timestep); 
    242243    const CDate opeDate   = (last_operation_srv - offsetAllButMonth + context->getCalendar()->getTimeStep()) 
    243                               + freq_op + freq_operation_srv - freq_op - context->getCalendar()->getTimeStep() + offsetAllButMonth; 
     244                             + freq_op + freq_operation_srv - freq_op - context->getCalendar()->getTimeStep() + offsetAllButMonth; 
    244245 
    245246    if (opeDate <= currDate) 
    246247    { 
    247       for (map<int, CArray<size_t, 1> >::iterator it = grid->outLocalIndexStoreOnClient_.begin(); it != grid->outLocalIndexStoreOnClient_.end(); ++it) 
     248      for (map<int, CArray<size_t, 1> >::iterator it = grid_->outLocalIndexStoreOnClient_.begin(); it != grid_->outLocalIndexStoreOnClient_.end(); ++it) 
    248249      { 
    249250        CArray<double,1> tmp; 
     
    287288      recvFoperationSrv->final(); 
    288289      last_Write_srv = writeDate; 
    289       grid->computeWrittenIndex(); 
     290      grid_->computeWrittenIndex(); 
    290291      writeField(); 
    291292      lastlast_Write_srv = last_Write_srv; 
     
    299300    if (!getRelFile()->isEmptyZone()) 
    300301    { 
    301       if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 
     302      if (grid_->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file) 
    302303      { 
    303304        getRelFile()->checkWriteFile(); 
     
    338339      else client->sendEvent(event); 
    339340    } 
    340     else 
    341       serverSourceFilter->signalEndOfStream(tsDataRequested); 
     341    else serverSourceFilter->signalEndOfStream(tsDataRequested); 
    342342 
    343343    wasDataRequestedFromServer = true; 
     
    398398 
    399399    map<int, CArray<double,1> >::iterator it; 
    400     if (!grid->doGridHaveDataDistributed(client)) 
     400    if (!grid_->doGridHaveDataDistributed(client)) 
    401401    { 
    402402       if (client->isServerLeader()) 
     
    436436    else 
    437437    { 
    438       for (map<int, CArray<size_t, 1> >::iterator it = grid->outLocalIndexStoreOnClient_.begin();  
    439                                                   it != grid->outLocalIndexStoreOnClient_.end(); ++it) 
     438      for (map<int, CArray<size_t, 1> >::iterator it = grid_->outLocalIndexStoreOnClient_.begin();  
     439                                                  it != grid_->outLocalIndexStoreOnClient_.end(); ++it) 
    440440      { 
    441441        CArray<size_t,1>& indexTmp = it->second; 
     
    463463        } 
    464464 
    465         event.push(it->first, grid->nbReadSenders_[client][it->first], msg); 
     465        event.push(it->first, grid_->nbReadSenders_[client][it->first], msg); 
    466466      } 
    467467      client->sendEvent(event); 
     
    479479  { 
    480480    CContext* context = CContext::getCurrent(); 
    481     grid->computeWrittenIndex(); 
     481    grid_->computeWrittenIndex(); 
    482482    getRelFile()->initRead(); 
    483483    EReadField readState = RF_DATA; 
     
    485485    if (!getRelFile()->isEmptyZone()) 
    486486    {       
    487       if (grid->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)       
     487      if (grid_->doGridHaveDataToWrite() || getRelFile()->type == CFile::type_attr::one_file)       
    488488      { 
    489489        if (0 == recvDataSrv.numElements()) 
    490490        {             
    491           CArray<int,1>& storeClient = grid->storeIndex_client_;           
     491          CArray<int,1>& storeClient = grid_->getStoreIndex_client();           
    492492          recvDataSrv.resize(storeClient.numElements());           
    493493        } 
     
    660660  CATCH_DUMP_ATTR 
    661661 
     662  //---------------------------------------------------------------- 
     663 
     664  void CField::setRelFile(CFile* _file) 
     665  TRY 
     666  { 
     667    this->file = _file; 
     668    hasOutputFile = true; 
     669  } 
     670  CATCH_DUMP_ATTR 
     671 
     672  //---------------------------------------------------------------- 
     673 
     674  StdString CField::GetName(void)    { return StdString("field"); } 
     675  StdString CField::GetDefName(void) { return CField::GetName(); } 
     676  ENodeType CField::GetType(void)    { return eField; } 
     677 
     678  //---------------------------------------------------------------- 
     679 
     680  CGrid* CField::getRelGrid(void) const 
     681  TRY 
     682  { 
     683    return this->grid_; 
     684  } 
     685  CATCH 
     686 
     687  //---------------------------------------------------------------- 
     688 
     689  CFile* CField::getRelFile(void) const 
     690  TRY 
     691  { 
     692    return this->file; 
     693  } 
     694  CATCH 
     695 
     696  int CField::getNStep(void) const 
     697  TRY 
     698  { 
     699    return this->nstep; 
     700  } 
     701  CATCH 
     702 
     703  func::CFunctor::ETimeType CField::getOperationTimeType() const 
     704  TRY 
     705  { 
     706    return operationTimeType; 
     707  } 
     708  CATCH 
     709 
    662710   //---------------------------------------------------------------- 
    663711 
    664    void CField::setRelFile(CFile* _file) 
    665    TRY 
    666    { 
    667       this->file = _file; 
    668       hasOutputFile = true; 
    669    } 
    670    CATCH_DUMP_ATTR 
    671  
    672    //---------------------------------------------------------------- 
    673  
    674    StdString CField::GetName(void)    { return StdString("field"); } 
    675    StdString CField::GetDefName(void) { return CField::GetName(); } 
    676    ENodeType CField::GetType(void)    { return eField; } 
    677  
    678    //---------------------------------------------------------------- 
    679  
    680    CGrid* CField::getRelGrid(void) const 
    681    TRY 
    682    { 
    683       return this->grid; 
    684    } 
    685    CATCH 
    686  
    687    //---------------------------------------------------------------- 
    688  
    689    CFile* CField::getRelFile(void) const 
    690    TRY 
    691    { 
    692       return this->file; 
    693    } 
    694    CATCH 
    695  
    696    int CField::getNStep(void) const 
    697    TRY 
    698    { 
    699       return this->nstep; 
    700    } 
    701    CATCH 
    702  
    703    func::CFunctor::ETimeType CField::getOperationTimeType() const 
    704    TRY 
    705    { 
    706      return operationTimeType; 
    707    } 
    708    CATCH 
    709  
    710    //---------------------------------------------------------------- 
    711  
    712    void CField::incrementNStep(void) 
    713    TRY 
    714    { 
    715       this->nstep++; 
    716    } 
    717    CATCH_DUMP_ATTR 
    718  
    719    void CField::resetNStep(int nstep /*= 0*/) 
    720    TRY 
    721    { 
    722       this->nstep = nstep; 
    723    } 
    724    CATCH_DUMP_ATTR 
    725  
    726    void CField::resetNStepMax(void) 
    727    TRY 
    728    { 
    729       this->nstepMax = 0; 
    730       nstepMaxRead = false; 
    731    } 
    732    CATCH_DUMP_ATTR 
    733  
    734    //---------------------------------------------------------------- 
    735  
    736    bool CField::isActive(bool atCurrentTimestep /*= false*/) const 
    737    TRY 
    738    { 
    739       if (clientSourceFilter) 
    740         return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 
    741       else if (storeFilter) 
    742         return true; 
    743       else if (instantDataFilter) 
    744         ERROR("bool CField::isActive(bool atCurrentTimestep)", 
    745               << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 
    746  
    747       return false; 
    748    } 
    749    CATCH 
    750  
    751    //---------------------------------------------------------------- 
    752  
    753    bool CField::wasWritten() const 
    754    TRY 
    755    { 
    756      return written; 
    757    } 
    758    CATCH 
    759  
    760    void CField::setWritten() 
    761    TRY 
    762    { 
    763      written = true; 
    764    } 
    765    CATCH_DUMP_ATTR 
    766  
    767    //---------------------------------------------------------------- 
    768  
    769    bool CField::getUseCompressedOutput() const 
    770    TRY 
    771    { 
    772      return useCompressedOutput; 
    773    } 
    774    CATCH 
    775  
    776    void CField::setUseCompressedOutput() 
    777    TRY 
    778    { 
    779      useCompressedOutput = true; 
    780    } 
    781    CATCH_DUMP_ATTR 
    782  
    783    //---------------------------------------------------------------- 
    784  
    785    std::shared_ptr<COutputPin> CField::getInstantDataFilter() 
    786    TRY 
    787    { 
    788      return instantDataFilter; 
    789    } 
    790    CATCH_DUMP_ATTR 
    791  
    792    //---------------------------------------------------------------- 
     712  void CField::incrementNStep(void) 
     713  TRY 
     714  { 
     715    this->nstep++; 
     716  } 
     717  CATCH_DUMP_ATTR 
     718 
     719  void CField::resetNStep(int nstep /*= 0*/) 
     720  TRY 
     721  { 
     722    this->nstep = nstep; 
     723  } 
     724  CATCH_DUMP_ATTR 
     725 
     726  void CField::resetNStepMax(void) 
     727  TRY 
     728  { 
     729    this->nstepMax = 0; 
     730    nstepMaxRead = false; 
     731  } 
     732  CATCH_DUMP_ATTR 
     733 
     734  //---------------------------------------------------------------- 
     735 
     736  bool CField::isActive(bool atCurrentTimestep /*= false*/) const 
     737  TRY 
     738  { 
     739    if (clientSourceFilter) 
     740      return atCurrentTimestep ? clientSourceFilter->isDataExpected(CContext::getCurrent()->getCalendar()->getCurrentDate()) : true; 
     741    else if (storeFilter) 
     742      return true; 
     743    else if (instantDataFilter) 
     744      ERROR("bool CField::isActive(bool atCurrentTimestep)", 
     745            << "Impossible to check if field [ id = " << getId() << " ] is active as it cannot be used to receive nor send data."); 
     746 
     747    return false; 
     748  } 
     749  CATCH 
     750 
     751  //---------------------------------------------------------------- 
     752 
     753  bool CField::wasWritten() const 
     754  TRY 
     755  { 
     756    return written; 
     757  } 
     758  CATCH 
     759 
     760  void CField::setWritten() 
     761  TRY 
     762  { 
     763    written = true; 
     764  } 
     765  CATCH_DUMP_ATTR 
     766 
     767  //---------------------------------------------------------------- 
     768 
     769  bool CField::getUseCompressedOutput() const 
     770  TRY 
     771  { 
     772    return useCompressedOutput; 
     773  } 
     774  CATCH 
     775 
     776  void CField::setUseCompressedOutput() 
     777  TRY 
     778  { 
     779    useCompressedOutput = true; 
     780  } 
     781  CATCH_DUMP_ATTR 
     782 
     783  //---------------------------------------------------------------- 
     784 
     785  std::shared_ptr<COutputPin> CField::getInstantDataFilter() 
     786  TRY 
     787  { 
     788    return instantDataFilter; 
     789  } 
     790  CATCH_DUMP_ATTR 
     791 
     792  //---------------------------------------------------------------- 
     793 
     794  /*! 
     795    Build up graph of grids which plays role of destination and source in grid transformation 
     796    This function should be called before \func solveGridReference() 
     797  */ 
     798  void CField::buildGridTransformationGraph() 
     799  TRY 
     800  { 
     801    CContext* context = CContext::getCurrent(); 
     802    if (context->getServiceType()==CServicesManager::CLIENT) 
     803    { 
     804      if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 
     805      { 
     806        grid_->addTransGridSource(getDirectFieldReference()->grid_); 
     807      } 
     808    } 
     809  } 
     810  CATCH_DUMP_ATTR 
     811 
     812  /*! 
     813    Generate a new grid destination if there are more than one grid source pointing to a same grid destination 
     814  */ 
     815  void CField::generateNewTransformationGridDest() 
     816  TRY 
     817  { 
     818    CContext* context = CContext::getCurrent(); 
     819    if (context->getServiceType()==CServicesManager::CLIENT) 
     820    { 
     821      std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid_->getTransGridSource(); 
     822      if (1 < gridSrcMap.size()) 
     823      { 
     824        // Search for grid source 
     825        CGrid* gridSrc = grid_; 
     826        CField* currField = this; 
     827        std::vector<CField*> hieraField; 
     828        while (currField->hasDirectFieldReference() && (gridSrc == grid_)) 
     829        { 
     830          hieraField.push_back(currField); 
     831          CField* tmp = currField->getDirectFieldReference(); 
     832          currField = tmp; 
     833          gridSrc = currField->grid_; 
     834        } 
     835 
     836        if (gridSrcMap.end() != gridSrcMap.find(gridSrc)) 
     837        { 
     838          CGrid* gridTmp; 
     839          std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc]; 
     840          if (newGridDest.first) 
     841          { 
     842            StdString newIdGridDest = newGridDest.second; 
     843            if (!CGrid::has(newIdGridDest)) 
     844            { 
     845              ERROR("CGrid* CGrid::generateNewTransformationGridDest()", 
     846                << " Something wrong happened! Grid whose id " << newIdGridDest 
     847                << "should exist "); 
     848            } 
     849            gridTmp = CGrid::get(newIdGridDest); 
     850          } 
     851          else 
     852          { 
     853            StdString newIdGridDest = CGrid::generateId(gridSrc, grid_); 
     854            gridTmp = CGrid::cloneGrid(newIdGridDest, grid_); 
     855 
     856            (gridSrcMap[gridSrc]).first = true; 
     857            (gridSrcMap[gridSrc]).second = newIdGridDest; 
     858          } 
     859 
     860          // Update all descendants 
     861          for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it) 
     862          { 
     863            (*it)->grid_ = gridTmp; 
     864            (*it)->updateRef((*it)->grid_); 
     865          } 
     866        } 
     867      } 
     868    } 
     869  } 
     870  CATCH_DUMP_ATTR 
     871 
     872  void CField::updateRef(CGrid* grid) 
     873  TRY 
     874  { 
     875    if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 
     876    else 
     877    { 
     878      std::vector<CAxis*> axisTmp = grid->getAxis(); 
     879      std::vector<CDomain*> domainTmp = grid->getDomains(); 
     880      if ((1<axisTmp.size()) || (1<domainTmp.size())) 
     881        ERROR("void CField::updateRef(CGrid* grid)", 
     882          << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 
     883 
     884      if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 
     885        ERROR("void CField::updateRef(CGrid* grid)", 
     886          << "Incoherent between available domain and domain_ref of field " << this->getId()); 
     887      if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 
     888        ERROR("void CField::updateRef(CGrid* grid)", 
     889          << "Incoherent between available axis and axis_ref of field " << this->getId()); 
     890 
     891      if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 
     892      if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 
     893    } 
     894  } 
     895  CATCH_DUMP_ATTR 
     896    
     897  /*! 
     898    Solve reference of all enabled fields even the source fields . 
     899    In this step, we do transformations. 
     900  */ 
     901  void CField::solveAllEnabledFieldsAndTransform() 
     902  TRY 
     903  { 
     904    CContext* context = CContext::getCurrent(); 
     905 
     906    if (!isReferenceSolvedAndTransformed) 
     907    { 
     908      isReferenceSolvedAndTransformed = true; 
     909 
     910      if (context->getServiceType()==CServicesManager::CLIENT) 
     911      { 
     912        solveRefInheritance(true); 
     913        if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFieldsAndTransform(); 
     914      } 
     915 
     916      if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
     917        solveServerOperation(); 
     918 
     919      solveGridReference(); 
     920 
     921      if (context->getServiceType()==CServicesManager::CLIENT) 
     922      { 
     923        solveGenerateGrid(); 
     924        buildGridTransformationGraph(); 
     925      } 
     926 
     927      solveGridDomainAxisRef(false); 
     928 
     929      if (context->getServiceType()==CServicesManager::CLIENT) 
     930      { 
     931        solveTransformedGrid(); 
     932      } 
     933 
     934      solveGridDomainAxisRef(false); 
     935    } 
     936  } 
     937  CATCH_DUMP_ATTR 
     938 
     939  void CField::checkGridOfEnabledFields() 
     940  TRY 
     941  { 
     942    if (!isGridChecked) 
     943    { 
     944      isGridChecked = true; 
     945      solveCheckMaskIndex(false); 
     946    } 
     947  } 
     948  CATCH_DUMP_ATTR 
     949 
     950  void CField::sendGridComponentOfEnabledFields() 
     951  TRY 
     952  { 
     953    solveGridDomainAxisRef(true); 
     954    // solveCheckMaskIndex(true); 
     955  } 
     956  CATCH_DUMP_ATTR 
     957 
     958  void CField::sendGridOfEnabledFields() 
     959  TRY 
     960  { 
     961    // solveGridDomainAxisRef(true); 
     962    solveCheckMaskIndex(true); 
     963  }    
     964  CATCH_DUMP_ATTR 
     965 
     966  void CField::solveOnlyReferenceEnabledField(void) 
     967  TRY 
     968  { 
     969    CContext* context = CContext::getCurrent(); 
     970    if (!isReferenceSolved) 
     971    { 
     972      isReferenceSolved = true; 
     973 
     974      if (context->getServiceType()==CServicesManager::CLIENT) 
     975      { 
     976        solveRefInheritance(true); 
     977        if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(); 
     978      } 
     979 
     980      if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
     981        solveServerOperation(); 
     982 
     983      solveGridReference(); 
     984      grid_->solveElementsRefInheritance(true); // make it again to solve grid reading from file 
     985 
     986      if (context->getServiceType()==CServicesManager::CLIENT) 
     987      { 
     988        solveGenerateGrid(); 
     989        buildGridTransformationGraph(); 
     990      } 
     991    } 
     992  } 
     993  CATCH_DUMP_ATTR 
     994 
     995  void CField::solveAllReferenceEnabledField(bool doSending2Server) 
     996  TRY 
     997  { 
     998    CContext* context = CContext::getCurrent(); 
     999    solveOnlyReferenceEnabledField(); 
     1000 
     1001    if (!areAllReferenceSolved) 
     1002    { 
     1003      areAllReferenceSolved = true; 
     1004       
     1005      if (context->getServiceType()==CServicesManager::CLIENT) 
     1006      { 
     1007        solveRefInheritance(true); 
     1008        if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 
     1009      } 
     1010      else if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
     1011        solveServerOperation(); 
     1012 
     1013      solveGridReference(); 
     1014    } 
     1015 
     1016    solveGridDomainAxisRef(doSending2Server); 
     1017 
     1018    if (context->getServiceType()==CServicesManager::CLIENT) 
     1019    { 
     1020      solveTransformedGrid(); 
     1021    } 
     1022 
     1023    solveCheckMaskIndex(doSending2Server); 
     1024  } 
     1025  CATCH_DUMP_ATTR 
     1026 
     1027  std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 
     1028  TRY 
     1029  { 
     1030    return grid_->getAttributesBufferSize(client, bufferForWriting); 
     1031  } 
     1032  CATCH_DUMP_ATTR 
     1033 
     1034  std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 
     1035  TRY 
     1036  { 
     1037    return grid_->getDataBufferSize(client, getId(), bufferForWriting); 
     1038  } 
     1039  CATCH_DUMP_ATTR 
     1040 
     1041  size_t CField::getGlobalWrittenSize() 
     1042  TRY 
     1043  { 
     1044    return grid_->getGlobalWrittenSize(); 
     1045  } 
     1046  CATCH_DUMP_ATTR 
     1047 
     1048  //---------------------------------------------------------------- 
     1049 
     1050  void CField::solveServerOperation(void) 
     1051  TRY 
     1052  { 
     1053    CContext* context = CContext::getCurrent(); 
     1054 
     1055    if (context->getServiceType()==CServicesManager::CLIENT || !hasOutputFile) return; 
     1056 
     1057    if (freq_op.isEmpty()) freq_op.setValue(TimeStep); 
     1058 
     1059    if (freq_offset.isEmpty()) freq_offset.setValue(NoneDu); 
     1060 
     1061    freq_operation_srv = file->output_freq.getValue(); 
     1062    freq_write_srv     = file->output_freq.getValue(); 
     1063 
     1064    lastlast_Write_srv = context->getCalendar()->getInitDate(); 
     1065    last_Write_srv     = context->getCalendar()->getInitDate(); 
     1066    last_operation_srv = context->getCalendar()->getInitDate(); 
     1067 
     1068    const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep(); 
     1069    last_operation_srv     = last_operation_srv - toffset; 
     1070 
     1071    if (operation.isEmpty()) 
     1072      ERROR("void CField::solveServerOperation(void)", 
     1073            << "An operation must be defined for field \"" << getId() << "\"."); 
     1074 
     1075    std::shared_ptr<func::CFunctor> functor; 
     1076    CArray<double, 1> dummyData; 
     1077 
     1078#define DECLARE_FUNCTOR(MType, mtype) \ 
     1079    if (operation.getValue().compare(#mtype) == 0) \ 
     1080    { \ 
     1081      functor.reset(new func::C##MType(dummyData)); \ 
     1082    } 
     1083 
     1084#include "functor_type.conf" 
     1085 
     1086    if (!functor) 
     1087      ERROR("void CField::solveServerOperation(void)", 
     1088            << "\"" << operation << "\" is not a valid operation."); 
     1089 
     1090    operationTimeType = functor->timeType(); 
     1091  } 
     1092  CATCH_DUMP_ATTR 
     1093 
     1094 //---------------------------------------------------------------- 
     1095 
     1096  bool CField::buildWorkflowGraph(CGarbageCollector& gc) 
     1097  { 
     1098    if (buildWorkflowGraphDone_) return true ; 
     1099    const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
     1100    const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 
     1101 
     1102    if (!inputFilter) inputFilter = std::shared_ptr<CPassThroughFilter>(new CPassThroughFilter(gc));  
     1103      
     1104    if (hasDirectFieldReference()) 
     1105    { 
     1106      CField* fieldRef = getDirectFieldReference(); 
     1107      bool ret=fieldRef->buildWorkflowGraph(gc);  
     1108      if (!ret) return false ; // workflow graph cannot be built at this stage 
     1109    } 
     1110 
     1111    // Check if we have an expression to parse 
     1112    std::shared_ptr<COutputPin> filterExpr ; 
     1113    if (hasExpression()) 
     1114    { 
     1115      boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 
     1116      filterExpr = expr->reduce(gc, *this); 
     1117      if (!filterExpr) return false ; // workflow graph cannot be built at this stage 
     1118    } 
     1119     
     1120    // now construct grid and check if element are enabled 
     1121    solveGridReference() ; // grid_ is now defined 
     1122     
     1123    // prepare transformation. Need to know before if workflow of auxillary field can be built 
     1124    if (hasDirectFieldReference()) 
     1125    { 
     1126      auto gridPath=getGridPath() ; 
     1127      gridPath.push_back(grid_) ; 
     1128 
     1129      CGrid* gridSrc=getDirectFieldReference()->getGrid() ; 
     1130      for(auto grid : gridPath) 
     1131      { 
     1132        if (!grid->checkIfCompleted()) return false ; 
     1133        grid->solveElementsRefInheritance() ; 
     1134        grid_->completeGrid(gridSrc); // grid generation, to be checked 
     1135        grid->prepareTransformGrid(gridSrc) ; // prepare the grid tranformation 
     1136        for(auto fieldId : grid->getAuxInputTransformGrid()) // try to build workflow graph for auxillary field tranformation 
     1137          if (!CField::get(fieldId)->buildWorkflowGraph(gc)) return false ; 
     1138        gridSrc=grid ; 
     1139      } 
     1140       
     1141      std::shared_ptr<COutputPin> lastFilter ; 
     1142      if (filterExpr) lastFilter=filterExpr ; 
     1143      else lastFilter = inputFilter ; 
     1144       
     1145      gridSrc=getDirectFieldReference()->getGrid() ; 
     1146      for(auto grid : gridPath)  
     1147      { 
     1148        grid->makeTransformGrid() ; // make the grid transformation 
     1149        std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridSrc, grid, detectMissingValues, defaultValue);  
     1150        lastFilter->connectOutput(filters.first, 0); 
     1151        lastFilter = filters.second; 
     1152        gridSrc=grid ; 
     1153      } 
     1154      instantDataFilter = lastFilter ; 
     1155       
     1156      // connect the input Filter to the reference 
     1157      getDirectFieldReference()->getInstantDataFilter()->connectOutput(inputFilter,0); 
     1158    } 
     1159    else  
     1160    { 
     1161      if (!grid_->checkIfCompleted()) return false ; 
     1162      grid_->solveElementsRefInheritance() ; 
     1163      grid_->completeGrid(); // grid generation, to be checked 
     1164      grid_->checkElementsAttributes() ; 
     1165      instantDataFilter=inputFilter ; 
     1166      setModelIn() ; // no reference, the field is potentially a source field from model 
     1167    } 
     1168     
     1169    buildWorkflowGraphDone_ = true ; 
     1170    workflowEnabled_ = true ; 
     1171    return true ; 
     1172  } 
     1173    
     1174   
     1175  void CField::connectToFileServer(CGarbageCollector& gc) 
     1176  { 
     1177    // insert temporal filter before sending to files 
     1178    fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 
     1179    // insert temporal filter before sending to files 
     1180    getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 
     1181  }  
     1182 
     1183  void CField::computeGridIndexToFileServer(void) 
     1184  { 
     1185    grid_->computeGridIndexToFileServer(client) ; 
     1186  } 
    7931187 
    7941188   /*! 
    795      Build up graph of grids which plays role of destination and source in grid transformation 
    796      This function should be called before \func solveGridReference() 
     1189   * Transform the grid_path attribut into vector of grid. 
     1190   * \return the vector CGrid* containing the list of grid path for tranformation 
     1191   */  
     1192  vector<CGrid*> CField::getGridPath(void) 
     1193  { 
     1194    std::vector<CGrid*> gridPath; 
     1195 
     1196    if (hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 
     1197    { 
     1198      if (!grid_path.isEmpty()) 
     1199      { 
     1200        std::string gridId; 
     1201        size_t start = 0, end; 
     1202 
     1203        do 
     1204        { 
     1205          end = grid_path.getValue().find(',', start); 
     1206          if (end != std::string::npos) 
     1207          { 
     1208            gridId = grid_path.getValue().substr(start, end - start); 
     1209            start = end + 1; 
     1210          } 
     1211          else gridId = grid_path.getValue().substr(start); 
     1212 
     1213          if (!CGrid::has(gridId)) 
     1214            ERROR("void CField::solveTransformedGrid()", 
     1215               << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 
     1216 
     1217          gridPath.push_back(CGrid::get(gridId)); 
     1218        } 
     1219        while (end != std::string::npos); 
     1220      } 
     1221    } 
     1222    return gridPath ; 
     1223  } 
     1224 
     1225  /*! 
     1226   * Constructs the graph filter for the field, enabling or not the data output. 
     1227   * This method should not be called more than once with enableOutput equal to true. 
     1228   * 
     1229   * \param gc the garbage collector to use when building the filter graph 
     1230   * \param enableOutput must be true when the field data is to be 
     1231   *                     read by the client or/and written to a file 
    7971232   */ 
    798    void CField::buildGridTransformationGraph() 
    799    TRY 
    800    { 
    801      CContext* context = CContext::getCurrent(); 
    802      if (context->getServiceType()==CServicesManager::CLIENT) 
    803      { 
    804        if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 
    805        { 
    806          grid->addTransGridSource(getDirectFieldReference()->grid); 
    807        } 
    808      } 
    809    } 
    810    CATCH_DUMP_ATTR 
    811  
    812    /*! 
    813      Generate a new grid destination if there are more than one grid source pointing to a same grid destination 
    814    */ 
    815    void CField::generateNewTransformationGridDest() 
    816    TRY 
    817    { 
    818      CContext* context = CContext::getCurrent(); 
    819      if (context->getServiceType()==CServicesManager::CLIENT) 
    820      { 
    821        std::map<CGrid*,std::pair<bool,StdString> >& gridSrcMap = grid->getTransGridSource(); 
    822        if (1 < gridSrcMap.size()) 
    823        { 
    824          // Search for grid source 
    825          CGrid* gridSrc = grid; 
    826          CField* currField = this; 
    827          std::vector<CField*> hieraField; 
    828  
    829          while (currField->hasDirectFieldReference() && (gridSrc == grid)) 
    830          { 
    831            hieraField.push_back(currField); 
    832            CField* tmp = currField->getDirectFieldReference(); 
    833            currField = tmp; 
    834            gridSrc = currField->grid; 
    835          } 
    836  
    837          if (gridSrcMap.end() != gridSrcMap.find(gridSrc)) 
    838          { 
    839            CGrid* gridTmp; 
    840            std::pair<bool,StdString> newGridDest = gridSrcMap[gridSrc]; 
    841            if (newGridDest.first) 
    842            { 
    843              StdString newIdGridDest = newGridDest.second; 
    844              if (!CGrid::has(newIdGridDest)) 
    845              { 
    846                 ERROR("CGrid* CGrid::generateNewTransformationGridDest()", 
    847                   << " Something wrong happened! Grid whose id " << newIdGridDest 
    848                   << "should exist "); 
    849              } 
    850              gridTmp = CGrid::get(newIdGridDest); 
    851            } 
    852            else 
    853            { 
    854              StdString newIdGridDest = CGrid::generateId(gridSrc, grid); 
    855              gridTmp = CGrid::cloneGrid(newIdGridDest, grid); 
    856  
    857              (gridSrcMap[gridSrc]).first = true; 
    858              (gridSrcMap[gridSrc]).second = newIdGridDest; 
    859            } 
    860  
    861            // Update all descendants 
    862            for (std::vector<CField*>::iterator it = hieraField.begin(); it != hieraField.end(); ++it) 
    863            { 
    864              (*it)->grid = gridTmp; 
    865              (*it)->updateRef((*it)->grid); 
    866            } 
    867          } 
    868        } 
    869      } 
    870    } 
    871    CATCH_DUMP_ATTR 
    872  
    873    void CField::updateRef(CGrid* grid) 
    874    TRY 
    875    { 
    876      if (!grid_ref.isEmpty()) grid_ref.setValue(grid->getId()); 
    877      else 
    878      { 
    879        std::vector<CAxis*> axisTmp = grid->getAxis(); 
    880        std::vector<CDomain*> domainTmp = grid->getDomains(); 
    881        if ((1<axisTmp.size()) || (1<domainTmp.size())) 
    882          ERROR("void CField::updateRef(CGrid* grid)", 
    883            << "More than one domain or axis is available for domain_ref/axis_ref of field " << this->getId()); 
    884  
    885        if ((!domain_ref.isEmpty()) && (domainTmp.empty())) 
    886          ERROR("void CField::updateRef(CGrid* grid)", 
    887            << "Incoherent between available domain and domain_ref of field " << this->getId()); 
    888        if ((!axis_ref.isEmpty()) && (axisTmp.empty())) 
    889          ERROR("void CField::updateRef(CGrid* grid)", 
    890            << "Incoherent between available axis and axis_ref of field " << this->getId()); 
    891  
    892        if (!domain_ref.isEmpty()) domain_ref.setValue(domainTmp[0]->getId()); 
    893        if (!axis_ref.isEmpty()) axis_ref.setValue(axisTmp[0]->getId()); 
    894      } 
    895    } 
    896    CATCH_DUMP_ATTR 
    897     
    898    /*! 
    899      Solve reference of all enabled fields even the source fields . 
    900      In this step, we do transformations. 
    901    */ 
    902    void CField::solveAllEnabledFieldsAndTransform() 
    903    TRY 
    904    { 
    905      CContext* context = CContext::getCurrent(); 
    906  
    907      if (!isReferenceSolvedAndTransformed) 
    908      { 
    909         isReferenceSolvedAndTransformed = true; 
    910  
    911         if (context->getServiceType()==CServicesManager::CLIENT) 
    912         { 
    913           solveRefInheritance(true); 
    914           if (hasDirectFieldReference()) getDirectFieldReference()->solveAllEnabledFieldsAndTransform(); 
    915         } 
    916  
    917         if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
    918           solveServerOperation(); 
    919  
    920         solveGridReference(); 
    921  
    922        if (context->getServiceType()==CServicesManager::CLIENT) 
    923        { 
    924          solveGenerateGrid(); 
    925          buildGridTransformationGraph(); 
    926        } 
    927  
    928        solveGridDomainAxisRef(false); 
    929  
    930        if (context->getServiceType()==CServicesManager::CLIENT) 
    931        { 
    932          solveTransformedGrid(); 
    933        } 
    934  
    935        solveGridDomainAxisRef(false); 
    936      } 
    937    } 
    938    CATCH_DUMP_ATTR 
    939  
    940    void CField::checkGridOfEnabledFields() 
    941    TRY 
    942    { 
    943      if (!isGridChecked) 
    944      { 
    945        isGridChecked = true; 
    946        solveCheckMaskIndex(false); 
    947      } 
    948    } 
    949    CATCH_DUMP_ATTR 
    950  
    951    void CField::sendGridComponentOfEnabledFields() 
    952    TRY 
    953    { 
    954       solveGridDomainAxisRef(true); 
    955       // solveCheckMaskIndex(true); 
    956    } 
    957    CATCH_DUMP_ATTR 
    958  
    959    void CField::sendGridOfEnabledFields() 
    960    TRY 
    961    { 
    962       // solveGridDomainAxisRef(true); 
    963       solveCheckMaskIndex(true); 
    964    }    
    965    CATCH_DUMP_ATTR 
    966  
    967    void CField::solveOnlyReferenceEnabledField(void) 
    968    TRY 
    969    { 
    970      CContext* context = CContext::getCurrent(); 
    971      if (!isReferenceSolved) 
    972      { 
    973         isReferenceSolved = true; 
    974  
    975         if (context->getServiceType()==CServicesManager::CLIENT) 
    976         { 
    977           solveRefInheritance(true); 
    978           if (hasDirectFieldReference()) getDirectFieldReference()->solveOnlyReferenceEnabledField(); 
    979         } 
    980  
    981         if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
    982           solveServerOperation(); 
    983  
    984         solveGridReference(); 
    985         grid->solveDomainAxisRefInheritance(true); // make it again to solve grid reading from file 
    986  
    987        if (context->getServiceType()==CServicesManager::CLIENT) 
    988        { 
    989          solveGenerateGrid(); 
    990          buildGridTransformationGraph(); 
    991        } 
    992      } 
    993    } 
    994    CATCH_DUMP_ATTR 
    995  
    996    void CField::solveAllReferenceEnabledField(bool doSending2Server) 
    997    TRY 
    998    { 
    999      CContext* context = CContext::getCurrent(); 
    1000      solveOnlyReferenceEnabledField(); 
    1001  
    1002      if (!areAllReferenceSolved) 
    1003      { 
    1004         areAllReferenceSolved = true; 
    1005         
    1006         if (context->getServiceType()==CServicesManager::CLIENT) 
    1007         { 
    1008           solveRefInheritance(true); 
    1009           if (hasDirectFieldReference()) getDirectFieldReference()->solveAllReferenceEnabledField(false); 
    1010         } 
    1011         else if (context->getServiceType()==CServicesManager::GATHERER || context->getServiceType()==CServicesManager::OUT_SERVER) 
    1012           solveServerOperation(); 
    1013  
    1014         solveGridReference(); 
    1015      } 
    1016  
    1017      solveGridDomainAxisRef(doSending2Server); 
    1018  
    1019      if (context->getServiceType()==CServicesManager::CLIENT) 
    1020      { 
    1021        solveTransformedGrid(); 
    1022      } 
    1023  
    1024      solveCheckMaskIndex(doSending2Server); 
    1025    } 
    1026    CATCH_DUMP_ATTR 
    1027  
    1028    std::map<int, StdSize> CField::getGridAttributesBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 
    1029    TRY 
    1030    { 
    1031      return grid->getAttributesBufferSize(client, bufferForWriting); 
    1032    } 
    1033    CATCH_DUMP_ATTR 
    1034  
    1035    std::map<int, StdSize> CField::getGridDataBufferSize(CContextClient* client, bool bufferForWriting /*= "false"*/) 
    1036    TRY 
    1037    { 
    1038      return grid->getDataBufferSize(client, getId(), bufferForWriting); 
    1039    } 
    1040    CATCH_DUMP_ATTR 
    1041  
    1042    size_t CField::getGlobalWrittenSize() 
    1043    TRY 
    1044    { 
    1045      return grid->getGlobalWrittenSize(); 
    1046    } 
    1047    CATCH_DUMP_ATTR 
    1048  
    1049    //---------------------------------------------------------------- 
    1050  
    1051    void CField::solveServerOperation(void) 
    1052    TRY 
    1053    { 
    1054       CContext* context = CContext::getCurrent(); 
    1055  
    1056       if (context->getServiceType()==CServicesManager::CLIENT || !hasOutputFile) return; 
    1057  
    1058       if (freq_op.isEmpty()) 
    1059         freq_op.setValue(TimeStep); 
    1060  
    1061       if (freq_offset.isEmpty()) 
    1062         freq_offset.setValue(NoneDu); 
    1063  
    1064       freq_operation_srv = file->output_freq.getValue(); 
    1065       freq_write_srv     = file->output_freq.getValue(); 
    1066  
    1067       lastlast_Write_srv = context->getCalendar()->getInitDate(); 
    1068       last_Write_srv     = context->getCalendar()->getInitDate(); 
    1069       last_operation_srv = context->getCalendar()->getInitDate(); 
    1070  
    1071       const CDuration toffset = freq_operation_srv - freq_offset.getValue() - context->getCalendar()->getTimeStep(); 
    1072       last_operation_srv     = last_operation_srv - toffset; 
    1073  
    1074       if (operation.isEmpty()) 
    1075         ERROR("void CField::solveServerOperation(void)", 
    1076               << "An operation must be defined for field \"" << getId() << "\"."); 
    1077  
    1078       std::shared_ptr<func::CFunctor> functor; 
    1079       CArray<double, 1> dummyData; 
    1080  
    1081 #define DECLARE_FUNCTOR(MType, mtype) \ 
    1082       if (operation.getValue().compare(#mtype) == 0) \ 
    1083       { \ 
    1084         functor.reset(new func::C##MType(dummyData)); \ 
    1085       } 
    1086  
    1087 #include "functor_type.conf" 
    1088  
    1089       if (!functor) 
    1090         ERROR("void CField::solveServerOperation(void)", 
    1091               << "\"" << operation << "\" is not a valid operation."); 
    1092  
    1093       operationTimeType = functor->timeType(); 
    1094    } 
    1095    CATCH_DUMP_ATTR 
    1096  
    1097    //---------------------------------------------------------------- 
    1098  
    1099    /*! 
    1100     * Constructs the graph filter for the field, enabling or not the data output. 
    1101     * This method should not be called more than once with enableOutput equal to true. 
    1102     * 
    1103     * \param gc the garbage collector to use when building the filter graph 
    1104     * \param enableOutput must be true when the field data is to be 
    1105     *                     read by the client or/and written to a file 
    1106     */ 
    1107    void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput) 
    1108    TRY 
    1109    {      
     1233 
     1234  void CField::buildFilterGraph(CGarbageCollector& gc, bool enableOutput) 
     1235  TRY 
     1236  {      
    11101237    if (!isReferenceSolvedAndTransformed) solveAllEnabledFieldsAndTransform(); 
    11111238    if (!isGridChecked) checkGridOfEnabledFields(); 
    11121239 
    1113      const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
    1114      const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 
    1115  
    1116      CContext* context = CContext::getCurrent(); 
    1117      bool hasWriterServer = context->getServiceType()==CServicesManager::OUT_SERVER ; 
    1118      bool hasIntermediateServer = context->getServiceType()==CServicesManager::GATHERER ; 
    1119  
    1120      if (hasWriterServer) 
    1121      { 
    1122         if (!instantDataFilter) 
    1123           instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false)); 
    1124  
    1125  
    1126        // If the field data is to be read by the client or/and written to a file 
    1127        if (enableOutput && !storeFilter && !fileWriterFilter) 
    1128        { 
    1129          if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
    1130          { 
    1131            fileServerWriterFilter = std::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this)); 
    1132            instantDataFilter->connectOutput(fileServerWriterFilter, 0); 
     1240    const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
     1241    const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 
     1242 
     1243    CContext* context = CContext::getCurrent(); 
     1244    bool hasWriterServer = context->getServiceType()==CServicesManager::OUT_SERVER ; 
     1245    bool hasIntermediateServer = context->getServiceType()==CServicesManager::GATHERER ; 
     1246 
     1247    if (hasWriterServer) 
     1248    { 
     1249      if (!instantDataFilter) 
     1250        instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false)); 
     1251 
     1252 
     1253      // If the field data is to be read by the client or/and written to a file 
     1254      if (enableOutput && !storeFilter && !fileWriterFilter) 
     1255      { 
     1256        if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
     1257        { 
     1258          fileServerWriterFilter = std::shared_ptr<CFileServerWriterFilter>(new CFileServerWriterFilter(gc, this)); 
     1259          instantDataFilter->connectOutput(fileServerWriterFilter, 0); 
     1260        } 
     1261      } 
     1262    } 
     1263    else if (hasIntermediateServer) 
     1264    { 
     1265      if (!instantDataFilter) 
     1266        instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, false, false)); 
     1267 
     1268      // If the field data is to be read by the client or/and written to a file 
     1269      if (enableOutput && !storeFilter && !fileWriterFilter) 
     1270      { 
     1271        if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
     1272        { 
     1273          fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 
     1274          instantDataFilter->connectOutput(fileWriterFilter, 0); 
     1275        } 
     1276      } 
     1277    } 
     1278    else 
     1279    { 
     1280      // Start by building a filter which can provide the field's instant data 
     1281      if (!instantDataFilter) 
     1282      { 
     1283        // Check if we have an expression to parse 
     1284        if (hasExpression()) 
     1285        { 
     1286          boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 
     1287          std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 
     1288 
     1289          // Check if a spatial transformation is needed 
     1290          if (!field_ref.isEmpty()) 
     1291          { 
     1292            CGrid* gridRef = CField::get(field_ref)->grid_; 
     1293            if (grid_ && grid_ != gridRef && grid_->hasTransform()) 
     1294            { 
     1295                std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid_, detectMissingValues, defaultValue);  
     1296 
     1297              filter->connectOutput(filters.first, 0); 
     1298              filter = filters.second; 
     1299            } 
     1300          } 
     1301 
     1302          instantDataFilter = filter; 
     1303        } 
     1304        // Check if we have a reference on another field 
     1305        else if (!field_ref.isEmpty()) instantDataFilter = getFieldReference(gc); 
     1306        // Check if the data is to be read from a file 
     1307        else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
     1308        { 
     1309          checkTimeAttributes(); 
     1310          instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false, freq_offset, true, 
     1311                                                                                                       detectMissingValues, defaultValue)); 
     1312        } 
     1313        else // The data might be passed from the model 
     1314        { 
     1315          if (check_if_active.isEmpty()) check_if_active = false;  
     1316          instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, false, true, NoneDu, false, 
     1317                                                                                                      detectMissingValues, defaultValue)); 
     1318        } 
     1319      } 
     1320 
     1321      // If the field data is to be read by the client or/and written to a file 
     1322      if (enableOutput && !storeFilter && !fileWriterFilter) 
     1323      { 
     1324        if (!read_access.isEmpty() && read_access) 
     1325        { 
     1326          storeFilter = std::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid_, 
     1327                                                                          detectMissingValues, defaultValue)); 
     1328          instantDataFilter->connectOutput(storeFilter, 0); 
     1329        } 
     1330 
     1331        if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
     1332        { 
     1333          fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 
     1334          getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 
     1335        } 
     1336      } 
     1337    } 
     1338  } 
     1339  CATCH_DUMP_ATTR 
     1340 
     1341  /*! 
     1342   * Returns the filter needed to handle the field reference. 
     1343   * This method should only be called when building the filter graph corresponding to the field. 
     1344   * 
     1345   * \param gc the garbage collector to use 
     1346   * \return the output pin corresponding to the field reference 
     1347   */ 
     1348  std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 
     1349  TRY 
     1350  { 
     1351    if (instantDataFilter || field_ref.isEmpty()) 
     1352      ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 
     1353            "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 
     1354 
     1355    CField* fieldRef = CField::get(field_ref); 
     1356    fieldRef->buildFilterGraph(gc, false); 
     1357 
     1358    std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters; 
     1359    // Check if a spatial transformation is needed 
     1360    if (grid_ && grid_ != fieldRef->grid_ && grid_->hasTransform()) 
     1361    {        
     1362      bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
     1363      double defaultValue  = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0);                                 
     1364      filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid_, grid_, hasMissingValue, defaultValue); 
     1365    } 
     1366    else 
     1367      filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 
     1368 
     1369    fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 
     1370 
     1371    return filters.second; 
     1372  } 
     1373  CATCH_DUMP_ATTR 
     1374 
     1375  /*! 
     1376   * Returns the filter needed to handle a self reference in the field's expression. 
     1377   * If the needed filter does not exist, it is created, otherwise it is reused. 
     1378   * This method should only be called when building the filter graph corresponding 
     1379   * to the field's expression. 
     1380   * 
     1381   * \param gc the garbage collector to use 
     1382   * \return the output pin corresponding to a self reference 
     1383   */ 
     1384 
     1385/* old version 
     1386  std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 
     1387  TRY 
     1388  { 
     1389    if (instantDataFilter || !hasExpression()) 
     1390      ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 
     1391            "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
     1392 
     1393    if (!selfReferenceFilter) 
     1394    { 
     1395      const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
     1396      const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 
     1397 
     1398      if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
     1399      { 
     1400        if (!serverSourceFilter) 
     1401        { 
     1402          checkTimeAttributes(); 
     1403          serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, false, freq_offset, true, 
     1404                                                              detectMissingValues, defaultValue)); 
    11331405         } 
    1134        } 
    1135      } 
    1136      else if (hasIntermediateServer) 
    1137      { 
    1138        if (!instantDataFilter) 
    1139          instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, false)); 
    1140  
    1141              // If the field data is to be read by the client or/and written to a file 
    1142        if (enableOutput && !storeFilter && !fileWriterFilter) 
    1143        { 
    1144          if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
    1145          { 
    1146            fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 
    1147            instantDataFilter->connectOutput(fileWriterFilter, 0); 
    1148          } 
    1149        } 
    1150      } 
    1151      else 
    1152      { 
    1153        // Start by building a filter which can provide the field's instant data 
    1154        if (!instantDataFilter) 
    1155        { 
    1156          // Check if we have an expression to parse 
    1157          if (hasExpression()) 
    1158          { 
    1159            boost::scoped_ptr<IFilterExprNode> expr(parseExpr(getExpression() + '\0')); 
    1160            std::shared_ptr<COutputPin> filter = expr->reduce(gc, *this); 
    1161  
    1162            // Check if a spatial transformation is needed 
    1163            if (!field_ref.isEmpty()) 
    1164            { 
    1165              CGrid* gridRef = CField::get(field_ref)->grid; 
    1166  
    1167              if (grid && grid != gridRef && grid->hasTransform()) 
    1168              { 
    1169                  std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters = CSpatialTransformFilter::buildFilterGraph(gc, gridRef, grid, detectMissingValues, defaultValue);  
    1170  
    1171                filter->connectOutput(filters.first, 0); 
    1172                filter = filters.second; 
    1173              } 
    1174            } 
    1175  
    1176            instantDataFilter = filter; 
    1177          } 
    1178          // Check if we have a reference on another field 
    1179          else if (!field_ref.isEmpty()) 
    1180            instantDataFilter = getFieldReference(gc); 
    1181          // Check if the data is to be read from a file 
    1182          else if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
    1183          { 
    1184            checkTimeAttributes(); 
    1185            instantDataFilter = serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 
    1186                                                                                                        detectMissingValues, defaultValue)); 
    1187          } 
    1188          else // The data might be passed from the model 
    1189          { 
    1190             if (check_if_active.isEmpty()) check_if_active = false;  
    1191             instantDataFilter = clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, false, true, NoneDu, false, 
    1192                                                                                                         detectMissingValues, defaultValue)); 
    1193          } 
    1194        } 
    1195  
    1196        // If the field data is to be read by the client or/and written to a file 
    1197        if (enableOutput && !storeFilter && !fileWriterFilter) 
    1198        { 
    1199          if (!read_access.isEmpty() && read_access) 
    1200          { 
    1201            storeFilter = std::shared_ptr<CStoreFilter>(new CStoreFilter(gc, CContext::getCurrent(), grid, 
    1202                                                                           detectMissingValues, defaultValue)); 
    1203            instantDataFilter->connectOutput(storeFilter, 0); 
    1204          } 
    1205  
    1206          if (file && (file->mode.isEmpty() || file->mode == CFile::mode_attr::write)) 
    1207          { 
    1208            fileWriterFilter = std::shared_ptr<CFileWriterFilter>(new CFileWriterFilter(gc, this, file->getContextClient())); 
    1209            getTemporalDataFilter(gc, file->output_freq)->connectOutput(fileWriterFilter, 0); 
    1210          } 
    1211        } 
    1212      } 
    1213    } 
    1214    CATCH_DUMP_ATTR 
    1215  
    1216    /*! 
    1217     * Returns the filter needed to handle the field reference. 
    1218     * This method should only be called when building the filter graph corresponding to the field. 
    1219     * 
    1220     * \param gc the garbage collector to use 
    1221     * \return the output pin corresponding to the field reference 
    1222     */ 
    1223    std::shared_ptr<COutputPin> CField::getFieldReference(CGarbageCollector& gc) 
    1224    TRY 
    1225    { 
    1226      if (instantDataFilter || field_ref.isEmpty()) 
    1227        ERROR("COutputPin* CField::getFieldReference(CGarbageCollector& gc)", 
    1228              "Impossible to get the field reference for a field which has already been parsed or which does not have a field_ref."); 
    1229  
    1230      CField* fieldRef = CField::get(field_ref); 
    1231      fieldRef->buildFilterGraph(gc, false); 
    1232  
    1233      std::pair<std::shared_ptr<CFilter>, std::shared_ptr<CFilter> > filters; 
    1234      // Check if a spatial transformation is needed 
    1235      if (grid && grid != fieldRef->grid && grid->hasTransform()) 
    1236      {        
    1237        bool hasMissingValue = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
    1238        double defaultValue  = hasMissingValue ? default_value : (!default_value.isEmpty() ? default_value : 0.0);                                 
    1239        filters = CSpatialTransformFilter::buildFilterGraph(gc, fieldRef->grid, grid, hasMissingValue, defaultValue); 
    1240      } 
    1241      else 
    1242        filters.first = filters.second = std::shared_ptr<CFilter>(new CPassThroughFilter(gc)); 
    1243  
    1244      fieldRef->getInstantDataFilter()->connectOutput(filters.first, 0); 
    1245  
    1246      return filters.second; 
    1247    } 
    1248    CATCH_DUMP_ATTR 
    1249  
    1250    /*! 
    1251     * Returns the filter needed to handle a self reference in the field's expression. 
    1252     * If the needed filter does not exist, it is created, otherwise it is reused. 
    1253     * This method should only be called when building the filter graph corresponding 
    1254     * to the field's expression. 
    1255     * 
    1256     * \param gc the garbage collector to use 
    1257     * \return the output pin corresponding to a self reference 
    1258     */ 
    1259    std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 
    1260    TRY 
    1261    { 
    1262      if (instantDataFilter || !hasExpression()) 
    1263        ERROR("COutputPin* CField::getSelfReference(CGarbageCollector& gc)", 
    1264              "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
    1265  
    1266      if (!selfReferenceFilter) 
    1267      { 
    1268        const bool detectMissingValues = (!detect_missing_value.isEmpty() && !default_value.isEmpty() && detect_missing_value == true); 
    1269        const double defaultValue  = detectMissingValues ? default_value : (!default_value.isEmpty() ? default_value : 0.0); 
    1270  
    1271        if (file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read) 
    1272        { 
    1273          if (!serverSourceFilter) 
    1274          { 
    1275            checkTimeAttributes(); 
    1276            serverSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, false, freq_offset, true, 
    1277                                                                                    detectMissingValues, defaultValue)); 
    1278          } 
    1279  
    1280          selfReferenceFilter = serverSourceFilter; 
    1281        } 
    1282        else if (!field_ref.isEmpty()) 
    1283        { 
    1284          CField* fieldRef = CField::get(field_ref); 
    1285          fieldRef->buildFilterGraph(gc, false); 
    1286          selfReferenceFilter = fieldRef->getInstantDataFilter(); 
    1287        } 
    1288        else 
    1289        { 
    1290          if (!clientSourceFilter) 
    1291          { 
    1292            if (check_if_active.isEmpty()) check_if_active = false; 
    1293            clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid, true, true, NoneDu, false, 
    1294                                                                                    detectMissingValues, defaultValue)); 
    1295          } 
    1296  
    1297          selfReferenceFilter = clientSourceFilter; 
    1298        } 
    1299      } 
    1300  
    1301      return selfReferenceFilter; 
    1302    } 
    1303    CATCH_DUMP_ATTR 
    1304  
    1305    /*! 
    1306     * Returns the temporal filter corresponding to the field's temporal operation 
    1307     * for the specified operation frequency. The filter is created if it does not 
    1308     * exist, otherwise it is reused. 
    1309     * 
    1310     * \param gc the garbage collector to use 
    1311     * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 
    1312     * \return the output pin corresponding to the requested temporal filter 
    1313     */ 
    1314    std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
    1315    TRY 
    1316    { 
    1317      std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 
    1318  
    1319      if (it == temporalDataFilters.end()) 
    1320      { 
    1321        if (operation.isEmpty()) 
    1322          ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
    1323                << "An operation must be defined for field \"" << getId() << "\"."); 
    1324  
    1325        checkTimeAttributes(&outFreq); 
    1326  
    1327        const bool detectMissingValues = (!detect_missing_value.isEmpty()  && detect_missing_value == true); 
    1328        std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 
     1406 
     1407        selfReferenceFilter = serverSourceFilter; 
     1408      } 
     1409      else if (!field_ref.isEmpty()) 
     1410      { 
     1411        CField* fieldRef = CField::get(field_ref); 
     1412        fieldRef->buildFilterGraph(gc, false); 
     1413        selfReferenceFilter = fieldRef->getInstantDataFilter(); 
     1414      } 
     1415      else 
     1416      { 
     1417        if (!clientSourceFilter) 
     1418        { 
     1419          if (check_if_active.isEmpty()) check_if_active = false; 
     1420          clientSourceFilter = std::shared_ptr<CSourceFilter>(new CSourceFilter(gc, grid_, true, true, NoneDu, false, 
     1421                                                                                detectMissingValues, defaultValue)); 
     1422        } 
     1423 
     1424        selfReferenceFilter = clientSourceFilter; 
     1425      } 
     1426    } 
     1427 
     1428    return selfReferenceFilter; 
     1429  } 
     1430  CATCH_DUMP_ATTR 
     1431*/ 
     1432  std::shared_ptr<COutputPin> CField::getSelfReference(CGarbageCollector& gc) 
     1433  TRY 
     1434  { 
     1435    return inputFilter ; 
     1436  }  
     1437  CATCH_DUMP_ATTR 
     1438 
     1439  /*! 
     1440   * Returns the temporal filter corresponding to the field's temporal operation 
     1441   * for the specified operation frequency. The filter is created if it does not 
     1442   * exist, otherwise it is reused. 
     1443   * 
     1444   * \param gc the garbage collector to use 
     1445   * \param outFreq the operation frequency, i.e. the frequency at which the output data will be computed 
     1446   * \return the output pin corresponding to the requested temporal filter 
     1447   */ 
     1448  std::shared_ptr<COutputPin> CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
     1449  TRY 
     1450  { 
     1451    std::map<CDuration, std::shared_ptr<COutputPin> >::iterator it = temporalDataFilters.find(outFreq); 
     1452 
     1453    if (it == temporalDataFilters.end()) 
     1454    { 
     1455      if (operation.isEmpty()) 
     1456        ERROR("void CField::getTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
     1457              << "An operation must be defined for field \"" << getId() << "\"."); 
     1458 
     1459      checkTimeAttributes(&outFreq); 
     1460 
     1461      const bool detectMissingValues = (!detect_missing_value.isEmpty()  && detect_missing_value == true); 
     1462      std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 
    13291463                                                                             CContext::getCurrent()->getCalendar()->getInitDate(), 
    13301464                                                                             freq_op, freq_offset, outFreq, detectMissingValues)); 
    13311465 
    1332        instantDataFilter->connectOutput(temporalFilter, 0); 
    1333  
    1334        it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first; 
    1335      } 
    1336  
    1337      return it->second; 
    1338    } 
    1339    CATCH_DUMP_ATTR 
     1466      instantDataFilter->connectOutput(temporalFilter, 0); 
     1467 
     1468      it = temporalDataFilters.insert(std::make_pair(outFreq, temporalFilter)).first; 
     1469    } 
     1470 
     1471    return it->second; 
     1472  } 
     1473  CATCH_DUMP_ATTR 
    13401474 
    13411475  /*! 
     
    13471481    * \return the output pin corresponding to the requested temporal filter 
    13481482    */ 
    1349     
    1350    std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
    1351    TRY 
    1352    { 
    1353      if (instantDataFilter || !hasExpression()) 
    1354        ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 
    1355              "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
    1356  
    1357      if (!selfReferenceFilter) getSelfReference(gc) ; 
    1358  
    1359      if (serverSourceFilter || clientSourceFilter) 
    1360      { 
    1361        if (operation.isEmpty()) 
    1362          ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
    1363                << "An operation must be defined for field \"" << getId() << "\"."); 
    1364  
    1365        checkTimeAttributes(&outFreq); 
    1366  
    1367        const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 
    1368        std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 
    1369                                                                              CContext::getCurrent()->getCalendar()->getInitDate(), 
    1370                                                                              freq_op, freq_offset, outFreq, detectMissingValues)); 
    1371  
    1372        selfReferenceFilter->connectOutput(temporalFilter, 0); 
    1373        return temporalFilter ; 
    1374      } 
    1375      else if (!field_ref.isEmpty()) 
    1376      { 
    1377        CField* fieldRef = CField::get(field_ref); 
    1378        fieldRef->buildFilterGraph(gc, false);  
    1379        return fieldRef->getTemporalDataFilter(gc, outFreq) ; 
    1380      } 
    1381   } 
    1382    CATCH_DUMP_ATTR 
    1383  
    1384    //---------------------------------------------------------------- 
     1483 
     1484  std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
     1485  TRY 
     1486  { 
     1487    if (instantDataFilter || !hasExpression()) 
     1488      ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 
     1489            "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
     1490     
     1491    if (selfTemporalDataFilter) return selfTemporalDataFilter; 
     1492 
     1493    if (hasDirectFieldReference()) 
     1494    { 
     1495      CField* fieldRef=getDirectFieldReference(); 
     1496      return fieldRef->getTemporalDataFilter(gc, outFreq) ; 
     1497    } 
     1498    else 
     1499    { 
     1500      if (selfTemporalDataFilter) return selfTemporalDataFilter ; 
     1501 
     1502      if (operation.isEmpty()) 
     1503        ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
     1504              << "An operation must be defined for field \"" << getId() << "\"."); 
     1505 
     1506      checkTimeAttributes(&outFreq); //bof 
     1507 
     1508      const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 
     1509      selfTemporalDataFilter = std::shared_ptr<CTemporalFilter>(new CTemporalFilter(gc, operation, 
     1510                                                                CContext::getCurrent()->getCalendar()->getInitDate(), 
     1511                                                                freq_op, freq_offset, outFreq, detectMissingValues)); 
     1512 
     1513      inputFilter->connectOutput(selfTemporalDataFilter, 0); 
     1514      return selfTemporalDataFilter ; 
     1515    } 
     1516  } 
     1517  CATCH_DUMP_ATTR 
     1518 
     1519/* old version    
     1520  std::shared_ptr<COutputPin> CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq) 
     1521  TRY 
     1522  { 
     1523    if (instantDataFilter || !hasExpression()) 
     1524      ERROR("COutputPin* CField::getSelfTemporalDataFilter(CGarbageCollector& gc)", 
     1525            "Impossible to add a self reference to a field which has already been parsed or which does not have an expression."); 
     1526 
     1527    if (!selfReferenceFilter) getSelfReference(gc) ; 
     1528 
     1529    if (serverSourceFilter || clientSourceFilter) 
     1530    { 
     1531      if (operation.isEmpty()) 
     1532        ERROR("void CField::getSelfTemporalDataFilter(CGarbageCollector& gc, CDuration outFreq)", 
     1533              << "An operation must be defined for field \"" << getId() << "\"."); 
     1534 
     1535      checkTimeAttributes(&outFreq); 
     1536 
     1537      const bool detectMissingValues = (!detect_missing_value.isEmpty() && detect_missing_value == true); 
     1538      std::shared_ptr<CTemporalFilter> temporalFilter(new CTemporalFilter(gc, operation, 
     1539                                                                          CContext::getCurrent()->getCalendar()->getInitDate(), 
     1540                                                                          freq_op, freq_offset, outFreq, detectMissingValues)); 
     1541 
     1542      selfReferenceFilter->connectOutput(temporalFilter, 0); 
     1543      return temporalFilter ; 
     1544    } 
     1545    else if (!field_ref.isEmpty()) 
     1546    { 
     1547      CField* fieldRef = CField::get(field_ref); 
     1548      fieldRef->buildFilterGraph(gc, false);  
     1549      return fieldRef->getTemporalDataFilter(gc, outFreq) ; 
     1550    } 
     1551  } 
     1552  CATCH_DUMP_ATTR 
     1553*/ 
     1554 
     1555  //---------------------------------------------------------------- 
    13851556/* 
    13861557   void CField::fromBinary(StdIStream& is) 
     
    13981569   //---------------------------------------------------------------- 
    13991570 
    1400    void CField::solveGridReference(void) 
    1401    TRY 
    1402    { 
    1403       if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 
    1404       { 
    1405         ERROR("CField::solveGridReference(void)", 
    1406               << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 
    1407       } 
    1408       else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 
    1409       { 
    1410         ERROR("CField::solveGridReference(void)", 
    1411               << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 
    1412               << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 
    1413       } 
    1414  
    1415       if (grid_ref.isEmpty()) 
    1416       { 
    1417         std::vector<CDomain*> vecDom; 
    1418         std::vector<CAxis*> vecAxis; 
    1419         std::vector<CScalar*> vecScalar; 
    1420         std::vector<int> axisDomainOrderTmp; 
    1421  
    1422         std::vector<CDomain*> vecDomRef; 
    1423         std::vector<CAxis*> vecAxisRef; 
    1424         std::vector<CScalar*> vecScalarRef; 
    1425  
     1571  void CField::solveGridReference(void) 
     1572  TRY 
     1573  { 
     1574    if (grid_!=nullptr) return ; // already done 
     1575 
     1576    if (grid_ref.isEmpty() && domain_ref.isEmpty() && axis_ref.isEmpty() && scalar_ref.isEmpty()) 
     1577    { 
     1578      ERROR("CField::solveGridReference(void)", 
     1579            << "A grid must be defined for field '" << getFieldOutputName() << "' ."); 
     1580    } 
     1581    else if (!grid_ref.isEmpty() && (!domain_ref.isEmpty() || !axis_ref.isEmpty() || !scalar_ref.isEmpty())) 
     1582    { 
     1583      ERROR("CField::solveGridReference(void)", 
     1584            << "Field '" << getFieldOutputName() << "' has both a grid and a domain/axis/scalar." << std::endl 
     1585            << "Please define either 'grid_ref' or 'domain_ref'/'axis_ref'/'scalar_ref'."); 
     1586    } 
     1587 
     1588    if (grid_ref.isEmpty()) 
     1589    { 
     1590      std::vector<CDomain*> vecDom; 
     1591      std::vector<CAxis*> vecAxis; 
     1592      std::vector<CScalar*> vecScalar; 
     1593      std::vector<int> axisDomainOrderTmp; 
     1594 
     1595      std::vector<CDomain*> vecDomRef; 
     1596      std::vector<CAxis*> vecAxisRef; 
     1597      std::vector<CScalar*> vecScalarRef; 
    14261598         
    1427         if (!domain_ref.isEmpty()) 
     1599      if (!domain_ref.isEmpty()) 
     1600      { 
     1601        StdString tmp = domain_ref.getValue(); 
     1602        if (CDomain::has(domain_ref)) 
    14281603        { 
    1429           StdString tmp = domain_ref.getValue(); 
    1430           if (CDomain::has(domain_ref)) 
    1431           { 
    1432             vecDom.push_back(CDomain::get(domain_ref)); 
    1433             vecDomRef.push_back(CDomain::createDomain()); 
    1434             vecDomRef.back()->domain_ref=domain_ref; 
    1435             axisDomainOrderTmp.push_back(2); 
    1436           } 
    1437           else  ERROR("CField::solveGridReference(void)", 
    1438                       << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 
     1604          vecDom.push_back(CDomain::get(domain_ref)); 
     1605          vecDomRef.push_back(CDomain::createDomain()); 
     1606          vecDomRef.back()->domain_ref=domain_ref; 
     1607          axisDomainOrderTmp.push_back(2); 
    14391608        } 
    1440  
    1441         if (!axis_ref.isEmpty()) 
     1609        else  ERROR("CField::solveGridReference(void)", 
     1610                    << "Invalid reference to domain '" << domain_ref.getValue() << "'."); 
     1611      } 
     1612 
     1613      if (!axis_ref.isEmpty()) 
     1614      { 
     1615        if (CAxis::has(axis_ref)) 
    14421616        { 
    1443           if (CAxis::has(axis_ref)) 
    1444           { 
    1445             vecAxis.push_back(CAxis::get(axis_ref)); 
    1446             vecAxisRef.push_back(CAxis::createAxis()); 
    1447             vecAxisRef.back()->axis_ref=axis_ref; 
    1448             axisDomainOrderTmp.push_back(1); 
    1449           } 
    1450           else  ERROR("CField::solveGridReference(void)", 
    1451                       << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 
     1617          vecAxis.push_back(CAxis::get(axis_ref)); 
     1618          vecAxisRef.push_back(CAxis::createAxis()); 
     1619          vecAxisRef.back()->axis_ref=axis_ref; 
     1620          axisDomainOrderTmp.push_back(1); 
    14521621        } 
    1453  
    1454         if (!scalar_ref.isEmpty()) 
     1622        else  ERROR("CField::solveGridReference(void)", 
     1623                    << "Invalid reference to axis '" << axis_ref.getValue() << "'."); 
     1624      } 
     1625 
     1626      if (!scalar_ref.isEmpty()) 
     1627      { 
     1628        if (CScalar::has(scalar_ref)) 
    14551629        { 
    1456           if (CScalar::has(scalar_ref)) 
    1457           { 
    1458             vecScalar.push_back(CScalar::get(scalar_ref)); 
    1459             vecScalarRef.push_back(CScalar::createScalar()); 
    1460             vecScalarRef.back()->scalar_ref=scalar_ref; 
    1461             axisDomainOrderTmp.push_back(0); 
    1462           } 
    1463           else ERROR("CField::solveGridReference(void)", 
    1464                      << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 
     1630          vecScalar.push_back(CScalar::get(scalar_ref)); 
     1631          vecScalarRef.push_back(CScalar::createScalar()); 
     1632          vecScalarRef.back()->scalar_ref=scalar_ref; 
     1633          axisDomainOrderTmp.push_back(0); 
    14651634        } 
     1635        else ERROR("CField::solveGridReference(void)", 
     1636                   << "Invalid reference to scalar '" << scalar_ref.getValue() << "'."); 
     1637      } 
    14661638         
    1467         CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 
    1468         for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 
    1469         { 
    1470           axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 
    1471         } 
    1472  
    1473         // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 
    1474         StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 
    1475         if (CGrid::has(gridId)) this->grid = CGrid::get(gridId); 
    1476         else  this->grid = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 
    1477       } 
    1478       else 
    1479       { 
    1480         if (CGrid::has(grid_ref)) this->grid = CGrid::get(grid_ref); 
    1481         else  ERROR("CField::solveGridReference(void)", 
    1482                      << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 
    1483       } 
    1484    } 
    1485    CATCH_DUMP_ATTR 
    1486  
    1487    void CField::solveGridDomainAxisRef(bool checkAtt) 
    1488    TRY 
    1489    { 
    1490      grid->solveDomainAxisRef(checkAtt); 
    1491    } 
    1492    CATCH_DUMP_ATTR 
    1493  
    1494    void CField::solveCheckMaskIndex(bool doSendingIndex) 
    1495    TRY 
    1496    { 
    1497      grid->checkMaskIndex(doSendingIndex); 
    1498    } 
    1499    CATCH_DUMP_ATTR 
    1500  
    1501    void CField::solveTransformedGrid() 
    1502    TRY 
    1503    { 
    1504      if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 
    1505      { 
    1506        std::vector<CGrid*> grids; 
    1507        // Source grid 
    1508        grids.push_back(getDirectFieldReference()->grid); 
    1509        // Intermediate grids 
    1510        if (!grid_path.isEmpty()) 
    1511        { 
    1512          std::string gridId; 
    1513          size_t start = 0, end; 
    1514  
    1515          do 
    1516          { 
    1517            end = grid_path.getValue().find(',', start); 
    1518            if (end != std::string::npos) 
    1519            { 
    1520              gridId = grid_path.getValue().substr(start, end - start); 
    1521              start = end + 1; 
    1522            } 
    1523            else 
    1524              gridId = grid_path.getValue().substr(start); 
    1525  
    1526            if (!CGrid::has(gridId)) 
    1527              ERROR("void CField::solveTransformedGrid()", 
    1528                    << "Invalid grid_path, the grid '" << gridId << "' does not exist."); 
    1529  
    1530            grids.push_back(CGrid::get(gridId)); 
    1531          } 
    1532          while (end != std::string::npos); 
    1533        } 
    1534        // Destination grid 
    1535        grids.push_back(grid); 
    1536  
    1537        for (size_t i = 0, count = grids.size() - 1; i < count; ++i) 
    1538        { 
    1539          CGrid *gridSrc  = grids[i]; 
    1540          CGrid *gridDest = grids[i + 1]; 
    1541          if (!gridDest->isTransformed()) 
    1542            gridDest->transformGrid(gridSrc); 
    1543        } 
    1544      } 
    1545      else if (grid && grid->hasTransform() && !grid->isTransformed()) 
    1546      { 
    1547        // Temporarily deactivate the self-transformation of grid 
    1548        // grid->transformGrid(grid); 
    1549      } 
    1550    } 
    1551    CATCH_DUMP_ATTR 
    1552  
    1553    void CField::solveGenerateGrid() 
    1554    TRY 
    1555    { 
    1556      if (grid && !grid->isTransformed() && hasDirectFieldReference() && grid != getDirectFieldReference()->grid) 
    1557        grid->completeGrid(getDirectFieldReference()->grid); 
    1558      else 
    1559        grid->completeGrid(); 
    1560    } 
    1561    CATCH_DUMP_ATTR 
    1562  
    1563    void CField::solveGridDomainAxisBaseRef() 
    1564    TRY 
    1565    { 
    1566      grid->solveDomainAxisRef(false); 
    1567      grid->solveDomainAxisBaseRef(); 
    1568    } 
    1569    CATCH_DUMP_ATTR 
    1570  
    1571    ///------------------------------------------------------------------- 
    1572  
    1573    template <> 
    1574    void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 
    1575    TRY 
    1576    { 
    1577       if (this->group_ref.isEmpty()) return; 
    1578       StdString gref = this->group_ref.getValue(); 
    1579  
    1580       if (!CFieldGroup::has(gref)) 
    1581          ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 
    1582                << "[ gref = " << gref << "]" 
    1583                << " invalid group name !"); 
    1584  
    1585       CFieldGroup* group = CFieldGroup::get(gref); 
    1586       CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 
    1587       owner->setAttributes(group); // inherite of attributes of group reference 
     1639      CArray<int,1> axisDomainOrder(axisDomainOrderTmp.size()); 
     1640      for (int idx = 0; idx < axisDomainOrderTmp.size(); ++idx) 
     1641      { 
     1642        axisDomainOrder(idx) = axisDomainOrderTmp[idx]; 
     1643      } 
     1644 
     1645      // Warning: the gridId shouldn't be set as the grid_ref since it could be inherited 
     1646      StdString gridId = CGrid::generateId(vecDom, vecAxis, vecScalar,axisDomainOrder); 
     1647      if (CGrid::has(gridId)) this->grid_ = CGrid::get(gridId); 
     1648      else  this->grid_ = CGrid::createGrid(gridId, vecDomRef, vecAxisRef, vecScalarRef,axisDomainOrder); 
     1649    } 
     1650    else 
     1651    { 
     1652      if (CGrid::has(grid_ref)) this->grid_ = CGrid::get(grid_ref); 
     1653      else  ERROR("CField::solveGridReference(void)", 
     1654                   << "Invalid reference to grid '" << grid_ref.getValue() << "'."); 
     1655    } 
     1656  } 
     1657  CATCH_DUMP_ATTR 
     1658 
     1659  void CField::solveGridDomainAxisRef(bool checkAtt) 
     1660  TRY 
     1661  { 
     1662    grid_->solveDomainAxisRef(checkAtt); 
     1663  } 
     1664  CATCH_DUMP_ATTR 
     1665 
     1666  void CField::solveCheckMaskIndex(bool doSendingIndex) 
     1667  TRY 
     1668  { 
     1669    grid_->checkMaskIndex(doSendingIndex); 
     1670  } 
     1671  CATCH_DUMP_ATTR 
     1672 
     1673  void CField::solveTransformedGrid() 
     1674  TRY 
     1675  { 
     1676    if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 
     1677    { 
     1678      std::vector<CGrid*> grids; 
     1679      // Source grid 
     1680      grids.push_back(getDirectFieldReference()->grid_); 
     1681      auto gridPath = getGridPath() ; 
     1682      grids.insert(grids.begin(), gridPath.begin(), gridPath.end()); 
     1683 
     1684      for (size_t i = 0, count = grids.size() - 1; i < count; ++i) 
     1685      { 
     1686        CGrid *gridSrc  = grids[i]; 
     1687        CGrid *gridDest = grids[i + 1]; 
     1688        if (!gridDest->isTransformed()) gridDest->transformGrid(gridSrc); 
     1689      } 
     1690    } 
     1691    else if (grid_ && grid_->hasTransform() && !grid_->isTransformed()) 
     1692    { 
     1693      // Temporarily deactivate the self-transformation of grid 
     1694      // grid_->transformGrid(grid_); 
     1695    } 
     1696  } 
     1697  CATCH_DUMP_ATTR 
     1698 
     1699  void CField::solveGenerateGrid() 
     1700  TRY 
     1701  { 
     1702    if (grid_ && !grid_->isTransformed() && hasDirectFieldReference() && grid_ != getDirectFieldReference()->grid_) 
     1703      grid_->completeGrid(getDirectFieldReference()->grid_); 
     1704    else grid_->completeGrid(); 
     1705  } 
     1706  CATCH_DUMP_ATTR 
     1707 
     1708  void CField::solveGridDomainAxisBaseRef() 
     1709  TRY 
     1710  { 
     1711    grid_->solveDomainAxisRef(false); 
     1712    grid_->solveDomainAxisBaseRef(); 
     1713  } 
     1714  CATCH_DUMP_ATTR 
     1715 
     1716  ///------------------------------------------------------------------- 
     1717 
     1718  template <> 
     1719  void CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void) 
     1720  TRY 
     1721  { 
     1722    if (this->group_ref.isEmpty()) return; 
     1723    StdString gref = this->group_ref.getValue(); 
     1724 
     1725    if (!CFieldGroup::has(gref)) 
     1726      ERROR("CGroupTemplate<CField, CFieldGroup, CFieldAttributes>::solveRefInheritance(void)", 
     1727         << "[ gref = " << gref << "]" 
     1728         << " invalid group name !"); 
     1729 
     1730    CFieldGroup* group = CFieldGroup::get(gref); 
     1731    CFieldGroup* owner = CFieldGroup::get(boost::polymorphic_downcast<CFieldGroup*>(this)); 
     1732    owner->setAttributes(group); // inherite of attributes of group reference 
    15881733       
    1589       std::vector<CField*> allChildren  = group->getAllChildren(); 
    1590       std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 
    1591  
    1592       for (; it != end; it++) 
    1593       { 
    1594          CField* child = *it; 
    1595          if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 
    1596  
    1597       } 
    1598    } 
    1599    CATCH_DUMP_ATTR 
    1600  
    1601    void CField::scaleFactorAddOffset(double scaleFactor, double addOffset) 
    1602    TRY 
    1603    { 
    1604      recvDataSrv = (recvDataSrv - addOffset) / scaleFactor; 
    1605    } 
    1606    CATCH_DUMP_ATTR 
    1607  
    1608    void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 
    1609    TRY 
    1610    { 
    1611      recvDataSrv = recvDataSrv * scaleFactor + addOffset; 
    1612    } 
    1613    CATCH_DUMP_ATTR 
    1614  
    1615    void CField::outputField(CArray<double,1>& fieldOut) 
    1616    TRY 
    1617    {  
    1618       CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 
    1619       CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 
    1620       for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
    1621       { 
    1622         fieldOut(outIndexServer(idx)) = recvDataSrv(outIndexClient(idx)); 
    1623       } 
    1624    } 
    1625    CATCH_DUMP_ATTR 
    1626  
    1627    void CField::inputField(CArray<double,1>& fieldIn) 
    1628    TRY 
    1629    { 
    1630       CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 
    1631       CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 
    1632       for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
    1633       { 
    1634         recvDataSrv(outIndexClient(idx)) = fieldIn(outIndexServer(idx)); 
    1635       } 
    1636    } 
    1637    CATCH_DUMP_ATTR 
    1638  
    1639    void CField::outputCompressedField(CArray<double,1>& fieldOut) 
    1640    TRY 
    1641    { 
    1642       CArray<size_t,1>& outIndexClient = grid->localIndexToWriteOnClient_; 
    1643       CArray<size_t,1>& outIndexServer = grid->localIndexToWriteOnServer_; 
    1644       for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
    1645       { 
    1646         fieldOut((idx)) = recvDataSrv(outIndexClient(idx)); 
    1647       } 
    1648    } 
    1649    CATCH_DUMP_ATTR 
    1650  
    1651    ///------------------------------------------------------------------- 
    1652  
    1653    void CField::parse(xml::CXMLNode& node) 
    1654    TRY 
    1655    { 
    1656       string newContent ; 
    1657       SuperClass::parse(node); 
    1658       if (node.goToChildElement()) 
    1659       { 
    1660         do 
    1661         { 
    1662           if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 
    1663           else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 
    1664         } while (node.goToNextElement()); 
    1665         node.goToParentElement(); 
    1666       } 
    1667       if (node.getContent(newContent)) content=newContent ; 
    1668     } 
    1669    CATCH_DUMP_ATTR 
    1670  
    1671    /*! 
    1672      This function retrieves Id of corresponding domain_ref and axis_ref (if any) 
     1734    std::vector<CField*> allChildren  = group->getAllChildren(); 
     1735    std::vector<CField*>::iterator it = allChildren.begin(), end = allChildren.end(); 
     1736 
     1737    for (; it != end; it++) 
     1738    { 
     1739      CField* child = *it; 
     1740     if (child->hasId()) owner->createChild()->field_ref.setValue(child->getId()); 
     1741    } 
     1742  } 
     1743  CATCH_DUMP_ATTR 
     1744 
     1745  void CField::scaleFactorAddOffset(double scaleFactor, double addOffset) 
     1746  TRY 
     1747  { 
     1748    recvDataSrv = (recvDataSrv - addOffset) / scaleFactor; 
     1749  } 
     1750  CATCH_DUMP_ATTR 
     1751 
     1752  void CField::invertScaleFactorAddOffset(double scaleFactor, double addOffset) 
     1753  TRY 
     1754  { 
     1755    recvDataSrv = recvDataSrv * scaleFactor + addOffset; 
     1756  } 
     1757  CATCH_DUMP_ATTR 
     1758 
     1759  void CField::outputField(CArray<double,1>& fieldOut) 
     1760  TRY 
     1761  {  
     1762    CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 
     1763    CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 
     1764    for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
     1765    { 
     1766      fieldOut(outIndexServer(idx)) = recvDataSrv(outIndexClient(idx)); 
     1767    } 
     1768  } 
     1769  CATCH_DUMP_ATTR 
     1770 
     1771  void CField::inputField(CArray<double,1>& fieldIn) 
     1772  TRY 
     1773  { 
     1774    CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 
     1775    CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 
     1776    for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
     1777    { 
     1778      recvDataSrv(outIndexClient(idx)) = fieldIn(outIndexServer(idx)); 
     1779    } 
     1780  } 
     1781  CATCH_DUMP_ATTR 
     1782 
     1783 void CField::outputCompressedField(CArray<double,1>& fieldOut) 
     1784 TRY 
     1785 { 
     1786    CArray<size_t,1>& outIndexClient = grid_->localIndexToWriteOnClient_; 
     1787    CArray<size_t,1>& outIndexServer = grid_->localIndexToWriteOnServer_; 
     1788    for (size_t idx = 0; idx < outIndexServer.numElements(); ++idx) 
     1789    { 
     1790      fieldOut((idx)) = recvDataSrv(outIndexClient(idx)); 
     1791    } 
     1792  } 
     1793  CATCH_DUMP_ATTR 
     1794 
     1795  ///------------------------------------------------------------------- 
     1796 
     1797  void CField::parse(xml::CXMLNode& node) 
     1798  TRY 
     1799  { 
     1800    string newContent ; 
     1801    SuperClass::parse(node); 
     1802    if (node.goToChildElement()) 
     1803    { 
     1804      do 
     1805      { 
     1806        if (node.getElementName() == "variable" || node.getElementName() == "variable_group") this->getVirtualVariableGroup()->parseChild(node); 
     1807        else if (node.getElementName() == "expr") if (node.getContent(newContent)) content+=newContent ; 
     1808      } while (node.goToNextElement()); 
     1809      node.goToParentElement(); 
     1810    } 
     1811    if (node.getContent(newContent)) content=newContent ; 
     1812  } 
     1813  CATCH_DUMP_ATTR 
     1814 
     1815 /*! 
     1816   This function retrieves Id of corresponding domain_ref and axis_ref (if any) 
    16731817   of a field. In some cases, only domain exists but axis doesn't 
    16741818   \return pair of Domain and Axis id 
     1819  */ 
     1820  const std::vector<StdString>& CField::getRefDomainAxisIds() 
     1821  TRY 
     1822  { 
     1823    CGrid* cgPtr = getRelGrid(); 
     1824    if (NULL != cgPtr) 
     1825    { 
     1826      std::vector<StdString>::iterator it; 
     1827      if (!domain_ref.isEmpty()) 
     1828      { 
     1829        std::vector<StdString> domainList = cgPtr->getDomainList(); 
     1830        it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue()); 
     1831        if (domainList.end() != it) domAxisScalarIds_[0] = *it; 
     1832      } 
     1833 
     1834      if (!axis_ref.isEmpty()) 
     1835      { 
     1836        std::vector<StdString> axisList = cgPtr->getAxisList(); 
     1837        it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue()); 
     1838        if (axisList.end() != it) domAxisScalarIds_[1] = *it; 
     1839      } 
     1840 
     1841      if (!scalar_ref.isEmpty()) 
     1842      { 
     1843        std::vector<StdString> scalarList = cgPtr->getScalarList(); 
     1844        it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue()); 
     1845        if (scalarList.end() != it) domAxisScalarIds_[2] = *it; 
     1846      } 
     1847    } 
     1848    return (domAxisScalarIds_); 
     1849  } 
     1850  CATCH_DUMP_ATTR 
     1851 
     1852  CVariable* CField::addVariable(const string& id) 
     1853  TRY 
     1854  { 
     1855    return vVariableGroup->createChild(id); 
     1856  } 
     1857  CATCH 
     1858 
     1859  CVariableGroup* CField::addVariableGroup(const string& id) 
     1860  TRY 
     1861  { 
     1862    return vVariableGroup->createChildGroup(id); 
     1863  } 
     1864  CATCH 
     1865 
     1866  void CField::setContextClient(CContextClient* contextClient) 
     1867  TRY 
     1868  { 
     1869    CContext* context = CContext::getCurrent(); 
     1870    client = contextClient; 
     1871   
     1872    // A grid is sent by a client (both for read or write) or by primary server (write only) 
     1873    if (context->getServiceType()==CServicesManager::GATHERER) 
     1874    { 
     1875      if (file->mode.isEmpty() || (!file->mode.isEmpty() && file->mode == CFile::mode_attr::write)) 
     1876        grid_->setContextClient(contextClient); 
     1877    } 
     1878    else if (context->getServiceType()==CServicesManager::CLIENT) 
     1879      grid_->setContextClient(contextClient); 
     1880  } 
     1881  CATCH_DUMP_ATTR 
     1882 
     1883  CContextClient* CField::getContextClient() 
     1884  TRY 
     1885  { 
     1886    return client; 
     1887  } 
     1888  CATCH 
     1889 
     1890  void CField::sendAddAllVariables(CContextClient* client) 
     1891  TRY 
     1892  { 
     1893    std::vector<CVariable*> allVar = getAllVariables(); 
     1894    std::vector<CVariable*>::const_iterator it = allVar.begin(); 
     1895    std::vector<CVariable*>::const_iterator itE = allVar.end(); 
     1896 
     1897    for (; it != itE; ++it) 
     1898    { 
     1899      this->sendAddVariable((*it)->getId(), client); 
     1900      (*it)->sendAllAttributesToServer(client); 
     1901      (*it)->sendValue(client); 
     1902    } 
     1903  } 
     1904  CATCH_DUMP_ATTR 
     1905 
     1906  /*! 
     1907   * Send all Attributes to server. This method is overloaded, since only grid_ref attribute 
     1908   * must be sent to server and not domain_ref/axis_ref/scalar_ref.  
    16751909   */ 
    1676    const std::vector<StdString>& CField::getRefDomainAxisIds() 
    1677    TRY 
    1678    { 
    1679      CGrid* cgPtr = getRelGrid(); 
    1680      if (NULL != cgPtr) 
    1681      { 
    1682        std::vector<StdString>::iterator it; 
    1683        if (!domain_ref.isEmpty()) 
    1684        { 
    1685          std::vector<StdString> domainList = cgPtr->getDomainList(); 
    1686          it = std::find(domainList.begin(), domainList.end(), domain_ref.getValue()); 
    1687          if (domainList.end() != it) domAxisScalarIds_[0] = *it; 
    1688        } 
    1689  
    1690        if (!axis_ref.isEmpty()) 
    1691        { 
    1692          std::vector<StdString> axisList = cgPtr->getAxisList(); 
    1693          it = std::find(axisList.begin(), axisList.end(), axis_ref.getValue()); 
    1694          if (axisList.end() != it) domAxisScalarIds_[1] = *it; 
    1695        } 
    1696  
    1697        if (!scalar_ref.isEmpty()) 
    1698        { 
    1699          std::vector<StdString> scalarList = cgPtr->getScalarList(); 
    1700          it = std::find(scalarList.begin(), scalarList.end(), scalar_ref.getValue()); 
    1701          if (scalarList.end() != it) domAxisScalarIds_[2] = *it; 
    1702        } 
    1703      } 
    1704      return (domAxisScalarIds_); 
    1705    } 
    1706    CATCH_DUMP_ATTR 
    1707  
    1708    CVariable* CField::addVariable(const string& id) 
    1709    TRY 
    1710    { 
    1711      return vVariableGroup->createChild(id); 
    1712    } 
    1713    CATCH 
    1714  
    1715    CVariableGroup* CField::addVariableGroup(const string& id) 
    1716    TRY 
    1717    { 
    1718      return vVariableGroup->createChildGroup(id); 
    1719    } 
    1720    CATCH 
    1721  
    1722    void CField::setContextClient(CContextClient* contextClient) 
    1723    TRY 
    1724    { 
    1725      CContext* context = CContext::getCurrent(); 
    1726      client = contextClient; 
    1727    
    1728      // A grid is sent by a client (both for read or write) or by primary server (write only) 
    1729      if (context->getServiceType()==CServicesManager::GATHERER) 
    1730      { 
    1731        if (file->mode.isEmpty() || (!file->mode.isEmpty() && file->mode == CFile::mode_attr::write)) 
    1732          grid->setContextClient(contextClient); 
    1733      } 
    1734      else if (context->getServiceType()==CServicesManager::CLIENT) 
    1735        grid->setContextClient(contextClient); 
    1736    } 
    1737    CATCH_DUMP_ATTR 
    1738  
    1739    CContextClient* CField::getContextClient() 
    1740    TRY 
    1741    { 
    1742      return client; 
    1743    } 
    1744    CATCH 
    1745  
    1746    void CField::sendAddAllVariables(CContextClient* client) 
    1747    TRY 
    1748    { 
    1749      std::vector<CVariable*> allVar = getAllVariables(); 
    1750      std::vector<CVariable*>::const_iterator it = allVar.begin(); 
    1751      std::vector<CVariable*>::const_iterator itE = allVar.end(); 
    1752  
    1753      for (; it != itE; ++it) 
    1754      { 
    1755        this->sendAddVariable((*it)->getId(), client); 
    1756        (*it)->sendAllAttributesToServer(client); 
    1757        (*it)->sendValue(client); 
    1758      } 
    1759    } 
    1760    CATCH_DUMP_ATTR 
    1761  
    1762    /*! 
    1763     * Send all Attributes to server. This method is overloaded, since only grid_ref attribute 
    1764     * must be sent to server and not domain_ref/axis_ref/scalar_ref.  
    1765     */ 
    17661910     
    1767    void CField::sendAllAttributesToServer(CContextClient* client) 
    1768    TRY 
    1769    { 
    1770      if (grid_ref.isEmpty()) 
    1771      { 
    1772        grid_ref=grid->getId() ; 
    1773        SuperClass::sendAllAttributesToServer(client) ; 
    1774        grid_ref.reset(); 
    1775      } 
    1776      else SuperClass::sendAllAttributesToServer(client) ; 
    1777    } 
    1778    CATCH_DUMP_ATTR 
     1911  void CField::sendAllAttributesToServer(CContextClient* client) 
     1912  TRY 
     1913  { 
     1914    if (grid_ref.isEmpty()) 
     1915    { 
     1916      grid_ref=grid_->getId() ; 
     1917      SuperClass::sendAllAttributesToServer(client) ; 
     1918      grid_ref.reset(); 
     1919    } 
     1920    else SuperClass::sendAllAttributesToServer(client) ; 
     1921  } 
     1922  CATCH_DUMP_ATTR 
    17791923     
    1780    void CField::sendAddVariable(const string& id, CContextClient* client) 
    1781    TRY 
    1782    { 
    1783       sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 
    1784    } 
    1785    CATCH_DUMP_ATTR 
    1786  
    1787    void CField::sendAddVariableGroup(const string& id, CContextClient* client) 
    1788    TRY 
    1789    { 
    1790       sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 
    1791    } 
    1792    CATCH_DUMP_ATTR 
    1793  
    1794    void CField::recvAddVariable(CEventServer& event) 
    1795    TRY 
    1796    { 
    1797  
    1798       CBufferIn* buffer = event.subEvents.begin()->buffer; 
    1799       string id; 
    1800       *buffer >> id; 
    1801       get(id)->recvAddVariable(*buffer); 
    1802    } 
    1803    CATCH 
    1804  
    1805    void CField::recvAddVariable(CBufferIn& buffer) 
    1806    TRY 
    1807    { 
    1808       string id; 
    1809       buffer >> id; 
    1810       addVariable(id); 
    1811    } 
    1812    CATCH_DUMP_ATTR 
    1813  
    1814    void CField::recvAddVariableGroup(CEventServer& event) 
    1815    TRY 
    1816    { 
    1817  
    1818       CBufferIn* buffer = event.subEvents.begin()->buffer; 
    1819       string id; 
    1820       *buffer >> id; 
    1821       get(id)->recvAddVariableGroup(*buffer); 
    1822    } 
    1823    CATCH 
    1824  
    1825    void CField::recvAddVariableGroup(CBufferIn& buffer) 
    1826    TRY 
    1827    { 
    1828       string id; 
    1829       buffer >> id; 
    1830       addVariableGroup(id); 
    1831    } 
    1832    CATCH_DUMP_ATTR 
    1833  
    1834    /*! 
    1835     * Check on freq_off and freq_op attributes. 
    1836     */ 
    1837    void CField::checkTimeAttributes(CDuration* freqOp) 
    1838    TRY 
    1839    { 
    1840      bool isFieldRead  = file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read; 
    1841      bool isFieldWrite = file && ( file->mode.isEmpty() ||  file->mode == CFile::mode_attr::write); 
    1842      if (isFieldRead && !(operation.getValue() == "instant" || operation.getValue() == "once") )      
    1843        ERROR("void CField::checkTimeAttributes(void)", 
    1844              << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 
    1845              << "Currently only \"instant\" is supported for fields read from file.") 
    1846  
    1847      if (freq_op.isEmpty()) 
    1848      { 
    1849        if (operation.getValue() == "instant") 
    1850        { 
    1851          if (isFieldRead || isFieldWrite) freq_op.setValue(file->output_freq.getValue()); 
    1852          else freq_op=*freqOp ; 
    1853        } 
    1854        else 
    1855          freq_op.setValue(TimeStep); 
    1856      } 
    1857      if (freq_offset.isEmpty()) 
    1858        freq_offset.setValue(isFieldRead ? NoneDu : (freq_op.getValue() - TimeStep)); 
    1859    } 
    1860    CATCH_DUMP_ATTR 
    1861  
    1862    /*! 
    1863     * Returns string arithmetic expression associated to the field. 
    1864     * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 
    1865     */ 
    1866    const string& CField::getExpression(void) 
    1867    TRY 
    1868    { 
    1869      if (!expr.isEmpty() && content.empty()) 
    1870      { 
    1871        content = expr; 
    1872        expr.reset(); 
    1873      } 
    1874  
    1875      return content; 
    1876    } 
    1877    CATCH_DUMP_ATTR 
    1878  
    1879    bool CField::hasExpression(void) const 
    1880    TRY 
    1881    { 
    1882      return (!expr.isEmpty() || !content.empty()); 
    1883    } 
    1884    CATCH 
    1885  
    1886    bool CField::hasGridMask(void) const 
    1887    TRY 
    1888    { 
    1889      return (this->grid->hasMask()); 
    1890    } 
    1891    CATCH 
    1892  
    1893    DEFINE_REF_FUNC(Field,field) 
     1924  void CField::sendAddVariable(const string& id, CContextClient* client) 
     1925  TRY 
     1926  { 
     1927    sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE, client); 
     1928  } 
     1929  CATCH_DUMP_ATTR 
     1930 
     1931  void CField::sendAddVariableGroup(const string& id, CContextClient* client) 
     1932  TRY 
     1933  { 
     1934    sendAddItem(id, (int)EVENT_ID_ADD_VARIABLE_GROUP, client); 
     1935  } 
     1936  CATCH_DUMP_ATTR 
     1937 
     1938  void CField::recvAddVariable(CEventServer& event) 
     1939  TRY 
     1940  { 
     1941    CBufferIn* buffer = event.subEvents.begin()->buffer; 
     1942    string id; 
     1943    *buffer >> id; 
     1944    get(id)->recvAddVariable(*buffer); 
     1945  } 
     1946  CATCH 
     1947 
     1948  void CField::recvAddVariable(CBufferIn& buffer) 
     1949  TRY 
     1950  { 
     1951    string id; 
     1952    buffer >> id; 
     1953    addVariable(id); 
     1954  } 
     1955  CATCH_DUMP_ATTR 
     1956 
     1957  void CField::recvAddVariableGroup(CEventServer& event) 
     1958  TRY 
     1959  { 
     1960    CBufferIn* buffer = event.subEvents.begin()->buffer; 
     1961    string id; 
     1962    *buffer >> id; 
     1963    get(id)->recvAddVariableGroup(*buffer); 
     1964  } 
     1965  CATCH 
     1966 
     1967  void CField::recvAddVariableGroup(CBufferIn& buffer) 
     1968  TRY 
     1969  { 
     1970    string id; 
     1971    buffer >> id; 
     1972    addVariableGroup(id); 
     1973  } 
     1974  CATCH_DUMP_ATTR 
     1975 
     1976  /*! 
     1977   * Check on freq_off and freq_op attributes. 
     1978   */ 
     1979  void CField::checkTimeAttributes(CDuration* freqOp) 
     1980  TRY 
     1981  { 
     1982    bool isFieldRead  = file && !file->mode.isEmpty() && file->mode == CFile::mode_attr::read; 
     1983    bool isFieldWrite = file && ( file->mode.isEmpty() ||  file->mode == CFile::mode_attr::write); 
     1984    if (isFieldRead && !(operation.getValue() == "instant" || operation.getValue() == "once") )      
     1985      ERROR("void CField::checkTimeAttributes(void)", 
     1986         << "Unsupported operation for field '" << getFieldOutputName() << "'." << std::endl 
     1987         << "Currently only \"instant\" is supported for fields read from file.") 
     1988 
     1989    if (freq_op.isEmpty()) 
     1990    { 
     1991      if (operation.getValue() == "instant") 
     1992      { 
     1993        if (isFieldRead || isFieldWrite) freq_op.setValue(file->output_freq.getValue()); 
     1994        else freq_op=*freqOp ; 
     1995      } 
     1996      else freq_op.setValue(TimeStep); 
     1997    } 
     1998    if (freq_offset.isEmpty()) freq_offset.setValue(isFieldRead ? NoneDu : (freq_op.getValue() - TimeStep)); 
     1999  } 
     2000  CATCH_DUMP_ATTR 
     2001 
     2002  /*! 
     2003   * Returns string arithmetic expression associated to the field. 
     2004   * \return if content is defined return content string, otherwise, if "expr" attribute is defined, return expr string. 
     2005   */ 
     2006  const string& CField::getExpression(void) 
     2007  TRY 
     2008  { 
     2009    if (!expr.isEmpty() && content.empty()) 
     2010    { 
     2011      content = expr; 
     2012      expr.reset(); 
     2013    } 
     2014 
     2015    return content; 
     2016  } 
     2017  CATCH_DUMP_ATTR 
     2018 
     2019  bool CField::hasExpression(void) const 
     2020  TRY 
     2021  { 
     2022    return (!expr.isEmpty() || !content.empty()); 
     2023  } 
     2024  CATCH 
     2025 
     2026  bool CField::hasGridMask(void) const 
     2027  TRY 
     2028  { 
     2029    return (this->grid_->hasMask()); 
     2030  } 
     2031  CATCH 
     2032 
     2033  DEFINE_REF_FUNC(Field,field) 
    18942034} // namespace xios 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.hpp

    r1853 r1869  
    1717#include "variable.hpp" 
    1818#include "context_client.hpp" 
     19#include "pass_through_filter.hpp" 
     20#include "temporal_filter.hpp" 
     21 
    1922 
    2023 
     
    2831 
    2932   class CFile; 
     33   class CCouplerIn ; 
     34   class CCouplerOut ; 
    3035   class CGrid; 
    3136   class CContext; 
     
    4752 
    4853   class CContextClient ; 
     54 
    4955   ///-------------------------------------------------------------- 
    5056   class CField 
     
    141147 
    142148         void buildFilterGraph(CGarbageCollector& gc, bool enableOutput); 
     149 
     150         bool buildWorkflowGraph(CGarbageCollector& gc) ; 
     151         bool buildWorkflowGraphDone_ = false ; 
     152 
    143153         size_t getGlobalWrittenSize(void) ; 
    144154          
     
    211221 
    212222        bool hasGridMask(void) const; 
     223        CGrid* getGrid(void) { return grid_; }  
     224 
     225        void connectToFileServer(CGarbageCollector& gc) ; 
     226        void computeGridIndexToFileServer(void) ; 
     227      private: 
     228        std::vector<CGrid*> getGridPath(void) ; 
    213229 
    214230      public: 
     
    216232         CVariableGroup* vVariableGroup; 
    217233 
    218          CGrid*  grid; 
     234         CGrid*  grid_=nullptr; 
    219235         CFile*  file; 
     236          
     237         CFile* fileIn_ = nullptr ; //<! pointer to input related file 
     238         bool hasFileIn(void) { fileIn_==nullptr ? false : true ;} 
     239         CFile* getFileIn(void) {return fileIn_;} 
     240         void setFileIn(CFile* fileIn) { fileIn_ = fileIn ;} 
     241         void unsetFileIn(void) { fileIn_ = nullptr ;} 
     242 
     243         CFile* fileOut_ = nullptr ; //<! pointer to output related file 
     244         bool hasFileOut(void) { fileOut_==nullptr ? false : true ;} 
     245         CFile* getFileOut(void) {return fileOut_;} 
     246         void setFileOut(CFile* fileOut) { fileOut_ = fileOut ;} 
     247         void unsetFileOut(void) { fileOut_ = nullptr ;} 
     248 
     249         CCouplerIn* couplerIn_ = nullptr ; //<!pointer to input related coupler 
     250         bool hasCouplerIn(void) { couplerIn_==nullptr ? false : true ;} 
     251         CCouplerIn* getCouplerIn(void) {return couplerIn_;} 
     252         void setCouplerIn(CCouplerIn* couplerIn) { couplerIn_ = couplerIn ;} 
     253         void unsetCouplerIn(void) { couplerIn_ = nullptr ;} 
     254 
     255         CCouplerOut* couplerOut_ = nullptr ; //<!pointer to output related coupler 
     256         bool hasCouplerOut(void) { couplerOut_==nullptr ? false : true ;} 
     257         CCouplerOut* getCouplerOut(void) {return couplerOut_;} 
     258         void setCouplerOut(CCouplerOut* couplerOut) { couplerOut_ = couplerOut ;} 
     259         void unsetCouplerOut(void) { couplerOut_ = nullptr ;} 
     260 
     261         bool modelIn_ = false ; //<! field can be received from model == true  
     262         bool getModelIn(void) { return modelIn_ ;} 
     263         void setModelIn(void) { modelIn_ = true ;} 
     264         void unsetModelIn(void) { modelIn_ = false ;} 
     265          
     266         bool modelOut_ = false ; //<! field can be retrieve to model == true 
     267         bool getModelOut(void) { return modelOut_ ;} 
     268         void setModelOut(void) { modelOut_ = true ;} 
     269         void unsetModelOut(void) { modelOut_ = false ;} 
    220270 
    221271         CDuration freq_operation_srv, freq_write_srv; 
     
    246296 
    247297         DECLARE_REF_FUNC(Field,field) 
    248  
     298         
    249299      private: 
    250300         CContextClient* client; 
     
    256306         bool nstepMaxRead; 
    257307 
     308       private:  
     309         //! define if the field is part of the active workflow. It will be tagged to true when CField::buildWorkflowGraph is successfull  
     310         bool workflowEnabled_ = false ; 
     311       public:  
     312         /*! workflowEnabled_ public accessor 
     313          * \return Value of workflowEnabled_ */ 
     314         bool getWorkflowEnabled(void) { return  workflowEnabled_; } 
     315  
     316 
    258317      private: 
     318      
    259319         //! The type of operation attached to the field 
    260320         func::CFunctor::ETimeType operationTimeType; 
    261321 
     322         //! The output pin of the input filter of the field 
     323         std::shared_ptr<CPassThroughFilter> inputFilter; 
     324 
     325         //! The self temporal data filter 
     326         std::shared_ptr<CTemporalFilter> selfTemporalDataFilter ; 
     327          
    262328         //! The output pin of the filter providing the instant data for the field 
    263329         std::shared_ptr<COutputPin> instantDataFilter; 
     330          
    264331         //! The output pin of the filters providing the result of the field's temporal operation 
    265332         std::map<CDuration, std::shared_ptr<COutputPin>, DurationFakeLessComparator> temporalDataFilters; 
     333          
    266334         //! The output pin of the filter providing the instant data for self references 
    267          std::shared_ptr<COutputPin> selfReferenceFilter; 
     335         std::shared_ptr<COutputPin> selfReferenceFilter; // probably redondant with inputFilter 
     336 
    268337         //! The source filter for data provided by the client 
    269338         std::shared_ptr<CSourceFilter> clientSourceFilter; 
     339          
    270340         //! The source filter for data provided by the server 
    271341         std::shared_ptr<CSourceFilter> serverSourceFilter; 
     342          
    272343         //! The terminal filter which stores the instant data 
    273344         std::shared_ptr<CStoreFilter> storeFilter; 
     345         
    274346         //! The terminal filter which writes the data to file 
    275347         std::shared_ptr<CFileWriterFilter> fileWriterFilter; 
     348         
    276349         //! The terminal filter which writes data to file 
    277350         std::shared_ptr<CFileServerWriterFilter> fileServerWriterFilter; 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/file.cpp

    r1853 r1869  
    145145   TRY 
    146146   { 
    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; 
    152150      std::vector<CField*>::iterator it; 
    153151      this->enabledFields = this->getAllFields(); 
     
    176174 
    177175         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)); 
    180176      } 
    181177      enabledFields = newEnabledFields; 
     
    256252      { 
    257253         CField* field = *it;          
    258          std::vector<CAxis*> vecAxis = field->grid->getAxis(); 
     254         std::vector<CAxis*> vecAxis = field->getGrid()->getAxis(); 
    259255         for (size_t i = 0; i < vecAxis.size(); ++i) 
    260256           setAxis.insert(vecAxis[i]->getAxisOutputName()); 
    261          std::vector<CDomain*> vecDomains = field->grid->getDomains(); 
     257         std::vector<CDomain*> vecDomains = field->getGrid()->getDomains(); 
    262258         for (size_t i = 0; i < vecDomains.size(); ++i) 
    263259           setDomains.insert(vecDomains[i]->getDomainOutputName()); 
     
    300296      { 
    301297         CField* field = *it; 
    302          bool nullGrid = (0 == field->grid); 
    303          allZoneEmpty &= nullGrid ? false : !field->grid->doGridHaveDataToWrite(); 
     298         bool nullGrid = (nullptr == field->getGrid()); 
     299         allZoneEmpty &= nullGrid ? false : !field->getGrid()->doGridHaveDataToWrite(); 
    304300      } 
    305301 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp

    r1853 r1869  
    9090   //--------------------------------------------------------------- 
    9191 
    92    StdSize CGrid::getDataSize(void) const 
     92   StdSize CGrid::getDataSize(void)  
    9393   TRY 
    9494   { 
     
    9696     if (!isScalarGrid()) 
    9797     { 
    98        std::vector<int> dataNindex = clientDistribution_->getDataNIndex(); 
     98       std::vector<int> dataNindex = getDistributionClient()->getDataNIndex(); 
    9999       for (int i = 0; i < dataNindex.size(); ++i) retvalue *= dataNindex[i];        
    100100     } 
     
    634634 
    635635      size_t nbWritten = 0, indGlo; 
    636       CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient(); 
     636      CDistributionClient::GlobalLocalDataMap& globalDataIndex = getDistributionClient()->getGlobalDataIndexOnClient(); 
    637637      CDistributionClient::GlobalLocalDataMap::const_iterator itb = globalDataIndex.begin(), 
    638638                                                              ite = globalDataIndex.end(), it;     
     
    677677   CATCH_DUMP_ATTR 
    678678 
     679    
     680 
     681   /*! 
     682     Compute the global index of grid to send to server as well as the connected server of the current client. 
     683     First of all, from the local data on each element of grid, we can calculate their local index which also allows us to know 
     684     their global index. We can have a map of global index of grid and local index that each client holds 
     685     Then, each client holds a piece of information about the distribution of servers, which permits to compute the connected server(s) 
     686     of the current client. 
     687   */ 
     688   void CGrid::computeGridIndexToFileServer(CContextClient* client) 
     689   { 
     690     if (isScalarGrid()) 
     691     { 
     692       computeClientIndexScalarGrid(); 
     693       computeConnectedClientsScalarGrid(client); 
     694     } 
     695     else 
     696     { 
     697       computeClientIndex(); 
     698       computeConnectedClients(client); 
     699     } 
     700 
     701     // compute indices for client/server transfer for domain 
     702     for (const auto& domainId : domList_) CDomain::get(domainId)->computeConnectedClients(client); 
     703    
     704    
     705     // compute indices for client/server transfer for axis 
     706     std::vector<CAxis*> axisList = this->getAxis(); 
     707     std::vector<int> axisPosInGrid ; 
     708     // compute axis position in grid      
     709     int idx=0 ; 
     710     for (int i = 0 ; i < axis_domain_order.numElements(); ++i) 
     711     { 
     712       if (axis_domain_order(i) == 0)  idx += 0 ; 
     713       else if (axis_domain_order(i) == 1) { axisPosInGrid.push_back(idx) ; ++idx; } 
     714       else if (axis_domain_order(i) == 2) idx += 2; 
     715     } 
     716     for(int i=0 ; i<axisList.size(); i++) axisList[i] -> computeConnectedClients(client, getGlobalDimension(),axisPositionInGrid_[i]) ; 
     717   } 
    679718   //--------------------------------------------------------------- 
     719 
     720    
     721   void CGrid::computeClientDistribution(void) 
     722   { 
     723     if (computeClientDistribution_done_) return ; 
     724     else computeClientDistribution_done_ = true ; 
     725 
     726     CContext* context = CContext::getCurrent(); 
     727     int rank = context-> getIntraCommRank(); 
     728     clientDistribution_ = new CDistributionClient(rank, this); 
     729   } 
     730 
     731   void CGrid::computeStoreIndex_client(void) 
     732   { 
     733     if (computeStoreIndex_client_done_) return ; 
     734     else computeStoreIndex_client_done_ = true ; 
     735     if (isScalarGrid()) 
     736     { 
     737       storeIndex_client_.resize(1); 
     738       storeIndex_client_(0) = 0; 
     739     } 
     740     else 
     741     { 
     742       CDistributionClient* clientDistribution = getDistributionClient() ; 
     743       const std::vector<int>& localDataIndex = clientDistribution->getLocalDataIndexOnClient() ; 
     744       int nbStoreIndex = localDataIndex.size() ; 
     745       storeIndex_client_.resize(nbStoreIndex); 
     746       for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = localDataIndex[idx]; 
     747     } 
     748   } 
     749 
     750   void CGrid::computeStoreMask_client(void) 
     751   { 
     752     if (computeStoreMask_client_done_) return ; 
     753     else computeStoreMask_client_done_ = true ; 
     754     if (isScalarGrid()) 
     755     { 
     756       storeMask_client_.resize(1); 
     757       storeMask_client_(0) = true; 
     758     } 
     759     else 
     760     { 
     761       CDistributionClient* clientDistribution = getDistributionClient() ; 
     762       const std::vector<bool>& localMaskIndex = clientDistribution->getLocalMaskIndexOnClient() ; 
     763       int nbMaskIndex = localMaskIndex.size() ; 
     764       storeMask_client_.resize(nbMaskIndex); 
     765       for (int idx = 0; idx < nbMaskIndex; ++idx) storeMask_client_(idx) = localMaskIndex[idx]; 
     766     } 
     767   } 
    680768 
    681769   /* 
     
    688776   TRY 
    689777   { 
     778     if (computeClientIndex_done_) return ; 
     779 
    690780     CContext* context = CContext::getCurrent(); 
    691  
    692      CContextClient* client = context->client; 
    693      int rank = client->clientRank; 
    694  
    695      clientDistribution_ = new CDistributionClient(rank, this); 
     781     int rank = context-> getIntraCommRank(); 
     782 
     783     auto clientDistribution = getDistributionClient(); 
    696784     // Get local data index on client 
    697      int nbStoreIndex = clientDistribution_->getLocalDataIndexOnClient().size(); 
    698      int nbStoreGridMask = clientDistribution_->getLocalMaskIndexOnClient().size(); 
     785     int nbStoreIndex = clientDistribution->getLocalDataIndexOnClient().size(); 
     786     int nbStoreGridMask = clientDistribution->getLocalMaskIndexOnClient().size(); 
    699787     // nbStoreGridMask = nbStoreIndex if grid mask is defined, and 0 otherwise 
    700788     storeIndex_client_.resize(nbStoreIndex); 
    701789     storeMask_client_.resize(nbStoreGridMask); 
    702      for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx]; 
    703      for (int idx = 0; idx < nbStoreGridMask; ++idx) storeMask_client_(idx) = (clientDistribution_->getLocalMaskIndexOnClient())[idx]; 
    704  
    705      if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed(); 
     790     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client_(idx) = (clientDistribution->getLocalDataIndexOnClient())[idx]; 
     791     for (int idx = 0; idx < nbStoreGridMask; ++idx) storeMask_client_(idx) = (clientDistribution->getLocalMaskIndexOnClient())[idx]; 
     792 
     793     if (0 == serverDistribution_) isDataDistributed_= clientDistribution->isDataDistributed(); 
    706794     else 
    707795     { 
    708796        // Mapping global index received from clients to the storeIndex_client_ 
    709         CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient(); 
     797        CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution->getGlobalDataIndexOnClient(); 
    710798        CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end(); 
    711799        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient_.begin(), 
     
    746834        } 
    747835      } 
     836      computeClientIndex_done_ = true ; 
    748837   } 
    749838   CATCH_DUMP_ATTR 
     
    752841     Compute connected receivers and indexes to be sent to these receivers. 
    753842   */ 
    754    void CGrid::computeConnectedClients() 
    755    TRY 
    756    { 
     843   void CGrid::computeConnectedClients(CContextClient* client) 
     844   TRY 
     845   { 
     846     if (computeConnectedClients_done_.count(client)!=0) return ; 
     847 
    757848     CContext* context = CContext::getCurrent(); 
    758849      
    759850     set<int> listReceiverSize ; 
    760      for (auto it=clients.begin(); it!=clients.end(); ++it) 
     851     int receiverSize = client->serverSize; 
     852       
     853     if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 
    761854     { 
    762         
    763        CContextClient* client = *it ; 
    764  
    765        int receiverSize = client->serverSize; 
    766        
    767        if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 
     855       listReceiverSize.insert(receiverSize) ; 
     856       if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 
    768857       { 
    769          listReceiverSize.insert(receiverSize) ; 
    770          if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 
    771          { 
    772             // delete corresponding map in case of recompute, probably because a grid could has been modifiedd  
    773             // by a transformation 
    774             connectedServerRank_.erase(receiverSize); 
    775             connectedDataSize_.erase(receiverSize); 
    776             globalIndexOnServer_.erase(receiverSize); 
    777             nbSenders_.erase(receiverSize); 
    778          } 
    779  
    780          if (!doGridHaveDataDistributed(client)) 
    781          { 
    782             if (client->isServerLeader()) 
     858          // delete corresponding map in case of recompute, probably because a grid could has been modifiedd  
     859          // by a transformation 
     860          connectedServerRank_.erase(receiverSize); 
     861          connectedDataSize_.erase(receiverSize); 
     862          globalIndexOnServer_.erase(receiverSize); 
     863          nbSenders_.erase(receiverSize); 
     864       } 
     865 
     866       if (!doGridHaveDataDistributed(client)) 
     867       { 
     868          if (client->isServerLeader()) 
     869          { 
     870            size_t ssize = getDistributionClient()->getLocalDataIndexOnClient().size(); 
     871            const std::list<int>& ranks = client->getRanksServerLeader(); 
     872            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    783873            { 
    784               size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size(); 
    785               const std::list<int>& ranks = client->getRanksServerLeader(); 
    786               for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    787               { 
    788                 connectedServerRank_[receiverSize].push_back(*itRank); 
    789                 connectedDataSize_[receiverSize][*itRank] = ssize; 
    790               } 
     874              connectedServerRank_[receiverSize].push_back(*itRank); 
     875              connectedDataSize_[receiverSize][*itRank] = ssize; 
    791876            } 
    792             return; 
    793          } 
    794  
    795          // Compute mapping between client and server 
    796          std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 
    797          CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 
    798          std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 
     877          } 
     878          return; 
     879       } 
     880 
     881       // Compute mapping between client and server 
     882       std::vector<std::unordered_map<size_t,std::vector<int> > > indexServerOnElement; 
     883       CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize); 
     884       std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement, 
    799885                                                                                                    client->clientRank, 
    800886                                                                                                    client->clientSize, 
     
    802888                                                                                                    getDistributedDimension()); 
    803889 
    804          // Even if servers have no index, they must received something from client 
    805          // We only use several client to send "empty" message to these servers 
    806          std::list<int> serverZeroIndexLeader; 
    807          std::list<int> serverZeroIndexNotLeader; 
    808          CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
    809          for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    810            *it = serverZeroIndex[*it]; 
    811  
    812          if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end()) 
    813            computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]); 
    814  
    815          const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer(); 
    816          CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap; 
    817          CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap; 
    818          itbGlobalMap = globalIndexOnServer_[receiverSize].begin(); 
    819          iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 
    820  
    821          for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 
     890       // Even if servers have no index, they must received something from client 
     891       // We only use several client to send "empty" message to these servers 
     892       std::list<int> serverZeroIndexLeader; 
     893       std::list<int> serverZeroIndexNotLeader; 
     894       CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader); 
     895       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     896         *it = serverZeroIndex[*it]; 
     897 
     898       if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end()) 
     899         computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]); 
     900 
     901       const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getDistributionClient()->getGlobalLocalDataSendToServer(); 
     902       CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap; 
     903       CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap; 
     904       itbGlobalMap = globalIndexOnServer_[receiverSize].begin(); 
     905       iteGlobalMap = globalIndexOnServer_[receiverSize].end(); 
     906 
     907       for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) 
     908       { 
     909         int serverRank = itGlobalMap->first; 
     910         int indexSize = itGlobalMap->second.size(); 
     911         const std::vector<size_t>& indexVec = itGlobalMap->second; 
     912         for (int idx = 0; idx < indexSize; ++idx) 
    822913         { 
    823            int serverRank = itGlobalMap->first; 
    824            int indexSize = itGlobalMap->second.size(); 
    825            const std::vector<size_t>& indexVec = itGlobalMap->second; 
    826            for (int idx = 0; idx < indexSize; ++idx) 
    827            { 
    828               itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]); 
    829               if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap) 
    830               { 
    831                 if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank)) 
    832                   connectedDataSize_[receiverSize][serverRank] = 1; 
    833                 else 
    834                   ++connectedDataSize_[receiverSize][serverRank]; 
    835               } 
    836            } 
     914            itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]); 
     915            if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap) 
     916            { 
     917              if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank)) 
     918                connectedDataSize_[receiverSize][serverRank] = 1; 
     919              else 
     920                ++connectedDataSize_[receiverSize][serverRank]; 
     921            } 
    837922         } 
    838  
    839          // Connected servers which really have index 
    840          for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) { 
    841            connectedServerRank_[receiverSize].push_back(itGlobalMap->first); 
    842          } 
    843  
    844          // Connected servers which have no index at all 
    845          for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
    846            connectedServerRank_[receiverSize].push_back(*it); 
    847  
    848          // Even if a client has no index, it must connect to at least one server and 
    849          // send an "empty" data to this server 
    850          if (connectedServerRank_[receiverSize].empty()) 
    851           connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize); 
    852  
    853          // Now check if all servers have data to receive. If not, master client will send empty data. 
    854          // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 
    855          std::vector<int> counts (client->clientSize); 
    856          std::vector<int> displs (client->clientSize); 
    857          displs[0] = 0; 
    858          int localCount = connectedServerRank_[receiverSize].size() ; 
    859          MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 
    860          for (int i = 0; i < client->clientSize-1; ++i) 
    861          { 
    862            displs[i+1] = displs[i] + counts[i]; 
    863          } 
    864          std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]); 
    865          MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 
    866  
    867          if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0)) 
    868          { 
    869            std::vector<bool> isSrvConnected (receiverSize, false); 
    870            for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 
    871            for (int i = 0; i < receiverSize; ++i) 
    872            { 
    873              if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i); 
    874            } 
    875          } 
    876  
    877          nbSenders_[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]); 
    878923       } 
     924 
     925       // Connected servers which really have index 
     926       for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)  
     927         connectedServerRank_[receiverSize].push_back(itGlobalMap->first); 
     928      
     929       // Connected servers which have no index at all 
     930       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it) 
     931         connectedServerRank_[receiverSize].push_back(*it); 
     932 
     933       // Even if a client has no index, it must connect to at least one server and 
     934       // send an "empty" data to this server 
     935       if (connectedServerRank_[receiverSize].empty()) 
     936         connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize); 
     937  
     938       // Now check if all servers have data to receive. If not, master client will send empty data. 
     939       // This ensures that all servers will participate in collective calls upon receiving even if they have no date to receive. 
     940       std::vector<int> counts (client->clientSize); 
     941       std::vector<int> displs (client->clientSize); 
     942       displs[0] = 0; 
     943       int localCount = connectedServerRank_[receiverSize].size() ; 
     944       MPI_Gather(&localCount, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, client->intraComm) ; 
     945       for (int i = 0; i < client->clientSize-1; ++i) displs[i+1] = displs[i] + counts[i]; 
     946       std::vector<int> allConnectedServers(displs[client->clientSize-1]+counts[client->clientSize-1]); 
     947       MPI_Gatherv(&(connectedServerRank_[receiverSize])[0], localCount, MPI_INT, &allConnectedServers[0], &counts[0], &displs[0], MPI_INT, 0, client->intraComm); 
     948 
     949       if ((allConnectedServers.size() != receiverSize) && (client->clientRank == 0)) 
     950       { 
     951         std::vector<bool> isSrvConnected (receiverSize, false); 
     952         for (int i = 0; i < allConnectedServers.size(); ++i) isSrvConnected[allConnectedServers[i]] = true; 
     953         for (int i = 0; i < receiverSize; ++i) if (!isSrvConnected[i]) connectedServerRank_[receiverSize].push_back(i); 
     954       } 
     955 
     956       nbSenders_[receiverSize] = CClientServerMapping::computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]); 
    879957     } 
     958     computeConnectedClients_done_.insert(client) ; 
    880959   } 
    881960   CATCH_DUMP_ATTR 
     
    888967     of the current client. 
    889968   */ 
     969   // ym obsolete : to be removed.... 
    890970   void CGrid::computeIndex(void) 
    891971   TRY 
    892972   { 
     973    // old interface 
    893974     CContext* context = CContext::getCurrent(); 
    894975     if (isScalarGrid()) 
     
    897978       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    898979       { 
    899          computeConnectedClientsScalarGrid(); 
     980         // ym computeConnectedClientsScalarGrid(); 
    900981       } 
    901982     } 
     
    905986       if (context->getServiceType()==CServicesManager::CLIENT || context->getServiceType()==CServicesManager::GATHERER) 
    906987       { 
    907          computeConnectedClients(); 
     988         //computeConnectedClients(); 
    908989       } 
    909990     } 
     
    11781259      } 
    11791260 
    1180       grid->solveDomainAxisRefInheritance(true); 
     1261 //     grid->solveElementsRefInheritance(true); 
    11811262 
    11821263      return grid; 
     
    13101391   //---------------------------------------------------------------- 
    13111392 
    1312    void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored) const 
    1313    TRY 
    1314    { 
    1315       const StdSize size = storeIndex_client_.numElements(); 
     1393   void CGrid::storeField_arr(const double* const data, CArray<double, 1>& stored)  
     1394   TRY 
     1395   { 
     1396      auto& storeIndex_client = getStoreIndex_client() ; 
     1397      const StdSize size = storeIndex_client.numElements(); 
    13161398 
    13171399      stored.resize(size); 
    1318       for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client_(i)]; 
     1400      for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 
    13191401   } 
    13201402   CATCH 
    13211403 
    1322    void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data) const 
    1323    TRY 
    1324    { 
    1325       const StdSize size = storeIndex_client_.numElements(); 
    1326  
    1327       for(StdSize i = 0; i < size; i++) data[storeIndex_client_(i)] = stored(i); 
     1404   void CGrid::restoreField_arr(const CArray<double, 1>& stored, double* const data)  
     1405   TRY 
     1406   { 
     1407      auto& storeIndex_client=getStoreIndex_client() ; 
     1408      const StdSize size = storeIndex_client.numElements(); 
     1409 
     1410      for(StdSize i = 0; i < size; i++) data[storeIndex_client(i)] = stored(i); 
    13281411   } 
    13291412   CATCH 
    13301413 
    1331    void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored) const 
    1332    { 
    1333       const StdSize size = storeIndex_client_.numElements(); 
     1414   void CGrid::maskField_arr(const double* const data, CArray<double, 1>& stored)  
     1415   { 
     1416      auto& storeIndex_client=getStoreIndex_client() ; 
     1417      auto& storeMask_client=getStoreMask_client() ; 
     1418         
     1419      const StdSize size = storeIndex_client.numElements(); 
    13341420      stored.resize(size); 
    13351421      const double nanValue = std::numeric_limits<double>::quiet_NaN(); 
    13361422 
    1337       if (storeMask_client_.numElements() != 0) 
    1338         for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client_(i)) ? data[storeIndex_client_(i)] : nanValue; 
     1423      if (storeMask_client.numElements() != 0) 
     1424        for(StdSize i = 0; i < size; i++) stored(i) = (storeMask_client(i)) ? data[storeIndex_client(i)] : nanValue; 
    13391425      else 
    1340         for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client_(i)]; 
    1341    } 
    1342  
    1343    void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out) const 
    1344    TRY 
    1345    { 
    1346       const std::vector<int>& localMaskedDataIndex = clientDistribution_->getLocalMaskedDataIndexOnClient(); 
     1426        for(StdSize i = 0; i < size; i++) stored(i) = data[storeIndex_client(i)]; 
     1427   } 
     1428 
     1429   void CGrid::uncompressField_arr(const double* const data, CArray<double, 1>& out)  
     1430   TRY 
     1431   { 
     1432      const std::vector<int>& localMaskedDataIndex = getDistributionClient()->getLocalMaskedDataIndexOnClient(); 
    13471433      const int size = localMaskedDataIndex.size(); 
    13481434      for(int i = 0; i < size; ++i) out(localMaskedDataIndex[i]) = data[i]; 
     
    13531439  TRY 
    13541440  { 
     1441    if (computeClientIndexScalarGrid_done_) return ; 
     1442 
    13551443    CContext* context = CContext::getCurrent();     
    13561444    { 
    13571445      int rank = context->intraCommRank_; 
    13581446 
    1359       clientDistribution_ = new CDistributionClient(rank, this); 
     1447      auto clientDistribution = getDistributionClient(); 
    13601448 
    13611449      storeIndex_client_.resize(1); 
     
    13821470      } 
    13831471    } 
    1384   } 
    1385   CATCH_DUMP_ATTR 
    1386  
    1387   void CGrid::computeConnectedClientsScalarGrid() 
    1388   TRY 
    1389   { 
     1472    computeClientIndexScalarGrid_done_ = true ; 
     1473  } 
     1474  CATCH_DUMP_ATTR 
     1475 
     1476  void CGrid::computeConnectedClientsScalarGrid(CContextClient* client) 
     1477  TRY 
     1478  { 
     1479    if (computeConnectedClientsScalarGrid_done_.count(client)!=0) return ; 
    13901480 
    13911481    CContext* context = CContext::getCurrent(); 
    13921482      
    13931483    set<int> listReceiverSize ; 
    1394     for (auto it=clients.begin(); it!=clients.end(); ++it) 
    1395     { 
    1396         
    1397       CContextClient* client = *it ; 
    1398  
    1399       int receiverSize = client->serverSize; 
     1484 
     1485    int receiverSize = client->serverSize; 
    14001486       
    1401       if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 
    1402       { 
    1403         listReceiverSize.insert(receiverSize) ; 
    1404         if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 
     1487    if (listReceiverSize.find(receiverSize)==listReceiverSize.end()) 
     1488    { 
     1489      listReceiverSize.insert(receiverSize) ; 
     1490      if (connectedServerRank_.find(receiverSize) != connectedServerRank_.end()) 
     1491      { 
     1492         // delete corresponding map in case of recompute, probably because a grid could has been modifiedd  
     1493         // by a transformation 
     1494        connectedServerRank_.erase(receiverSize); 
     1495        connectedDataSize_.erase(receiverSize); 
     1496        globalIndexOnServer_.erase(receiverSize); 
     1497        nbSenders_.erase(receiverSize); 
     1498      } 
     1499 
     1500      if (client->isServerLeader()) 
     1501      { 
     1502        const std::list<int>& ranks = client->getRanksServerLeader(); 
     1503        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    14051504        { 
    1406            // delete corresponding map in case of recompute, probably because a grid could has been modifiedd  
    1407            // by a transformation 
    1408           connectedServerRank_.erase(receiverSize); 
    1409           connectedDataSize_.erase(receiverSize); 
    1410           globalIndexOnServer_.erase(receiverSize); 
    1411           nbSenders_.erase(receiverSize); 
    1412         } 
    1413  
    1414         if (client->isServerLeader()) 
     1505          int rank = *itRank; 
     1506          int nb = 1; 
     1507          connectedServerRank_[receiverSize].push_back(rank); 
     1508          connectedDataSize_[receiverSize][rank] = nb; 
     1509          nbSenders_[receiverSize][rank] = nb; 
     1510        } 
     1511      } 
     1512      else 
     1513      { 
     1514        const std::list<int>& ranks = client->getRanksServerNotLeader(); 
     1515        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    14151516        { 
    1416           const std::list<int>& ranks = client->getRanksServerLeader(); 
    1417           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    1418           { 
    1419             int rank = *itRank; 
    1420             int nb = 1; 
    1421             connectedServerRank_[receiverSize].push_back(rank); 
    1422             connectedDataSize_[receiverSize][rank] = nb; 
    1423             nbSenders_[receiverSize][rank] = nb; 
    1424           } 
    1425         } 
    1426         else 
    1427         { 
    1428           const std::list<int>& ranks = client->getRanksServerNotLeader(); 
    1429           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    1430           { 
    1431             int rank = *itRank; 
    1432             int nb = 1; 
    1433             connectedServerRank_[receiverSize].push_back(rank); 
    1434             connectedDataSize_[receiverSize][rank] = nb; 
    1435             nbSenders_[receiverSize][rank] = nb; 
    1436           } 
    1437         } 
    1438       } 
    1439       isDataDistributed_ = false; 
    1440     } 
     1517          int rank = *itRank; 
     1518          int nb = 1; 
     1519          connectedServerRank_[receiverSize].push_back(rank); 
     1520          connectedDataSize_[receiverSize][rank] = nb; 
     1521          nbSenders_[receiverSize][rank] = nb; 
     1522        } 
     1523      } 
     1524    } 
     1525    isDataDistributed_ = false; 
     1526    computeConnectedClientsScalarGrid_done_.insert(client) ; 
    14411527  } 
    14421528  CATCH_DUMP_ATTR 
     
    15251611      list<CMessage> listMsg; 
    15261612      list<CArray<size_t,1> > listOutIndex; 
    1527       const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer(); 
     1613      const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = getDistributionClient()->getGlobalLocalDataSendToServer(); 
    15281614      CDistributionClient::GlobalLocalDataMap::const_iterator itbIndex = globalLocalIndexSendToServer.begin(), itIndex, 
    15291615                                                              iteIndex = globalLocalIndexSendToServer.end(); 
     
    19712057  TRY 
    19722058  { 
     2059    if (!computeClientDistribution_done_) computeClientDistribution() ; 
    19732060    return clientDistribution_; 
    19742061  } 
     
    22092296 
    22102297  /*! 
     2298  \brief Check if all elements of the grid are complete 
     2299  Before make any grid processing, we must be sure that all grid information elements have 
     2300  been sent, for exemple when reading a grid in a file or when grid elements are sent by an 
     2301  other context (coupling) 
     2302  */ 
     2303  bool CGrid::checkIfCompleted(void) 
     2304  { 
     2305    setDomainList(); 
     2306    for (auto domainId : domList_) if (!CDomain::get(domainId)->checkIfCompleted()) return false ; 
     2307    setAxisList() ; 
     2308    for (auto axisId : axisList_) if (!CAxis::get(axisId)->checkIfCompleted()) return false ; 
     2309    setScalarList() ; 
     2310    for (auto scalarId : scalarList_) if (!CScalar::get(scalarId)->checkIfCompleted()) return false ; 
     2311    return true ; 
     2312  } 
     2313 
     2314  /*! 
    22112315  \brief Solve domain and axis references 
    22122316  As field, domain and axis can refer to other domains or axis. In order to inherit correctly 
     
    22142318  \param[in] apply inherit all attributes of parents (true) 
    22152319  */ 
    2216   void CGrid::solveDomainAxisRefInheritance(bool apply) 
    2217   TRY 
    2218   { 
    2219     CContext* context = CContext::getCurrent(); 
    2220     unsigned int vecSize, i; 
    2221     std::vector<StdString>::iterator it, itE; 
     2320  void CGrid::solveElementsRefInheritance(bool apply) 
     2321  TRY 
     2322  { 
    22222323    setDomainList(); 
    2223     it = domList_.begin(); itE = domList_.end(); 
    2224     for (; it != itE; ++it) 
    2225     { 
    2226       CDomain* pDom = CDomain::get(*it); 
    2227       if (context->getServiceType()==CServicesManager::CLIENT) 
    2228       { 
    2229         pDom->solveRefInheritance(apply); 
    2230         pDom->solveInheritanceTransformation(); 
    2231       } 
     2324    for (auto domainId : domList_) 
     2325    { 
     2326      CDomain* pDom = CDomain::get(domainId); 
     2327      pDom->solveRefInheritance(apply); 
     2328      pDom->solveInheritanceTransformation(); 
    22322329    } 
    22332330 
    22342331    setAxisList(); 
    2235     it = axisList_.begin(); itE = axisList_.end(); 
    2236     for (; it != itE; ++it) 
    2237     { 
    2238       CAxis* pAxis = CAxis::get(*it); 
    2239       if (context->getServiceType()==CServicesManager::CLIENT) 
    2240       { 
    2241         pAxis->solveRefInheritance(apply); 
    2242         pAxis->solveInheritanceTransformation(); 
    2243       } 
     2332    for (auto axisId : axisList_) 
     2333    { 
     2334      CAxis* pAxis = CAxis::get(axisId); 
     2335      pAxis->solveRefInheritance(apply); 
     2336      pAxis->solveInheritanceTransformation(); 
    22442337    } 
    22452338 
    22462339    setScalarList(); 
    2247     it = scalarList_.begin(); itE = scalarList_.end(); 
    2248     for (; it != itE; ++it) 
    2249     { 
    2250       CScalar* pScalar = CScalar::get(*it); 
    2251       if (context->getServiceType()==CServicesManager::CLIENT) 
    2252       { 
    2253         pScalar->solveRefInheritance(apply); 
    2254         pScalar->solveInheritanceTransformation(); 
    2255       } 
    2256     } 
     2340    for (auto scalarId : scalarList_) 
     2341    { 
     2342      CScalar* pScalar = CScalar::get(scalarId); 
     2343      pScalar->solveRefInheritance(apply); 
     2344      pScalar->solveInheritanceTransformation(); 
     2345    } 
     2346  } 
     2347  CATCH_DUMP_ATTR 
     2348 
     2349 /*! 
     2350  \brief check attributes of all elements of the grid 
     2351  */ 
     2352  void CGrid::checkElementsAttributes(void) 
     2353  TRY 
     2354  { 
     2355    setDomainList(); 
     2356    for (auto domainId : domList_) CDomain::get(domainId)->checkAttributes(); 
     2357 
     2358    setAxisList(); 
     2359    for (auto axisId : axisList_) CAxis::get(axisId)->checkAttributes(); 
     2360     
     2361    setScalarList(); 
     2362    for (auto scalarId : scalarList_) CScalar::get(scalarId)->checkAttributes(); 
    22572363  } 
    22582364  CATCH_DUMP_ATTR 
     
    23012407  TRY 
    23022408  { 
    2303     if (0 != transformGridSrc) 
     2409    if (nullptr != transformGridSrc) 
    23042410    { 
    23052411      if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) 
     
    23622468  } 
    23632469  CATCH_DUMP_ATTR 
     2470 
     2471 
     2472 
     2473 
     2474  void CGrid::prepareTransformGrid(CGrid* transformGridSrc) 
     2475  TRY 
     2476  { 
     2477    if (prepareTransformGrid_done_) return ; 
     2478 
     2479    if (!transformGridSrc) 
     2480      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 
     2481            << "Impossible to transform grid '" << getId() << "', the source grid is null."); 
     2482 
     2483    if (isTransformed()) return; 
     2484    setTransformed(); 
     2485    if (axis_domain_order.numElements() != transformGridSrc->axis_domain_order.numElements()) 
     2486    { 
     2487      ERROR("CGrid::transformGrid(CGrid* transformGridSrc)", 
     2488           << "Two grids have different number of elements. " << std::endl 
     2489           << "Number of element of grid destination " << this->getId() << " is " << axis_domain_order.numElements() << std::endl 
     2490           << "Number of element of grid source " << transformGridSrc->getId() << " is " << transformGridSrc->axis_domain_order.numElements()); 
     2491    } 
     2492    else 
     2493    { 
     2494    } 
     2495 
     2496    transformations_ = new CGridTransformation(this, transformGridSrc); 
     2497    if (0 < transformations_->getNbAlgo()) hasTransform_ = true; 
     2498 
     2499    prepareTransformGrid_done_ = true;  
     2500  } 
     2501  CATCH_DUMP_ATTR 
     2502 
     2503 
     2504  void CGrid::makeTransformGrid(void) 
     2505  TRY 
     2506  { 
     2507    if (makeTransformGrid_done_) return ; 
     2508    transformations_->computeAll(); 
     2509 
     2510    makeTransformGrid_done_ = true ;  
     2511  } 
     2512  CATCH_DUMP_ATTR 
     2513 
     2514 
     2515  vector<std::string> CGrid::getAuxInputTransformGrid(void) 
     2516  TRY 
     2517  { 
     2518    if (transformations_ != nullptr) return transformations_->getAuxInputs() ; 
     2519  } 
     2520  CATCH_DUMP_ATTR 
     2521 
     2522 
     2523 
     2524 
     2525 
     2526 
    23642527 
    23652528  bool CGrid::hasTransform() 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp

    r1853 r1869  
    7171         void checkEligibilityForCompressedOutput(); 
    7272 
    73          void solveDomainAxisRef(bool areAttributesChecked); 
     73 
    7474 
    7575         void checkMaskIndex(bool doCalculateIndex); 
     
    8989         StdSize getDimension(void); 
    9090 
    91          StdSize  getDataSize(void) const; 
     91         StdSize  getDataSize(void) ; 
    9292 
    9393         /// Entrees-sorties de champs 
    9494         template <int n> 
    95          void inputField(const CArray<double,n>& field, CArray<double,1>& stored) const; 
     95         void inputField(const CArray<double,n>& field, CArray<double,1>& stored) ; 
    9696         template <int n> 
    97          void maskField(const CArray<double,n>& field, CArray<double,1>& stored) const; 
     97         void maskField(const CArray<double,n>& field, CArray<double,1>& stored) ; 
    9898         template <int n> 
    99          void outputField(const CArray<double,1>& stored, CArray<double,n>& field) const 
     99         void outputField(const CArray<double,1>& stored, CArray<double,n>& field)  
    100100         template <int n> 
    101          void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) const;  
     101         void uncompressField(const CArray<double,n>& data, CArray<double,1>& outData) ;  
    102102 
    103103         virtual void parse(xml::CXMLNode& node); 
     
    133133         void computeIndexScalarGrid(); 
    134134         void computeWrittenIndex(); 
     135         void solveDomainAxisRef(bool areAttributesChecked); 
     136         void checkElementsAttributes(void) ; 
    135137 
    136138         void solveDomainRef(bool checkAtt); 
    137139         void solveAxisRef(bool checkAtt); 
    138140         void solveScalarRef(bool checkAtt); 
    139          void solveDomainAxisRefInheritance(bool apply = true); 
    140         void solveTransformations(); 
     141         void solveElementsRefInheritance(bool apply = true); 
     142        // void solveTransformations(); 
    141143         void solveDomainAxisBaseRef(); 
    142144 
     
    195197 
    196198         void transformGrid(CGrid* transformGridSrc); 
     199          
     200         void prepareTransformGrid(CGrid* transformGridSrc); 
     201         bool prepareTransformGrid_done_ = false ; 
     202 
     203         void makeTransformGrid(void);  
     204         bool makeTransformGrid_done_ = false ; 
     205          
     206         std::vector<std::string> getAuxInputTransformGrid(void) ;  
     207 
    197208         void completeGrid(CGrid* transformGridSrc = 0); 
    198209         void doAutoDistribution(CGrid* transformGridSrc); 
     
    205216         bool hasTransform(); 
    206217         size_t getGlobalWrittenSize(void) ; 
     218         bool checkIfCompleted(void) ; 
     219 
    207220 
    208221         bool hasMask(void) const; 
     
    217230                                         const CArray<int,1>& axisDomainOrder); 
    218231 
     232         void computeGridIndexToFileServer(CContextClient* client) ; 
     233 
    219234      private: 
     235       void computeClientDistribution(void) ; 
     236       bool computeClientDistribution_done_ = false ; 
     237 
    220238       template<int N> 
    221239       void checkGridMask(CArray<bool,N>& gridMask, 
     
    230248        void modifyGridMaskSize(CArray<bool,N>& gridMask, const std::vector<int>& eachDimSize, bool newValue); 
    231249 
    232         void storeField_arr(const double* const data, CArray<double, 1>& stored) const; 
    233         void restoreField_arr(const CArray<double, 1>& stored, double* const data) const; 
    234         void uncompressField_arr(const double* const data, CArray<double, 1>& outData) const; 
    235         void maskField_arr(const double* const data, CArray<double, 1>& stored) const; 
     250        void storeField_arr(const double* const data, CArray<double, 1>& stored) ; 
     251        void restoreField_arr(const CArray<double, 1>& stored, double* const data) ; 
     252        void uncompressField_arr(const double* const data, CArray<double, 1>& outData) ; 
     253        void maskField_arr(const double* const data, CArray<double, 1>& stored) ; 
    236254 
    237255        void setVirtualDomainGroup(CDomainGroup* newVDomainGroup); 
     
    259277        int getDistributedDimension(); 
    260278 
     279        
    261280        void computeClientIndex(); 
    262         void computeConnectedClients(); 
     281        bool computeClientIndex_done_ = false ; 
     282         
     283        void computeConnectedClients(CContextClient* client); 
     284        set<CContextClient*> computeConnectedClients_done_ ; 
     285 
    263286        void computeClientIndexScalarGrid();  
    264         void computeConnectedClientsScalarGrid();  
    265  
     287        bool computeClientIndexScalarGrid_done_ = false ; 
     288 
     289        void computeConnectedClientsScalarGrid(CContextClient* client);  
     290        set<CContextClient*> computeConnectedClientsScalarGrid_done_ ; 
    266291 
    267292      public: 
     
    270295 *  Used to store field from model into the worklow, or to return field into models.   
    271296 *  The size of the array is the number of local index of the workflow grid */         
    272          CArray<int, 1> storeIndex_client_; 
     297        CArray<int, 1> storeIndex_client_; 
     298        void computeStoreIndex_client(void) ; 
     299        bool computeStoreIndex_client_done_ = false ; 
     300        CArray<int, 1>& getStoreIndex_client(void) { if (!computeStoreIndex_client_done_) computeStoreIndex_client() ; return storeIndex_client_ ;} 
    273301 
    274302/** Array containing the grid mask masked defined by the mask_nd grid attribute.         
    275303  * The corresponding masked field value provided by the model will be replaced by a NaN value 
    276304  * in the workflow.  */ 
    277          CArray<bool, 1> storeMask_client_; 
     305        CArray<bool, 1> storeMask_client_; 
     306        void computeStoreMask_client(void) ; 
     307        bool computeStoreMask_client_done_ = false ; 
     308        CArray<bool, 1>& getStoreMask_client(void) { if (!computeStoreMask_client_done_) computeStoreMask_client() ; return storeMask_client_ ;} 
    278309 
    279310/** Map containing the indexes on client side that will be sent to each connected server. 
     
    419450 
    420451   template <int n> 
    421    void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) const 
     452   void CGrid::inputField(const CArray<double,n>& field, CArray<double,1>& stored) 
    422453   TRY 
    423454   { 
     
    435466 
    436467   template <int n> 
    437    void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) const 
     468   void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored) 
    438469   { 
    439470//#ifdef __XIOS_DEBUG 
     
    449480 
    450481   template <int n> 
    451    void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) const 
     482   void CGrid::outputField(const CArray<double,1>& stored, CArray<double,n>& field) 
    452483   TRY 
    453484   { 
     
    471502   */ 
    472503   template <int N> 
    473    void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) const 
     504   void CGrid::uncompressField(const CArray<double,N>& data, CArray<double,1>& outData) 
    474505   TRY 
    475506   {       
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/scalar.cpp

    r1314 r1869  
    5959   void CScalar::checkAttributes(void) 
    6060   { 
     61      if (checkAttributes_done_) return ; 
     62 
     63      checkAttributes_done_ = true ;  
    6164   } 
    6265 
     
    6568 
    6669  } 
     70 
     71  /*! 
     72  \brief Check if a scalar is completed 
     73  Before make any scalar processing, we must be sure that all scalar informations have 
     74  been sent, for exemple when reading a grid in a file or when grid elements are sent by an