Index: XIOS/trunk/src/client_server_mapping.cpp
===================================================================
--- XIOS/trunk/src/client_server_mapping.cpp	(revision 567)
+++ XIOS/trunk/src/client_server_mapping.cpp	(revision 568)
@@ -21,4 +21,11 @@
 
 void CClientServerMapping::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
+                                                     const CArray<int,1>& localIndexOnClient)
+{
+//  defaultComputeServerIndexMapping(globalIndexOnClient, globalIndexServer);
+}
+
+
+void CClientServerMapping::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
                                                      const std::vector<CArray<size_t,1>* >& globalIndexServer)
 {
@@ -26,10 +33,10 @@
 }
 
-void CClientServerMapping::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
-                                                     const CArray<int,1>& localIndexOnClient,
-                                                     const std::vector<CArray<size_t,1>* >& globalIndexOnServer)
-{
-  defaultComputeServerIndexMapping(globalIndexOnClient, globalIndexOnServer, &localIndexOnClient);
-}
+//void CClientServerMapping::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
+//                                                     const CArray<int,1>& localIndexOnClient,
+//                                                     const std::vector<CArray<size_t,1>* >& globalIndexOfServer)
+//{
+//  defaultComputeServerIndexMapping(globalIndexOnClient, globalIndexOfServer, &localIndexOnClient);
+//}
 
 /*!
@@ -68,5 +75,4 @@
   }
 }
-
 
 /*!
Index: XIOS/trunk/src/client_server_mapping.hpp
===================================================================
--- XIOS/trunk/src/client_server_mapping.hpp	(revision 567)
+++ XIOS/trunk/src/client_server_mapping.hpp	(revision 568)
@@ -13,4 +13,5 @@
 #include "array_new.hpp"
 #include "mpi.hpp"
+#include <boost/unordered_map.hpp>
 
 namespace xios {
@@ -34,6 +35,9 @@
 
     virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
-                                           const CArray<int,1>& localIndexOnClient,
-                                           const std::vector<CArray<size_t,1>* >& globalIndexOnServer);
+                                           const CArray<int,1>& localIndexOnClient);
+
+//    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
+//                                           const CArray<int,1>& localIndexOnClient,
+//                                           const std::vector<CArray<size_t,1>* >& globalIndexOnServer);
 
     std::map<int,int> computeConnectedClients(int nbServer, int nbClient,
@@ -49,5 +53,5 @@
                                           const CArray<int,1>* localIndexOnClient = 0);
 
-  private:
+  protected:
     //! Global index of data on SERVER, which are calculated by client(s)
     std::map<int, std::vector<size_t> > indexGlobalOnServer_;
Index: XIOS/trunk/src/client_server_mapping_distributed.cpp
===================================================================
--- XIOS/trunk/src/client_server_mapping_distributed.cpp	(revision 568)
+++ XIOS/trunk/src/client_server_mapping_distributed.cpp	(revision 568)
@@ -0,0 +1,496 @@
+#include "client_server_mapping_distributed.hpp"
+#include <limits>
+#include <boost/functional/hash.hpp>
+
+namespace xios
+{
+
+CClientServerMappingDistributed::CClientServerMappingDistributed(const boost::unordered_map<size_t,int>& globalIndexOfServer,
+                                                                 const MPI_Comm& clientIntraComm) : CClientServerMapping(), indexClientHash_()
+{
+  clientIntraComm_ = clientIntraComm;
+  MPI_Comm_size(clientIntraComm,&(nbClient_));
+  MPI_Comm_rank(clientIntraComm,&clientRank_) ;
+  computeDistributedServerIndex(globalIndexOfServer, clientIntraComm);
+}
+
+CClientServerMappingDistributed::~CClientServerMappingDistributed()
+{
+
+}
+
+void CClientServerMappingDistributed::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
+                                                                const CArray<int,1>& localIndexOnClient)
+{
+  size_t ssize = globalIndexOnClient.numElements(), hashedIndex;
+
+  std::vector<size_t>::const_iterator itbClientHash = indexClientHash_.begin(), itClientHash,
+                                      iteClientHash = indexClientHash_.end();
+  std::map<int, std::vector<size_t> > client2ClientIndexGlobal;
+  std::map<int, std::vector<int> > client2ClientIndexServer;
+  std::map<int, std::vector<int> > clientLocalIndex;
+
+  // Number of global index whose mapping server can be found out thanks to index-server mapping
+  int nbIndexAlreadyOnClient = 0;
+
+  // Number of global index whose mapping server are on other clients
+  int nbIndexSendToOthers = 0;
+  boost::hash<size_t> hashGlobalIndex;
+  for (int i = 0; i < ssize; ++i)
+  {
+    size_t globalIndexClient = globalIndexOnClient(i);
+    hashedIndex  = hashGlobalIndex(globalIndexClient);
+    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashedIndex);
+    if (iteClientHash != itClientHash)
+    {
+      int indexClient = std::distance(itbClientHash, itClientHash)-1;
+
+      if (clientRank_ == indexClient)
+      {
+        (indexGlobalOnServer_[globalIndexToServerMapping_[globalIndexClient]]).push_back(globalIndexClient);
+        (localIndexSend2Server_[globalIndexToServerMapping_[globalIndexClient]]).push_back(localIndexOnClient(i));
+        ++nbIndexAlreadyOnClient;
+      }
+      else
+      {
+        client2ClientIndexGlobal[indexClient].push_back(globalIndexClient);
+        clientLocalIndex[indexClient].push_back(i);
+        ++nbIndexSendToOthers;
+      }
+    }
+  }
+
+  int* sendBuff = new int[nbClient_];
+  for (int i = 0; i < nbClient_; ++i) sendBuff[i] = 0;
+  std::map<int, std::vector<size_t> >::iterator it  = client2ClientIndexGlobal.begin(),
+                                                ite = client2ClientIndexGlobal.end();
+  for (; it != ite; ++it) sendBuff[it->first] = 1;
+  int* recvBuff = new int[nbClient_];
+  MPI_Allreduce(sendBuff, recvBuff, nbClient_, MPI_INT, MPI_SUM, clientIntraComm_);
+
+  std::list<MPI_Request> sendRequest;
+  if (0 != nbIndexSendToOthers)
+      for (it = client2ClientIndexGlobal.begin(); it != ite; ++it)
+         sendIndexGlobalToClients(it->first, it->second, clientIntraComm_, sendRequest);
+
+  // Receiving demand as well as the responds from other clients
+  // The demand message contains global index; meanwhile the responds have server index information
+  // Buffer to receive demand from other clients, it can be allocated or not depending whether it has demand(s)
+  unsigned long* recvBuffIndexGlobal = 0;
+  int maxNbIndexDemandedFromOthers = (nbIndexAlreadyOnClient >= globalIndexToServerMapping_.size())
+                                   ? 0 : (globalIndexToServerMapping_.size() - nbIndexAlreadyOnClient);
+  if (0 != maxNbIndexDemandedFromOthers)
+    recvBuffIndexGlobal = new unsigned long[maxNbIndexDemandedFromOthers];
+
+  // Buffer to receive respond from other clients, it can be allocated or not depending whether it demands other clients
+  int* recvBuffIndexServer = 0;
+  int nbIndexReceivedFromOthers = nbIndexSendToOthers;
+  if (0 != nbIndexReceivedFromOthers)
+    recvBuffIndexServer = new int[nbIndexReceivedFromOthers];
+
+  resetRequestAndCount();
+  std::map<int, MPI_Request>::iterator itRequest;
+  std::vector<int> demandAlreadyReceived, repondAlreadyReceived;
+  int nbDemandingClient = recvBuff[clientRank_], nbIndexServerReceived = 0;
+  while ((0 < nbDemandingClient) || (!sendRequest.empty()) ||
+         (nbIndexServerReceived < nbIndexReceivedFromOthers))
+  {
+    // Just check whether a client has any demand from other clients.
+    // If it has, then it should send responds to these client(s)
+    probeIndexGlobalMessageFromClients(recvBuffIndexGlobal, maxNbIndexDemandedFromOthers);
+    if (0 < nbDemandingClient)
+    {
+      for (itRequest = requestRecvIndexGlobal_.begin();
+           itRequest != requestRecvIndexGlobal_.end(); ++itRequest)
+      {
+        int flagIndexGlobal, count;
+        MPI_Status statusIndexGlobal;
+
+        MPI_Test(&(itRequest->second), &flagIndexGlobal, &statusIndexGlobal);
+        if (true == flagIndexGlobal)
+        {
+          MPI_Get_count(&statusIndexGlobal, MPI_UNSIGNED_LONG, &count);
+          int clientSourceRank = statusIndexGlobal.MPI_SOURCE;
+          unsigned long* beginBuff = indexGlobalBuffBegin_[clientSourceRank];
+          for (int i = 0; i < count; ++i)
+          {
+            client2ClientIndexServer[clientSourceRank].push_back(globalIndexToServerMapping_[*(beginBuff+i)]);
+          }
+          sendIndexServerToClients(clientSourceRank, client2ClientIndexServer[clientSourceRank], clientIntraComm_, sendRequest);
+          --nbDemandingClient;
+
+          demandAlreadyReceived.push_back(clientSourceRank);
+        }
+      }
+      for (int i = 0; i< demandAlreadyReceived.size(); ++i)
+        requestRecvIndexGlobal_.erase(demandAlreadyReceived[i]);
+    }
+
+    testSendRequest(sendRequest);
+
+    // In some cases, a client need to listen respond from other clients about server information
+    // Ok, with the information, a client can fill in its server-global index map.
+    probeIndexServerMessageFromClients(recvBuffIndexServer, nbIndexReceivedFromOthers);
+    for (itRequest = requestRecvIndexServer_.begin();
+         itRequest != requestRecvIndexServer_.end();
+         ++itRequest)
+    {
+      int flagIndexServer, count;
+      MPI_Status statusIndexServer;
+
+      MPI_Test(&(itRequest->second), &flagIndexServer, &statusIndexServer);
+      if (true == flagIndexServer)
+      {
+        MPI_Get_count(&statusIndexServer, MPI_INT, &count);
+        int clientSourceRank = statusIndexServer.MPI_SOURCE;
+        int* beginBuff = indexServerBuffBegin_[clientSourceRank];
+        std::vector<size_t>& globalIndexTmp = client2ClientIndexGlobal[clientSourceRank];
+        std::vector<int>& localIndexTmp = clientLocalIndex[clientSourceRank];
+        for (int i = 0; i < count; ++i)
+        {
+          (indexGlobalOnServer_[*(beginBuff+i)]).push_back(globalIndexTmp[i]);
+          (localIndexSend2Server_[*(beginBuff+i)]).push_back(localIndexOnClient(localIndexTmp[i]));
+        }
+        nbIndexServerReceived += count;
+        repondAlreadyReceived.push_back(clientSourceRank);
+      }
+    }
+
+    for (int i = 0; i< repondAlreadyReceived.size(); ++i)
+      requestRecvIndexServer_.erase(repondAlreadyReceived[i]);
+    repondAlreadyReceived.resize(0);
+  }
+
+  if (0 != recvBuffIndexGlobal) delete recvBuffIndexGlobal;
+  if (0 != recvBuffIndexServer) delete recvBuffIndexServer;
+  delete [] sendBuff;
+  delete [] recvBuff;
+}
+
+void CClientServerMappingDistributed::computeHashIndex()
+{
+  // Compute range of hash index for each client
+  indexClientHash_.resize(nbClient_+1);
+  size_t nbHashIndexMax = std::numeric_limits<size_t>::max();
+  size_t nbHashIndex;
+  indexClientHash_[0] = 0;
+  for (int i = 1; i < nbClient_; ++i)
+  {
+    nbHashIndex = nbHashIndexMax / nbClient_;
+    if (i < (nbHashIndexMax%nbClient_)) ++nbHashIndex;
+    indexClientHash_[i] = indexClientHash_[i-1] + nbHashIndex;
+  }
+  indexClientHash_[nbClient_] = nbHashIndexMax;
+}
+
+void CClientServerMappingDistributed::computeDistributedServerIndex(const boost::unordered_map<size_t,int>& globalIndexOfServer,
+                                                                    const MPI_Comm& clientIntraComm)
+{
+  computeHashIndex();
+  int clientRank;
+  MPI_Comm_rank(clientIntraComm,&clientRank);
+
+  int* sendBuff = new int[nbClient_];
+  int* sendNbIndexBuff = new int[nbClient_];
+  for (int i = 0; i < nbClient_; ++i)
+  {
+    sendBuff[i] = 0; sendNbIndexBuff[i] = 0;
+  }
+
+  // Compute size of sending and receving buffer
+  std::map<int, std::vector<size_t> > client2ClientIndexGlobal;
+  std::map<int, std::vector<int> > client2ClientIndexServer;
+
+  std::vector<size_t>::const_iterator itbClientHash = indexClientHash_.begin(), itClientHash,
+                                      iteClientHash = indexClientHash_.end();
+  boost::unordered_map<size_t,int>::const_iterator it  = globalIndexOfServer.begin(),
+                                                   ite = globalIndexOfServer.end();
+  boost::hash<size_t> hashGlobalIndex;
+  for (; it != ite; ++it)
+  {
+    size_t hashIndex = hashGlobalIndex(it->first);
+    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashIndex);
+    if (itClientHash != iteClientHash)
+    {
+      int indexClient = std::distance(itbClientHash, itClientHash)-1;
+      if (clientRank == indexClient)
+      {
+        globalIndexToServerMapping_.insert(std::make_pair<size_t,int>(it->first, it->second));
+      }
+      else
+      {
+        sendBuff[indexClient] = 1;
+        ++sendNbIndexBuff[indexClient];
+        client2ClientIndexGlobal[indexClient].push_back(it->first);
+        client2ClientIndexServer[indexClient].push_back(it->second);
+      }
+    }
+  }
+
+
+//    for (boost::unordered_map<size_t,int>::const_iterator it = globalIndexToServerMapping_.begin();
+//       it != globalIndexToServerMapping_.end(); ++it)
+//       std::cout << " " << it->first << ":" << it->second;
+//       std::cout << "First Number = " << globalIndexToServerMapping_.size() << std::endl;
+
+
+  int* recvBuff = new int[nbClient_];
+  MPI_Allreduce(sendBuff, recvBuff, nbClient_, MPI_INT, MPI_SUM, clientIntraComm);
+
+  int* recvNbIndexBuff = new int[nbClient_];
+  MPI_Allreduce(sendNbIndexBuff, recvNbIndexBuff, nbClient_, MPI_INT, MPI_SUM, clientIntraComm);
+
+  MPI_Status statusIndexGlobal, statusIndexServer;
+  int flag, countIndexGlobal_ = 0, countIndexServer_ = 0;
+
+
+  std::map<int, MPI_Request>::iterator itRequestIndexGlobal, itRequestIndexServer;
+  std::map<int, int> countBuffIndexServer, countBuffIndexGlobal;
+  std::vector<int> processedList;
+
+
+  bool isFinished=false;
+  int recvNbIndexCount = recvNbIndexBuff[clientRank];
+  int recvNbClient = recvBuff[clientRank];
+  unsigned long* recvIndexGlobalBuff = new unsigned long[recvNbIndexCount];
+  int* recvIndexServerBuff = new int[recvNbIndexCount];
+
+  std::list<MPI_Request> sendRequest;
+  std::map<int, std::vector<size_t> >::iterator itGlobal  = client2ClientIndexGlobal.begin(),
+                                                iteGlobal = client2ClientIndexGlobal.end();
+  for ( ; itGlobal != iteGlobal; ++itGlobal)
+    sendIndexGlobalToClients(itGlobal->first, itGlobal->second, clientIntraComm, sendRequest);
+  std::map<int, std::vector<int> >::iterator itServer  = client2ClientIndexServer.begin(),
+                                             iteServer = client2ClientIndexServer.end();
+  for (; itServer != iteServer; ++itServer)
+    sendIndexServerToClients(itServer->first, itServer->second, clientIntraComm, sendRequest);
+
+  resetRequestAndCount();
+  while (!isFinished || (!sendRequest.empty()))
+  {
+    testSendRequest(sendRequest);
+    probeIndexGlobalMessageFromClients(recvIndexGlobalBuff, recvNbIndexCount);
+
+    // Processing complete request
+    for (itRequestIndexGlobal = requestRecvIndexGlobal_.begin();
+         itRequestIndexGlobal != requestRecvIndexGlobal_.end();
+         ++itRequestIndexGlobal)
+    {
+      int rank = itRequestIndexGlobal->first;
+      int countIndexGlobal = computeBuffCountIndexGlobal(itRequestIndexGlobal->second);
+      if (0 != countIndexGlobal)
+        countBuffIndexGlobal[rank] = countIndexGlobal;
+    }
+
+    probeIndexServerMessageFromClients(recvIndexServerBuff, recvNbIndexCount);
+    for (itRequestIndexServer = requestRecvIndexServer_.begin();
+         itRequestIndexServer != requestRecvIndexServer_.end();
+         ++itRequestIndexServer)
+    {
+      int rank = itRequestIndexServer->first;
+      int countIndexServer = computeBuffCountIndexServer(itRequestIndexServer->second);
+      if (0 != countIndexServer)
+        countBuffIndexServer[rank] = countIndexServer;
+    }
+
+    for (std::map<int, int>::iterator it = countBuffIndexGlobal.begin();
+                                      it != countBuffIndexGlobal.end(); ++it)
+    {
+      int rank = it->first;
+      if (countBuffIndexServer.end() != countBuffIndexServer.find(rank))
+      {
+        processReceivedRequest(indexGlobalBuffBegin_[rank], indexServerBuffBegin_[rank], it->second);
+        processedList.push_back(rank);
+        --recvNbClient;
+      }
+
+    }
+
+    for (int i = 0; i < processedList.size(); ++i)
+    {
+      requestRecvIndexServer_.erase(processedList[i]);
+      requestRecvIndexGlobal_.erase(processedList[i]);
+      countBuffIndexGlobal.erase(processedList[i]);
+      countBuffIndexServer.erase(processedList[i]);
+    }
+
+    if (0 == recvNbClient) isFinished = true;
+  }
+
+  delete [] sendBuff;
+  delete [] sendNbIndexBuff;
+  delete [] recvBuff;
+  delete [] recvNbIndexBuff;
+  delete [] recvIndexGlobalBuff;
+  delete [] recvIndexServerBuff;
+
+//    for (boost::unordered_map<size_t,int>::const_iterator it = globalIndexToServerMapping_.begin();
+//       it != globalIndexToServerMapping_.end(); ++it)
+//       std::cout << " " << it->first << ":" << it->second;
+//       std::cout << "Number = " << globalIndexToServerMapping_.size() << std::endl;
+
+}
+
+void CClientServerMappingDistributed::probeIndexGlobalMessageFromClients(unsigned long* recvIndexGlobalBuff, int recvNbIndexCount)
+{
+  MPI_Status statusIndexGlobal;
+  int flagIndexGlobal, count;
+
+  // Probing for global index
+  MPI_Iprobe(MPI_ANY_SOURCE, 15, clientIntraComm_, &flagIndexGlobal, &statusIndexGlobal);
+  if ((true == flagIndexGlobal) && (countIndexGlobal_ < recvNbIndexCount))
+  {
+    MPI_Get_count(&statusIndexGlobal, MPI_UNSIGNED_LONG, &count);
+    indexGlobalBuffBegin_.insert(std::make_pair<int, unsigned long*>(statusIndexGlobal.MPI_SOURCE, recvIndexGlobalBuff+countIndexGlobal_));
+    MPI_Irecv(recvIndexGlobalBuff+countIndexGlobal_, count, MPI_UNSIGNED_LONG,
+              statusIndexGlobal.MPI_SOURCE, 15, clientIntraComm_,
+              &requestRecvIndexGlobal_[statusIndexGlobal.MPI_SOURCE]);
+    countIndexGlobal_ += count;
+  }
+}
+
+void CClientServerMappingDistributed::probeIndexServerMessageFromClients(int* recvIndexServerBuff, int recvNbIndexCount)
+{
+  MPI_Status statusIndexServer;
+  int flagIndexServer, count;
+
+  // Probing for server index
+  MPI_Iprobe(MPI_ANY_SOURCE, 12, clientIntraComm_, &flagIndexServer, &statusIndexServer);
+  if ((true == flagIndexServer) && (countIndexServer_ < recvNbIndexCount))
+  {
+    MPI_Get_count(&statusIndexServer, MPI_INT, &count);
+    indexServerBuffBegin_.insert(std::make_pair<int, int*>(statusIndexServer.MPI_SOURCE, recvIndexServerBuff+countIndexServer_));
+    MPI_Irecv(recvIndexServerBuff+countIndexServer_, count, MPI_INT,
+              statusIndexServer.MPI_SOURCE, 12, clientIntraComm_,
+              &requestRecvIndexServer_[statusIndexServer.MPI_SOURCE]);
+
+    countIndexServer_ += count;
+  }
+}
+
+
+void CClientServerMappingDistributed::sendIndexGlobalToClients(int clientDestRank, std::vector<size_t>& indexGlobal,
+                                                               const MPI_Comm& clientIntraComm,
+                                                               std::list<MPI_Request>& requestSendIndexGlobal)
+{
+  MPI_Request request;
+  requestSendIndexGlobal.push_back(request);
+  MPI_Isend(&(indexGlobal)[0], (indexGlobal).size(), MPI_UNSIGNED_LONG,
+            clientDestRank, 15, clientIntraComm, &(requestSendIndexGlobal.back()));
+
+//  int nbSendClient = indexGlobal.size();
+//  std::map<int, std::vector<size_t> >::iterator
+//                        itClient2ClientIndexGlobal  = indexGlobal.begin(),
+//                        iteClient2ClientIndexGlobal = indexGlobal.end();
+//
+//  for (; itClient2ClientIndexGlobal != iteClient2ClientIndexGlobal;
+//         ++itClient2ClientIndexGlobal)
+//  {
+//    MPI_Request request;
+//    requestSendIndexGlobal.push_back(request);
+//    MPI_Isend(&(itClient2ClientIndexGlobal->second)[0],
+//              (itClient2ClientIndexGlobal->second).size(),
+//              MPI_UNSIGNED_LONG,
+//              itClient2ClientIndexGlobal->first,
+//              15, clientIntraComm, &(requestSendIndexGlobal.back()));
+//  }
+
+}
+
+void CClientServerMappingDistributed::sendIndexServerToClients(int clientDestRank, std::vector<int>& indexServer,
+                                                               const MPI_Comm& clientIntraComm,
+                                                               std::list<MPI_Request>& requestSendIndexServer)
+{
+  MPI_Request request;
+  requestSendIndexServer.push_back(request);
+  MPI_Isend(&(indexServer)[0], (indexServer).size(), MPI_INT,
+            clientDestRank, 12, clientIntraComm, &(requestSendIndexServer.back()));
+
+//  int nbSendClient = indexServer.size();
+//  std::map<int, std::vector<int> >::iterator
+//                        itClient2ClientIndexServer  = indexServer.begin(),
+//                        iteClient2ClientIndexServer = indexServer.end();
+
+//  for (; itClient2ClientIndexServer != iteClient2ClientIndexServer;
+//         ++itClient2ClientIndexServer)
+//  {
+//    MPI_Request request;
+//    requestSendIndexServer.push_back(request);
+//    MPI_Isend(&(itClient2ClientIndexServer->second)[0],
+//              (itClient2ClientIndexServer->second).size(),
+//              MPI_INT,
+//              itClient2ClientIndexServer->first,
+//              12, clientIntraComm, &(requestSendIndexServer.back()));
+//
+//  }
+}
+
+void CClientServerMappingDistributed::testSendRequest(std::list<MPI_Request>& sendRequest)
+{
+  int flag = 0;
+  MPI_Status status;
+  std::list<MPI_Request>::iterator itRequest;
+  int sizeListRequest = sendRequest.size();
+  int idx = 0;
+  while (idx < sizeListRequest)
+  {
+    bool isErased = false;
+    for (itRequest = sendRequest.begin(); itRequest != sendRequest.end(); ++itRequest)
+    {
+      MPI_Test(&(*itRequest), &flag, &status);
+      if (true == flag)
+      {
+        --sizeListRequest;
+        isErased = true;
+        break;
+      }
+    }
+    if (true == isErased) sendRequest.erase(itRequest);
+    ++idx;
+  }
+}
+
+void CClientServerMappingDistributed::processReceivedRequest(unsigned long* buffIndexGlobal, int* buffIndexServer, int count)
+{
+  for (int i = 0; i < count; ++i)
+    globalIndexToServerMapping_.insert(std::make_pair<size_t,int>(*(buffIndexGlobal+i),*(buffIndexServer+i)));
+}
+
+int CClientServerMappingDistributed::computeBuffCountIndexGlobal(MPI_Request& requestRecv)
+{
+  int flag, count = 0;
+  MPI_Status status;
+
+  MPI_Test(&requestRecv, &flag, &status);
+  if (true == flag)
+  {
+    MPI_Get_count(&status, MPI_UNSIGNED_LONG, &count);
+  }
+
+  return count;
+}
+
+int CClientServerMappingDistributed::computeBuffCountIndexServer(MPI_Request& requestRecv)
+{
+  int flag, count = 0;
+  MPI_Status status;
+
+  MPI_Test(&requestRecv, &flag, &status);
+  if (true == flag)
+  {
+    MPI_Get_count(&status, MPI_INT, &count);
+  }
+
+  return count;
+}
+
+void CClientServerMappingDistributed::resetRequestAndCount()
+{
+  countIndexGlobal_ = countIndexServer_ = 0;
+  requestRecvIndexGlobal_.clear();
+  requestRecvIndexServer_.clear();
+  indexGlobalBuffBegin_.clear();
+  indexServerBuffBegin_.clear();
+}
+
+}
Index: XIOS/trunk/src/client_server_mapping_distributed.hpp
===================================================================
--- XIOS/trunk/src/client_server_mapping_distributed.hpp	(revision 568)
+++ XIOS/trunk/src/client_server_mapping_distributed.hpp	(revision 568)
@@ -0,0 +1,87 @@
+#ifndef __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
+#define __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
+
+#include <client_server_mapping.hpp>
+#include "xmlioserver_spl.hpp"
+#include "array_new.hpp"
+#include "mpi.hpp"
+#include <boost/unordered_map.hpp>
+
+namespace xios
+{
+
+class CClientServerMappingDistributed : public CClientServerMapping
+{
+  public:
+    /** Default constructor */
+    CClientServerMappingDistributed(const boost::unordered_map<size_t,int>& globalIndexOfServer,
+                                    const MPI_Comm& clientIntraComm);
+
+    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient,
+                                           const CArray<int,1>& localIndexOnClient);
+
+    /** Default destructor */
+    virtual ~CClientServerMappingDistributed();
+
+  protected:
+    void computeDistributedServerIndex(const boost::unordered_map<size_t,int>& globalIndexOfServer,
+                                       const MPI_Comm& clientIntraComm);
+
+    void processReceivedRequest(unsigned long* buffIndexGlobal, int* buffIndexServer, int count);
+
+    void testSendRequest(std::list<MPI_Request>& sendRequest);
+
+    int computeBuffCount(MPI_Request& requestRecvIndexGlobal, MPI_Request& requestRecvIndexServer);
+
+    void computeHashIndex();
+
+//    void sendIndexServerToClients(std::map<int, std::vector<int> >& indexServer,
+//                                  const MPI_Comm& clientIntraComm,
+//                                  std::list<MPI_Request>& requestSendIndexServer);
+
+//    void sendIndexGlobalToClients(std::map<int, std::vector<size_t> >& indexGlobal,
+//                                  const MPI_Comm& clientIntraComm,
+//                                  std::list<MPI_Request>& requestSendIndexGlobal);
+
+    void sendIndexServerToClients(int clientDestRank, std::vector<int>& indexServer,
+                                  const MPI_Comm& clientIntraComm, std::list<MPI_Request>& requestSendIndexServer);
+
+    void sendIndexGlobalToClients(int clientDestRank, std::vector<size_t>& indexGlobal,
+                                  const MPI_Comm& clientIntraComm, std::list<MPI_Request>& requestSendIndexGlobal);
+
+    void resetRequestAndCount();
+
+    void probeIndexGlobalMessageFromClients(unsigned long* recvIndexGlobalBuff, int recvNbIndexCount);
+
+    void probeIndexServerMessageFromClients(int* recvIndexServerBuff, int recvNbIndexCount);
+
+    int computeBuffCountIndexGlobal(MPI_Request& requestRecv);
+
+    int computeBuffCountIndexServer(MPI_Request& requestRecv);
+  private:
+    boost::unordered_map<size_t,int> globalIndexToServerMapping_;
+
+    std::map<int, MPI_Request> requestRecvIndexGlobal_;
+
+    std::map<int, MPI_Request> requestRecvIndexServer_;
+
+    std::vector<size_t> indexClientHash_;
+
+    int nbClient_;
+
+    int clientRank_;
+
+    int countIndexGlobal_;
+
+    int countIndexServer_;
+
+    MPI_Comm clientIntraComm_;
+
+    std::map<int, unsigned long*> indexGlobalBuffBegin_;
+
+    std::map<int, int*> indexServerBuffBegin_;
+
+};
+
+} // namespace xios
+#endif // __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
Index: XIOS/trunk/src/node/axis.cpp
===================================================================
--- XIOS/trunk/src/node/axis.cpp	(revision 567)
+++ XIOS/trunk/src/node/axis.cpp	(revision 568)
@@ -109,5 +109,5 @@
    void CAxis::checkZoom(void)
    {
-      StdSize zoom_begin,zoom_end, zoom_size;
+      StdSize zoom_begin,zoom_end, zoom_size, axisSize;
 
       zoom_begin = (this->zoom_begin.isEmpty()) ?  0 : this->zoom_begin.getValue() ;
@@ -118,6 +118,7 @@
       if (this->zoom_end.isEmpty()) zoom_end=zoom_begin+zoom_size-1 ;
       if (this->zoom_size.isEmpty()) zoom_size=zoom_end-zoom_begin+1 ;
-
-      if ( (zoom_begin < 0) || (zoom_begin > size-1) || (zoom_end<0) || (zoom_end>size-1) || (zoom_size<1) || (zoom_size>size) || (zoom_begin>zoom_end))
+      axisSize = size.getValue();
+
+      if ( (zoom_begin < 0) || (zoom_begin > axisSize-1) || (zoom_end<0) || (zoom_end>axisSize-1) || (zoom_size<1) || (zoom_size>axisSize) || (zoom_begin>zoom_end))
         ERROR("CAxis::checkAttributes(void)",<< "One or more attribut of <zoom_begin>, <zoom_end>, <zoom_size>, are not well specified") ;
 
Index: XIOS/trunk/src/node/grid.cpp
===================================================================
--- XIOS/trunk/src/node/grid.cpp	(revision 567)
+++ XIOS/trunk/src/node/grid.cpp	(revision 568)
@@ -13,4 +13,5 @@
 #include "context_server.hpp"
 #include "array_new.hpp"
+#include "client_server_mapping_distributed.hpp"
 
 namespace xios {
@@ -22,5 +23,5 @@
       , isChecked(false), isDomainAxisChecked(false), storeIndex(1)
       , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
-      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(), writtenDataSize_(0), globalDim_()
+      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
    {
      setVirtualDomainGroup();
@@ -32,5 +33,5 @@
       , isChecked(false), isDomainAxisChecked(false), storeIndex(1)
       , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
-      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(), writtenDataSize_(0), globalDim_()
+      , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
    {
      setVirtualDomainGroup();
@@ -174,5 +175,5 @@
      StdSize retVal;
      std::map<int, StdSize> ret;
-     const std::map<int, std::vector<int> >& distribution = clientServerMap_.getLocalIndexSendToServer();
+     const std::map<int, std::vector<int> >& distribution = clientServerMap_->getLocalIndexSendToServer();
      std::map<int, std::vector<int> >::const_iterator it = distribution.begin(), itE = distribution.end();
      for (; it != itE; ++it)
@@ -280,12 +281,22 @@
       {
         int idx = 0;
+        std::vector<int> axisPositionMap;
+        for (int i = 0; i < axisDomainOrder.numElements(); ++i)
+        {
+          if (false == axisDomainOrder(i))
+          {
+            axisPositionMap.push_back(idx);
+            ++idx;
+          }
+          else idx += 2;
+        }
+
         computeGridGlobalDimension(getDomains(), getAxis(), axisDomainOrder);
         for (int i = 0; i < axisListP.size(); ++i)
         {
-          while (this->axisDomainOrder(idx)) idx += 2;
           if (sendAtt)
-            axisListP[i]->sendCheckedAttributes(globalDim_,idx);
+            axisListP[i]->sendCheckedAttributes(globalDim_,axisPositionMap[i]);
           else
-            axisListP[i]->checkAttributesOnClient(globalDim_,idx);
+            axisListP[i]->checkAttributesOnClient(globalDim_,axisPositionMap[i]);
           ++idx;
         }
@@ -303,19 +314,39 @@
      // First of all, compute distribution on client side
      clientDistribution_ = new CDistributionClient(client->clientRank, this);
+     size_t globalSizeIndex = 1, indexBegin, indexEnd;
+     int range, clientSize = client->clientSize;
+     for (int i = 0; i < globalDim_.size(); ++i) globalSizeIndex *= globalDim_[i];
+     indexBegin = 0;
+     for (int i = 0; i < clientSize; ++i)
+     {
+       range = globalSizeIndex / clientSize;
+       if (i < (globalSizeIndex%clientSize)) ++range;
+       if (i == client->clientRank) break;
+       indexBegin += range;
+     }
+     indexEnd = indexBegin + range - 1;
 
      // Then compute distribution on server side
      serverDistributionDescription_ = new CServerDistributionDescription(clientDistribution_->getNGlob());
      serverDistributionDescription_->computeServerDistribution(client->serverSize, true);
+     serverDistributionDescription_->computeServerGlobalIndexInRange(client->serverSize,
+                                                                     std::make_pair<size_t,size_t>(indexBegin, indexEnd));
 
      // Finally, compute index mapping between client(s) and server(s)
-     clientServerMap_.computeServerIndexMapping(clientDistribution_->getGlobalIndex(),
-                                                clientDistribution_->getLocalDataIndexSendToServerOnClient(),
-                                                serverDistributionDescription_->getGlobalIndex());
-     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_.getGlobalIndexOnServer();
+     clientServerMap_ = new CClientServerMappingDistributed(serverDistributionDescription_->getGlobalIndexRange(),
+                                                            client->intraComm);
+
+     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex(),
+                                                 clientDistribution_->getLocalDataIndexSendToServerOnClient());
+
+//     clientServerMap_->computeServerIndexMapping(clientDistribution_->getGlobalIndex(),
+//                                                 clientDistribution_->getLocalDataIndexSendToServerOnClient(),
+//                                                 serverDistributionDescription_->getGlobalIndex());
+     const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
      std::vector<int> connectedServerRank;
      for (std::map<int, std::vector<size_t> >::const_iterator it = globalIndexOnServer.begin(); it != globalIndexOnServer.end(); ++it) {
        connectedServerRank.push_back(it->first);
      }
-     nbSenders = clientServerMap_.computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank);
+     nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank);
 
      // Get local data index on client
@@ -415,6 +446,6 @@
     list<shared_ptr<CMessage> > list_msg ;
     list< CArray<size_t,1>* > listOutIndex;
-    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_.getGlobalIndexOnServer();
-    const std::map<int, std::vector<int> >& localIndexSendToServer  = clientServerMap_.getLocalIndexSendToServer();
+    const std::map<int, std::vector<size_t> >& globalIndexOnServer = clientServerMap_->getGlobalIndexOnServer();
+    const std::map<int, std::vector<int> >& localIndexSendToServer  = clientServerMap_->getLocalIndexSendToServer();
 
     std::map<int, std::vector<size_t> >::const_iterator iteMap, itbMap, itGlobal;
Index: XIOS/trunk/src/node/grid.hpp
===================================================================
--- XIOS/trunk/src/node/grid.hpp	(revision 567)
+++ XIOS/trunk/src/node/grid.hpp	(revision 568)
@@ -221,5 +221,5 @@
         CDistributionServer* serverDistribution_;
         CServerDistributionDescription* serverDistributionDescription_;
-        CClientServerMapping clientServerMap_;
+        CClientServerMapping* clientServerMap_;
         size_t writtenDataSize_;
    }; // class CGrid
Index: XIOS/trunk/src/server_distribution_description.cpp
===================================================================
--- XIOS/trunk/src/server_distribution_description.cpp	(revision 567)
+++ XIOS/trunk/src/server_distribution_description.cpp	(revision 568)
@@ -13,5 +13,5 @@
 {
 CServerDistributionDescription::CServerDistributionDescription(const std::vector<int>& globalDimensionSize)
-  : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(0), vecGlobalIndex_()
+  : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(), vecGlobalIndex_()
 {
 
@@ -20,5 +20,5 @@
 CServerDistributionDescription::~CServerDistributionDescription()
 {
-  if (0 != globalIndex_) delete globalIndex_;
+//  if (0 != globalIndex_) delete globalIndex_;
   if (!vecGlobalIndex_.empty())
     for (int i = 0; i < vecGlobalIndex_.size(); ++i) delete vecGlobalIndex_[i];
@@ -92,4 +92,69 @@
 }
 
+void CServerDistributionDescription::computeServerGlobalIndexInRange(int nServer,
+                                        const std::pair<size_t, size_t>& indexBeginEnd,
+                                        ServerDistributionType distributionType)
+{
+  switch (distributionType) {
+    case BAND_DISTRIBUTION:
+      computeBandDistribution(nServer);
+      break;
+    default:
+      break;
+  }
+
+  size_t indexBegin = indexBeginEnd.first;
+  size_t indexEnd   = indexBeginEnd.second;
+  if (indexBegin > indexEnd)
+     ERROR("CServerDistributionDescription::computeServerGlobalIndexInRange",
+           << "Index begin is larger than index end");
+
+  int dim = nGlobal_.size();
+  std::vector<int> currentIndex(dim);
+
+  for (int idxServer = 0; idxServer < nServer; ++idxServer)
+  {
+    size_t ssize = 1, idx = 0;
+    for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
+    vecGlobalIndex_[idxServer] = new CArray<size_t,1>(ssize);
+
+    std::vector<int> idxLoop(dim,0);
+
+    int innerLoopSize = dimensionSizes_[idxServer][0];
+
+    while (idx<ssize)
+    {
+      for (int idxDim = 0; idxDim < dim-1; ++idxDim)
+      {
+        if (idxLoop[idxDim] == dimensionSizes_[idxServer][idxDim])
+        {
+          idxLoop[idxDim] = 0;
+          ++idxLoop[idxDim+1];
+        }
+      }
+
+      for (int idxDim = 1; idxDim < dim; ++idxDim)  currentIndex[idxDim] = idxLoop[idxDim] + indexBegin_[idxServer][idxDim];
+
+      size_t mulDim, globalIndex;
+      for (int j = 0; j < innerLoopSize; ++j)
+      {
+        mulDim = 1;
+        globalIndex = j + indexBegin_[idxServer][0];
+
+        for (int k = 1; k < dim; ++k)
+        {
+          mulDim *= nGlobal_[k-1];
+          globalIndex += (currentIndex[k])*mulDim;
+        }
+        if ((indexBegin <= globalIndex) && (globalIndex <= indexEnd))
+          globalIndex_.insert(std::make_pair<size_t,int>(globalIndex, idxServer));
+        ++idx;
+      }
+      idxLoop[0] += innerLoopSize;
+    }
+  }
+
+}
+
 /*!
   Compute global index of servers with band distribution
@@ -178,3 +243,7 @@
 }
 
+const boost::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
+{
+  return globalIndex_;
+}
 } // namespace xios
Index: XIOS/trunk/src/server_distribution_description.hpp
===================================================================
--- XIOS/trunk/src/server_distribution_description.hpp	(revision 567)
+++ XIOS/trunk/src/server_distribution_description.hpp	(revision 568)
@@ -13,4 +13,5 @@
 #include "xmlioserver_spl.hpp"
 #include "array_new.hpp"
+#include <boost/unordered_map.hpp>
 
 namespace xios
@@ -36,10 +37,12 @@
                                    ServerDistributionType type = BAND_DISTRIBUTION);
 
-    const CArray<size_t,1>& computeServerGlobalIndex(int nServer, int serverRank,
-                                                     ServerDistributionType = BAND_DISTRIBUTION);
+    void computeServerGlobalIndexInRange(int nServer,
+                                         const std::pair<size_t, size_t>& indexBeginEnd,
+                                         ServerDistributionType = BAND_DISTRIBUTION);
 
     std::vector<std::vector<int> > getServerIndexBegin() const;
     std::vector<std::vector<int> > getServerDimensionSizes() const;
     const std::vector<CArray<size_t,1>* >& getGlobalIndex() const;
+    const boost::unordered_map<size_t,int>& getGlobalIndexRange() const;
 
   protected:
@@ -56,5 +59,5 @@
 
     //!< In case we need only global index of one server with specific rank
-    CArray<size_t,1>* globalIndex_;
+    boost::unordered_map<size_t,int> globalIndex_;
 };
 
