Index: XIOS/dev/XIOS_DEV_CMIP6/src/node/field.cpp
===================================================================
--- XIOS/dev/XIOS_DEV_CMIP6/src/node/field.cpp	(revision 1262)
+++ XIOS/dev/XIOS_DEV_CMIP6/src/node/field.cpp	(revision 1263)
@@ -132,4 +132,5 @@
     CContext* context = CContext::getCurrent();
     CContextClient* client = (!context->hasServer) ? context->client : this->file->getContextClient();
+    int receiverSize = client->serverSize;
 
     CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
@@ -175,5 +176,5 @@
 
         list_msg.back() << getId() << data_tmp;
-        event.push(rank, grid->nbSenders[client][rank], list_msg.back());
+        event.push(rank, grid->nbSenders[receiverSize][rank], list_msg.back());
       }
       client->sendEvent(event);
Index: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp
===================================================================
--- XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp	(revision 1262)
+++ XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.cpp	(revision 1263)
@@ -146,8 +146,8 @@
 
    /*!
-    * Compute the minimum buffer size required to send the data to the server(s).
-    *
+    * Compute the minimum buffer size required to send the data.
+    * \param client contextClient used to determine the size of connected receivers
     * \param id the id used to tag the data
-    * \return A map associating the server rank with its minimum buffer size.
+    * \return A map associating the sender rank with its minimum buffer size.
     */
    std::map<int, StdSize> CGrid::getDataBufferSize(CContextClient* client, const std::string& id /*= ""*/)
@@ -176,9 +176,10 @@
 
      std::map<int, StdSize> dataSizes;
-     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[client].end();
-     for (size_t k = 0; k < connectedServerRank_[client].size(); ++k)
+     int receiverSize = client->serverSize;
+     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[receiverSize].end();
+     for (size_t k = 0; k < connectedServerRank_[receiverSize].size(); ++k)
      {
-       int rank = connectedServerRank_[client][k];
-       std::map<int, size_t>::const_iterator it = connectedDataSize_[client].find(rank);
+       int rank = connectedServerRank_[receiverSize][k];
+       std::map<int, size_t>::const_iterator it = connectedDataSize_[receiverSize].find(rank);
        size_t count = (it != itEnd) ? it->second : 0;
 
@@ -315,5 +316,4 @@
    {
      CContext* context = CContext::getCurrent();
-     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
      int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;   
      nbSrvPools = 1;  
@@ -658,60 +658,54 @@
      CContext* context = CContext::getCurrent();
 
-     // This needs to change one day
-     int nbSrvPools = 1; 
-     for (int p = 0; p < nbSrvPools; ++p)
+     CContextClient* client = context->client;  // Here it's not important which contextClient to recuperate
+     int rank = client->clientRank;
+
+     clientDistribution_ = new CDistributionClient(rank, this);
+     // Get local data index on client
+     storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
+     int nbStoreIndex = storeIndex_client.numElements();
+     for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
+
+     if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed();
+     else
      {
-       CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client) : context->client;
-       int rank = client->clientRank;
-
-       clientDistribution_ = new CDistributionClient(rank, this);
-       // Get local data index on client
-       storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
-       int nbStoreIndex = storeIndex_client.numElements();
-       for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];       
-     
-       if (0 == serverDistribution_) isDataDistributed_= clientDistribution_->isDataDistributed();
-       else          
-       {          
-          // Mapping global index received from clients to the storeIndex_client
-          CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
-          CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
-          map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
-                                                 ite = outGlobalIndexFromClient.end(), it;
-                  
-          for (it = itb; it != ite; ++it)
+        // Mapping global index received from clients to the storeIndex_client
+        CDistributionClient::GlobalLocalDataMap& globalDataIndex = clientDistribution_->getGlobalDataIndexOnClient();
+        CDistributionClient::GlobalLocalDataMap::const_iterator itGloe = globalDataIndex.end();
+        map<int, CArray<size_t, 1> >::iterator itb = outGlobalIndexFromClient.begin(),
+                                               ite = outGlobalIndexFromClient.end(), it;
+
+        for (it = itb; it != ite; ++it)
+        {
+          int rank = it->first;
+          CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
+          outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
+          CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
+          size_t nbIndex = 0;
+
+          // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
+          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
           {
-            int rank = it->first;
-            CArray<size_t,1>& globalIndex = outGlobalIndexFromClient[rank];
-            outLocalIndexStoreOnClient.insert(make_pair(rank, CArray<size_t,1>(globalIndex.numElements())));
-            CArray<size_t,1>& localIndex = outLocalIndexStoreOnClient[rank];
-            size_t nbIndex = 0;
-            
-            // Keep this code for this moment but it should be removed (or moved to DEBUG) to improve performance
-            for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
+            if (itGloe != globalDataIndex.find(globalIndex(idx)))
             {
-              if (itGloe != globalDataIndex.find(globalIndex(idx)))
-              {
-                ++nbIndex;                           
-              }              
+              ++nbIndex;
             }
-
-            
-            if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements()))
-                 ERROR("void CGrid::computeClientIndex()",
-                    << "Number of local index on client is different from number of received global index" 
-                    << "Rank of sent client " << rank <<"."
-                    << "Number of local index " << nbIndex << ". "
-                    << "Number of received global index " << localIndex.numElements() << ".");
-
-            nbIndex = 0;
-            for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
+          }
+
+          if (doGridHaveDataDistributed(client) && (nbIndex != localIndex.numElements()))
+               ERROR("void CGrid::computeClientIndex()",
+                  << "Number of local index on client is different from number of received global index"
+                  << "Rank of sent client " << rank <<"."
+                  << "Number of local index " << nbIndex << ". "
+                  << "Number of received global index " << localIndex.numElements() << ".");
+
+          nbIndex = 0;
+          for (size_t idx = 0; idx < globalIndex.numElements(); ++idx)
+          {
+            if (itGloe != globalDataIndex.find(globalIndex(idx)))
             {
-              if (itGloe != globalDataIndex.find(globalIndex(idx)))
-              {            
-                localIndex(idx) = globalDataIndex[globalIndex(idx)];                
-              }              
+              localIndex(idx) = globalDataIndex[globalIndex(idx)];
             }
-          }          
+          }
         }
       }
@@ -719,11 +713,10 @@
 
    /*!
-     Compute the connected clients and index to send to these clients.
-     Each client can connect to a pool of other clients, each of which can have a piece of information of a grid
+     Compute connected receivers and indexes to be sent to these receivers.
    */
    void CGrid::computeConnectedClients()
    {
      CContext* context = CContext::getCurrent();
-     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
+     int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
      connectedServerRank_.clear();
      connectedDataSize_.clear();
@@ -733,81 +726,85 @@
      for (int p = 0; p < nbSrvPools; ++p)
      {
-       CContextClient* client = (context->hasServer) ? context->clientPrimServer[p] : context->client;
-
-       connectedServerRank_[client].clear();
-
-       if (!doGridHaveDataDistributed(client))
+       CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
+       int receiverSize = client->serverSize;
+//       connectedServerRank_[client].clear();
+
+       if (connectedServerRank_.find(receiverSize) == connectedServerRank_.end())
        {
-          if (client->isServerLeader())
-          {
-            size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
-            const std::list<int>& ranks = client->getRanksServerLeader();
-            for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+        if (!doGridHaveDataDistributed(client))
+         {
+            if (client->isServerLeader())
             {
-              connectedServerRank_[client].push_back(*itRank);
-              connectedDataSize_[client][*itRank] = ssize;
+              size_t ssize = clientDistribution_->getLocalDataIndexOnClient().size();
+              const std::list<int>& ranks = client->getRanksServerLeader();
+              for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+              {
+                connectedServerRank_[receiverSize].push_back(*itRank);
+                connectedDataSize_[receiverSize][*itRank] = ssize;
+              }
             }
-          }
-          return;
+            return;
+         }
+
+         // Compute mapping between client and server
+         std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
+         CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
+         std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
+                                                                                                    client->clientRank,
+                                                                                                    client->clientSize,
+                                                                                                    axis_domain_order,
+                                                                                                    getDistributedDimension());
+
+         // Even if servers have no index, they must received something from client
+         // We only use several client to send "empty" message to these servers
+         std::list<int> serverZeroIndexLeader;
+         std::list<int> serverZeroIndexNotLeader;
+         CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
+         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
+           *it = serverZeroIndex[*it];
+
+         if (globalIndexOnServer_.find(receiverSize) == globalIndexOnServer_.end())
+           computeIndexByElement(indexServerOnElement, client, globalIndexOnServer_[receiverSize]);
+
+         const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
+         CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
+         CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
+         itbGlobalMap = globalIndexOnServer_[receiverSize].begin();
+         iteGlobalMap = globalIndexOnServer_[receiverSize].end();
+
+         for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
+         {
+           int serverRank = itGlobalMap->first;
+           int indexSize = itGlobalMap->second.size();
+           const std::vector<size_t>& indexVec = itGlobalMap->second;
+           for (int idx = 0; idx < indexSize; ++idx)
+           {
+              itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
+              if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
+              {
+                if (connectedDataSize_[receiverSize].end() == connectedDataSize_[receiverSize].find(serverRank))
+                  connectedDataSize_[receiverSize][serverRank] = 1;
+                else
+                  ++connectedDataSize_[receiverSize][serverRank];
+              }
+           }
+         }
+
+         // Connected servers which really have index
+         for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
+           connectedServerRank_[receiverSize].push_back(itGlobalMap->first);
+         }
+
+         // Connected servers which have no index at all
+         for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
+           connectedServerRank_[receiverSize].push_back(*it);
+
+         // Even if a client has no index, it must connect to at least one server and
+         // send an "empty" data to this server
+         if (connectedServerRank_[receiverSize].empty())
+          connectedServerRank_[receiverSize].push_back(client->clientRank % client->serverSize);
+
+         nbSenders[receiverSize] = clientServerMap_->computeConnectedClients(receiverSize, client->clientSize, client->intraComm, connectedServerRank_[receiverSize]);
        }
-
-       // Compute mapping between client and server
-       std::vector<boost::unordered_map<size_t,std::vector<int> > > indexServerOnElement;
-       CServerDistributionDescription serverDistributionDescription(getGlobalDimension(), client->serverSize);
-       std::vector<int> serverZeroIndex = serverDistributionDescription.computeServerGlobalByElement(indexServerOnElement,
-                                                                                                  client->clientRank,
-                                                                                                  client->clientSize,
-                                                                                                  axis_domain_order,
-                                                                                                  getDistributedDimension());
-
-       // Even if servers have no index, they must received something from client
-       // We only use several client to send "empty" message to these servers
-       std::list<int> serverZeroIndexLeader;
-       std::list<int> serverZeroIndexNotLeader; 
-       CContextClient::computeLeader(client->clientRank, client->clientSize, serverZeroIndex.size(), serverZeroIndexLeader, serverZeroIndexNotLeader);
-       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
-         *it = serverZeroIndex[*it];
-
-       computeIndexByElement(indexServerOnElement, globalIndexOnServer_[client]);
-
-       const CDistributionClient::GlobalLocalDataMap& globalLocalIndexSendToServer = clientDistribution_->getGlobalLocalDataSendToServer();
-       CDistributionClient::GlobalLocalDataMap::const_iterator iteGlobalLocalIndexMap = globalLocalIndexSendToServer.end(), itGlobalLocalIndexMap;
-       CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itbGlobalMap, itGlobalMap;
-       itbGlobalMap = globalIndexOnServer_[client].begin();
-       iteGlobalMap = globalIndexOnServer_[client].end();
-
-       for (itGlobalMap  = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap)
-       {
-         int serverRank = itGlobalMap->first;
-         int indexSize = itGlobalMap->second.size();
-         const std::vector<size_t>& indexVec = itGlobalMap->second;
-         for (int idx = 0; idx < indexSize; ++idx)
-         {
-            itGlobalLocalIndexMap = globalLocalIndexSendToServer.find(indexVec[idx]);
-            if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
-            {
-               if (connectedDataSize_[client].end() == connectedDataSize_[client].find(serverRank))
-                 connectedDataSize_[client][serverRank] = 1;
-               else
-                 ++connectedDataSize_[client][serverRank];
-            }
-         }
-       }
-
-       // Connected servers which really have index
-       for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
-         connectedServerRank_[client].push_back(itGlobalMap->first);
-       }
-
-       // Connected servers which have no index at all
-       for (std::list<int>::iterator it = serverZeroIndexLeader.begin(); it != serverZeroIndexLeader.end(); ++it)
-         connectedServerRank_[client].push_back(*it);
-
-       // Even if a client has no index, it must connect to at least one server and 
-       // send an "empty" data to this server
-       if (connectedServerRank_[client].empty())
-        connectedServerRank_[client].push_back(client->clientRank % client->serverSize);
-
-       nbSenders[client] = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[client]);
      }
    }
@@ -847,177 +844,172 @@
       on each element whose size is much smaller than one of whole grid.
       \param [in] indexServerOnElement global index of each element and the rank of server associated with these index
+      \param [in] client contextClient
       \param [out] globalIndexOnServer global index of grid and its corresponding rank of server.
    */
    void CGrid::computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
+                                     const CContextClient* client,
                                      CClientServerMapping::GlobalIndexMap& globalIndexOnServer)
    {
-     CContext* context = CContext::getCurrent();
-     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
-     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
-     nbSrvPools = 1;
-     for (int p = 0; p < nbSrvPools; ++p)
+     int serverSize = client->serverSize;
+
+     std::vector<CDomain*> domList = getDomains();
+     std::vector<CAxis*> axisList = getAxis();
+
+     // Some pre-calculations of global index on each element of current grid.
+     int nbElement = axis_domain_order.numElements();
+     std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
+     int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
+     std::vector<size_t> elementNGlobal(nbElement);
+     elementNGlobal[0] = 1;
+     size_t globalSize = 1;
+     for (int idx = 0; idx < nbElement; ++idx)
      {
-       CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
-       int serverSize = client->serverSize;
-       std::vector<CDomain*> domList = getDomains();
-       std::vector<CAxis*> axisList = getAxis();
-
-       // Some pre-calculations of global index on each element of current grid.
-       int nbElement = axis_domain_order.numElements();
-       std::vector<CArray<size_t,1> > globalIndexElement(nbElement);
-       int domainIdx = 0, axisIdx = 0, scalarIdx = 0;
-       std::vector<size_t> elementNGlobal(nbElement);
-       elementNGlobal[0] = 1;
-       size_t globalSize = 1;
-       for (int idx = 0; idx < nbElement; ++idx)
+       elementNGlobal[idx] = globalSize;
+       size_t elementSize;
+       size_t elementGlobalSize = 1;
+       if (2 == axis_domain_order(idx)) // This is domain
        {
-         elementNGlobal[idx] = globalSize;
-         size_t elementSize;
-         size_t elementGlobalSize = 1;
-         if (2 == axis_domain_order(idx)) // This is domain
+         elementSize = domList[domainIdx]->i_index.numElements();
+         globalIndexElement[idx].resize(elementSize);
+         for (int jdx = 0; jdx < elementSize; ++jdx)
          {
-           elementSize = domList[domainIdx]->i_index.numElements();
-           globalIndexElement[idx].resize(elementSize);
-           for (int jdx = 0; jdx < elementSize; ++jdx)
+           globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
+         }
+         elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
+         ++domainIdx;
+       }
+       else if (1 == axis_domain_order(idx))  // This is axis
+       {
+         elementSize = axisList[axisIdx]->index.numElements();
+         globalIndexElement[idx].resize(elementSize);
+         for (int jdx = 0; jdx < elementSize; ++jdx)
+         {
+           globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
+         }
+         elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
+         ++axisIdx;
+       }
+       else  // Of course, this is scalar
+       {
+         globalIndexElement[idx].resize(1);
+         globalIndexElement[idx](0) = 0;
+         elementGlobalSize = 1;
+       }
+       globalSize *= elementGlobalSize;
+     }
+
+     std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
+     std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
+     CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
+     // Number of temporary distributed global index held by each client for each server
+     // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
+     CArray<int,1> nbIndexOnServerTmp(serverSize);
+     for (int idx = 0; idx < nbElement; ++idx)
+     {
+       nbIndexOnServer = 0;
+       const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
+       const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
+       CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
+       clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
+       const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
+       CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
+                                                                    ite = globalIndexElementOnServerMap.end(), it;
+       for (it = itb; it != ite; ++it)
+       {
+         const std::vector<int>& tmp = it->second;
+         nbIndexOnServerTmp = 0;
+         for (int i = 0; i < tmp.size(); ++i)
+         {
+           if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
+         }
+         nbIndexOnServer += nbIndexOnServerTmp;
+       }
+
+       for (int i = 0; i < serverSize; ++i)
+       {
+         if (0 != nbIndexOnServer(i))
+         {
+           globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
+           elementOnServer[idx][i] = true;
+         }
+       }
+
+     nbIndexOnServer = 0;
+     for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
+     {
+       it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
+       if (it != ite)
+       {
+         const std::vector<int>& tmp = it->second;
+         nbIndexOnServerTmp = 0;
+         for (int i = 0; i < tmp.size(); ++i)
+         {
+           if (0 == nbIndexOnServerTmp(tmp[i]))
            {
-             globalIndexElement[idx](jdx) = (domList[domainIdx]->i_index)(jdx) + domList[domainIdx]->ni_glo * (domList[domainIdx]->j_index)(jdx);
-           }
-           elementGlobalSize = domList[domainIdx]->ni_glo.getValue() * domList[domainIdx]->nj_glo.getValue();
-           ++domainIdx;
-         }
-         else if (1 == axis_domain_order(idx))  // This is axis
-         {
-           elementSize = axisList[axisIdx]->index.numElements();
-           globalIndexElement[idx].resize(elementSize);
-           for (int jdx = 0; jdx < elementSize; ++jdx)
-           {
-             globalIndexElement[idx](jdx) = (axisList[axisIdx]->index)(jdx);
-           }
-           elementGlobalSize = axisList[axisIdx]->n_glo.getValue();
-           ++axisIdx;
-         }
-         else  // Of course, this is scalar
-         {
-           globalIndexElement[idx].resize(1);
-           globalIndexElement[idx](0) = 0;
-           elementGlobalSize = 1;
-         }
-         globalSize *= elementGlobalSize;
-       }
-
-       std::vector<std::vector<bool> > elementOnServer(nbElement, std::vector<bool>(serverSize, false));
-       std::vector<boost::unordered_map<int,std::vector<size_t> > > globalElementIndexOnServer(nbElement);
-       CArray<int,1> nbIndexOnServer(serverSize); // Number of distributed global index held by each client for each server
-       // Number of temporary distributed global index held by each client for each server
-       // We have this variable for the case of non-distributed element (often axis) to check the duplicate server rank
-       CArray<int,1> nbIndexOnServerTmp(serverSize);
-       for (int idx = 0; idx < nbElement; ++idx)
-       {
-         nbIndexOnServer = 0;
-         const boost::unordered_map<size_t,std::vector<int> >& indexServerElement = indexServerOnElement[idx];
-         const CArray<size_t,1>& globalIndexElementOnClient = globalIndexElement[idx];
-         CClientClientDHTInt clientClientDHT(indexServerElement, client->intraComm);
-         clientClientDHT.computeIndexInfoMapping(globalIndexElementOnClient);
-         const CClientClientDHTInt::Index2VectorInfoTypeMap& globalIndexElementOnServerMap = clientClientDHT.getInfoIndexMap();
-         CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = globalIndexElementOnServerMap.begin(),
-                                                                      ite = globalIndexElementOnServerMap.end(), it;
-         for (it = itb; it != ite; ++it)
-         {
-           const std::vector<int>& tmp = it->second;
-           nbIndexOnServerTmp = 0;
-           for (int i = 0; i < tmp.size(); ++i)
-           {
-             if (0 == nbIndexOnServerTmp(tmp[i])) ++nbIndexOnServerTmp(tmp[i]);
-           }
-           nbIndexOnServer += nbIndexOnServerTmp;
-         }
-
-         for (int i = 0; i < serverSize; ++i)
-         {
-           if (0 != nbIndexOnServer(i))
-           {
-             globalElementIndexOnServer[idx][i].resize(nbIndexOnServer(i));
-             elementOnServer[idx][i] = true;
+             globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
+             ++nbIndexOnServerTmp(tmp[i]);
            }
          }
-
-       nbIndexOnServer = 0;
-       for (size_t j = 0; j < globalIndexElementOnServerMap.size(); ++j)
-       {
-         it = globalIndexElementOnServerMap.find(globalIndexElementOnClient(j));
-         if (it != ite)
-         {
-           const std::vector<int>& tmp = it->second;
-           nbIndexOnServerTmp = 0;
-           for (int i = 0; i < tmp.size(); ++i)
-           {
-             if (0 == nbIndexOnServerTmp(tmp[i]))
-             {
-               globalElementIndexOnServer[idx][tmp[i]][nbIndexOnServer(tmp[i])] = it->first;
-               ++nbIndexOnServerTmp(tmp[i]);
-             }
-           }
-           nbIndexOnServer += nbIndexOnServerTmp;
-         }
+         nbIndexOnServer += nbIndexOnServerTmp;
        }
      }
-
-      // Determine server which contain global source index
-      std::vector<bool> intersectedProc(serverSize, true);
+   }
+
+    // Determine server which contain global source index
+    std::vector<bool> intersectedProc(serverSize, true);
+    for (int idx = 0; idx < nbElement; ++idx)
+    {
+      std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
+                     intersectedProc.begin(), intersectedProc.begin(),
+                     std::logical_and<bool>());
+    }
+
+    std::vector<int> srcRank;
+    for (int idx = 0; idx < serverSize; ++idx)
+    {
+      if (intersectedProc[idx]) srcRank.push_back(idx);
+    }
+
+    // Compute the global index of grid from global index of each element.
+    for (int i = 0; i < srcRank.size(); ++i)
+    {
+      size_t ssize = 1;
+      int rankSrc = srcRank[i];
+      std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
+      std::vector<size_t> currentIndex(nbElement,0);
       for (int idx = 0; idx < nbElement; ++idx)
       {
-        std::transform(elementOnServer[idx].begin(), elementOnServer[idx].end(),
-                       intersectedProc.begin(), intersectedProc.begin(),
-                       std::logical_and<bool>());
-      }
-
-      std::vector<int> srcRank;
-      for (int idx = 0; idx < serverSize; ++idx)
-      {
-        if (intersectedProc[idx]) srcRank.push_back(idx);
-      }
-
-      // Compute the global index of grid from global index of each element.
-      for (int i = 0; i < srcRank.size(); ++i)
-      {
-        size_t ssize = 1;
-        int rankSrc = srcRank[i];
-        std::vector<std::vector<size_t>* > globalIndexOfElementTmp(nbElement);
-        std::vector<size_t> currentIndex(nbElement,0);
-        for (int idx = 0; idx < nbElement; ++idx)
-        {
-          ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
-          globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
-        }
-        globalIndexOnServer[rankSrc].resize(ssize);
-
-        std::vector<int> idxLoop(nbElement,0);
-        int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
-        size_t idx = 0;
-        while (idx < ssize)
-        {
-          for (int ind = 0; ind < nbElement; ++ind)
+        ssize *= (globalElementIndexOnServer[idx][rankSrc]).size();
+        globalIndexOfElementTmp[idx] = &(globalElementIndexOnServer[idx][rankSrc]);
+      }
+      globalIndexOnServer[rankSrc].resize(ssize);
+
+      std::vector<int> idxLoop(nbElement,0);
+      int innnerLoopSize = (globalIndexOfElementTmp[0])->size();
+      size_t idx = 0;
+      while (idx < ssize)
+      {
+        for (int ind = 0; ind < nbElement; ++ind)
+        {
+          if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
           {
-            if (idxLoop[ind] == (globalIndexOfElementTmp[ind])->size())
-            {
-              idxLoop[ind] = 0;
-              ++idxLoop[ind+1];
-            }
-
-            currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
+            idxLoop[ind] = 0;
+            ++idxLoop[ind+1];
           }
 
-          for (int ind = 0; ind < innnerLoopSize; ++ind)
+          currentIndex[ind] = (*(globalIndexOfElementTmp[ind]))[idxLoop[ind]];
+        }
+
+        for (int ind = 0; ind < innnerLoopSize; ++ind)
+        {
+          currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
+          size_t globalSrcIndex = 0;
+          for (int idxElement = 0; idxElement < nbElement; ++idxElement)
           {
-            currentIndex[0] = (*globalIndexOfElementTmp[0])[ind];
-            size_t globalSrcIndex = 0;
-            for (int idxElement = 0; idxElement < nbElement; ++idxElement)
-            {
-              globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
-            }
-            globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
-            ++idx;
-            ++idxLoop[0];
+            globalSrcIndex += currentIndex[idxElement] * elementNGlobal[idxElement];
           }
+          globalIndexOnServer[rankSrc][idx] = globalSrcIndex;
+          ++idx;
+          ++idxLoop[0];
         }
       }
@@ -1270,9 +1262,10 @@
   {
     CContext* context = CContext::getCurrent();    
-    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; // This should be changed soon
-    for (int p = 0; p < nbSrvPools; ++p)
-    {
-      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client) 
-                                                    : context->client;
+//    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1; // This should be changed soon
+//    for (int p = 0; p < nbSrvPools; ++p)
+    {
+//      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client)
+//                                                    : context->client;
+      CContextClient* client = context->client;
 
       int rank = client->clientRank;
@@ -1308,5 +1301,5 @@
   {
     CContext* context = CContext::getCurrent();    
-    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
+    int nbSrvPools = (context->clientPrimServer.size()==0) ? 1 : context->clientPrimServer.size();
     connectedServerRank_.clear();
     connectedDataSize_.clear();
@@ -1315,34 +1308,36 @@
     for (int p = 0; p < nbSrvPools; ++p)
     {
-      CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client) 
-                                                    : context->client;
-
-      connectedServerRank_[client].clear();
-
-      if (client->isServerLeader())
-      {
-        const std::list<int>& ranks = client->getRanksServerLeader();
-        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
-        {
-          int rank = *itRank;
-          int nb = 1;
-          connectedServerRank_[client].push_back(rank);
-          connectedDataSize_[client][rank] = nb;
-          nbSenders[client][rank] = nb;
-        }
-      }
-      else
-      {
-        const std::list<int>& ranks = client->getRanksServerNotLeader();
-        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
-        {
-          int rank = *itRank;
-          int nb = 1;
-          connectedServerRank_[client].push_back(rank);
-          connectedDataSize_[client][rank] = nb;
-          nbSenders[client][rank] = nb;
-        }        
-      }
-
+      CContextClient* client = (context->clientPrimServer.size()==0) ? context->client : context->clientPrimServer[p];
+      int receiverSize = client->serverSize;
+
+//      connectedServerRank_[client].clear();
+
+      if (connectedServerRank_.find(receiverSize)==connectedServerRank_.end())
+      {
+        if (client->isServerLeader())
+        {
+          const std::list<int>& ranks = client->getRanksServerLeader();
+          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+          {
+            int rank = *itRank;
+            int nb = 1;
+            connectedServerRank_[receiverSize].push_back(rank);
+            connectedDataSize_[receiverSize][rank] = nb;
+            nbSenders[receiverSize][rank] = nb;
+          }
+        }
+        else
+        {
+          const std::list<int>& ranks = client->getRanksServerNotLeader();
+          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+          {
+            int rank = *itRank;
+            int nb = 1;
+            connectedServerRank_[receiverSize].push_back(rank);
+            connectedDataSize_[receiverSize][rank] = nb;
+            nbSenders[receiverSize][rank] = nb;
+          }
+        }
+      }
       isDataDistributed_ = false;
     }
@@ -1358,4 +1353,5 @@
     {
       CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
+      int receiverSize = client->serverSize;
 
       CEventClient event(getType(), EVENT_ID_INDEX);
@@ -1416,9 +1412,10 @@
   {
     CContext* context = CContext::getCurrent();
-    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
+    int nbSrvPools = (context->clientPrimServer.size() == 0) ? 1 : context->clientPrimServer.size();
     storeIndex_toSrv.clear();
     for (int p = 0; p < nbSrvPools; ++p)
     {
-      CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client ;
+      CContextClient* client = (context->clientPrimServer.size() == 0) ? context->client : context->clientPrimServer[p];
+      int receiverSize = client->serverSize;
 
       CEventClient event(getType(), EVENT_ID_INDEX);
@@ -1480,6 +1477,6 @@
       {
         CClientServerMapping::GlobalIndexMap::const_iterator iteGlobalMap, itGlobalMap;
-        itGlobalMap = globalIndexOnServer_[client].begin();
-        iteGlobalMap = globalIndexOnServer_[client].end();
+        itGlobalMap = globalIndexOnServer_[receiverSize].begin();
+        iteGlobalMap = globalIndexOnServer_[receiverSize].end();
 
         std::map<int,std::vector<int> >localIndexTmp;
@@ -1501,7 +1498,7 @@
         }
 
-        for (int ns = 0; ns < connectedServerRank_[client].size(); ++ns)
-        {
-          rank = connectedServerRank_[client][ns];
+        for (int ns = 0; ns < connectedServerRank_[receiverSize].size(); ++ns)
+        {
+          rank = connectedServerRank_[receiverSize][ns];
           int nb = 0;
           if (globalIndexTmp.end() != globalIndexTmp.find(rank))
@@ -1524,5 +1521,5 @@
           listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
 
-          event.push(rank, nbSenders[client][rank], listMsg.back());
+          event.push(rank, nbSenders[receiverSize][rank], listMsg.back());
         }
 
Index: XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.hpp
===================================================================
--- XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.hpp	(revision 1262)
+++ XIOS/dev/XIOS_DEV_CMIP6/src/node/grid.hpp	(revision 1263)
@@ -205,11 +205,14 @@
          CArray<int, 1> storeIndex_client;
 
-/** Map containing indexes that will be sent in sendIndex(). In future: change the key to pair<distrType, serverSize> (?) */
+/** Map containing indexes that will be sent in sendIndex(). */
          std::map<CContextClient*, map<int, CArray<int, 1> > > storeIndex_toSrv;
 
+/** Map storing the number of senders. Key = size of receiver's intracomm */
+         std::map<int, std::map<int,int> > nbSenders;
+
+         std::map<CContextClient*, std::map<int,int> > nbReadSenders;
+
          map<int, CArray<int, 1> > storeIndex_fromSrv; // Support, for now, reading with level-1 server
 
-
-         std::map<CContextClient*, std::map<int,int> > nbSenders, nbReadSenders;
 
          map<int, CArray<size_t, 1> > outIndexFromClient, compressedOutIndexFromClient, outGlobalIndexFromClient;
@@ -271,4 +274,5 @@
         void setTransformationAlgorithms();
         void computeIndexByElement(const std::vector<boost::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
+                                   const CContextClient* client,
                                    CClientServerMapping::GlobalIndexMap& globalIndexOnServer);
         int computeGridGlobalDimension(std::vector<int>& globalDim,
@@ -305,9 +309,9 @@
         int numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_;
 
-/** Map storing ranks of connected servers. In future: change the key to the server size (?) */
-        std::map<CContextClient*, std::vector<int> > connectedServerRank_;
-
-/** Map storing data size that will be sent to connected servers. In future: change the key to the server size (?) */
-        std::map<CContextClient*, std::map<int,size_t> > connectedDataSize_;
+/** Map storing local ranks of connected receivers. Key = size of receiver's intracomm */
+        std::map<int, std::vector<int> > connectedServerRank_;
+
+/** Map storing the size of data to be send. Key = size of receiver's intracomm */
+        std::map<int, std::map<int,size_t> > connectedDataSize_;
 
         bool isDataDistributed_;        
@@ -324,6 +328,10 @@
         bool hasTransform_;
 
-/** Map storing data size that will be sent to connected servers. In future: change the key to the server size (?) */
-        std::map<CContextClient*, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_;
+/** Map storing global indexes of server-like (band-wise) distribution for sending to receivers.
+  * Key = size of receiver's intracomm.
+  */
+//        std::map<CContextClient*, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_;
+        std::map<int, CClientServerMapping::GlobalIndexMap> globalIndexOnServer_;
+
 
 /** List order of axis and domain in a grid, if there is a domain, it will take value 1 (true), axis 0 (false) */
