Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.cpp	(revision 1918)
@@ -333,8 +333,64 @@
       this->checkData();
       this->checkLabel();
+      initializeLocalElement() ;
+      addFullView() ;
+      addWorkflowView() ;
+      addModelView() ;
+
+      checkAttributes_done_ = true ;
+   }
+   CATCH_DUMP_ATTR
+
+
+
+   void CAxis::initializeLocalElement(void)
+   {
+      // after checkAttribute index of size n
+      int rank = CContext::getCurrent()->getIntraCommRank() ;
       
-      checkAttributes_done_ = true ;
-   }
-   CATCH_DUMP_ATTR
+      CArray<size_t,1> ind(n) ;
+      for (int i=0;i<n;i++) ind(i)=index(i) ;
+
+      localElement_ = new CLocalElement(rank, n_glo, ind) ;
+   }
+
+   void CAxis::addFullView(void)
+   {
+      CArray<int,1> index(n) ;
+      for(int i=0; i<n ; i++) index(i)=i ;
+      localElement_ -> addView(CElementView::FULL, index) ;
+   }
+
+   void CAxis::addWorkflowView(void)
+   {
+     // mask + data are included into data_index
+     int nk=data_index.numElements() ;
+     int nMask=0 ;
+     for(int k=0;k<nk;k++) if (data_index(k)>=0 && data_index(k)<n) nMask++ ;
+     
+     CArray<int,1> index(nMask) ;
+     nMask=0 ;
+     for(int k=0;k<nk;k++) 
+       if (data_index(k)>=0 && data_index(k)<n) 
+       {
+         index(nMask) = data_index(k) ;
+         nMask++ ;
+       }
+     localElement_ -> addView(CElementView::WORKFLOW, index) ;
+   }
+
+   void CAxis::addModelView(void)
+   {
+     // information for model view is stored in data_index
+     localElement_->addView(CElementView::MODEL, data_index) ;
+   }
+
+   void CAxis::computeModelToWorkflowConnector(void)
+   { 
+     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
+     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
+     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
+     modelToWorkflowConnector_->computeConnector() ;
+   }
 
    /*!
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/axis.hpp	(revision 1918)
@@ -16,4 +16,6 @@
 #include "transformation.hpp"
 #include "transformation_enum.hpp"
+#include "element.hpp"
+#include "local_connector.hpp"
 
 namespace xios {
@@ -222,4 +224,24 @@
          static bool dummyTransformationMapList_;
 
+
+         
+        private:
+         CLocalElement* localElement_ = nullptr ;
+         void initializeLocalElement(void) ;
+        public: 
+         CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; }
+         CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;}
+        private:
+         void addFullView(void) ;
+         void addWorkflowView(void) ;
+         void addModelView(void) ;
+
+        private:
+         CLocalConnector* modelToWorkflowConnector_ ;
+         void computeModelToWorkflowConnector(void)  ;
+        public:
+         CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;}
+
+
          DECLARE_REF_FUNC(Axis,axis)
    }; // class CAxis
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.cpp	(revision 1918)
@@ -18,4 +18,14 @@
 #include "server_distribution_description.hpp"
 #include "client_server_mapping_distributed.hpp"
+#include "local_connector.hpp"
+#include "grid_local_connector.hpp"
+#include "remote_connector.hpp"
+#include "gatherer_connector.hpp"
+#include "scatterer_connector.hpp"
+#include "grid_scatterer_connector.hpp"
+#include "grid_gatherer_connector.hpp"
+
+
+
 
 #include <algorithm>
@@ -1734,7 +1744,96 @@
       this->computeLocalMask() ;
       this->completeLonLatClient();
+      this->initializeLocalElement() ;
+      this->addFullView() ;
+      this->addWorkflowView() ;
+      this->addModelView() ;
+      // testing ?
+      CLocalView* local = localElement_->getView(CElementView::WORKFLOW) ;
+      CLocalView* model = localElement_->getView(CElementView::MODEL) ;
+
+      CLocalConnector test1(model, local) ;
+      test1.computeConnector() ;
+      CLocalConnector test2(local, model) ;
+      test2.computeConnector() ;
+      CGridLocalConnector gridTest1(vector<CLocalConnector*>{&test1}) ;
+      CGridLocalConnector gridTest2(vector<CLocalConnector*>{&test2}) ;
+      
+      
+      CArray<int,1> out1 ;
+      CArray<int,1> out2 ;
+      test1.transfer(data_i_index,out1,-111) ;
+      test2.transfer(out1,out2,-111) ;
+      
+      out1 = 0 ;
+      out2 = 0 ;
+      gridTest1.transfer(data_i_index,out1,-111) ;
+      gridTest2.transfer(out1, out2,-111) ;
+      
       this->checkAttributes_done_ = true;
    }
    CATCH_DUMP_ATTR
+
+
+   void CDomain::initializeLocalElement(void)
+   {
+      // after checkDomain i_index and j_index of size (ni*nj) 
+      int nij = ni*nj ;
+      CArray<size_t, 1> ij_index(ni*nj) ;
+      for(int ij=0; ij<nij ; ij++) ij_index(ij) = i_index(ij)+j_index(ij)*ni_glo ;
+      int rank = CContext::getCurrent()->getIntraCommRank() ;
+      localElement_ = new CLocalElement(rank, ni_glo*nj_glo, ij_index) ;
+   }
+
+   void CDomain::addFullView(void)
+   {
+      CArray<int,1> index(ni*nj) ;
+      int nij=ni*nj ;
+      for(int ij=0; ij<nij ; ij++) index(ij)=ij ;
+      localElement_ -> addView(CElementView::FULL, index) ;
+   }
+
+   void CDomain::addWorkflowView(void)
+   {
+     // information for workflow view is stored in localMask
+     int nij=ni*nj ;
+     int nMask=0 ;
+     for(int ij=0; ij<nij ; ij++) if (localMask(ij)) nMask++ ;
+     CArray<int,1> index(nMask) ;
+
+     nMask=0 ;
+     for(int ij=0; ij<nij ; ij++) 
+      if (localMask(ij))
+      {
+        index(nMask)=ij ;
+        nMask++ ;
+      }
+      localElement_ -> addView(CElementView::WORKFLOW, index) ;
+   }
+
+   void CDomain::addModelView(void)
+   {
+     // information for model view is stored in data_i_index/data_j_index
+     // very weird, do not mix data_i_index and data_i_begin => in future only keep data_i_index
+     int dataSize = data_i_index.numElements() ;
+     CArray<int,1> index(dataSize) ;
+     int i,j ;
+     for(int k=0;k<dataSize;k++)
+     {
+        i=data_i_index(k)+data_ibegin ; // bad
+        j=data_j_index(k)+data_jbegin ; // bad
+        if (i>=0 && i<ni && j>=0 && j<nj) index(k)=i+j*ni ;
+        else index(k)=-1 ;
+     }
+     localElement_->addView(CElementView::MODEL, index) ;
+   }
+        
+   void CDomain::computeModelToWorkflowConnector(void)
+   { 
+     CLocalView* srcView=getLocalView(CElementView::MODEL) ;
+     CLocalView* dstView=getLocalView(CElementView::WORKFLOW) ;
+     modelToWorkflowConnector_ = new CLocalConnector(srcView, dstView); 
+     modelToWorkflowConnector_->computeConnector() ;
+   }
+
 
    //----------------------------------------------------------------
@@ -2099,4 +2198,7 @@
     this->sendArea(client);    
     this->sendDataIndex(client);
+
+    // test new connector functionnality
+    this->sendDomainDistribution(client) ;
   }
 
@@ -2129,4 +2231,123 @@
     this->createAlias(domainId) ;
   }
+
+
+  void CDomain::sendDomainDistribution(CContextClient* client, const string& domainId)
+  TRY
+  {
+    string serverDomainId = domainId.empty() ? this->getId() : domainId ;
+    CContext* context = CContext::getCurrent();
+    int nbServer = client->serverSize;
+    std::vector<int> nGlobDomain(2);
+    nGlobDomain[0] = this->ni_glo;
+    nGlobDomain[1] = this->nj_glo;
+
+    CServerDistributionDescription serverDescription(nGlobDomain, nbServer);
+    int distributedPosition ;
+    if (isUnstructed_) distributedPosition = 0 ;
+    else distributedPosition = 1 ;
+
+    serverDescription.computeServerDistribution(false, distributedPosition);
+    
+    std::vector<std::vector<int> > serverIndexBegin = serverDescription.getServerIndexBegin();
+    std::vector<std::vector<int> > serverDimensionSizes = serverDescription.getServerDimensionSizes();
+ 
+    vector<unordered_map<size_t,vector<int>>> indexServerOnElement ;
+    CArray<int,1> axisDomainOrder(1) ; axisDomainOrder(0)=2 ;
+    auto zeroIndex=serverDescription.computeServerGlobalByElement(indexServerOnElement, context->getIntraCommRank(), context->getIntraCommSize(),
+                                                                  axisDomainOrder,distributedPosition) ;
+    // distribution is very bad => to redo
+    // convert indexServerOnElement => map<int,CArray<size_t,1>> - need to be changed later
+    map<int, vector<size_t>> vectGlobalIndex ;
+    for(auto& indexRanks : indexServerOnElement[0])
+    {
+      size_t index=indexRanks.first ;
+      auto& ranks=indexRanks.second ;
+      for(int rank : ranks) vectGlobalIndex[rank].push_back(index) ;
+    }
+    map<int, CArray<size_t,1>> globalIndex ;
+    for(auto& vect : vectGlobalIndex ) globalIndex.emplace(vect.first, CArray<size_t,1>(vect.second.data(), shape(vect.second.size()))) ; 
+
+    CDistributedElement remoteElement(ni_glo*nj_glo, globalIndex) ;
+    remoteElement.addFullView() ;
+
+    CRemoteConnector remoteConnector(localElement_->getView(CElementView::FULL), remoteElement.getView(CElementView::FULL),context->getIntraComm()) ;
+    remoteConnector.computeConnector() ;
+    CDistributedElement scatteredElement(remoteElement.getGlobalSize(), remoteConnector.getDistributedGlobalIndex()) ;
+    scatteredElement.addFullView() ;
+    CScattererConnector scatterConnector(localElement_->getView(CElementView::FULL), scatteredElement.getView(CElementView::FULL), context->getIntraComm()) ;
+    scatterConnector.computeConnector() ;
+    CGridScattererConnector gridScatter({&scatterConnector}) ;
+
+    CEventClient event0(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message0 ;
+    message0<<serverDomainId<<0 ; 
+    remoteElement.sendToServer(client,event0,message0) ;
+
+    CEventClient event1(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message1 ;
+    message1<<serverDomainId<<1<<localElement_->getView(CElementView::FULL)->getGlobalSize() ; 
+    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event1,message1) ;
+    
+    CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message2 ;
+    message2<<serverDomainId<<2 ; 
+//    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+    scatterConnector.transfer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+
+/*
+    localElement_->getView(CElementView::FULL)->sendRemoteElement(remoteConnector, client, event1, message1) ;
+    CEventClient event2(getType(), EVENT_ID_DOMAIN_DISTRIBUTION);
+    CMessage message2 ;
+    message2<<serverDomainId<<2 ; 
+    remoteConnector.transferToServer(localElement_->getView(CElementView::FULL)->getGlobalIndex(),client,event2,message2) ;
+*/
+
+  }
+  CATCH
+  
+
+  void CDomain::recvDomainDistribution(CEventServer& event)
+  TRY
+  {
+    string domainId;
+    int phasis ;
+    for (auto& subEvent : event.subEvents) (*subEvent.buffer) >> domainId >> phasis ;
+    get(domainId)->receivedDomainDistribution(event, phasis);
+  }
+  CATCH
+
+  void CDomain::receivedDomainDistribution(CEventServer& event, int phasis)
+  TRY
+  {
+    CContext* context = CContext::getCurrent();
+    if (phasis==0)
+    {
+      localElement_ = new  CLocalElement(context->getIntraCommRank(),event) ;
+      localElement_->addFullView() ;
+    }
+    else if (phasis==1)
+    {
+      CContext* context = CContext::getCurrent();
+      CDistributedElement* elementFrom = new  CDistributedElement(event) ;
+      elementFrom->addFullView() ;
+      gathererConnector_ = new CGathererConnector(elementFrom->getView(CElementView::FULL), localElement_->getView(CElementView::FULL)) ;
+      gathererConnector_->computeConnector() ; 
+    }
+    else if (phasis==2)
+    {
+      CArray<size_t,1> globalIndex ;
+      //gathererConnector_->transfer(event,globalIndex) ;
+      CGridGathererConnector gridGathererConnector({gathererConnector_}) ;
+      gridGathererConnector.transfer(event, globalIndex) ;
+    }
+    else if (phasis==3)
+    {
+
+    }
+  }
+  CATCH
+
+  
 
   /*!
@@ -2482,4 +2703,8 @@
           return true;
           break;
+        case EVENT_ID_DOMAIN_DISTRIBUTION:
+          recvDomainDistribution(event);
+          return true;
+          break;
         default:
           ERROR("bool CDomain::dispatchEvent(CEventServer& event)",
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/domain.hpp	(revision 1918)
@@ -18,4 +18,7 @@
 #include "server_distribution_description.hpp"
 #include "mesh.hpp"
+#include "element.hpp"
+#include "local_connector.hpp"
+#include "gatherer_connector.hpp"
 
 namespace xios {
@@ -50,5 +53,6 @@
            EVENT_ID_INDEX, EVENT_ID_LON, EVENT_ID_LAT, 
            EVENT_ID_AREA,
-           EVENT_ID_DATA_INDEX, EVENT_ID_SERVER_ATTRIBUT
+           EVENT_ID_DATA_INDEX, EVENT_ID_SERVER_ATTRIBUT,
+           EVENT_ID_DOMAIN_DISTRIBUTION
          } ;
 
@@ -216,4 +220,9 @@
        private:
 
+         static void recvDomainDistribution(CEventServer& event) ;
+         void receivedDomainDistribution(CEventServer& event, int phasis) ;
+        
+
+         void sendDomainDistribution(CContextClient* client, const string& domainId="") ; //for testing
          void sendAttributes(); // ym obsolete -> to be removed
          void sendIndex(CContextClient* client, const string& domainId="");
@@ -301,4 +310,26 @@
          static bool _dummyTransformationMapList;
 
+ 
+       private:
+         CLocalElement* localElement_ = nullptr ;
+         void initializeLocalElement(void) ;
+       
+       public:  
+         CLocalElement* getLocalElement(void) { if (localElement_==nullptr) initializeLocalElement() ; return localElement_ ; }
+         CLocalView* getLocalView(CElementView::type type) { return getLocalElement()->getView(type) ;}
+       
+       private:  
+         void addFullView(void) ;
+         void addWorkflowView(void) ;
+         void addModelView(void) ;
+        
+       private:
+         CLocalConnector* modelToWorkflowConnector_ ;
+         void computeModelToWorkflowConnector(void)  ;
+         CGathererConnector*  gathererConnector_ ;
+
+       public:
+         CLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_ ;}
+         
          DECLARE_REF_FUNC(Domain,domain)
 
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.cpp	(revision 1918)
@@ -372,4 +372,21 @@
    CATCH
 
+   
+   CArray<bool,1>& CGrid::getMask(void)
+   {
+      
+      if (mask_.isEmpty())
+      {  
+        if (!mask_0d.isEmpty()) mask_.reference(CArray<bool,1>(mask_0d.dataFirst(),shape(mask_0d.numElements()), neverDeleteData)) ;
+        if (!mask_1d.isEmpty()) mask_.reference(CArray<bool,1>(mask_1d.dataFirst(),shape(mask_1d.numElements()), neverDeleteData)) ;
+        if (!mask_2d.isEmpty()) mask_.reference(CArray<bool,1>(mask_2d.dataFirst(),shape(mask_2d.numElements()), neverDeleteData)) ;
+        if (!mask_3d.isEmpty()) mask_.reference(CArray<bool,1>(mask_3d.dataFirst(),shape(mask_3d.numElements()), neverDeleteData)) ;
+        if (!mask_4d.isEmpty()) mask_.reference(CArray<bool,1>(mask_4d.dataFirst(),shape(mask_4d.numElements()), neverDeleteData)) ;
+        if (!mask_5d.isEmpty()) mask_.reference(CArray<bool,1>(mask_5d.dataFirst(),shape(mask_5d.numElements()), neverDeleteData)) ;
+        if (!mask_6d.isEmpty()) mask_.reference(CArray<bool,1>(mask_6d.dataFirst(),shape(mask_6d.numElements()), neverDeleteData)) ;
+        if (!mask_7d.isEmpty()) mask_.reference(CArray<bool,1>(mask_7d.dataFirst(),shape(mask_7d.numElements()), neverDeleteData)) ;
+      }
+      return mask_ ;
+   }
    /*
      Create mask of grid from mask of its components
@@ -3044,3 +3061,39 @@
   CATCH_DUMP_ATTR
 
+
+  void CGrid::computeGridLocalElements()
+  {
+    std::vector<CDomain*> domainList = this->getDomains();
+    std::vector<CAxis*> axisList = this->getAxis();
+    auto domain=domainList.begin() ;
+    auto axis=axisList.begin() ;
+    vector<CLocalElement*> elements;
+    for(auto order : order_)
+    {
+      if (order==2) 
+      {
+        elements.push_back((*domain)->getLocalElement());
+        domain++ ;
+      }
+      else if (order==1)
+      {
+        elements.push_back((*axis)->getLocalElement());
+        axis++ ;
+      }
+      else if (order==0)
+      { 
+      }
+    }
+    if (hasMask()) 
+    {
+      vector<bool> mask(getMask().getVector()) ;
+      gridLocalElements_ = new CGridLocalElements(elements, mask) ;  
+    }
+    else gridLocalElements_ = new CGridLocalElements(elements) ;  
+  }
+
+  void CGrid::computeModelToWorkflowConnector(void)
+  {
+    modelToWorkflowConnector_ = getGridLocalElements()->getConnector(CElementView::MODEL,CElementView::WORKFLOW) ;
+  }
 } // namespace xios
Index: XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp
===================================================================
--- XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp	(revision 1883)
+++ XIOS/dev/dev_ym/XIOS_COUPLING/src/node/grid.hpp	(revision 1918)
@@ -16,4 +16,6 @@
 #include "utils.hpp"
 #include "transformation_enum.hpp"
+#include "grid_local_connector.hpp"
+#include "grid_elements.hpp"
 
 namespace xios {
@@ -255,4 +257,8 @@
          void modifyMask(const CArray<int,1>& indexToModify, bool valueToModify = false);
          void modifyMaskSize(const std::vector<int>& newDimensionSize, bool newValue = false);
+        
+        /** get mask pointer stored in mask_1d, or mask_2d, or..., or mask_7d */
+         CArray<bool,1> mask_ ;
+         CArray<bool,1>& getMask(void) ;
 
          void computeGridGlobalDimension(const std::vector<CDomain*>& domains,
@@ -289,4 +295,5 @@
                           const CArray<int,1>& axisDomainOrder,
                           bool createMask = false);
+
         template<int N>
         void modifyGridMask(CArray<bool,N>& gridMask, const CArray<int,1>& indexToModify, bool valueToModify);
@@ -500,4 +507,16 @@
 /** List order of axis and domain in a grid, if there is a domain, it will take value 2, axis 1, scalar 0 */
         std::vector<int> order_;
+
+      private:  
+        CGridLocalElements* gridLocalElements_= nullptr ;
+        void computeGridLocalElements(void) ;
+      public:
+        CGridLocalElements* getGridLocalElements(void) { if (gridLocalElements_==nullptr) computeGridLocalElements() ; return gridLocalElements_ ;}
+
+      private:
+        CGridLocalConnector* modelToWorkflowConnector_ ;
+      public:
+        void computeModelToWorkflowConnector(void) ;
+        CGridLocalConnector* getModelToWorkflowConnector(void) { if (modelToWorkflowConnector_==nullptr) computeModelToWorkflowConnector() ; return modelToWorkflowConnector_;}
 
    }; // class CGrid
@@ -521,4 +540,5 @@
    CATCH
 
+/* obsolete
    template <int n>
    void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored)
@@ -534,4 +554,21 @@
       this->maskField_arr(field.dataFirst(), stored);
    }
+*/
+   template <int n>
+   void CGrid::maskField(const CArray<double,n>& field, CArray<double,1>& stored)
+   {
+      auto connector = getModelToWorkflowConnector() ;
+
+      if (connector->getSrcSize() != field.numElements())
+         ERROR("void CGrid::inputField(const  CArray<double,n>& field, CArray<double,1>& stored) const",
+                << "[ Awaiting data of size = " << this->getDataSize() << ", "
+                << "Received data size = "      << field.numElements() << " ] "
+                << "The data array does not have the right size! "
+                << "Grid = " << this->getId())
+      const double nanValue = std::numeric_limits<double>::quiet_NaN();
+      connector->transfer(field, stored, nanValue) ;
+   }
+
+
 
    template <int n>
