Index: XIOS/dev/dev_olga/src/config/axis_attribute_private.conf
===================================================================
--- XIOS/dev/dev_olga/src/config/axis_attribute_private.conf	(revision 1077)
+++ XIOS/dev/dev_olga/src/config/axis_attribute_private.conf	(revision 1099)
@@ -2,4 +2,7 @@
 DECLARE_ATTRIBUTE_PRIVATE(int, global_zoom_n)
 
+DECLARE_ATTRIBUTE_PRIVATE(int, zoom_begin)
+DECLARE_ATTRIBUTE_PRIVATE(int, zoom_n)
+
 /* LOCAL DATA*/
 DECLARE_ARRAY_PRIVATE(int    ,   1 , zoom_index)
Index: XIOS/dev/dev_olga/src/config/domain_attribute_private.conf
===================================================================
--- XIOS/dev/dev_olga/src/config/domain_attribute_private.conf	(revision 1077)
+++ XIOS/dev/dev_olga/src/config/domain_attribute_private.conf	(revision 1099)
@@ -19,10 +19,11 @@
 DECLARE_ATTRIBUTE_PRIVATE(int,  global_zoom_nj)
 
+// Local zoom information
+DECLARE_ATTRIBUTE_PRIVATE(int,  zoom_ibegin)
+DECLARE_ATTRIBUTE_PRIVATE(int,  zoom_ni)
+DECLARE_ATTRIBUTE_PRIVATE(int,  zoom_jbegin)
+DECLARE_ATTRIBUTE_PRIVATE(int,  zoom_nj)
+
+
 DECLARE_ARRAY_PRIVATE(int    ,   1 , zoom_i_index, false)
 DECLARE_ARRAY_PRIVATE(int    ,   1 , zoom_j_index, false)
-//DECLARE_ARRAY_PRIVATE(double ,   1 , areavalue, false)
-//DECLARE_ARRAY_PRIVATE(int    ,   1 , lonvalue, false)
-//DECLARE_ARRAY_PRIVATE(int    ,   1 , latvalue, false)
-//DECLARE_ARRAY_PRIVATE(int    ,   2 , bounds_lonvalue, false)
-//DECLARE_ARRAY_PRIVATE(int    ,   2 , bounds_latvalue, false)
-
Index: XIOS/dev/dev_olga/src/declare_ref_func.hpp
===================================================================
--- XIOS/dev/dev_olga/src/declare_ref_func.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/declare_ref_func.hpp	(revision 1099)
@@ -71,5 +71,6 @@
 bool C##type::hasDirect##type##Reference(void) const                   \
 {                                                                      \
-  return !this->name_##_ref.isEmpty();                                 \
+  return (!this->name_##_ref.isEmpty() &&                              \
+          C##type::has(this->name_##_ref));                            \
 }                                                                      \
                                                                        \
Index: XIOS/dev/dev_olga/src/distribution_server.cpp
===================================================================
--- XIOS/dev/dev_olga/src/distribution_server.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/distribution_server.cpp	(revision 1099)
@@ -175,12 +175,17 @@
 void CDistributionServer::computeLocalIndex(CArray<size_t,1>& globalIndex)
 {
-  int ssize = globalIndex.numElements();
-  CArray<size_t,1> localIndex(ssize);
+  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;
-  for (int idx = 0; idx < ssize; ++idx)
+  int i = 0;
+  for (size_t idx = 0; idx < ssize; ++idx)
   {
     it = globalLocalIndexMap_.find(globalIndex(idx));
     if (ite != it)
-      localIndex(idx) = it->second;
+    {
+      localIndex(i) = it->second;
+      ++i;
+    }
   }
 
@@ -201,4 +206,11 @@
 }
 
+/*!
+  Get the size of grid index in server (e.x: sizeGrid *= size of each dimensiion)
+*/
+int CDistributionServer::getGridSize() const
+{
+   return globalLocalIndexMap_.size();
+}
 
 const std::vector<int>& CDistributionServer::getZoomBeginGlobal() const
Index: XIOS/dev/dev_olga/src/distribution_server.hpp
===================================================================
--- XIOS/dev/dev_olga/src/distribution_server.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/distribution_server.hpp	(revision 1099)
@@ -42,4 +42,5 @@
     const GlobalLocalMap& getGlobalLocalIndex() const { return globalLocalIndexMap_; }
     const std::vector<CArray<int,1> >& getGlobalIndexEachDimension() const {return globalIndexEachDimension_;}
+    int getGridSize() const;
 
     virtual CArray<size_t,1> computeLocalIndex(const CArray<size_t,1>& globalIndex);
Index: XIOS/dev/dev_olga/src/io/nc4_data_output.cpp
===================================================================
--- XIOS/dev/dev_olga/src/io/nc4_data_output.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/io/nc4_data_output.cpp	(revision 1099)
@@ -74,8 +74,8 @@
          else setWrittenDomain(domid);
 
-        const std::vector<int>& local_size_write  = domain->getLocalWriteSize();
-        const std::vector<int>& global_size_write = domain->getGlobalWriteSize();
-        const std::vector<int>& start_write = domain->getStartWriteIndex();
-        const std::vector<int>& count_write = domain->getCountWriteIndex();
+        // const std::vector<int>& local_size_write  = domain->getLocalWriteSize();
+        // const std::vector<int>& global_size_write = domain->getGlobalWriteSize();
+        // const std::vector<int>& start_write = domain->getStartWriteIndex();
+        // const std::vector<int>& count_write = domain->getCountWriteIndex();
         int nvertex = (domain->nvertex.isEmpty()) ? 0 : domain->nvertex;
 
@@ -140,6 +140,6 @@
                  bounds_latid = StdString("bounds_lat").append(appendDomid);
 
-                 SuperClassWriter::addDimension(dimXid, local_size_write[0]);
-                 SuperClassWriter::addDimension(dimYid, local_size_write[1]);
+                 SuperClassWriter::addDimension(dimXid, domain->zoom_ni);
+                 SuperClassWriter::addDimension(dimYid, domain->zoom_nj);
 
                  if (domain->hasBounds)
@@ -148,12 +148,16 @@
                  if (server->intraCommSize > 1)
                  {
-                   this->writeLocalAttributes(0, count_write[0],
-                                              0, count_write[1],
+                   this->writeLocalAttributes(domain->zoom_ibegin,
+                                              domain->zoom_ni,
+                                              domain->zoom_jbegin,
+                                              domain->zoom_nj,
                                               appendDomid);
 
                    if (singleDomain)
                     this->writeLocalAttributes_IOIPSL(dimXid, dimYid,
-                                                      0, count_write[0],
-                                                      0, count_write[1],
+                                                      domain->zoom_ibegin,
+                                                      domain->zoom_ni,
+                                                      domain->zoom_jbegin,
+                                                      domain->zoom_nj,
                                                       domain->ni_glo,domain->nj_glo,
                                                       server->intraCommRank,server->intraCommSize);
@@ -228,7 +232,7 @@
                        break;
                      case CDomain::type_attr::rectilinear :
-                       CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,local_size_write[0])) ;
+                       CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,domain->zoom_ni)) ;
                        SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0);
-                       CArray<double,1> lon = domain->lonvalue(Range(0,local_size_write[1])) ;
+                       CArray<double,1> lon = domain->lonvalue(Range(0,domain->zoom_ni-1)) ;
 //                       CArray<double,1> lon = domain->lonvalue(Range(0,local_size_write[1]-1)) ;
                        SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0);
@@ -252,6 +256,6 @@
               case (ONE_FILE) :
               {
-                 SuperClassWriter::addDimension(dimXid, global_size_write[0]);
-                 SuperClassWriter::addDimension(dimYid, global_size_write[1]);
+                 SuperClassWriter::addDimension(dimXid, domain->global_zoom_ni);
+                 SuperClassWriter::addDimension(dimYid, domain->global_zoom_nj);
 
                  if (domain->hasBounds)
@@ -327,11 +331,11 @@
                      else
                      {
-                       // start[1]=domain->zoom_ibegin_srv-domain->global_zoom_ibegin;
-                       // start[0]=domain->zoom_jbegin_srv-domain->global_zoom_jbegin;
-                       // count[1]=domain->zoom_ni_srv ; count[0]=domain->zoom_nj_srv ;
-                       start[1]= start_write[0];
-                       start[0]= start_write[1];
-                       count[1]= count_write[0];
-                       count[0]= count_write[1];
+                       start[1]=domain->zoom_ibegin-domain->global_zoom_ibegin;
+                       start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin;
+                       count[1]=domain->zoom_ni ; count[0]=domain->zoom_nj ;
+                       // start[1]= start_write[0];
+                       // start[0]= start_write[1];
+                       // count[1]= count_write[0];
+                       // count[0]= count_write[1];
                      }
 
@@ -359,12 +363,16 @@
                        else
                        {
-                         start[0]= start_write[1];
-                         count[0]= count_write[1];
-                         CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,count_write[0])) ;
+                         // start[0]= start_write[1];
+                         // count[0]= count_write[1];
+                         start[0]=domain->zoom_jbegin-domain->global_zoom_jbegin;
+                         count[0]=domain->zoom_nj;
+                         CArray<double,1> lat = domain->latvalue(Range(fromStart,toEnd,domain->zoom_ni)) ;
                          SuperClassWriter::writeData(CArray<double,1>(lat.copy()), latid, isCollective, 0,&start,&count);
 
-                         start[0]= start_write[0];
-                         count[0]= count_write[0];
-                         CArray<double,1> lon=domain->lonvalue(Range(0,count_write[1])) ;
+                         // start[0]= start_write[0];
+                         // count[0]= count_write[0];
+                         start[0]=domain->zoom_ibegin-domain->global_zoom_ibegin;
+                         count[0]=domain->zoom_ni;
+                         CArray<double,1> lon=domain->lonvalue(Range(0,domain->zoom_ni-1)) ;
                          SuperClassWriter::writeData(CArray<double,1>(lon.copy()), lonid, isCollective, 0,&start,&count);
                        }
@@ -386,9 +394,9 @@
                    {
                      start[2] = 0;
-                     start[1] = start_write[0];
-                     start[0] = start_write[1];
-                     count[2] = nvertex;
-                     count[1] = count_write[0];
-                     count[0] = count_write[1];
+                     start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin;
+                     start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin;
+                     count[2] = domain->nvertex;
+                     count[1] = domain->zoom_ni;
+                     count[0] = domain->zoom_nj;
                    }
 
@@ -409,13 +417,13 @@
                    else
                    {
-                     // start[1] = domain->zoom_ibegin_srv - domain->global_zoom_ibegin;
-                     // start[0] = domain->zoom_jbegin_srv - domain->global_zoom_jbegin;
-                     // count[1] = domain->zoom_ni_srv;
-                     // count[0] = domain->zoom_nj_srv;
-
-                     start[1]= start_write[0];
-                     start[0]= start_write[1];
-                     count[1]= count_write[0];
-                     count[0]= count_write[1];
+                     start[1] = domain->zoom_ibegin - domain->global_zoom_ibegin;
+                     start[0] = domain->zoom_jbegin - domain->global_zoom_jbegin;
+                     count[1] = domain->zoom_ni;
+                     count[0] = domain->zoom_nj;
+
+                     // start[1]= start_write[0];
+                     // start[0]= start_write[1];
+                     // count[1]= count_write[0];
+                     // count[0]= count_write[1];
                    }
 
@@ -1048,10 +1056,18 @@
         axis->checkAttributes();
 
-        int local_size_write  = axis->getLocalWriteSize();
-        int global_size_write = axis->getGlobalWriteSize();
-        int start_write = axis->getStartWriteIndex();
-        int count_write = axis->getCountWriteIndex();
-
-        if ((0 == local_size_write) && (MULTI_FILE == SuperClass::type)) return;
+        // int local_size_write  = axis->getLocalWriteSize();
+        // int global_size_write = axis->getGlobalWriteSize();
+        // int start_write = axis->getStartWriteIndex();
+        // int count_write = axis->getCountWriteIndex();
+
+
+        // if ((0 == local_size_write) && (MULTI_FILE == SuperClass::type)) return;
+
+        int zoom_size  = (MULTI_FILE == SuperClass::type) ? axis->zoom_n
+                                                          : axis->global_zoom_n;
+        int zoom_begin = (MULTI_FILE == SuperClass::type) ? axis->zoom_begin
+                                                          : axis->global_zoom_begin;
+
+        if ((0 == axis->zoom_n) && (MULTI_FILE == SuperClass::type)) return;
 
         std::vector<StdString> dims;
@@ -1062,5 +1078,5 @@
         try
         {
-          SuperClassWriter::addDimension(axisid, global_size_write);
+          SuperClassWriter::addDimension(axisid, zoom_size);
           if (axis->hasValue)
           {
@@ -1102,6 +1118,6 @@
               case MULTI_FILE:
               {
-                CArray<double,1> axis_value(local_size_write);
-                for (int i = 0; i < local_size_write; i++) axis_value(i) = axis->value(i);
+                CArray<double,1> axis_value(axis->zoom_n);
+                for (int i = 0; i < axis->zoom_n; i++) axis_value(i) = axis->value(i);
                 SuperClassWriter::writeData(axis_value, axisid, isCollective, 0);
 
@@ -1115,11 +1131,10 @@
               case ONE_FILE:
               {
-                CArray<double,1> axis_value(count_write);
+                CArray<double,1> axis_value(axis->zoom_n);
                 axis_value = axis->value;
-
                 std::vector<StdSize> start(1), startBounds(2) ;
                 std::vector<StdSize> count(1), countBounds(2) ;
-                start[0] = startBounds[0] = start_write;
-                count[0] = countBounds[0] = count_write;
+                start[0] = startBounds[0] = zoom_begin - axis->global_zoom_begin;
+                count[0] = countBounds[0] = zoom_size;
                 startBounds[1] = 0;
                 countBounds[1] = 2;
@@ -2295,12 +2310,16 @@
                         // start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
                         // count.push_back(nZoomSizeServer[idx]);
-                        start.push_back((domain->getStartWriteIndex())[idx]);
-                        count.push_back((domain->getCountWriteIndex())[idx]);
+                        // start.push_back((domain->getStartWriteIndex())[idx]);
+                        // count.push_back((domain->getCountWriteIndex())[idx]);
+                        start.push_back(domain->zoom_jbegin - domain->global_zoom_jbegin);
+                        count.push_back(domain->zoom_nj);
                       }
                       --idx ;
                       // start.push_back(nZoomBeginServer[idx] - nZoomBeginGlobal[idx]);
                       // count.push_back(nZoomSizeServer[idx]);
-                      start.push_back((domain->getStartWriteIndex())[idx]);
-                      count.push_back((domain->getCountWriteIndex())[idx]);
+                      // start.push_back((domain->getStartWriteIndex())[idx]);
+                      // count.push_back((domain->getCountWriteIndex())[idx]);
+                        start.push_back(domain->zoom_ibegin - domain->global_zoom_ibegin);
+                        count.push_back(domain->zoom_ni);
                       --idx ;
                       --idxDomain;
@@ -2309,6 +2328,8 @@
                     {
                       CAxis* axis = CAxis::get(axisList[idxAxis]);
-                      start.push_back(axis->getStartWriteIndex());
-                      count.push_back(axis->getCountWriteIndex());
+                      // start.push_back(axis->getStartWriteIndex());
+                      // count.push_back(axis->getCountWriteIndex());
+                        start.push_back(axis->zoom_begin - axis->global_zoom_begin);
+                        count.push_back(axis->zoom_n);
                       --idx;
                       --idxAxis;
Index: XIOS/dev/dev_olga/src/node/axis.cpp
===================================================================
--- XIOS/dev/dev_olga/src/node/axis.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/axis.cpp	(revision 1099)
@@ -27,5 +27,5 @@
       , isDistributed_(false), hasBounds_(false), isCompressible_(false)
       , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
-      , transformationMap_(), hasValue(false)
+      , transformationMap_(), hasValue(false), doZoomByIndex_(false)
    {
    }
@@ -37,5 +37,5 @@
       , isDistributed_(false), hasBounds_(false), isCompressible_(false)
       , numberWrittenIndexes_(0), totalNumberWrittenIndexes_(0), offsetWrittenIndexes_(0)
-      , transformationMap_(), hasValue(false)
+      , transformationMap_(), hasValue(false), doZoomByIndex_(false)
    {
    }
@@ -334,4 +334,6 @@
        zoom_index.setValue(index.getValue());
      }
+     if (zoom_n.isEmpty()) zoom_n.setValue(n);
+     if (zoom_begin.isEmpty()) zoom_begin.setValue(begin);
    }
 
@@ -384,8 +386,8 @@
         switch(event.type)
         {
-           // case EVENT_ID_SERVER_ATTRIBUT :
-           //   recvServerAttribut(event);
-           //   return true;
-           //   break;
+           case EVENT_ID_DISTRIBUTION_ATTRIBUTE :
+             recvDistributionAttribute(event);
+             return true;
+             break;
           //  case EVENT_ID_INDEX:
           //   recvIndex(event);
@@ -440,15 +442,19 @@
 
      if (this->isChecked) return;
-     if (context->hasClient) sendAttributes();    
+     if (context->hasClient) sendAttributes(globalDim, orderPositionInGrid, distType);    
 
      this->isChecked = true;
    }
 
-  void CAxis::sendAttributes()
+  void CAxis::sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
+                             CServerDistributionDescription::ServerDistributionType distType)
   {
      if (index.numElements() == n_glo.getValue())
        sendNonDistributedAttributes();
      else
+     {
        sendDistributedAttributes();
+       sendDistributionAttribute(globalDim, orderPositionInGrid, distType);
+     }
   }
 
@@ -457,4 +463,5 @@
   {
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
@@ -466,45 +473,70 @@
       int rank = client->clientRank;
 
-      // size_t ni = this->n.getValue();
-      // size_t ibegin = this->begin.getValue();
-      // size_t zoom_end = global_zoom_begin+global_zoom_n-1;
-      // size_t nZoomCount = 0;
+      size_t ni = this->n.getValue();
+      size_t ibegin = this->begin.getValue();
+      size_t global_zoom_end = global_zoom_begin+global_zoom_n-1;
+      size_t nZoomCount = 0;
       size_t nbIndex = index.numElements();
-      for (size_t idx = 0; idx < nbIndex; ++idx)
-      {
-        globalLocalIndexMap_[index(idx)] = idx;
-        // size_t globalIndex = index(idx);
-        // if (globalIndex >= global_zoom_begin && globalIndex <= zoom_end) ++nZoomCount;
-      }
-
-      // CArray<size_t,1> globalIndexAxis(nbIndex);
-      // std::vector<size_t> globalAxisZoom(nZoomCount);
-      // nZoomCount = 0;
-      // for (size_t idx = 0; idx < nbIndex; ++idx)
-      // {
-      //   size_t globalIndex = index(idx);
-      //   globalIndexAxis(idx) = globalIndex;
-      //   if (globalIndex >= global_zoom_begin && globalIndex <= zoom_end)
-      //   {
-      //     globalAxisZoom[nZoomCount] = globalIndex;
-      //     ++nZoomCount;
-      //   }
-      // }
-
-      // std::set<int> writtenInd;
-      // if (isCompressible_)
-      // {
-      //   for (int idx = 0; idx < data_index.numElements(); ++idx)
-      //   {
-      //     int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);
-
-      //     if (ind >= 0 && ind < ni && mask(ind))
-      //     {
-      //       ind += ibegin;
-      //       if (ind >= global_zoom_begin && ind <= zoom_end)
-      //         writtenInd.insert(ind);
-      //     }
-      //   }
-      // }
+
+      if (doZoomByIndex_) 
+      {
+        nZoomCount = zoom_index.numElements();
+      }
+      else
+      {
+        for (size_t idx = 0; idx < nbIndex; ++idx)
+        {
+          globalLocalIndexMap_[index(idx)] = idx;
+          size_t globalIndex = index(idx);
+          if (globalIndex >= global_zoom_begin && globalIndex <= global_zoom_end) ++nZoomCount;
+        }
+      }
+
+
+      CArray<size_t,1> globalIndexAxis(nbIndex);
+      std::vector<size_t> globalAxisZoom(nZoomCount);
+      nZoomCount = 0;
+      if (doZoomByIndex_) 
+      {
+        int nbIndexZoom = zoom_index.numElements();        
+        for (int i = 0; i < nbIndexZoom; ++i)
+        {   
+          globalIndexAxis(i) = zoom_index(i);
+        }
+      }
+      else 
+      {
+        for (size_t idx = 0; idx < nbIndex; ++idx)
+        {
+          size_t globalIndex = index(idx);
+          globalIndexAxis(idx) = globalIndex;
+          if (globalIndex >= global_zoom_begin && globalIndex <= global_zoom_end)
+          {
+            globalAxisZoom[nZoomCount] = globalIndex;
+            ++nZoomCount;
+          }
+        }
+
+        int end       = begin + n -1;        
+        zoom_begin    = global_zoom_begin > begin ? global_zoom_begin : begin;
+        int zoom_end  = global_zoom_end < end ? zoom_end : end;
+        zoom_n        = zoom_end-zoom_begin+1;
+      }
+
+      std::set<int> writtenInd;
+      if (isCompressible_)
+      {
+        for (int idx = 0; idx < data_index.numElements(); ++idx)
+        {
+          int ind = CDistributionClient::getAxisIndex(data_index(idx), data_begin, ni);
+
+          if (ind >= 0 && ind < ni && mask(ind))
+          {
+            ind += ibegin;
+            if (ind >= global_zoom_begin && ind <= global_zoom_end)
+              writtenInd.insert(ind);
+          }
+        }
+      }
 
       CServerDistributionDescription serverDescriptionGlobal(globalDim, nbServer, distType);
@@ -608,4 +640,55 @@
   }
 
+
+  void CAxis::sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
+                                        CServerDistributionDescription::ServerDistributionType distType)
+  {
+    CContext* context = CContext::getCurrent();
+
+    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
+    for (int i = 0; i < nbSrvPools; ++i)
+    {
+      CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i]
+                                                                         : context->client;
+      int nbServer = contextClientTmp->serverSize;
+
+      CServerDistributionDescription serverDescription(globalDim, nbServer);
+      serverDescription.computeServerDistribution();
+
+      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
+      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
+
+      globalDimGrid.resize(globalDim.size());
+      for (int idx = 0; idx < globalDim.size(); ++idx) globalDimGrid(idx) = globalDim[idx];
+
+      CEventClient event(getType(),EVENT_ID_DISTRIBUTION_ATTRIBUTE);
+      if (contextClientTmp->isServerLeader())
+      {
+        std::list<CMessage> msgs;
+
+        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
+        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+        {
+          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
+          const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
+          const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
+          const int end   = begin + ni - 1;
+
+          msgs.push_back(CMessage());
+          CMessage& msg = msgs.back();
+          msg << this->getId();
+          msg << ni << begin << end;
+          msg << global_zoom_begin.getValue() << global_zoom_n.getValue();
+          msg << isCompressible_;
+          msg << orderPositionInGrid;
+          msg << globalDimGrid;
+
+          event.push(*itRank,1,msg);
+        }
+        contextClientTmp->sendEvent(event);
+      }
+      else contextClientTmp->sendEvent(event);
+    }
+  }
 
   // void CAxis::computeConnectedServer(const std::vector<int>& globalDim, int orderPositionInGrid,
@@ -753,4 +836,5 @@
   {
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
@@ -859,4 +943,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     //int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
@@ -894,8 +979,9 @@
 
         list_indi.push_back(CArray<int,1>(nbData));
-        list_dataInd.push_back(CArray<int,1>(nbData));
-        list_zoomInd.push_back(CArray<int,1>(nbData));
+        list_dataInd.push_back(CArray<int,1>(nbData));        
         list_mask.push_back(CArray<bool,1>(nbData));
 
+        if (doZoomByIndex_)
+          list_zoomInd.push_back(CArray<int,1>(nbData));
 
         if (hasValue)
@@ -908,6 +994,5 @@
 
         CArray<int,1>& indi = list_indi.back();
-        CArray<int,1>& dataIndi = list_dataInd.back();
-        CArray<int,1>& zoomIndi = list_zoomInd.back();
+        CArray<int,1>& dataIndi = list_dataInd.back();        
         CArray<bool,1>& maskIndi = list_mask.back();
 
@@ -920,5 +1005,10 @@
           dataIndi(n) = dataIndex(ind);
           maskIndi(n) = mask(ind);
-          zoomIndi(n) = zoom_index(ind);
+
+          if (doZoomByIndex_)
+          {
+            CArray<int,1>& zoomIndi = list_zoomInd.back();
+            zoomIndi(n) = zoom_index(ind);
+          }
 
           if (hasValue)
@@ -938,8 +1028,14 @@
         listData.push_back(CMessage());
         listData.back() << this->getId()
-                        << list_indi.back() << list_dataInd.back() << list_zoomInd.back() << list_mask.back()
-                        << hasValue;
+                        << list_indi.back() << list_dataInd.back() << list_mask.back();
+
+        listData.back() << doZoomByIndex_;           
+        if (doZoomByIndex_)
+          listData.back() << list_zoomInd.back();
+
+        listData.back() << hasValue;
         if (hasValue)
           listData.back() << list_val.back();
+
         listData.back() << hasBounds_;
         if (hasBounds_)
@@ -982,11 +1078,15 @@
       CBufferIn& buffer = *buffers[idx];
       buffer >> vec_indi[idx];
-      buffer >> vec_dataInd[idx];
-      buffer >> vec_zoomInd[idx];
+      buffer >> vec_dataInd[idx];      
       buffer >> vec_mask[idx];
+
+      buffer >> doZoomByIndex_;
+      if (doZoomByIndex_)
+        buffer >> vec_zoomInd[idx];
 
       buffer >> hasValue;
       if (hasValue)
         buffer >> vec_val[idx];
+
       buffer >> hasBounds_;
       if (hasBounds_)
@@ -1050,133 +1150,77 @@
     }
 
-    int nbZoomIndex = 0;
-    for (int idx = 0; idx < nbReceived; ++idx)
-    {
-      nbZoomIndex += vec_zoomInd[idx].numElements();
-    }
-
-    zoom_index.resize(nbZoomIndex);
-    nbZoomIndex = 0;
-    CArray<int,1>& zoom_Index_Tmp = this->zoom_index;
-    for (int idx = 0; idx < nbReceived; ++idx)
-    {      
-      CArray<int,1> tmp = zoom_Index_Tmp(Range(nbZoomIndex, nbZoomIndex + vec_zoomInd[idx].numElements()-1));
-      tmp = vec_zoomInd[idx];
-
-      nbZoomIndex += vec_zoomInd[idx].numElements();
-    }
-
-
-    {
-      CContextServer* server = CContext::getCurrent()->server;
-      count_write_index_ = zoom_index.numElements();      
-      MPI_Scan(&count_write_index_, &start_write_index_, 1, MPI_INT, MPI_SUM, server->intraComm);
-      global_write_size_ = start_write_index_;
-      start_write_index_ -= count_write_index_;
-      local_write_size_ = count_write_index_;      
-    }
-  }
-
-  // void CAxis::sendServerAttribut(const std::vector<int>& globalDim, int orderPositionInGrid,
-  //                                CServerDistributionDescription::ServerDistributionType distType)
-  // {
-  //   CContext* context = CContext::getCurrent();
-
-  //   CContextClient* contextClientTmp = (0 != context->clientPrimServer) ? context->clientPrimServer 
-  //                                                                       : context->client;
-
-    
-  //   int nbServer = contextClientTmp->serverSize;
-
-  //   CServerDistributionDescription serverDescription(globalDim, nbServer);
-  //   serverDescription.computeServerDistribution();
-
-  //   std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
-  //   std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
-
-  //   globalDimGrid.resize(globalDim.size());
-  //   for (int idx = 0; idx < globalDim.size(); ++idx) globalDimGrid(idx) = globalDim[idx];
-
-  //   CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
-  //   if (contextClientTmp->isServerLeader())
-  //   {
-  //     std::list<CMessage> msgs;
-
-  //     const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
-  //     for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
-  //     {
-  //       // Use const int to ensure CMessage holds a copy of the value instead of just a reference
-  //       const int begin = serverIndexBegin[*itRank][orderPositionInGrid];
-  //       const int ni    = serverDimensionSizes[*itRank][orderPositionInGrid];
-  //       const int end   = begin + ni - 1;
-
-  //       msgs.push_back(CMessage());
-  //       CMessage& msg = msgs.back();
-  //       msg << this->getId();
-  //       msg << ni << begin << end;
-  //       msg << global_zoom_begin.getValue() << global_zoom_n.getValue();
-  //       msg << isCompressible_;
-  //       msg << orderPositionInGrid;
-  //       msg << globalDimGrid;
-
-  //       event.push(*itRank,1,msg);
-  //     }
-  //     contextClientTmp->sendEvent(event);
-  //   }
-  //   else contextClientTmp->sendEvent(event);
-  // }
-
-  // void CAxis::recvServerAttribut(CEventServer& event)
-  // {
-  //   CBufferIn* buffer = event.subEvents.begin()->buffer;
-  //   string axisId;
-  //   *buffer >> axisId;
-  //   get(axisId)->recvServerAttribut(*buffer);
-
-  //   CContext* context = CContext::getCurrent();
-  //   if (context->hasClient && context->hasServer)
-  //   {
-  //     std::vector<int> globalDim(get(axisId)->globalDimGrid.numElements());
-  //     for (int idx = 0; idx < globalDim.size(); ++idx) globalDim[idx] = get(axisId)->globalDimGrid(idx);
-  //     get(axisId)->sendServerAttribut(globalDim, get(axisId)->orderPosInGrid, 
-  //                                     CServerDistributionDescription::BAND_DISTRIBUTION);
-  //   }
-  // }
-
-  // void CAxis::recvServerAttribut(CBufferIn& buffer)
-  // {
-  //   int ni_srv, begin_srv, end_srv, global_zoom_begin_tmp, global_zoom_n_tmp;
-
-  //   buffer >> ni_srv >> begin_srv >> end_srv;
-  //   buffer >> global_zoom_begin_tmp >> global_zoom_n_tmp;
-  //   buffer >> isCompressible_;
-  //   buffer >> orderPosInGrid;
-  //   buffer >> globalDimGrid;
-
-  //   global_zoom_begin = global_zoom_begin_tmp;
-  //   global_zoom_n  = global_zoom_n_tmp;
-  //   int global_zoom_end = global_zoom_begin + global_zoom_n - 1;
-
-  //   zoom_begin_srv = global_zoom_begin > begin_srv ? global_zoom_begin : begin_srv ;
-  //   zoom_end_srv   = global_zoom_end < end_srv ? global_zoom_end : end_srv ;
-  //   zoom_size_srv  = zoom_end_srv - zoom_begin_srv + 1;
-
-  //   if (zoom_size_srv<=0)
-  //   {
-  //     zoom_begin_srv = 0; zoom_end_srv = 0; zoom_size_srv = 0;
-  //   }
-
-  //   if (n_glo == n)
-  //   {
-  //     zoom_begin_srv = global_zoom_begin;
-  //     zoom_end_srv   = global_zoom_end; //zoom_end;
-  //     zoom_size_srv  = zoom_end_srv - zoom_begin_srv + 1;
-  //   }
-  //   if (hasValue)
-  //   {
-  //     value_srv.resize(zoom_size_srv);
-  //     if (hasBounds_)  bound_srv.resize(2,zoom_size_srv);
-  //   }
-  // }
+    if (doZoomByIndex_)
+    {
+      int nbZoomIndex = 0;
+      for (int idx = 0; idx < nbReceived; ++idx)
+      {
+        nbZoomIndex += vec_zoomInd[idx].numElements();
+      }
+
+      zoom_index.resize(nbZoomIndex);
+      nbZoomIndex = 0;      
+      for (int idx = 0; idx < nbReceived; ++idx)
+      {      
+        CArray<int,1>& tmp = vec_zoomInd[idx];
+        for (int i = 0; i < tmp.size(); ++i)
+        {
+          zoom_index(nbZoomIndex) = tmp(i);
+          ++nbZoomIndex;
+        }       
+      }
+    }
+
+
+    // {
+    //   CContextServer* server = CContext::getCurrent()->server;
+    //   count_write_index_ = zoom_index.numElements();      
+    //   MPI_Scan(&count_write_index_, &start_write_index_, 1, MPI_INT, MPI_SUM, server->intraComm);
+    //   global_write_size_ = start_write_index_;
+    //   start_write_index_ -= count_write_index_;
+    //   local_write_size_ = count_write_index_;      
+    // }
+  }
+
+  void CAxis::recvDistributionAttribute(CEventServer& event)
+  {
+    CBufferIn* buffer = event.subEvents.begin()->buffer;
+    string axisId;
+    *buffer >> axisId;
+    get(axisId)->recvDistributionAttribute(*buffer);
+  }
+
+  void CAxis::recvDistributionAttribute(CBufferIn& buffer)
+  {
+    int ni_srv, begin_srv, end_srv, global_zoom_begin_tmp, global_zoom_n_tmp;
+
+    buffer >> ni_srv >> begin_srv >> end_srv;
+    buffer >> global_zoom_begin_tmp >> global_zoom_n_tmp;
+    buffer >> isCompressible_;
+    buffer >> orderPosInGrid;
+    buffer >> globalDimGrid;
+
+    n.setValue(ni_srv);
+    begin.setValue(begin_srv);
+    global_zoom_begin = global_zoom_begin_tmp;
+    global_zoom_n  = global_zoom_n_tmp;
+    int global_zoom_end = global_zoom_begin + global_zoom_n - 1;
+
+    zoom_begin = global_zoom_begin > begin_srv ? global_zoom_begin : begin_srv ;
+    zoom_end_srv   = global_zoom_end < end_srv ? global_zoom_end : end_srv ;
+    zoom_n  = zoom_end_srv - zoom_begin_srv + 1;
+
+    if (zoom_n<=0)
+    {
+      zoom_begin = 0; zoom_end_srv = 0; zoom_n = 0;
+    }
+
+    if (n_glo == n)
+    {
+      zoom_begin = global_zoom_begin;
+      zoom_end_srv   = global_zoom_end; //zoom_end;
+      zoom_n     = zoom_end_srv - zoom_begin + 1;
+    }
+  }
+
 
   CTransformation<CAxis>* CAxis::addTransformation(ETranformationType transType, const StdString& id)
Index: XIOS/dev/dev_olga/src/node/axis.hpp
===================================================================
--- XIOS/dev/dev_olga/src/node/axis.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/axis.hpp	(revision 1099)
@@ -45,5 +45,5 @@
          enum EEventId
          {
-           EVENT_ID_SERVER_ATTRIBUT,
+           EVENT_ID_DISTRIBUTION_ATTRIBUTE,
            EVENT_ID_INDEX,
            EVENT_ID_DISTRIBUTED_VALUE,
@@ -108,9 +108,7 @@
          static ENodeType GetType(void);
 
-         // void sendServerAttribut(const std::vector<int>& globalDim, int orderPositionInGrid,
-         //                         CServerDistributionDescription::ServerDistributionType distType);
          static bool dispatchEvent(CEventServer& event);
-         static void recvServerAttribut(CEventServer& event);
-         // void recvServerAttribut(CBufferIn& buffer) ;
+         static void recvDistributionAttribute(CEventServer& event);
+         void recvDistributionAttribute(CBufferIn& buffer) ;
          void checkAttributesOnClient();
          void checkAttributesOnClientAfterTransformation(const std::vector<int>& globalDim, int orderPositionInGrid,
@@ -142,5 +140,8 @@
          void checkZoom();
          void checkBounds();         
-         void sendAttributes();
+         void sendAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
+                             CServerDistributionDescription::ServerDistributionType distType);
+         void sendDistributionAttribute(const std::vector<int>& globalDim, int orderPositionInGrid,
+                                        CServerDistributionDescription::ServerDistributionType distType);
          void computeConnectedServer(const std::vector<int>& globalDim, int orderPositionInGrid,
                                      CServerDistributionDescription::ServerDistributionType distType);
@@ -180,4 +181,6 @@
          int global_write_size_;
 
+         bool doZoomByIndex_;
+
        private:
          static bool initializeTransformationMap(std::map<StdString, ETranformationType>& m);
Index: XIOS/dev/dev_olga/src/node/context.cpp
===================================================================
--- XIOS/dev/dev_olga/src/node/context.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/context.cpp	(revision 1099)
@@ -300,4 +300,5 @@
      std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize);
 
+
      std::map<int, StdSize>::iterator it, ite = dataBufferSize.end();
      for (it = dataBufferSize.begin(); it != ite; ++it)
@@ -475,9 +476,15 @@
      if (allProcessed) return;
      
-     if (hasClient)
-     {
+     // if (hasClient)
+     // {
        // After xml is parsed, there are some more works with post processing
        postProcessing();
-     }
+
+       // Check grid and calculate its distribution
+       checkGridEnabledFields();
+
+     //}
+
+
 
      setClientServerBuffer();
@@ -502,9 +509,12 @@
 
        // After that, send all grid (if any)
-       sendRefGrid();
+       sendRefGrid();       
 
        // We have a xml tree on the server side and now, it should be also processed
        sendPostProcessing();
-     }
+
+       sendGridEnabledFields();       
+     }
+
      allProcessed = true;
    }
@@ -523,5 +533,8 @@
        {
          CMessage msg;
-         msg<<this->getIdServer();
+         if (hasServer)
+           msg<<this->getIdServer(i);
+         else
+           msg<<this->getIdServer();
          const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
@@ -538,10 +551,9 @@
       string id;
       *buffer>>id;
-      // get(id)->recvPostProcessingGlobalAttributes(*buffer);
+      get(id)->recvPostProcessingGlobalAttributes(*buffer);
    }
 
    void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer)
-   {
-      // CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
+   {      
       postProcessingGlobalAttributes();
    }
@@ -570,6 +582,8 @@
     }
 
-    // if (hasClient) this->solveAllRefOfEnabledFields(true);
-    this->processGridEnabledFields();
+    // if (hasClient) this->solveAllRefOfEnabledFields(true);    
+    checkGridEnabledFields();
+    // sendGridEnabledFields();
+
     if (hasClient) this->sendProcessingGridOfEnabledFields();
     if (hasClient) this->sendCloseDefinition();
@@ -617,11 +631,19 @@
    }
 
-   void CContext::processGridEnabledFields()
+   void CContext::sendGridEnabledFields()
    {
      int size = this->enabledFiles.size();
      for (int i = 0; i < size; ++i)
-     {
-       this->enabledFiles[i]->checkGridOfEnabledFields();
+     {       
        this->enabledFiles[i]->sendGridOfEnabledFields();
+     }
+   }
+
+   void CContext::checkGridEnabledFields()
+   {
+     int size = this->enabledFiles.size();
+     for (int i = 0; i < size; ++i)
+     {
+       this->enabledFiles[i]->checkGridOfEnabledFields();       
      }
    }
@@ -993,5 +1015,8 @@
        {
          CMessage msg;
-         msg<<this->getIdServer();
+         if (hasServer)
+           msg<<this->getIdServer(i);
+         else
+           msg<<this->getIdServer();
          const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
          for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
@@ -1009,5 +1034,5 @@
       string id;
       *buffer>>id;
-      // get(id)->processGridEnabledFields();
+      //get(id)->solveOnlyRefOfEnabledFields(false);
    }
 
@@ -1140,8 +1165,11 @@
 
       // Only search and rebuild all reference objects of enable fields, don't transform
-      if (hasClient) this->solveOnlyRefOfEnabledFields(false);
-
-      // Search and rebuild all reference object of enabled fields
-      // if (hasClient) this->solveAllRefOfEnabledFields(false);
+      this->solveOnlyRefOfEnabledFields(false);
+
+      // Search and rebuild all reference object of enabled fields, and transform
+      this->solveAllEnabledFields();
+
+      // // Check grid and calculate its distribution
+      // if (hasClient) checkGridEnabledFields();
 
       // Find all fields with read access from the public API
@@ -1216,17 +1244,20 @@
          for (size_t j = 0; j < numEnabledFields; ++j)
          {
-           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize();
-           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
-           for (; it != itE; ++it)
+           const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize();
+           for (size_t c = 0; c < mapSize.size(); ++c)
            {
-             // If dataSize[it->first] does not exist, it will be zero-initialized
-             // so we can use it safely without checking for its existance
-             if (CXios::isOptPerformance)
-               dataSize[it->first] += it->second;
-             else if (dataSize[it->first] < it->second)
-               dataSize[it->first] = it->second;
-
-             if (maxEventSize[it->first] < it->second)
-               maxEventSize[it->first] = it->second;
+             std::map<int, StdSize>::const_iterator it = mapSize[c].begin(), itE = mapSize[c].end();
+             for (; it != itE; ++it)
+             {
+               // If dataSize[it->first] does not exist, it will be zero-initialized
+               // so we can use it safely without checking for its existance
+               if (CXios::isOptPerformance)
+                 dataSize[it->first] += it->second;
+               else if (dataSize[it->first] < it->second)
+                 dataSize[it->first] = it->second;
+
+               if (maxEventSize[it->first] < it->second)
+                 maxEventSize[it->first] = it->second;
+             }
            }
          }
Index: XIOS/dev/dev_olga/src/node/context.hpp
===================================================================
--- XIOS/dev/dev_olga/src/node/context.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/context.hpp	(revision 1099)
@@ -126,5 +126,6 @@
 
          void solveAllEnabledFields();
-         void processGridEnabledFields();
+         void checkGridEnabledFields();
+         void sendGridEnabledFields();
 
          std::map<int, StdSize> getAttributesBufferSize(std::map<int, StdSize>& maxEventSize);
Index: XIOS/dev/dev_olga/src/node/domain.cpp
===================================================================
--- XIOS/dev/dev_olga/src/node/domain.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/domain.cpp	(revision 1099)
@@ -33,5 +33,7 @@
       , hasBounds(false), hasArea(false), isDistributed_(false), isCompressible_(false), isUnstructed_(false)
       , isClientAfterTransformationChecked(false), hasLonLat(false)
-      , isRedistributed_(false), hasPole(false)
+      , isRedistributed_(false), hasPole(false), doZoomByIndex_(false)
+      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
+      , globalLocalIndexMap_()
    {
    }
@@ -42,5 +44,7 @@
       , hasBounds(false), hasArea(false), isDistributed_(false), isCompressible_(false), isUnstructed_(false)
       , isClientAfterTransformationChecked(false), hasLonLat(false)
-      , isRedistributed_(false), hasPole(false)
+      , isRedistributed_(false), hasPole(false), doZoomByIndex_(false)
+      , lonvalue(), latvalue(), bounds_lonvalue(), bounds_latvalue()
+      , globalLocalIndexMap_()
    {
 	 }
@@ -756,4 +760,8 @@
     if (zoom_i_index.isEmpty()) zoom_i_index.setValue(i_index.getValue());
     if (zoom_j_index.isEmpty()) zoom_j_index.setValue(j_index.getValue());
+    if (zoom_ibegin.isEmpty()) zoom_ibegin.setValue(ibegin);
+    if (zoom_ni.isEmpty()) zoom_ni.setValue(ni);
+    if (zoom_jbegin.isEmpty()) zoom_jbegin.setValue(jbegin);
+    if (zoom_nj.isEmpty()) zoom_nj.setValue(nj);
    }
 
@@ -1076,5 +1084,6 @@
    void CDomain::completeLonLatClient(void)
    {
-     if (!lonvalue_2d.isEmpty())
+     bool lonlatValueExisted = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
+     if (!lonvalue_2d.isEmpty() && !lonlatValueExisted)
      {
        lonvalue.resize(ni * nj);
@@ -1106,5 +1115,5 @@
        }
      }
-     else if (!lonvalue_1d.isEmpty())
+     else if (!lonvalue_1d.isEmpty()  && !lonlatValueExisted)
      {
        if (type_attr::rectilinear == type)
@@ -1140,5 +1149,5 @@
            }
          }
-         else if (i_index.numElements() == lonvalue_1d.numElements() && j_index.numElements() == latvalue_1d.numElements())
+         else if (i_index.numElements() == lonvalue_1d.numElements() && j_index.numElements() == latvalue_1d.numElements()  && !lonlatValueExisted)
          {
            lonvalue.reference(lonvalue_1d);
@@ -1159,5 +1168,5 @@
                  << i_index.numElements() << " and "  << j_index.numElements() << ".");
        }
-       else if (type == type_attr::curvilinear || type == type_attr::unstructured)
+       else if (type == type_attr::curvilinear || type == type_attr::unstructured  && !lonlatValueExisted)
        {
          lonvalue.reference(lonvalue_1d);
@@ -1174,5 +1183,6 @@
    void CDomain::checkBounds(void)
    {
-     if (!nvertex.isEmpty() && nvertex > 0)
+     bool hasBoundValues = (0 != bounds_lonvalue.numElements()) || (0 != bounds_latvalue.numElements());
+     if (!nvertex.isEmpty() && nvertex > 0 && !hasBoundValues)
      {
        if (!bounds_lon_1d.isEmpty() && !bounds_lon_2d.isEmpty())
@@ -1262,4 +1272,5 @@
    void CDomain::checkArea(void)
    {
+     bool hasAreaValue = (0 != areavalue.numElements());
      hasArea = !area.isEmpty() || !areavalue.isEmpty();
      if (hasArea)
@@ -1292,5 +1303,6 @@
      hasLonLat = (!latvalue_1d.isEmpty() && !lonvalue_1d.isEmpty()) ||
                  (!latvalue_2d.isEmpty() && !lonvalue_2d.isEmpty());
-     if (hasLonLat)
+     bool hasLonLatValue = (0 != lonvalue.numElements()) || (0 != latvalue.numElements());
+     if (hasLonLat && !hasLonLatValue)
      {
        if (!lonvalue_1d.isEmpty() && !lonvalue_2d.isEmpty())
@@ -1443,59 +1455,4 @@
    }
 
-  /*!
-    Send distribution from client to other clients
-    Because a client in a level knows correctly the grid distribution of client on the next level
-    it calculates this distribution then sends it to the corresponding clients on the next level
-  */
-  void CDomain::sendDistributionAttributes(void)
-  {
-    CContext* context = CContext::getCurrent();
-     // Use correct context client to send message
-    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
-    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
-    for (int p = 0; p < nbSrvPools; ++p)
-    {
-      CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[p]
-                                                                       : context->client;
-
-      int nbServer = contextClientTmp->serverSize;
-      std::vector<int> nGlobDomain(2);
-      nGlobDomain[0] = this->ni_glo;
-      nGlobDomain[1] = this->nj_glo;
-
-      CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
-      if (isUnstructed_) serverDescription.computeServerDistribution(false, 0);
-      else serverDescription.computeServerDistribution(false, 1);
-
-      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
-      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
-
-      CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
-      if (contextClientTmp->isServerLeader())
-      {
-        std::list<CMessage> msgs;
-
-        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
-        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
-        {
-          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
-          const int ibegin_srv = serverIndexBegin[*itRank][0];
-          const int jbegin_srv = serverIndexBegin[*itRank][1];
-          const int ni_srv = serverDimensionSizes[*itRank][0];
-          const int nj_srv = serverDimensionSizes[*itRank][1];
-
-          msgs.push_back(CMessage());
-          CMessage& msg = msgs.back();
-          msg << this->getId() ;
-        msg << ni_srv << ibegin_srv << nj_srv << jbegin_srv;        
-          msg << isCompressible_;
-
-          event.push(*itRank,1,msg);
-        }
-        contextClientTmp->sendEvent(event);
-      }
-      else contextClientTmp->sendEvent(event);
-    }
-  }
 
   // void CDomain::computeConnectedClients(const std::vector<int>& globalDim, int orderPositionInGrid,
@@ -1507,4 +1464,5 @@
   {
     CContext* context=CContext::getCurrent() ;
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -1512,15 +1470,34 @@
     {
       CContextClient* client = (0 != context->clientPrimServer.size()) ? context->clientPrimServer[p] : context->client;
-      int nbServer=client->serverSize;
-      int rank = client->clientRank;
+      int nbServer = client->serverSize;
+      int rank     = client->clientRank;
       bool doComputeGlobalIndexServer = true;
 
       int i,j,i_ind,j_ind, nbIndex, nbIndexZoom;
-      int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1 ;
-      int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1 ;
+      int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
+      int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
 
       // Precompute number of index
       int globalIndexCountZoom = 0;
       nbIndex = i_index.numElements();
+
+      if (doZoomByIndex_) 
+      {
+        globalIndexCountZoom = zoom_i_index.numElements();
+      }
+      else 
+      {
+        for (i = 0; i < nbIndex; ++i)
+        {
+          i_ind=i_index(i);
+          j_ind=j_index(i);
+
+          if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
+          {
+            ++globalIndexCountZoom;
+          }
+        }
+      }
+
       // for (i = 0; i < nbIndex; ++i)
       // {
@@ -1554,4 +1531,5 @@
       // Fill in index
 
+      CArray<size_t,1> globalIndexDomainZoom(globalIndexCountZoom);
       CArray<size_t,1> localIndexDomainZoom(globalIndexCountZoom);
       CArray<size_t,1> globalIndexDomain(nbIndex);
@@ -1559,5 +1537,4 @@
       int globalIndexCount = 0;
 
-
       for (i = 0; i < nbIndex; ++i)
       {
@@ -1565,27 +1542,61 @@
         j_ind=j_index(i);
         globalIndex = i_ind + j_ind * ni_glo;
-        globalIndexDomain(globalIndexCount) = globalIndex;
-        globalLocalIndexMap_[globalIndex] = i;
-        ++globalIndexCount;
-      }
-
-      nbIndexZoom = zoom_i_index.numElements();
-      CArray<size_t,1> globalIndexDomainZoom(nbIndexZoom);
+        globalIndexDomain(i) = globalIndex;                
+      }
+
+      if (globalLocalIndexMap_.empty())
+      {
+        for (i = 0; i < nbIndex; ++i)
+          globalLocalIndexMap_[globalIndexDomain(i)] = i;
+
+      }
+
       globalIndexCountZoom = 0;
-      for (i = 0; i < nbIndexZoom; ++i)
-      {
-        i_ind=zoom_i_index(i);
-        j_ind=zoom_j_index(i);
-        globalIndex = i_ind + j_ind * ni_glo;
-        globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
-
-        ++globalIndexCountZoom;
-        // if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
-        // {
-        //   globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
-        //   localIndexDomainZoom(globalIndexCountZoom) = i;
-        //   ++globalIndexCountZoom;
-        // }
-      }
+      if (doZoomByIndex_) 
+      {
+        int nbIndexZoom = zoom_i_index.numElements();        
+        
+        for (i = 0; i < nbIndexZoom; ++i)
+        {
+          i_ind=zoom_i_index(i);
+          j_ind=zoom_j_index(i);
+          globalIndex = i_ind + j_ind * ni_glo;
+          globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
+          ++globalIndexCountZoom;
+          // if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
+          // {
+          //   globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
+          //   localIndexDomainZoom(globalIndexCountZoom) = i;
+          //   ++globalIndexCountZoom;
+          // }
+        }
+      }
+      else 
+      {
+          int global_zoom_iend=global_zoom_ibegin+global_zoom_ni-1;
+          int global_zoom_jend=global_zoom_jbegin+global_zoom_nj-1;
+          for (i = 0; i < nbIndex; ++i)
+          {
+            i_ind=i_index(i);
+            j_ind=j_index(i);
+            globalIndex = i_ind + j_ind * ni_glo;
+            if (i_ind >= global_zoom_ibegin && i_ind <= global_zoom_iend && j_ind >= global_zoom_jbegin && j_ind <= global_zoom_jend)
+            {
+              globalIndexDomainZoom(globalIndexCountZoom) = globalIndex;
+              ++globalIndexCountZoom;
+            }
+          }
+
+          int iend = ibegin + ni -1;
+          int jend = jbegin + nj -1;
+          zoom_ibegin = global_zoom_ibegin > ibegin ? global_zoom_ibegin : ibegin;
+          int zoom_iend   = global_zoom_iend < iend ? zoom_iend : iend ;
+          zoom_ni     = zoom_iend-zoom_ibegin+1 ;
+
+          zoom_jbegin = global_zoom_jbegin > jbegin ? global_zoom_jbegin : jbegin ;
+          int zoom_jend   = global_zoom_jend < jend ? zoom_jend : jend;
+          zoom_nj     = zoom_jend-zoom_jbegin+1;
+      }
+
 
       // CArray<int,1> globalIndexWrittenDomain(globalIndexWrittenCount);
@@ -1679,10 +1690,10 @@
       for (it = globalIndexDomainOnServer.begin(); it != ite; ++it) {
         connectedServerRank_.push_back(it->first);
-        std::vector<size_t> vec = it->second;
-        std::sort(vec.begin(), vec.end());
-        indSrv_[it->first] = vec;
-      }
-
-//      indSrv_.swap(globalIndexDomainOnServer);
+        // std::vector<size_t> vec = it->second;
+        // std::sort(vec.begin(), vec.end());
+        // indSrv_[it->first] = vec;
+      }
+
+      indSrv_.swap(globalIndexDomainOnServer);
       nbConnectedClients_ = clientServerMap->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
 
@@ -1690,5 +1701,5 @@
       CClientServerMapping::GlobalIndexMap& globalIndexDomainZoomOnServer = clientServerMap->getGlobalIndexOnServer();
 //      indZoomSrv_.swap(globalIndexDomainZoomOnServer);
-      std::vector<int> connectedServerZoomRank(indZoomSrv_.size());
+      std::vector<int> connectedServerZoomRank; //(indZoomSrv_.size());
 //      for (it = indZoomSrv_.begin(); it != indZoomSrv_.end(); ++it)
 //        connectedServerZoomRank.push_back(it->first);
@@ -1719,4 +1730,5 @@
     sendDistributionAttributes();
     sendIndex();
+    sendIndex();    
     sendMask();
     sendLonLat();
@@ -1733,4 +1745,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -1776,6 +1789,10 @@
         list_msgsIndex.back() << this->getId() << (int)type; // enum ne fonctionne pour les message => ToFix
         list_msgsIndex.back() << isCurvilinear;
-        list_msgsIndex.back() << list_indGlob.back() << list_indZoom.back(); //list_indi.back() << list_indj.back();
-
+        list_msgsIndex.back() << list_indGlob.back() << list_indZoom.back() << doZoomByIndex_; //list_indi.back() << list_indj.back();
+        if (!doZoomByIndex_) 
+        {
+          //list_msgsIndex.back() << zoom_ni.getValue() << zoom_ibegin.getValue() << zoom_nj.getValue() << zoom_jbegin.getValue();
+        }
+       
         // if (isCompressible_)
         // {
@@ -1798,4 +1815,60 @@
 
   /*!
+    Send distribution from client to other clients
+    Because a client in a level knows correctly the grid distribution of client on the next level
+    it calculates this distribution then sends it to the corresponding clients on the next level
+  */
+  void CDomain::sendDistributionAttributes(void)
+  {
+    CContext* context = CContext::getCurrent();
+     // Use correct context client to send message
+    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
+    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
+    for (int i = 0; i < nbSrvPools; ++i)
+    {
+      CContextClient* contextClientTmp = (context->hasServer) ? context->clientPrimServer[i]
+                                                                         : context->client;    
+      int nbServer = contextClientTmp->serverSize;
+      std::vector<int> nGlobDomain(2);
+      nGlobDomain[0] = this->ni_glo;
+      nGlobDomain[1] = this->nj_glo;
+
+      CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
+      if (isUnstructed_) serverDescription.computeServerDistribution(false, 0);
+      else serverDescription.computeServerDistribution(false, 1);
+
+      std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
+      std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
+
+      CEventClient event(getType(),EVENT_ID_SERVER_ATTRIBUT);
+      if (contextClientTmp->isServerLeader())
+      {
+        std::list<CMessage> msgs;
+
+        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
+        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+        {
+          // Use const int to ensure CMessage holds a copy of the value instead of just a reference
+          const int ibegin_srv = serverIndexBegin[*itRank][0];
+          const int jbegin_srv = serverIndexBegin[*itRank][1];
+          const int ni_srv = serverDimensionSizes[*itRank][0];
+          const int nj_srv = serverDimensionSizes[*itRank][1];
+
+          msgs.push_back(CMessage());
+          CMessage& msg = msgs.back();
+          msg << this->getId() ;
+          msg << ni_srv << ibegin_srv << nj_srv << jbegin_srv;
+          msg << global_zoom_ni.getValue() << global_zoom_ibegin.getValue() << global_zoom_nj.getValue() << global_zoom_jbegin.getValue();        
+          msg << isCompressible_;
+
+          event.push(*itRank,1,msg);
+        }
+        contextClientTmp->sendEvent(event);
+      }
+      else contextClientTmp->sendEvent(event);
+    }
+  }
+
+  /*!
     Send mask index from client to connected(s)
   */
@@ -1804,4 +1877,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -1851,4 +1925,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -1901,4 +1976,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -1986,4 +2062,5 @@
     int ns, n, i, j, ind, nv, idx;
     CContext* context = CContext::getCurrent();
+
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
@@ -2085,32 +2162,4 @@
 
   /*!
-    Receive attributes event from clients(s)
-    \param[in] event event contain info about rank and associated attributes
-  */
-  void CDomain::recvDistributionAttributes(CEventServer& event)
-  {
-    CBufferIn* buffer=event.subEvents.begin()->buffer;
-    string domainId ;
-    *buffer>>domainId ;
-    get(domainId)->recvDistributionAttributes(*buffer) ;
-  }
-
-  /*!
-    Receive attributes from client(s): zoom info and begin and n of each server
-    \param[in] rank rank of client source
-    \param[in] buffer message containing attributes info
-  */
-  void CDomain::recvDistributionAttributes(CBufferIn& buffer)
-  {
-    int ni_tmp, ibegin_tmp, nj_tmp, jbegin_tmp;
-    buffer >> ni_tmp >> ibegin_tmp >> nj_tmp >> jbegin_tmp           
-           >> isCompressible_;
-    ni.setValue(ni_tmp);
-    ibegin.setValue(ibegin_tmp);
-    nj.setValue(nj_tmp);
-    jbegin.setValue(jbegin_tmp);
-  }
-
-  /*!
     Receive index event from clients(s)
     \param[in] event event contain info about rank and associated index
@@ -2151,4 +2200,5 @@
     recvClientRanks_.resize(nbReceived);
     vector<CArray<int,1> > recvZoomInd(nbReceived);
+    int ni_zoom_tmp, ibegin_zoom_tmp, nj_zoom_tmp, jbegin_zoom_tmp;
 
     std::map<int, CBufferIn*>::iterator it = rankBuffers.begin(), ite = rankBuffers.end();
@@ -2158,5 +2208,9 @@
        recvClientRanks_[ind] = it->first;
        CBufferIn& buffer = *(it->second);
-       buffer >> type_int >> isCurvilinear >> indGlob_[it->first] >> recvZoomInd[ind]; //recvIndGlob[ind];
+       buffer >> type_int >> isCurvilinear >> indGlob_[it->first] >> recvZoomInd[ind] >> doZoomByIndex_; 
+       if (!doZoomByIndex_)
+       {
+        //buffer >> ni_zoom_tmp >> ibegin_zoom_tmp >> nj_zoom_tmp >> jbegin_zoom_tmp;
+       }
        type.setValue((type_attr::t_enum)type_int); // probleme des type enum avec les buffers : ToFix
     }
@@ -2189,88 +2243,113 @@
     }
 
-    zoom_i_index.resize(nbZoomInd);
-    zoom_j_index.resize(nbZoomInd);
+    if (doZoomByIndex_)
+    {
+      zoom_i_index.resize(nbZoomInd);
+      zoom_j_index.resize(nbZoomInd);
+      
+      nbZoomInd = 0;
+      for (i = 0; i < nbReceived; ++i)
+      {
+        CArray<int,1>& tmp = recvZoomInd[i];
+        for (ind = 0; ind < tmp.numElements(); ++ind)
+        {
+           index = tmp(ind);
+           zoom_i_index(nbZoomInd) = index % ni_glo;
+           zoom_j_index(nbZoomInd) = index / ni_glo;
+           ++nbZoomInd;
+        } 
+      }      
+    }
+    else 
+    {
+      // zoom_ni.setValue(ni_zoom_tmp);
+      // zoom_ibegin.setValue(ibegin_zoom_tmp);
+      // zoom_nj.setValue(nj_zoom_tmp);
+      // zoom_jbegin.setValue(jbegin_zoom_tmp);
+      // int nbZoom = ni_zoom_tmp * nj_zoom_tmp;
+      // zoom_i_index.resize(nbZoom);
+      // zoom_j_index.resize(nbZoom);
+      // nbZoom = 0;
+      // for (int j = 0; j < nj_zoom_tmp; ++j) 
+      //   for (int i = 0; i < ni_zoom_tmp; ++i)
+      //   {
+      //     zoom_i_index(nbZoom) = ibegin_zoom_tmp + i;
+      //     zoom_j_index(nbZoom) = jbegin_zoom_tmp + j;
+      //     ++nbZoom;
+      //   }
+    }
+
+    globalLocalIndexMap_.rehash(std::ceil(nbIndGlob/globalLocalIndexMap_.max_load_factor()));
+    nbIndGlob = 0;
+    for (int j = 0; j < nj; ++j) 
+      for (int i = 0; i < ni; ++i)
+      {
+        globalLocalIndexMap_[(i + ibegin) + (j + jbegin) * ni_glo] = nbIndGlob;
+        ++nbIndGlob;
+      }
+
+
     
-    nbZoomInd = 0;
-    for (i = 0; i < nbReceived; ++i)
-    {
-      CArray<int,1>& tmp = recvZoomInd[i];
-      for (ind = 0; ind < tmp.numElements(); ++ind)
-      {
-         index = tmp(ind);
-         zoom_i_index(nbZoomInd) = index % ni_glo;
-         zoom_j_index(nbZoomInd) = index / ni_glo;
-         ++nbZoomInd;
-      } 
-    }    
-
-    {
-      CContextServer* server = CContext::getCurrent()->server;
-      count_write_index_.resize(2);
-      start_write_index_.resize(2);
-      local_write_size_.resize(2);
-      global_write_size_.resize(2);
-      if ((this->type) == CDomain::type_attr::unstructured)
-      {
-        count_write_index_[0] = zoom_i_index.numElements();
-        count_write_index_[1] = 0;
-      }
-      else
-      {
-        int ni_zoom = zoom_i_index.numElements(), idx, nbIZoom = 0, nbJZoom = 0;
-        for (idx =0; idx < ni_zoom; ++idx)
-        {
-          if ((ibegin <= zoom_i_index(idx)) && (zoom_i_index(idx) < ibegin+ni) && (nbIZoom < ni))
-            ++nbIZoom;
-          if ((jbegin <= zoom_j_index(idx)) && (zoom_j_index(idx) < jbegin+nj) && (nbJZoom < nj))
-            ++nbJZoom;
-        }
-        count_write_index_[0] = nbIZoom;
-        count_write_index_[1] = nbJZoom;
-
-        // Reoder the zoom_index
-        for (int j = 0; j < nbJZoom; ++j)
-          for (int i = 0; i < nbIZoom; ++i)
-          {
-            idx = nbIZoom * j + i;
-            if (idx < ni_zoom)
-            {
-              zoom_i_index(idx) = ibegin + i;
-              zoom_j_index(idx) = jbegin + j;
-            }
-          }  
-
-        // Reorder the global index
-        for (int j = 0; j < nj; ++j)
-          for (int i = 0; i < ni; ++i)
-          {
-            idx = ni * j + i;
-            if (idx < nbIndGlob)
-            {
-              i_index(idx) = ibegin + i;
-              j_index(idx) = jbegin + j;
-            }
-          }         
-      }
+    // {
+    //   CContextServer* server = CContext::getCurrent()->server;
+    //   count_write_index_.resize(2);
+    //   start_write_index_.resize(2);
+    //   local_write_size_.resize(2);
+    //   global_write_size_.resize(2);
+    //   if ((this->type) == CDomain::type_attr::unstructured)
+    //   {
+    //     count_write_index_[0] = zoom_i_index.numElements();
+    //     count_write_index_[1] = 0;
+    //   }
+    //   else
+    //   {
+    //     int ni_zoom = zoom_i_index.numElements(), idx, nbIZoom = 0, nbJZoom = 0;
+    //     for (idx =0; idx < ni_zoom; ++idx)
+    //     {
+    //        if ((ibegin <= zoom_i_index(idx)) && (zoom_i_index(idx) < ibegin+ni) && (nbIZoom < ni))
+    //         ++nbIZoom;
+    //        if ((jbegin <= zoom_j_index(idx)) && (zoom_j_index(idx) < jbegin+nj) && (nbJZoom < nj))
+    //         ++nbJZoom;
+    //     }
+    //     count_write_index_[0] = nbIZoom;
+    //     count_write_index_[1] = nbJZoom;
+
+    //     // Reoder the zoom_index
+    //     for (int j = 0; j < nbJZoom; ++j)
+    //       for (int i = 0; i < nbIZoom; ++i)
+    //       {
+    //         idx = nbIZoom * j + i;
+    //         if (idx < ni_zoom)
+    //         {
+    //           zoom_i_index(idx) = ibegin + i;
+    //           zoom_j_index(idx) = jbegin + j;
+    //         }
+    //       }  
+
+    //     // Reorder the global index
+    //     for (int j = 0; j < nj; ++j)
+    //       for (int i = 0; i < ni; ++i)
+    //       {
+    //         idx = ni * j + i;
+    //         if (idx < nbIndGlob)
+    //         {
+    //           i_index(idx) = ibegin + i;
+    //           j_index(idx) = jbegin + j;
+    //         }
+    //       }         
+    //   }
+
             
-      MPI_Scan(&count_write_index_[0], &start_write_index_[0], 2, MPI_INT, MPI_SUM, server->intraComm);
-      if ((this->type) != CDomain::type_attr::unstructured)
-      {
-        start_write_index_[0] = 0;
-        start_write_index_[1] -= count_write_index_[1];
-      }
-      else
-      {
-        start_write_index_[0] -= count_write_index_[0];
-      }
-      local_write_size_[0] = count_write_index_[0];
-      local_write_size_[1] = count_write_index_[1];
-      MPI_Allreduce(&count_write_index_[0], &global_write_size_[0], 2, MPI_INT, MPI_SUM, server->intraComm);
-      if ((this->type) != CDomain::type_attr::unstructured)
-      {
-        global_write_size_[0] = count_write_index_[0];
-        global_write_size_[1] = (global_write_size_[1] > nj_glo) ? nj_glo : global_write_size_[1];
-      }
-    }
+    //   MPI_Scan(&count_write_index_[0], &start_write_index_[0], 2, MPI_INT, MPI_SUM, server->intraComm);      
+    //   start_write_index_[0] = 0; 
+    //   start_write_index_[1] -= count_write_index_[1];
+    //   local_write_size_[0] = count_write_index_[0];
+    //   local_write_size_[1] = count_write_index_[1];
+    //   MPI_Allreduce(&count_write_index_[0], &global_write_size_[0], 2, MPI_INT, MPI_SUM, server->intraComm);
+    //   global_write_size_[0] = count_write_index_[0];
+    //   global_write_size_[1] = (global_write_size_[1] > nj_glo) ? nj_glo : global_write_size_[1];
+         
+
+    // }
 
     // int type_int;
@@ -2289,4 +2368,59 @@
 
   /*!
+    Receive attributes event from clients(s)
+    \param[in] event event contain info about rank and associated attributes
+  */
+  void CDomain::recvDistributionAttributes(CEventServer& event)
+  {
+    CBufferIn* buffer=event.subEvents.begin()->buffer;
+    string domainId ;
+    *buffer>>domainId ;
+    get(domainId)->recvDistributionAttributes(*buffer);
+  }
+
+  /*!
+    Receive attributes from client(s): zoom info and begin and n of each server
+    \param[in] rank rank of client source
+    \param[in] buffer message containing attributes info
+  */
+  void CDomain::recvDistributionAttributes(CBufferIn& buffer)
+  {
+    int ni_tmp, ibegin_tmp, nj_tmp, jbegin_tmp;
+    int global_zoom_ni_tmp, global_zoom_ibegin_tmp, global_zoom_nj_tmp, global_zoom_jbegin_tmp;
+    buffer >> ni_tmp >> ibegin_tmp >> nj_tmp >> jbegin_tmp
+           >> global_zoom_ni_tmp >> global_zoom_ibegin_tmp >> global_zoom_nj_tmp >> global_zoom_jbegin_tmp           
+           >> isCompressible_;
+    ni.setValue(ni_tmp);
+    ibegin.setValue(ibegin_tmp);
+    nj.setValue(nj_tmp);
+    jbegin.setValue(jbegin_tmp);
+
+    global_zoom_ni.setValue(global_zoom_ni_tmp);
+    global_zoom_ibegin.setValue(global_zoom_ibegin_tmp);
+    global_zoom_nj.setValue(global_zoom_nj_tmp);
+    global_zoom_jbegin.setValue(global_zoom_jbegin_tmp);
+
+    int iend = ibegin + ni  - 1;
+    int jend = jbegin + nj  - 1;
+    int zoom_iend_glob = global_zoom_ibegin + global_zoom_ni - 1;
+    int zoom_jend_glob = global_zoom_jbegin + global_zoom_nj - 1;
+
+    zoom_ibegin.setValue(global_zoom_ibegin > ibegin ? global_zoom_ibegin : ibegin);
+    int zoom_iend = zoom_iend_glob < iend ? zoom_iend_glob : iend ;
+    zoom_ni.setValue(zoom_iend-zoom_ibegin+1);
+
+    zoom_jbegin.setValue(global_zoom_jbegin > jbegin ? global_zoom_jbegin : jbegin);
+    int zoom_jend = zoom_jend_glob < jend ? zoom_jend_glob : jend ;
+    zoom_nj.setValue(zoom_jend-zoom_jbegin+1);
+
+    if (zoom_ni<=0 || zoom_nj<=0)
+    {
+      zoom_ibegin=0 ; zoom_iend=0 ; zoom_ni=0 ;
+      zoom_jbegin=0 ; zoom_jend=0 ; zoom_nj=0 ;
+    }
+
+  }
+
+  /*!
     Receive area event from clients(s)
     \param[in] event event contain info about rank and associated area
@@ -2372,5 +2506,5 @@
   void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)
   {
-    int nbReceived = rankBuffers.size(), i, ind, index;
+    int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex;
     if (nbReceived != recvClientRanks_.size())
       ERROR("void CDomain::recvLon(std::map<int, CBufferIn*>& rankBuffers)",
@@ -2391,30 +2525,27 @@
     }
 
-    int nbLonInd = 0;
+    lonvalue.resize(zoom_ni*zoom_nj);
+    lonvalue = 0;
+
+    if (hasBounds)
+    {
+      bounds_lonvalue.resize(nvertex,zoom_ni*zoom_nj);
+      bounds_lonvalue = 0.;
+    }
+    
     for (i = 0; i < nbReceived; ++i)
     {
-      nbLonInd += recvLonValue[i].numElements();
-    }
-
-    lonvalue.resize(nbLonInd);
-    if (hasBounds)
-    {
-      bounds_lonvalue.resize(nvertex, nbLonInd);
-    }
-
-    nbLonInd = 0;
-    for (i = 0; i < nbReceived; ++i)
-    {
-      CArray<double,1>& tmp = recvLonValue[i];
-      for (ind = 0; ind < tmp.numElements(); ++ind)
-      {
-         lonvalue(nbLonInd) = tmp(ind);
+      int rank = recvClientRanks_[i];
+      CArray<int,1> &indi = indGlob_[rank], &indj = indGlob_[rank];      
+      for (ind = 0; ind < indi.numElements(); ++ind)
+      {
+         iindex = indi(ind) % ni_glo; jindex = indj(ind) / ni_glo;
+         index = (iindex - zoom_ibegin) + (jindex - zoom_jbegin) * zoom_ni;
+         lonvalue(index) = recvLonValue[i](ind);
          if (hasBounds)
-         {
-          CArray<double,2>& tmpBnds = recvBoundsLonValue[i];
+         {          
           for (int nv = 0; nv < nvertex; ++nv)
-            bounds_lonvalue(nv, nbLonInd) = tmpBnds(nv, ind);
-         }       
-         ++nbLonInd;
+            bounds_lonvalue(nv, index) = recvBoundsLonValue[i](nv, ind);
+         }         
       }
     }
@@ -2446,5 +2577,5 @@
   void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)
   {
-    int nbReceived = rankBuffers.size(), i, ind, index;
+    int nbReceived = rankBuffers.size(), i, ind, index, iindex, jindex;
     if (nbReceived != recvClientRanks_.size())
       ERROR("void CDomain::recvLat(std::map<int, CBufferIn*>& rankBuffers)",
@@ -2465,30 +2596,29 @@
     }
 
-    int nbLatInd = 0;
+    latvalue.resize(zoom_ni*zoom_nj);
+    latvalue = 0;
+
+    if (hasBounds)
+    {
+      bounds_latvalue.resize(nvertex,zoom_ni*zoom_nj);
+      bounds_latvalue = 0. ;
+    }
+    
     for (i = 0; i < nbReceived; ++i)
     {
-      nbLatInd += recvLatValue[i].numElements();
-    }
-
-    latvalue.resize(nbLatInd);
-    if (hasBounds)
-    {
-      bounds_latvalue.resize(nvertex, nbLatInd);
-    }
-    
-    nbLatInd = 0;
-    for (i = 0; i < nbReceived; ++i)
-    {
-      CArray<double,1>& tmp = recvLatValue[i];
-      for (ind = 0; ind < tmp.numElements(); ++ind)
-      {         
-         latvalue(nbLatInd) = tmp(ind);
+      int rank = recvClientRanks_[i];
+      CArray<int,1> &indi = indGlob_[rank], &indj = indGlob_[rank];
+      CArray<double,1>& lat = recvLatValue[i];
+      for (ind = 0; ind < indi.numElements(); ++ind)
+      {
+         iindex = indi(ind) % ni_glo; jindex = indj(ind) / ni_glo;
+         index = (iindex - zoom_ibegin) + (jindex - zoom_jbegin) * zoom_ni;
+         latvalue(index) = lat(ind);
          if (hasBounds)
          {
-          CArray<double,2>& tmpBnds = recvBoundsLatValue[i];
+          CArray<double,2>& boundslat = recvBoundsLatValue[i];
           for (int nv = 0; nv < nvertex; ++nv)
-            bounds_latvalue(nv, nbLatInd) = tmpBnds(nv, ind);
-         }       
-         ++nbLatInd;
+            bounds_latvalue(nv, index) = boundslat(nv, ind);
+         }         
       }
     }
Index: XIOS/dev/dev_olga/src/node/domain.hpp
===================================================================
--- XIOS/dev/dev_olga/src/node/domain.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/domain.hpp	(revision 1099)
@@ -201,4 +201,5 @@
          std::vector<int> global_write_size_;
 
+         bool doZoomByIndex_;
          bool isChecked;
          std::set<StdString> relFiles, relFilesCompressed;
Index: XIOS/dev/dev_olga/src/node/field.cpp
===================================================================
--- XIOS/dev/dev_olga/src/node/field.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/field.cpp	(revision 1099)
@@ -125,8 +125,7 @@
 //    CContextClient* client = context->client;
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
-//    int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
-//    for (int i = 0; i < nbSrvPools; ++i)
-//    {
-//      CContextClient* client = (!context->hasServer) ? context->client : context->clientPrimServer[i];
+    // int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
+    // for (int i = 0; i < nbSrvPools; ++i)
+    // {
       CContextClient* client = (!context->hasServer) ? context->client : this->file->getContextClient();
 
@@ -173,67 +172,66 @@
 
           list_msg.back() << getId() << data_tmp;
-          event.push(rank, grid->nbSenders[rank], list_msg.back());
+          event.push(rank, grid->nbSenders[0][rank], list_msg.back());
         }
         client->sendEvent(event);
       }
-//    }
+    // }
 
     CTimer::get("XIOS Send Data").suspend();
   }
 
-/*
-  void CField::sendUpdateData(const CArray<double,1>& data, CContextClient* client)
-  {
-    CTimer::get("XIOS Send Data").resume();
-
-    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
-
-    map<int, CArray<int,1> >::iterator it;
-    list<CMessage> list_msg;
-    list<CArray<double,1> > list_data;
-
-    if (!grid->doGridHaveDataDistributed())
-    {
-       if (client->isServerLeader())
-       {
-          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
-          {
-            int rank = it->first;
-            CArray<int,1>& index = it->second;
-
-            list_msg.push_back(CMessage());
-            list_data.push_back(CArray<double,1>(index.numElements()));
-
-            CArray<double,1>& data_tmp = list_data.back();
-            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
-
-            list_msg.back() << getId() << data_tmp;
-            event.push(rank, 1, list_msg.back());
-          }
-          client->sendEvent(event);
-       }
-       else client->sendEvent(event);
-    }
-    else
-    {
-      for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
-      {
-        int rank = it->first;
-        CArray<int,1>& index = it->second;
-
-        list_msg.push_back(CMessage());
-        list_data.push_back(CArray<double,1>(index.numElements()));
-
-        CArray<double,1>& data_tmp = list_data.back();
-        for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
-
-        list_msg.back() << getId() << data_tmp;
-        event.push(rank, grid->nbSenders[rank], list_msg.back());
-      }
-      client->sendEvent(event);
-    }
-    CTimer::get("XIOS Send Data").suspend();
-  }
-*/
+  // void CField::sendUpdateData(const CArray<double,1>& data, CContextClient* client)
+  // {
+  //   CTimer::get("XIOS Send Data").resume();
+
+  //   CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
+
+  //   map<int, CArray<int,1> >::iterator it;
+  //   list<CMessage> list_msg;
+  //   list<CArray<double,1> > list_data;
+
+  //   if (!grid->doGridHaveDataDistributed())
+  //   {
+  //      if (client->isServerLeader())
+  //      {
+  //         for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
+  //         {
+  //           int rank = it->first;
+  //           CArray<int,1>& index = it->second;
+
+  //           list_msg.push_back(CMessage());
+  //           list_data.push_back(CArray<double,1>(index.numElements()));
+
+  //           CArray<double,1>& data_tmp = list_data.back();
+  //           for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
+
+  //           list_msg.back() << getId() << data_tmp;
+  //           event.push(rank, 1, list_msg.back());
+  //         }
+  //         client->sendEvent(event);
+  //      }
+  //      else client->sendEvent(event);
+  //   }
+  //   else
+  //   {
+  //     for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
+  //     {
+  //       int rank = it->first;
+  //       CArray<int,1>& index = it->second;
+
+  //       list_msg.push_back(CMessage());
+  //       list_data.push_back(CArray<double,1>(index.numElements()));
+
+  //       CArray<double,1>& data_tmp = list_data.back();
+  //       for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
+
+  //       list_msg.back() << getId() << data_tmp;
+  //       event.push(rank, grid->nbSenders[rank], list_msg.back());
+  //     }
+  //     client->sendEvent(event);
+  //   }
+  //   CTimer::get("XIOS Send Data").suspend();
+  // }
+
   void CField::recvUpdateData(CEventServer& event)
   {
@@ -263,4 +261,5 @@
       {
         sizeData += it->second.numElements();
+        data_srv.insert(std::make_pair(it->first, CArray<double,1>(it->second.numElements())));
       }
 
@@ -271,7 +270,7 @@
 
     CArray<double,1> recv_data_tmp(recvDataSrv.numElements());
-    sizeData = 0;
+    // sizeData = 0;
     const CDate& currDate = context->getCalendar()->getCurrentDate();
-    const CDate opeDate      = last_operation_srv +freq_op + freq_operation_srv - freq_op;
+    const CDate opeDate   = last_operation_srv +freq_op + freq_operation_srv - freq_op;
 
     if (opeDate <= currDate)
@@ -279,8 +278,13 @@
       for (map<int, CArray<size_t, 1> >::iterator it = grid->outIndexFromClient.begin(); it != grid->outIndexFromClient.end(); ++it)
       {        
-        CArray<double,1> tmp;       
+        CArray<double,1> tmp;
+        CArray<size_t,1>& indexTmp = it->second;
         *(rankBuffers[it->first]) >> tmp;
-        recv_data_tmp(Range(sizeData,sizeData+it->second.numElements()-1)) = tmp;  
-        sizeData += it->second.numElements();      
+        for (int idx = 0; idx < indexTmp.numElements(); ++idx)
+        {
+          recv_data_tmp(indexTmp(idx)) = tmp(idx);
+        }
+        // recv_data_tmp(Range(sizeData,sizeData+it->second.numElements()-1)) = tmp;  
+        // sizeData += it->second.numElements();      
       }
     }
@@ -525,5 +529,5 @@
         else
           msg << int(-1);
-        event.push(it->first, grid->nbSenders[it->first], msg);
+        event.push(it->first, grid->nbSenders[0][it->first], msg);
       }
       client->sendEvent(event);
@@ -924,5 +928,5 @@
    }
 
-   std::map<int, StdSize> CField::getGridDataBufferSize()
+   std::vector<std::map<int, StdSize> > CField::getGridDataBufferSize()
    {
      return grid->getDataBufferSize(getId());
@@ -1424,11 +1428,13 @@
    void CField::outputField(CArray<double,1>& fieldOut)
    {
-      // map<int, CArray<double,1> >::iterator it;
-
+      map<int, CArray<double,1> >::iterator it;
+      
+      fieldOut = recvDataSrv;
+      
       // for (it = data_srv.begin(); it != data_srv.end(); it++)
       // {
       //    grid->outputField(it->first, it->second, fieldOut.dataFirst());
       // }
-    grid->outputField(recvDataSrv, fieldOut);
+    // grid->outputField(recvDataSrv, fieldOut);
    }
 
Index: XIOS/dev/dev_olga/src/node/field.hpp
===================================================================
--- XIOS/dev/dev_olga/src/node/field.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/field.hpp	(revision 1099)
@@ -96,5 +96,5 @@
 
          std::map<int, StdSize> getGridAttributesBufferSize();
-         std::map<int, StdSize> getGridDataBufferSize();
+         std::vector<std::map<int, StdSize> > getGridDataBufferSize(); // Grid data buffer size for each connection of contextclient
 
        public:
@@ -146,5 +146,5 @@
         static bool dispatchEvent(CEventServer& event);
         void sendUpdateData(const CArray<double,1>& data);
-//        void sendUpdateData(const CArray<double,1>& data, CContextClient* client);
+        void sendUpdateData(const CArray<double,1>& data, CContextClient* client);
         static void recvUpdateData(CEventServer& event);
         void recvUpdateData(std::map<int,CBufferIn*>& rankBuffers);
Index: XIOS/dev/dev_olga/src/node/grid.cpp
===================================================================
--- XIOS/dev/dev_olga/src/node/grid.cpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/grid.cpp	(revision 1099)
@@ -96,4 +96,5 @@
     *
     * \return A map associating the server rank with its minimum buffer size.
+    * TODO: Refactor code
     */
    std::map<int, StdSize> CGrid::getAttributesBufferSize()
@@ -102,18 +103,22 @@
 
      // The grid indexes require a similar size as the actual data
-     std::map<int, StdSize> dataSizes = getDataBufferSize();
-     std::map<int, StdSize>::iterator it, itE = dataSizes.end();
-     for (it = dataSizes.begin(); it != itE; ++it)
+     std::vector<std::map<int, StdSize> > dataSizes = getDataBufferSize();
+     for (size_t i = 0; i < dataSizes.size(); ++i)
      {
-       it->second += 2 * sizeof(bool);
-       if (it->second > attributesSizes[it->first])
-         attributesSizes[it->first] = it->second;
+       std::map<int, StdSize>::iterator it, itE = dataSizes[i].end();
+       for (it = dataSizes[i].begin(); it != itE; ++it)
+       {
+         it->second += 2 * sizeof(bool);
+         if (it->second > attributesSizes[it->first])
+           attributesSizes[it->first] = it->second;
+       }
      }
 
+     std::map<int, StdSize>::iterator it, itE;
      // Account for the axis attributes
      std::vector<CAxis*> axisList = getAxis();
      for (size_t i = 0; i < axisList.size(); ++i)
      {
-       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();
+       std::map<int, StdSize> axisAttBuffSize = axisList[i]->getAttributesBufferSize();       
        for (it = axisAttBuffSize.begin(), itE = axisAttBuffSize.end(); it != itE; ++it)
        {
@@ -144,19 +149,23 @@
     * \return A map associating the server rank with its minimum buffer size.
     */
-   std::map<int, StdSize> CGrid::getDataBufferSize(const std::string& id /*= ""*/)
-   {
-     std::map<int, StdSize> dataSizes;
+   std::vector<std::map<int, StdSize> > CGrid::getDataBufferSize(const std::string& id /*= ""*/)
+   {     
      // The record index is sometimes sent along with the data but we always
      // include it in the size calculation for the sake of simplicity
      const size_t extraSize = CEventClient::headerSize + (id.empty() ? getId() : id).size() + 2 * sizeof(size_t);
-
-     std::map<int, size_t>::const_iterator itEnd = connectedDataSize_.end();
-     for (size_t k = 0; k < connectedServerRank_.size(); ++k)
+     CContext* context = CContext::getCurrent();
+     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
+     std::vector<std::map<int, StdSize> > dataSizes(nbSrvPools);
+     for (int p = 0; p < nbSrvPools; ++p) 
      {
-       int rank = connectedServerRank_[k];
-       std::map<int, size_t>::const_iterator it = connectedDataSize_.find(rank);
-       size_t count = (it != itEnd) ? it->second : 0;
-
-       dataSizes.insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
+       std::map<int, size_t>::const_iterator itEnd = connectedDataSize_[p].end();
+       for (size_t k = 0; k < connectedServerRank_[p].size(); ++k) // TODO: Should change connectedServerRank_[0] to something more general
+       {
+         int rank = connectedServerRank_[p][k];
+         std::map<int, size_t>::const_iterator it = connectedDataSize_[0].find(rank);
+         size_t count = (it != itEnd) ? it->second : 0;
+
+         dataSizes[p].insert(std::make_pair(rank, extraSize + CArray<double,1>::size(count)));
+       }
      }
 
@@ -276,5 +285,5 @@
      int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;   
      nbSrvPools = 1;  
-     for (int i = 0; i < nbSrvPools; ++i)
+     for (int p = 0; p < nbSrvPools; ++p)
      {       
        if (isScalarGrid())
@@ -304,5 +313,7 @@
      if (this->isChecked) return;
      this->checkAttributesAfterTransformation();
-     this->checkMask();
+
+     // TODO: Transfer grid attributes
+     if (!context->hasClient && context->hasServer) this->createMask();
      this->computeIndex();
 
@@ -506,8 +517,7 @@
      // It works only for the same number of procs on secondary pools
      int nbSrvPools = 1; 
-
-     for (int i = 0; i < nbSrvPools; ++i)
+     for (int p = 0; p < nbSrvPools; ++p)
      {
-       CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[i] : context->client) : context->client;
+       CContextClient* client = (context->hasServer) ? (context->hasClient ? context->clientPrimServer[p] : context->client) : context->client;
        // CContextClient* client = (context->hasServer) ? context->clientPrimServer[i] : context->client;
        // CContextServer* server = (context->hasServer) ? context->server : 0 ;
@@ -517,12 +527,19 @@
        // First of all, compute distribution on client side
        if (0 != serverDistribution_)
+       {
          clientDistribution_ = new CDistributionClient(rank, this, serverDistribution_->getGlobalLocalIndex());
+         storeIndex_client.resize(serverDistribution_->getGridSize());
+         int nbStoreIndex = storeIndex_client.numElements();
+         for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = idx;
+       }
        else
+       {
          clientDistribution_ = new CDistributionClient(rank, this);
-
-       // Get local data index on client
-       storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
-       int nbStoreIndex = storeIndex_client.numElements();
-       for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
+         // Get local data index on client
+         storeIndex_client.resize(clientDistribution_->getLocalDataIndexOnClient().size());
+         int nbStoreIndex = storeIndex_client.numElements();
+         for (int idx = 0; idx < nbStoreIndex; ++idx) storeIndex_client(idx) = (clientDistribution_->getLocalDataIndexOnClient())[idx];
+       }
+     
        if (0 == serverDistribution_) 
         isDataDistributed_= clientDistribution_->isDataDistributed();
@@ -535,10 +552,13 @@
      // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
      int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
-     // int nbSrvPools = 1;
-     for (int i = 0; i < nbSrvPools; ++i)
+     connectedServerRank_.resize(nbSrvPools);
+     connectedDataSize_.resize(nbSrvPools);
+     nbSenders.resize(nbSrvPools);
+
+     for (int p = 0; p < nbSrvPools; ++p)
      {
-       CContextClient* client = (context->hasServer) ? context->clientPrimServer[i] : context->client;
-
-       connectedServerRank_.clear();
+       CContextClient* client = (context->hasServer) ? context->clientPrimServer[p] : context->client;
+
+       connectedServerRank_[p].clear();
 
        if (!doGridHaveDataDistributed())
@@ -550,6 +570,6 @@
             for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
             {
-              connectedServerRank_.push_back(*itRank);
-              connectedDataSize_[*itRank] = ssize;
+              connectedServerRank_[p].push_back(*itRank);
+              connectedDataSize_[p][*itRank] = ssize;
             }
           }
@@ -583,8 +603,8 @@
             if (iteGlobalLocalIndexMap != itGlobalLocalIndexMap)
             {
-               if (connectedDataSize_.end() == connectedDataSize_.find(serverRank))
-                 connectedDataSize_[serverRank] = 1;
+               if (connectedDataSize_[p].end() == connectedDataSize_[p].find(serverRank))
+                 connectedDataSize_[p][serverRank] = 1;
                else
-                 ++connectedDataSize_[serverRank];
+                 ++connectedDataSize_[p][serverRank];
             }
          }
@@ -592,8 +612,8 @@
 
        for (itGlobalMap = itbGlobalMap; itGlobalMap != iteGlobalMap; ++itGlobalMap) {
-         connectedServerRank_.push_back(itGlobalMap->first);
+         connectedServerRank_[p].push_back(itGlobalMap->first);
        }
 
-       nbSenders = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_);
+       nbSenders[p] = clientServerMap_->computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, connectedServerRank_[p]);
      }
    }
@@ -626,4 +646,5 @@
      // isDataDistributed_= clientDistribution_->isDataDistributed();
 
+
      // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
 
@@ -633,5 +654,4 @@
        computeConnectedClients();
      }
-
 
      // connectedServerRank_.clear();
@@ -708,7 +728,7 @@
      int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
      nbSrvPools = 1;
-     for (int i = 0; i < nbSrvPools; ++i)
+     for (int p = 0; p < nbSrvPools; ++p)
      {
-       CContextClient* client = context->hasServer ? context->clientPrimServer[i] : context->client;
+       CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
        int serverSize = client->serverSize;
        std::vector<CDomain*> domList = getDomains();
@@ -1139,12 +1159,16 @@
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
-    for (int i = 0; i < nbSrvPools; ++i)
-    {
-      CContextClient* client = context->hasServer ? context->clientPrimServer[i] : context->client;
+    connectedServerRank_.resize(nbSrvPools);
+    connectedDataSize_.resize(nbSrvPools);
+    nbSenders.resize(nbSrvPools);
+
+    for (int p = 0; p < nbSrvPools; ++p)
+    {
+      CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
 
       storeIndex_client.resize(1);
       storeIndex_client(0) = 0;
 
-      connectedServerRank_.clear();
+      connectedServerRank_[p].clear();
 
       if (0 == client->clientRank)
@@ -1152,7 +1176,7 @@
         for (int rank = 0; rank < client->serverSize; ++rank)
         {
-          connectedServerRank_.push_back(rank);
-          connectedDataSize_[rank] = 1;
-          nbSenders[rank] = 1;
+          connectedServerRank_[p].push_back(rank);
+          connectedDataSize_[p][rank] = 1;
+          nbSenders[p][rank] = 1;
         }
       }
@@ -1200,7 +1224,7 @@
     // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 0) : 1;
-    for (int i = 0; i < nbSrvPools; ++i)
-    {
-      CContextClient* client = context->hasServer ? context->clientPrimServer[i] : context->client;
+    for (int p = 0; p < nbSrvPools; ++p)
+    {
+      CContextClient* client = context->hasServer ? context->clientPrimServer[p] : context->client;
 
       CEventClient event(getType(), EVENT_ID_INDEX);
@@ -1257,6 +1281,4 @@
   {
     CContext* context = CContext::getCurrent();
-//    CContextClient* client = context->client;
-    // int nbSrvPools = (context->hasServer) ? context->clientPrimServer.size() : 1;
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
     for (int p = 0; p < nbSrvPools; ++p)
@@ -1368,7 +1390,7 @@
         }
 
-        for (int ns = 0; ns < connectedServerRank_.size(); ++ns)
+        for (int ns = 0; ns < connectedServerRank_[p].size(); ++ns)
         {
-          rank = connectedServerRank_[ns];
+          rank = connectedServerRank_[p][ns];
           int nb = 0;
           if (globalIndexTmp.end() != globalIndexTmp.find(rank))
@@ -1391,5 +1413,5 @@
           listMsg.back() << getId() << isDataDistributed_ << isCompressible_ << listOutIndex.back();
 
-          event.push(rank, nbSenders[rank], listMsg.back());
+          event.push(rank, nbSenders[p][rank], listMsg.back());
         }
 
@@ -1419,6 +1441,9 @@
   {
     CContext* context = CContext::getCurrent();
+
     int nbSrvPools = (context->hasServer) ? (context->hasClient ? context->clientPrimServer.size() : 1) : 1;
     nbSrvPools = 1;
+    // connectedServerRank_.resize(nbSrvPools);
+    // nbSenders.resize(nbSrvPools);
     for (int p = 0; p < nbSrvPools; ++p)
     {
@@ -1428,5 +1453,5 @@
 //      CContextClient* client = (context->hasServer) ? context->client : context->clientPrimServer[p];
       numberWrittenIndexes_ = totalNumberWrittenIndexes_ = offsetWrittenIndexes_ = 0;
-      connectedServerRank_ = ranks;
+      //connectedServerRank_[p] = ranks;
 
       for (int n = 0; n < ranks.size(); n++)
@@ -1465,46 +1490,46 @@
             if (2 == axis_domain_order(i)) //domain
             {
-              // nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin_srv;
-              // nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni_srv;
-              // nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
+              nZoomBegin[indexMap[i]] = domainList[domainId]->zoom_ibegin;
+              nZoomSize[indexMap[i]]  = domainList[domainId]->zoom_ni;
+              nZoomBeginGlobal[indexMap[i]] = domainList[domainId]->global_zoom_ibegin;
               // zoomIndex.push_back(domainList[domainId]->zoom_i_index);
-              // nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
-
-              // nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin_srv;
-              // nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj_srv;
-              // nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
+              nGlob[indexMap[i]] = domainList[domainId]->ni_glo;
+
+              nZoomBegin[indexMap[i] + 1] = domainList[domainId]->zoom_jbegin;
+              nZoomSize[indexMap[i] + 1] = domainList[domainId]->zoom_nj;
+              nZoomBeginGlobal[indexMap[i] + 1] = domainList[domainId]->global_zoom_jbegin;
               // zoomIndex.push_back(domainList[domainId]->zoom_j_index);
-              // nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
-
-              int nbZoom = domainList[domainId]->zoom_i_index.numElements();
-              zoomIndex.push_back(CArray<int,1>(nbZoom));
-              CArray<int,1>& zoomDomain = zoomIndex.back();
-              for (int ind = 0; ind < nbZoom; ++ind)
-              {
-                zoomDomain(ind) = domainList[domainId]->zoom_i_index(ind) + domainList[domainId]->zoom_j_index(ind) * domainList[domainId]->ni_glo;
-              }
-
-              globalSize *= domainList[domainId]->ni_glo * domainList[domainId]->nj_glo;
+              nGlob[indexMap[i] + 1] = domainList[domainId]->nj_glo;
+
+              // int nbZoom = domainList[domainId]->zoom_i_index.numElements();
+              // zoomIndex.push_back(CArray<int,1>(nbZoom));
+              // CArray<int,1>& zoomDomain = zoomIndex.back();
+              // for (int ind = 0; ind < nbZoom; ++ind)
+              // {
+              //   zoomDomain(ind) = domainList[domainId]->zoom_i_index(ind) + domainList[domainId]->zoom_j_index(ind) * domainList[domainId]->ni_glo;
+              // }
+
+              // globalSize *= domainList[domainId]->ni_glo * domainList[domainId]->nj_glo;
               ++domainId;
             }
             else if (1 == axis_domain_order(i)) // axis
             {
-              // nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin_srv;
-              // nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_size_srv;
-              // nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
-              zoomIndex.push_back(axisList[axisId]->zoom_index);
-              // nGlob[indexMap[i]] = axisList[axisId]->n_glo;
-              globalSize *= axisList[axisId]->n_glo;
+              nZoomBegin[indexMap[i]] = axisList[axisId]->zoom_begin;
+              nZoomSize[indexMap[i]]  = axisList[axisId]->zoom_n;
+              nZoomBeginGlobal[indexMap[i]] = axisList[axisId]->global_zoom_begin;
+              // zoomIndex.push_back(axisList[axisId]->zoom_index);
+              nGlob[indexMap[i]] = axisList[axisId]->n_glo;
+              // globalSize *= axisList[axisId]->n_glo;
               ++axisId;
             }
             else // scalar
             {
-              CArray<int,1> zoomScalar(1);
-              zoomScalar(0) = 0;
-              // nZoomBegin[indexMap[i]] = 0;
-              // nZoomSize[indexMap[i]]  = 1;
-              // nZoomBeginGlobal[indexMap[i]] = 0;
-              zoomIndex.push_back(zoomScalar);
-              // nGlob[indexMap[i]] = 1;
+              // CArray<int,1> zoomScalar(1);
+              // zoomScalar(0) = 0;
+              nZoomBegin[indexMap[i]] = 0;
+              nZoomSize[indexMap[i]]  = 1;
+              nZoomBeginGlobal[indexMap[i]] = 0;
+              // zoomIndex.push_back(zoomScalar);
+              nGlob[indexMap[i]] = 1;
               ++scalarId;
             }
@@ -1512,19 +1537,21 @@
           dataSize = 1;
 
-          // for (int i = 0; i < nZoomSize.size(); ++i)
-          //   dataSize *= nZoomSize[i];
-          // serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
-          //                                               nZoomBeginGlobal, nGlob);
-          for (int i = 0; i < zoomIndex.size(); ++i)
-          {
-            dataSize *= zoomIndex[i].numElements();
-          }
-          serverDistribution_ = new CDistributionServer(server->intraCommRank, zoomIndex, nGlobElement);
+          for (int i = 0; i < nZoomSize.size(); ++i)
+            dataSize *= nZoomSize[i];
+          serverDistribution_ = new CDistributionServer(server->intraCommRank, nZoomBegin, nZoomSize,
+                                                        nZoomBeginGlobal, nGlob);
+          // for (int i = 0; i < zoomIndex.size(); ++i)
+          // {
+          //   dataSize *= zoomIndex[i].numElements();
+          // }
+          // serverDistribution_ = new CDistributionServer(server->intraCommRank, zoomIndex, nGlobElement);
         }
 
         CArray<size_t,1> outIndex;
         buffer >> outIndex;
+        serverDistribution_->computeLocalIndex(outIndex);
+
         if (isDataDistributed_)
-          serverDistribution_->computeLocalIndex(outIndex);
+        {}
         else
         {
@@ -1533,7 +1560,8 @@
           // THE PROBLEM HERE IS THAT DATA CAN BE NONDISTRIBUTED ON CLIENT AND DISTRIBUTED ON SERVER
           // BELOW IS THE TEMPORARY FIX only for a single type of element (domain, asix, scalar)
-          dataSize = serverDistribution_->getGlobalIndexEachDimension()[0].numElements();
-          outIndex.resize(dataSize);
-          outIndex = serverDistribution_->getGlobalIndexEachDimension()[0];
+          dataSize = serverDistribution_->getGridSize();
+          // dataSize = serverDistribution_->getGlobalIndexEachDimension()[0].numElements();
+          // outIndex.resize(dataSize);
+          // outIndex = serverDistribution_->getGlobalIndexEachDimension()[0];
 
         }
@@ -1541,22 +1569,22 @@
 
         outIndexFromClient.insert(std::make_pair(rank, outIndex));
-        connectedDataSize_[rank] = outIndex.numElements();
+        // connectedDataSize_[p][rank] = outIndex.numElements();
         numberWrittenIndexes_ += outIndex.numElements();
       }
 
-      int sizeData = 0;
-      for (map<int, CArray<size_t, 1> >::iterator it = outIndexFromClient.begin(); it != outIndexFromClient.end(); ++it)
-      {
-        sizeData += it->second.numElements();
-      }
-      indexFromClients.resize(sizeData);
-      sizeData = 0;
-      for (map<int, CArray<size_t, 1> >::iterator it = outIndexFromClient.begin(); it != outIndexFromClient.end(); ++it)
-      {
-         CArray<size_t, 1>& tmp0 = it->second;
-         CArray<size_t, 1> tmp1 = indexFromClients(Range(sizeData, sizeData + tmp0.numElements() - 1));
-         tmp1 = tmp0;
-         sizeData += tmp0.numElements();
-      }
+      // int sizeData = 0;
+      // for (map<int, CArray<size_t, 1> >::iterator it = outIndexFromClient.begin(); it != outIndexFromClient.end(); ++it)
+      // {
+      //   sizeData += it->second.numElements();
+      // }
+      // indexFromClients.resize(sizeData);
+      // sizeData = 0;
+      // for (map<int, CArray<size_t, 1> >::iterator it = outIndexFromClient.begin(); it != outIndexFromClient.end(); ++it)
+      // {
+      //    CArray<size_t, 1>& tmp0 = it->second;
+      //    CArray<size_t, 1> tmp1 = indexFromClients(Range(sizeData, sizeData + tmp0.numElements() - 1));
+      //    tmp1 = tmp0;
+      //    sizeData += tmp0.numElements();
+      // }
 
       // if (isScalarGrid()) return;
@@ -1571,5 +1599,5 @@
         totalNumberWrittenIndexes_ = numberWrittenIndexes_;
 
-      nbSenders = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, ranks);
+      // nbSenders[p] = CClientServerMappingDistributed::computeConnectedClients(client->serverSize, client->clientSize, client->intraComm, ranks);
     }
   }
Index: XIOS/dev/dev_olga/src/node/grid.hpp
===================================================================
--- XIOS/dev/dev_olga/src/node/grid.hpp	(revision 1077)
+++ XIOS/dev/dev_olga/src/node/grid.hpp	(revision 1099)
@@ -174,5 +174,5 @@
          std::map<int, int> getDomConServerSide();
          std::map<int, StdSize> getAttributesBufferSize();
-         std::map<int, StdSize> getDataBufferSize(const std::string& id = "");
+         std::vector<std::map<int, StdSize> > getDataBufferSize(const std::string& id = "");
          std::vector<StdString> getDomainList();
          std::vector<StdString> getAxisList();
@@ -222,5 +222,5 @@
          map<int, CArray<int, 1> > storeIndex_toSrv;
          map<int, CArray<int, 1> > storeIndex_fromSrv;
-         map<int,int> nbSenders;
+         std::vector<map<int,int> > nbSenders;
 
          map<int, CArray<size_t, 1> > outIndexFromClient, compressedOutIndexFromClient;
@@ -277,6 +277,6 @@
         size_t writtenDataSize_;
         int numberWrittenIndexes_, totalNumberWrittenIndexes_, offsetWrittenIndexes_;
-        std::map<int,size_t> connectedDataSize_;
-        std::vector<int> connectedServerRank_;
+        std::vector<std::map<int,size_t> > connectedDataSize_;
+        std::vector<std::vector<int> > connectedServerRank_;
         bool isDataDistributed_;
         int positionDimensionDistributed_;
Index: XIOS/dev/dev_olga/src/test/test_client.f90
===================================================================
--- XIOS/dev/dev_olga/src/test/test_client.f90	(revision 1077)
+++ XIOS/dev/dev_olga/src/test/test_client.f90	(revision 1099)
@@ -17,6 +17,6 @@
   CHARACTER(len=15) :: calendar_type
   TYPE(xios_context) :: ctx_hdl
-  INTEGER,PARAMETER :: ni_glo=4
-  INTEGER,PARAMETER :: nj_glo=4
+  INTEGER,PARAMETER :: ni_glo=100
+  INTEGER,PARAMETER :: nj_glo=100
   INTEGER,PARAMETER :: llm=2
   DOUBLE PRECISION  :: lval(llm)=1
@@ -50,5 +50,5 @@
       lat_glo(i,j)=1000+(i-1)+(j-1)*ni_glo
       DO l=1,llm
-        field_A_glo(i,j,l)=(i-1)+(j-1)*ni_glo+10000*l
+        field_A_glo(i,j,l)=(i-1)+(j-1)*ni_glo*100+10000*l
       ENDDO
     ENDDO
@@ -66,10 +66,10 @@
   iend=ibegin+ni-1 ; jend=jbegin+nj-1
 
-  ALLOCATE(lon(ni,nj),lat(ni,nj),field_A(0:ni+1,-1:nj+2,llm),lonvalue(ni,nj), axisValue(nj), field_domain(0:ni+1,-1:nj+2))
+  ALLOCATE(lon(ni,nj),lat(ni,nj),field_A(0:ni+1,-1:nj+2,llm),lonvalue(ni,nj), axisValue(nj_glo), field_domain(0:ni+1,-1:nj+2))
   lon(:,:)=lon_glo(ibegin+1:iend+1,jbegin+1:jend+1)
   lat(:,:)=lat_glo(ibegin+1:iend+1,jbegin+1:jend+1)
   field_A(1:ni,1:nj,:)=field_A_glo(ibegin+1:iend+1,jbegin+1:jend+1,:)
   field_domain(1:ni,1:nj) = field_A_glo(ibegin+1:iend+1,jbegin+1:jend+1,1)
-  axisValue(1:nj)=field_A(1,1:nj,1);
+  axisValue(1:nj_glo)=field_A_glo(1,1:nj_glo,1);
 
   CALL xios_context_initialize("test",comm)
@@ -131,8 +131,8 @@
 
   PRINT*,"field field_A is active ? ",xios_field_is_active("field_A")
-  DO ts=1,40
+  DO ts=1,4
     CALL xios_update_calendar(ts)
     CALL xios_send_field("field_A",field_A)
-    ! CALL xios_send_field("field_Axis",axisValue)
+    CALL xios_send_field("field_Axis",axisValue)
     ! CALL xios_send_field("field_Axis",lval)
     CALL xios_send_field("field_Domain",field_domain)
