Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/array_new.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/array_new.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/array_new.hpp	(revision 1918)
@@ -567,4 +567,5 @@
       virtual bool isEmpty(void) const { return !initialized; }
       virtual size_t size(void) const { return size(this->numElements()); }
+      virtual std::vector<T_numtype> getVector(void) { return vector<T_numtype>(this->dataFirst(),this->dataFirst()+this->numElements()) ;}
       static size_t size(sizeType numElements) { return (N_rank + 1) * sizeof(int) + sizeof(size_t) + numElements * sizeof(T_numtype); }
       
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_decl.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_decl.cpp	(revision 1917)
+++ 	(revision )
@@ -1,19 +1,0 @@
-/*!
-   \file client_client_dht.cpp
-   \author Ha NGUYEN
-   \since 05 Oct 2015
-   \date 23 Mars 2016
-
-   \brief Distributed hashed table implementation.
- */
-#include "client_client_dht_template_impl.hpp"
-
-namespace xios
-{
-
-template class CClientClientDHTTemplate<int>;
-template class CClientClientDHTTemplate<size_t>;
-template class CClientClientDHTTemplate<double>;
-template class CClientClientDHTTemplate<PairIntInt>;
-
-}
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_template.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_template.hpp	(revision 1917)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*!
-   \file client_client_dht_template.hpp
-   \author Ha NGUYEN
-   \since 01 Oct 2015
-   \date 15 April 2016
-
-   \brief Distributed hashed table implementation.
- */
-
-#ifndef __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
-#define __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
-
-#include "xios_spl.hpp"
-#include "array_new.hpp"
-#include "mpi.hpp"
-#include "policy.hpp"
-#include  <unordered_map>
-#include "dht_data_types.hpp"
-
-namespace xios
-{
-template<typename T, class HierarchyPolicy = DivideAdaptiveComm> class CClientClientDHTTemplate;
-
-/*!
-  \class CClientClientDHTTemplate
-  This class provides the similar features like \class CClientServerMappingDistributed,
-which implements a simple distributed hashed table; Moreover, by extending with hierarchical structure,
-it allows to reduce greatly the number of communication among processes.
-*/
-template<typename T, typename HierarchyPolicy>
-class CClientClientDHTTemplate: public HierarchyPolicy
-{
-  public:
-    typedef T InfoType;
-    static const int infoTypeSize = sizeof(InfoType);
-//    typedef typename std::unordered_map<InfoType, std::vector<size_t> > InfoType2IndexMap;
-    typedef typename std::unordered_map<size_t,InfoType> Index2InfoTypeMap;
-    typedef typename std::unordered_map<size_t,std::vector<InfoType> > Index2VectorInfoTypeMap;
-
-  public:
-    CClientClientDHTTemplate(const Index2InfoTypeMap& indexInfoInitMap,
-                             const MPI_Comm& clientIntraComm);
-
-    CClientClientDHTTemplate(const Index2VectorInfoTypeMap& indexInfoInitMap,
-                             const MPI_Comm& clientIntraComm);
-
-    void computeIndexInfoMapping(const CArray<size_t,1>& indices);
-
-    const Index2VectorInfoTypeMap& getInfoIndexMap() const {return indexToInfoMappingLevel_; }
-    Index2VectorInfoTypeMap& getInfoIndexMap() {return indexToInfoMappingLevel_; }
-    int getNbClient() { return nbClient_; }
-
-    /** Default destructor */
-    virtual ~CClientClientDHTTemplate();
-
-  protected:
-    CClientClientDHTTemplate(const MPI_Comm& clientIntraComm);
-
-  protected:
-
-
-    // Redistribute index and info among clients
-    void computeDistributedIndex(const Index2InfoTypeMap& indexInfoInitMap,
-                                 const MPI_Comm& intraCommLevel,
-                                 int level);
-
-    void computeDistributedIndex(const Index2VectorInfoTypeMap& indexInfoInitMap,
-                                 const MPI_Comm& intraCommLevel,
-                                 int level);
-
-
-    void computeHashIndex(std::vector<size_t>& indexClientHash, int nbClient);
-
-    void computeIndexInfoMappingLevel(const CArray<size_t,1>& indices,
-                                      const MPI_Comm& intraCommLevel,
-                                      int level);
-
-    void computeSendRecvRank(int level, int rank);
-
-    void sendRecvRank(int level,
-                      const std::vector<int>& sendNbRank, const std::vector<int>& sendNbElements,
-                      std::vector<int>& recvNbRank, std::vector<int>& recvNbElements);
-
-  protected:
-    // Send information to clients
-    void sendInfoToClients(int clientDestRank, unsigned char* info, int infoSize,
-                           const MPI_Comm& clientIntraComm,
-                           std::vector<MPI_Request>& requestSendInfo);
-
-    void recvInfoFromClients(int clientSrcRank, unsigned char* info, int infoSize,
-                            const MPI_Comm& clientIntraComm,
-                            std::vector<MPI_Request>& requestRecvInfo);
-
-    // Send global index to clients
-    void sendIndexToClients(int clientDestRank, size_t* indices, size_t indiceSize,
-                            const MPI_Comm& clientIntraComm,
-                            std::vector<MPI_Request>& requestSendIndexGlobal);
-
-    void recvIndexFromClients(int clientSrcRank, size_t* indices, size_t indiceSize,
-                             const MPI_Comm& clientIntraComm,
-                             std::vector<MPI_Request>& requestRecvIndex);
-
-    void sendRecvOnReturn(const std::vector<int>& sendNbRank, std::vector<int>& sendNbElements,
-                          const std::vector<int>& recvNbRank, std::vector<int>& recvNbElements);
-
-  protected:
-    //! Mapping of global index to the corresponding client
-    Index2VectorInfoTypeMap index2InfoMapping_;
-
-    //! A mapping of index to the corresponding information in each level of hierarchy
-    Index2VectorInfoTypeMap indexToInfoMappingLevel_;
-
-    //! Rank of client to send on each DHT level
-    std::vector<std::vector<int> > sendRank_;
-
-    //! Rank of client to receive on each DHT level
-    std::vector<std::vector<int> > recvRank_;
-
-    //! Flag to specify whether data is distributed or not
-    bool isDataDistributed_;
-
-    //! Number of client
-    int nbClient_;
-};
-
-typedef CClientClientDHTTemplate<int> CClientClientDHTInt;
-typedef CClientClientDHTTemplate<size_t> CClientClientDHTSizet;
-typedef CClientClientDHTTemplate<double> CClientClientDHTDouble;
-typedef CClientClientDHTTemplate<PairIntInt> CClientClientDHTPairIntInt;
-
-} // namespace xios
-#endif // __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_template_impl.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_client_dht_template_impl.hpp	(revision 1917)
+++ 	(revision )
@@ -1,737 +1,0 @@
-/*!
-   \file client_client_dht_template_impl.hpp
-   \author Ha NGUYEN
-   \since 05 Oct 2015
-   \date 23 Mars 2016
-
-   \brief Distributed hashed table implementation.
- */
-#include "client_client_dht_template.hpp"
-#include "utils.hpp"
-#include "mpi_tag.hpp"
-
-namespace xios
-{
-template<typename T, typename H>
-CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const MPI_Comm& clientIntraComm)
-  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
-{
-  MPI_Comm_size(clientIntraComm, &nbClient_);
-  this->computeMPICommLevel();
-  int nbLvl = this->getNbLevel();
-  sendRank_.resize(nbLvl);
-  recvRank_.resize(nbLvl);
-}
-
-/*!
-  Constructor with initial distribution information and the corresponding index
-  Each client (process) holds a piece of information as well as the attached index, the index
-will be redistributed (projected) into size_t space as long as the associated information.
-  \param [in] indexInfoMap initial index and information mapping
-  \param [in] clientIntraComm communicator of clients
-  \param [in] hierarLvl level of hierarchy
-*/
-template<typename T, typename H>
-CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const Index2InfoTypeMap& indexInfoMap,
-                                                        const MPI_Comm& clientIntraComm)
-  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
-{
-  MPI_Comm_size(clientIntraComm, &nbClient_);
-  this->computeMPICommLevel();
-  int nbLvl = this->getNbLevel();
-  sendRank_.resize(nbLvl);
-  recvRank_.resize(nbLvl);
-  Index2VectorInfoTypeMap indexToVecInfoMap;
-  indexToVecInfoMap.rehash(std::ceil(indexInfoMap.size()/indexToVecInfoMap.max_load_factor()));
-  typename Index2InfoTypeMap::const_iterator it = indexInfoMap.begin(), ite = indexInfoMap.end();
-  for (; it != ite; ++it) indexToVecInfoMap[it->first].push_back(it->second);
-  computeDistributedIndex(indexToVecInfoMap, clientIntraComm, nbLvl-1);
-}
-
-/*!
-  Constructor with initial distribution information and the corresponding index
-  Each client (process) holds a piece of information as well as the attached index, the index
-will be redistributed (projected) into size_t space as long as the associated information.
-  \param [in] indexInfoMap initial index and information mapping
-  \param [in] clientIntraComm communicator of clients
-  \param [in] hierarLvl level of hierarchy
-*/
-template<typename T, typename H>
-CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const Index2VectorInfoTypeMap& indexInfoMap,
-                                                        const MPI_Comm& clientIntraComm)
-  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
-{
-  MPI_Comm_size(clientIntraComm, &nbClient_);
-  this->computeMPICommLevel();
-  int nbLvl = this->getNbLevel();
-  sendRank_.resize(nbLvl);
-  recvRank_.resize(nbLvl);
-  computeDistributedIndex(indexInfoMap, clientIntraComm, nbLvl-1);
-}
-
-template<typename T, typename H>
-CClientClientDHTTemplate<T,H>::~CClientClientDHTTemplate()
-{
-}
-
-/*!
-  Compute mapping between indices and information corresponding to these indices
-  \param [in] indices indices a proc has
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::computeIndexInfoMapping(const CArray<size_t,1>& indices)
-{
-  int nbLvl = this->getNbLevel();
-  computeIndexInfoMappingLevel(indices, this->internalComm_, nbLvl-1);
-}
-
-/*!
-    Compute mapping between indices and information corresponding to these indices
-for each level of hierarchical DHT. Recursive function
-   \param [in] indices indices a proc has
-   \param [in] commLevel communicator of current level
-   \param [in] level current level
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::computeIndexInfoMappingLevel(const CArray<size_t,1>& indices,
-                                                                 const MPI_Comm& commLevel,
-                                                                 int level)
-{
-  int clientRank;
-  MPI_Comm_rank(commLevel,&clientRank);
-  int groupRankBegin = this->getGroupBegin()[level];
-  int nbClient = this->getNbInGroup()[level];
-  std::vector<size_t> hashedIndex;
-  computeHashIndex(hashedIndex, nbClient);
-
-  size_t ssize = indices.numElements(), hashedVal;
-
-  std::vector<size_t>::const_iterator itbClientHash = hashedIndex.begin(), itClientHash,
-                                      iteClientHash = hashedIndex.end();
-  std::vector<int> sendBuff(nbClient,0);
-  std::vector<int> sendNbIndexBuff(nbClient,0);
-
-  // Number of global index whose mapping server are on other clients
-  int nbIndexToSend = 0;
-  size_t index;
-  HashXIOS<size_t> hashGlobalIndex;
-  std::unordered_map<size_t,int> nbIndices;
-  nbIndices.rehash(std::ceil(ssize/nbIndices.max_load_factor()));
-  for (int i = 0; i < ssize; ++i)
-  {
-    index = indices(i);
-    if (0 == nbIndices.count(index))
-    {
-      hashedVal  = hashGlobalIndex(index);
-      itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashedVal);
-      int indexClient = std::distance(itbClientHash, itClientHash)-1;
-      ++sendNbIndexBuff[indexClient];
-      nbIndices[index] = 1;
-    }
-  }
-
-  std::unordered_map<int, size_t* > client2ClientIndex;
-  for (int idx = 0; idx < nbClient; ++idx)
-  {
-    if (0 != sendNbIndexBuff[idx])
-    {
-      client2ClientIndex[idx+groupRankBegin] = new unsigned long [sendNbIndexBuff[idx]];
-      nbIndexToSend += sendNbIndexBuff[idx];
-      sendBuff[idx] = 1;
-      sendNbIndexBuff[idx] = 0;
-    }
-  }
-
-  for (int i = 0; i < ssize; ++i)
-  {
-    index = indices(i);
-    if (1 == nbIndices[index])
-    {
-      hashedVal  = hashGlobalIndex(index);
-      itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashedVal);
-      int indexClient = std::distance(itbClientHash, itClientHash)-1;
-      client2ClientIndex[indexClient+groupRankBegin][sendNbIndexBuff[indexClient]] = index;
-      ++sendNbIndexBuff[indexClient];
-      ++nbIndices[index];
-    }
-  }
-
-  std::vector<int> recvRankClient, recvNbIndexClientCount;
-  sendRecvRank(level, sendBuff, sendNbIndexBuff,
-               recvRankClient, recvNbIndexClientCount);
-
-  int recvNbIndexCount = 0;
-  for (int idx = 0; idx < recvNbIndexClientCount.size(); ++idx)
-    recvNbIndexCount += recvNbIndexClientCount[idx];
-
-  unsigned long* recvIndexBuff;
-  if (0 != recvNbIndexCount)
-    recvIndexBuff = new unsigned long[recvNbIndexCount];
-
-  std::vector<MPI_Request> request;
-  std::vector<int>::iterator itbRecvIndex = recvRankClient.begin(), itRecvIndex,
-                             iteRecvIndex = recvRankClient.end(),
-                           itbRecvNbIndex = recvNbIndexClientCount.begin(),
-                           itRecvNbIndex;
-  int currentIndex = 0;
-  int nbRecvClient = recvRankClient.size();
-  for (int idx = 0; idx < nbRecvClient; ++idx)
-  {
-    if (0 != recvNbIndexClientCount[idx])
-      recvIndexFromClients(recvRankClient[idx], recvIndexBuff+currentIndex, recvNbIndexClientCount[idx], commLevel, request);
-    currentIndex += recvNbIndexClientCount[idx];
-  }
-
-  std::unordered_map<int, size_t* >::iterator itbIndex = client2ClientIndex.begin(), itIndex,
-                                                iteIndex = client2ClientIndex.end();
-  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
-    sendIndexToClients(itIndex->first, (itIndex->second), sendNbIndexBuff[itIndex->first-groupRankBegin], commLevel, request);
-
-  std::vector<MPI_Status> status(request.size());
-  MPI_Waitall(request.size(), &request[0], &status[0]);
-
-  CArray<size_t,1>* tmpGlobalIndex;
-  if (0 != recvNbIndexCount)
-    tmpGlobalIndex = new CArray<size_t,1>(recvIndexBuff, shape(recvNbIndexCount), neverDeleteData);
-  else
-    tmpGlobalIndex = new CArray<size_t,1>();
-
-  // OK, we go to the next level and do something recursive
-  if (0 < level)
-  {
-    --level;
-    computeIndexInfoMappingLevel(*tmpGlobalIndex, this->internalComm_, level);
-  }
-  else // Now, we are in the last level where necessary mappings are.
-    indexToInfoMappingLevel_= (index2InfoMapping_);
-
-  typename Index2VectorInfoTypeMap::const_iterator iteIndexToInfoMap = indexToInfoMappingLevel_.end(), itIndexToInfoMap;
-  std::vector<int> sendNbIndexOnReturn(nbRecvClient,0);
-  currentIndex = 0;
-  for (int idx = 0; idx < nbRecvClient; ++idx)
-  {
-    for (int i = 0; i < recvNbIndexClientCount[idx]; ++i)
-    {
-      itIndexToInfoMap = indexToInfoMappingLevel_.find(*(recvIndexBuff+currentIndex+i));
-      if (iteIndexToInfoMap != itIndexToInfoMap)
-        sendNbIndexOnReturn[idx] += itIndexToInfoMap->second.size();
-    }
-    currentIndex += recvNbIndexClientCount[idx];
-  }
-
-  std::vector<int> recvRankOnReturn(client2ClientIndex.size());
-  std::vector<int> recvNbIndexOnReturn(client2ClientIndex.size(),0);
-  int indexIndex = 0;
-  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex, ++indexIndex)
-  {
-    recvRankOnReturn[indexIndex] = itIndex->first;
-  }
-  sendRecvOnReturn(recvRankClient, sendNbIndexOnReturn,
-                   recvRankOnReturn, recvNbIndexOnReturn);
-
-  int recvNbIndexCountOnReturn = 0;
-  for (int idx = 0; idx < recvRankOnReturn.size(); ++idx)
-    recvNbIndexCountOnReturn += recvNbIndexOnReturn[idx];
-
-  unsigned long* recvIndexBuffOnReturn;
-  unsigned char* recvInfoBuffOnReturn;
-  if (0 != recvNbIndexCountOnReturn)
-  {
-    recvIndexBuffOnReturn = new unsigned long[recvNbIndexCountOnReturn];
-    recvInfoBuffOnReturn = new unsigned char[recvNbIndexCountOnReturn*ProcessDHTElement<InfoType>::typeSize()];
-  }
-
-  std::vector<MPI_Request> requestOnReturn;
-  currentIndex = 0;
-  for (int idx = 0; idx < recvRankOnReturn.size(); ++idx)
-  {
-    if (0 != recvNbIndexOnReturn[idx])
-    {
-      recvIndexFromClients(recvRankOnReturn[idx], recvIndexBuffOnReturn+currentIndex, recvNbIndexOnReturn[idx], commLevel, requestOnReturn);
-      recvInfoFromClients(recvRankOnReturn[idx],
-                          recvInfoBuffOnReturn+currentIndex*ProcessDHTElement<InfoType>::typeSize(),
-                          recvNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize(),
-                          commLevel, requestOnReturn);
-    }
-    currentIndex += recvNbIndexOnReturn[idx];
-  }
-
-  std::unordered_map<int,unsigned char*> client2ClientInfoOnReturn;
-  std::unordered_map<int,size_t*> client2ClientIndexOnReturn;
-  currentIndex = 0;
-  for (int idx = 0; idx < nbRecvClient; ++idx)
-  {
-    if (0 != sendNbIndexOnReturn[idx])
-    {
-      int rank = recvRankClient[idx];
-      client2ClientIndexOnReturn[rank] = new unsigned long [sendNbIndexOnReturn[idx]];
-      client2ClientInfoOnReturn[rank] = new unsigned char [sendNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize()];
-      unsigned char* tmpInfoPtr = client2ClientInfoOnReturn[rank];
-      int infoIndex = 0;
-      int nb = 0;
-      for (int i = 0; i < recvNbIndexClientCount[idx]; ++i)
-      {
-        itIndexToInfoMap = indexToInfoMappingLevel_.find(*(recvIndexBuff+currentIndex+i));
-        if (iteIndexToInfoMap != itIndexToInfoMap)
-        {
-          const std::vector<InfoType>& infoTmp = itIndexToInfoMap->second;
-          for (int k = 0; k < infoTmp.size(); ++k)
-          {
-            client2ClientIndexOnReturn[rank][nb] = itIndexToInfoMap->first;
-            ProcessDHTElement<InfoType>::packElement(infoTmp[k], tmpInfoPtr, infoIndex);
-            ++nb;
-          }
-        }
-      }
-
-      sendIndexToClients(rank, client2ClientIndexOnReturn[rank],
-                         sendNbIndexOnReturn[idx], commLevel, requestOnReturn);
-      sendInfoToClients(rank, client2ClientInfoOnReturn[rank],
-                        sendNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize(), commLevel, requestOnReturn);
-    }
-    currentIndex += recvNbIndexClientCount[idx];
-  }
-
-  std::vector<MPI_Status> statusOnReturn(requestOnReturn.size());
-  MPI_Waitall(requestOnReturn.size(), &requestOnReturn[0], &statusOnReturn[0]);
-
-  Index2VectorInfoTypeMap indexToInfoMapping;
-  indexToInfoMapping.rehash(std::ceil(recvNbIndexCountOnReturn/indexToInfoMapping.max_load_factor()));
-  int infoIndex = 0;
-  InfoType unpackedInfo;
-  for (int idx = 0; idx < recvNbIndexCountOnReturn; ++idx)
-  {
-    ProcessDHTElement<InfoType>::unpackElement(unpackedInfo, recvInfoBuffOnReturn, infoIndex);
-    indexToInfoMapping[recvIndexBuffOnReturn[idx]].push_back(unpackedInfo);
-  }
-
-  indexToInfoMappingLevel_.swap(indexToInfoMapping);
-  if (0 != recvNbIndexCount) delete [] recvIndexBuff;
-  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndex.begin();
-                                                        it != client2ClientIndex.end(); ++it)
-      delete [] it->second;
-  delete tmpGlobalIndex;
-
-  if (0 != recvNbIndexCountOnReturn)
-  {
-    delete [] recvIndexBuffOnReturn;
-    delete [] recvInfoBuffOnReturn;
-  }
-
-  for (std::unordered_map<int,unsigned char*>::const_iterator it = client2ClientInfoOnReturn.begin();
-                                                               it != client2ClientInfoOnReturn.end(); ++it)
-      delete [] it->second;
-
-  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndexOnReturn.begin();
-                                            it != client2ClientIndexOnReturn.end(); ++it)
-      delete [] it->second;
-}
-
-/*!
-  Compute the hash index distribution of whole size_t space then each client will have a range of this distribution
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::computeHashIndex(std::vector<size_t>& hashedIndex, int nbClient)
-{
-  // Compute range of hash index for each client
-  hashedIndex.resize(nbClient+1);
-  size_t nbHashIndexMax = std::numeric_limits<size_t>::max();
-  size_t nbHashIndex;
-  hashedIndex[0] = 0;
-  for (int i = 1; i < nbClient; ++i)
-  {
-    nbHashIndex = nbHashIndexMax / nbClient;
-    if (i < (nbHashIndexMax%nbClient)) ++nbHashIndex;
-    hashedIndex[i] = hashedIndex[i-1] + nbHashIndex;
-  }
-  hashedIndex[nbClient] = nbHashIndexMax;
-}
-
-/*!
-  Compute distribution of global index for servers
-  Each client already holds a piece of information and its associated index.
-This information will be redistributed among processes by projecting indices into size_t space,
-the corresponding information will be also distributed on size_t space.
-After the redistribution, each client holds rearranged index and its corresponding information.
-  \param [in] indexInfoMap index and its corresponding info (usually server index)
-  \param [in] commLevel communicator of current level
-  \param [in] level current level
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::computeDistributedIndex(const Index2VectorInfoTypeMap& indexInfoMap,
-                                                            const MPI_Comm& commLevel,
-                                                            int level)
-{
-  int clientRank;
-  MPI_Comm_rank(commLevel,&clientRank);
-  computeSendRecvRank(level, clientRank);
-
-  int groupRankBegin = this->getGroupBegin()[level];
-  int nbClient = this->getNbInGroup()[level];
-  std::vector<size_t> hashedIndex;
-  computeHashIndex(hashedIndex, nbClient);
-
-  std::vector<int> sendBuff(nbClient,0);
-  std::vector<int> sendNbIndexBuff(nbClient,0);
-  std::vector<size_t>::const_iterator itbClientHash = hashedIndex.begin(), itClientHash,
-                                      iteClientHash = hashedIndex.end();
-  typename Index2VectorInfoTypeMap::const_iterator itb = indexInfoMap.begin(),it,
-                                                   ite = indexInfoMap.end();
-  HashXIOS<size_t> hashGlobalIndex;
-
-  // Compute size of sending and receving buffer
-  for (it = itb; it != ite; ++it)
-  {
-    size_t hashIndex = hashGlobalIndex(it->first);
-    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashIndex);
-    int indexClient = std::distance(itbClientHash, itClientHash)-1;
-    sendNbIndexBuff[indexClient] += it->second.size();
-  }
-
-  std::unordered_map<int, size_t*> client2ClientIndex;
-  std::unordered_map<int, unsigned char*> client2ClientInfo;
-  for (int idx = 0; idx < nbClient; ++idx)
-  {
-    if (0 != sendNbIndexBuff[idx])
-    {
-      client2ClientIndex[idx+groupRankBegin] = new unsigned long [sendNbIndexBuff[idx]];
-      client2ClientInfo[idx+groupRankBegin] = new unsigned char [sendNbIndexBuff[idx]*ProcessDHTElement<InfoType>::typeSize()];
-      sendNbIndexBuff[idx] = 0;
-      sendBuff[idx] = 1;
-    }
-  }
-
-  std::vector<int> sendNbInfo(nbClient,0);
-  for (it = itb; it != ite; ++it)
-  {
-    const std::vector<InfoType>& infoTmp = it->second;
-    size_t hashIndex = hashGlobalIndex(it->first);
-    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashIndex);
-    int indexClient = std::distance(itbClientHash, itClientHash)-1;
-    for (int idx = 0; idx < infoTmp.size(); ++idx)
-    {
-      client2ClientIndex[indexClient + groupRankBegin][sendNbIndexBuff[indexClient]] = it->first;;
-  //          ProcessDHTElement<InfoType>::packElement(it->second, client2ClientInfo[indexClient + groupRankBegin], sendNbInfo[indexClient]);
-      ProcessDHTElement<InfoType>::packElement(infoTmp[idx], client2ClientInfo[indexClient + groupRankBegin], sendNbInfo[indexClient]);
-      ++sendNbIndexBuff[indexClient];
-    }
-  }
-
-  // Calculate from how many clients each client receive message.
-  // Calculate size of buffer for receiving message
-  std::vector<int> recvRankClient, recvNbIndexClientCount;
-  sendRecvRank(level, sendBuff, sendNbIndexBuff,
-               recvRankClient, recvNbIndexClientCount);
-
-  int recvNbIndexCount = 0;
-  for (int idx = 0; idx < recvNbIndexClientCount.size(); ++idx)
-    recvNbIndexCount += recvNbIndexClientCount[idx];
-
-  unsigned long* recvIndexBuff;
-  unsigned char* recvInfoBuff;
-  if (0 != recvNbIndexCount)
-  {
-    recvIndexBuff = new unsigned long[recvNbIndexCount];
-    recvInfoBuff = new unsigned char[recvNbIndexCount*ProcessDHTElement<InfoType>::typeSize()];
-  }
-
-  // If a client holds information about index and the corresponding which don't belong to it,
-  // it will send a message to the correct clients.
-  // Contents of the message are index and its corresponding informatioin
-  std::vector<MPI_Request> request;
-  int currentIndex = 0;
-  int nbRecvClient = recvRankClient.size();
-  for (int idx = 0; idx < nbRecvClient; ++idx)
-  {
-    if (0 != recvNbIndexClientCount[idx])
-    {
-      recvIndexFromClients(recvRankClient[idx], recvIndexBuff+currentIndex, recvNbIndexClientCount[idx], commLevel, request);
-      recvInfoFromClients(recvRankClient[idx],
-                          recvInfoBuff+currentIndex*ProcessDHTElement<InfoType>::typeSize(),
-                          recvNbIndexClientCount[idx]*ProcessDHTElement<InfoType>::typeSize(),
-                          commLevel, request);
-    }
-    currentIndex += recvNbIndexClientCount[idx];
-  }
-
-  std::unordered_map<int, size_t* >::iterator itbIndex = client2ClientIndex.begin(), itIndex,
-                                                iteIndex = client2ClientIndex.end();
-  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
-    sendIndexToClients(itIndex->first, itIndex->second, sendNbIndexBuff[itIndex->first-groupRankBegin], commLevel, request);
-  std::unordered_map<int, unsigned char*>::iterator itbInfo = client2ClientInfo.begin(), itInfo,
-                                                      iteInfo = client2ClientInfo.end();
-  for (itInfo = itbInfo; itInfo != iteInfo; ++itInfo)
-    sendInfoToClients(itInfo->first, itInfo->second, sendNbInfo[itInfo->first-groupRankBegin], commLevel, request);
-
-  std::vector<MPI_Status> status(request.size());
-  MPI_Waitall(request.size(), &request[0], &status[0]);
-
-  Index2VectorInfoTypeMap indexToInfoMapping;
-  indexToInfoMapping.rehash(std::ceil(currentIndex/indexToInfoMapping.max_load_factor()));
-  currentIndex = 0;
-  InfoType infoValue;
-  int infoIndex = 0;
-  unsigned char* infoBuff = recvInfoBuff;
-  for (int idx = 0; idx < nbRecvClient; ++idx)
-  {
-    size_t index;
-    int count = recvNbIndexClientCount[idx];
-    for (int i = 0; i < count; ++i)
-    {
-      ProcessDHTElement<InfoType>::unpackElement(infoValue, infoBuff, infoIndex);
-      indexToInfoMapping[*(recvIndexBuff+currentIndex+i)].push_back(infoValue);
-    }
-    currentIndex += count;
-  }
-
-  if (0 != recvNbIndexCount)
-  {
-    delete [] recvIndexBuff;
-    delete [] recvInfoBuff;
-  }
-  for (std::unordered_map<int,unsigned char*>::const_iterator it = client2ClientInfo.begin();
-                                                               it != client2ClientInfo.end(); ++it)
-      delete [] it->second;
-
-  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndex.begin();
-                                                        it != client2ClientIndex.end(); ++it)
-      delete [] it->second;
-
-  // Ok, now do something recursive
-  if (0 < level)
-  {
-    --level;
-    computeDistributedIndex(indexToInfoMapping, this->internalComm_, level);
-  }
-  else
-    index2InfoMapping_.swap(indexToInfoMapping);
-}
-
-/*!
-  Send message containing index to clients
-  \param [in] clientDestRank rank of destination client
-  \param [in] indices index to send
-  \param [in] indiceSize size of index array to send
-  \param [in] clientIntraComm communication group of client
-  \param [in] requestSendIndex list of sending request
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::sendIndexToClients(int clientDestRank, size_t* indices, size_t indiceSize,
-                                                       const MPI_Comm& clientIntraComm,
-                                                       std::vector<MPI_Request>& requestSendIndex)
-{
-  MPI_Request request;
-  requestSendIndex.push_back(request);
-  MPI_Isend(indices, indiceSize, MPI_UNSIGNED_LONG,
-            clientDestRank, MPI_DHT_INDEX, clientIntraComm, &(requestSendIndex.back()));
-}
-
-/*!
-  Receive message containing index to clients
-  \param [in] clientDestRank rank of destination client
-  \param [in] indices index to send
-  \param [in] clientIntraComm communication group of client
-  \param [in] requestRecvIndex list of receiving request
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::recvIndexFromClients(int clientSrcRank, size_t* indices, size_t indiceSize,
-                                                         const MPI_Comm& clientIntraComm,
-                                                         std::vector<MPI_Request>& requestRecvIndex)
-{
-  MPI_Request request;
-  requestRecvIndex.push_back(request);
-  MPI_Irecv(indices, indiceSize, MPI_UNSIGNED_LONG,
-            clientSrcRank, MPI_DHT_INDEX, clientIntraComm, &(requestRecvIndex.back()));
-}
-
-/*!
-  Send message containing information to clients
-  \param [in] clientDestRank rank of destination client
-  \param [in] info info array to send
-  \param [in] infoSize info array size to send
-  \param [in] clientIntraComm communication group of client
-  \param [in] requestSendInfo list of sending request
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::sendInfoToClients(int clientDestRank, unsigned char* info, int infoSize,
-                                                      const MPI_Comm& clientIntraComm,
-                                                      std::vector<MPI_Request>& requestSendInfo)
-{
-  MPI_Request request;
-  requestSendInfo.push_back(request);
-
-  MPI_Isend(info, infoSize, MPI_CHAR,
-            clientDestRank, MPI_DHT_INFO, clientIntraComm, &(requestSendInfo.back()));
-}
-
-/*!
-  Receive message containing information from other clients
-  \param [in] clientDestRank rank of destination client
-  \param [in] info info array to receive
-  \param [in] infoSize info array size to receive
-  \param [in] clientIntraComm communication group of client
-  \param [in] requestRecvInfo list of sending request
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::recvInfoFromClients(int clientSrcRank, unsigned char* info, int infoSize,
-                                                        const MPI_Comm& clientIntraComm,
-                                                        std::vector<MPI_Request>& requestRecvInfo)
-{
-  MPI_Request request;
-  requestRecvInfo.push_back(request);
-
-  MPI_Irecv(info, infoSize, MPI_CHAR,
-            clientSrcRank, MPI_DHT_INFO, clientIntraComm, &(requestRecvInfo.back()));
-}
-
-/*!
-  Compute how many processes one process needs to send to and from how many processes it will receive.
-  This computation is only based on hierachical structure of distributed hash table (e.x: number of processes)
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::computeSendRecvRank(int level, int rank)
-{
-  int groupBegin = this->getGroupBegin()[level];
-  int nbInGroup  = this->getNbInGroup()[level];
-  const std::vector<int>& groupParentBegin = this->getGroupParentsBegin()[level];
-  const std::vector<int>& nbInGroupParents = this->getNbInGroupParents()[level];
-
-  std::vector<size_t> hashedIndexGroup;
-  computeHashIndex(hashedIndexGroup, nbInGroup);
-  size_t a = hashedIndexGroup[rank-groupBegin];
-  size_t b = hashedIndexGroup[rank-groupBegin+1]-1;
-
-  int currentGroup, offset;
-  size_t e,f;
-
-  // Do a simple math [a,b) intersect [c,d)
-  for (int idx = 0; idx < groupParentBegin.size(); ++idx)
-  {
-    std::vector<size_t> hashedIndexGroupParent;
-    int nbInGroupParent = nbInGroupParents[idx];
-    if (0 != nbInGroupParent)
-      computeHashIndex(hashedIndexGroupParent, nbInGroupParent);
-    for (int i = 0; i < nbInGroupParent; ++i)
-    {
-      size_t c = hashedIndexGroupParent[i];
-      size_t d = hashedIndexGroupParent[i+1]-1;
-
-    if (!((d < a) || (b <c)))
-        recvRank_[level].push_back(groupParentBegin[idx]+i);
-    }
-
-    offset = rank - groupParentBegin[idx];
-    if ((offset<nbInGroupParents[idx]) && (0 <= offset))
-    {
-      e = hashedIndexGroupParent[offset];
-      f = hashedIndexGroupParent[offset+1]-1;
-    }
-  }
-
-  std::vector<size_t>::const_iterator itbHashGroup = hashedIndexGroup.begin(), itHashGroup,
-                                      iteHashGroup = hashedIndexGroup.end();
-  itHashGroup = std::lower_bound(itbHashGroup, iteHashGroup, e+1);
-  int begin = std::distance(itbHashGroup, itHashGroup)-1;
-  itHashGroup = std::upper_bound(itbHashGroup, iteHashGroup, f);
-  int end = std::distance(itbHashGroup, itHashGroup) -1;
-  sendRank_[level].resize(end-begin+1);
-  for (int idx = 0; idx < sendRank_[level].size(); ++idx) sendRank_[level][idx] = idx + groupBegin + begin;
-}
-
-/*!
-  Compute number of clients as well as corresponding number of elements each client will receive on returning searching result
-  \param [in] sendNbRank Rank of clients to send to
-  \param [in] sendNbElements Number of elements each client to send to
-  \param [in] receiveNbRank Rank of clients to receive from
-  \param [out] recvNbElements Number of elements each client to send to
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::sendRecvOnReturn(const std::vector<int>& sendNbRank, std::vector<int>& sendNbElements,
-                                                     const std::vector<int>& recvNbRank, std::vector<int>& recvNbElements)
-{
-  recvNbElements.resize(recvNbRank.size());
-  std::vector<MPI_Request> request(sendNbRank.size()+recvNbRank.size());
-  std::vector<MPI_Status> requestStatus(sendNbRank.size()+recvNbRank.size());
-
-  int nRequest = 0;
-  for (int idx = 0; idx < recvNbRank.size(); ++idx)
-  {
-    MPI_Irecv(&recvNbElements[0]+idx, 1, MPI_INT,
-              recvNbRank[idx], MPI_DHT_INDEX_1, this->internalComm_, &request[nRequest]);
-    ++nRequest;
-  }
-
-  for (int idx = 0; idx < sendNbRank.size(); ++idx)
-  {
-    MPI_Isend(&sendNbElements[0]+idx, 1, MPI_INT,
-              sendNbRank[idx], MPI_DHT_INDEX_1, this->internalComm_, &request[nRequest]);
-    ++nRequest;
-  }
-
-  MPI_Waitall(sendNbRank.size()+recvNbRank.size(), &request[0], &requestStatus[0]);
-}
-
-/*!
-  Send and receive number of process each process need to listen to as well as number
-  of index it will receive during the initalization phase
-  \param [in] level current level
-  \param [in] sendNbRank Rank of clients to send to
-  \param [in] sendNbElements Number of elements each client to send to
-  \param [out] receiveNbRank Rank of clients to receive from
-  \param [out] recvNbElements Number of elements each client to send to
-*/
-template<typename T, typename H>
-void CClientClientDHTTemplate<T,H>::sendRecvRank(int level,
-                                                 const std::vector<int>& sendNbRank, const std::vector<int>& sendNbElements,
-                                                 std::vector<int>& recvNbRank, std::vector<int>& recvNbElements)
-{
-  int groupBegin = this->getGroupBegin()[level];
-
-  int offSet = 0;
-  std::vector<int>& sendRank = sendRank_[level];
-  std::vector<int>& recvRank = recvRank_[level];
-  int sendBuffSize = sendRank.size();
-  std::vector<int> sendBuff(sendBuffSize*2);
-  int recvBuffSize = recvRank.size();
-  std::vector<int> recvBuff(recvBuffSize*2,0);
-
-  std::vector<MPI_Request> request(sendBuffSize+recvBuffSize);
-  std::vector<MPI_Status> requestStatus(sendBuffSize+recvBuffSize);
-
-  int nRequest = 0;
-  for (int idx = 0; idx < recvBuffSize; ++idx)
-  {
-    MPI_Irecv(&recvBuff[0]+2*idx, 2, MPI_INT,
-              recvRank[idx], MPI_DHT_INDEX_0, this->internalComm_, &request[nRequest]);
-    ++nRequest;
-  }
-
-  for (int idx = 0; idx < sendBuffSize; ++idx)
-  {
-    offSet = sendRank[idx]-groupBegin;
-    sendBuff[idx*2] = sendNbRank[offSet];
-    sendBuff[idx*2+1] = sendNbElements[offSet];
-  }
-
-  for (int idx = 0; idx < sendBuffSize; ++idx)
-  {
-    MPI_Isend(&sendBuff[idx*2], 2, MPI_INT,
-              sendRank[idx], MPI_DHT_INDEX_0, this->internalComm_, &request[nRequest]);
-    ++nRequest;
-  }
-
-  MPI_Waitall(sendBuffSize+recvBuffSize, &request[0], &requestStatus[0]);
-  int nbRecvRank = 0, nbRecvElements = 0;
-  recvNbRank.clear();
-  recvNbElements.clear();
-  for (int idx = 0; idx < recvBuffSize; ++idx)
-  {
-    if (0 != recvBuff[2*idx])
-    {
-      recvNbRank.push_back(recvRank[idx]);
-      recvNbElements.push_back(recvBuff[2*idx+1]);
-    }
-  }
-}
-
-}
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping.cpp	(revision 1917)
+++ 	(revision )
@@ -1,104 +1,0 @@
-/*!
-   \file client_server_mapping.hpp
-   \author Ha NGUYEN
-   \since 04 Feb 2015
-   \date 09 Mars 2015
-
-   \brief Mapping between index client and server.
- */
-#include "client_server_mapping.hpp"
-
-namespace xios {
-
-CClientServerMapping::CClientServerMapping()
-  : indexGlobalOnServer_()
-{
-}
-
-CClientServerMapping::~CClientServerMapping()
-{
-}
-
-/*!
-  Compute how many clients each server will receive data from
-  On client can send data to several servers as well as one server can receive data originated from
-some clients. In order to write data correctly, each server must know from how many clients it receives data
-  \param [in] nbServer number of servers
-  \param [in] nClient number of clients
-  \param [in] clientIntraComm MPI communication of clients
-  \param [in] connectedServerRank Rank of servers connected to the current client
-*/
-std::map<int,int> CClientServerMapping::computeConnectedClients(int nbServer, int nbClient,
-                                                                MPI_Comm& clientIntraComm,
-                                                                const std::vector<int>& connectedServerRank)
-{
-  std::map<int, int> connectedClients; // number of clients connected to a server
-
-  std::vector<int>::const_iterator itbVec, iteVec, it;
-  itbVec = it = connectedServerRank.begin();
-  iteVec = connectedServerRank.end();
-
-  std::vector<int> connectedServer;
-  std::vector<bool> isConnected(nbServer,false);
-
-  for (it = itbVec; it != iteVec; ++it)
-  {
-    for (int serverNum = 0; serverNum < nbServer; ++serverNum)
-      if (*it == serverNum) isConnected[serverNum] = true;
-  }
-
-  for(int serverNum = 0; serverNum<nbServer; ++serverNum)
-    if (isConnected[serverNum])
-      connectedServer.push_back(serverNum);
-
-
-  int nbConnectedServer=connectedServer.size();
-  int* recvCount=new int[nbClient];
-  int* displ=new int[nbClient];
-  int* sendBuff=new int[nbConnectedServer];
-  valarray<int> clientRes(0,nbServer);
-
-  for(int n=0;n<nbConnectedServer;n++) sendBuff[n]=connectedServer[n] ;
-
-  // get connected server for everybody
-  MPI_Allgather(&nbConnectedServer,1,MPI_INT,recvCount,1,MPI_INT,clientIntraComm) ;
-
-  displ[0]=0 ;
-  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvCount[n-1] ;
-  int recvSize=displ[nbClient-1]+recvCount[nbClient-1] ;
-  int* recvBuff=new int[recvSize] ;
-
-
-  MPI_Allgatherv(sendBuff,nbConnectedServer,MPI_INT,recvBuff,recvCount,displ,MPI_INT,clientIntraComm) ;
-  for(int n=0;n<recvSize;n++) clientRes[recvBuff[n]]++ ;
-
-  for(int n=0;n<nbConnectedServer;n++)
-  {
-    connectedClients[connectedServer[n]] = clientRes[connectedServer[n]];
-  }
-
-  delete [] recvCount ;
-  delete [] displ ;
-  delete [] sendBuff ;
-  delete [] recvBuff ;
-
-  return connectedClients;
-}
-
-/*!
-  Return global index of data on each connected server.
-  On receiving data sent from client(s), each server with this global index, is able to
-know where the data should be written.
-  \return mapping of server rank and its global index.
-*/
-const CClientServerMapping::GlobalIndexMap& CClientServerMapping::getGlobalIndexOnServer() const
-{
-  return indexGlobalOnServer_;
-}
-
-CClientServerMapping::GlobalIndexMap& CClientServerMapping::getGlobalIndexOnServer()
-{
-  return indexGlobalOnServer_;
-}
-
-} //namespace xios
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping.hpp	(revision 1917)
+++ 	(revision )
@@ -1,52 +1,0 @@
-/*!
-   \file client_server_mapping.hpp
-   \author Ha NGUYEN
-   \since 04 Feb 2015
-   \date 09 Mars 2015
-
-   \brief Mapping between index client and server.
- */
-#ifndef __XIOS_CLIENT_SERVER_MAPPING_HPP__
-#define __XIOS_CLIENT_SERVER_MAPPING_HPP__
-
-#include "xios_spl.hpp"
-#include "array_new.hpp"
-#include "mpi.hpp"
-#include <unordered_map>
-
-namespace xios {
-
-/*!
-  \class CClientServerMapping
-  This class computes index of data which are sent to server as well as index of data
-on server side.
-*/
-class CClientServerMapping
-{
-public:
-  typedef std::unordered_map<int, std::vector<size_t> > GlobalIndexMap;
-  public:
-    /** Default constructor */
-    CClientServerMapping();
-
-    /** Default destructor */
-    virtual ~CClientServerMapping();
-
-    // Only need global index on client to calculate mapping (supposed client has info of distribution)
-    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient, int nbServer) = 0;
-
-    static std::map<int,int> computeConnectedClients(int nbServer, int nbClient,
-                                                     MPI_Comm& clientIntraComm,
-                                                     const std::vector<int>& connectedServerRank);
-
-    const GlobalIndexMap& getGlobalIndexOnServer() const;
-
-    GlobalIndexMap& getGlobalIndexOnServer();
-
-  protected:
-    //! Global index of data on SERVER, which are calculated by client(s)
-    GlobalIndexMap indexGlobalOnServer_;
-};
-
-} // namespace xios
-#endif // __XIOS_CLIENT_SERVER_MAPPING_HPP__
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping_distributed.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping_distributed.cpp	(revision 1917)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*!
-   \file client_server_mapping.hpp
-   \author Ha NGUYEN
-   \since 27 Feb 2015
-   \date 16 Mars 2016
-
-   \brief Mapping between index client and server.
-   Clients pre-calculate all information of server distribution.
- */
-#include "client_server_mapping_distributed.hpp"
-#include <limits>
-#include <boost/functional/hash.hpp>
-#include "utils.hpp"
-#include "mpi_tag.hpp"
-#include "context.hpp"
-#include "context_client.hpp"
-
-namespace xios
-{
-
-CClientServerMappingDistributed::CClientServerMappingDistributed(const std::unordered_map<size_t,int>& globalIndexOfServer,
-                                                                 const MPI_Comm& clientIntraComm, bool isDataDistributed)
-  : CClientServerMapping(), ccDHT_(0)
-{
-  ccDHT_ = new CClientClientDHTInt(globalIndexOfServer,
-                                   clientIntraComm);
-}
-
-CClientServerMappingDistributed::~CClientServerMappingDistributed()
-{
-  if (0 != ccDHT_) delete ccDHT_;
-}
-
-/*!
-   Compute mapping global index of server which client sends to.
-   \param [in] globalIndexOnClient global index client has
-   \param [in] nbServer size of server's intracomm
-*/
-void CClientServerMappingDistributed::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient, int nbServer)
-{
-
-  ccDHT_->computeIndexInfoMapping(globalIndexOnClient);
-  const CClientClientDHTInt::Index2VectorInfoTypeMap& infoIndexMap = (ccDHT_->getInfoIndexMap());
-  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = infoIndexMap.begin(), ite = infoIndexMap.end(), it;
-  std::vector<size_t> nbInfoIndex(std::max(ccDHT_->getNbClient(),nbServer),0);
-
-  for (it = itb; it != ite; ++it)
-  {
-    ++nbInfoIndex[it->second[0]];
-  }
-
-  for (int idx = 0; idx < nbInfoIndex.size(); ++idx)
-  {
-    if (0 != nbInfoIndex[idx])
-    {
-      indexGlobalOnServer_[idx].resize(nbInfoIndex[idx]);
-      nbInfoIndex[idx] = 0;
-    }
-  }
-
-  for (it = itb; it != ite; ++it)
-  {
-    indexGlobalOnServer_[it->second[0]][nbInfoIndex[it->second[0]]] = (it->first);
-    ++nbInfoIndex[it->second[0]];
-  }
-}
-
-}
Index: OS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping_distributed.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/client_server_mapping_distributed.hpp	(revision 1917)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*!
-   \file client_server_mapping.hpp
-   \author Ha NGUYEN
-   \since 27 Feb 2015
-   \date 09 Mars 2015
-
-   \brief Mapping between index client and server.
-   Clients pre-calculate all information of server distribution.
- */
-
-#ifndef __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
-#define __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
-
-#include <client_server_mapping.hpp>
-#include "xios_spl.hpp"
-#include "array_new.hpp"
-#include "mpi.hpp"
-#include <unordered_map>
-#include "client_client_dht_template.hpp"
-
-namespace xios
-{
-/*!
-  \class CClientServerMappingDistributed
-  This class computes index of data which are sent to server as well as index of data
-on server side with a distributed alogrithm. Each client has a piece of information about the distribution
-of servers. To find out all these info, first of all, all client join a discovering process in which each client
-announces the others about the info they have as well as demand others info they are lacked of. After this process,
-each client has enough info to decide to which client it need to send a demand for corresponding server of a global index.
-The alogrithm depends on hashed index.
-*/
-class CClientServerMappingDistributed : public CClientServerMapping
-{
-  public:
-    /** Default constructor */
-    CClientServerMappingDistributed(const std::unordered_map<size_t,int>& globalIndexOfServer,
-                                    const MPI_Comm& clientIntraComm,
-                                    bool isDataDistributed = true);
-
-    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClientSendToServer, int nbServer);
-
-    /** Default destructor */
-    virtual ~CClientServerMappingDistributed();
-
-  protected:
-    CClientClientDHTInt* ccDHT_;
-};
-
-} // namespace xios
-#endif // __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/context_client.hpp	(revision 1918)
@@ -67,4 +67,7 @@
       int getRemoteSize(void) {return serverSize;}
       int getServerSize(void) {return serverSize;}
+      MPI_Comm getIntraComm(void)  {return intraComm ;} 
+      int getIntraCommSize(void) {return clientSize ;}
+      int getIntraCommRank(void) {return clientRank ;}
 
       /*! set the associated server (dual chanel client/server) */      
Index: OS/dev/dev_ym/XIOS_COUPLING/src/dht_auto_indexing.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/dht_auto_indexing.cpp	(revision 1917)
+++ 	(revision )
@@ -1,115 +1,0 @@
-/*!
-   \file dht_auto_indexing.cpp
-   \author Ha NGUYEN
-   \since 6 Jul 2016
-   \date 6 Jul 2016
-
-   \brief Auto assign global index across processes.
- */
-#include "dht_auto_indexing.hpp"
-
-namespace xios
-{
-
-  CDHTAutoIndexing::~CDHTAutoIndexing()
-  {
-  }
-
-  /*!
-    \param [in]
-    \param [in]
-  */
-
-  CDHTAutoIndexing::CDHTAutoIndexing(const CArray<size_t,1>& hashValue,
-                                     const MPI_Comm& clientIntraComm)
-    : CClientClientDHTTemplate<size_t>(clientIntraComm)
-  {
-
-    nbIndexOnProc_ = hashValue.size();
-    size_t nbIndexAccum;
-    MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm);
-
-    // Broadcasting the total number of indexes
-    int rank, size;
-    MPI_Comm_rank(clientIntraComm, &rank);
-    MPI_Comm_size(clientIntraComm, &size);
-    if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum;
-    MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm);
-
-    CArray<size_t,1>::const_iterator itbIdx = hashValue.begin(), itIdx,
-                                     iteIdx = hashValue.end();
-
-    size_t idx = 0;
-    beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_;
-    globalIndex_.resize(nbIndexOnProc_);
-    for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx)
-    {
-      globalIndex_[idx] = beginIndexOnProc_ + idx;
-      ++idx ;
-    }
-  }
-
-  /*!
-   * \fn void CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap, const MPI_Comm& clientIntraComm)
-   * Assigns a global index to unique input indexes.
-   * The returned map has unique indexes as a key and global indexes as a mapped value.
-   * \param [in] hashInitMap map<size_t, vector<size_t>> is a map of unique indexes.
-   * \param [in] clientIntraComm
-  */
-  CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap,
-                                     const MPI_Comm& clientIntraComm)
-    : CClientClientDHTTemplate<size_t>(clientIntraComm)
-  {
-
-    nbIndexOnProc_ = hashInitMap.size();
-    size_t nbIndexAccum;
-    MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm);
-
-    int rank, size;
-    MPI_Comm_rank(clientIntraComm, &rank);
-    MPI_Comm_size(clientIntraComm, &size);
-    if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum;
-    MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm);
-
-    Index2VectorInfoTypeMap::iterator itbIdx = hashInitMap.begin(), itIdx,
-                                      iteIdx = hashInitMap.end();
-    size_t idx = 0;
-    beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_;
-    globalIndex_.resize(nbIndexOnProc_);
-    for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx)
-    {
-//      (itIdx->second)[0] = beginIndexOnProc_ + idx;
-      (itIdx->second)[1] = beginIndexOnProc_ + idx;
-      globalIndex_[idx] = beginIndexOnProc_ + idx;
-      ++idx ;
-    }
-  }
-
-  /*!
-   * \fn size_t CDHTAutoIndexing::getNbIndexesGlobal() const
-   * Returns the total number of global indexes.
-  */
-  size_t CDHTAutoIndexing::getNbIndexesGlobal() const
-  {
-    return nbIndexesGlobal_;
-  }
-
-  /*!
-   * \fn size_t CDHTAutoIndexing::getIndexStart() const
-   * Returns the starting global index for a proc.
-  */
-  size_t CDHTAutoIndexing::getIndexStart() const
-  {
-    return beginIndexOnProc_;
-  }
-
-  /*!
-   * \fn size_t CDHTAutoIndexing::getIndexCount() const
-   * Returns the number of global indexes on a proc.
-  */
-  size_t CDHTAutoIndexing::getIndexCount() const
-  {
-    return nbIndexOnProc_;
-  }
-
-}
Index: OS/dev/dev_ym/XIOS_COUPLING/src/dht_auto_indexing.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/dht_auto_indexing.hpp	(revision 1917)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*!
-   \file dht_auto_indexing.hpp
-   \author Ha NGUYEN
-   \since 6 Jul 2016
-   \date 6 Jul 2016
-
-   \brief Auto assign global index across processes.
- */
-
-#ifndef __XIOS_DHT_AUTO_INDEXING_HPP__
-#define __XIOS_DHT_AUTO_INDEXING_HPP__
-
-#include "client_client_dht_template.hpp"
-
-namespace xios
-{
-
-/*!
-  \class CDHTAutoIndexing
-  .
-*/
-class CDHTAutoIndexing: public CClientClientDHTTemplate<size_t>
-{
-  public:
-
-    CDHTAutoIndexing(const CArray<size_t,1>& hashValue,
-                     const MPI_Comm& clientIntraComm);
-
-    CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap,
-                     const MPI_Comm& clientIntraComm);
-
-    size_t getNbIndexesGlobal() const;
-    size_t getIndexStart() const;
-    size_t getIndexCount() const;
-
-    /** Default destructor */
-    virtual ~CDHTAutoIndexing();
-
-  protected:
-    std::vector<size_t> globalIndex_;
-    size_t nbIndexesGlobal_;
-    size_t nbIndexOnProc_ ;
-    size_t beginIndexOnProc_ ;
-};
-
-} // namespace xios
-#endif // __XIOS_DHT_AUTO_INDEXING_HPP__
Index: OS/dev/dev_ym/XIOS_COUPLING/src/dht_data_types.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/dht_data_types.hpp	(revision 1917)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*!
-   \file dht_data_types.hpp
-   \author Ha NGUYEN
-   \since 17 Mars 2016
-   \date 17 Mars 2016
-
-   \brief Customized data type for dht
- */
-
-#ifndef __XIOS_DHT_DATATYPES_HPP__
-#define __XIOS_DHT_DATATYPES_HPP__
-
-#include "utils.hpp"
-
-namespace xios
-{
-typedef std::pair<int,int> PairIntInt;
-
-template<typename T>
-struct ProcessDHTElement
-{
-  typedef T Type;
-  static int typeSize()
-  {
-    return sizeof(Type);
-  }
-
-  static void packElement(const T& inputElement, unsigned char* packedElement, int& index)
-  {
-    if (NULL == packedElement) index += sizeof(Type);
-    else
-    {
-      *(T *)(&packedElement[index]) = inputElement;
-      index+=sizeof(Type);
-    }
-  }
-
-  static void unpackElement(T& outputElement, unsigned char* unpackedElement, int& index)
-  {
-    outputElement = *(Type*)(&unpackedElement[index]);
-    index+=sizeof(Type);
-  }
-};
-
-template<>
-struct ProcessDHTElement<PairIntInt>
-{
-  typedef PairIntInt Type;
-  static int typeSize()
-  {
-    return (2*sizeof(int));
-  }
-
-  static void packElement(const PairIntInt& inputElement, unsigned char* packedElement, int& index)
-  {
-    if (NULL == packedElement) index +=(2*sizeof(int));
-    else
-    {
-      *(int *)(&packedElement[index]) = inputElement.first;
-      index+=sizeof(int);
-      *(int *)(&packedElement[index]) = inputElement.second;
-      index+=sizeof(int);
-    }
-  }
-
-  static void unpackElement(PairIntInt& outputElement, unsigned char* unpackedElement, int& index)
-  {
-    outputElement.first=*(int *)(&unpackedElement[index]);
-    index+=sizeof(int);
-    outputElement.second=*(int *)(&unpackedElement[index]);
-    index+=sizeof(int);
-  }
-};
-
-}
-
-#endif // __XIOS_DHT_DATATYPES_HPP__
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution.cpp	(revision 1917)
+++ 	(revision )
@@ -1,38 +1,0 @@
-/*!
-   \file distribution.hpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 09 Feb 2015
-
-   \brief Index distribution on server side.
- */
-#include "distribution.hpp"
-
-namespace xios {
-
-CDistribution::CDistribution(int rank, int dims, const CArray<size_t,1>& globalIndex)
-  : rank_(rank), dims_(dims), globalIndex_(globalIndex.shape())
-{
-  if (0 != globalIndex.numElements())
-    globalIndex_ = globalIndex;
-}
-
-const CArray<size_t,1>& CDistribution:: getGlobalIndex() const 
-{ 
-  return globalIndex_; 
-}
-
-CDistribution::~CDistribution()
-{ /* Nothing to do */ }
-
-int CDistribution::getDims() const
-{
-  return dims_;
-}
-
-int CDistribution::getRank() const
-{
-  return rank_;
-}
-
-} // namespace xios
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution.hpp	(revision 1917)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*!
-   \file distribution.hpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 09 Feb 2015
-
-   \brief Index distribution on server side.
- */
-#ifndef __XIOS_DISTRIBUTION_HPP__
-#define __XIOS_DISTRIBUTION_HPP__
-
-#include "xios_spl.hpp"
-#include "array_new.hpp"
-#include <unordered_map>
-
-namespace xios {
-/*!
- \class CDistribution
- The parent class of CDistributionClient and CDistributionServer, which declares and defines
-some basic methods and properties for its children. This class allows its descendants to calculate
-distribution of index on client or server side.
-*/
-class CDistribution
-{
-  public:
-  typedef std::unordered_map<size_t,int> GlobalLocalMap;
-
-  public:
-    /** Default constructor */
-    CDistribution(int rank, int dims, const CArray<size_t,1>& globalIndex = CArray<size_t,1>());
-
-    /** Default destructor */
-    virtual ~CDistribution();
-
-    int getDims() const; //! Get dimension size
-    int getRank() const; //! Get rank of current process
-    const CArray<size_t,1>& getGlobalIndex() const;
-    
-  protected:
-    virtual void createGlobalIndex() {};
-
-  protected:
-    CArray<size_t,1> globalIndex_;
-    int dims_;
-    int rank_;
-};
-
-} // namespace xios
-#endif // __XIOS_DISTRIBUTION_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_decl.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_decl.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_decl.cpp	(revision 1918)
@@ -0,0 +1,19 @@
+/*!
+   \file client_client_dht.cpp
+   \author Ha NGUYEN
+   \since 05 Oct 2015
+   \date 23 Mars 2016
+
+   \brief Distributed hashed table implementation.
+ */
+#include "client_client_dht_template_impl.hpp"
+
+namespace xios
+{
+
+template class CClientClientDHTTemplate<int>;
+template class CClientClientDHTTemplate<size_t>;
+template class CClientClientDHTTemplate<double>;
+template class CClientClientDHTTemplate<PairIntInt>;
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template.hpp	(revision 1918)
@@ -0,0 +1,132 @@
+/*!
+   \file client_client_dht_template.hpp
+   \author Ha NGUYEN
+   \since 01 Oct 2015
+   \date 15 April 2016
+
+   \brief Distributed hashed table implementation.
+ */
+
+#ifndef __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
+#define __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "mpi.hpp"
+#include "policy.hpp"
+#include  <unordered_map>
+#include "dht_data_types.hpp"
+
+namespace xios
+{
+template<typename T, class HierarchyPolicy = DivideAdaptiveComm> class CClientClientDHTTemplate;
+
+/*!
+  \class CClientClientDHTTemplate
+  This class provides the similar features like \class CClientServerMappingDistributed,
+which implements a simple distributed hashed table; Moreover, by extending with hierarchical structure,
+it allows to reduce greatly the number of communication among processes.
+*/
+template<typename T, typename HierarchyPolicy>
+class CClientClientDHTTemplate: public HierarchyPolicy
+{
+  public:
+    typedef T InfoType;
+    static const int infoTypeSize = sizeof(InfoType);
+//    typedef typename std::unordered_map<InfoType, std::vector<size_t> > InfoType2IndexMap;
+    typedef typename std::unordered_map<size_t,InfoType> Index2InfoTypeMap;
+    typedef typename std::unordered_map<size_t,std::vector<InfoType> > Index2VectorInfoTypeMap;
+
+  public:
+    CClientClientDHTTemplate(const Index2InfoTypeMap& indexInfoInitMap,
+                             const MPI_Comm& clientIntraComm);
+
+    CClientClientDHTTemplate(const Index2VectorInfoTypeMap& indexInfoInitMap,
+                             const MPI_Comm& clientIntraComm);
+
+    void computeIndexInfoMapping(const CArray<size_t,1>& indices);
+
+    const Index2VectorInfoTypeMap& getInfoIndexMap() const {return indexToInfoMappingLevel_; }
+    Index2VectorInfoTypeMap& getInfoIndexMap() {return indexToInfoMappingLevel_; }
+    int getNbClient() { return nbClient_; }
+
+    /** Default destructor */
+    virtual ~CClientClientDHTTemplate();
+
+  protected:
+    CClientClientDHTTemplate(const MPI_Comm& clientIntraComm);
+
+  protected:
+
+
+    // Redistribute index and info among clients
+    void computeDistributedIndex(const Index2InfoTypeMap& indexInfoInitMap,
+                                 const MPI_Comm& intraCommLevel,
+                                 int level);
+
+    void computeDistributedIndex(const Index2VectorInfoTypeMap& indexInfoInitMap,
+                                 const MPI_Comm& intraCommLevel,
+                                 int level);
+
+
+    void computeHashIndex(std::vector<size_t>& indexClientHash, int nbClient);
+
+    void computeIndexInfoMappingLevel(const CArray<size_t,1>& indices,
+                                      const MPI_Comm& intraCommLevel,
+                                      int level);
+
+    void computeSendRecvRank(int level, int rank);
+
+    void sendRecvRank(int level,
+                      const std::vector<int>& sendNbRank, const std::vector<int>& sendNbElements,
+                      std::vector<int>& recvNbRank, std::vector<int>& recvNbElements);
+
+  protected:
+    // Send information to clients
+    void sendInfoToClients(int clientDestRank, unsigned char* info, int infoSize,
+                           const MPI_Comm& clientIntraComm,
+                           std::vector<MPI_Request>& requestSendInfo);
+
+    void recvInfoFromClients(int clientSrcRank, unsigned char* info, int infoSize,
+                            const MPI_Comm& clientIntraComm,
+                            std::vector<MPI_Request>& requestRecvInfo);
+
+    // Send global index to clients
+    void sendIndexToClients(int clientDestRank, size_t* indices, size_t indiceSize,
+                            const MPI_Comm& clientIntraComm,
+                            std::vector<MPI_Request>& requestSendIndexGlobal);
+
+    void recvIndexFromClients(int clientSrcRank, size_t* indices, size_t indiceSize,
+                             const MPI_Comm& clientIntraComm,
+                             std::vector<MPI_Request>& requestRecvIndex);
+
+    void sendRecvOnReturn(const std::vector<int>& sendNbRank, std::vector<int>& sendNbElements,
+                          const std::vector<int>& recvNbRank, std::vector<int>& recvNbElements);
+
+  protected:
+    //! Mapping of global index to the corresponding client
+    Index2VectorInfoTypeMap index2InfoMapping_;
+
+    //! A mapping of index to the corresponding information in each level of hierarchy
+    Index2VectorInfoTypeMap indexToInfoMappingLevel_;
+
+    //! Rank of client to send on each DHT level
+    std::vector<std::vector<int> > sendRank_;
+
+    //! Rank of client to receive on each DHT level
+    std::vector<std::vector<int> > recvRank_;
+
+    //! Flag to specify whether data is distributed or not
+    bool isDataDistributed_;
+
+    //! Number of client
+    int nbClient_;
+};
+
+typedef CClientClientDHTTemplate<int> CClientClientDHTInt;
+typedef CClientClientDHTTemplate<size_t> CClientClientDHTSizet;
+typedef CClientClientDHTTemplate<double> CClientClientDHTDouble;
+typedef CClientClientDHTTemplate<PairIntInt> CClientClientDHTPairIntInt;
+
+} // namespace xios
+#endif // __XIOS_CLIENT_CLIENT_DHT_TEMPLATE_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template_impl.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template_impl.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_client_dht_template_impl.hpp	(revision 1918)
@@ -0,0 +1,737 @@
+/*!
+   \file client_client_dht_template_impl.hpp
+   \author Ha NGUYEN
+   \since 05 Oct 2015
+   \date 23 Mars 2016
+
+   \brief Distributed hashed table implementation.
+ */
+#include "client_client_dht_template.hpp"
+#include "utils.hpp"
+#include "mpi_tag.hpp"
+
+namespace xios
+{
+template<typename T, typename H>
+CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const MPI_Comm& clientIntraComm)
+  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
+{
+  MPI_Comm_size(clientIntraComm, &nbClient_);
+  this->computeMPICommLevel();
+  int nbLvl = this->getNbLevel();
+  sendRank_.resize(nbLvl);
+  recvRank_.resize(nbLvl);
+}
+
+/*!
+  Constructor with initial distribution information and the corresponding index
+  Each client (process) holds a piece of information as well as the attached index, the index
+will be redistributed (projected) into size_t space as long as the associated information.
+  \param [in] indexInfoMap initial index and information mapping
+  \param [in] clientIntraComm communicator of clients
+  \param [in] hierarLvl level of hierarchy
+*/
+template<typename T, typename H>
+CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const Index2InfoTypeMap& indexInfoMap,
+                                                        const MPI_Comm& clientIntraComm)
+  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
+{
+  MPI_Comm_size(clientIntraComm, &nbClient_);
+  this->computeMPICommLevel();
+  int nbLvl = this->getNbLevel();
+  sendRank_.resize(nbLvl);
+  recvRank_.resize(nbLvl);
+  Index2VectorInfoTypeMap indexToVecInfoMap;
+  indexToVecInfoMap.rehash(std::ceil(indexInfoMap.size()/indexToVecInfoMap.max_load_factor()));
+  typename Index2InfoTypeMap::const_iterator it = indexInfoMap.begin(), ite = indexInfoMap.end();
+  for (; it != ite; ++it) indexToVecInfoMap[it->first].push_back(it->second);
+  computeDistributedIndex(indexToVecInfoMap, clientIntraComm, nbLvl-1);
+}
+
+/*!
+  Constructor with initial distribution information and the corresponding index
+  Each client (process) holds a piece of information as well as the attached index, the index
+will be redistributed (projected) into size_t space as long as the associated information.
+  \param [in] indexInfoMap initial index and information mapping
+  \param [in] clientIntraComm communicator of clients
+  \param [in] hierarLvl level of hierarchy
+*/
+template<typename T, typename H>
+CClientClientDHTTemplate<T,H>::CClientClientDHTTemplate(const Index2VectorInfoTypeMap& indexInfoMap,
+                                                        const MPI_Comm& clientIntraComm)
+  : H(clientIntraComm), index2InfoMapping_(), indexToInfoMappingLevel_(), nbClient_(0)
+{
+  MPI_Comm_size(clientIntraComm, &nbClient_);
+  this->computeMPICommLevel();
+  int nbLvl = this->getNbLevel();
+  sendRank_.resize(nbLvl);
+  recvRank_.resize(nbLvl);
+  computeDistributedIndex(indexInfoMap, clientIntraComm, nbLvl-1);
+}
+
+template<typename T, typename H>
+CClientClientDHTTemplate<T,H>::~CClientClientDHTTemplate()
+{
+}
+
+/*!
+  Compute mapping between indices and information corresponding to these indices
+  \param [in] indices indices a proc has
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::computeIndexInfoMapping(const CArray<size_t,1>& indices)
+{
+  int nbLvl = this->getNbLevel();
+  computeIndexInfoMappingLevel(indices, this->internalComm_, nbLvl-1);
+}
+
+/*!
+    Compute mapping between indices and information corresponding to these indices
+for each level of hierarchical DHT. Recursive function
+   \param [in] indices indices a proc has
+   \param [in] commLevel communicator of current level
+   \param [in] level current level
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::computeIndexInfoMappingLevel(const CArray<size_t,1>& indices,
+                                                                 const MPI_Comm& commLevel,
+                                                                 int level)
+{
+  int clientRank;
+  MPI_Comm_rank(commLevel,&clientRank);
+  int groupRankBegin = this->getGroupBegin()[level];
+  int nbClient = this->getNbInGroup()[level];
+  std::vector<size_t> hashedIndex;
+  computeHashIndex(hashedIndex, nbClient);
+
+  size_t ssize = indices.numElements(), hashedVal;
+
+  std::vector<size_t>::const_iterator itbClientHash = hashedIndex.begin(), itClientHash,
+                                      iteClientHash = hashedIndex.end();
+  std::vector<int> sendBuff(nbClient,0);
+  std::vector<int> sendNbIndexBuff(nbClient,0);
+
+  // Number of global index whose mapping server are on other clients
+  int nbIndexToSend = 0;
+  size_t index;
+  HashXIOS<size_t> hashGlobalIndex;
+  std::unordered_map<size_t,int> nbIndices;
+  nbIndices.rehash(std::ceil(ssize/nbIndices.max_load_factor()));
+  for (int i = 0; i < ssize; ++i)
+  {
+    index = indices(i);
+    if (0 == nbIndices.count(index))
+    {
+      hashedVal  = hashGlobalIndex(index);
+      itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashedVal);
+      int indexClient = std::distance(itbClientHash, itClientHash)-1;
+      ++sendNbIndexBuff[indexClient];
+      nbIndices[index] = 1;
+    }
+  }
+
+  std::unordered_map<int, size_t* > client2ClientIndex;
+  for (int idx = 0; idx < nbClient; ++idx)
+  {
+    if (0 != sendNbIndexBuff[idx])
+    {
+      client2ClientIndex[idx+groupRankBegin] = new unsigned long [sendNbIndexBuff[idx]];
+      nbIndexToSend += sendNbIndexBuff[idx];
+      sendBuff[idx] = 1;
+      sendNbIndexBuff[idx] = 0;
+    }
+  }
+
+  for (int i = 0; i < ssize; ++i)
+  {
+    index = indices(i);
+    if (1 == nbIndices[index])
+    {
+      hashedVal  = hashGlobalIndex(index);
+      itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashedVal);
+      int indexClient = std::distance(itbClientHash, itClientHash)-1;
+      client2ClientIndex[indexClient+groupRankBegin][sendNbIndexBuff[indexClient]] = index;
+      ++sendNbIndexBuff[indexClient];
+      ++nbIndices[index];
+    }
+  }
+
+  std::vector<int> recvRankClient, recvNbIndexClientCount;
+  sendRecvRank(level, sendBuff, sendNbIndexBuff,
+               recvRankClient, recvNbIndexClientCount);
+
+  int recvNbIndexCount = 0;
+  for (int idx = 0; idx < recvNbIndexClientCount.size(); ++idx)
+    recvNbIndexCount += recvNbIndexClientCount[idx];
+
+  unsigned long* recvIndexBuff;
+  if (0 != recvNbIndexCount)
+    recvIndexBuff = new unsigned long[recvNbIndexCount];
+
+  std::vector<MPI_Request> request;
+  std::vector<int>::iterator itbRecvIndex = recvRankClient.begin(), itRecvIndex,
+                             iteRecvIndex = recvRankClient.end(),
+                           itbRecvNbIndex = recvNbIndexClientCount.begin(),
+                           itRecvNbIndex;
+  int currentIndex = 0;
+  int nbRecvClient = recvRankClient.size();
+  for (int idx = 0; idx < nbRecvClient; ++idx)
+  {
+    if (0 != recvNbIndexClientCount[idx])
+      recvIndexFromClients(recvRankClient[idx], recvIndexBuff+currentIndex, recvNbIndexClientCount[idx], commLevel, request);
+    currentIndex += recvNbIndexClientCount[idx];
+  }
+
+  std::unordered_map<int, size_t* >::iterator itbIndex = client2ClientIndex.begin(), itIndex,
+                                                iteIndex = client2ClientIndex.end();
+  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
+    sendIndexToClients(itIndex->first, (itIndex->second), sendNbIndexBuff[itIndex->first-groupRankBegin], commLevel, request);
+
+  std::vector<MPI_Status> status(request.size());
+  MPI_Waitall(request.size(), &request[0], &status[0]);
+
+  CArray<size_t,1>* tmpGlobalIndex;
+  if (0 != recvNbIndexCount)
+    tmpGlobalIndex = new CArray<size_t,1>(recvIndexBuff, shape(recvNbIndexCount), neverDeleteData);
+  else
+    tmpGlobalIndex = new CArray<size_t,1>();
+
+  // OK, we go to the next level and do something recursive
+  if (0 < level)
+  {
+    --level;
+    computeIndexInfoMappingLevel(*tmpGlobalIndex, this->internalComm_, level);
+  }
+  else // Now, we are in the last level where necessary mappings are.
+    indexToInfoMappingLevel_= (index2InfoMapping_);
+
+  typename Index2VectorInfoTypeMap::const_iterator iteIndexToInfoMap = indexToInfoMappingLevel_.end(), itIndexToInfoMap;
+  std::vector<int> sendNbIndexOnReturn(nbRecvClient,0);
+  currentIndex = 0;
+  for (int idx = 0; idx < nbRecvClient; ++idx)
+  {
+    for (int i = 0; i < recvNbIndexClientCount[idx]; ++i)
+    {
+      itIndexToInfoMap = indexToInfoMappingLevel_.find(*(recvIndexBuff+currentIndex+i));
+      if (iteIndexToInfoMap != itIndexToInfoMap)
+        sendNbIndexOnReturn[idx] += itIndexToInfoMap->second.size();
+    }
+    currentIndex += recvNbIndexClientCount[idx];
+  }
+
+  std::vector<int> recvRankOnReturn(client2ClientIndex.size());
+  std::vector<int> recvNbIndexOnReturn(client2ClientIndex.size(),0);
+  int indexIndex = 0;
+  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex, ++indexIndex)
+  {
+    recvRankOnReturn[indexIndex] = itIndex->first;
+  }
+  sendRecvOnReturn(recvRankClient, sendNbIndexOnReturn,
+                   recvRankOnReturn, recvNbIndexOnReturn);
+
+  int recvNbIndexCountOnReturn = 0;
+  for (int idx = 0; idx < recvRankOnReturn.size(); ++idx)
+    recvNbIndexCountOnReturn += recvNbIndexOnReturn[idx];
+
+  unsigned long* recvIndexBuffOnReturn;
+  unsigned char* recvInfoBuffOnReturn;
+  if (0 != recvNbIndexCountOnReturn)
+  {
+    recvIndexBuffOnReturn = new unsigned long[recvNbIndexCountOnReturn];
+    recvInfoBuffOnReturn = new unsigned char[recvNbIndexCountOnReturn*ProcessDHTElement<InfoType>::typeSize()];
+  }
+
+  std::vector<MPI_Request> requestOnReturn;
+  currentIndex = 0;
+  for (int idx = 0; idx < recvRankOnReturn.size(); ++idx)
+  {
+    if (0 != recvNbIndexOnReturn[idx])
+    {
+      recvIndexFromClients(recvRankOnReturn[idx], recvIndexBuffOnReturn+currentIndex, recvNbIndexOnReturn[idx], commLevel, requestOnReturn);
+      recvInfoFromClients(recvRankOnReturn[idx],
+                          recvInfoBuffOnReturn+currentIndex*ProcessDHTElement<InfoType>::typeSize(),
+                          recvNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize(),
+                          commLevel, requestOnReturn);
+    }
+    currentIndex += recvNbIndexOnReturn[idx];
+  }
+
+  std::unordered_map<int,unsigned char*> client2ClientInfoOnReturn;
+  std::unordered_map<int,size_t*> client2ClientIndexOnReturn;
+  currentIndex = 0;
+  for (int idx = 0; idx < nbRecvClient; ++idx)
+  {
+    if (0 != sendNbIndexOnReturn[idx])
+    {
+      int rank = recvRankClient[idx];
+      client2ClientIndexOnReturn[rank] = new unsigned long [sendNbIndexOnReturn[idx]];
+      client2ClientInfoOnReturn[rank] = new unsigned char [sendNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize()];
+      unsigned char* tmpInfoPtr = client2ClientInfoOnReturn[rank];
+      int infoIndex = 0;
+      int nb = 0;
+      for (int i = 0; i < recvNbIndexClientCount[idx]; ++i)
+      {
+        itIndexToInfoMap = indexToInfoMappingLevel_.find(*(recvIndexBuff+currentIndex+i));
+        if (iteIndexToInfoMap != itIndexToInfoMap)
+        {
+          const std::vector<InfoType>& infoTmp = itIndexToInfoMap->second;
+          for (int k = 0; k < infoTmp.size(); ++k)
+          {
+            client2ClientIndexOnReturn[rank][nb] = itIndexToInfoMap->first;
+            ProcessDHTElement<InfoType>::packElement(infoTmp[k], tmpInfoPtr, infoIndex);
+            ++nb;
+          }
+        }
+      }
+
+      sendIndexToClients(rank, client2ClientIndexOnReturn[rank],
+                         sendNbIndexOnReturn[idx], commLevel, requestOnReturn);
+      sendInfoToClients(rank, client2ClientInfoOnReturn[rank],
+                        sendNbIndexOnReturn[idx]*ProcessDHTElement<InfoType>::typeSize(), commLevel, requestOnReturn);
+    }
+    currentIndex += recvNbIndexClientCount[idx];
+  }
+
+  std::vector<MPI_Status> statusOnReturn(requestOnReturn.size());
+  MPI_Waitall(requestOnReturn.size(), &requestOnReturn[0], &statusOnReturn[0]);
+
+  Index2VectorInfoTypeMap indexToInfoMapping;
+  indexToInfoMapping.rehash(std::ceil(recvNbIndexCountOnReturn/indexToInfoMapping.max_load_factor()));
+  int infoIndex = 0;
+  InfoType unpackedInfo;
+  for (int idx = 0; idx < recvNbIndexCountOnReturn; ++idx)
+  {
+    ProcessDHTElement<InfoType>::unpackElement(unpackedInfo, recvInfoBuffOnReturn, infoIndex);
+    indexToInfoMapping[recvIndexBuffOnReturn[idx]].push_back(unpackedInfo);
+  }
+
+  indexToInfoMappingLevel_.swap(indexToInfoMapping);
+  if (0 != recvNbIndexCount) delete [] recvIndexBuff;
+  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndex.begin();
+                                                        it != client2ClientIndex.end(); ++it)
+      delete [] it->second;
+  delete tmpGlobalIndex;
+
+  if (0 != recvNbIndexCountOnReturn)
+  {
+    delete [] recvIndexBuffOnReturn;
+    delete [] recvInfoBuffOnReturn;
+  }
+
+  for (std::unordered_map<int,unsigned char*>::const_iterator it = client2ClientInfoOnReturn.begin();
+                                                               it != client2ClientInfoOnReturn.end(); ++it)
+      delete [] it->second;
+
+  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndexOnReturn.begin();
+                                            it != client2ClientIndexOnReturn.end(); ++it)
+      delete [] it->second;
+}
+
+/*!
+  Compute the hash index distribution of whole size_t space then each client will have a range of this distribution
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::computeHashIndex(std::vector<size_t>& hashedIndex, int nbClient)
+{
+  // Compute range of hash index for each client
+  hashedIndex.resize(nbClient+1);
+  size_t nbHashIndexMax = std::numeric_limits<size_t>::max();
+  size_t nbHashIndex;
+  hashedIndex[0] = 0;
+  for (int i = 1; i < nbClient; ++i)
+  {
+    nbHashIndex = nbHashIndexMax / nbClient;
+    if (i < (nbHashIndexMax%nbClient)) ++nbHashIndex;
+    hashedIndex[i] = hashedIndex[i-1] + nbHashIndex;
+  }
+  hashedIndex[nbClient] = nbHashIndexMax;
+}
+
+/*!
+  Compute distribution of global index for servers
+  Each client already holds a piece of information and its associated index.
+This information will be redistributed among processes by projecting indices into size_t space,
+the corresponding information will be also distributed on size_t space.
+After the redistribution, each client holds rearranged index and its corresponding information.
+  \param [in] indexInfoMap index and its corresponding info (usually server index)
+  \param [in] commLevel communicator of current level
+  \param [in] level current level
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::computeDistributedIndex(const Index2VectorInfoTypeMap& indexInfoMap,
+                                                            const MPI_Comm& commLevel,
+                                                            int level)
+{
+  int clientRank;
+  MPI_Comm_rank(commLevel,&clientRank);
+  computeSendRecvRank(level, clientRank);
+
+  int groupRankBegin = this->getGroupBegin()[level];
+  int nbClient = this->getNbInGroup()[level];
+  std::vector<size_t> hashedIndex;
+  computeHashIndex(hashedIndex, nbClient);
+
+  std::vector<int> sendBuff(nbClient,0);
+  std::vector<int> sendNbIndexBuff(nbClient,0);
+  std::vector<size_t>::const_iterator itbClientHash = hashedIndex.begin(), itClientHash,
+                                      iteClientHash = hashedIndex.end();
+  typename Index2VectorInfoTypeMap::const_iterator itb = indexInfoMap.begin(),it,
+                                                   ite = indexInfoMap.end();
+  HashXIOS<size_t> hashGlobalIndex;
+
+  // Compute size of sending and receving buffer
+  for (it = itb; it != ite; ++it)
+  {
+    size_t hashIndex = hashGlobalIndex(it->first);
+    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashIndex);
+    int indexClient = std::distance(itbClientHash, itClientHash)-1;
+    sendNbIndexBuff[indexClient] += it->second.size();
+  }
+
+  std::unordered_map<int, size_t*> client2ClientIndex;
+  std::unordered_map<int, unsigned char*> client2ClientInfo;
+  for (int idx = 0; idx < nbClient; ++idx)
+  {
+    if (0 != sendNbIndexBuff[idx])
+    {
+      client2ClientIndex[idx+groupRankBegin] = new unsigned long [sendNbIndexBuff[idx]];
+      client2ClientInfo[idx+groupRankBegin] = new unsigned char [sendNbIndexBuff[idx]*ProcessDHTElement<InfoType>::typeSize()];
+      sendNbIndexBuff[idx] = 0;
+      sendBuff[idx] = 1;
+    }
+  }
+
+  std::vector<int> sendNbInfo(nbClient,0);
+  for (it = itb; it != ite; ++it)
+  {
+    const std::vector<InfoType>& infoTmp = it->second;
+    size_t hashIndex = hashGlobalIndex(it->first);
+    itClientHash = std::upper_bound(itbClientHash, iteClientHash, hashIndex);
+    int indexClient = std::distance(itbClientHash, itClientHash)-1;
+    for (int idx = 0; idx < infoTmp.size(); ++idx)
+    {
+      client2ClientIndex[indexClient + groupRankBegin][sendNbIndexBuff[indexClient]] = it->first;;
+  //          ProcessDHTElement<InfoType>::packElement(it->second, client2ClientInfo[indexClient + groupRankBegin], sendNbInfo[indexClient]);
+      ProcessDHTElement<InfoType>::packElement(infoTmp[idx], client2ClientInfo[indexClient + groupRankBegin], sendNbInfo[indexClient]);
+      ++sendNbIndexBuff[indexClient];
+    }
+  }
+
+  // Calculate from how many clients each client receive message.
+  // Calculate size of buffer for receiving message
+  std::vector<int> recvRankClient, recvNbIndexClientCount;
+  sendRecvRank(level, sendBuff, sendNbIndexBuff,
+               recvRankClient, recvNbIndexClientCount);
+
+  int recvNbIndexCount = 0;
+  for (int idx = 0; idx < recvNbIndexClientCount.size(); ++idx)
+    recvNbIndexCount += recvNbIndexClientCount[idx];
+
+  unsigned long* recvIndexBuff;
+  unsigned char* recvInfoBuff;
+  if (0 != recvNbIndexCount)
+  {
+    recvIndexBuff = new unsigned long[recvNbIndexCount];
+    recvInfoBuff = new unsigned char[recvNbIndexCount*ProcessDHTElement<InfoType>::typeSize()];
+  }
+
+  // If a client holds information about index and the corresponding which don't belong to it,
+  // it will send a message to the correct clients.
+  // Contents of the message are index and its corresponding informatioin
+  std::vector<MPI_Request> request;
+  int currentIndex = 0;
+  int nbRecvClient = recvRankClient.size();
+  for (int idx = 0; idx < nbRecvClient; ++idx)
+  {
+    if (0 != recvNbIndexClientCount[idx])
+    {
+      recvIndexFromClients(recvRankClient[idx], recvIndexBuff+currentIndex, recvNbIndexClientCount[idx], commLevel, request);
+      recvInfoFromClients(recvRankClient[idx],
+                          recvInfoBuff+currentIndex*ProcessDHTElement<InfoType>::typeSize(),
+                          recvNbIndexClientCount[idx]*ProcessDHTElement<InfoType>::typeSize(),
+                          commLevel, request);
+    }
+    currentIndex += recvNbIndexClientCount[idx];
+  }
+
+  std::unordered_map<int, size_t* >::iterator itbIndex = client2ClientIndex.begin(), itIndex,
+                                                iteIndex = client2ClientIndex.end();
+  for (itIndex = itbIndex; itIndex != iteIndex; ++itIndex)
+    sendIndexToClients(itIndex->first, itIndex->second, sendNbIndexBuff[itIndex->first-groupRankBegin], commLevel, request);
+  std::unordered_map<int, unsigned char*>::iterator itbInfo = client2ClientInfo.begin(), itInfo,
+                                                      iteInfo = client2ClientInfo.end();
+  for (itInfo = itbInfo; itInfo != iteInfo; ++itInfo)
+    sendInfoToClients(itInfo->first, itInfo->second, sendNbInfo[itInfo->first-groupRankBegin], commLevel, request);
+
+  std::vector<MPI_Status> status(request.size());
+  MPI_Waitall(request.size(), &request[0], &status[0]);
+
+  Index2VectorInfoTypeMap indexToInfoMapping;
+  indexToInfoMapping.rehash(std::ceil(currentIndex/indexToInfoMapping.max_load_factor()));
+  currentIndex = 0;
+  InfoType infoValue;
+  int infoIndex = 0;
+  unsigned char* infoBuff = recvInfoBuff;
+  for (int idx = 0; idx < nbRecvClient; ++idx)
+  {
+    size_t index;
+    int count = recvNbIndexClientCount[idx];
+    for (int i = 0; i < count; ++i)
+    {
+      ProcessDHTElement<InfoType>::unpackElement(infoValue, infoBuff, infoIndex);
+      indexToInfoMapping[*(recvIndexBuff+currentIndex+i)].push_back(infoValue);
+    }
+    currentIndex += count;
+  }
+
+  if (0 != recvNbIndexCount)
+  {
+    delete [] recvIndexBuff;
+    delete [] recvInfoBuff;
+  }
+  for (std::unordered_map<int,unsigned char*>::const_iterator it = client2ClientInfo.begin();
+                                                               it != client2ClientInfo.end(); ++it)
+      delete [] it->second;
+
+  for (std::unordered_map<int,size_t*>::const_iterator it = client2ClientIndex.begin();
+                                                        it != client2ClientIndex.end(); ++it)
+      delete [] it->second;
+
+  // Ok, now do something recursive
+  if (0 < level)
+  {
+    --level;
+    computeDistributedIndex(indexToInfoMapping, this->internalComm_, level);
+  }
+  else
+    index2InfoMapping_.swap(indexToInfoMapping);
+}
+
+/*!
+  Send message containing index to clients
+  \param [in] clientDestRank rank of destination client
+  \param [in] indices index to send
+  \param [in] indiceSize size of index array to send
+  \param [in] clientIntraComm communication group of client
+  \param [in] requestSendIndex list of sending request
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::sendIndexToClients(int clientDestRank, size_t* indices, size_t indiceSize,
+                                                       const MPI_Comm& clientIntraComm,
+                                                       std::vector<MPI_Request>& requestSendIndex)
+{
+  MPI_Request request;
+  requestSendIndex.push_back(request);
+  MPI_Isend(indices, indiceSize, MPI_UNSIGNED_LONG,
+            clientDestRank, MPI_DHT_INDEX, clientIntraComm, &(requestSendIndex.back()));
+}
+
+/*!
+  Receive message containing index to clients
+  \param [in] clientDestRank rank of destination client
+  \param [in] indices index to send
+  \param [in] clientIntraComm communication group of client
+  \param [in] requestRecvIndex list of receiving request
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::recvIndexFromClients(int clientSrcRank, size_t* indices, size_t indiceSize,
+                                                         const MPI_Comm& clientIntraComm,
+                                                         std::vector<MPI_Request>& requestRecvIndex)
+{
+  MPI_Request request;
+  requestRecvIndex.push_back(request);
+  MPI_Irecv(indices, indiceSize, MPI_UNSIGNED_LONG,
+            clientSrcRank, MPI_DHT_INDEX, clientIntraComm, &(requestRecvIndex.back()));
+}
+
+/*!
+  Send message containing information to clients
+  \param [in] clientDestRank rank of destination client
+  \param [in] info info array to send
+  \param [in] infoSize info array size to send
+  \param [in] clientIntraComm communication group of client
+  \param [in] requestSendInfo list of sending request
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::sendInfoToClients(int clientDestRank, unsigned char* info, int infoSize,
+                                                      const MPI_Comm& clientIntraComm,
+                                                      std::vector<MPI_Request>& requestSendInfo)
+{
+  MPI_Request request;
+  requestSendInfo.push_back(request);
+
+  MPI_Isend(info, infoSize, MPI_CHAR,
+            clientDestRank, MPI_DHT_INFO, clientIntraComm, &(requestSendInfo.back()));
+}
+
+/*!
+  Receive message containing information from other clients
+  \param [in] clientDestRank rank of destination client
+  \param [in] info info array to receive
+  \param [in] infoSize info array size to receive
+  \param [in] clientIntraComm communication group of client
+  \param [in] requestRecvInfo list of sending request
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::recvInfoFromClients(int clientSrcRank, unsigned char* info, int infoSize,
+                                                        const MPI_Comm& clientIntraComm,
+                                                        std::vector<MPI_Request>& requestRecvInfo)
+{
+  MPI_Request request;
+  requestRecvInfo.push_back(request);
+
+  MPI_Irecv(info, infoSize, MPI_CHAR,
+            clientSrcRank, MPI_DHT_INFO, clientIntraComm, &(requestRecvInfo.back()));
+}
+
+/*!
+  Compute how many processes one process needs to send to and from how many processes it will receive.
+  This computation is only based on hierachical structure of distributed hash table (e.x: number of processes)
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::computeSendRecvRank(int level, int rank)
+{
+  int groupBegin = this->getGroupBegin()[level];
+  int nbInGroup  = this->getNbInGroup()[level];
+  const std::vector<int>& groupParentBegin = this->getGroupParentsBegin()[level];
+  const std::vector<int>& nbInGroupParents = this->getNbInGroupParents()[level];
+
+  std::vector<size_t> hashedIndexGroup;
+  computeHashIndex(hashedIndexGroup, nbInGroup);
+  size_t a = hashedIndexGroup[rank-groupBegin];
+  size_t b = hashedIndexGroup[rank-groupBegin+1]-1;
+
+  int currentGroup, offset;
+  size_t e,f;
+
+  // Do a simple math [a,b) intersect [c,d)
+  for (int idx = 0; idx < groupParentBegin.size(); ++idx)
+  {
+    std::vector<size_t> hashedIndexGroupParent;
+    int nbInGroupParent = nbInGroupParents[idx];
+    if (0 != nbInGroupParent)
+      computeHashIndex(hashedIndexGroupParent, nbInGroupParent);
+    for (int i = 0; i < nbInGroupParent; ++i)
+    {
+      size_t c = hashedIndexGroupParent[i];
+      size_t d = hashedIndexGroupParent[i+1]-1;
+
+    if (!((d < a) || (b <c)))
+        recvRank_[level].push_back(groupParentBegin[idx]+i);
+    }
+
+    offset = rank - groupParentBegin[idx];
+    if ((offset<nbInGroupParents[idx]) && (0 <= offset))
+    {
+      e = hashedIndexGroupParent[offset];
+      f = hashedIndexGroupParent[offset+1]-1;
+    }
+  }
+
+  std::vector<size_t>::const_iterator itbHashGroup = hashedIndexGroup.begin(), itHashGroup,
+                                      iteHashGroup = hashedIndexGroup.end();
+  itHashGroup = std::lower_bound(itbHashGroup, iteHashGroup, e+1);
+  int begin = std::distance(itbHashGroup, itHashGroup)-1;
+  itHashGroup = std::upper_bound(itbHashGroup, iteHashGroup, f);
+  int end = std::distance(itbHashGroup, itHashGroup) -1;
+  sendRank_[level].resize(end-begin+1);
+  for (int idx = 0; idx < sendRank_[level].size(); ++idx) sendRank_[level][idx] = idx + groupBegin + begin;
+}
+
+/*!
+  Compute number of clients as well as corresponding number of elements each client will receive on returning searching result
+  \param [in] sendNbRank Rank of clients to send to
+  \param [in] sendNbElements Number of elements each client to send to
+  \param [in] receiveNbRank Rank of clients to receive from
+  \param [out] recvNbElements Number of elements each client to send to
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::sendRecvOnReturn(const std::vector<int>& sendNbRank, std::vector<int>& sendNbElements,
+                                                     const std::vector<int>& recvNbRank, std::vector<int>& recvNbElements)
+{
+  recvNbElements.resize(recvNbRank.size());
+  std::vector<MPI_Request> request(sendNbRank.size()+recvNbRank.size());
+  std::vector<MPI_Status> requestStatus(sendNbRank.size()+recvNbRank.size());
+
+  int nRequest = 0;
+  for (int idx = 0; idx < recvNbRank.size(); ++idx)
+  {
+    MPI_Irecv(&recvNbElements[0]+idx, 1, MPI_INT,
+              recvNbRank[idx], MPI_DHT_INDEX_1, this->internalComm_, &request[nRequest]);
+    ++nRequest;
+  }
+
+  for (int idx = 0; idx < sendNbRank.size(); ++idx)
+  {
+    MPI_Isend(&sendNbElements[0]+idx, 1, MPI_INT,
+              sendNbRank[idx], MPI_DHT_INDEX_1, this->internalComm_, &request[nRequest]);
+    ++nRequest;
+  }
+
+  MPI_Waitall(sendNbRank.size()+recvNbRank.size(), &request[0], &requestStatus[0]);
+}
+
+/*!
+  Send and receive number of process each process need to listen to as well as number
+  of index it will receive during the initalization phase
+  \param [in] level current level
+  \param [in] sendNbRank Rank of clients to send to
+  \param [in] sendNbElements Number of elements each client to send to
+  \param [out] receiveNbRank Rank of clients to receive from
+  \param [out] recvNbElements Number of elements each client to send to
+*/
+template<typename T, typename H>
+void CClientClientDHTTemplate<T,H>::sendRecvRank(int level,
+                                                 const std::vector<int>& sendNbRank, const std::vector<int>& sendNbElements,
+                                                 std::vector<int>& recvNbRank, std::vector<int>& recvNbElements)
+{
+  int groupBegin = this->getGroupBegin()[level];
+
+  int offSet = 0;
+  std::vector<int>& sendRank = sendRank_[level];
+  std::vector<int>& recvRank = recvRank_[level];
+  int sendBuffSize = sendRank.size();
+  std::vector<int> sendBuff(sendBuffSize*2);
+  int recvBuffSize = recvRank.size();
+  std::vector<int> recvBuff(recvBuffSize*2,0);
+
+  std::vector<MPI_Request> request(sendBuffSize+recvBuffSize);
+  std::vector<MPI_Status> requestStatus(sendBuffSize+recvBuffSize);
+
+  int nRequest = 0;
+  for (int idx = 0; idx < recvBuffSize; ++idx)
+  {
+    MPI_Irecv(&recvBuff[0]+2*idx, 2, MPI_INT,
+              recvRank[idx], MPI_DHT_INDEX_0, this->internalComm_, &request[nRequest]);
+    ++nRequest;
+  }
+
+  for (int idx = 0; idx < sendBuffSize; ++idx)
+  {
+    offSet = sendRank[idx]-groupBegin;
+    sendBuff[idx*2] = sendNbRank[offSet];
+    sendBuff[idx*2+1] = sendNbElements[offSet];
+  }
+
+  for (int idx = 0; idx < sendBuffSize; ++idx)
+  {
+    MPI_Isend(&sendBuff[idx*2], 2, MPI_INT,
+              sendRank[idx], MPI_DHT_INDEX_0, this->internalComm_, &request[nRequest]);
+    ++nRequest;
+  }
+
+  MPI_Waitall(sendBuffSize+recvBuffSize, &request[0], &requestStatus[0]);
+  int nbRecvRank = 0, nbRecvElements = 0;
+  recvNbRank.clear();
+  recvNbElements.clear();
+  for (int idx = 0; idx < recvBuffSize; ++idx)
+  {
+    if (0 != recvBuff[2*idx])
+    {
+      recvNbRank.push_back(recvRank[idx]);
+      recvNbElements.push_back(recvBuff[2*idx+1]);
+    }
+  }
+}
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.cpp	(revision 1918)
@@ -0,0 +1,104 @@
+/*!
+   \file client_server_mapping.hpp
+   \author Ha NGUYEN
+   \since 04 Feb 2015
+   \date 09 Mars 2015
+
+   \brief Mapping between index client and server.
+ */
+#include "client_server_mapping.hpp"
+
+namespace xios {
+
+CClientServerMapping::CClientServerMapping()
+  : indexGlobalOnServer_()
+{
+}
+
+CClientServerMapping::~CClientServerMapping()
+{
+}
+
+/*!
+  Compute how many clients each server will receive data from
+  On client can send data to several servers as well as one server can receive data originated from
+some clients. In order to write data correctly, each server must know from how many clients it receives data
+  \param [in] nbServer number of servers
+  \param [in] nClient number of clients
+  \param [in] clientIntraComm MPI communication of clients
+  \param [in] connectedServerRank Rank of servers connected to the current client
+*/
+std::map<int,int> CClientServerMapping::computeConnectedClients(int nbServer, int nbClient,
+                                                                MPI_Comm& clientIntraComm,
+                                                                const std::vector<int>& connectedServerRank)
+{
+  std::map<int, int> connectedClients; // number of clients connected to a server
+
+  std::vector<int>::const_iterator itbVec, iteVec, it;
+  itbVec = it = connectedServerRank.begin();
+  iteVec = connectedServerRank.end();
+
+  std::vector<int> connectedServer;
+  std::vector<bool> isConnected(nbServer,false);
+
+  for (it = itbVec; it != iteVec; ++it)
+  {
+    for (int serverNum = 0; serverNum < nbServer; ++serverNum)
+      if (*it == serverNum) isConnected[serverNum] = true;
+  }
+
+  for(int serverNum = 0; serverNum<nbServer; ++serverNum)
+    if (isConnected[serverNum])
+      connectedServer.push_back(serverNum);
+
+
+  int nbConnectedServer=connectedServer.size();
+  int* recvCount=new int[nbClient];
+  int* displ=new int[nbClient];
+  int* sendBuff=new int[nbConnectedServer];
+  valarray<int> clientRes(0,nbServer);
+
+  for(int n=0;n<nbConnectedServer;n++) sendBuff[n]=connectedServer[n] ;
+
+  // get connected server for everybody
+  MPI_Allgather(&nbConnectedServer,1,MPI_INT,recvCount,1,MPI_INT,clientIntraComm) ;
+
+  displ[0]=0 ;
+  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvCount[n-1] ;
+  int recvSize=displ[nbClient-1]+recvCount[nbClient-1] ;
+  int* recvBuff=new int[recvSize] ;
+
+
+  MPI_Allgatherv(sendBuff,nbConnectedServer,MPI_INT,recvBuff,recvCount,displ,MPI_INT,clientIntraComm) ;
+  for(int n=0;n<recvSize;n++) clientRes[recvBuff[n]]++ ;
+
+  for(int n=0;n<nbConnectedServer;n++)
+  {
+    connectedClients[connectedServer[n]] = clientRes[connectedServer[n]];
+  }
+
+  delete [] recvCount ;
+  delete [] displ ;
+  delete [] sendBuff ;
+  delete [] recvBuff ;
+
+  return connectedClients;
+}
+
+/*!
+  Return global index of data on each connected server.
+  On receiving data sent from client(s), each server with this global index, is able to
+know where the data should be written.
+  \return mapping of server rank and its global index.
+*/
+const CClientServerMapping::GlobalIndexMap& CClientServerMapping::getGlobalIndexOnServer() const
+{
+  return indexGlobalOnServer_;
+}
+
+CClientServerMapping::GlobalIndexMap& CClientServerMapping::getGlobalIndexOnServer()
+{
+  return indexGlobalOnServer_;
+}
+
+} //namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping.hpp	(revision 1918)
@@ -0,0 +1,52 @@
+/*!
+   \file client_server_mapping.hpp
+   \author Ha NGUYEN
+   \since 04 Feb 2015
+   \date 09 Mars 2015
+
+   \brief Mapping between index client and server.
+ */
+#ifndef __XIOS_CLIENT_SERVER_MAPPING_HPP__
+#define __XIOS_CLIENT_SERVER_MAPPING_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "mpi.hpp"
+#include <unordered_map>
+
+namespace xios {
+
+/*!
+  \class CClientServerMapping
+  This class computes index of data which are sent to server as well as index of data
+on server side.
+*/
+class CClientServerMapping
+{
+public:
+  typedef std::unordered_map<int, std::vector<size_t> > GlobalIndexMap;
+  public:
+    /** Default constructor */
+    CClientServerMapping();
+
+    /** Default destructor */
+    virtual ~CClientServerMapping();
+
+    // Only need global index on client to calculate mapping (supposed client has info of distribution)
+    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient, int nbServer) = 0;
+
+    static std::map<int,int> computeConnectedClients(int nbServer, int nbClient,
+                                                     MPI_Comm& clientIntraComm,
+                                                     const std::vector<int>& connectedServerRank);
+
+    const GlobalIndexMap& getGlobalIndexOnServer() const;
+
+    GlobalIndexMap& getGlobalIndexOnServer();
+
+  protected:
+    //! Global index of data on SERVER, which are calculated by client(s)
+    GlobalIndexMap indexGlobalOnServer_;
+};
+
+} // namespace xios
+#endif // __XIOS_CLIENT_SERVER_MAPPING_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.cpp	(revision 1918)
@@ -0,0 +1,68 @@
+/*!
+   \file client_server_mapping.hpp
+   \author Ha NGUYEN
+   \since 27 Feb 2015
+   \date 16 Mars 2016
+
+   \brief Mapping between index client and server.
+   Clients pre-calculate all information of server distribution.
+ */
+#include "client_server_mapping_distributed.hpp"
+#include <limits>
+#include <boost/functional/hash.hpp>
+#include "utils.hpp"
+#include "mpi_tag.hpp"
+#include "context.hpp"
+#include "context_client.hpp"
+
+namespace xios
+{
+
+CClientServerMappingDistributed::CClientServerMappingDistributed(const std::unordered_map<size_t,int>& globalIndexOfServer,
+                                                                 const MPI_Comm& clientIntraComm, bool isDataDistributed)
+  : CClientServerMapping(), ccDHT_(0)
+{
+  ccDHT_ = new CClientClientDHTInt(globalIndexOfServer,
+                                   clientIntraComm);
+}
+
+CClientServerMappingDistributed::~CClientServerMappingDistributed()
+{
+  if (0 != ccDHT_) delete ccDHT_;
+}
+
+/*!
+   Compute mapping global index of server which client sends to.
+   \param [in] globalIndexOnClient global index client has
+   \param [in] nbServer size of server's intracomm
+*/
+void CClientServerMappingDistributed::computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClient, int nbServer)
+{
+
+  ccDHT_->computeIndexInfoMapping(globalIndexOnClient);
+  const CClientClientDHTInt::Index2VectorInfoTypeMap& infoIndexMap = (ccDHT_->getInfoIndexMap());
+  CClientClientDHTInt::Index2VectorInfoTypeMap::const_iterator itb = infoIndexMap.begin(), ite = infoIndexMap.end(), it;
+  std::vector<size_t> nbInfoIndex(std::max(ccDHT_->getNbClient(),nbServer),0);
+
+  for (it = itb; it != ite; ++it)
+  {
+    ++nbInfoIndex[it->second[0]];
+  }
+
+  for (int idx = 0; idx < nbInfoIndex.size(); ++idx)
+  {
+    if (0 != nbInfoIndex[idx])
+    {
+      indexGlobalOnServer_[idx].resize(nbInfoIndex[idx]);
+      nbInfoIndex[idx] = 0;
+    }
+  }
+
+  for (it = itb; it != ite; ++it)
+  {
+    indexGlobalOnServer_[it->second[0]][nbInfoIndex[it->second[0]]] = (it->first);
+    ++nbInfoIndex[it->second[0]];
+  }
+}
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/client_server_mapping_distributed.hpp	(revision 1918)
@@ -0,0 +1,50 @@
+/*!
+   \file client_server_mapping.hpp
+   \author Ha NGUYEN
+   \since 27 Feb 2015
+   \date 09 Mars 2015
+
+   \brief Mapping between index client and server.
+   Clients pre-calculate all information of server distribution.
+ */
+
+#ifndef __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
+#define __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
+
+#include <client_server_mapping.hpp>
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "mpi.hpp"
+#include <unordered_map>
+#include "client_client_dht_template.hpp"
+
+namespace xios
+{
+/*!
+  \class CClientServerMappingDistributed
+  This class computes index of data which are sent to server as well as index of data
+on server side with a distributed alogrithm. Each client has a piece of information about the distribution
+of servers. To find out all these info, first of all, all client join a discovering process in which each client
+announces the others about the info they have as well as demand others info they are lacked of. After this process,
+each client has enough info to decide to which client it need to send a demand for corresponding server of a global index.
+The alogrithm depends on hashed index.
+*/
+class CClientServerMappingDistributed : public CClientServerMapping
+{
+  public:
+    /** Default constructor */
+    CClientServerMappingDistributed(const std::unordered_map<size_t,int>& globalIndexOfServer,
+                                    const MPI_Comm& clientIntraComm,
+                                    bool isDataDistributed = true);
+
+    virtual void computeServerIndexMapping(const CArray<size_t,1>& globalIndexOnClientSendToServer, int nbServer);
+
+    /** Default destructor */
+    virtual ~CClientServerMappingDistributed();
+
+  protected:
+    CClientClientDHTInt* ccDHT_;
+};
+
+} // namespace xios
+#endif // __XIOS_CLIENT_SERVER_MAPPING_DISTRIBUTED_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.cpp	(revision 1918)
@@ -0,0 +1,115 @@
+/*!
+   \file dht_auto_indexing.cpp
+   \author Ha NGUYEN
+   \since 6 Jul 2016
+   \date 6 Jul 2016
+
+   \brief Auto assign global index across processes.
+ */
+#include "dht_auto_indexing.hpp"
+
+namespace xios
+{
+
+  CDHTAutoIndexing::~CDHTAutoIndexing()
+  {
+  }
+
+  /*!
+    \param [in]
+    \param [in]
+  */
+
+  CDHTAutoIndexing::CDHTAutoIndexing(const CArray<size_t,1>& hashValue,
+                                     const MPI_Comm& clientIntraComm)
+    : CClientClientDHTTemplate<size_t>(clientIntraComm)
+  {
+
+    nbIndexOnProc_ = hashValue.size();
+    size_t nbIndexAccum;
+    MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm);
+
+    // Broadcasting the total number of indexes
+    int rank, size;
+    MPI_Comm_rank(clientIntraComm, &rank);
+    MPI_Comm_size(clientIntraComm, &size);
+    if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum;
+    MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm);
+
+    CArray<size_t,1>::const_iterator itbIdx = hashValue.begin(), itIdx,
+                                     iteIdx = hashValue.end();
+
+    size_t idx = 0;
+    beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_;
+    globalIndex_.resize(nbIndexOnProc_);
+    for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx)
+    {
+      globalIndex_[idx] = beginIndexOnProc_ + idx;
+      ++idx ;
+    }
+  }
+
+  /*!
+   * \fn void CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap, const MPI_Comm& clientIntraComm)
+   * Assigns a global index to unique input indexes.
+   * The returned map has unique indexes as a key and global indexes as a mapped value.
+   * \param [in] hashInitMap map<size_t, vector<size_t>> is a map of unique indexes.
+   * \param [in] clientIntraComm
+  */
+  CDHTAutoIndexing::CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap,
+                                     const MPI_Comm& clientIntraComm)
+    : CClientClientDHTTemplate<size_t>(clientIntraComm)
+  {
+
+    nbIndexOnProc_ = hashInitMap.size();
+    size_t nbIndexAccum;
+    MPI_Scan(&nbIndexOnProc_, &nbIndexAccum, 1, MPI_UNSIGNED_LONG, MPI_SUM, clientIntraComm);
+
+    int rank, size;
+    MPI_Comm_rank(clientIntraComm, &rank);
+    MPI_Comm_size(clientIntraComm, &size);
+    if (rank == (size-1)) nbIndexesGlobal_ = nbIndexAccum;
+    MPI_Bcast(&nbIndexesGlobal_, 1, MPI_UNSIGNED_LONG, size-1, clientIntraComm);
+
+    Index2VectorInfoTypeMap::iterator itbIdx = hashInitMap.begin(), itIdx,
+                                      iteIdx = hashInitMap.end();
+    size_t idx = 0;
+    beginIndexOnProc_ = nbIndexAccum - nbIndexOnProc_;
+    globalIndex_.resize(nbIndexOnProc_);
+    for (itIdx = itbIdx; itIdx != iteIdx; ++itIdx)
+    {
+//      (itIdx->second)[0] = beginIndexOnProc_ + idx;
+      (itIdx->second)[1] = beginIndexOnProc_ + idx;
+      globalIndex_[idx] = beginIndexOnProc_ + idx;
+      ++idx ;
+    }
+  }
+
+  /*!
+   * \fn size_t CDHTAutoIndexing::getNbIndexesGlobal() const
+   * Returns the total number of global indexes.
+  */
+  size_t CDHTAutoIndexing::getNbIndexesGlobal() const
+  {
+    return nbIndexesGlobal_;
+  }
+
+  /*!
+   * \fn size_t CDHTAutoIndexing::getIndexStart() const
+   * Returns the starting global index for a proc.
+  */
+  size_t CDHTAutoIndexing::getIndexStart() const
+  {
+    return beginIndexOnProc_;
+  }
+
+  /*!
+   * \fn size_t CDHTAutoIndexing::getIndexCount() const
+   * Returns the number of global indexes on a proc.
+  */
+  size_t CDHTAutoIndexing::getIndexCount() const
+  {
+    return nbIndexOnProc_;
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_auto_indexing.hpp	(revision 1918)
@@ -0,0 +1,47 @@
+/*!
+   \file dht_auto_indexing.hpp
+   \author Ha NGUYEN
+   \since 6 Jul 2016
+   \date 6 Jul 2016
+
+   \brief Auto assign global index across processes.
+ */
+
+#ifndef __XIOS_DHT_AUTO_INDEXING_HPP__
+#define __XIOS_DHT_AUTO_INDEXING_HPP__
+
+#include "client_client_dht_template.hpp"
+
+namespace xios
+{
+
+/*!
+  \class CDHTAutoIndexing
+  .
+*/
+class CDHTAutoIndexing: public CClientClientDHTTemplate<size_t>
+{
+  public:
+
+    CDHTAutoIndexing(const CArray<size_t,1>& hashValue,
+                     const MPI_Comm& clientIntraComm);
+
+    CDHTAutoIndexing(Index2VectorInfoTypeMap& hashInitMap,
+                     const MPI_Comm& clientIntraComm);
+
+    size_t getNbIndexesGlobal() const;
+    size_t getIndexStart() const;
+    size_t getIndexCount() const;
+
+    /** Default destructor */
+    virtual ~CDHTAutoIndexing();
+
+  protected:
+    std::vector<size_t> globalIndex_;
+    size_t nbIndexesGlobal_;
+    size_t nbIndexOnProc_ ;
+    size_t beginIndexOnProc_ ;
+};
+
+} // namespace xios
+#endif // __XIOS_DHT_AUTO_INDEXING_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_data_types.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_data_types.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/dht_data_types.hpp	(revision 1918)
@@ -0,0 +1,77 @@
+/*!
+   \file dht_data_types.hpp
+   \author Ha NGUYEN
+   \since 17 Mars 2016
+   \date 17 Mars 2016
+
+   \brief Customized data type for dht
+ */
+
+#ifndef __XIOS_DHT_DATATYPES_HPP__
+#define __XIOS_DHT_DATATYPES_HPP__
+
+#include "utils.hpp"
+
+namespace xios
+{
+typedef std::pair<int,int> PairIntInt;
+
+template<typename T>
+struct ProcessDHTElement
+{
+  typedef T Type;
+  static int typeSize()
+  {
+    return sizeof(Type);
+  }
+
+  static void packElement(const T& inputElement, unsigned char* packedElement, int& index)
+  {
+    if (NULL == packedElement) index += sizeof(Type);
+    else
+    {
+      *(T *)(&packedElement[index]) = inputElement;
+      index+=sizeof(Type);
+    }
+  }
+
+  static void unpackElement(T& outputElement, unsigned char* unpackedElement, int& index)
+  {
+    outputElement = *(Type*)(&unpackedElement[index]);
+    index+=sizeof(Type);
+  }
+};
+
+template<>
+struct ProcessDHTElement<PairIntInt>
+{
+  typedef PairIntInt Type;
+  static int typeSize()
+  {
+    return (2*sizeof(int));
+  }
+
+  static void packElement(const PairIntInt& inputElement, unsigned char* packedElement, int& index)
+  {
+    if (NULL == packedElement) index +=(2*sizeof(int));
+    else
+    {
+      *(int *)(&packedElement[index]) = inputElement.first;
+      index+=sizeof(int);
+      *(int *)(&packedElement[index]) = inputElement.second;
+      index+=sizeof(int);
+    }
+  }
+
+  static void unpackElement(PairIntInt& outputElement, unsigned char* unpackedElement, int& index)
+  {
+    outputElement.first=*(int *)(&unpackedElement[index]);
+    index+=sizeof(int);
+    outputElement.second=*(int *)(&unpackedElement[index]);
+    index+=sizeof(int);
+  }
+};
+
+}
+
+#endif // __XIOS_DHT_DATATYPES_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.cpp	(revision 1918)
@@ -0,0 +1,19 @@
+#include "element_view.hpp"
+#include "element.hpp"
+#include "distributed_view.hpp"
+
+namespace xios
+{
+
+  CDistributedView::CDistributedView(CDistributedElement* parent, CElementView::type, const std::map<int,CArray<int,1>>& indexView) 
+                                    : globalIndex_(parent->globalIndex_), globalSize_(parent->globalSize_), localSize_(parent->localSize_) 
+  {
+    for(auto index : indexView) 
+    {
+      index_[index.first].reference(index.second.copy()) ;
+      size_[index.first] = index.second.numElements() ;
+    }
+  }
+
+
+} 
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distributed_view.hpp	(revision 1918)
@@ -0,0 +1,59 @@
+#ifndef __DISTRIBUTED_VIEW_HPP__
+#define __DISTRIBUTED_VIEW_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "element_view.hpp"
+
+namespace xios
+{
+  class CDistributedElement;
+
+  class CDistributedView : public CElementView
+  {
+    public:
+
+      CDistributedView(CDistributedElement* parent, CElementView::type type, const std::map<int,CArray<int,1>>& indexView) ;
+      
+      std::map<int,CArray<int,1>>&  getIndex(void) { return index_ ;}
+      std::map<int,CArray<size_t,1>>&  getGlobalIndex(void) { return globalIndex_ ;}
+      std::map<int, int>& getSize(void) { return size_ ;}
+      std::map<int, int>& getLocalSize(void) { return localSize_ ;}
+      size_t getGlobalSize(void) { return globalSize_ ;}
+
+      void getGlobalIndex(int rank, vector<size_t>& globalIndex, size_t sliceIndex, size_t* sliceSize, CDistributedView** view, int pos)
+      {
+        // using map can be expensive, find an otherway later
+        auto& globalInd=globalIndex_[rank] ;
+        int localSize=globalInd.numElements() ;
+        auto& index=index_[rank] ;
+        int size=index.numElements() ;
+                
+        if (pos==0)
+        {
+          for(int i=0;i<size;i++)
+            if (index(i)>=0 && index(i)<localSize) globalIndex.push_back(sliceIndex + globalInd(index(i))) ;
+        }
+        else 
+        {
+          for(int i=0;i<size;i++)
+            if (index(i)>=0 && index(i)<localSize) 
+              view[pos-1]->getGlobalIndex(rank, globalIndex, sliceIndex + globalInd(index(i))*sliceSize[pos], sliceSize, view , pos-1) ;
+        }
+      }
+
+
+    protected:
+
+      std::map<int,CArray<int,1>> index_ ;
+      std::map<int, int> size_;
+
+      std::map<int,CArray<size_t,1>>& globalIndex_ ; 
+      size_t& globalSize_ ;
+      std::map<int, int>& localSize_ ;
+    
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.cpp	(revision 1918)
@@ -0,0 +1,38 @@
+/*!
+   \file distribution.hpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 09 Feb 2015
+
+   \brief Index distribution on server side.
+ */
+#include "distribution.hpp"
+
+namespace xios {
+
+CDistribution::CDistribution(int rank, int dims, const CArray<size_t,1>& globalIndex)
+  : rank_(rank), dims_(dims), globalIndex_(globalIndex.shape())
+{
+  if (0 != globalIndex.numElements())
+    globalIndex_ = globalIndex;
+}
+
+const CArray<size_t,1>& CDistribution:: getGlobalIndex() const 
+{ 
+  return globalIndex_; 
+}
+
+CDistribution::~CDistribution()
+{ /* Nothing to do */ }
+
+int CDistribution::getDims() const
+{
+  return dims_;
+}
+
+int CDistribution::getRank() const
+{
+  return rank_;
+}
+
+} // namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution.hpp	(revision 1918)
@@ -0,0 +1,49 @@
+/*!
+   \file distribution.hpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 09 Feb 2015
+
+   \brief Index distribution on server side.
+ */
+#ifndef __XIOS_DISTRIBUTION_HPP__
+#define __XIOS_DISTRIBUTION_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include <unordered_map>
+
+namespace xios {
+/*!
+ \class CDistribution
+ The parent class of CDistributionClient and CDistributionServer, which declares and defines
+some basic methods and properties for its children. This class allows its descendants to calculate
+distribution of index on client or server side.
+*/
+class CDistribution
+{
+  public:
+  typedef std::unordered_map<size_t,int> GlobalLocalMap;
+
+  public:
+    /** Default constructor */
+    CDistribution(int rank, int dims, const CArray<size_t,1>& globalIndex = CArray<size_t,1>());
+
+    /** Default destructor */
+    virtual ~CDistribution();
+
+    int getDims() const; //! Get dimension size
+    int getRank() const; //! Get rank of current process
+    const CArray<size_t,1>& getGlobalIndex() const;
+    
+  protected:
+    virtual void createGlobalIndex() {};
+
+  protected:
+    CArray<size_t,1> globalIndex_;
+    int dims_;
+    int rank_;
+};
+
+} // namespace xios
+#endif // __XIOS_DISTRIBUTION_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.cpp	(revision 1918)
@@ -0,0 +1,610 @@
+/*!
+   \file distribution_client.cpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 09 Mars 2015
+
+   \brief Index distribution on client side.
+ */
+#include "distribution_client.hpp"
+
+namespace xios {
+
+CDistributionClient::CDistributionClient(int rank, CGrid* grid)
+   : CDistribution(rank, 0)
+   , axisDomainOrder_()
+   , nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_()
+   , dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_()
+   , gridMask_(), indexMap_()
+   , isDataDistributed_(true), axisNum_(0), domainNum_(0)
+   , localDataIndex_(), localMaskIndex_()
+   , globalLocalDataSendToServerMap_()
+   , infoIndex_(), isComputed_(false)
+   , elementLocalIndex_(), elementGlobalIndex_(), elementIndexData_()
+   , elementNLocal_(), elementNGlobal_()
+{
+  readDistributionInfo(grid);
+  createGlobalIndex();
+}
+
+CDistributionClient::~CDistributionClient()
+{ /* Nothing to do */ }
+
+void CDistributionClient::partialClear()
+{
+  GlobalLocalMap void1 ;
+  GlobalLocalMap void2 ;
+  std::vector<int> void3 ;
+  std::vector<bool> void4 ;
+
+  globalLocalDataSendToServerMap_.swap(void1) ;
+  globalDataIndex_.swap(void2) ;
+  localDataIndex_.swap(void3);
+  localMaskIndex_.swap(void4) ;
+}
+
+/*!
+  Read information of a grid to generate distribution.
+  Every grid is composed of several axis or/and domain(s). Their information are processed
+stored and used to calculate index distribution between client and server
+  \param [in] grid Grid to read
+*/
+void CDistributionClient::readDistributionInfo(CGrid* grid)
+{
+  std::vector<CDomain*> domList = grid->getDomains();
+  std::vector<CAxis*> axisList = grid->getAxis();
+  std::vector<CScalar*> scalarList = grid->getScalars();
+  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
+
+  readDistributionInfo(domList, axisList, scalarList, axisDomainOrder);
+
+  // Then check mask of grid
+  int gridDim = domList.size() * 2 + axisList.size();
+  switch (gridDim) {
+    case 0:
+      gridMask_.resize(1);
+      gridMask_(0) = true;
+      break;
+    case 1:
+      if (!grid->mask_1d.isEmpty()) readGridMaskInfo(grid->mask_1d);
+      break;
+    case 2:
+      if (!grid->mask_2d.isEmpty()) readGridMaskInfo(grid->mask_2d);
+      break;
+    case 3:
+      if (!grid->mask_3d.isEmpty()) readGridMaskInfo(grid->mask_3d);
+      break;
+    case 4:
+      if (!grid->mask_4d.isEmpty()) readGridMaskInfo(grid->mask_4d);
+      break;
+    case 5:
+      if (!grid->mask_5d.isEmpty()) readGridMaskInfo(grid->mask_5d);
+      break;
+    case 6:
+      if (!grid->mask_6d.isEmpty()) readGridMaskInfo(grid->mask_6d);
+      break;
+    case 7:
+      if (!grid->mask_7d.isEmpty()) readGridMaskInfo(grid->mask_7d);
+      break;
+    default:
+      break;
+  }
+}
+
+/*!
+  Read information from domain(s) and axis to generate distribution.
+  All information related to domain, e.g ibegin, jbegin, ni, nj, ni_glo, nj_glo
+as well as related to axis, e.g dataNIndex, dataIndex will be stored to compute
+the distribution between clients and servers. Till now, every data structure of domain has been kept
+like before, e.g: data_n_index to make sure a compability, however, it should be changed?
+  \param [in] domList List of domains of grid
+  \param [in] axisList List of axis of grid
+  \param [in] scalarList List of scalar of grid
+  \param [in] axisDomainOrder order of axis and domain inside a grid. 2 if domain, 1 if axis and zero if scalar
+//  \param [in] gridMask Mask of grid, for now, keep it 3 dimension, but it needs changing
+*/
+void CDistributionClient::readDistributionInfo(const std::vector<CDomain*>& domList,
+                                               const std::vector<CAxis*>& axisList,
+                                               const std::vector<CScalar*>& scalarList,
+                                               const CArray<int,1>& axisDomainOrder)
+{
+  domainNum_ = domList.size();
+  axisNum_   = axisList.size();
+  numElement_ = axisDomainOrder.numElements(); // Number of element, e.x: Axis, Domain
+
+  axisDomainOrder_.resize(numElement_);
+  axisDomainOrder_ = axisDomainOrder;
+
+  // Because domain and axis can be in any order (axis1, domain1, axis2, axis3, )
+  // their position should be specified. In axisDomainOrder, domain == true, axis == false
+  int idx = 0;
+  indexMap_.resize(numElement_);
+  this->dims_ = numElement_;
+  for (int i = 0; i < numElement_; ++i)
+  {
+    indexMap_[i] = idx;
+    if (2 == axisDomainOrder(i))
+    {
+      ++(this->dims_);
+      idx += 2;
+    }
+    else ++idx;
+  }
+
+  // Size of each dimension (local and global)
+  nLocal_.resize(this->dims_);
+  nGlob_.resize(this->dims_);
+  nBeginLocal_.resize(this->dims_,0);
+  nBeginGlobal_.resize(this->dims_,0);
+
+  // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
+  dataNIndex_.resize(numElement_);
+  dataDims_.resize(numElement_);
+  dataBegin_.resize(this->dims_);
+
+  // Data_*_index of each dimension
+  dataIndex_.resize(this->dims_);
+  infoIndex_.resize(this->dims_);
+
+  // A trick to determine position of each domain in domainList
+  int domIndex = 0, axisIndex = 0, scalarIndex = 0;
+  idx = 0;
+
+  elementLocalIndex_.resize(numElement_);
+  elementGlobalIndex_.resize(numElement_);
+  elementIndexData_.resize(numElement_);
+  elementNLocal_.resize(numElement_);
+  elementNGlobal_.resize(numElement_);
+  elementNLocal_[0] = 1;
+  elementNGlobal_[0] = 1;
+  size_t localSize = 1, globalSize = 1;
+
+  isDataDistributed_ = false;
+  // Update all the vectors above
+  for (idx = 0; idx < numElement_; ++idx)
+  {
+    int eleDim = axisDomainOrder(idx);
+    elementNLocal_[idx] = localSize;
+    elementNGlobal_[idx] = globalSize;
+
+    // If this is a domain
+    if (2 == eleDim)
+    {
+      // On the j axis
+      nLocal_.at(indexMap_[idx]+1) = domList[domIndex]->nj.getValue();
+      nGlob_.at(indexMap_[idx]+1)  = domList[domIndex]->nj_glo.getValue();
+      nBeginLocal_.at(indexMap_[idx]+1) = 0;
+      nBeginGlobal_.at(indexMap_[idx]+1) = domList[domIndex]->jbegin;
+
+      dataBegin_.at(indexMap_[idx]+1) = domList[domIndex]->data_jbegin.getValue();
+      dataIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->data_j_index);
+      infoIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->j_index);
+
+      // On the i axis
+      nLocal_.at(indexMap_[idx]) = domList[domIndex]->ni.getValue();
+      nGlob_.at(indexMap_[idx]) = domList[domIndex]->ni_glo.getValue();
+      nBeginLocal_.at(indexMap_[idx]) = 0;
+      nBeginGlobal_.at(indexMap_[idx]) = domList[domIndex]->ibegin;
+
+      dataBegin_.at(indexMap_[idx]) = domList[domIndex]->data_ibegin.getValue();
+      dataIndex_.at(indexMap_[idx]).reference(domList[domIndex]->data_i_index);
+      infoIndex_.at(indexMap_[idx]).reference(domList[domIndex]->i_index);
+
+      dataNIndex_.at(idx) = domList[domIndex]->data_i_index.numElements();
+      dataDims_.at(idx) = domList[domIndex]->data_dim.getValue();
+
+      isDataDistributed_ |= domList[domIndex]->isDistributed();
+
+      localSize *= nLocal_.at(indexMap_[idx]+1)* nLocal_.at(indexMap_[idx]);
+      globalSize *= nGlob_.at(indexMap_[idx]+1)* nGlob_.at(indexMap_[idx]);
+      ++domIndex;
+    }
+    else if (1 == eleDim)// So it's an axis
+    {
+      nLocal_.at(indexMap_[idx]) = axisList[axisIndex]->n.getValue();
+      nGlob_.at(indexMap_[idx]) = axisList[axisIndex]->n_glo.getValue();
+      nBeginLocal_.at(indexMap_[idx]) = 0;
+      nBeginGlobal_.at(indexMap_[idx]) = axisList[axisIndex]->begin.getValue();
+
+      dataBegin_.at(indexMap_[idx]) = axisList[axisIndex]->data_begin.getValue();
+      dataIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->data_index);
+      infoIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->index);
+      dataNIndex_.at(idx) = axisList[axisIndex]->data_index.numElements();
+      dataDims_.at(idx) = 1;
+
+      isDataDistributed_ |= axisList[axisIndex]->isDistributed();
+
+      localSize *= nLocal_.at(indexMap_[idx]);
+      globalSize *= nGlob_.at(indexMap_[idx]);
+
+      ++axisIndex;
+    }
+    else // scalar
+    {
+      nLocal_.at(indexMap_[idx]) = 1;
+      nGlob_.at(indexMap_[idx]) = 1;
+      nBeginLocal_.at(indexMap_[idx]) = 0;
+      nBeginGlobal_.at(indexMap_[idx]) = 1;
+
+      dataBegin_.at(indexMap_[idx]) = 0;
+      dataIndex_.at(indexMap_[idx]).resize(1); dataIndex_.at(indexMap_[idx])(0) = 0;
+      infoIndex_.at(indexMap_[idx]).resize(1); infoIndex_.at(indexMap_[idx])(0) = 0;
+      dataNIndex_.at(idx) = 1;
+      dataDims_.at(idx) = 1;
+
+      isDataDistributed_ |= false;
+
+      localSize *= nLocal_.at(indexMap_[idx]);
+      globalSize *= nGlob_.at(indexMap_[idx]);
+
+      ++scalarIndex;
+    }
+  }
+}
+
+/*!
+  Create local index of domain(s).
+  A domain can have data index which even contains the "ghost" points. Very often, these
+data surround the true data. In order to send correct data to server,
+a client need to know index of the true data.
+*/
+void CDistributionClient::createLocalDomainDataIndex()
+{
+  int idxDomain = 0;
+  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
+  {
+    if (2 == axisDomainOrder_(i))
+    {
+      elementIndexData_[i].resize(dataNIndex_[i]);
+      elementIndexData_[i] = false;
+      int iIdx, jIdx = 0, count = 0, localIndex;
+      for (int j = 0; j < dataNIndex_[i]; ++j)
+      {
+        iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
+                              dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
+                              dataDims_[i], nLocal_[indexMap_[i]], jIdx);
+
+        if ((iIdx >= nBeginLocal_[indexMap_[i]]) && (iIdx < nLocal_[indexMap_[i]]) &&
+           (jIdx >= nBeginLocal_[indexMap_[i]+1]) && (jIdx < nLocal_[indexMap_[i]+1]))
+        {
+          ++count;
+          elementIndexData_[i](j) = true;
+        }
+      }
+
+      elementLocalIndex_[i].resize(count);
+      elementGlobalIndex_[i].resize(count);
+      count = 0;
+      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
+      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
+      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
+      for (int j = 0; j < dataNIndex_[i]; ++j)
+      {
+        if (tmpIndexElementData(j))
+        {
+          iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
+                                dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
+                                dataDims_[i], nLocal_[indexMap_[i]], jIdx);
+          localIndex = tmpLocalElementIndex(count) = iIdx + jIdx * nLocal_[indexMap_[i]];
+          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(localIndex) + ((infoIndex_[indexMap_[i]+1])(localIndex))*nGlob_[indexMap_[i]];
+          ++count;
+        }
+      }
+      ++idxDomain;
+    }
+  }
+}
+
+/*!
+  Create local index of axis.
+*/
+void CDistributionClient::createLocalAxisDataIndex()
+{
+  int idxAxis = 0;
+  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
+  {
+    if (1 == axisDomainOrder_(i))
+    {
+      elementIndexData_[i].resize(dataNIndex_[i]);
+      elementIndexData_[i] = false;
+      int iIdx = 0, count = 0;
+      for (int j = 0; j < dataNIndex_[i]; ++j)
+      {
+        iIdx = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
+        if ((iIdx >= nBeginLocal_[indexMap_[i]]) &&
+           (iIdx < nLocal_[indexMap_[i]]) )//&& (axisMasks_[idxAxis](iIdx)))
+        {
+          ++count;
+          elementIndexData_[i](j) = true;
+        }
+      }
+
+      elementLocalIndex_[i].resize(count);
+      elementGlobalIndex_[i].resize(count);
+      count = 0;
+      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
+      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
+      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
+      for (int j = 0; j < dataNIndex_[i]; ++j)
+      {
+        if (tmpIndexElementData(j))
+        {
+          iIdx = tmpLocalElementIndex(count) = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
+          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(iIdx);
+          ++count;
+        }
+      }
+      ++idxAxis;
+    }
+  }
+}
+
+/*!
+  Create local index of scalar.
+*/
+void CDistributionClient::createLocalScalarDataIndex()
+{
+  int idxAxis = 0;
+  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
+  {
+    if (0 == axisDomainOrder_(i))
+    {
+      elementIndexData_[i].resize(dataNIndex_[i]);
+      elementIndexData_[i] = true;
+      int count = 1;
+
+      elementLocalIndex_[i].resize(count);
+      elementLocalIndex_[i] = 0;
+      elementGlobalIndex_[i].resize(count);
+      elementGlobalIndex_[i] = 0;
+    }
+  }
+}
+
+/*!
+   Create global index on client
+   In order to do the mapping between client-server, each client creates its own
+global index of sending data. This global index is then used to calculate to which server
+the client needs to send it data as well as which part of data belongs to the server.
+So as to make clients and server coherent in order of index, global index is calculated by
+take into account of C-convention, the rightmost dimension varies faster.
+*/
+void CDistributionClient::createGlobalIndexSendToServer()
+{
+  if (isComputed_) return;
+  isComputed_ = true;
+  createLocalDomainDataIndex();
+  createLocalAxisDataIndex();
+  createLocalScalarDataIndex();
+
+  int idxDomain = 0, idxAxis = 0;
+  std::vector<int> eachElementSize(numElement_);
+
+  // Precompute size of the loop
+  for (int i = 0; i < numElement_; ++i)
+  {
+    eachElementSize[i] = elementLocalIndex_[i].numElements();
+  }
+
+  //   Compute size of the global index on client
+  std::vector<StdSize> idxLoop(numElement_,0);
+  std::vector<StdSize> currentIndex(numElement_,0);
+  std::vector<StdSize> currentGlobalIndex(numElement_,0);
+  int innerLoopSize = eachElementSize[0];
+  size_t idx = 0, indexLocalDataOnClientCount = 0;
+  size_t ssize = 1;
+
+  for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i];
+  localDataSize_=ssize ;
+
+  localDataIndex_.resize(ssize);
+  if (!gridMask_.isEmpty()) localMaskIndex_.resize(ssize);
+  localMaskedDataIndex_.resize(ssize);
+  globalDataIndex_.rehash(std::ceil(ssize/globalDataIndex_.max_load_factor()));
+  globalLocalDataSendToServerMap_.rehash(std::ceil(ssize/globalLocalDataSendToServerMap_.max_load_factor()));
+
+
+  // We need to loop with data index
+  idxLoop.assign(numElement_,0);
+  idx = indexLocalDataOnClientCount = 0;
+  ssize = 1; for (int i = 0; i < numElement_; ++i) ssize *= dataNIndex_[i];
+  innerLoopSize = dataNIndex_[0];
+  int countLocalData = 0;
+  std::vector<int> correctIndexOfElement(numElement_,0);
+  bool isOuterIndexCorrect = true;
+  while (idx < ssize)
+  {
+    for (int i = 0; i < numElement_-1; ++i)
+    {
+      if (idxLoop[i] == dataNIndex_[i])
+      {
+        idxLoop[i] = 0;
+        correctIndexOfElement[i] = 0;
+        ++idxLoop[i+1];
+        if (isOuterIndexCorrect) ++correctIndexOfElement[i+1];
+      }
+    }
+
+    // Depending the inner-most element axis or domain,
+    // The outer loop index begins correspondingly at one (1) or zero (0)
+    bool isIndexElementDataCorrect = true;
+    for (int i = 1; i < numElement_; ++i)
+    {
+      if (elementIndexData_[i](idxLoop[i]))
+      {
+        currentIndex[i] = elementLocalIndex_[i](correctIndexOfElement[i]);
+        currentGlobalIndex[i] = elementGlobalIndex_[i](correctIndexOfElement[i]);
+        isIndexElementDataCorrect &= true;
+      }
+      else isIndexElementDataCorrect = false;
+    }
+
+    isOuterIndexCorrect = isIndexElementDataCorrect;
+
+    if (isOuterIndexCorrect)
+    {
+      // Inner most index
+      int correctIndexInnerElement = 0;
+      for (int i = 0; i < innerLoopSize; ++i)
+      {
+        bool isCurrentIndexDataCorrect = isOuterIndexCorrect;
+        if (elementIndexData_[0](i))
+        {
+          currentIndex[0] = elementLocalIndex_[0](correctIndexInnerElement);
+          currentGlobalIndex[0] = elementGlobalIndex_[0](correctIndexInnerElement);
+          isCurrentIndexDataCorrect &= true;
+          ++correctIndexInnerElement;
+        }
+        else isCurrentIndexDataCorrect = false;
+
+        if (isCurrentIndexDataCorrect)
+        {
+          bool maskTmp = true;
+          bool maskGridTmp = true;
+          size_t globalIndex = 0;
+          for (int k = 0; k < numElement_; ++k)
+          {
+            globalIndex += (currentGlobalIndex[k])*elementNGlobal_[k];
+          }
+          globalDataIndex_[globalIndex] = indexLocalDataOnClientCount;
+          localDataIndex_[indexLocalDataOnClientCount] = countLocalData;
+          globalLocalDataSendToServerMap_[globalIndex] = indexLocalDataOnClientCount;
+          localMaskedDataIndex_[indexLocalDataOnClientCount] = indexLocalDataOnClientCount;
+
+          // Grid mask: unmasked values will be replaces by NaN and then all values will be sent
+          if (!gridMask_.isEmpty())
+          {
+            int gridMaskIndex = 0;
+            for (int k = 0; k < this->numElement_; ++k)
+            {
+              gridMaskIndex += (currentIndex[k])*elementNLocal_[k];
+            }
+            maskGridTmp =  gridMask_(gridMaskIndex);
+            if (maskGridTmp)
+              localMaskIndex_[indexLocalDataOnClientCount] = true;
+            else
+              localMaskIndex_[indexLocalDataOnClientCount] = false;
+          }
+
+          ++indexLocalDataOnClientCount;
+
+        }
+        ++countLocalData;
+        correctIndexOfElement[0] = correctIndexInnerElement;;
+      }
+    }
+    else countLocalData+=innerLoopSize ;
+
+    idxLoop[0] += innerLoopSize;
+    idx += innerLoopSize;
+  }
+}
+
+void CDistributionClient::createGlobalIndex()
+{
+}
+
+/*!
+  Retrieve index i and index j of a domain from its data index
+  Data contains not only true data, which are sent to servers, but also ghost data, which
+very often play a role of border of each local data, so does data index. Because data of a domain
+can be one dimension, or two dimensions, there is a need to convert data index to domain index
+  \param [in] dataIIndex index of i data
+  \param [in] dataJIndex index of j data
+  \param [in] dataIBegin index begin of i data
+  \param [in] dataJBegin index begin of j data
+  \param [in] dataDim dimension of data (1 or 2)
+  \param [in] ni local size ni of domain
+  \param [out] j j index of domain
+  \return i index of domain
+*/
+int CDistributionClient::getDomainIndex(const int& dataIIndex, const int& dataJIndex,
+                                        const int& dataIBegin, const int& dataJBegin,
+                                        const int& dataDim, const int& ni, int& j)
+{
+  int i;
+  int tempI = dataIIndex + dataIBegin,
+      tempJ = (dataJIndex + dataJBegin);
+  if (ni == 0)
+  {
+    i = -1;
+    j = -1;
+    return i;
+  }
+  if ((tempI < 0) || (tempJ < 0))
+  {
+    i = -1;
+    j = -1;
+    return i;
+  }
+  else
+  {
+    i = (dataDim == 1) ? (tempI) % ni : (tempI) ;
+    j = (dataDim == 1) ? (tempI) / ni : (tempJ) ;
+  }
+  return i;
+}
+
+/*!
+  Retrieve index of an axis from its data index
+  \param [in] dataIndex index of data
+  \param [in] dataBegin index begin of data
+  \param [in] ni local size of axis
+  \return index of domain
+*/
+int CDistributionClient::getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni)
+{
+  if (ni == 0)
+  {
+    return -1;
+  }
+  int tempI = dataIndex;
+  if ((tempI < 0) || (tempI > ni))
+    return -1;
+  else
+    return tempI;
+}
+
+/*!
+  Return global local data mapping of client
+*/
+CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalLocalDataSendToServer()
+{
+  if (!isComputed_) createGlobalIndexSendToServer();
+  return globalLocalDataSendToServerMap_;
+}
+
+CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalDataIndexOnClient()
+{
+  if (!isComputed_) createGlobalIndexSendToServer();
+  return globalDataIndex_;
+}
+
+/*!
+  Return local data index of client
+*/
+const std::vector<int>& CDistributionClient::getLocalDataIndexOnClient()
+{
+  if (!isComputed_) createGlobalIndexSendToServer();
+  return localDataIndex_;
+}
+
+/*!
+  Return local mask index of client
+*/
+const std::vector<bool>& CDistributionClient::getLocalMaskIndexOnClient()
+{
+  if (!isComputed_) createGlobalIndexSendToServer();
+  return localMaskIndex_;
+}
+
+/*!
+  Return local mask index of client
+*/
+const std::vector<int>& CDistributionClient::getLocalMaskedDataIndexOnClient()
+{
+  if (!isComputed_) createGlobalIndexSendToServer();
+  return localMaskedDataIndex_;
+}
+
+} // namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_client.hpp	(revision 1918)
@@ -0,0 +1,186 @@
+/*!
+   \file distribution_client.hpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 09 Mars 2015
+
+   \brief Index distribution on client side.
+ */
+#ifndef __XIOS_DISTRIBUTIONCLIENT_HPP__
+#define __XIOS_DISTRIBUTIONCLIENT_HPP__
+
+#include <distribution.hpp>
+#include "axis.hpp"
+#include "domain.hpp"
+#include "grid.hpp"
+
+namespace xios {
+
+class CGrid;
+class CDomain;
+class CAxis;
+class CScalar;
+
+/*!
+  \class CDistributionClient
+  This class bases on the knowledge of distribution on client side (decided by users)
+to calculate the global index of its local data.
+*/
+class CDistributionClient : public CDistribution
+{
+public:
+  typedef CDistribution::GlobalLocalMap GlobalLocalDataMap;
+
+  public:
+    /** Default constructor */
+    CDistributionClient(int rank, CGrid* grid);
+
+    void createGlobalIndexSendToServer();
+
+    /** Default destructor */
+    virtual ~CDistributionClient();
+
+    virtual const std::vector<int>& getLocalDataIndexOnClient();
+    GlobalLocalDataMap& getGlobalLocalDataSendToServer();
+    GlobalLocalDataMap& getGlobalDataIndexOnClient();
+    const std::vector<bool>& getLocalMaskIndexOnClient();
+    const std::vector<int>& getLocalMaskedDataIndexOnClient();
+
+    size_t getLocalDataSize(void) { if (!isComputed_) createGlobalIndexSendToServer(); return localDataSize_ ;}
+    std::vector<int> getNGlob() { return nGlob_; }
+    std::vector<int> getDataNIndex() { return dataNIndex_; }
+
+    bool isDataDistributed() { return isDataDistributed_; }
+
+    static int getDomainIndex(const int& dataIIndex, const int& dataJIndex,
+                                     const int& dataIBegin, const int& dataJBegin,
+                                     const int& dataDim, const int& ni, int& j);
+    static int getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni);
+
+    void partialClear(void) ;  //! clear heavy sized attibutes
+
+  protected:
+    void createGlobalIndex();
+    void readDistributionInfo(CGrid* grid);
+    void readDistributionInfo(const std::vector<CDomain*>& domList,
+                              const std::vector<CAxis*>& axisList,
+                              const std::vector<CScalar*>& scalarList,
+                              const CArray<int,1>& axisDomainOrder);
+  private:
+    //! Create local index of a domain
+    void createLocalDomainDataIndex();
+
+    //! Create local index of an axis
+    void createLocalAxisDataIndex();
+
+    //! Create local index of a scalar
+    void createLocalScalarDataIndex();
+
+    template<int N>
+    void readGridMaskInfo(const CArray<bool,N>& gridMask);
+
+  private:
+    //!< LocalData index on client
+    GlobalLocalDataMap globalLocalDataSendToServerMap_;
+    GlobalLocalDataMap globalDataIndex_;
+
+    /*! Array holding masked data indexes.
+     * It includes:
+     *  masking on data (data_i/j_index or data_ni/nj and data_ibegin)
+     *  masking on grid elements (domains, axes or scalars)
+     * It DOES NOT include grid mask.
+     * The array size defines the data size entering the workflow. It is used by source filter of client or server1.
+    */
+    std::vector<int> localDataIndex_;
+
+    /*! Array holding grid mask. If grid mask is not defined, its size is zero.
+     * It is used by source filter of client for replacing unmasked data by NaN.
+    */
+    std::vector<bool> localMaskIndex_;
+
+    std::vector<int> localMaskedDataIndex_;
+    //!< the size of local data of the grid
+    size_t localDataSize_ ;
+
+  private:
+    /*! Domains and axis are considered elements.
+     * A grid composed of 1 domain and 1 axis has 2 elements */
+    int numElement_;
+    CArray<int,1> axisDomainOrder_; //!< Order of axis and domain of a grid
+
+    std::vector<int> nLocal_; //!< Local size of each dimension (ni, nj, etc, ...)
+    std::vector<int> nGlob_; //!< Global size of each dimension (e.x: ni_glo, nj_glo, etc, ...)
+    std::vector<int> nBeginLocal_;//!< Begin index of each dimension (e.x: for domain, it's always 0, for axis, it's zoom_begin, ...)
+    std::vector<int> nBeginGlobal_; //!< Begin index of each dimension (e.x: ibegin, jbegin, ...)
+
+    // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
+    std::vector<int> dataNIndex_; //!< Data_n_index in case of domain
+    std::vector<int> dataDims_; //!< Data_dim, domain can have data_dim == 1 or 2
+    std::vector<int> dataBegin_; //!< Data begin (data_ibegin, data_jbegin, etc)
+    std::vector<CArray<int,1> > dataIndex_; //!< Data index
+    std::vector<CArray<int,1> > infoIndex_; //!< i_index, j_index
+
+    std::vector<int> indexMap_; //!< Mapping element index to dimension index
+    std::vector<CArray<int,1> > elementLocalIndex_;  //!< Local index of each element
+    std::vector<CArray<size_t,1> > elementGlobalIndex_; //!< Global index of each element
+    std::vector<CArray<bool,1> > elementIndexData_; //!< // The correct index of a domain has true value, the ghost one has false value
+    std::vector<size_t> elementNLocal_;
+    std::vector<size_t> elementNGlobal_;
+
+    //!< (Only for grid with one axis or scalar)Flag to determine whether data is distributed or not
+    bool isDataDistributed_;
+    int axisNum_;
+    int domainNum_;
+    bool isComputed_;
+
+  private:
+    // Just suppose that grid mask has 3 dimension. Need change
+    CArray<bool,1> gridMask_; //!< Mask of grid
+
+  private:
+    CDistributionClient(const CDistributionClient& distClient); //! Not implement
+};
+
+/*!
+  A grid can have multiple dimension, so can its mask in the form of multi-dimension array.
+It's not a good idea to store all multi-dimension arrays corresponding to each mask.
+One of the ways is to convert this array into 1-dimension one and every process is taken place on it.
+  \param [in] multi-dimension array grid mask
+*/
+template<int N>
+void CDistributionClient::readGridMaskInfo(const CArray<bool,N>& gridMask)
+{
+  int dim = gridMask.dimensions();
+  std::vector<int> dimensionSizes(dim);
+  for (int i = 0; i < dim; ++i) dimensionSizes[i] = gridMask.extent(i);
+
+  std::vector<int> idxLoop(dim,0);
+  int ssize = gridMask.numElements(), idx = 0;
+  gridMask_.resize(ssize);
+  while (idx < ssize)
+  {
+    for (int i = 0; i < dim-1; ++i)
+    {
+      if (idxLoop[i] == dimensionSizes[i])
+      {
+        idxLoop[i] = 0;
+        ++idxLoop[i+1];
+      }
+    }
+
+    int maskIndex = idxLoop[0];
+    int mulDim = 1;
+    for (int k = 1; k < dim; ++k)
+    {
+      mulDim *= dimensionSizes[k-1];
+      maskIndex += idxLoop[k]*mulDim;
+    }
+    gridMask_(maskIndex) = *(gridMask.dataFirst()+maskIndex);
+
+    ++idxLoop[0];
+    ++idx;
+  }
+}
+
+} // namespace xios
+#endif // __XIOS_DISTRIBUTIONCLIENT_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.cpp	(revision 1918)
@@ -0,0 +1,223 @@
+/*!
+   \file distribution_server.cpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 10 Sep 2016
+
+   \brief Index distribution on server side.
+ */
+#include "distribution_server.hpp"
+#include "utils.hpp"
+
+namespace xios {
+
+CDistributionServer::CDistributionServer(int rank, const std::vector<int>& nBegin,
+                                         const std::vector<int>& nSize,
+                                         const std::vector<int>& nBeginGlobal,
+                                         const std::vector<int>& nGlobal)
+  : CDistribution(rank, nGlobal.size()), nGlobal_(nGlobal), nBeginGlobal_(nBeginGlobal),
+    nSize_(nSize), nBegin_(nBegin), globalLocalIndexMap_()
+{
+  createGlobalIndex();
+}
+
+CDistributionServer::CDistributionServer(int rank,
+                                        const std::vector<CArray<int,1> >& globalIndexElements,
+                                        const CArray<int,1>& elementOrder,
+                                        const std::vector<int>& nBegin,
+                                        const std::vector<int>& nSize,
+                                        const std::vector<int>& nBeginGlobal,
+                                        const std::vector<int>& nGlobal)
+  : CDistribution(rank, nGlobal.size()), nGlobal_(nGlobal), nBeginGlobal_(nBeginGlobal),
+    nSize_(nSize), nBegin_(nBegin), globalLocalIndexMap_()
+{
+  createGlobalIndex(globalIndexElements, elementOrder);
+}
+
+CDistributionServer::~CDistributionServer()
+{
+}
+
+/*!
+  Create global index on server side
+  Like the similar function on client side, this function serves on creating global index
+for data written by the server. The global index is used to calculating local index of data
+written on each server
+*/
+void CDistributionServer::createGlobalIndex()
+{
+  size_t idx = 0, ssize = 1;
+  for (int i = 0; i < nSize_.size(); ++i) ssize *= nSize_[i];
+
+  this->globalIndex_.resize(ssize);
+  std::vector<int> idxLoop(this->getDims(),0);
+  std::vector<int> currentIndex(this->getDims());
+  int innerLoopSize = nSize_[0];
+
+  globalLocalIndexMap_.rehash(std::ceil(ssize/globalLocalIndexMap_.max_load_factor()));
+  while (idx<ssize)
+  {
+    for (int i = 0; i < this->dims_-1; ++i)
+    {
+      if (idxLoop[i] == nSize_[i])
+      {
+        idxLoop[i] = 0;
+        ++idxLoop[i+1];
+      }
+    }
+
+    for (int i = 1; i < this->dims_; ++i)  currentIndex[i] = idxLoop[i] + nBegin_[i];
+
+    size_t mulDim, globalIndex;
+    for (int i = 0; i < innerLoopSize; ++i)
+    {
+      mulDim = 1;
+      globalIndex = i + nBegin_[0];
+
+      for (int k = 1; k < this->dims_; ++k)
+      {
+        mulDim *= nGlobal_[k-1];
+        globalIndex += (currentIndex[k])*mulDim;
+      }
+      globalLocalIndexMap_[globalIndex] = idx;
+      this->globalIndex_(idx) = globalIndex;
+
+      ++idx;
+    }
+    idxLoop[0] += innerLoopSize;
+  }
+}
+
+/*!
+  Create global index on server side
+  Like the similar function on client side, this function serves on creating global index
+for data written by the server. The global index is used to calculating local index of data
+written on each server
+  \param[in] globalIndexElement global index on server side of each element of grid (scalar, axis, domain)
+  \param[in] elementOrder the order of elements of grid (e.x: domain->axis or domain->scalar)
+*/
+void CDistributionServer::createGlobalIndex(const std::vector<CArray<int,1> >& globalIndexElements,
+                                            const CArray<int,1>& elementOrder)
+{
+  int numElement = elementOrder.numElements(), elementIdx = 0;  
+  std::vector<int> indexMap(numElement);
+  for (int i = 0; i < numElement; ++i)
+  {
+    indexMap[i] = elementIdx;
+    if (2 == elementOrder(i))
+    {      
+      elementIdx += 2;
+    }
+    else
+      ++elementIdx;
+  }
+
+  std::vector<size_t> elementGlobalSize(numElement);
+  size_t globalSize = 1;
+  for (int i = 0; i < numElement; ++i)
+  {
+    int elementType = elementOrder(i);
+    elementGlobalSize[i] = globalSize;
+    if (2 == elementType) // domain
+    {
+      globalSize *= nGlobal_[indexMap[i]+1] * nGlobal_[indexMap[i]];
+    }
+    else // axis or scalar
+    {
+      globalSize *= nGlobal_[indexMap[i]];
+    }
+  } 
+
+  size_t ssize = 1;
+  for (int i = 0; i < globalIndexElements.size(); ++i) ssize *= globalIndexElements[i].numElements();
+  this->globalIndex_.resize(ssize);
+  globalLocalIndexMap_.rehash(std::ceil(ssize/globalLocalIndexMap_.max_load_factor()));
+
+  std::vector<int> idxLoop(numElement,0);
+  std::vector<int> currentIndex(numElement);
+  int innerLoopSize = globalIndexElements[0].numElements();
+
+  size_t idx = 0;
+  while (idx<ssize)
+  {
+    for (int i = 0; i < numElement-1; ++i)
+    {
+      if (idxLoop[i] == globalIndexElements[i].numElements())
+      {
+        idxLoop[i] = 0;
+        ++idxLoop[i+1];
+      }
+    }
+
+    for (int i = 1; i < numElement; ++i)  currentIndex[i] = globalIndexElements[i](idxLoop[i]);
+
+    size_t mulDim, globalIndex;
+    for (int i = 0; i < innerLoopSize; ++i)
+    {      
+      globalIndex = 0;
+      currentIndex[0] = globalIndexElements[0](i);
+
+      for (int k = 0; k < numElement; ++k)
+      {     
+        globalIndex += (currentIndex[k])*elementGlobalSize[k];
+      }
+      globalLocalIndexMap_[globalIndex] = idx;
+      this->globalIndex_(idx) = globalIndex;
+      ++idx;
+    }
+    idxLoop[0] += innerLoopSize;
+  }
+}
+
+/*!
+  Compute local index for writing data on server
+  \param [in] globalIndex Global index received from client
+*/
+void CDistributionServer::computeLocalIndex(CArray<size_t,1>& globalIndex)
+{
+  size_t ssize = globalIndex.numElements();
+  size_t localIndexSize = std::min(globalIndex_.numElements(), ssize);
+  CArray<size_t,1> localIndex(localIndexSize);
+  GlobalLocalMap::const_iterator ite = globalLocalIndexMap_.end(), it;
+  int i = 0;
+  for (size_t idx = 0; idx < ssize; ++idx)
+  {
+    it = globalLocalIndexMap_.find(globalIndex(idx));
+    if (ite != it)
+    {
+      localIndex(i) = it->second;
+      ++i;
+    }
+  }
+
+  globalIndex.reference(localIndex);
+}
+
+/*!
+  Transforms local indexes owned by the server into global indexes
+  \param [in/out] indexes on input, local indexes of the server,
+                          on output, the corresponding global indexes
+*/
+void CDistributionServer::computeGlobalIndex(CArray<int,1>& indexes) const
+{
+  for (int i = 0; i < indexes.numElements(); ++i)
+  {
+    indexes(i) = globalIndex_(indexes(i));
+  }
+}
+
+/*!
+  Get the size of grid index in server (e.x: sizeGrid *= size of each dimensiion)
+*/
+int CDistributionServer::getGridSize() const
+{
+   return globalLocalIndexMap_.size();
+}
+
+void CDistributionServer::partialClear(void)
+{
+  GlobalLocalMap void1 ;
+  globalLocalIndexMap_.swap(void1) ;
+}
+  
+} // namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/distribution_server.hpp	(revision 1918)
@@ -0,0 +1,68 @@
+/*!
+   \file distribution_server.hpp
+   \author Ha NGUYEN
+   \since 13 Jan 2015
+   \date 04 Feb 2015
+
+   \brief Index distribution on server side.
+ */
+
+#ifndef __XIOS_DISTRIBUTION_SERVER_HPP__
+#define __XIOS_DISTRIBUTION_SERVER_HPP__
+
+#include "distribution.hpp"
+
+namespace xios {
+
+/*!
+  \class CDistributionServer
+  The class, for now, plays a role of computing local index for writing data on server
+*/
+class CDistributionServer : public CDistribution
+{
+  public:
+    /** Default constructor */
+    CDistributionServer(int rank, int dims, const CArray<size_t,1>& globalIndex = CArray<size_t,1>());
+    CDistributionServer(int rank, const std::vector<int>& nBeginServer,
+                        const std::vector<int>& nSizeServer, const std::vector<int>& nGlobal);
+    CDistributionServer(int rank, const std::vector<int>& nBeginServer,
+                        const std::vector<int>& nSizeServer,
+                        const std::vector<int>& nBeginGlobal,
+                        const std::vector<int>& nGlobal);
+
+    CDistributionServer(int rank,
+                        const std::vector<CArray<int,1> >& globalIndexElements,
+                        const CArray<int,1>& elementOrder,
+                        const std::vector<int>& nBeginServer,
+                        const std::vector<int>& nSizeServer,
+                        const std::vector<int>& nBeginGlobal,
+                        const std::vector<int>& nGlobal);
+
+    /** Default destructor */
+    virtual ~CDistributionServer();
+
+    const GlobalLocalMap& getGlobalLocalIndex() const { return globalLocalIndexMap_; }    
+    int getGridSize() const;
+    
+    virtual void computeLocalIndex(CArray<size_t,1>& globalIndex);
+    virtual void computeGlobalIndex(CArray<int,1>& indexes) const;
+    virtual void partialClear(void); //! clear heavy sized attibutes
+
+  protected:
+    virtual void createGlobalIndex();
+    void createGlobalIndex(const std::vector<CArray<int,1> >& globalIndexElements,
+                           const CArray<int,1>& elementOrder);
+    
+  protected:
+    GlobalLocalMap globalLocalIndexMap_;
+
+  private:
+    std::vector<int> nGlobal_;
+    std::vector<int> nBeginGlobal_;
+    std::vector<int> nSize_;
+    std::vector<int> nBegin_;
+
+};
+
+} // namespace xios
+#endif // __XIOS_DISTRIBUTION_SERVER_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.cpp	(revision 1918)
@@ -0,0 +1,142 @@
+#include "element.hpp"
+#include "distributed_view.hpp"
+#include "local_view.hpp"
+#include "local_connector.hpp"
+#include "context_client.hpp"
+#include "context_server.hpp"
+#include "mpi.hpp"
+
+
+namespace xios
+{
+
+  CDistributedElement::CDistributedElement(int globalSize, const map<int, CArray<size_t,1>>& globalIndex)
+  {
+    globalSize_= globalSize ;
+    for(auto index : globalIndex) 
+    {
+      globalIndex_[index.first].reference(index.second.copy()) ;
+      localSize_[index.first] = index.second.numElements() ;
+    }
+  }
+
+  CDistributedElement::CDistributedElement(CEventServer& event) 
+  {
+    recvFromClient(event) ;
+  }
+  
+  void CDistributedElement::addView(CElementView::type type, std::map<int, CArray<int,1>>& indexView)
+  {
+    views_[type] = new CDistributedView(this, type, indexView) ;
+  } 
+
+  void CDistributedElement::addFullView(void)
+  {
+    if (views_[CElementView::FULL]!=nullptr) return ;
+
+    std::map<int, CArray<int,1>> indexView ;
+    for(auto rank : globalIndex_)
+    {
+      auto& index = indexView[rank.first] ;
+      int size=rank.second.numElements() ;
+      index.resize(size) ;
+      for(int i=0;i<size;i++) index(i)=i ;
+    }
+    addView(CElementView::FULL, indexView) ;
+  } 
+
+  void CDistributedElement::sendToServer(CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+  {
+    int remoteSize = client->getRemoteSize() ;
+    vector<int> nbSenders(remoteSize,0) ;
+    for(auto rank : globalIndex_) nbSenders[rank.first]=1 ; 
+    MPI_Allreduce(MPI_IN_PLACE, nbSenders.data(), remoteSize, MPI_INT, MPI_SUM, client->getIntraComm()) ;
+
+    list<CMessage> messages;
+    for(auto ranksData : globalIndex_)
+    {
+      int rank = ranksData.first ;
+      auto& data = ranksData.second ;
+
+      messages.push_back(CMessage(messageHeader));
+      messages.back()<<globalSize_<<data;
+      event.push(rank, nbSenders[rank], messages.back());
+    } 
+    client->sendEvent(event) ; 
+  }
+
+  void CDistributedElement::recvFromClient(CEventServer& event)
+  {
+    globalIndex_.clear();
+    for (auto& subEvent : event.subEvents)
+    {      
+      CBufferIn* buffer = subEvent.buffer;
+      int rank=subEvent.rank ;
+      *buffer>>globalSize_ ;
+      *buffer >> globalIndex_[rank];
+    }
+    localSize_.clear() ;
+    for(auto& globalIndex : globalIndex_) localSize_[globalIndex.first] = globalIndex.second.numElements() ;  
+  }
+ 
+
+
+  CLocalElement::CLocalElement(int localRank, size_t globalSize, CArray<size_t,1>& globalIndex) 
+                             : CDistributedElement(globalSize, {{localRank, globalIndex}}),
+                               globalIndex_(CDistributedElement::globalIndex_[localRank]), localSize_(CDistributedElement::localSize_[localRank]), localRank_(localRank)
+  {
+   
+  }   
+
+  CLocalElement::CLocalElement(int localRank, CEventServer& event) : globalIndex_(CDistributedElement::globalIndex_[localRank]), localSize_(CDistributedElement::localSize_[localRank]), localRank_(localRank) 
+  {
+    recvFromClient(localRank, event) ;
+  }
+
+  void CLocalElement::recvFromClient(int localRank, CEventServer& event)
+  {
+    set<size_t> globalIndex ;
+
+    for (auto& subEvent : event.subEvents)
+    {      
+      CBufferIn* buffer = subEvent.buffer;
+      int rank=subEvent.rank ;
+      CArray<size_t,1> indGlo ;
+      *buffer >> globalSize_>> indGlo;
+      globalIndex.insert(indGlo.dataFirst(), indGlo.dataFirst()+indGlo.numElements()) ;
+    }
+
+    localSize_ = globalIndex.size() ;
+    globalIndex_.resize(localSize_) ;
+    int i=0 ;
+    for(auto& ind : globalIndex) { globalIndex_(i)=ind ; i++; }
+  }
+
+  void CLocalElement::addView(CElementView::type type, CArray<int,1>& indexView)
+  {
+    views_[type] = new CLocalView(this, type, indexView) ;
+  } 
+
+  void CLocalElement::addFullView(void)
+  {
+    if (views_[CElementView::FULL]!=nullptr) return ;
+
+    CArray<int,1> indexView(localSize_) ;
+    for(int i=0;i<localSize_;i++) indexView(i)=i ;
+    addView(CElementView::FULL, indexView) ;
+  } 
+
+  CLocalConnector* CLocalElement::getConnector(CElementView::type srcType, CElementView::type dstType) 
+  { 
+    auto newPair = pair<CElementView::type,CElementView::type>(srcType,dstType);
+    auto it = connectors_.find(newPair) ;
+    if (it==connectors_.end()) 
+    {
+      auto insertPair=pair<pair<CElementView::type,CElementView::type>, CLocalConnector*>(newPair,new CLocalConnector(getView(srcType),getView(dstType))) ;
+      it=connectors_.insert(insertPair).first ;
+      it->second->computeConnector() ;
+    }
+    return it->second ;
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element.hpp	(revision 1918)
@@ -0,0 +1,79 @@
+#ifndef __ELEMENT_HPP__
+#define __ELEMENT_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "element_view.hpp"
+#include "exception.hpp"
+#include "context_client.hpp"
+#include "context_server.hpp"
+
+namespace xios
+{
+  class CDistributedView ;
+  class CLocalView;
+  class CLocalConnector ;
+
+  class CDistributedElement
+  {
+
+  protected:
+    std::map<int, CArray<size_t,1>> globalIndex_ ;
+    std::map<int, int> localSize_ ;
+    size_t globalSize_ ;
+    std::vector<CDistributedView*> views_= std::vector<CDistributedView*>(CElementView::numViewType_) ;
+    CDistributedElement(void) {} ;
+    
+  public:
+    CDistributedElement(int globalSize, const map<int, CArray<size_t,1>>& globalIndex) ;
+    CDistributedElement(CEventServer& event) ;
+    void addFullView(void) ;
+    void sendToServer(CContextClient* client, CEventClient& event, const CMessage& messageHeader) ;
+    void recvFromClient(CEventServer& event) ;
+    size_t getGlobalSize(void) { return globalSize_;}
+
+    CDistributedView* getView(CElementView::type type) 
+    { 
+      if (views_[(size_t)type]==nullptr) { ERROR("CDistributedElement::getView(CElementView::type type)",<<"View is not initialized");} 
+      else return views_[(size_t)type] ; 
+    }
+
+    void addView(CElementView::type type, std::map<int, CArray<int,1>>& indexView) ;
+    void sendToServer(CEventClient& event, const CMessage& messageHeader) ;
+
+    friend class CDistributedView ;
+  } ;
+
+
+  class CLocalElement : public CDistributedElement
+  {
+    // keep local connector inside    
+      std::map<pair<CElementView::type,CElementView::type>, CLocalConnector*> connectors_  ;
+ 
+    public: 
+      CLocalElement(int localRank, size_t globalSize, CArray<size_t,1>& globalIndex) ;
+      CLocalElement(int localRank, CEventServer& event) ;
+      void recvFromClient(int localRank, CEventServer& event) ;
+      
+      void addView(CElementView::type type, CArray<int,1>& indexView) ;
+      void addFullView(void) ;
+      CLocalView* getView(CElementView::type type) 
+      { 
+        if (views_[(size_t)type]==nullptr) { ERROR("CLocalElement::getView(CElementView::type type)",<<"View is not initialized");} 
+        else return (CLocalView*) views_[(size_t)type] ; 
+      }
+      
+      CLocalConnector* getConnector(CElementView::type srcType, CElementView::type dstType) ;
+
+    private :
+      int localRank_;
+      CArray<size_t,1>& globalIndex_ ;
+      int& localSize_ ;
+    
+    friend class CLocalView ;
+  } ;
+
+}
+
+#endif
+
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element_view.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element_view.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/element_view.hpp	(revision 1918)
@@ -0,0 +1,20 @@
+#ifndef __ELEMENT_VIEW_HPP__
+#define __ELEMENT_VIEW_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+
+namespace xios
+{
+  class CElementView
+  {
+    public:
+      enum type : size_t { FULL=0, MODEL, WORKFLOW} ;
+      const static int numViewType_ = 3 ;
+    protected:
+      type type_;
+  } ;
+ 
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.cpp	(revision 1918)
@@ -0,0 +1,45 @@
+#include "gatherer_connector.hpp"
+
+namespace xios
+{
+  void CGathererConnector::computeConnector(void)
+  {
+    dstSize_=dstView_->getSize() ;
+    auto& srcGlobalIndex = srcView_->getGlobalIndex() ;
+    auto& srcIndex = srcView_->getIndex() ;
+    for(auto& rankIndex : srcIndex) srcSize_[rankIndex.first] = rankIndex.second.numElements();
+    auto& dstGlobalIndex = dstView_->getGlobalIndex() ;
+    auto& dstIndex = dstView_->getIndex() ;
+    dstSize_=dstIndex.numElements() ;
+
+    unordered_map<size_t,int> mapGlobalLocalIndex ;
+    int globalIndexSize=dstGlobalIndex.size() ;
+    for(auto& ind : dstIndex) mapGlobalLocalIndex[dstGlobalIndex(ind)] = ind ;
+    for(auto& rankIndex : srcIndex)
+    {
+      int rank=rankIndex.first ;
+      auto& index=rankIndex.second ;
+      int indexSize = index.numElements() ;
+      auto& globalIndex = srcGlobalIndex[rank] ;
+      int globalIndexSize=globalIndex.numElements() ;
+      auto& connector = connector_[rank] ;
+      auto& mask = mask_[rank] ;
+      for(int ind=0; ind<indexSize ; ind++)
+      {
+        if (ind>=0 && ind<globalIndexSize)
+        {
+           auto it=mapGlobalLocalIndex.find(globalIndex(ind)) ;
+           if (it != mapGlobalLocalIndex.end()) 
+           {
+             connector.push_back(it->second) ;
+             mask.push_back(true) ;
+           }
+           else mask.push_back(false) ;
+        }
+        else mask.push_back(false) ;
+      } 
+    } 
+  }
+
+  
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/gatherer_connector.hpp	(revision 1918)
@@ -0,0 +1,135 @@
+#ifndef __GATHERER_CONNECTOR_HPP__
+#define __GATHERER_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+
+
+namespace xios
+{
+ 
+  class CGathererConnector
+  {
+    private:
+      CDistributedView* srcView_;
+      CLocalView* dstView_;
+      map<int, vector<int>> connector_ ;
+      map<int, vector<bool>> mask_ ;  // mask is on src view
+      int dstSize_ ; 
+      map<int,int> srcSize_ ;
+
+    public:
+      CGathererConnector(CDistributedView* srcView, CLocalView* dstView) : srcView_(srcView), dstView_(dstView) {} ;
+      void computeConnector(void) ;
+      
+      template<typename T>
+      void transfer(map<int, CArray<T,1>>& dataIn, CArray<T,1>& dataOut)
+      {
+        dataOut.resize(dstSize_) ;
+        T* output = dataOut.dataFirst() ;
+        for(auto& data : dataIn)
+        {
+          int rank=data.first ;
+          auto input  = data.second.dataFirst() ;
+          auto& connector=connector_[rank] ;
+          auto& mask=mask_[rank] ;
+          int size=data.second.numElements() ;
+
+          for(int i=0, j=0 ;i<size;i++)
+          {
+            if (mask[i]) 
+            {
+              output[connector[j]] = input[i] ;
+              j++ ;
+            }
+          }
+        }
+      }
+    
+
+      template<typename T>
+      void transfer(int rank,  CGathererConnector** connectors, int nConnectors, const T* input, T* output)
+      {
+        auto& connector = connector_[rank] ; // probably costly, find a better way to avoid the map
+        auto& mask = mask_[rank] ; 
+        int srcSize = mask.size() ;
+      
+        if (nConnectors==0)
+        {
+          for(int i=0, j=0; i<srcSize; i++)
+            if (mask[i]) 
+            {
+              *(output+connector[j]) = *(input + i) ;
+              j++ ;
+            }
+
+        }
+        else
+       {
+          int srcSliceSize = (*(connectors-1))->getSrcSliceSize(rank, connectors-1, nConnectors-1) ;
+          int dstSliceSize = (*(connectors-1))->getDstSliceSize(connectors-1, nConnectors-1) ;
+
+          const T* in = input ; 
+          for(int i=0,j=0;i<srcSize;i++) 
+          {
+            if (mask[i]) 
+            {
+              (*(connectors-1))->transfer(rank, connectors-1, nConnectors-1, in, output+connector[j]*dstSliceSize) ; // the multiplication must be avoid in further optimization
+              j++ ;
+            }
+            in += srcSliceSize ;
+          }
+        }
+
+      }
+
+
+      template<typename T>
+      void transfer(map<int, CArray<T,1>>& dataIn, CArray<T,1>& dataOut, T missingValue)
+      {
+        dataOut.resize(dstSize_) ;
+        dataOut=missingValue ;
+        transfer(map<int, CArray<T,1>>& dataIn, CArray<T,1>& dataOut) ;
+      }
+      
+      template<typename T>
+      void transfer(CEventServer& event, CArray<T,1>& dataOut)
+      {
+        map<int, CArray<T,1>> dataIn ;
+        for (auto& subEvent : event.subEvents) 
+        {
+          auto& data = dataIn[subEvent.rank]; 
+          (*subEvent.buffer) >> data ;
+        }
+        transfer(dataIn, dataOut) ;
+      }
+
+      template<typename T>
+      void transfer(CEventServer& event, CArray<T,1>& dataOut, T missingValue)
+      {
+        map<int, CArray<T,1>> dataIn ;
+        for (auto& subEvent : event.subEvents) 
+        {
+          auto& data = dataIn[subEvent.rank]; 
+          (*subEvent.buffer) >> data ;
+        }
+        transfer(dataIn, dataOut, missingValue) ;
+      }
+
+    int getSrcSliceSize(int rank, CGathererConnector** connectors, int nConnectors) 
+    { if (nConnectors==0) return srcSize_[rank] ; else return srcSize_[rank] * (*(connectors-1))->getSrcSliceSize(rank, connectors-1,nConnectors-1) ; }
+
+    int getDstSliceSize(CGathererConnector** connectors, int nConnectors) 
+    { if (nConnectors==0) return dstSize_ ; else return dstSize_ * (*(connectors-1))->getDstSliceSize(connectors-1,nConnectors-1) ; }
+  
+    int getDstSize(void) {return dstSize_ ;}
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.cpp	(revision 1918)
@@ -0,0 +1,25 @@
+#include "grid_elements.hpp"
+#include "grid_local_view.hpp"
+#include "grid_local_connector.hpp"
+
+namespace xios
+{
+
+  CGridLocalView* CGridLocalElements::getView(CElementView::type type)
+  { 
+    if (views_[type]==nullptr) views_[type] = new CGridLocalView(this, type) ;
+    return views_[type] ;
+  }
+  
+  CGridLocalConnector* CGridLocalElements::getConnector(CElementView::type srcType, CElementView::type dstType)
+  {
+    auto newPair = pair<CElementView::type,CElementView::type>(srcType,dstType);
+    auto it = connectors_.find(newPair) ;
+    if (it==connectors_.end()) 
+    {
+      auto insertPair=pair<pair<CElementView::type,CElementView::type>, CGridLocalConnector*>(newPair,new CGridLocalConnector(this, srcType, dstType)) ;
+      it=connectors_.insert(insertPair).first ;
+    }
+    return it->second ;
+  }
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_elements.hpp	(revision 1918)
@@ -0,0 +1,34 @@
+#ifndef __GRID_ELEMENTS_HPP__
+#define __GRID_ELEMENTS_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "element.hpp"
+
+namespace xios
+{
+  class CGridLocalView ;
+  class CGridLocalConnector ;
+
+  class CGridLocalElements  
+  {
+    private:
+      std::vector<CLocalElement*> elements_ ;
+      std::vector<CGridLocalView*> views_= std::vector<CGridLocalView*>(CElementView::numViewType_) ;
+      std::map<pair<CElementView::type,CElementView::type>, CGridLocalConnector*> connectors_ ;
+      vector<bool> localMask_ ;
+  
+    public:
+      CGridLocalElements(vector<CLocalElement*> elements) : elements_(elements) {}
+      CGridLocalElements(vector<CLocalElement*> elements, vector<bool>& localMask) : elements_(elements), localMask_(localMask) {}
+
+      bool hasLocalMask() { return !localMask_.empty() ;}
+      vector<bool>& getLocalMask(void) { return localMask_ ;}
+
+      std::vector<CLocalElement*>& getElements(void) { return elements_ ; }
+      CGridLocalView* getView(CElementView::type type) ;
+      CGridLocalConnector* getConnector(CElementView::type srcType, CElementView::type dstType) ;
+  } ;
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_gatherer_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_gatherer_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_gatherer_connector.hpp	(revision 1918)
@@ -0,0 +1,58 @@
+#ifndef __GRID_GATHERER_CONNECTOR_HPP__
+#define __GRID_GATHERER_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+#include "gatherer_connector.hpp"
+
+
+namespace xios
+{
+ 
+  class CGridGathererConnector
+  {
+    private:
+    
+      vector<CGathererConnector*> elementsConnector_ ;
+      int dstSize_ ;
+
+    public:
+      CGridGathererConnector(vector<CGathererConnector*> elementsConnector) : elementsConnector_(elementsConnector)
+      {
+        dstSize_ = 1 ;
+        for(auto& connector : elementsConnector_) dstSize_=dstSize_*connector->getDstSize() ;
+      }
+
+      template<typename T> 
+      void transfer(const map<int, CArray<T,1>>& input, CArray<T,1>& output)
+      {
+        int n = elementsConnector_.size()-1 ;
+        CGathererConnector** connector = elementsConnector_.data() + n ;
+        output.resize(dstSize_) ;
+        for(auto& rankDataIn : input) 
+        {
+          elementsConnector_[n]->transfer(rankDataIn.first, connector, n, rankDataIn.second.dataFirst(), output.dataFirst()) ;
+        }
+      } 
+
+      template<typename T>
+      void transfer(CEventServer& event, CArray<T,1>& dataOut)
+      {
+        map<int, CArray<T,1>> dataIn ;
+        for (auto& subEvent : event.subEvents) 
+        {
+          auto& data = dataIn[subEvent.rank]; 
+          (*subEvent.buffer) >> data ;
+        }
+        transfer(dataIn, dataOut) ;
+      }
+  
+  };
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.cpp	(revision 1918)
@@ -0,0 +1,57 @@
+#include "grid_local_connector.hpp"
+#include "grid_elements.hpp"
+#include "element.hpp" 
+#include "grid_local_view.hpp"
+#include "local_view.hpp"
+
+namespace xios
+{
+ 
+  CGridLocalConnector::CGridLocalConnector(const std::vector<CLocalConnector*>& elementsConnector) : elementsConnector_(elementsConnector)
+  {
+    srcSize_=1 ;
+    for(auto connector : elementsConnector_) srcSize_*=connector->getSrcSize() ;
+    dstSize_=1 ;
+    for(auto connector : elementsConnector_) dstSize_*=connector->getDstSize() ;
+  } 
+
+  CGridLocalConnector::CGridLocalConnector(CGridLocalElements* parent, CElementView::type srcType, CElementView::type dstType)
+  {
+    CGridLocalView* srcView=parent->getView(srcType) ;
+    CGridLocalView* dstView=parent->getView(dstType) ;
+
+    vector<CLocalView*> srcViews = srcView->getViews() ; 
+    vector<CLocalView*> dstViews = dstView->getViews() ;
+    
+    vector<CLocalElement*>& elements = parent->getElements();
+    for(auto element : elements) elementsConnector_.push_back(element->getConnector(srcType, dstType)) ;
+    srcSize_=1 ;
+    for(auto connector : elementsConnector_) srcSize_*=connector->getSrcSize() ;
+    dstSize_=1 ;
+    for(auto connector : elementsConnector_) dstSize_*=connector->getDstSize() ;
+
+    if (parent->hasLocalMask())
+    {
+      vector<CLocalConnector*> elementsConnector ;
+      for(auto element : elements) elementsConnector.push_back(element->getConnector(CElementView::FULL, dstType)) ;
+      CGridLocalConnector localToDst(elementsConnector) ;
+      CArray<bool,1> maskIn(localToDst.getSrcSize()) ;
+      CArray<bool,1> maskOut1(localToDst.getDstSize()) ;
+      CArray<bool,1> maskOut2(localToDst.getDstSize()) ;
+      maskIn=true ;
+      localToDst.transfer(maskIn,maskOut1,false) ;
+      auto& localMask = parent->getLocalMask() ;
+      for(int i=0 ; i < maskIn.numElements() ; i++) maskIn(i)=localMask[i] ;
+      localToDst.transfer(maskIn,maskOut2,false) ;
+      mask_.assign(dstSize_,true) ;
+      for(int i=0;i<dstSize_;i++) if (maskOut1(i)==true && maskOut2(i)==false) mask_[i]=false ;
+    } 
+  }
+
+  void CGridLocalConnector::computeMask(void)
+  {
+
+
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_connector.hpp	(revision 1918)
@@ -0,0 +1,61 @@
+#ifndef __GRID_LOCAL_CONNECTOR_HPP__
+#define __GRID_LOCAL_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "local_connector.hpp"
+
+
+
+namespace xios
+{
+
+  class CGridLocalElements;
+
+  class CGridLocalConnector
+  {
+
+    private:  
+      std::vector<CLocalConnector*> elementsConnector_ ;
+      int srcSize_ ;
+      int dstSize_ ;
+      vector<bool> mask_ ;
+
+    public:
+      
+      CGridLocalConnector(const std::vector<CLocalConnector*>& elementsConnector)  ;
+      CGridLocalConnector(CGridLocalElements* parent, CElementView::type srcType, CElementView::type dstType) ;
+      int getSrcSize(void) { return srcSize_ ;}
+      int getDstSize(void) { return dstSize_ ;}
+
+      void computeMask(void) ;
+      bool computeMask_done_=false ;
+
+      
+      template<typename T, int Nin, int Nout> 
+      void transfer(const CArray<T,Nin>& input, CArray<T,Nout>& output)
+      {
+        int n = elementsConnector_.size()-1 ;
+        CLocalConnector** connector = elementsConnector_.data() + n ;
+        elementsConnector_[n]->transfer(connector, n, input.dataFirst(), output.dataFirst()) ;
+      }
+      
+      template<typename T, int Nin, int Nout> 
+      void transfer(const CArray<T,Nin>& input, CArray<T,Nout>& output, T missingValue)
+      {
+        int n = elementsConnector_.size()-1 ;
+        CLocalConnector** connector = elementsConnector_.data() + n ;
+        elementsConnector_[n]->transfer(connector, n, input.dataFirst(), output.dataFirst(), missingValue) ;
+        if (!computeMask_done_) computeMask() ;
+        if (!mask_.empty()) 
+        {
+          T* out = output.dataFirst() ;
+          for(auto mask : mask_) { if (!mask) *out=missingValue ; out++;}
+        }
+      }
+
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.cpp	(revision 1918)
@@ -0,0 +1,11 @@
+#include "grid_local_view.hpp"
+#include "grid_elements.hpp"
+
+namespace xios
+{
+  CGridLocalView::CGridLocalView(CGridLocalElements* parent, CElementView::type type) : localMask_(parent->getLocalMask())
+  {
+    for(auto element : parent->getElements()) views_.push_back(element->getView(type)) ;
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_local_view.hpp	(revision 1918)
@@ -0,0 +1,24 @@
+#ifndef __GRID_LOCAL_VIEW_HPP__
+#define __GRID_LOCAL_VIEW_HPP__
+
+#include "local_view.hpp"
+#include "element.hpp"
+
+namespace xios
+{
+  class CGridLocalElements;
+
+  class CGridLocalView
+  {
+    private:
+      std::vector<CLocalView*> views_ ;
+      std::vector<bool>& localMask_ ;
+    
+    public:
+      CGridLocalView(CGridLocalElements* parent, CElementView::type type) ;
+      std::vector<CLocalView*>& getViews(void) {return views_ ;}
+  } ;
+}
+
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.cpp	(revision 1918)
@@ -0,0 +1,87 @@
+#include "grid_remote_connector.hpp"
+#include "client_client_dht_template.hpp"
+
+
+
+namespace xios
+{
+  
+  CGridRemoteConnector::CGridRemoteConnector(vector<CLocalView*>& srcView, vector<CDistributedView*>& dstView, MPI_Comm localComm) 
+                       : srcView_(srcView), dstView_(dstView), localComm_(localComm) 
+  {}
+
+  void CGridRemoteConnector::computeConnector(void)
+  {
+    computeGenericMethod() ;
+  }
+
+  void CGridRemoteConnector::computeGenericMethod(void)
+  {
+    // generic method, every element can be distributed
+    CClientClientDHTTemplate<int>::Index2VectorInfoTypeMap info ; // info map
+        
+// generate list of global index for dst view, and insert it into DHT map
+    int nDst = dstView_.size() ;
+    vector<size_t> dstGlobalIndex ;
+    vector<size_t> dstSliceSize(nDst) ;
+    dstSliceSize[nDst-1] = 1 ;  
+    for(int i=nDst-2; i>=0; i--)  dstSliceSize[i] = dstView_[i+1]->getGlobalSize()*dstSliceSize[i+1] ;
+    for(auto& ranks : dstView_[0]->getLocalSize())
+    {
+      dstGlobalIndex.clear() ;
+      int rank=ranks.first ;
+      size_t sliceIndex=0 ;
+      dstView_[nDst-1]->getGlobalIndex(rank, dstGlobalIndex, sliceIndex, dstSliceSize.data(), dstView_.data(), nDst-1) ;
+      for(auto globalIndex : dstGlobalIndex) info[globalIndex].push_back(rank) ; // insert into DHT
+    }
+    
+    CClientClientDHTTemplate<int> dataRanks(info, localComm_) ;
+    
+    // generate list of global index for src view
+    int nSrc = srcView_.size() ;
+    vector<size_t> srcSliceSize(nSrc) ;
+    srcSliceSize[nSrc-1] = 1 ;
+    for(int i=nSrc-2; i>=0; i--)  srcSliceSize[i] = srcView_[i+1]->getGlobalSize()*srcSliceSize[i+1] ;
+    
+    vector<size_t> srcGlobalIndex ;
+    size_t sliceIndex=0 ;
+    srcView_[nSrc-1]->getGlobalIndex(srcGlobalIndex, sliceIndex, srcSliceSize.data(), srcView_.data(), nSrc-1) ;
+    
+    CArray<size_t,1> srcGlobalIndexArray(srcGlobalIndex.data(), shape(srcGlobalIndex.size()),neverDeleteData) ;
+    dataRanks.computeIndexInfoMapping(srcGlobalIndexArray) ;
+    const auto& returnInfo = dataRanks.getInfoIndexMap() ;
+
+    vector<map<int, set<size_t>>> elements(nSrc) ; // internal representation of elements composing the grid
+
+    srcSliceSize[nSrc-1] = srcView_[nSrc-1]->getGlobalSize() ;
+    for(int i=nSrc-2 ; i>=0 ; i--) srcSliceSize[i] = srcView_[i]->getGlobalSize()*srcSliceSize[i+1] ;
+
+    for(auto& indRanks : returnInfo)
+    {
+      size_t gridIndexGlo=indRanks.first ;
+      auto& ranks = indRanks.second ;
+      for(int i=0;i<nSrc;i++)
+      {
+        auto& element = elements[i] ;
+        size_t localIndGlo = gridIndexGlo % srcSliceSize[i] ;
+        for(int rank : ranks) element[rank].insert(localIndGlo) ;
+      }
+    }
+
+    elements_.resize(nSrc) ;
+    for(int i=0 ; i<nSrc; i++)
+    {
+      auto& element=elements[i] ;
+      for(auto& rankInd : element)
+      {
+        int rank=rankInd.first ;
+        set<size_t>& indGlo = rankInd.second ;
+        CArray<size_t,1>& indGloArray = elements_[i][rank] ;
+        indGloArray.resize(indGlo.size()) ;
+        int j=0 ;
+        for (auto index : indGlo) { indGloArray(j) = index ; j++; }
+      }
+    }
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_remote_connector.hpp	(revision 1918)
@@ -0,0 +1,35 @@
+#ifndef __GRID_REMOTE_CONNECTOR_HPP__
+#define __GRID_REMOTE_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+
+
+namespace xios
+{
+ 
+  class CGridRemoteConnector
+  {
+
+    public:
+
+      CGridRemoteConnector(vector<CLocalView*>& srcView, vector<CDistributedView*>& dstView, MPI_Comm localComm) ;
+      void computeConnector(void) ;
+      void computeGenericMethod(void) ;
+      std::map<int, CArray<size_t,1>>& getDistributedGlobalIndex(int pos) { return elements_[pos] ;} 
+
+    private:
+      vector<map<int, CArray<size_t,1>>> elements_ ;
+      vector<CLocalView*> srcView_ ;
+      vector<CDistributedView*> dstView_ ;
+      MPI_Comm localComm_ ;
+
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_scatterer_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_scatterer_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/grid_scatterer_connector.hpp	(revision 1918)
@@ -0,0 +1,85 @@
+#ifndef __GRID_SCATTERER_CONNECTOR_HPP__
+#define __GRID_SCATTERER_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+#include "scatterer_connector.hpp"
+
+
+namespace xios
+{
+ 
+  class CGridScattererConnector
+  {
+    private:
+     vector<CScattererConnector*> elementsConnector_ ;
+     map<int,int> nbSenders_ ;
+     vector<int> ranks_ ;
+     map<int,int> dstSize_ ;
+     
+
+    public:
+      CGridScattererConnector(vector<CScattererConnector*> elementsConnector) : elementsConnector_(elementsConnector) 
+      {
+        nbSenders_ = elementsConnector[0]->getNbSenders() ;
+        for(auto& rank : nbSenders_) 
+        {
+          ranks_.push_back(rank.first) ;
+          dstSize_[rank.first] = 1 ;
+        }
+
+        // init dstSize_
+        for(auto& connector : elementsConnector_) 
+        {
+          auto& sizes = connector->getDstSize() ;
+          for(auto& rankSize : sizes) dstSize_[rankSize.first] = dstSize_[rankSize.first] * rankSize.second ;
+        }    
+      }     
+
+
+      template<typename T, int N> 
+      void transfer(const CArray<T,N>& input, map<int, CArray<T,1>>& output)
+      {
+        int n = elementsConnector_.size()-1 ;
+        CScattererConnector** connector = elementsConnector_.data() + n ;
+        for(int rank : ranks_) 
+        {
+          auto& out = output[rank] ;
+          out.resize(dstSize_[rank]) ;
+          elementsConnector_[n]->transfer(rank, connector, n, input.dataFirst(), out.dataFirst()) ;
+        }
+      }
+ 
+      template<typename T, int N> 
+      void transfer(const CArray<T,N>& input, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+      {
+        map<int, CArray<T,1>> output ;
+        transfer(input, output) ;
+        sendToServer(output, client, event, messageHeader) ;
+      }
+      
+      template<typename T>
+      void sendToServer(const map<int, CArray<T,1>>& dataOut, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+      {
+        list<CMessage> messages;
+        for(auto ranksData : dataOut)
+        {
+          int rank = ranksData.first ;
+          auto& data = ranksData.second ;
+
+          messages.push_back(CMessage(messageHeader));
+          messages.back().push(data) ;
+          event.push(rank, nbSenders_[rank], messages.back());
+        }
+        client->sendEvent(event) ;
+      }
+ 
+  };
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.cpp	(revision 1918)
@@ -0,0 +1,50 @@
+#include "local_connector.hpp"
+
+
+namespace xios
+{
+    void CLocalConnector::computeConnector(void)
+  {
+    int srcLocalSize=srcView_->getLocalSize() ;
+    const CArray<int,1>& srcIndex = srcView_->getIndex() ;
+    int srcSize = srcIndex.numElements() ;
+
+    int dstLocalSize=dstView_->getLocalSize() ;
+    const CArray<int,1>& dstIndex = dstView_->getIndex() ;
+    int dstSize = dstIndex.numElements() ;
+
+    CArray<int,1> local(srcLocalSize) ;
+    local = -1 ;
+    mask_.resize(dstSize) ;
+
+    for(int i=0;i<srcSize;i++)
+    {
+      if (srcIndex(i)>=0 && srcIndex(i) < srcLocalSize) local(srcIndex(i)) = i ;
+    }
+
+    int connectorSize=0 ;
+    for(int i=0;i<dstSize;i++)
+    {
+      if (dstIndex(i)>=0 && dstIndex(i) < dstLocalSize && local(dstIndex(i))!=-1)
+      { 
+        mask_[i]=true ;
+        connectorSize++ ;
+      }
+      else mask_[i]=false ;
+    }
+    
+    connector_.resize(connectorSize) ;
+    connectorSize=0 ;
+    for(int i=0;i<dstSize;i++)
+    {
+      if (mask_[i])
+      {
+        connector_[connectorSize] = local(dstIndex(i)) ;
+        connectorSize++ ;
+      }
+    }
+  }
+
+
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_connector.hpp	(revision 1918)
@@ -0,0 +1,135 @@
+#ifndef __LOCAL_CONNECTOR_HPP__
+#define __LOCAL_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "local_view.hpp"
+
+
+
+namespace xios
+{
+  
+  class CLocalConnector
+  {
+    
+    private:
+      CLocalView* srcView_;
+      CLocalView* dstView_;
+      int srcSize_ ;
+      int dstSize_ ;
+      vector<int> connector_ ;
+      vector<bool> mask_ ;
+
+    public:
+    
+      CLocalConnector(CLocalView* srcView, CLocalView* dstView) : srcView_(srcView), dstView_(dstView), 
+                                                                  srcSize_(srcView->getSize()), dstSize_(dstView->getSize()) {}
+      void computeConnector(void);
+      int getSrcSize(void) {return srcSize_ ;}
+      int getDstSize(void) {return dstSize_ ; }
+
+      template<typename T> void transfer(const CArray<T,1>& input, CArray<T,1>& output)
+      {
+        int size=mask_.size() ;
+        output.resize(size) ;
+        for(int i=0,j=0;i<size;i++) 
+        {
+          if (mask_[i]) 
+          {
+            output(i)=input(connector_[j]) ;
+            j++ ;
+          }
+        }
+      }
+
+      template<typename T> void transfer(const CArray<T,1>& input, CArray<T,1>& output, T missingValue)
+      {
+        int size=mask_.size() ;
+        output.resize(size) ;
+        for(int i=0,j=0;i<size;i++) 
+        {
+          if (mask_[i]) 
+          {
+            output(i)=input(connector_[j]) ;
+            j++ ;
+          }
+          else output(i)=missingValue ;
+        }
+      }
+
+      template<typename T> void transfer(CLocalConnector** connectors, int nConnectors, const T* input, T* output)
+      {
+
+        int size=mask_.size() ;
+        if (nConnectors==0)
+        {
+          for(int i=0,j=0;i<size;i++) 
+            if (mask_[i]) 
+            {
+              *(output+i)=*(input+connector_[j]) ;
+              j++ ;
+            }
+        }
+        else
+        {
+          int srcSliceSize = (*(connectors-1))->getSrcSliceSize(connectors-1, nConnectors-1) ;
+          int dstSliceSize = (*(connectors-1))->getDstSliceSize(connectors-1, nConnectors-1) ;
+
+          T* out = output ; 
+          for(int i=0,j=0;i<size;i++) 
+          {
+            if (mask_[i]) 
+            {
+              (*(connectors-1))->transfer(connectors-1, nConnectors-1, input+connector_[j]*srcSliceSize, out) ; // the multiplication must be avoid in further optimization
+              j++ ;
+            }
+            out += dstSliceSize ;
+          }
+
+        }
+      }
+
+      template<typename T> void transfer(CLocalConnector** connectors, int nConnectors, const T* input, T* output, T missingValue)
+      {
+        int size=mask_.size() ;
+        if (nConnectors==0)
+        {
+          for(int i=0,j=0;i<size;i++) 
+            if (mask_[i]) 
+            {
+              *(output+i)=*(input+connector_[j]) ;
+              j++ ;
+            }
+            else *(output+i)=missingValue ;
+        }
+        else
+        {
+          int srcSliceSize = (*(connectors-1))->getSrcSliceSize(connectors-1, nConnectors-1) ;
+          int dstSliceSize = (*(connectors-1))->getDstSliceSize(connectors-1, nConnectors-1) ;
+
+          T* out = output ; 
+          for(int i=0,j=0;i<size;i++) 
+          {
+            if (mask_[i]) 
+            {
+              (*(connectors-1))->transfer(connectors-1, nConnectors-1, input+connector_[j]*srcSliceSize, out, missingValue) ; // the multiplication must be avoid in further optimization
+              j++ ;
+            }
+            else for (int j=0 ; j<dstSliceSize ; j++) *(out+j) = missingValue ;
+            out += dstSliceSize ;
+          }
+        }
+      }
+
+      int getSrcSliceSize(CLocalConnector** connectors, int nConnectors) 
+      { if (nConnectors==0) return srcSize_ ; else return srcSize_ * (*(connectors-1))->getSrcSliceSize(connectors-1,nConnectors-1) ; }
+
+      int getDstSliceSize(CLocalConnector** connectors, int nConnectors) 
+      { if (nConnectors==0) return dstSize_ ; else return dstSize_ * (*(connectors-1))->getDstSliceSize(connectors-1,nConnectors-1) ; }
+
+  };
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.cpp	(revision 1918)
@@ -0,0 +1,34 @@
+#include "local_view.hpp"
+#include "element.hpp"
+#include "array_new.hpp"
+#include "remote_connector.hpp"
+
+namespace xios
+{
+  CLocalView::CLocalView(CLocalElement* parent, CElementView::type type, const CArray<int,1>& indexView) 
+                        : CDistributedView( parent, type, {{  parent->localRank_,  indexView }} ),
+                          localRank_(parent->localRank_),
+                          globalIndex_(parent->globalIndex_), size_(CDistributedView::size_[parent->localRank_]),
+                          index_(CDistributedView::index_[parent->localRank_]), localSize_(CDistributedView::localSize_[parent->localRank_]) 
+  {
+
+  }
+
+
+  void CLocalView::sendRemoteElement(CRemoteConnector& connector, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+  {
+    int n = index_.numElements() ;
+    int nglo=globalIndex_.numElements() ;
+    CArray<size_t,1> ind(n) ;
+    for(int i=0; i<n;i++)
+    {
+      if (index_(i)>=0 && index_(i)<nglo) ind(i) = globalIndex_(index_(i)) ;
+      else ind(i)=index_(i) ;
+    }
+    CMessage message(messageHeader) ;
+    message<<globalSize_ ;
+    connector.transferToServer(ind, client, event, message) ;
+  }
+
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/local_view.hpp	(revision 1918)
@@ -0,0 +1,51 @@
+#ifndef __LOCAL_VIEW_HPP__
+#define __LOCAL_VIEW_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+
+namespace xios
+{
+
+  class CLocalElement ;
+  class CRemoteConnector ;
+
+  class CLocalView : public CDistributedView
+  {
+    public:
+    CLocalView(CLocalElement* parent, CElementView::type type, const CArray<int,1>& indexView) ;
+    const CArray<int,1>& getIndex(void) { return index_ ;}
+    const CArray<size_t,1>& getGlobalIndex(void) { return globalIndex_ ;}
+
+    void getGlobalIndex(vector<size_t>& globalIndex, size_t sliceIndex, size_t* sliceSize, CLocalView** localView, int pos)
+    {
+      if (pos==0)
+      {
+        for(int i=0;i<size_;i++)
+          if (index_(i)>=0 && index_(i)<localSize_) globalIndex.push_back(sliceIndex + globalIndex_(index_(i))) ;
+      }
+      else 
+      {
+        for(int i=0;i<size_;i++)
+          if (index_(i)>=0 && index_(i)<localSize_) 
+            localView[pos-1]->getGlobalIndex(globalIndex, sliceIndex + globalIndex_(index_(i))*sliceSize[pos], sliceSize, localView, pos-1) ;
+      }
+    }
+
+
+    int getLocalSize(void) {return localSize_ ;}
+    int getSize(void) {return size_;} 
+    void sendRemoteElement(CRemoteConnector& connector, CContextClient* client, CEventClient& event, const CMessage& messageHeader) ;
+   
+    CArray<size_t,1>& globalIndex_ ;
+    CArray<int,1>& index_ ;
+    int& size_ ;
+    int& localRank_ ;
+    int& localSize_ ;
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.cpp	(revision 1918)
@@ -0,0 +1,77 @@
+#include "remote_connector.hpp"
+#include "client_client_dht_template.hpp"
+
+
+namespace xios
+{
+
+  void CRemoteConnector::computeConnector(void)
+  {
+    CClientClientDHTTemplate<int>::Index2VectorInfoTypeMap info ;
+    for(auto& dstIndex : dstView_->getIndex())
+    {
+      int rank=dstIndex.first ;
+      auto& indexList=dstIndex.second ;
+      auto& globalIndex = dstView_->getGlobalIndex()[rank] ;
+      for(int i=0;i<indexList.numElements();i++) info[globalIndex(indexList(i))].push_back(rank) ;  
+    }
+    CClientClientDHTTemplate<int> dataRanks(info, localComm_) ;
+    
+    set<size_t> setGlobalIndex ; // all global index from src
+    auto& srcIndex = srcView_->getIndex() ;
+    auto& globalIndex = srcView_->getGlobalIndex() ;
+    int globalIndexSize = globalIndex.numElements() ;
+    int indexSize = srcIndex.numElements() ;
+    for(int i=0;i<indexSize;i++) 
+    {
+      if (srcIndex(i)>=0 & srcIndex(i)<globalIndexSize) setGlobalIndex.insert(globalIndex(srcIndex(i))) ;
+    }
+    
+    CArray<size_t,1> srcGlobalIndex(setGlobalIndex.size()) ;
+    int i=0 ;
+    for(auto& globalIndex : setGlobalIndex) 
+    {
+      srcGlobalIndex(i) = globalIndex ;
+      i++ ;
+    }
+
+    dataRanks.computeIndexInfoMapping(srcGlobalIndex) ;
+    const auto& returnInfo = dataRanks.getInfoIndexMap() ;
+
+    // so we have the info where to send data : rank and local index. 
+    // create the interconnector :
+    map<int,vector<size_t>> element ;
+    for(int i=0;i<indexSize;i++)
+    {
+      if (srcIndex(i)>=0 & srcIndex(i)<globalIndexSize)
+      {
+        size_t indGlo = globalIndex(srcIndex(i)) ;
+        // don't forget that a single point can be sent multiple time (redondency ?)
+        for(auto& rank : returnInfo.at(indGlo))
+        {
+          connector_[rank].push_back(i) ;
+          element[rank].push_back(indGlo) ;
+        }
+      }
+    }
+
+    for(auto rankIndex : element)
+    {
+      CArray<size_t,1> arrayTmp(rankIndex.second.data(), shape(rankIndex.second.size()), duplicateData) ;
+      element_[rankIndex.first].reference(arrayTmp) ;
+    }
+    
+    // compute the number of senders for a remote destination view
+    int commSize ;
+    MPI_Comm_size(localComm_, &commSize) ;
+    vector<int> ranks(commSize,0) ;
+    for(auto& rank : connector_) ranks[rank.first] = 1 ;
+    MPI_Allreduce(MPI_IN_PLACE,ranks.data(),commSize,MPI_INT,MPI_SUM,localComm_) ;
+    for(auto& rank : connector_) nbSenders_[rank.first] = ranks[rank.first] ;
+  }
+
+
+
+
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/remote_connector.hpp	(revision 1918)
@@ -0,0 +1,78 @@
+#ifndef __REMOTE_CONNECTOR_HPP__
+#define __REMOTE_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+
+
+namespace xios
+{
+ 
+  class CRemoteConnector
+  {
+    private:
+      CLocalView* srcView_;
+      CDistributedView* dstView_;
+      map<int, vector<int>> connector_ ; // connector[rank][srcIndex]
+
+      MPI_Comm localComm_ ;
+      map<int,int> nbSenders_ ; // number of participant when sending remote buffer
+      map<int, CArray<size_t,1>> element_ ; // global index of elements to send
+    
+    public:
+      CRemoteConnector(CLocalView* srcView, CDistributedView* dstView, MPI_Comm localComm) : srcView_(srcView), dstView_(dstView), localComm_(localComm){} ;
+      void computeConnector(void) ;
+      map<int, CArray<size_t,1>>& getDistributedGlobalIndex() { return element_ ;} 
+      
+      template<typename T>
+      void transfer(const CArray<T,1>& dataIn, map<int, CArray<T,1>>& dataOut)
+      {
+        auto ptrDataIn = dataIn.dataFirst() ;
+        for(auto& indexRank : connector_) 
+        {
+          int rank=indexRank.first ;
+          auto& index=indexRank.second ;
+          auto it = dataOut.emplace(rank, CArray<T,1>(index.size())).first ; // return an iterator on the obect inserted
+          auto ptrDataOut = it->second.dataFirst() ;
+          for(auto ind : index) 
+          {
+            *ptrDataOut = ptrDataIn[ind] ;
+            ptrDataOut++ ;
+          }
+        }
+      }
+      
+      template<typename T>
+      void sendToServer(map<int, CArray<T,1>>& dataOut, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+      {
+        list<CMessage> messages;
+        for(auto ranksData : dataOut)
+        {
+          int rank = ranksData.first ;
+          auto& data = ranksData.second ;
+
+          messages.push_back(CMessage(messageHeader));
+          messages.back().push(data) ;
+          event.push(rank, nbSenders_[rank], messages.back());
+        }
+        client->sendEvent(event) ;
+      }
+
+      template<typename T>
+      void transferToServer(const CArray<T,1>& dataIn, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+      {
+        map<int, CArray<T,1>> dataOut ;
+        transfer(dataIn, dataOut) ;
+        sendToServer(dataOut, client, event,messageHeader) ;
+      }
+
+  } ;
+
+}
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.cpp	(revision 1918)
@@ -0,0 +1,62 @@
+#include "scatterer_connector.hpp"
+
+
+namespace xios
+{
+
+  void CScattererConnector::computeConnector(void)
+  {
+    auto& srcGlobalIndex = srcView_->getGlobalIndex() ;
+    auto& srcIndex = srcView_->getIndex() ;
+    srcSize_=srcIndex.numElements() ;
+    auto srcSize = srcView_->getSize() ;
+    auto srcLocalSize = srcView_->getLocalSize() ;
+    
+    auto& dstIndex = dstView_->getIndex() ;
+    for(auto& rankIndex : dstIndex) dstSize_[rankIndex.first]=rankIndex.second.numElements() ;
+    auto& dstGlobalIndex = dstView_->getGlobalIndex() ;
+
+    unordered_map<size_t,int> mapGlobalLocalIndex ;
+    int globalIndexSize=srcGlobalIndex.size() ;
+    
+    for(int i=0 ; i<srcSize ; i++) 
+      if (srcIndex(i) >=0 && srcIndex(i) <srcLocalSize) mapGlobalLocalIndex[srcGlobalIndex(srcIndex(i))] = i ;
+    
+    for(auto& rankIndex : dstIndex)
+    {
+      int rank = rankIndex.first ;
+      auto& index = rankIndex.second ;
+      int size = index.numElements() ;
+      auto& globalIndex = dstGlobalIndex[rank] ;
+      int localSize = globalIndex.numElements() ;
+      auto& connector = connector_[rank] ;
+      auto& mask = mask_[rank] ;
+      mask.resize(size) ;
+
+      for(int i=0 ; i<size ; i++) 
+      {
+        if (index(i) >= 0  && index(i) < localSize)
+        {
+          const auto& it = mapGlobalLocalIndex.find(globalIndex(index(i))) ;
+          if (it != mapGlobalLocalIndex.end()) 
+          {
+            connector.push_back(it->second) ;
+            mask[i] = true ;
+          }
+          else mask[i]=false ;
+        }
+        else mask[i]=false ;
+      }
+    }
+
+   // compute the number of senders for a remote destination view
+    int commSize ;
+    MPI_Comm_size(localComm_, &commSize) ;
+    vector<int> ranks(commSize,0) ;
+    for(auto& rank : connector_) ranks[rank.first] = 1 ;
+    MPI_Allreduce(MPI_IN_PLACE,ranks.data(),commSize,MPI_INT,MPI_SUM,localComm_) ;
+    for(auto& rank : connector_) nbSenders_[rank.first] = ranks[rank.first] ;
+
+  }
+
+}
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/scatterer_connector.hpp	(revision 1918)
@@ -0,0 +1,128 @@
+#ifndef __SCATTERER_CONNECTOR_HPP__
+#define __SCATTERER_CONNECTOR_HPP__
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include "distributed_view.hpp"
+#include "mpi.hpp"
+#include "local_view.hpp"
+#include "distributed_view.hpp"
+#include "context_client.hpp"
+
+
+namespace xios
+{
+ 
+  class CScattererConnector
+  {
+
+    private:
+      map<int, vector<int>> connector_ ;
+      map<int, vector<bool>> mask_ ;  // mask is on dst view
+      MPI_Comm localComm_ ;
+
+      CLocalView* srcView_ ;
+      CDistributedView* dstView_ ;
+      map<int,int> nbSenders_ ; // number of participant when sending remote buffer
+      int srcSize_ ;
+      map<int,int> dstSize_ ;
+
+    public:
+
+    CScattererConnector(CLocalView* srcView, CDistributedView* dstView, MPI_Comm localComm) 
+                       : srcView_(srcView), dstView_(dstView), localComm_(localComm) {}
+    void computeConnector(void) ;
+    
+    template<typename T>
+    void transfer(const CArray<T,1>& dataIn, map<int, CArray<T,1>>& dataOut)
+    {
+      for(auto& rankConnector : connector_)
+      {
+        int rank = rankConnector.first ;
+        auto& connector = rankConnector.second ;
+        auto& mask = mask_[rank] ;
+        int dstSize = mask.size() ;
+        auto& data = dataOut[rank] ;
+        data.resize(dstSize) ;
+        T* dstData = data.dataFirst() ;
+        const T* srcData = dataIn.dataFirst() ;
+        for(int i=0, j=0; i<dstSize; i++)
+          if (mask[i]) 
+          {
+            dstData[i] = srcData[connector[j]] ;
+            j++ ;
+          }
+      }
+    }
+    
+    template<typename T>
+    void transfer(const CArray<T,1>& dataIn, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+    {
+      map<int, CArray<T,1>> dataOut ;
+      transfer(dataIn, dataOut) ;
+      sendToServer(dataOut, client, event, messageHeader) ;
+    }
+
+    template<typename T> 
+    void transfer(int rank, CScattererConnector** connectors, int nConnectors, const T* input, T* output)
+    {
+      auto& connector = connector_[rank] ; // probably costly, find a better way to avoid the map
+      auto& mask = mask_[rank] ; 
+      int dstSize = mask.size() ;
+      if (nConnectors==0)
+      {
+        for(int i=0, j=0; i<dstSize; i++)
+          if (mask[i]) 
+          {
+            *(output+i)=*(input+connector[j]) ;
+            j++ ;
+          }
+
+      }
+      else
+      {
+        int srcSliceSize = (*(connectors-1))->getSrcSliceSize(connectors-1, nConnectors-1) ;
+        int dstSliceSize = (*(connectors-1))->getDstSliceSize(rank, connectors-1, nConnectors-1) ;
+
+        T* out = output ; 
+        for(int i=0,j=0;i<dstSize;i++) 
+        {
+          if (mask[i]) 
+          {
+            (*(connectors-1))->transfer(rank, connectors-1, nConnectors-1, input+connector[j]*srcSliceSize, out) ; // the multiplication must be avoid in further optimization
+            j++ ;
+          }
+          out += dstSliceSize ;
+        }
+      }
+    }
+
+      
+    template<typename T>
+    void sendToServer(const map<int, CArray<T,1>>& dataOut, CContextClient* client, CEventClient& event, const CMessage& messageHeader)
+    {
+      list<CMessage> messages;
+      for(auto ranksData : dataOut)
+      {
+        int rank = ranksData.first ;
+        auto& data = ranksData.second ;
+
+        messages.push_back(CMessage(messageHeader));
+        messages.back().push(data) ;
+        event.push(rank, nbSenders_[rank], messages.back());
+      }
+      client->sendEvent(event) ;
+    }
+
+    int getSrcSliceSize(CScattererConnector** connectors, int nConnectors) 
+    { if (nConnectors==0) return srcSize_ ; else return srcSize_ * (*(connectors-1))->getSrcSliceSize(connectors-1,nConnectors-1) ; }
+
+    int getDstSliceSize(int rank, CScattererConnector** connectors, int nConnectors) 
+    { if (nConnectors==0) return dstSize_[rank] ; else return dstSize_[rank] * (*(connectors-1))->getDstSliceSize(rank, connectors-1,nConnectors-1) ; }
+
+    const map<int,int>& getNbSenders(void) {return nbSenders_ ;} 
+    const map<int,int>& getDstSize(void) { return dstSize_ ;}
+  } ;
+} 
+
+#endif
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.cpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.cpp	(revision 1918)
@@ -0,0 +1,522 @@
+/*!
+   \file server_distribution_description.hpp
+   \author Ha NGUYEN
+   \since 04 Jan 2015
+   \date 11 Jan 2016
+
+   \brief Description of index distribution on server(s).
+ */
+
+#include "server_distribution_description.hpp"
+#include "exception.hpp"
+
+namespace xios
+{
+  /*!
+  \param [in] globalDimensionSize global dimension of grid
+  \param [in] nServer number of server
+  \param [in] serType type of server distribution. For now, we can distribute server by band or plan
+  */
+CServerDistributionDescription::CServerDistributionDescription(const std::vector<int>& globalDimensionSize,
+                                                               int nServer,
+                                                               ServerDistributionType serType)
+  : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(),
+    vecGlobalIndex_(), serverType_(serType), nServer_(nServer), positionDimensionDistributed_(1)
+{
+}
+
+CServerDistributionDescription::~CServerDistributionDescription()
+{ /* Nothing to do */ }
+
+int CServerDistributionDescription::defaultDistributedDimension(int gridDimension,                                   
+                                                                ServerDistributionType serType)
+{  
+  switch (serType) 
+  {
+    case BAND_DISTRIBUTION:       
+       return ((1 == gridDimension) ? 0 : 1);
+      break;
+    default:
+      break;
+  } 
+}
+
+/*!
+  Compute pre-defined global index distribution of server(s).
+  \param [in] doComputeGlobalIndex flag to compute global index on each server. By default, false
+
+*/
+void CServerDistributionDescription::computeServerDistribution(bool doComputeGlobalIndex,
+                                                               int positionDimensionDistributed)
+{
+  switch (serverType_) {
+    case BAND_DISTRIBUTION:
+      computeBandDistribution(nServer_, positionDimensionDistributed);
+      break;
+    default:
+      break;
+  }
+
+  if (doComputeGlobalIndex)
+  {
+    vecGlobalIndex_.resize(nServer_);
+    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].resize(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;
+          }
+          vecGlobalIndex_[idxServer](idx) = globalIndex;
+          ++idx;
+        }
+        idxLoop[0] += innerLoopSize;
+      }
+    }
+  }
+}
+
+/*!
+  Compute global index assigned to a server with a range.E.g: if a grid has 100 points and
+  there are 2 servers, the first one takes index from 0 to 49, the second has index from 50 to 99
+  \param [in] indexBeginEnd begining and ending index of range
+  \param [in] positionDimensionDistributed dimension of server on which we make the cut.
+*/
+std::vector<int> CServerDistributionDescription::computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd,
+                                                                     int positionDimensionDistributed)
+{
+  int nBand  = 0;
+  switch (serverType_)
+  {
+    case BAND_DISTRIBUTION:
+      nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
+      break;
+    case ROOT_DISTRIBUTION:
+      nBand = computeRootDistribution(nServer_);
+    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");
+
+  globalIndex_.rehash(std::ceil((indexEnd-indexBegin+1)/globalIndex_.max_load_factor()));
+
+  int dim = nGlobal_.size();
+  std::vector<int> currentIndex(dim);
+
+  for (int idxServer = 0; idxServer < nBand; ++idxServer)
+  {
+    size_t ssize = 1, idx = 0;
+    for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
+
+    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_[globalIndex] = idxServer;
+        ++idx;
+      }
+      idxLoop[0] += innerLoopSize;
+    }
+  }
+
+    // List of servers without distribution (cause total number of server is greater than number of bands, for example)
+  std::vector<int> zeroIndexServer(nServer_-nBand); 
+  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
+    zeroIndexServer[idxServer-nBand] = idxServer;
+
+  return zeroIndexServer;
+}
+
+/*!
+  Compute the global index of grid elements (domain, axis) and their associated server rank.
+  Each client knows the general distribution of servers and from which they can compute the pieces of information to hold
+  \param [out] indexServerOnElement global index of each element as well as the corresponding server which contains these indices
+  \param [in] clientRank rank of client
+  \param [in] clientSize number of client
+  \param [in] axisDomainOrder the order of element in grid (2 for domain, 1 for axis, 0 for scalar)
+  \param [in] positionDimensionDistributed dimension of server on which we make the cut.
+*/
+std::vector<int> CServerDistributionDescription::computeServerGlobalByElement(std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
+                                                                              int clientRank,
+                                                                              int clientSize,
+                                                                              const CArray<int,1>& axisDomainOrder,
+                                                                              int positionDimensionDistributed)
+{
+  int nBand  = 0;
+  switch (serverType_) {
+    case BAND_DISTRIBUTION:
+      nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
+      break;
+    default:
+      break;
+  }
+
+  int nbElement = axisDomainOrder.numElements();
+  indexServerOnElement.resize(nbElement);
+  int idx = 0;
+  std::vector<int> idxMap(nbElement);
+  for (int i = 0; i < nbElement; ++i)
+  {
+    idxMap[i] = idx;
+    if (2 == axisDomainOrder(i)) idx += 2;
+    else if (1 == axisDomainOrder(i)) idx += 1;
+    // nothing for scalar
+  }
+
+  for (int idxServer = 0; idxServer < nBand; ++idxServer)
+  {
+    std::vector<int> elementDimension(4);
+    for (int i = 0; i < nbElement; ++i)
+    {
+      int elementSize = 1;
+      if (2 == axisDomainOrder(i))
+      {
+        elementSize *= dimensionSizes_[idxServer][idxMap[i]] * dimensionSizes_[idxServer][idxMap[i]+1];
+        elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
+        elementDimension[1] = indexBegin_[idxServer][idxMap[i]+1];
+        elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
+        elementDimension[3] = dimensionSizes_[idxServer][idxMap[i]+1];
+      }
+
+      else if (1 == axisDomainOrder(i))
+      {
+        elementSize *= dimensionSizes_[idxServer][idxMap[i]];
+        elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
+        elementDimension[1] = 0;
+        elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
+        elementDimension[3] = 1;
+      }
+      else
+      {
+        elementSize *= dimensionSizes_[idxServer][idxMap[i]];
+        elementDimension[0] = 0;
+        elementDimension[1] = 0;
+        elementDimension[2] = 1;
+        elementDimension[3] = 1;
+      }
+
+      int rangeBegin, rangeSize;
+      computeRangeProcIndex(clientRank, clientSize, elementSize, rangeBegin, rangeSize);
+
+      size_t globalIndexElement;
+      idx = 0; int idxRange = 0;
+      for (int k = 0; k < elementDimension[3]; ++k)
+        for (int l = 0; l < elementDimension[2]; ++l)
+        {
+          globalIndexElement = (l+elementDimension[0]) + (k+elementDimension[1])*elementDimension[2];
+          if ((rangeBegin <= idx) && (idxRange < rangeSize))
+          {
+            indexServerOnElement[i][globalIndexElement].push_back(idxServer);
+            ++idxRange;
+          }
+          ++idx;
+        }
+    }
+  }
+
+  // List of servers without distribution (cause total number of server is greater than number of bands, for example)
+  std::vector<int> zeroIndexServer(nServer_-nBand); 
+  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
+    zeroIndexServer[idxServer-nBand] = idxServer;
+
+  return zeroIndexServer;
+}
+
+/*!
+  Compute a range of index on server which a client holds
+  For a range of index on a specific server, each client can hold a piece of the index range
+  If the range size is smaller than the number of client, there are some clients holding the same index
+  \param [in] clientRank rank of client
+  \param [in] clientSize number of client
+  \param [in] rangeProcSize index range size
+  \param [out] rangeBegin begin of range index a client holds
+  \param [out] rangeSize size of range index a client holds
+*/
+void CServerDistributionDescription::computeRangeProcIndex(int clientRank,
+                                                           int clientSize,
+                                                           int rangeProcSize,
+                                                           int& rangeBegin,
+                                                           int& rangeSize)
+{
+  if (rangeProcSize < clientSize)
+  {
+    int rangeIndex = 0;
+    for (int idx = 0; idx < clientSize; ++idx)
+    {
+      if (idx == clientRank)
+      {
+        rangeBegin = rangeIndex;
+        rangeSize = 1;
+      }
+      ++rangeIndex;
+      if (rangeIndex == rangeProcSize) rangeIndex = 0;
+    }
+    return;
+  }
+
+  int range, indexBegin = 0;
+  for (int i = 0; i < clientSize; ++i)
+  {
+    range = rangeProcSize / clientSize;
+    if (i < (rangeProcSize%clientSize)) ++range;
+    if (i == clientRank) break;
+    indexBegin += range;
+  }
+  rangeBegin = indexBegin;
+  rangeSize = range;
+}
+
+/*!
+  Compute global index of servers with band distribution
+  \param [in] nServer number of server
+*/
+int CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)
+{
+  int dim = nGlobal_.size();
+  positionDimensionDistributed_ = positionDimensionDistributed;
+  if (1 == dim) positionDimensionDistributed_ = 0;
+  if (positionDimensionDistributed_ > dim)
+    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
+          << "Position of distributed dimension is invalid" << std::endl
+          << "Position of distributed dimension is " << positionDimensionDistributed_
+          << "Dimension " << dim)
+
+  indexBegin_.resize(nServer);
+  dimensionSizes_.resize(nServer);
+
+  for (int i = 0; i< nServer; ++i)
+  {
+    indexBegin_[i].resize(dim);
+    dimensionSizes_[i].resize(dim);
+  }
+
+  int njRangeSize;
+  int nGlobTemp = 0;
+  std::vector<int> njRangeBegin(nServer,0);
+  std::vector<int> njRangeEnd(nServer,0);
+
+  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
+  nGlobTemp = nGlobal_[positionDistributed];
+  int nbBand = std::min(nGlobTemp, nServer);
+
+  for (int i = 0; i < nbBand; ++i)
+  {
+    if (0 < i) njRangeBegin[i] = njRangeEnd[i-1];
+    njRangeSize = nGlobTemp / nbBand;
+    if (i < nGlobTemp%nbBand) ++njRangeSize;
+    njRangeEnd[i] = njRangeSize + njRangeBegin[i];
+  }
+  njRangeEnd[nbBand-1] = nGlobTemp;
+
+  for (int i = nbBand; i < nServer; ++i)
+  {
+    njRangeBegin[i] = njRangeEnd[i] = 0;
+  }
+
+  for (int i = 0; i < nServer; ++i)
+  {
+    for (int j = 0; j < dim; ++j)
+    {
+      if (positionDistributed != j)
+      {
+        if (1 == dim)
+        {
+          indexBegin_[i][j] = njRangeBegin[i];
+          dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
+        }
+        else
+        {
+          indexBegin_[i][j] = 0;
+          dimensionSizes_[i][j] = nGlobal_[j];
+        }
+      }
+      else
+      {
+        indexBegin_[i][j] = njRangeBegin[i];
+        dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
+      }
+    }
+  }
+
+  return nbBand;
+}
+
+
+/*!
+  Compute global index of servers with root distribution : only root server will received data
+  \param [in] nServer number of server
+*/
+int CServerDistributionDescription::computeRootDistribution(int nServer, int positionDimensionDistributed)
+{
+  int dim = nGlobal_.size();
+  positionDimensionDistributed_ = positionDimensionDistributed;
+  if (1 == dim) positionDimensionDistributed_ = 0;
+  if (positionDimensionDistributed_ > dim)
+    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
+          << "Position of distributed dimension is invalid" << std::endl
+          << "Position of distributed dimension is " << positionDimensionDistributed_
+          << "Dimension " << dim)
+
+  indexBegin_.resize(nServer);
+  dimensionSizes_.resize(nServer);
+
+  for (int i = 0; i< nServer; ++i)
+  {
+    indexBegin_[i].resize(dim);
+    dimensionSizes_[i].resize(dim);
+  }
+
+  int nGlobTemp = 0;
+
+  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
+  nGlobTemp = nGlobal_[positionDistributed];
+  int nbBand = 1 ;
+
+
+  for (int i = 0; i < nServer; ++i)
+  {
+    for (int j = 0; j < dim; ++j)
+    {
+      if (positionDistributed != j) // bad coding, need to be rewrite
+      {
+        if (1 == dim)
+        {
+          if (i==0)
+          {
+            indexBegin_[i][j] = 0;
+            dimensionSizes_[i][j] = nGlobTemp;
+          }
+          else
+          {
+            indexBegin_[i][j] = nGlobTemp-1;
+            dimensionSizes_[i][j] = 0;
+          }
+        }
+        else
+        {
+          indexBegin_[i][j] = 0;
+          dimensionSizes_[i][j] = nGlobal_[j];
+        }
+      }
+      else
+      {
+        if (i==0)
+        {
+          indexBegin_[i][j] = 0;
+          dimensionSizes_[i][j] = nGlobTemp;
+        }
+        else
+        {
+          indexBegin_[i][j] = nGlobTemp-1;
+          dimensionSizes_[i][j] = 0;
+        }
+      }
+    }
+  }
+
+  return nbBand;
+}
+
+
+
+
+/*!
+  Get size of each dimension on distributed server
+  \return size of dimensions on server(s)
+*/
+std::vector<std::vector<int> > CServerDistributionDescription::getServerDimensionSizes() const
+{
+  return dimensionSizes_;
+}
+
+/*!
+  Get index begin of each dimension on distributed server
+  \return index begin of dimensions on server(s)
+*/
+std::vector<std::vector<int> > CServerDistributionDescription::getServerIndexBegin() const
+{
+  return indexBegin_;
+}
+
+/*!
+  Get global index on distributed server
+  \return global index on server(s)
+*/
+const std::vector<CArray<size_t,1> >& CServerDistributionDescription::getGlobalIndex() const
+{
+  return vecGlobalIndex_;
+}
+
+/*!
+  Get global index calculated by computeServerGlobalIndexInRange
+*/
+const std::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
+{
+  return globalIndex_;
+}
+
+int CServerDistributionDescription::getDimensionDistributed()
+{
+  return ((1<nGlobal_.size()) ? positionDimensionDistributed_ : 0);
+}
+
+} // namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.hpp	(revision 1918)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution/server_distribution_description.hpp	(revision 1918)
@@ -0,0 +1,88 @@
+/*!
+   \file server_distribution_description.hpp
+   \author Ha NGUYEN
+   \since 04 Jan 2015
+   \date 11 Jan 2016
+
+   \brief Description of index distribution on server(s).
+ */
+
+#ifndef __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
+#define __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
+
+#include "xios_spl.hpp"
+#include "array_new.hpp"
+#include <unordered_map>
+
+namespace xios
+{
+/*!
+   \class CServerDistributionDescription
+   This class contains information that describe distribution of servers.
+*/
+class CServerDistributionDescription
+{
+  public:
+    enum ServerDistributionType
+    {
+      BAND_DISTRIBUTION, PLAN_DISTRIBUTION, ROOT_DISTRIBUTION
+    };
+
+    /** Default constructor */
+    CServerDistributionDescription(const std::vector<int>& globalDimensionSize,
+                                   int nServer,
+                                   ServerDistributionType serType=BAND_DISTRIBUTION);
+
+    /** Default destructor */
+    virtual ~CServerDistributionDescription();
+
+    void computeServerDistribution(bool doComputeGlobalIndex = false, int positionDimensionDistributed = 1);
+    std::vector<int> computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd, int positionDimensionDistributed = 1);
+    std::vector<int> computeServerGlobalByElement(std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
+                                                  int rank,
+                                                  int clientSize,
+                                                  const CArray<int,1>& axisDomainOrder,
+                                                  int positionDimensionDistributed = 1);
+
+    std::vector<std::vector<int> > getServerIndexBegin() const;
+    std::vector<std::vector<int> > getServerDimensionSizes() const;
+    const std::vector<CArray<size_t,1> >& getGlobalIndex() const;
+    const std::unordered_map<size_t,int>& getGlobalIndexRange() const;
+    int getDimensionDistributed();
+
+    static int defaultDistributedDimension(int gridDimension,                                   
+                                           ServerDistributionType serType=BAND_DISTRIBUTION);
+
+  protected:
+    int computeBandDistribution(int nServer, int positionDimensionDistributed = 1);
+    int computeRootDistribution(int nServer, int positionDimensionDistributed = 1);
+    void computePlanDistribution(int nServer);
+    void computeRangeProcIndex(int clientRank,
+                               int clientSize,
+                               int rangeProcSize,
+                               int& rangeBegin,
+                               int& rangeSize);
+
+  private:
+    std::vector<std::vector<int> > indexBegin_;     //!< Begin index of each dimension
+    std::vector<std::vector<int> > dimensionSizes_; //!< Size of each dimension
+    std::vector<int> nGlobal_; //!< Global size of each dimension
+
+    //!< General case, index describes distribution of each server (rarely use)
+    std::vector<CArray<size_t,1> > vecGlobalIndex_;
+
+    //!< In case we need only global index of one server with specific rank
+    std::unordered_map<size_t,int> globalIndex_;
+
+    //!< Type of distribution on server side
+    ServerDistributionType serverType_;
+
+    //!< Number of server
+    int nServer_;
+
+    //!< Position of dimension distributed on server side (by default, the second dimension)
+    int positionDimensionDistributed_;
+};
+
+} // namespace xios
+#endif // __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.cpp	(revision 1917)
+++ 	(revision )
@@ -1,610 +1,0 @@
-/*!
-   \file distribution_client.cpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 09 Mars 2015
-
-   \brief Index distribution on client side.
- */
-#include "distribution_client.hpp"
-
-namespace xios {
-
-CDistributionClient::CDistributionClient(int rank, CGrid* grid)
-   : CDistribution(rank, 0)
-   , axisDomainOrder_()
-   , nLocal_(), nGlob_(), nBeginLocal_(), nBeginGlobal_()
-   , dataNIndex_(), dataDims_(), dataBegin_(), dataIndex_()
-   , gridMask_(), indexMap_()
-   , isDataDistributed_(true), axisNum_(0), domainNum_(0)
-   , localDataIndex_(), localMaskIndex_()
-   , globalLocalDataSendToServerMap_()
-   , infoIndex_(), isComputed_(false)
-   , elementLocalIndex_(), elementGlobalIndex_(), elementIndexData_()
-   , elementNLocal_(), elementNGlobal_()
-{
-  readDistributionInfo(grid);
-  createGlobalIndex();
-}
-
-CDistributionClient::~CDistributionClient()
-{ /* Nothing to do */ }
-
-void CDistributionClient::partialClear()
-{
-  GlobalLocalMap void1 ;
-  GlobalLocalMap void2 ;
-  std::vector<int> void3 ;
-  std::vector<bool> void4 ;
-
-  globalLocalDataSendToServerMap_.swap(void1) ;
-  globalDataIndex_.swap(void2) ;
-  localDataIndex_.swap(void3);
-  localMaskIndex_.swap(void4) ;
-}
-
-/*!
-  Read information of a grid to generate distribution.
-  Every grid is composed of several axis or/and domain(s). Their information are processed
-stored and used to calculate index distribution between client and server
-  \param [in] grid Grid to read
-*/
-void CDistributionClient::readDistributionInfo(CGrid* grid)
-{
-  std::vector<CDomain*> domList = grid->getDomains();
-  std::vector<CAxis*> axisList = grid->getAxis();
-  std::vector<CScalar*> scalarList = grid->getScalars();
-  CArray<int,1> axisDomainOrder = grid->axis_domain_order;
-
-  readDistributionInfo(domList, axisList, scalarList, axisDomainOrder);
-
-  // Then check mask of grid
-  int gridDim = domList.size() * 2 + axisList.size();
-  switch (gridDim) {
-    case 0:
-      gridMask_.resize(1);
-      gridMask_(0) = true;
-      break;
-    case 1:
-      if (!grid->mask_1d.isEmpty()) readGridMaskInfo(grid->mask_1d);
-      break;
-    case 2:
-      if (!grid->mask_2d.isEmpty()) readGridMaskInfo(grid->mask_2d);
-      break;
-    case 3:
-      if (!grid->mask_3d.isEmpty()) readGridMaskInfo(grid->mask_3d);
-      break;
-    case 4:
-      if (!grid->mask_4d.isEmpty()) readGridMaskInfo(grid->mask_4d);
-      break;
-    case 5:
-      if (!grid->mask_5d.isEmpty()) readGridMaskInfo(grid->mask_5d);
-      break;
-    case 6:
-      if (!grid->mask_6d.isEmpty()) readGridMaskInfo(grid->mask_6d);
-      break;
-    case 7:
-      if (!grid->mask_7d.isEmpty()) readGridMaskInfo(grid->mask_7d);
-      break;
-    default:
-      break;
-  }
-}
-
-/*!
-  Read information from domain(s) and axis to generate distribution.
-  All information related to domain, e.g ibegin, jbegin, ni, nj, ni_glo, nj_glo
-as well as related to axis, e.g dataNIndex, dataIndex will be stored to compute
-the distribution between clients and servers. Till now, every data structure of domain has been kept
-like before, e.g: data_n_index to make sure a compability, however, it should be changed?
-  \param [in] domList List of domains of grid
-  \param [in] axisList List of axis of grid
-  \param [in] scalarList List of scalar of grid
-  \param [in] axisDomainOrder order of axis and domain inside a grid. 2 if domain, 1 if axis and zero if scalar
-//  \param [in] gridMask Mask of grid, for now, keep it 3 dimension, but it needs changing
-*/
-void CDistributionClient::readDistributionInfo(const std::vector<CDomain*>& domList,
-                                               const std::vector<CAxis*>& axisList,
-                                               const std::vector<CScalar*>& scalarList,
-                                               const CArray<int,1>& axisDomainOrder)
-{
-  domainNum_ = domList.size();
-  axisNum_   = axisList.size();
-  numElement_ = axisDomainOrder.numElements(); // Number of element, e.x: Axis, Domain
-
-  axisDomainOrder_.resize(numElement_);
-  axisDomainOrder_ = axisDomainOrder;
-
-  // Because domain and axis can be in any order (axis1, domain1, axis2, axis3, )
-  // their position should be specified. In axisDomainOrder, domain == true, axis == false
-  int idx = 0;
-  indexMap_.resize(numElement_);
-  this->dims_ = numElement_;
-  for (int i = 0; i < numElement_; ++i)
-  {
-    indexMap_[i] = idx;
-    if (2 == axisDomainOrder(i))
-    {
-      ++(this->dims_);
-      idx += 2;
-    }
-    else ++idx;
-  }
-
-  // Size of each dimension (local and global)
-  nLocal_.resize(this->dims_);
-  nGlob_.resize(this->dims_);
-  nBeginLocal_.resize(this->dims_,0);
-  nBeginGlobal_.resize(this->dims_,0);
-
-  // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
-  dataNIndex_.resize(numElement_);
-  dataDims_.resize(numElement_);
-  dataBegin_.resize(this->dims_);
-
-  // Data_*_index of each dimension
-  dataIndex_.resize(this->dims_);
-  infoIndex_.resize(this->dims_);
-
-  // A trick to determine position of each domain in domainList
-  int domIndex = 0, axisIndex = 0, scalarIndex = 0;
-  idx = 0;
-
-  elementLocalIndex_.resize(numElement_);
-  elementGlobalIndex_.resize(numElement_);
-  elementIndexData_.resize(numElement_);
-  elementNLocal_.resize(numElement_);
-  elementNGlobal_.resize(numElement_);
-  elementNLocal_[0] = 1;
-  elementNGlobal_[0] = 1;
-  size_t localSize = 1, globalSize = 1;
-
-  isDataDistributed_ = false;
-  // Update all the vectors above
-  for (idx = 0; idx < numElement_; ++idx)
-  {
-    int eleDim = axisDomainOrder(idx);
-    elementNLocal_[idx] = localSize;
-    elementNGlobal_[idx] = globalSize;
-
-    // If this is a domain
-    if (2 == eleDim)
-    {
-      // On the j axis
-      nLocal_.at(indexMap_[idx]+1) = domList[domIndex]->nj.getValue();
-      nGlob_.at(indexMap_[idx]+1)  = domList[domIndex]->nj_glo.getValue();
-      nBeginLocal_.at(indexMap_[idx]+1) = 0;
-      nBeginGlobal_.at(indexMap_[idx]+1) = domList[domIndex]->jbegin;
-
-      dataBegin_.at(indexMap_[idx]+1) = domList[domIndex]->data_jbegin.getValue();
-      dataIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->data_j_index);
-      infoIndex_.at(indexMap_[idx]+1).reference(domList[domIndex]->j_index);
-
-      // On the i axis
-      nLocal_.at(indexMap_[idx]) = domList[domIndex]->ni.getValue();
-      nGlob_.at(indexMap_[idx]) = domList[domIndex]->ni_glo.getValue();
-      nBeginLocal_.at(indexMap_[idx]) = 0;
-      nBeginGlobal_.at(indexMap_[idx]) = domList[domIndex]->ibegin;
-
-      dataBegin_.at(indexMap_[idx]) = domList[domIndex]->data_ibegin.getValue();
-      dataIndex_.at(indexMap_[idx]).reference(domList[domIndex]->data_i_index);
-      infoIndex_.at(indexMap_[idx]).reference(domList[domIndex]->i_index);
-
-      dataNIndex_.at(idx) = domList[domIndex]->data_i_index.numElements();
-      dataDims_.at(idx) = domList[domIndex]->data_dim.getValue();
-
-      isDataDistributed_ |= domList[domIndex]->isDistributed();
-
-      localSize *= nLocal_.at(indexMap_[idx]+1)* nLocal_.at(indexMap_[idx]);
-      globalSize *= nGlob_.at(indexMap_[idx]+1)* nGlob_.at(indexMap_[idx]);
-      ++domIndex;
-    }
-    else if (1 == eleDim)// So it's an axis
-    {
-      nLocal_.at(indexMap_[idx]) = axisList[axisIndex]->n.getValue();
-      nGlob_.at(indexMap_[idx]) = axisList[axisIndex]->n_glo.getValue();
-      nBeginLocal_.at(indexMap_[idx]) = 0;
-      nBeginGlobal_.at(indexMap_[idx]) = axisList[axisIndex]->begin.getValue();
-
-      dataBegin_.at(indexMap_[idx]) = axisList[axisIndex]->data_begin.getValue();
-      dataIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->data_index);
-      infoIndex_.at(indexMap_[idx]).reference(axisList[axisIndex]->index);
-      dataNIndex_.at(idx) = axisList[axisIndex]->data_index.numElements();
-      dataDims_.at(idx) = 1;
-
-      isDataDistributed_ |= axisList[axisIndex]->isDistributed();
-
-      localSize *= nLocal_.at(indexMap_[idx]);
-      globalSize *= nGlob_.at(indexMap_[idx]);
-
-      ++axisIndex;
-    }
-    else // scalar
-    {
-      nLocal_.at(indexMap_[idx]) = 1;
-      nGlob_.at(indexMap_[idx]) = 1;
-      nBeginLocal_.at(indexMap_[idx]) = 0;
-      nBeginGlobal_.at(indexMap_[idx]) = 1;
-
-      dataBegin_.at(indexMap_[idx]) = 0;
-      dataIndex_.at(indexMap_[idx]).resize(1); dataIndex_.at(indexMap_[idx])(0) = 0;
-      infoIndex_.at(indexMap_[idx]).resize(1); infoIndex_.at(indexMap_[idx])(0) = 0;
-      dataNIndex_.at(idx) = 1;
-      dataDims_.at(idx) = 1;
-
-      isDataDistributed_ |= false;
-
-      localSize *= nLocal_.at(indexMap_[idx]);
-      globalSize *= nGlob_.at(indexMap_[idx]);
-
-      ++scalarIndex;
-    }
-  }
-}
-
-/*!
-  Create local index of domain(s).
-  A domain can have data index which even contains the "ghost" points. Very often, these
-data surround the true data. In order to send correct data to server,
-a client need to know index of the true data.
-*/
-void CDistributionClient::createLocalDomainDataIndex()
-{
-  int idxDomain = 0;
-  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
-  {
-    if (2 == axisDomainOrder_(i))
-    {
-      elementIndexData_[i].resize(dataNIndex_[i]);
-      elementIndexData_[i] = false;
-      int iIdx, jIdx = 0, count = 0, localIndex;
-      for (int j = 0; j < dataNIndex_[i]; ++j)
-      {
-        iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
-                              dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
-                              dataDims_[i], nLocal_[indexMap_[i]], jIdx);
-
-        if ((iIdx >= nBeginLocal_[indexMap_[i]]) && (iIdx < nLocal_[indexMap_[i]]) &&
-           (jIdx >= nBeginLocal_[indexMap_[i]+1]) && (jIdx < nLocal_[indexMap_[i]+1]))
-        {
-          ++count;
-          elementIndexData_[i](j) = true;
-        }
-      }
-
-      elementLocalIndex_[i].resize(count);
-      elementGlobalIndex_[i].resize(count);
-      count = 0;
-      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
-      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
-      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
-      for (int j = 0; j < dataNIndex_[i]; ++j)
-      {
-        if (tmpIndexElementData(j))
-        {
-          iIdx = getDomainIndex((dataIndex_[indexMap_[i]])(j), (dataIndex_[indexMap_[i]+1])(j),
-                                dataBegin_[indexMap_[i]], dataBegin_[indexMap_[i]+1],
-                                dataDims_[i], nLocal_[indexMap_[i]], jIdx);
-          localIndex = tmpLocalElementIndex(count) = iIdx + jIdx * nLocal_[indexMap_[i]];
-          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(localIndex) + ((infoIndex_[indexMap_[i]+1])(localIndex))*nGlob_[indexMap_[i]];
-          ++count;
-        }
-      }
-      ++idxDomain;
-    }
-  }
-}
-
-/*!
-  Create local index of axis.
-*/
-void CDistributionClient::createLocalAxisDataIndex()
-{
-  int idxAxis = 0;
-  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
-  {
-    if (1 == axisDomainOrder_(i))
-    {
-      elementIndexData_[i].resize(dataNIndex_[i]);
-      elementIndexData_[i] = false;
-      int iIdx = 0, count = 0;
-      for (int j = 0; j < dataNIndex_[i]; ++j)
-      {
-        iIdx = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
-        if ((iIdx >= nBeginLocal_[indexMap_[i]]) &&
-           (iIdx < nLocal_[indexMap_[i]]) )//&& (axisMasks_[idxAxis](iIdx)))
-        {
-          ++count;
-          elementIndexData_[i](j) = true;
-        }
-      }
-
-      elementLocalIndex_[i].resize(count);
-      elementGlobalIndex_[i].resize(count);
-      count = 0;
-      CArray<bool,1>& tmpIndexElementData = elementIndexData_[i];
-      CArray<int,1>& tmpLocalElementIndex = elementLocalIndex_[i];
-      CArray<size_t,1>& tmpGlobalElementIndex = elementGlobalIndex_[i];
-      for (int j = 0; j < dataNIndex_[i]; ++j)
-      {
-        if (tmpIndexElementData(j))
-        {
-          iIdx = tmpLocalElementIndex(count) = getAxisIndex((dataIndex_[indexMap_[i]])(j), dataBegin_[indexMap_[i]], nLocal_[indexMap_[i]]);
-          tmpGlobalElementIndex(count) = (infoIndex_[indexMap_[i]])(iIdx);
-          ++count;
-        }
-      }
-      ++idxAxis;
-    }
-  }
-}
-
-/*!
-  Create local index of scalar.
-*/
-void CDistributionClient::createLocalScalarDataIndex()
-{
-  int idxAxis = 0;
-  for (int i = 0; i < axisDomainOrder_.numElements(); ++i)
-  {
-    if (0 == axisDomainOrder_(i))
-    {
-      elementIndexData_[i].resize(dataNIndex_[i]);
-      elementIndexData_[i] = true;
-      int count = 1;
-
-      elementLocalIndex_[i].resize(count);
-      elementLocalIndex_[i] = 0;
-      elementGlobalIndex_[i].resize(count);
-      elementGlobalIndex_[i] = 0;
-    }
-  }
-}
-
-/*!
-   Create global index on client
-   In order to do the mapping between client-server, each client creates its own
-global index of sending data. This global index is then used to calculate to which server
-the client needs to send it data as well as which part of data belongs to the server.
-So as to make clients and server coherent in order of index, global index is calculated by
-take into account of C-convention, the rightmost dimension varies faster.
-*/
-void CDistributionClient::createGlobalIndexSendToServer()
-{
-  if (isComputed_) return;
-  isComputed_ = true;
-  createLocalDomainDataIndex();
-  createLocalAxisDataIndex();
-  createLocalScalarDataIndex();
-
-  int idxDomain = 0, idxAxis = 0;
-  std::vector<int> eachElementSize(numElement_);
-
-  // Precompute size of the loop
-  for (int i = 0; i < numElement_; ++i)
-  {
-    eachElementSize[i] = elementLocalIndex_[i].numElements();
-  }
-
-  //   Compute size of the global index on client
-  std::vector<StdSize> idxLoop(numElement_,0);
-  std::vector<StdSize> currentIndex(numElement_,0);
-  std::vector<StdSize> currentGlobalIndex(numElement_,0);
-  int innerLoopSize = eachElementSize[0];
-  size_t idx = 0, indexLocalDataOnClientCount = 0;
-  size_t ssize = 1;
-
-  for (int i = 0; i < numElement_; ++i) ssize *= eachElementSize[i];
-  localDataSize_=ssize ;
-
-  localDataIndex_.resize(ssize);
-  if (!gridMask_.isEmpty()) localMaskIndex_.resize(ssize);
-  localMaskedDataIndex_.resize(ssize);
-  globalDataIndex_.rehash(std::ceil(ssize/globalDataIndex_.max_load_factor()));
-  globalLocalDataSendToServerMap_.rehash(std::ceil(ssize/globalLocalDataSendToServerMap_.max_load_factor()));
-
-
-  // We need to loop with data index
-  idxLoop.assign(numElement_,0);
-  idx = indexLocalDataOnClientCount = 0;
-  ssize = 1; for (int i = 0; i < numElement_; ++i) ssize *= dataNIndex_[i];
-  innerLoopSize = dataNIndex_[0];
-  int countLocalData = 0;
-  std::vector<int> correctIndexOfElement(numElement_,0);
-  bool isOuterIndexCorrect = true;
-  while (idx < ssize)
-  {
-    for (int i = 0; i < numElement_-1; ++i)
-    {
-      if (idxLoop[i] == dataNIndex_[i])
-      {
-        idxLoop[i] = 0;
-        correctIndexOfElement[i] = 0;
-        ++idxLoop[i+1];
-        if (isOuterIndexCorrect) ++correctIndexOfElement[i+1];
-      }
-    }
-
-    // Depending the inner-most element axis or domain,
-    // The outer loop index begins correspondingly at one (1) or zero (0)
-    bool isIndexElementDataCorrect = true;
-    for (int i = 1; i < numElement_; ++i)
-    {
-      if (elementIndexData_[i](idxLoop[i]))
-      {
-        currentIndex[i] = elementLocalIndex_[i](correctIndexOfElement[i]);
-        currentGlobalIndex[i] = elementGlobalIndex_[i](correctIndexOfElement[i]);
-        isIndexElementDataCorrect &= true;
-      }
-      else isIndexElementDataCorrect = false;
-    }
-
-    isOuterIndexCorrect = isIndexElementDataCorrect;
-
-    if (isOuterIndexCorrect)
-    {
-      // Inner most index
-      int correctIndexInnerElement = 0;
-      for (int i = 0; i < innerLoopSize; ++i)
-      {
-        bool isCurrentIndexDataCorrect = isOuterIndexCorrect;
-        if (elementIndexData_[0](i))
-        {
-          currentIndex[0] = elementLocalIndex_[0](correctIndexInnerElement);
-          currentGlobalIndex[0] = elementGlobalIndex_[0](correctIndexInnerElement);
-          isCurrentIndexDataCorrect &= true;
-          ++correctIndexInnerElement;
-        }
-        else isCurrentIndexDataCorrect = false;
-
-        if (isCurrentIndexDataCorrect)
-        {
-          bool maskTmp = true;
-          bool maskGridTmp = true;
-          size_t globalIndex = 0;
-          for (int k = 0; k < numElement_; ++k)
-          {
-            globalIndex += (currentGlobalIndex[k])*elementNGlobal_[k];
-          }
-          globalDataIndex_[globalIndex] = indexLocalDataOnClientCount;
-          localDataIndex_[indexLocalDataOnClientCount] = countLocalData;
-          globalLocalDataSendToServerMap_[globalIndex] = indexLocalDataOnClientCount;
-          localMaskedDataIndex_[indexLocalDataOnClientCount] = indexLocalDataOnClientCount;
-
-          // Grid mask: unmasked values will be replaces by NaN and then all values will be sent
-          if (!gridMask_.isEmpty())
-          {
-            int gridMaskIndex = 0;
-            for (int k = 0; k < this->numElement_; ++k)
-            {
-              gridMaskIndex += (currentIndex[k])*elementNLocal_[k];
-            }
-            maskGridTmp =  gridMask_(gridMaskIndex);
-            if (maskGridTmp)
-              localMaskIndex_[indexLocalDataOnClientCount] = true;
-            else
-              localMaskIndex_[indexLocalDataOnClientCount] = false;
-          }
-
-          ++indexLocalDataOnClientCount;
-
-        }
-        ++countLocalData;
-        correctIndexOfElement[0] = correctIndexInnerElement;;
-      }
-    }
-    else countLocalData+=innerLoopSize ;
-
-    idxLoop[0] += innerLoopSize;
-    idx += innerLoopSize;
-  }
-}
-
-void CDistributionClient::createGlobalIndex()
-{
-}
-
-/*!
-  Retrieve index i and index j of a domain from its data index
-  Data contains not only true data, which are sent to servers, but also ghost data, which
-very often play a role of border of each local data, so does data index. Because data of a domain
-can be one dimension, or two dimensions, there is a need to convert data index to domain index
-  \param [in] dataIIndex index of i data
-  \param [in] dataJIndex index of j data
-  \param [in] dataIBegin index begin of i data
-  \param [in] dataJBegin index begin of j data
-  \param [in] dataDim dimension of data (1 or 2)
-  \param [in] ni local size ni of domain
-  \param [out] j j index of domain
-  \return i index of domain
-*/
-int CDistributionClient::getDomainIndex(const int& dataIIndex, const int& dataJIndex,
-                                        const int& dataIBegin, const int& dataJBegin,
-                                        const int& dataDim, const int& ni, int& j)
-{
-  int i;
-  int tempI = dataIIndex + dataIBegin,
-      tempJ = (dataJIndex + dataJBegin);
-  if (ni == 0)
-  {
-    i = -1;
-    j = -1;
-    return i;
-  }
-  if ((tempI < 0) || (tempJ < 0))
-  {
-    i = -1;
-    j = -1;
-    return i;
-  }
-  else
-  {
-    i = (dataDim == 1) ? (tempI) % ni : (tempI) ;
-    j = (dataDim == 1) ? (tempI) / ni : (tempJ) ;
-  }
-  return i;
-}
-
-/*!
-  Retrieve index of an axis from its data index
-  \param [in] dataIndex index of data
-  \param [in] dataBegin index begin of data
-  \param [in] ni local size of axis
-  \return index of domain
-*/
-int CDistributionClient::getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni)
-{
-  if (ni == 0)
-  {
-    return -1;
-  }
-  int tempI = dataIndex;
-  if ((tempI < 0) || (tempI > ni))
-    return -1;
-  else
-    return tempI;
-}
-
-/*!
-  Return global local data mapping of client
-*/
-CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalLocalDataSendToServer()
-{
-  if (!isComputed_) createGlobalIndexSendToServer();
-  return globalLocalDataSendToServerMap_;
-}
-
-CDistributionClient::GlobalLocalDataMap& CDistributionClient::getGlobalDataIndexOnClient()
-{
-  if (!isComputed_) createGlobalIndexSendToServer();
-  return globalDataIndex_;
-}
-
-/*!
-  Return local data index of client
-*/
-const std::vector<int>& CDistributionClient::getLocalDataIndexOnClient()
-{
-  if (!isComputed_) createGlobalIndexSendToServer();
-  return localDataIndex_;
-}
-
-/*!
-  Return local mask index of client
-*/
-const std::vector<bool>& CDistributionClient::getLocalMaskIndexOnClient()
-{
-  if (!isComputed_) createGlobalIndexSendToServer();
-  return localMaskIndex_;
-}
-
-/*!
-  Return local mask index of client
-*/
-const std::vector<int>& CDistributionClient::getLocalMaskedDataIndexOnClient()
-{
-  if (!isComputed_) createGlobalIndexSendToServer();
-  return localMaskedDataIndex_;
-}
-
-} // namespace xios
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_client.hpp	(revision 1917)
+++ 	(revision )
@@ -1,186 +1,0 @@
-/*!
-   \file distribution_client.hpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 09 Mars 2015
-
-   \brief Index distribution on client side.
- */
-#ifndef __XIOS_DISTRIBUTIONCLIENT_HPP__
-#define __XIOS_DISTRIBUTIONCLIENT_HPP__
-
-#include <distribution.hpp>
-#include "axis.hpp"
-#include "domain.hpp"
-#include "grid.hpp"
-
-namespace xios {
-
-class CGrid;
-class CDomain;
-class CAxis;
-class CScalar;
-
-/*!
-  \class CDistributionClient
-  This class bases on the knowledge of distribution on client side (decided by users)
-to calculate the global index of its local data.
-*/
-class CDistributionClient : public CDistribution
-{
-public:
-  typedef CDistribution::GlobalLocalMap GlobalLocalDataMap;
-
-  public:
-    /** Default constructor */
-    CDistributionClient(int rank, CGrid* grid);
-
-    void createGlobalIndexSendToServer();
-
-    /** Default destructor */
-    virtual ~CDistributionClient();
-
-    virtual const std::vector<int>& getLocalDataIndexOnClient();
-    GlobalLocalDataMap& getGlobalLocalDataSendToServer();
-    GlobalLocalDataMap& getGlobalDataIndexOnClient();
-    const std::vector<bool>& getLocalMaskIndexOnClient();
-    const std::vector<int>& getLocalMaskedDataIndexOnClient();
-
-    size_t getLocalDataSize(void) { if (!isComputed_) createGlobalIndexSendToServer(); return localDataSize_ ;}
-    std::vector<int> getNGlob() { return nGlob_; }
-    std::vector<int> getDataNIndex() { return dataNIndex_; }
-
-    bool isDataDistributed() { return isDataDistributed_; }
-
-    static int getDomainIndex(const int& dataIIndex, const int& dataJIndex,
-                                     const int& dataIBegin, const int& dataJBegin,
-                                     const int& dataDim, const int& ni, int& j);
-    static int getAxisIndex(const int& dataIndex, const int& dataBegin, const int& ni);
-
-    void partialClear(void) ;  //! clear heavy sized attibutes
-
-  protected:
-    void createGlobalIndex();
-    void readDistributionInfo(CGrid* grid);
-    void readDistributionInfo(const std::vector<CDomain*>& domList,
-                              const std::vector<CAxis*>& axisList,
-                              const std::vector<CScalar*>& scalarList,
-                              const CArray<int,1>& axisDomainOrder);
-  private:
-    //! Create local index of a domain
-    void createLocalDomainDataIndex();
-
-    //! Create local index of an axis
-    void createLocalAxisDataIndex();
-
-    //! Create local index of a scalar
-    void createLocalScalarDataIndex();
-
-    template<int N>
-    void readGridMaskInfo(const CArray<bool,N>& gridMask);
-
-  private:
-    //!< LocalData index on client
-    GlobalLocalDataMap globalLocalDataSendToServerMap_;
-    GlobalLocalDataMap globalDataIndex_;
-
-    /*! Array holding masked data indexes.
-     * It includes:
-     *  masking on data (data_i/j_index or data_ni/nj and data_ibegin)
-     *  masking on grid elements (domains, axes or scalars)
-     * It DOES NOT include grid mask.
-     * The array size defines the data size entering the workflow. It is used by source filter of client or server1.
-    */
-    std::vector<int> localDataIndex_;
-
-    /*! Array holding grid mask. If grid mask is not defined, its size is zero.
-     * It is used by source filter of client for replacing unmasked data by NaN.
-    */
-    std::vector<bool> localMaskIndex_;
-
-    std::vector<int> localMaskedDataIndex_;
-    //!< the size of local data of the grid
-    size_t localDataSize_ ;
-
-  private:
-    /*! Domains and axis are considered elements.
-     * A grid composed of 1 domain and 1 axis has 2 elements */
-    int numElement_;
-    CArray<int,1> axisDomainOrder_; //!< Order of axis and domain of a grid
-
-    std::vector<int> nLocal_; //!< Local size of each dimension (ni, nj, etc, ...)
-    std::vector<int> nGlob_; //!< Global size of each dimension (e.x: ni_glo, nj_glo, etc, ...)
-    std::vector<int> nBeginLocal_;//!< Begin index of each dimension (e.x: for domain, it's always 0, for axis, it's zoom_begin, ...)
-    std::vector<int> nBeginGlobal_; //!< Begin index of each dimension (e.x: ibegin, jbegin, ...)
-
-    // Data_n_index of domain or axis (For now, axis uses its size as data_n_index
-    std::vector<int> dataNIndex_; //!< Data_n_index in case of domain
-    std::vector<int> dataDims_; //!< Data_dim, domain can have data_dim == 1 or 2
-    std::vector<int> dataBegin_; //!< Data begin (data_ibegin, data_jbegin, etc)
-    std::vector<CArray<int,1> > dataIndex_; //!< Data index
-    std::vector<CArray<int,1> > infoIndex_; //!< i_index, j_index
-
-    std::vector<int> indexMap_; //!< Mapping element index to dimension index
-    std::vector<CArray<int,1> > elementLocalIndex_;  //!< Local index of each element
-    std::vector<CArray<size_t,1> > elementGlobalIndex_; //!< Global index of each element
-    std::vector<CArray<bool,1> > elementIndexData_; //!< // The correct index of a domain has true value, the ghost one has false value
-    std::vector<size_t> elementNLocal_;
-    std::vector<size_t> elementNGlobal_;
-
-    //!< (Only for grid with one axis or scalar)Flag to determine whether data is distributed or not
-    bool isDataDistributed_;
-    int axisNum_;
-    int domainNum_;
-    bool isComputed_;
-
-  private:
-    // Just suppose that grid mask has 3 dimension. Need change
-    CArray<bool,1> gridMask_; //!< Mask of grid
-
-  private:
-    CDistributionClient(const CDistributionClient& distClient); //! Not implement
-};
-
-/*!
-  A grid can have multiple dimension, so can its mask in the form of multi-dimension array.
-It's not a good idea to store all multi-dimension arrays corresponding to each mask.
-One of the ways is to convert this array into 1-dimension one and every process is taken place on it.
-  \param [in] multi-dimension array grid mask
-*/
-template<int N>
-void CDistributionClient::readGridMaskInfo(const CArray<bool,N>& gridMask)
-{
-  int dim = gridMask.dimensions();
-  std::vector<int> dimensionSizes(dim);
-  for (int i = 0; i < dim; ++i) dimensionSizes[i] = gridMask.extent(i);
-
-  std::vector<int> idxLoop(dim,0);
-  int ssize = gridMask.numElements(), idx = 0;
-  gridMask_.resize(ssize);
-  while (idx < ssize)
-  {
-    for (int i = 0; i < dim-1; ++i)
-    {
-      if (idxLoop[i] == dimensionSizes[i])
-      {
-        idxLoop[i] = 0;
-        ++idxLoop[i+1];
-      }
-    }
-
-    int maskIndex = idxLoop[0];
-    int mulDim = 1;
-    for (int k = 1; k < dim; ++k)
-    {
-      mulDim *= dimensionSizes[k-1];
-      maskIndex += idxLoop[k]*mulDim;
-    }
-    gridMask_(maskIndex) = *(gridMask.dataFirst()+maskIndex);
-
-    ++idxLoop[0];
-    ++idx;
-  }
-}
-
-} // namespace xios
-#endif // __XIOS_DISTRIBUTIONCLIENT_HPP__
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution_server.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_server.cpp	(revision 1917)
+++ 	(revision )
@@ -1,223 +1,0 @@
-/*!
-   \file distribution_server.cpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 10 Sep 2016
-
-   \brief Index distribution on server side.
- */
-#include "distribution_server.hpp"
-#include "utils.hpp"
-
-namespace xios {
-
-CDistributionServer::CDistributionServer(int rank, const std::vector<int>& nBegin,
-                                         const std::vector<int>& nSize,
-                                         const std::vector<int>& nBeginGlobal,
-                                         const std::vector<int>& nGlobal)
-  : CDistribution(rank, nGlobal.size()), nGlobal_(nGlobal), nBeginGlobal_(nBeginGlobal),
-    nSize_(nSize), nBegin_(nBegin), globalLocalIndexMap_()
-{
-  createGlobalIndex();
-}
-
-CDistributionServer::CDistributionServer(int rank,
-                                        const std::vector<CArray<int,1> >& globalIndexElements,
-                                        const CArray<int,1>& elementOrder,
-                                        const std::vector<int>& nBegin,
-                                        const std::vector<int>& nSize,
-                                        const std::vector<int>& nBeginGlobal,
-                                        const std::vector<int>& nGlobal)
-  : CDistribution(rank, nGlobal.size()), nGlobal_(nGlobal), nBeginGlobal_(nBeginGlobal),
-    nSize_(nSize), nBegin_(nBegin), globalLocalIndexMap_()
-{
-  createGlobalIndex(globalIndexElements, elementOrder);
-}
-
-CDistributionServer::~CDistributionServer()
-{
-}
-
-/*!
-  Create global index on server side
-  Like the similar function on client side, this function serves on creating global index
-for data written by the server. The global index is used to calculating local index of data
-written on each server
-*/
-void CDistributionServer::createGlobalIndex()
-{
-  size_t idx = 0, ssize = 1;
-  for (int i = 0; i < nSize_.size(); ++i) ssize *= nSize_[i];
-
-  this->globalIndex_.resize(ssize);
-  std::vector<int> idxLoop(this->getDims(),0);
-  std::vector<int> currentIndex(this->getDims());
-  int innerLoopSize = nSize_[0];
-
-  globalLocalIndexMap_.rehash(std::ceil(ssize/globalLocalIndexMap_.max_load_factor()));
-  while (idx<ssize)
-  {
-    for (int i = 0; i < this->dims_-1; ++i)
-    {
-      if (idxLoop[i] == nSize_[i])
-      {
-        idxLoop[i] = 0;
-        ++idxLoop[i+1];
-      }
-    }
-
-    for (int i = 1; i < this->dims_; ++i)  currentIndex[i] = idxLoop[i] + nBegin_[i];
-
-    size_t mulDim, globalIndex;
-    for (int i = 0; i < innerLoopSize; ++i)
-    {
-      mulDim = 1;
-      globalIndex = i + nBegin_[0];
-
-      for (int k = 1; k < this->dims_; ++k)
-      {
-        mulDim *= nGlobal_[k-1];
-        globalIndex += (currentIndex[k])*mulDim;
-      }
-      globalLocalIndexMap_[globalIndex] = idx;
-      this->globalIndex_(idx) = globalIndex;
-
-      ++idx;
-    }
-    idxLoop[0] += innerLoopSize;
-  }
-}
-
-/*!
-  Create global index on server side
-  Like the similar function on client side, this function serves on creating global index
-for data written by the server. The global index is used to calculating local index of data
-written on each server
-  \param[in] globalIndexElement global index on server side of each element of grid (scalar, axis, domain)
-  \param[in] elementOrder the order of elements of grid (e.x: domain->axis or domain->scalar)
-*/
-void CDistributionServer::createGlobalIndex(const std::vector<CArray<int,1> >& globalIndexElements,
-                                            const CArray<int,1>& elementOrder)
-{
-  int numElement = elementOrder.numElements(), elementIdx = 0;  
-  std::vector<int> indexMap(numElement);
-  for (int i = 0; i < numElement; ++i)
-  {
-    indexMap[i] = elementIdx;
-    if (2 == elementOrder(i))
-    {      
-      elementIdx += 2;
-    }
-    else
-      ++elementIdx;
-  }
-
-  std::vector<size_t> elementGlobalSize(numElement);
-  size_t globalSize = 1;
-  for (int i = 0; i < numElement; ++i)
-  {
-    int elementType = elementOrder(i);
-    elementGlobalSize[i] = globalSize;
-    if (2 == elementType) // domain
-    {
-      globalSize *= nGlobal_[indexMap[i]+1] * nGlobal_[indexMap[i]];
-    }
-    else // axis or scalar
-    {
-      globalSize *= nGlobal_[indexMap[i]];
-    }
-  } 
-
-  size_t ssize = 1;
-  for (int i = 0; i < globalIndexElements.size(); ++i) ssize *= globalIndexElements[i].numElements();
-  this->globalIndex_.resize(ssize);
-  globalLocalIndexMap_.rehash(std::ceil(ssize/globalLocalIndexMap_.max_load_factor()));
-
-  std::vector<int> idxLoop(numElement,0);
-  std::vector<int> currentIndex(numElement);
-  int innerLoopSize = globalIndexElements[0].numElements();
-
-  size_t idx = 0;
-  while (idx<ssize)
-  {
-    for (int i = 0; i < numElement-1; ++i)
-    {
-      if (idxLoop[i] == globalIndexElements[i].numElements())
-      {
-        idxLoop[i] = 0;
-        ++idxLoop[i+1];
-      }
-    }
-
-    for (int i = 1; i < numElement; ++i)  currentIndex[i] = globalIndexElements[i](idxLoop[i]);
-
-    size_t mulDim, globalIndex;
-    for (int i = 0; i < innerLoopSize; ++i)
-    {      
-      globalIndex = 0;
-      currentIndex[0] = globalIndexElements[0](i);
-
-      for (int k = 0; k < numElement; ++k)
-      {     
-        globalIndex += (currentIndex[k])*elementGlobalSize[k];
-      }
-      globalLocalIndexMap_[globalIndex] = idx;
-      this->globalIndex_(idx) = globalIndex;
-      ++idx;
-    }
-    idxLoop[0] += innerLoopSize;
-  }
-}
-
-/*!
-  Compute local index for writing data on server
-  \param [in] globalIndex Global index received from client
-*/
-void CDistributionServer::computeLocalIndex(CArray<size_t,1>& globalIndex)
-{
-  size_t ssize = globalIndex.numElements();
-  size_t localIndexSize = std::min(globalIndex_.numElements(), ssize);
-  CArray<size_t,1> localIndex(localIndexSize);
-  GlobalLocalMap::const_iterator ite = globalLocalIndexMap_.end(), it;
-  int i = 0;
-  for (size_t idx = 0; idx < ssize; ++idx)
-  {
-    it = globalLocalIndexMap_.find(globalIndex(idx));
-    if (ite != it)
-    {
-      localIndex(i) = it->second;
-      ++i;
-    }
-  }
-
-  globalIndex.reference(localIndex);
-}
-
-/*!
-  Transforms local indexes owned by the server into global indexes
-  \param [in/out] indexes on input, local indexes of the server,
-                          on output, the corresponding global indexes
-*/
-void CDistributionServer::computeGlobalIndex(CArray<int,1>& indexes) const
-{
-  for (int i = 0; i < indexes.numElements(); ++i)
-  {
-    indexes(i) = globalIndex_(indexes(i));
-  }
-}
-
-/*!
-  Get the size of grid index in server (e.x: sizeGrid *= size of each dimensiion)
-*/
-int CDistributionServer::getGridSize() const
-{
-   return globalLocalIndexMap_.size();
-}
-
-void CDistributionServer::partialClear(void)
-{
-  GlobalLocalMap void1 ;
-  globalLocalIndexMap_.swap(void1) ;
-}
-  
-} // namespace xios
Index: OS/dev/dev_ym/XIOS_COUPLING/src/distribution_server.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/distribution_server.hpp	(revision 1917)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*!
-   \file distribution_server.hpp
-   \author Ha NGUYEN
-   \since 13 Jan 2015
-   \date 04 Feb 2015
-
-   \brief Index distribution on server side.
- */
-
-#ifndef __XIOS_DISTRIBUTION_SERVER_HPP__
-#define __XIOS_DISTRIBUTION_SERVER_HPP__
-
-#include "distribution.hpp"
-
-namespace xios {
-
-/*!
-  \class CDistributionServer
-  The class, for now, plays a role of computing local index for writing data on server
-*/
-class CDistributionServer : public CDistribution
-{
-  public:
-    /** Default constructor */
-    CDistributionServer(int rank, int dims, const CArray<size_t,1>& globalIndex = CArray<size_t,1>());
-    CDistributionServer(int rank, const std::vector<int>& nBeginServer,
-                        const std::vector<int>& nSizeServer, const std::vector<int>& nGlobal);
-    CDistributionServer(int rank, const std::vector<int>& nBeginServer,
-                        const std::vector<int>& nSizeServer,
-                        const std::vector<int>& nBeginGlobal,
-                        const std::vector<int>& nGlobal);
-
-    CDistributionServer(int rank,
-                        const std::vector<CArray<int,1> >& globalIndexElements,
-                        const CArray<int,1>& elementOrder,
-                        const std::vector<int>& nBeginServer,
-                        const std::vector<int>& nSizeServer,
-                        const std::vector<int>& nBeginGlobal,
-                        const std::vector<int>& nGlobal);
-
-    /** Default destructor */
-    virtual ~CDistributionServer();
-
-    const GlobalLocalMap& getGlobalLocalIndex() const { return globalLocalIndexMap_; }    
-    int getGridSize() const;
-    
-    virtual void computeLocalIndex(CArray<size_t,1>& globalIndex);
-    virtual void computeGlobalIndex(CArray<int,1>& indexes) const;
-    virtual void partialClear(void); //! clear heavy sized attibutes
-
-  protected:
-    virtual void createGlobalIndex();
-    void createGlobalIndex(const std::vector<CArray<int,1> >& globalIndexElements,
-                           const CArray<int,1>& elementOrder);
-    
-  protected:
-    GlobalLocalMap globalLocalIndexMap_;
-
-  private:
-    std::vector<int> nGlobal_;
-    std::vector<int> nBeginGlobal_;
-    std::vector<int> nSize_;
-    std::vector<int> nBegin_;
-
-};
-
-} // namespace xios
-#endif // __XIOS_DISTRIBUTION_SERVER_HPP__
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/source_filter.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/source_filter.cpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/filter/source_filter.cpp	(revision 1918)
@@ -43,8 +43,6 @@
     else
     {
-      if (mask)
-        grid->maskField(data, packet->data);
-      else
-        grid->inputField(data, packet->data);
+      if (mask) grid->maskField(data, packet->data);
+      else grid->inputField(data, packet->data);
     }
     // Convert missing values to NaN
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 1918)
@@ -333,8 +333,64 @@
       this->checkData();
       this->checkLabel();
+      initializeLocalElement() ;
+      addFullView() ;
+      addWorkflowView() ;
+      addModelView() ;
+
+      checkAttributes_done_ = true ;
+   }
+   CATCH_DUMP_ATTR
+
+
+
+   void CAxis::initializeLocalElement(void)
+   {
+      // after checkAttribute index of size n
+      int rank = CContext::getCurrent()->getIntraCommRank() ;
       
-      checkAttributes_done_ = true ;
-   }
-   CATCH_DUMP_ATTR
+      CArray<size_t,1> ind(n) ;
+      for (int i=0;i<n;i++) ind(i)=index(i) ;
+
+      localElement_ = new CLocalElement(rank, n_glo, ind) ;
+   }
+
+   void CAxis::addFullView(void)
+   {
+      CArray<int,1> index(n) ;
+      for(int i=0; i<n ; i++) index(i)=i ;
+      localElement_ -> addView(CElementView::FULL, index) ;
+   }
+
+   void CAxis::addWorkflowView(void)
+   {
+     // mask + data are included into data_index
+     int nk=data_index.numElements() ;
+     int nMask=0 ;
+     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
+     
+     CArray<int,1> index(nMask) ;
+     nMask=0 ;
+     for(int k=0;k<nk;k++) 
+       if (data_index(k)>=0 && data_index(k)<n) 
+       {
+         index(nMask) = data_index(k) ;
+         nMask++ ;
+       }
+     localElement_ -> addView(CElementView::WORKFLOW, index) ;
+   }
+
+   void CAxis::addModelView(void)
+   {
+     // information for model view is stored in data_index
+     localElement_->addView(CElementView::MODEL, data_index) ;
+   }
+
+   void CAxis::computeModelToWorkflowConnector(void)
+   { 
+     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
+     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
+     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
+     modelToWorkflowConnector_->computeConnector() ;
+   }
 
    /*!
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp	(revision 1918)
@@ -16,4 +16,6 @@
 #include "transformation.hpp"
 #include "transformation_enum.hpp"
+#include "element.hpp"
+#include "local_connector.hpp"
 
 namespace xios {
@@ -222,4 +224,24 @@
          static bool dummyTransformationMapList_;
 
+
+         
+        private:
+         CLocalElement* localElement_ = nullptr ;
+         void initializeLocalElement(void) ;
+        public: 
+         CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; }
+         CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;}
+        private:
+         void addFullView(void) ;
+         void addWorkflowView(void) ;
+         void addModelView(void) ;
+
+        private:
+         CLocalConnector* modelToWorkflowConnector_ ;
+         void computeModelToWorkflowConnector(void)  ;
+        public:
+         CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;}
+
+
          DECLARE_REF_FUNC(Axis,axis)
    }; // class CAxis
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 1918)
@@ -18,4 +18,14 @@
 #include "server_distribution_description.hpp"
 #include "client_server_mapping_distributed.hpp"
+#include "local_connector.hpp"
+#include "grid_local_connector.hpp"
+#include "remote_connector.hpp"
+#include "gatherer_connector.hpp"
+#include "scatterer_connector.hpp"
+#include "grid_scatterer_connector.hpp"
+#include "grid_gatherer_connector.hpp"
+
+
+
 
 #include <algorithm>
@@ -1734,7 +1744,96 @@
       this->computeLocalMask() ;
       this->completeLonLatClient();
+      this->initializeLocalElement() ;
+      this->addFullView() ;
+      this->addWorkflowView() ;
+      this->addModelView() ;
+      // testing ?
+      CLocalView* local = localElement_->getView(CElementView::WORKFLOW) ;
+      CLocalView* model = localElement_->getView(CElementView::MODEL) ;
+
+      CLocalConnector test1(model, local) ;
+      test1.computeConnector() ;
+      CLocalConnector test2(local, model) ;
+      test2.computeConnector() ;
+      CGridLocalConnector gridTest1(vector<CLocalConnector*>{&test1}) ;
+      CGridLocalConnector gridTest2(vector<CLocalConnector*>{&test2}) ;
+      
+      
+      CArray<int,1> out1 ;
+      CArray<int,1> out2 ;
+      test1.transfer(data_i_index,out1,-111) ;
+      test2.transfer(out1,out2,-111) ;
+      
+      out1 = 0 ;
+      out2 = 0 ;
+      gridTest1.transfer(data_i_index,out1,-111) ;
+      gridTest2.transfer(out1, out2,-111) ;
+      
       this->checkAttributes_done_ = true;
    }
    CATCH_DUMP_ATTR
+
+
+   void CDomain::initializeLocalElement(void)
+   {
+      // after checkDomain i_index and j_index of size (ni*nj) 
+      int nij = ni*nj ;
+      CArray<size_t, 1> ij_index(ni*nj) ;
+      for(int ij=0; ij<nij ; ij++) ij_index(ij) = i_index(ij)+j_index(ij)*ni_glo ;
+      int rank = CContext::getCurrent()->getIntraCommRank() ;
+      localElement_ = new CLocalElement(rank, ni_glo*nj_glo, ij_index) ;
+   }
+
+   void CDomain::addFullView(void)
+   {
+      CArray<int,1> index(ni*nj) ;
+      int nij=ni*nj ;
+      for(int ij=0; ij<nij ; ij++) index(ij)=ij ;
+      localElement_ -> addView(CElementView::FULL, index) ;
+   }
+
+   void CDomain::addWorkflowView(void)
+   {
+     // information for workflow view is stored in localMask
+     int nij=ni*nj ;
+     int nMask=0 ;
+     for(int ij=0; ij<nij ; ij++) if (localMask(ij)) nMask++ ;
+     CArray<int,1> index(nMask) ;
+
+     nMask=0 ;
+     for(int ij=0; ij<nij ; ij++) 
+      if (localMask(ij))
+      {
+        index(nMask)=ij ;
+        nMask++ ;
+      }
+      localElement_ -> addView(CElementView::WORKFLOW, index) ;
+   }
+
+   void CDomain::addModelView(void)
+   {
+     // information for model view is stored in data_i_index/data_j_index
+     // very weird, do not mix data_i_index and data_i_begin => in future only keep data_i_index
+     int dataSize = data_i_index.numElements() ;
+     CArray<int,1> index(dataSize) ;
+     int i,j ;
+     for(int k=0;k<dataSize;k++)
+     {
+        i=data_i_index(k)+data_ibegin ; // bad
+        j=data_j_index(k)+data_jbegin ; // bad
+        if (i>=0 && i<ni && j>=0 && j<nj) index(k)=i+j*ni ;
+        else index(k)=-1 ;
+     }
+     localElement_->addView(CElementView::MODEL, index) ;
+   }
+        
+   void CDomain::computeModelToWorkflowConnector(void)
+   { 
+     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
+     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
+     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
+     modelToWorkflowConnector_->computeConnector() ;
+   }
+
 
    //----------------------------------------------------------------
@@ -2099,4 +2198,7 @@
     this->sendArea(client);    
     this->sendDataIndex(client);
+
+    // test new connector functionnality
+    this->sendDomainDistribution(client) ;
   }
 
@@ -2129,4 +2231,123 @@
     this->createAlias(domainId) ;
   }
+
+
+  void CDomain::sendDomainDistribution(CContextClient* client, const string& domainId)
+  TRY
+  {
+    string serverDomainId = domainId.empty() ? this->getId() : domainId ;
+    CContext* context = CContext::getCurrent();
+    int nbServer = client->serverSize;
+    std::vector<int> nGlobDomain(2);
+    nGlobDomain[0] = this->ni_glo;
+    nGlobDomain[1] = this->nj_glo;
+
+    CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
+    int distributedPosition ;
+    if (isUnstructed_) distributedPosition = 0 ;
+    else distributedPosition = 1 ;
+
+    serverDescription.computeServerDistribution(false, distributedPosition);
+    
+    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
+    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
+ 
+    vector<unordered_map<size_t,vector<int>>> indexServerOnElement ;
+    CArray<int,1> axisDomainOrder(1) ; axisDomainOrder(0)=2 ;
+    auto zeroIndex=serverDescription.computeServerGlobalByElement(indexServerOnElement, context->getIntraCommRank(), context->getIntraCommSize(),
+                                                                  axisDomainOrder,distributedPosition) ;
+    // distribution is very bad => to redo
+    // convert indexServerOnElement => map<int,CArray<size_t,1>> - need to be changed later
+    map<int, vector<size_t>> vectGlobalIndex ;
+    for(auto& indexRanks : indexServerOnElement[0])
+    {
+      size_t index=indexRanks.first ;
+      auto& ranks=indexRanks.second ;
+      for(int rank : ranks) vectGlobalIndex[rank].push_back(index) ;
+    }
+    map<int, CArray<size_t,1>> globalIndex ;
+    for(auto& vect : vectGlobalIndex ) globalIndex.emplace(vect.first, CArray<size_t,1>(vect.second.data(), shape(vect.second.size()))) ; 
+
+    CDistributedElement remoteElement(ni_glo*nj_glo, globalIndex) ;
+    remoteElement.addFullView() ;
+
+    CRemoteConnector remoteConnector(localElement_->getView(CElementView::FULL), remoteElement.getView(CElementView::FULL),context->getIntraComm()) ;
+    remoteConnector.computeConnector() ;
+    CDistributedElement scatteredElement(remoteElement.getGlobalSize(), remoteConnector.getDistributedGlobalIndex()) ;
+    scatteredElement.addFullView() ;
+    CScattererConnector scatterConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), context->getIntraComm()) ;
+    scatterConnector.computeConnector() ;
+    CGridScattererConnector gridScatter({&scatterConnector}) ;
+
+    CEventClient event0(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message0 ;
+    message0<<serverDomainId<<0 ; 
+    remoteElement.sendToServer(client,event0,message0) ;
+
+    CEventClient event1(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message1 ;
+    message1<<serverDomainId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
+    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
+    
+    CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message2 ;
+    message2<<serverDomainId<<2 ; 
+//    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+
+/*
+    localElement_->getView(CElementView::FULL)->sendRemoteElement(remoteConnector, client, event1, message1) ;
+    CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message2 ;
+    message2<<serverDomainId<<2 ; 
+    remoteConnector.transferToServer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+*/
+
+  }
+  CATCH
+  
+
+  void CDomain::recvDomainDistribution(CEventServer& event)
+  TRY
+  {
+    string domainId;
+    int phasis ;
+    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> phasis ;
+    get(domainId)->receivedDomainDistribution(event, phasis);
+  }
+  CATCH
+
+  void CDomain::receivedDomainDistribution(CEventServer& event, int phasis)
+  TRY
+  {
+    CContext* context = CContext::getCurrent();
+    if (phasis==0)
+    {
+      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
+      localElement_->addFullView() ;
+    }
+    else if (phasis==1)
+    {
+      CContext* context = CContext::getCurrent();
+      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
+      elementFrom->addFullView() ;
+      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
+      gathererConnector_->computeConnector() ; 
+    }
+    else if (phasis==2)
+    {
+      CArray<size_t,1> globalIndex ;
+      //gathererConnector_->transfer(event,globalIndex) ;
+      CGridGathererConnector gridGathererConnector({gathererConnector_}) ;
+      gridGathererConnector.transfer(event, globalIndex) ;
+    }
+    else if (phasis==3)
+    {
+
+    }
+  }
+  CATCH
+
+  
 
   /*!
@@ -2482,4 +2703,8 @@
           return true;
           break;
+        case EVENT_ID_DOMAIN_DISTRIBUTION:
+          recvDomainDistribution(event);
+          return true;
+          break;
         default:
           ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp	(revision 1918)
@@ -18,4 +18,7 @@
 #include "server_distribution_description.hpp"
 #include "mesh.hpp"
+#include "element.hpp"
+#include "local_connector.hpp"
+#include "gatherer_connector.hpp"
 
 namespace xios {
@@ -50,5 +53,6 @@
            EVENT_ID_INDEX, EVENT_ID_LON, EVENT_ID_LAT, 
            EVENT_ID_AREA,
-           EVENT_ID_DATA_INDEX, EVENT_ID_SERVER_ATTRIBUT
+           EVENT_ID_DATA_INDEX, EVENT_ID_SERVER_ATTRIBUT,
+           EVENT_ID_DOMAIN_DISTRIBUTION
          } ;
 
@@ -216,4 +220,9 @@
        private:
 
+         static void recvDomainDistribution(CEventServer& event) ;
+         void receivedDomainDistribution(CEventServer& event, int phasis) ;
+        
+
+         void sendDomainDistribution(CContextClient* client, const string& domainId="") ; //for testing
          void sendAttributes(); // ym obsolete -> to be removed
          void sendIndex(CContextClient* client, const string& domainId="");
@@ -301,4 +310,26 @@
          static bool _dummyTransformationMapList;
 
+ 
+       private:
+         CLocalElement* localElement_ = nullptr ;
+         void initializeLocalElement(void) ;
+       
+       public:  
+         CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; }
+         CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;}
+       
+       private:  
+         void addFullView(void) ;
+         void addWorkflowView(void) ;
+         void addModelView(void) ;
+        
+       private:
+         CLocalConnector* modelToWorkflowConnector_ ;
+         void computeModelToWorkflowConnector(void)  ;
+         CGathererConnector*  gathererConnector_ ;
+
+       public:
+         CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;}
+         
          DECLARE_REF_FUNC(Domain,domain)
 
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 1918)
@@ -372,4 +372,21 @@
    CATCH
 
+   
+   CArray<bool,1>& CGrid::getMask(void)
+   {
+      
+      if (mask_.isEmpty())
+      {  
+        if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ;
+        if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ;
+        if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ;
+        if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ;
+        if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ;
+        if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ;
+        if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ;
+        if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ;
+      }
+      return mask_ ;
+   }
    /*
      Create mask of grid from mask of its components
@@ -3044,3 +3061,39 @@
   CATCH_DUMP_ATTR
 
+
+  void CGrid::computeGridLocalElements()
+  {
+    std::vector<CDomain*> domainList = this->getDomains();
+    std::vector<CAxis*> axisList = this->getAxis();
+    auto domain=domainList.begin() ;
+    auto axis=axisList.begin() ;
+    vector<CLocalElement*> elements;
+    for(auto order : order_)
+    {
+      if (order==2) 
+      {
+        elements.push_back((*domain)->getLocalElement());
+        domain++ ;
+      }
+      else if (order==1)
+      {
+        elements.push_back((*axis)->getLocalElement());
+        axis++ ;
+      }
+      else if (order==0)
+      { 
+      }
+    }
+    if (hasMask()) 
+    {
+      vector<bool> mask(getMask().getVector()) ;
+      gridLocalElements_ = new CGridLocalElements(elements, mask) ;  
+    }
+    else gridLocalElements_ = new CGridLocalElements(elements) ;  
+  }
+
+  void CGrid::computeModelToWorkflowConnector(void)
+  {
+    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW) ;
+  }
 } // namespace xios
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp	(revision 1918)
@@ -16,4 +16,6 @@
 #include "utils.hpp"
 #include "transformation_enum.hpp"
+#include "grid_local_connector.hpp"
+#include "grid_elements.hpp"
 
 namespace xios {
@@ -255,4 +257,8 @@
          void modifyMask(const CArray<int,1>& indexToModify, bool valueToModify = false);
          void modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue = false);
+        
+        /** get mask pointer stored in mask_1d, or mask_2d, or..., or mask_7d */
+         CArray<bool,1> mask_ ;
+         CArray<bool,1>& getMask(void) ;
 
          void computeGridGlobalDimension(const std::vector<CDomain*>& domains,
@@ -289,4 +295,5 @@
                           const CArray<int,1>& axisDomainOrder,
                           bool createMask = false);
+
         template<int N>
         void modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify);
@@ -500,4 +507,16 @@
 /** List order of axis and domain in a grid, if there is a domain, it will take value 2, axis 1, scalar 0 */
         std::vector<int> order_;
+
+      private:  
+        CGridLocalElements* gridLocalElements_= nullptr ;
+        void computeGridLocalElements(void) ;
+      public:
+        CGridLocalElements* getGridLocalElements(void) { if (gridLocalElements_==nullptr) computeGridLocalElements() ; return gridLocalElements_ ;}
+
+      private:
+        CGridLocalConnector* modelToWorkflowConnector_ ;
+      public:
+        void computeModelToWorkflowConnector(void) ;
+        CGridLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_;}
 
    }; // class CGrid
@@ -521,4 +540,5 @@
    CATCH
 
+/* obsolete
    template <int n>
    void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored)
@@ -534,4 +554,21 @@
       this->maskField_arr(field.dataFirst(), stored);
    }
+*/
+   template <int n>
+   void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored)
+   {
+      auto connector = getModelToWorkflowConnector() ;
+
+      if (connector->getSrcSize() != field.numElements())
+         ERROR("void CGrid::inputField(const  CArray<double,n>& field, CArray<double,1>& stored) const",
+                << "[ Awaiting data of size = " << this->getDataSize() << ", "
+                << "Received data size = "      << field.numElements() << " ] "
+                << "The data array does not have the right size! "
+                << "Grid = " << this->getId())
+      const double nanValue = std::numeric_limits<double>::quiet_NaN();
+      connector->transfer(field, stored, nanValue) ;
+   }
+
+
 
    template <int n>
Index: OS/dev/dev_ym/XIOS_COUPLING/src/server_distribution_description.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/server_distribution_description.cpp	(revision 1917)
+++ 	(revision )
@@ -1,522 +1,0 @@
-/*!
-   \file server_distribution_description.hpp
-   \author Ha NGUYEN
-   \since 04 Jan 2015
-   \date 11 Jan 2016
-
-   \brief Description of index distribution on server(s).
- */
-
-#include "server_distribution_description.hpp"
-#include "exception.hpp"
-
-namespace xios
-{
-  /*!
-  \param [in] globalDimensionSize global dimension of grid
-  \param [in] nServer number of server
-  \param [in] serType type of server distribution. For now, we can distribute server by band or plan
-  */
-CServerDistributionDescription::CServerDistributionDescription(const std::vector<int>& globalDimensionSize,
-                                                               int nServer,
-                                                               ServerDistributionType serType)
-  : nGlobal_(globalDimensionSize), indexBegin_(), dimensionSizes_(), globalIndex_(),
-    vecGlobalIndex_(), serverType_(serType), nServer_(nServer), positionDimensionDistributed_(1)
-{
-}
-
-CServerDistributionDescription::~CServerDistributionDescription()
-{ /* Nothing to do */ }
-
-int CServerDistributionDescription::defaultDistributedDimension(int gridDimension,                                   
-                                                                ServerDistributionType serType)
-{  
-  switch (serType) 
-  {
-    case BAND_DISTRIBUTION:       
-       return ((1 == gridDimension) ? 0 : 1);
-      break;
-    default:
-      break;
-  } 
-}
-
-/*!
-  Compute pre-defined global index distribution of server(s).
-  \param [in] doComputeGlobalIndex flag to compute global index on each server. By default, false
-
-*/
-void CServerDistributionDescription::computeServerDistribution(bool doComputeGlobalIndex,
-                                                               int positionDimensionDistributed)
-{
-  switch (serverType_) {
-    case BAND_DISTRIBUTION:
-      computeBandDistribution(nServer_, positionDimensionDistributed);
-      break;
-    default:
-      break;
-  }
-
-  if (doComputeGlobalIndex)
-  {
-    vecGlobalIndex_.resize(nServer_);
-    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].resize(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;
-          }
-          vecGlobalIndex_[idxServer](idx) = globalIndex;
-          ++idx;
-        }
-        idxLoop[0] += innerLoopSize;
-      }
-    }
-  }
-}
-
-/*!
-  Compute global index assigned to a server with a range.E.g: if a grid has 100 points and
-  there are 2 servers, the first one takes index from 0 to 49, the second has index from 50 to 99
-  \param [in] indexBeginEnd begining and ending index of range
-  \param [in] positionDimensionDistributed dimension of server on which we make the cut.
-*/
-std::vector<int> CServerDistributionDescription::computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd,
-                                                                     int positionDimensionDistributed)
-{
-  int nBand  = 0;
-  switch (serverType_)
-  {
-    case BAND_DISTRIBUTION:
-      nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
-      break;
-    case ROOT_DISTRIBUTION:
-      nBand = computeRootDistribution(nServer_);
-    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");
-
-  globalIndex_.rehash(std::ceil((indexEnd-indexBegin+1)/globalIndex_.max_load_factor()));
-
-  int dim = nGlobal_.size();
-  std::vector<int> currentIndex(dim);
-
-  for (int idxServer = 0; idxServer < nBand; ++idxServer)
-  {
-    size_t ssize = 1, idx = 0;
-    for (int j = 0; j < dim; ++j) ssize *= dimensionSizes_[idxServer][j];
-
-    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_[globalIndex] = idxServer;
-        ++idx;
-      }
-      idxLoop[0] += innerLoopSize;
-    }
-  }
-
-    // List of servers without distribution (cause total number of server is greater than number of bands, for example)
-  std::vector<int> zeroIndexServer(nServer_-nBand); 
-  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
-    zeroIndexServer[idxServer-nBand] = idxServer;
-
-  return zeroIndexServer;
-}
-
-/*!
-  Compute the global index of grid elements (domain, axis) and their associated server rank.
-  Each client knows the general distribution of servers and from which they can compute the pieces of information to hold
-  \param [out] indexServerOnElement global index of each element as well as the corresponding server which contains these indices
-  \param [in] clientRank rank of client
-  \param [in] clientSize number of client
-  \param [in] axisDomainOrder the order of element in grid (2 for domain, 1 for axis, 0 for scalar)
-  \param [in] positionDimensionDistributed dimension of server on which we make the cut.
-*/
-std::vector<int> CServerDistributionDescription::computeServerGlobalByElement(std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
-                                                                              int clientRank,
-                                                                              int clientSize,
-                                                                              const CArray<int,1>& axisDomainOrder,
-                                                                              int positionDimensionDistributed)
-{
-  int nBand  = 0;
-  switch (serverType_) {
-    case BAND_DISTRIBUTION:
-      nBand = computeBandDistribution(nServer_, positionDimensionDistributed);
-      break;
-    default:
-      break;
-  }
-
-  int nbElement = axisDomainOrder.numElements();
-  indexServerOnElement.resize(nbElement);
-  int idx = 0;
-  std::vector<int> idxMap(nbElement);
-  for (int i = 0; i < nbElement; ++i)
-  {
-    idxMap[i] = idx;
-    if (2 == axisDomainOrder(i)) idx += 2;
-    else if (1 == axisDomainOrder(i)) idx += 1;
-    // nothing for scalar
-  }
-
-  for (int idxServer = 0; idxServer < nBand; ++idxServer)
-  {
-    std::vector<int> elementDimension(4);
-    for (int i = 0; i < nbElement; ++i)
-    {
-      int elementSize = 1;
-      if (2 == axisDomainOrder(i))
-      {
-        elementSize *= dimensionSizes_[idxServer][idxMap[i]] * dimensionSizes_[idxServer][idxMap[i]+1];
-        elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
-        elementDimension[1] = indexBegin_[idxServer][idxMap[i]+1];
-        elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
-        elementDimension[3] = dimensionSizes_[idxServer][idxMap[i]+1];
-      }
-
-      else if (1 == axisDomainOrder(i))
-      {
-        elementSize *= dimensionSizes_[idxServer][idxMap[i]];
-        elementDimension[0] = indexBegin_[idxServer][idxMap[i]];
-        elementDimension[1] = 0;
-        elementDimension[2] = dimensionSizes_[idxServer][idxMap[i]];
-        elementDimension[3] = 1;
-      }
-      else
-      {
-        elementSize *= dimensionSizes_[idxServer][idxMap[i]];
-        elementDimension[0] = 0;
-        elementDimension[1] = 0;
-        elementDimension[2] = 1;
-        elementDimension[3] = 1;
-      }
-
-      int rangeBegin, rangeSize;
-      computeRangeProcIndex(clientRank, clientSize, elementSize, rangeBegin, rangeSize);
-
-      size_t globalIndexElement;
-      idx = 0; int idxRange = 0;
-      for (int k = 0; k < elementDimension[3]; ++k)
-        for (int l = 0; l < elementDimension[2]; ++l)
-        {
-          globalIndexElement = (l+elementDimension[0]) + (k+elementDimension[1])*elementDimension[2];
-          if ((rangeBegin <= idx) && (idxRange < rangeSize))
-          {
-            indexServerOnElement[i][globalIndexElement].push_back(idxServer);
-            ++idxRange;
-          }
-          ++idx;
-        }
-    }
-  }
-
-  // List of servers without distribution (cause total number of server is greater than number of bands, for example)
-  std::vector<int> zeroIndexServer(nServer_-nBand); 
-  for (int idxServer = nBand; idxServer < nServer_; ++idxServer)
-    zeroIndexServer[idxServer-nBand] = idxServer;
-
-  return zeroIndexServer;
-}
-
-/*!
-  Compute a range of index on server which a client holds
-  For a range of index on a specific server, each client can hold a piece of the index range
-  If the range size is smaller than the number of client, there are some clients holding the same index
-  \param [in] clientRank rank of client
-  \param [in] clientSize number of client
-  \param [in] rangeProcSize index range size
-  \param [out] rangeBegin begin of range index a client holds
-  \param [out] rangeSize size of range index a client holds
-*/
-void CServerDistributionDescription::computeRangeProcIndex(int clientRank,
-                                                           int clientSize,
-                                                           int rangeProcSize,
-                                                           int& rangeBegin,
-                                                           int& rangeSize)
-{
-  if (rangeProcSize < clientSize)
-  {
-    int rangeIndex = 0;
-    for (int idx = 0; idx < clientSize; ++idx)
-    {
-      if (idx == clientRank)
-      {
-        rangeBegin = rangeIndex;
-        rangeSize = 1;
-      }
-      ++rangeIndex;
-      if (rangeIndex == rangeProcSize) rangeIndex = 0;
-    }
-    return;
-  }
-
-  int range, indexBegin = 0;
-  for (int i = 0; i < clientSize; ++i)
-  {
-    range = rangeProcSize / clientSize;
-    if (i < (rangeProcSize%clientSize)) ++range;
-    if (i == clientRank) break;
-    indexBegin += range;
-  }
-  rangeBegin = indexBegin;
-  rangeSize = range;
-}
-
-/*!
-  Compute global index of servers with band distribution
-  \param [in] nServer number of server
-*/
-int CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)
-{
-  int dim = nGlobal_.size();
-  positionDimensionDistributed_ = positionDimensionDistributed;
-  if (1 == dim) positionDimensionDistributed_ = 0;
-  if (positionDimensionDistributed_ > dim)
-    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
-          << "Position of distributed dimension is invalid" << std::endl
-          << "Position of distributed dimension is " << positionDimensionDistributed_
-          << "Dimension " << dim)
-
-  indexBegin_.resize(nServer);
-  dimensionSizes_.resize(nServer);
-
-  for (int i = 0; i< nServer; ++i)
-  {
-    indexBegin_[i].resize(dim);
-    dimensionSizes_[i].resize(dim);
-  }
-
-  int njRangeSize;
-  int nGlobTemp = 0;
-  std::vector<int> njRangeBegin(nServer,0);
-  std::vector<int> njRangeEnd(nServer,0);
-
-  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
-  nGlobTemp = nGlobal_[positionDistributed];
-  int nbBand = std::min(nGlobTemp, nServer);
-
-  for (int i = 0; i < nbBand; ++i)
-  {
-    if (0 < i) njRangeBegin[i] = njRangeEnd[i-1];
-    njRangeSize = nGlobTemp / nbBand;
-    if (i < nGlobTemp%nbBand) ++njRangeSize;
-    njRangeEnd[i] = njRangeSize + njRangeBegin[i];
-  }
-  njRangeEnd[nbBand-1] = nGlobTemp;
-
-  for (int i = nbBand; i < nServer; ++i)
-  {
-    njRangeBegin[i] = njRangeEnd[i] = 0;
-  }
-
-  for (int i = 0; i < nServer; ++i)
-  {
-    for (int j = 0; j < dim; ++j)
-    {
-      if (positionDistributed != j)
-      {
-        if (1 == dim)
-        {
-          indexBegin_[i][j] = njRangeBegin[i];
-          dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
-        }
-        else
-        {
-          indexBegin_[i][j] = 0;
-          dimensionSizes_[i][j] = nGlobal_[j];
-        }
-      }
-      else
-      {
-        indexBegin_[i][j] = njRangeBegin[i];
-        dimensionSizes_[i][j] = njRangeEnd[i] - njRangeBegin[i];
-      }
-    }
-  }
-
-  return nbBand;
-}
-
-
-/*!
-  Compute global index of servers with root distribution : only root server will received data
-  \param [in] nServer number of server
-*/
-int CServerDistributionDescription::computeRootDistribution(int nServer, int positionDimensionDistributed)
-{
-  int dim = nGlobal_.size();
-  positionDimensionDistributed_ = positionDimensionDistributed;
-  if (1 == dim) positionDimensionDistributed_ = 0;
-  if (positionDimensionDistributed_ > dim)
-    ERROR("CServerDistributionDescription::computeBandDistribution(int nServer, int positionDimensionDistributed)",
-          << "Position of distributed dimension is invalid" << std::endl
-          << "Position of distributed dimension is " << positionDimensionDistributed_
-          << "Dimension " << dim)
-
-  indexBegin_.resize(nServer);
-  dimensionSizes_.resize(nServer);
-
-  for (int i = 0; i< nServer; ++i)
-  {
-    indexBegin_[i].resize(dim);
-    dimensionSizes_[i].resize(dim);
-  }
-
-  int nGlobTemp = 0;
-
-  int positionDistributed = (1<dim) ? positionDimensionDistributed_ : 0;
-  nGlobTemp = nGlobal_[positionDistributed];
-  int nbBand = 1 ;
-
-
-  for (int i = 0; i < nServer; ++i)
-  {
-    for (int j = 0; j < dim; ++j)
-    {
-      if (positionDistributed != j) // bad coding, need to be rewrite
-      {
-        if (1 == dim)
-        {
-          if (i==0)
-          {
-            indexBegin_[i][j] = 0;
-            dimensionSizes_[i][j] = nGlobTemp;
-          }
-          else
-          {
-            indexBegin_[i][j] = nGlobTemp-1;
-            dimensionSizes_[i][j] = 0;
-          }
-        }
-        else
-        {
-          indexBegin_[i][j] = 0;
-          dimensionSizes_[i][j] = nGlobal_[j];
-        }
-      }
-      else
-      {
-        if (i==0)
-        {
-          indexBegin_[i][j] = 0;
-          dimensionSizes_[i][j] = nGlobTemp;
-        }
-        else
-        {
-          indexBegin_[i][j] = nGlobTemp-1;
-          dimensionSizes_[i][j] = 0;
-        }
-      }
-    }
-  }
-
-  return nbBand;
-}
-
-
-
-
-/*!
-  Get size of each dimension on distributed server
-  \return size of dimensions on server(s)
-*/
-std::vector<std::vector<int> > CServerDistributionDescription::getServerDimensionSizes() const
-{
-  return dimensionSizes_;
-}
-
-/*!
-  Get index begin of each dimension on distributed server
-  \return index begin of dimensions on server(s)
-*/
-std::vector<std::vector<int> > CServerDistributionDescription::getServerIndexBegin() const
-{
-  return indexBegin_;
-}
-
-/*!
-  Get global index on distributed server
-  \return global index on server(s)
-*/
-const std::vector<CArray<size_t,1> >& CServerDistributionDescription::getGlobalIndex() const
-{
-  return vecGlobalIndex_;
-}
-
-/*!
-  Get global index calculated by computeServerGlobalIndexInRange
-*/
-const std::unordered_map<size_t,int>& CServerDistributionDescription::getGlobalIndexRange() const
-{
-  return globalIndex_;
-}
-
-int CServerDistributionDescription::getDimensionDistributed()
-{
-  return ((1<nGlobal_.size()) ? positionDimensionDistributed_ : 0);
-}
-
-} // namespace xios
Index: OS/dev/dev_ym/XIOS_COUPLING/src/server_distribution_description.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/server_distribution_description.hpp	(revision 1917)
+++ 	(revision )
@@ -1,88 +1,0 @@
-/*!
-   \file server_distribution_description.hpp
-   \author Ha NGUYEN
-   \since 04 Jan 2015
-   \date 11 Jan 2016
-
-   \brief Description of index distribution on server(s).
- */
-
-#ifndef __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
-#define __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
-
-#include "xios_spl.hpp"
-#include "array_new.hpp"
-#include <unordered_map>
-
-namespace xios
-{
-/*!
-   \class CServerDistributionDescription
-   This class contains information that describe distribution of servers.
-*/
-class CServerDistributionDescription
-{
-  public:
-    enum ServerDistributionType
-    {
-      BAND_DISTRIBUTION, PLAN_DISTRIBUTION, ROOT_DISTRIBUTION
-    };
-
-    /** Default constructor */
-    CServerDistributionDescription(const std::vector<int>& globalDimensionSize,
-                                   int nServer,
-                                   ServerDistributionType serType=BAND_DISTRIBUTION);
-
-    /** Default destructor */
-    virtual ~CServerDistributionDescription();
-
-    void computeServerDistribution(bool doComputeGlobalIndex = false, int positionDimensionDistributed = 1);
-    std::vector<int> computeServerGlobalIndexInRange(const std::pair<size_t, size_t>& indexBeginEnd, int positionDimensionDistributed = 1);
-    std::vector<int> computeServerGlobalByElement(std::vector<std::unordered_map<size_t,std::vector<int> > >& indexServerOnElement,
-                                                  int rank,
-                                                  int clientSize,
-                                                  const CArray<int,1>& axisDomainOrder,
-                                                  int positionDimensionDistributed = 1);
-
-    std::vector<std::vector<int> > getServerIndexBegin() const;
-    std::vector<std::vector<int> > getServerDimensionSizes() const;
-    const std::vector<CArray<size_t,1> >& getGlobalIndex() const;
-    const std::unordered_map<size_t,int>& getGlobalIndexRange() const;
-    int getDimensionDistributed();
-
-    static int defaultDistributedDimension(int gridDimension,                                   
-                                           ServerDistributionType serType=BAND_DISTRIBUTION);
-
-  protected:
-    int computeBandDistribution(int nServer, int positionDimensionDistributed = 1);
-    int computeRootDistribution(int nServer, int positionDimensionDistributed = 1);
-    void computePlanDistribution(int nServer);
-    void computeRangeProcIndex(int clientRank,
-                               int clientSize,
-                               int rangeProcSize,
-                               int& rangeBegin,
-                               int& rangeSize);
-
-  private:
-    std::vector<std::vector<int> > indexBegin_;     //!< Begin index of each dimension
-    std::vector<std::vector<int> > dimensionSizes_; //!< Size of each dimension
-    std::vector<int> nGlobal_; //!< Global size of each dimension
-
-    //!< General case, index describes distribution of each server (rarely use)
-    std::vector<CArray<size_t,1> > vecGlobalIndex_;
-
-    //!< In case we need only global index of one server with specific rank
-    std::unordered_map<size_t,int> globalIndex_;
-
-    //!< Type of distribution on server side
-    ServerDistributionType serverType_;
-
-    //!< Number of server
-    int nServer_;
-
-    //!< Position of dimension distributed on server side (by default, the second dimension)
-    int positionDimensionDistributed_;
-};
-
-} // namespace xios
-#endif // __XIOS_SERVER_DISTRIBUTION_DESCRIPTION_HPP
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.cpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.cpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.cpp	(revision 1918)
@@ -9,4 +9,10 @@
 
    CMessage::CMessage(void) {}
+
+   CMessage::CMessage(const CMessage& msg) 
+   {
+     for(auto type : msg.typeList) push(*type) ;
+   }
+
    
    CMessage& CMessage::push(const CBaseType& type)
Index: /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.hpp
===================================================================
--- /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.hpp	(revision 1917)
+++ /XIOS/dev/dev_ym/XIOS_COUPLING/src/type/message.hpp	(revision 1918)
@@ -17,4 +17,6 @@
     
     CMessage(void) ;
+    CMessage(const CMessage& Msg)  ;
+    
     list<CBaseType*> typeList ;
     virtual bool fromBuffer(CBufferIn& buffer) const;
