Index: XIOS/dev/dev_trunk_graph/src/node/context.cpp
===================================================================
--- XIOS/dev/dev_trunk_graph/src/node/context.cpp	(revision 1687)
+++ XIOS/dev/dev_trunk_graph/src/node/context.cpp	(revision 2019)
@@ -20,4 +20,10 @@
 #include "server.hpp"
 #include "distribute_file_server2.hpp"
+#include "services_manager.hpp"
+#include "contexts_manager.hpp"
+#include "cxios.hpp"
+#include "client.hpp"
+#include "coupler_in.hpp"
+#include "coupler_out.hpp"
 
 namespace xios {
@@ -31,6 +37,6 @@
       , calendar(), hasClient(false), hasServer(false)
       , isPostProcessed(false), finalized(false)
-      , idServer_(), client(0), server(0)
-      , allProcessed(false), countChildCtx_(0)
+      , client(nullptr), server(nullptr)
+      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
 
    { /* Ne rien faire de plus */ }
@@ -40,6 +46,6 @@
       , calendar(), hasClient(false), hasServer(false)
       , isPostProcessed(false), finalized(false)
-      , idServer_(), client(0), server(0)
-      , allProcessed(false), countChildCtx_(0)
+      , client(nullptr), server(nullptr)
+      , allProcessed(false), countChildContextFinalized_(0), isProcessingEvent_(false)
    { /* Ne rien faire de plus */ }
 
@@ -264,59 +270,65 @@
    ///---------------------------------------------------------------
 
-   //! Initialize client side
-   void CContext::initClient(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtServer /*= 0*/)
-   TRY
-   {
-
-     hasClient = true;
-     MPI_Comm intraCommServer, interCommServer;
+
+   void CContext::setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting)
+   TRY
+   {
+      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
+     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
+      // Ensure there is at least some room for 20 of such events in the buffers
+     size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize);
+
+#define DECLARE_NODE(Name_, name_)    \
+     if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition);
+#define DECLARE_NODE_PAR(Name_, name_)
+#include "node_type.conf"
+#undef DECLARE_NODE
+#undef DECLARE_NODE_PAR
+
+
+     map<CContextClient*,map<int,size_t>> dataSize ;
+     map<CContextClient*,map<int,size_t>> maxEventSize ;
+     map<CContextClient*,map<int,size_t>> attributesSize ;  
+
+     for(auto field : fields)
+     {
+       field->setContextClientDataBufferSize(dataSize, maxEventSize, bufferForWriting) ;
+       field->setContextClientAttributesBufferSize(attributesSize, maxEventSize, bufferForWriting) ;
+     }
      
 
-     if (CServer::serverLevel != 1)
-      // initClient is called by client
-     {
-       client = new CContextClient(this, intraComm, interComm, cxtServer);
-       if (cxtServer) // Attached mode
+     for(auto& it : attributesSize)
+     {
+       auto contextClient = it.first ;
+       auto& contextDataSize =  dataSize[contextClient] ;
+       auto& contextAttributesSize =  attributesSize[contextClient] ;
+       auto& contextMaxEventSize =  maxEventSize[contextClient] ;
+   
+       for (auto& it : contextAttributesSize)
        {
-         intraCommServer = intraComm;
-         interCommServer = interComm;
+         auto serverRank=it.first ;
+         auto& buffer = contextAttributesSize[serverRank] ;
+         if (contextDataSize[serverRank] > buffer) buffer=contextDataSize[serverRank] ;
+         buffer *= CXios::bufferSizeFactor;
+         if (buffer < minBufferSize) buffer = minBufferSize;
+         if (buffer > CXios::maxBufferSize ) buffer = CXios::maxBufferSize;
        }
-       else
-       {
-         MPI_Comm_dup(intraComm, &intraCommServer);
-         comms.push_back(intraCommServer);
-         MPI_Comm_dup(interComm, &interCommServer);
-         comms.push_back(interCommServer);
-       }
-/* for registry take the id of client context */
-/* for servers, supress the _server_ from id  */
-       string contextRegistryId=getId() ;
-       size_t pos=contextRegistryId.find("_server_") ;
-       if (pos!=std::string::npos)  contextRegistryId=contextRegistryId.substr(0,pos) ;
-
-       registryIn=new CRegistry(intraComm);
-       registryIn->setPath(contextRegistryId) ;
-       if (client->clientRank==0) registryIn->fromFile("xios_registry.bin") ;
-       registryIn->bcastRegistry() ;
-       registryOut=new CRegistry(intraComm) ;
-       
-       registryOut->setPath(contextRegistryId) ;
-
-       server = new CContextServer(this, intraCommServer, interCommServer);
-     }
-     else
-     // initClient is called by primary server
-     {
-       clientPrimServer.push_back(new CContextClient(this, intraComm, interComm));
-       MPI_Comm_dup(intraComm, &intraCommServer);
-       comms.push_back(intraCommServer);
-       MPI_Comm_dup(interComm, &interCommServer);
-       comms.push_back(interCommServer);
-       serverPrimServer.push_back(new CContextServer(this, intraCommServer, interCommServer));
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
+
+       // Leaders will have to send some control events so ensure there is some room for those in the buffers
+       if (contextClient->isServerLeader())
+         for(auto& rank : contextClient->getRanksServerLeader())
+           if (!contextAttributesSize.count(rank))
+           {
+             contextAttributesSize[rank] = minBufferSize;
+             contextMaxEventSize[rank] = minEventSize;
+           }
+      
+       contextClient->setBufferSize(contextAttributesSize, contextMaxEventSize);    
+     }
+   }
+   CATCH_DUMP_ATTR
+
+
+    /*!
     Sets client buffers.
     \param [in] contextClient
@@ -324,9 +336,10 @@
     This flag is only true for client and server-1 for communication with server-2
   */
+  // ym obsolete to be removed
    void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting)
    TRY
    {
-      // Estimated minimum event size for small events (10 is an arbitrary constant just for safety)
-     const size_t minEventSize = CEventClient::headerSize + getIdServer().size() + 10 * sizeof(int);
+      // Estimated minimum event size for small events (20 is an arbitrary constant just for safety)
+     const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int);
 
       // Ensure there is at least some room for 20 of such events in the buffers
@@ -375,4 +388,96 @@
    CATCH_DUMP_ATTR
 
+ /*!
+    * Compute the required buffer size to send the fields data.
+    * \param maxEventSize [in/out] the size of the bigger event for each connected server
+    * \param [in] contextClient
+    * \param [in] bufferForWriting True if buffers are used for sending data for writing
+      This flag is only true for client and server-1 for communication with server-2
+    */
+   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize,
+                                                      CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
+   TRY
+   {
+     std::map<int, StdSize> dataSize;
+
+     // Find all reference domain and axis of all active fields
+     std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles;
+     size_t numEnabledFiles = fileList.size();
+     for (size_t i = 0; i < numEnabledFiles; ++i)
+     {
+       CFile* file = fileList[i];
+       if (file->getContextClient() == contextClient)
+       {
+         std::vector<CField*> enabledFields = file->getEnabledFields();
+         size_t numEnabledFields = enabledFields.size();
+         for (size_t j = 0; j < numEnabledFields; ++j)
+         {
+           // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient);
+           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting);
+           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.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;
+           }
+         }
+       }
+     }
+     return dataSize;
+   }
+   CATCH_DUMP_ATTR
+
+/*!
+    * Compute the required buffer size to send the attributes (mostly those grid related).
+    * \param maxEventSize [in/out] the size of the bigger event for each connected server
+    * \param [in] contextClient
+    * \param [in] bufferForWriting True if buffers are used for sending data for writing
+      This flag is only true for client and server-1 for communication with server-2
+    */
+   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize,
+                                                           CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
+   TRY
+   {
+   // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes
+     std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
+     maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
+
+     std::vector<CFile*>& fileList = this->enabledFiles;
+     size_t numEnabledFiles = fileList.size();
+     for (size_t i = 0; i < numEnabledFiles; ++i)
+     {
+//         CFile* file = this->enabledWriteModeFiles[i];
+        CFile* file = fileList[i];
+        std::vector<CField*> enabledFields = file->getEnabledFields();
+        size_t numEnabledFields = enabledFields.size();
+        for (size_t j = 0; j < numEnabledFields; ++j)
+        {
+          const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting);
+          std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
+          for (; it != itE; ++it)
+          {
+         // If attributesSize[it->first] does not exist, it will be zero-initialized
+         // so we can use it safely without checking for its existence
+             if (attributesSize[it->first] < it->second)
+         attributesSize[it->first] = it->second;
+
+         if (maxEventSize[it->first] < it->second)
+         maxEventSize[it->first] = it->second;
+          }
+        }
+     }
+     return attributesSize;
+   }
+   CATCH_DUMP_ATTR
+
+
+
    //! Verify whether a context is initialized
    bool CContext::isInitialized(void)
@@ -383,174 +488,391 @@
    CATCH_DUMP_ATTR
 
-   void CContext::initServer(MPI_Comm intraComm, MPI_Comm interComm, CContext* cxtClient /*= 0*/)
+
+   void CContext::init(CServerContext* parentServerContext, MPI_Comm intraComm, int serviceType)
+   TRY
+   {
+     parentServerContext_ = parentServerContext ;
+     if (serviceType==CServicesManager::CLIENT) 
+       initClient(intraComm, serviceType) ;
+     else
+       initServer(intraComm, serviceType) ;
+    }
+    CATCH_DUMP_ATTR
+
+
+
+//! Initialize client side
+   void CContext::initClient(MPI_Comm intraComm, int serviceType)
+   TRY
+   {
+      intraComm_=intraComm ;
+      MPI_Comm_rank(intraComm_, &intraCommRank_) ;
+      MPI_Comm_size(intraComm_, &intraCommSize_) ;
+
+      serviceType_ = CServicesManager::CLIENT ;
+      if (serviceType_==CServicesManager::CLIENT)
+      {
+        hasClient=true ;
+        hasServer=false ;
+      }
+      contextId_ = getId() ;
+      
+      attached_mode=true ;
+      if (!CXios::isUsingServer()) attached_mode=false ;
+
+
+      string contextRegistryId=getId() ;
+      registryIn=new CRegistry(intraComm);
+      registryIn->setPath(contextRegistryId) ;
+      
+      int commRank ;
+      MPI_Comm_rank(intraComm_,&commRank) ;
+      if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
+      registryIn->bcastRegistry() ;
+      registryOut=new CRegistry(intraComm_) ;
+      registryOut->setPath(contextRegistryId) ;
+     
+   }
+   CATCH_DUMP_ATTR
+
+   
+   void CContext::initServer(MPI_Comm intraComm, int serviceType)
    TRY
    {
      hasServer=true;
-     server = new CContextServer(this,intraComm,interComm);
-
-/* for registry take the id of client context */
-/* for servers, supress the _server_ from id  */
-     string contextRegistryId=getId() ;
-     size_t pos=contextRegistryId.find("_server_") ;
-     if (pos!=std::string::npos)  contextRegistryId=contextRegistryId.substr(0,pos) ;
-       
+     intraComm_=intraComm ;
+     MPI_Comm_rank(intraComm_, &intraCommRank_) ;
+     MPI_Comm_size(intraComm_, &intraCommSize_) ;
+
+     serviceType_=serviceType ;
+
+     if (serviceType_==CServicesManager::GATHERER)
+     {
+       hasClient=true ;
+       hasServer=true ;
+     }
+     else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
+     {
+       hasClient=false ;
+       hasServer=true ;
+     }
+
+     CXios::getContextsManager()->getContextId(getId(), contextId_, intraComm) ;
+     
      registryIn=new CRegistry(intraComm);
-     registryIn->setPath(contextRegistryId) ;
-     if (server->intraCommRank==0) registryIn->fromFile("xios_registry.bin") ;
+     registryIn->setPath(contextId_) ;
+     
+     int commRank ;
+     MPI_Comm_rank(intraComm_,&commRank) ;
+     if (commRank==0) registryIn->fromFile("xios_registry.bin") ;
+    
      registryIn->bcastRegistry() ;
      registryOut=new CRegistry(intraComm) ;
-     registryOut->setPath(contextRegistryId) ;
-
-     MPI_Comm intraCommClient, interCommClient;
-     if (cxtClient) // Attached mode
-     {
-       intraCommClient = intraComm;
-       interCommClient = interComm;
-     }
-     else
-     {
-       MPI_Comm_dup(intraComm, &intraCommClient);
-       comms.push_back(intraCommClient);
-       MPI_Comm_dup(interComm, &interCommClient);
-       comms.push_back(interCommClient);
-     }
-     client = new CContextClient(this,intraCommClient,interCommClient, cxtClient);
-   }
-   CATCH_DUMP_ATTR
-
-   //! Try to send the buffers and receive possible answers
-  bool CContext::checkBuffersAndListen(bool enableEventsProcessing /*= true*/)
+     registryOut->setPath(contextId_) ;
+
+   }
+   CATCH_DUMP_ATTR
+
+
+  void CContext::createClientInterComm(MPI_Comm interCommClient, MPI_Comm interCommServer) // for servers
   TRY
   {
-    bool clientReady, serverFinished;
-
-    // Only classical servers are non-blocking
-    if (CServer::serverLevel == 0)
-    {
-      client->checkBuffers();
-      bool hasTmpBufferedEvent = client->hasTemporarilyBufferedEvent();
-      if (hasTmpBufferedEvent)
-        hasTmpBufferedEvent = !client->sendTemporarilyBufferedEvent();
-      // Don't process events if there is a temporarily buffered event
-      return server->eventLoop(!hasTmpBufferedEvent || !enableEventsProcessing);
-    }
-    else if (CServer::serverLevel == 1)
-    {
-      if (!finalized)
-        client->checkBuffers();
-      bool serverFinished = true;
-      if (!finalized)
-        serverFinished = server->eventLoop(enableEventsProcessing);
-      bool serverPrimFinished = true;
-      for (int i = 0; i < clientPrimServer.size(); ++i)
-      {
-        if (!finalized)
-          clientPrimServer[i]->checkBuffers();
-        if (!finalized)
-          serverPrimFinished *= serverPrimServer[i]->eventLoop(enableEventsProcessing);
-      }
-      return ( serverFinished && serverPrimFinished);
-    }
-
-    else if (CServer::serverLevel == 2)
-    {
-      client->checkBuffers();
-      return server->eventLoop(enableEventsProcessing);
-    }
+    MPI_Comm intraCommClient ;
+    MPI_Comm_dup(intraComm_, &intraCommClient);
+    comms.push_back(intraCommClient);
+    // attached_mode=parentServerContext_->isAttachedMode() ; //ym probably inherited from source context
+    server = new CContextServer(this,intraComm_, interCommServer); // check if we need to dupl. intraComm_ ?
+    client = new CContextClient(this,intraCommClient,interCommClient);
+    client->setAssociatedServer(server) ;  
+    server->setAssociatedClient(client) ;  
+
   }
-   CATCH_DUMP_ATTR
-
-   //! Terminate a context
+  CATCH_DUMP_ATTR
+
+  void CContext::createServerInterComm(void) 
+  TRY
+  {
+   
+    MPI_Comm interCommClient, interCommServer ;
+
+    if (serviceType_ == CServicesManager::CLIENT)
+    {
+
+      int commRank ;
+      MPI_Comm_rank(intraComm_,&commRank) ;
+      if (commRank==0)
+      {
+        if (attached_mode) CXios::getContextsManager()->createServerContext(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId()) ;
+        else if (CXios::usingServer2) CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId()) ;
+        else  CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId()) ;
+      }
+
+      MPI_Comm interComm ;
+      
+      if (attached_mode)
+      {
+        parentServerContext_->createIntercomm(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, getContextId(), intraComm_, 
+                                              interCommClient, interCommServer) ;
+        int type ; 
+        if (commRank==0) CXios::getServicesManager()->getServiceType(CClient::getPoolRessource()->getId(), CXios::defaultServerId, 0, type) ;
+        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
+        setCurrent(getId()) ; // getCurrent/setCurrent may be supress, it can cause a lot of trouble
+      }
+      else if (CXios::usingServer2)
+      { 
+//      CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_, interComm) ;
+        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultGathererId, 0, getContextId(), intraComm_,
+                                              interCommClient, interCommServer) ;
+        int type ; 
+        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultGathererId, 0, type) ;
+        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
+      }
+      else
+      {
+        //CXios::getContextsManager()->createServerContextIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_, interComm) ;
+        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, 0, getContextId(), intraComm_,
+                                              interCommClient, interCommServer) ;
+        int type ; 
+        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
+        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
+      }
+
+        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
+        // in future better to replace it by intracommuncator associated to the context
+    
+      MPI_Comm intraCommClient, intraCommServer ;
+      intraCommClient=intraComm_ ;
+      MPI_Comm_dup(intraComm_, &intraCommServer) ;
+      client = new CContextClient(this, intraCommClient, interCommClient);
+      server = new CContextServer(this, intraCommServer, interCommServer);
+      client->setAssociatedServer(server) ;
+      server->setAssociatedClient(client) ;
+    }
+    
+    if (serviceType_ == CServicesManager::GATHERER)
+    {
+      int commRank ;
+      MPI_Comm_rank(intraComm_,&commRank) ;
+      
+      int nbPartitions ;
+      if (commRank==0) 
+      { 
+        CXios::getServicesManager()->getServiceNbPartitions(CXios::defaultPoolId, CXios::defaultServerId, 0, nbPartitions) ;
+        for(int i=0 ; i<nbPartitions; i++)
+          CXios::getContextsManager()->createServerContext(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId()) ;
+      }      
+      MPI_Bcast(&nbPartitions, 1, MPI_INT, 0, intraComm_) ;
+      
+      MPI_Comm interComm ;
+      for(int i=0 ; i<nbPartitions; i++)
+      {
+        parentServerContext_->createIntercomm(CXios::defaultPoolId, CXios::defaultServerId, i, getContextId(), intraComm_, interCommClient, interCommServer) ;
+        int type ; 
+        if (commRank==0) CXios::getServicesManager()->getServiceType(CXios::defaultPoolId, CXios::defaultServerId, 0, type) ;
+        MPI_Bcast(&type,1,MPI_INT,0,intraComm_) ;
+        primServerId_.push_back(CXios::getContextsManager()->getServerContextName(CXios::defaultPoolId, CXios::defaultServerId, i, type, getContextId())) ;
+
+        // intraComm client is not duplicated. In all the code we use client->intraComm for MPI
+        // in future better to replace it by intracommuncator associated to the context
+      
+        MPI_Comm intraCommClient, intraCommServer ;
+
+        intraCommClient=intraComm_ ;
+        MPI_Comm_dup(intraComm_, &intraCommServer) ;
+
+        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient) ;
+        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer) ;
+        client->setAssociatedServer(server) ;
+        server->setAssociatedClient(client) ;
+        clientPrimServer.push_back(client);
+        serverPrimServer.push_back(server);  
+
+      
+      }
+    }
+  }
+  CATCH_DUMP_ATTR
+
+   
+
+  bool CContext::eventLoop(bool enableEventsProcessing)
+  {
+    bool finished=true; 
+
+    if (client!=nullptr && !finalized) client->checkBuffers();
+    
+    for (int i = 0; i < clientPrimServer.size(); ++i)
+    {
+      if (!finalized) clientPrimServer[i]->checkBuffers();
+      if (!finalized) finished &= serverPrimServer[i]->eventLoop(enableEventsProcessing);
+    }
+
+    for (auto couplerOut : couplerOutClient_)
+      if (!finalized) couplerOut.second->checkBuffers();
+    
+    for (auto couplerIn : couplerInClient_)
+      if (!finalized) couplerIn.second->checkBuffers();
+    
+    for (auto couplerOut : couplerOutServer_)
+      if (!finalized) couplerOut.second->eventLoop(enableEventsProcessing);
+
+    for (auto couplerIn : couplerInServer_)
+      if (!finalized) couplerIn.second->eventLoop(enableEventsProcessing);
+    
+    if (server!=nullptr) if (!finalized) finished &= server->eventLoop(enableEventsProcessing);
+  
+    return finalized && finished ;
+  }
+
+  void CContext::addCouplingChanel(const std::string& fullContextId, bool out)
+  {
+     int contextLeader ;
+     
+     if (out)
+     { 
+       if (couplerOutClient_.find(fullContextId)==couplerOutClient_.end()) 
+       {
+         bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
+     
+         MPI_Comm interComm, interCommClient, interCommServer  ;
+         MPI_Comm intraCommClient, intraCommServer ;
+
+         if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
+
+        MPI_Comm_dup(intraComm_, &intraCommClient) ;
+        MPI_Comm_dup(intraComm_, &intraCommServer) ;
+        MPI_Comm_dup(interComm, &interCommClient) ;
+        MPI_Comm_dup(interComm, &interCommServer) ;
+        CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
+        CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
+        client->setAssociatedServer(server) ;
+        server->setAssociatedClient(client) ;
+        MPI_Comm_free(&interComm) ;
+        couplerOutClient_[fullContextId] = client ;
+        couplerOutServer_[fullContextId] = server ;
+
+/*
+      // for now, we don't now which beffer size must be used for client coupler
+      // It will be evaluated later. Fix a constant size for now...
+      // set to 10Mb for development
+       map<int,size_t> bufferSize, maxEventSize ;
+       for(int i=0;i<client->getRemoteSize();i++)
+       {
+         bufferSize[i]=10000000 ;
+         maxEventSize[i]=10000000 ;
+       }
+
+       client->setBufferSize(bufferSize, maxEventSize);    
+*/
+      }
+    }
+    else if (couplerInClient_.find(fullContextId)==couplerInClient_.end())
+    {
+      bool ok=CXios::getContextsManager()->getContextLeader(fullContextId, contextLeader, getIntraComm()) ;
+     
+       MPI_Comm interComm, interCommClient, interCommServer  ;
+       MPI_Comm intraCommClient, intraCommServer ;
+
+       if (ok) MPI_Intercomm_create(getIntraComm(), 0, CXios::getXiosComm(), contextLeader, 0, &interComm) ;
+
+       MPI_Comm_dup(intraComm_, &intraCommClient) ;
+       MPI_Comm_dup(intraComm_, &intraCommServer) ;
+       MPI_Comm_dup(interComm, &interCommServer) ;
+       MPI_Comm_dup(interComm, &interCommClient) ;
+       CContextServer* server = new CContextServer(this, intraCommServer, interCommServer);
+       CContextClient* client = new CContextClient(this, intraCommClient, interCommClient);
+       client->setAssociatedServer(server) ;
+       server->setAssociatedClient(client) ;
+       MPI_Comm_free(&interComm) ;
+
+       map<int,size_t> bufferSize, maxEventSize ;
+       for(int i=0;i<client->getRemoteSize();i++)
+       {
+         bufferSize[i]=10000000 ;
+         maxEventSize[i]=10000000 ;
+       }
+
+       client->setBufferSize(bufferSize, maxEventSize);    
+       couplerInClient_[fullContextId] = client ;
+       couplerInServer_[fullContextId] = server ;        
+    }
+  }
+  
+  void CContext::globalEventLoop(void)
+  {
+    CXios::getDaemonsManager()->eventLoop() ;
+    setCurrent(getId()) ;
+  }
+
+
    void CContext::finalize(void)
    TRY
    {
-      if (hasClient && !hasServer) // For now we only use server level 1 to read data
-      {
-        doPreTimestepOperationsForEnabledReadModeFiles();
-      }
-     // Send registry upon calling the function the first time
-     if (countChildCtx_ == 0)
-       if (hasClient) sendRegistry() ;
-
-     // Client:
-     // (1) blocking send context finalize to its server
-     // (2) blocking receive context finalize from its server
-     // (3) some memory deallocations
-     if (CXios::isClient)
-     {
-       // Make sure that client (model) enters the loop only once
-       if (countChildCtx_ < 1)
-       {
-         ++countChildCtx_;
-
-         client->finalize();
-         while (client->havePendingRequests())
-            client->checkBuffers();
-
-         while (!server->hasFinished())
-           server->eventLoop();
-
-         if (hasServer) // Mode attache
+      registryOut->hierarchicalGatherRegistry() ;
+      if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
+
+      if (serviceType_==CServicesManager::CLIENT)
+      {
+//ym        doPreTimestepOperationsForEnabledReadModeFiles(); // For now we only use server level 1 to read data
+
+        triggerLateFields() ;
+
+        // inform couplerIn that I am finished
+        for(auto& couplerInClient : couplerInClient_) sendCouplerInContextFinalized(couplerInClient.second) ;
+
+        // wait until received message from couplerOut that they have finished
+        bool couplersInFinalized ;
+        do
+        {
+          couplersInFinalized=true ;
+          for(auto& couplerOutClient : couplerOutClient_) couplersInFinalized &= isCouplerInContextFinalized(couplerOutClient.second) ; 
+          globalEventLoop() ;
+        } while (!couplersInFinalized) ;
+
+        info(100)<<"DEBUG: context "<<getId()<<" Send client finalize"<<endl ;
+        client->finalize();
+        info(100)<<"DEBUG: context "<<getId()<<" Client finalize sent"<<endl ;
+        while (client->havePendingRequests()) client->checkBuffers();
+        info(100)<<"DEBUG: context "<<getId()<<" no pending request ok"<<endl ;
+        bool notifiedFinalized=false ;
+        do
+        {
+          notifiedFinalized=client->isNotifiedFinalized() ;
+        } while (!notifiedFinalized) ;
+        client->releaseBuffers();
+        info(100)<<"DEBUG: context "<<getId()<<" release client ok"<<endl ;
+      }
+      else if (serviceType_==CServicesManager::GATHERER)
+      {
+         for (int i = 0; i < clientPrimServer.size(); ++i)
          {
-           closeAllFile();
-           registryOut->hierarchicalGatherRegistry() ;
-           if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
+           clientPrimServer[i]->finalize();
+           bool bufferReleased;
+           do
+           {
+             clientPrimServer[i]->checkBuffers();
+             bufferReleased = !clientPrimServer[i]->havePendingRequests();
+           } while (!bufferReleased);
+           
+           bool notifiedFinalized=false ;
+           do
+           {
+             notifiedFinalized=clientPrimServer[i]->isNotifiedFinalized() ;
+           } while (!notifiedFinalized) ;
+           clientPrimServer[i]->releaseBuffers();
          }
-
-         //! Deallocate client buffers
-         client->releaseBuffers();
-
-         //! Free internally allocated communicators
-         for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
-           MPI_Comm_free(&(*it));
-         comms.clear();
-
-         info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
-       }
-     }
-     else if (CXios::isServer)
-     {
-       // First context finalize message received from a model
-       // Send context finalize to its child contexts (if any)
-       if (countChildCtx_ == 0)
-         for (int i = 0; i < clientPrimServer.size(); ++i)
-           clientPrimServer[i]->finalize();
-
-       // (Last) context finalized message received
-       if (countChildCtx_ == clientPrimServer.size())
-       {
-         // Blocking send of context finalize message to its client (e.g. primary server or model)
-         info(100)<<"DEBUG: context "<<getId()<<" Send client finalize<<"<<endl ;
-         client->finalize();
-         bool bufferReleased;
-         do
-         {
-           client->checkBuffers();
-           bufferReleased = !client->havePendingRequests();
-         } while (!bufferReleased);
-         finalized = true;
-
-         closeAllFile(); // Just move to here to make sure that server-level 1 can close files
-         if (hasServer && !hasClient)
-         {           
-           registryOut->hierarchicalGatherRegistry() ;
-           if (server->intraCommRank==0) CXios::globalRegistry->mergeRegistry(*registryOut) ;
-         }
-
-         //! Deallocate client buffers
-         client->releaseBuffers();
-         for (int i = 0; i < clientPrimServer.size(); ++i)
-           clientPrimServer[i]->releaseBuffers();
-
-         //! Free internally allocated communicators
-         for (std::list<MPI_Comm>::iterator it = comms.begin(); it != comms.end(); ++it)
-           MPI_Comm_free(&(*it));
-         comms.clear();
-
-         info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
-       }
-
-       ++countChildCtx_;
-     }
+         closeAllFile();
+
+      }
+      else if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
+      {
+        closeAllFile();
+      }
+
+      freeComms() ;
+        
+      parentServerContext_->freeComm() ;
+      finalized = true;
+      info(20)<<"CContext: Context <"<<getId()<<"> is finalized."<<endl;
    }
    CATCH_DUMP_ATTR
@@ -576,116 +898,5 @@
    CATCH_DUMP_ATTR
 
-   void CContext::postProcessingGlobalAttributes()
-   TRY
-   {
-     if (allProcessed) return;  
-     
-     // After xml is parsed, there are some more works with post processing
-     postProcessing();
-
-     // Check grid and calculate its distribution
-     checkGridEnabledFields();
- 
-     // Distribute files between secondary servers according to the data size
-     distributeFiles();
-
-     setClientServerBuffer(client, (hasClient && !hasServer));
-     for (int i = 0; i < clientPrimServer.size(); ++i)
-         setClientServerBuffer(clientPrimServer[i], true);
-
-     if (hasClient)
-     {
-      // Send all attributes of current context to server
-      this->sendAllAttributesToServer();
-
-      // Send all attributes of current calendar
-      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer();
-
-      // We have enough information to send to server
-      // First of all, send all enabled files
-      sendEnabledFiles(this->enabledWriteModeFiles);
-      // We only use server-level 1 (for now) to read data
-      if (!hasServer)
-        sendEnabledFiles(this->enabledReadModeFiles);
-
-      // Then, send all enabled fields      
-      sendEnabledFieldsInFiles(this->enabledWriteModeFiles);
-      if (!hasServer)
-        sendEnabledFieldsInFiles(this->enabledReadModeFiles);
-
-      // Then, check whether we have domain_ref, axis_ref or scalar_ref attached to the enabled fields
-      // If any, so send them to server
-       sendRefDomainsAxisScalars(this->enabledWriteModeFiles);
-      if (!hasServer)
-        sendRefDomainsAxisScalars(this->enabledReadModeFiles);        
-
-       // Check whether enabled fields have grid_ref, if any, send this info to server
-      sendRefGrid(this->enabledFiles);
-      // This code may be useful in the future when we want to seperate completely read and write
-      // sendRefGrid(this->enabledWriteModeFiles);
-      // if (!hasServer)
-      //   sendRefGrid(this->enabledReadModeFiles);
-      
-      // A grid of enabled fields composed of several components which must be checked then their
-      // checked attributes should be sent to server
-      sendGridComponentEnabledFieldsInFiles(this->enabledFiles); // This code can be seperated in two (one for reading, another for writing)
-
-       // We have a xml tree on the server side and now, it should be also processed
-      sendPostProcessing();
-       
-      // Finally, we send information of grid itself to server 
-      sendGridEnabledFieldsInFiles(this->enabledWriteModeFiles);       
-      if (!hasServer)
-        sendGridEnabledFieldsInFiles(this->enabledReadModeFiles);       
-     }
-     allProcessed = true;
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::sendPostProcessingGlobalAttributes()
-   TRY
-   {
-      // Use correct context client to send message
-     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
-    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
-     for (int i = 0; i < nbSrvPools; ++i)
-     {
-       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
-       CEventClient event(getType(),EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES);
-
-       if (contextClientTmp->isServerLeader())
-       {
-         CMessage msg;
-         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)
-           event.push(*itRank,1,msg);
-         contextClientTmp->sendEvent(event);
-       }
-       else contextClientTmp->sendEvent(event);
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::recvPostProcessingGlobalAttributes(CEventServer& event)
-   TRY
-   {
-      CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;
-      get(id)->recvPostProcessingGlobalAttributes(*buffer);
-   }
-   CATCH
-
-   void CContext::recvPostProcessingGlobalAttributes(CBufferIn& buffer)
-   TRY
-   {      
-      postProcessingGlobalAttributes();
-   }
-   CATCH_DUMP_ATTR
-
+   
    /*!
    \brief Close all the context defintion and do processing data
@@ -697,47 +908,334 @@
    and the active fields (fields will be written onto active files)
    */
-
-   void CContext::closeDefinition(void)
-   TRY
-   {
-    CTimer::get("Context : close definition").resume() ;
-    postProcessingGlobalAttributes();
-
-    if (hasClient) sendPostProcessingGlobalAttributes();
-
-    // There are some processings that should be done after all of above. For example: check mask or index
-    this->buildFilterGraphOfEnabledFields();
+  void CContext::closeDefinition(void)
+   TRY
+   {
+     CTimer::get("Context : close definition").resume() ;
+     
+     // create intercommunicator with servers. 
+     // not sure it is the good place to be called here 
+     createServerInterComm() ;
+
+
+     // After xml is parsed, there are some more works with post processing
+//     postProcessing();
+
     
-     if (hasClient && !hasServer)
-    {
-      buildFilterGraphOfFieldsWithReadAccess();
-      postProcessFilterGraph();
-    }
+    // Make sure the calendar was correctly created
+    if (serviceType_!=CServicesManager::CLIENT) CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
+    if (!calendar)
+      ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
+    else if (calendar->getTimeStep() == NoneDu)
+      ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
+    // Calendar first update to set the current date equals to the start date
+    calendar->update(0);
+
+    // RÃ©solution des hÃ©ritages descendants (cÃ d des hÃ©ritages de groupes)
+    // pour chacun des contextes.
+    solveDescInheritance(true);
+ 
+    // Solve inheritance for field to know if enabled or not.
+    for (auto field : CField::getAll()) field->solveRefInheritance();
+
+    // Check if some axis, domains or grids are eligible to for compressed indexed output.
+    // Warning: This must be done after solving the inheritance and before the rest of post-processing
+    // --> later ????    checkAxisDomainsGridsEligibilityForCompressedOutput();      
+
+      // Check if some automatic time series should be generated
+      // Warning: This must be done after solving the inheritance and before the rest of post-processing      
+
+    // The timeseries should only be prepared in client
+    prepareTimeseries();
+
+    //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers Ã  sortir.
+    findEnabledFiles();
+    findEnabledWriteModeFiles();
+    findEnabledReadModeFiles();
+    findEnabledCouplerIn();
+    findEnabledCouplerOut();
+    createCouplerInterCommunicator() ;
+
+    // Find all enabled fields of each file      
+    vector<CField*>&& fileOutField = findAllEnabledFieldsInFileOut(this->enabledWriteModeFiles);
+    vector<CField*>&& fileInField = findAllEnabledFieldsInFileIn(this->enabledReadModeFiles);
+    vector<CField*>&& couplerOutField = findAllEnabledFieldsCouplerOut(this->enabledCouplerOut);
+    vector<CField*>&& couplerInField = findAllEnabledFieldsCouplerIn(this->enabledCouplerIn);
+    findFieldsWithReadAccess();
+    vector<CField*>& fieldWithReadAccess = fieldsWithReadAccess_ ;
+    vector<CField*> fieldModelIn ; // fields potentially from model
+     
+    // define if files are on clientSied or serverSide 
+    if (serviceType_==CServicesManager::CLIENT)
+    {
+      for (auto& file : enabledWriteModeFiles) file->setClientSide() ;
+      for (auto& file : enabledReadModeFiles) file->setClientSide() ;
+    }
+    else
+    {
+      for (auto& file : enabledWriteModeFiles) file->setServerSide() ;
+      for (auto& file : enabledReadModeFiles) file->setServerSide() ;
+    }
+
     
-    checkGridEnabledFields();   
-
-    if (hasClient) this->sendProcessingGridOfEnabledFields();
-    if (hasClient) this->sendCloseDefinition();
-
-    // Nettoyage de l'arborescence
-    if (hasClient) CleanTree(); // Only on client side??
-
-    if (hasClient)
-    {
-      sendCreateFileHeader();
-      if (!hasServer) startPrefetchingOfEnabledReadModeFiles();
-    }
-    CTimer::get("Context : close definition").suspend() ;
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::findAllEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
-   TRY
-   {
-     for (unsigned int i = 0; i < activeFiles.size(); i++)
-     (void)activeFiles[i]->getEnabledFields();
-   }
-   CATCH_DUMP_ATTR
-
+    for (auto& field : couplerInField)
+    {
+      field->unsetGridCompleted() ;
+    }
+// find all field potentially at workflow end
+    vector<CField*> endWorkflowFields ;
+    endWorkflowFields.reserve(fileOutField.size()+couplerOutField.size()+fieldWithReadAccess.size()) ;
+    endWorkflowFields.insert(endWorkflowFields.end(),fileOutField.begin(), fileOutField.end()) ;
+    endWorkflowFields.insert(endWorkflowFields.end(),couplerOutField.begin(), couplerOutField.end()) ;
+    endWorkflowFields.insert(endWorkflowFields.end(),fieldWithReadAccess.begin(), fieldWithReadAccess.end()) ;
+
+    bool workflowGraphIsCompleted ;
+
+    bool first=true ;
+    do
+    {
+      workflowGraphIsCompleted=true; 
+      for(auto endWorkflowField : endWorkflowFields) 
+      {
+        workflowGraphIsCompleted &= endWorkflowField->buildWorkflowGraph(garbageCollector) ;
+      }
+
+      for(auto couplerIn : enabledCouplerIn) couplerIn->assignContext() ;
+      for(auto field : couplerInField) field->makeGridAliasForCoupling();
+      for(auto field : couplerInField) this->sendCouplerInReady(field->getContextClient()) ;
+    
+
+      // assign context to coupler out and related fields
+      for(auto couplerOut : enabledCouplerOut) couplerOut->assignContext() ;
+      // for now supose that all coupling out endpoint are succesfull. The difficultie is client/server buffer evaluation
+      for(auto field : couplerOutField) 
+      {
+        // connect to couplerOut -> to do
+      }
+      if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check
+   
+      bool couplersReady ;
+      do 
+      {
+        couplersReady=true ;
+        for(auto field : couplerOutField)
+        {
+          bool ready = isCouplerInReady(field->getContextClient()) ; 
+          if (ready) field->sendFieldToCouplerOut() ;
+          couplersReady &= ready ;
+        }
+        if (!couplersReady) this->eventLoop() ;
+      } while (!couplersReady) ;
+
+      first=false ;
+      this->eventLoop() ;
+    } while (!workflowGraphIsCompleted) ;
+
+    for( auto field : couplerInField) couplerInFields_.push_back(field) ;
+
+    // get all field coming potentially from model
+    for (auto field : CField::getAll() ) if (field->getModelIn()) fieldModelIn.push_back(field) ;
+
+    // Distribute files between secondary servers according to the data size => assign a context to a file and then to fields
+    if (serviceType_==CServicesManager::GATHERER) distributeFiles(this->enabledWriteModeFiles);
+    else if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledWriteModeFiles) file->setContextClient(client) ;
+
+    // client side, assign context for file reading
+    if (serviceType_==CServicesManager::CLIENT) for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
+    
+    // server side, assign context where to send file data read
+    if (serviceType_==CServicesManager::CServicesManager::GATHERER || serviceType_==CServicesManager::IO_SERVER) 
+      for(auto file : this->enabledReadModeFiles) file->setContextClient(client) ;
+   
+    // workflow endpoint => sent to IO/SERVER
+    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER)
+    {
+      for(auto field : fileOutField) 
+      {
+        field->connectToFileServer(garbageCollector) ; // connect the field to server filter
+      }
+      setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review
+      for(auto field : fileOutField) field->sendFieldToFileServer() ;
+    }
+
+    // workflow endpoint => write to file
+    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)
+    {
+      for(auto field : fileOutField) 
+      {
+        field->connectToFileWriter(garbageCollector) ; // connect the field to server filter
+      }
+    }
+    
+    // workflow endpoint => Send data from server to client
+    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
+    {
+      for(auto field : fileInField) 
+      {
+        field->connectToServerToClient(garbageCollector) ;
+      }
+    }
+
+    // workflow endpoint => sent to model on client side
+    if (serviceType_==CServicesManager::CLIENT)
+    {
+      for(auto field : fieldWithReadAccess) field->connectToModelOutput(garbageCollector) ;
+    }
+
+
+    // workflow startpoint => data from model
+    if (serviceType_==CServicesManager::CLIENT)
+    {
+      for(auto field : fieldModelIn) 
+      {
+        field->connectToModelInput(garbageCollector) ; // connect the field to server filter
+        // grid index will be computed on the fly
+      }
+    }
+    
+    // workflow startpoint => data from client on server side
+    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER || serviceType_==CServicesManager::OUT_SERVER)
+    {
+      for(auto field : fieldModelIn) 
+      {
+        field->connectToClientInput(garbageCollector) ; // connect the field to server filter
+      }
+    }
+
+    
+    for(auto field : couplerInField) 
+    {
+      field->connectToCouplerIn(garbageCollector) ; // connect the field to server filter
+    }
+    
+    
+    for(auto field : couplerOutField) 
+    {
+      field->connectToCouplerOut(garbageCollector) ; // for now the same kind of filter that for file server
+    }
+
+     // workflow startpoint => data from server on client side
+    if (serviceType_==CServicesManager::CLIENT)
+    {
+      for(auto field : fileInField) 
+      {
+        field->sendFieldToInputFileServer() ;
+        field->connectToServerInput(garbageCollector) ; // connect the field to server filter
+        fileInFields_.push_back(field) ;
+      }
+    }
+
+    // workflow startpoint => data read from file on server side
+    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::GATHERER)
+    {
+      for(auto field : fileInField) 
+      {
+        field->connectToFileReader(garbageCollector) ;
+      }
+    }
+    
+    // construct slave server list
+    if (serviceType_==CServicesManager::CLIENT || serviceType_==CServicesManager::GATHERER) 
+    {
+      for(auto field : fileOutField) slaveServers_.insert(field->getContextClient()) ; 
+      for(auto field : fileInField)  slaveServers_.insert(field->getContextClient()) ;  
+    }
+
+    for(auto& slaveServer : slaveServers_) sendCloseDefinition(slaveServer) ;
+
+    if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER)  
+    {
+      createFileHeader();
+    }
+
+    if (serviceType_==CServicesManager::CLIENT) startPrefetchingOfEnabledReadModeFiles();
+   
+    // send signal to couplerIn context that definition phasis is done
+
+    for(auto& couplerInClient : couplerInClient_) sendCouplerInCloseDefinition(couplerInClient.second) ;
+
+    // wait until all couplerIn signal that closeDefition is done.
+    bool ok;
+    do
+    {
+      ok = true ;
+      for(auto& couplerOutClient : couplerOutClient_) ok &= isCouplerInCloseDefinition(couplerOutClient.second) ;
+      this->eventLoop() ; 
+    } while (!ok) ;
+
+     CTimer::get("Context : close definition").suspend() ;
+  }
+  CATCH_DUMP_ATTR
+
+
+  vector<CField*> CContext::findAllEnabledFieldsInFileOut(const std::vector<CFile*>& activeFiles)
+   TRY
+   {
+     vector<CField*> fields ;
+     for(auto file : activeFiles)
+     {
+        const vector<CField*>&& fieldList=file->getEnabledFields() ;
+        for(auto field : fieldList) field->setFileOut(file) ;
+        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
+     }
+     return fields ;
+   }
+   CATCH_DUMP_ATTR
+
+   vector<CField*> CContext::findAllEnabledFieldsInFileIn(const std::vector<CFile*>& activeFiles)
+   TRY
+   {
+     vector<CField*> fields ;
+     for(auto file : activeFiles)
+     {
+        const vector<CField*>&& fieldList=file->getEnabledFields() ;
+        for(auto field : fieldList) field->setFileIn(file) ;
+        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
+     }
+     return fields ;
+   }
+   CATCH_DUMP_ATTR
+
+   vector<CField*> CContext::findAllEnabledFieldsCouplerOut(const std::vector<CCouplerOut*>& activeCouplerOut)
+   TRY
+   {
+     vector<CField*> fields ;
+     for (auto couplerOut :activeCouplerOut)
+     {
+        const vector<CField*>&& fieldList=couplerOut->getEnabledFields() ;
+        for(auto field : fieldList) field->setCouplerOut(couplerOut) ;
+        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
+     }
+     return fields ;
+   }
+   CATCH_DUMP_ATTR
+
+   vector<CField*> CContext::findAllEnabledFieldsCouplerIn(const std::vector<CCouplerIn*>& activeCouplerIn)
+   TRY
+   {
+     vector<CField*> fields ;
+     for (auto couplerIn :activeCouplerIn)
+     {
+        const vector<CField*>&& fieldList=couplerIn->getEnabledFields() ;
+        for(auto field : fieldList) field->setCouplerIn(couplerIn) ;
+        fields.insert(fields.end(),fieldList.begin(),fieldList.end());
+     }
+     return fields ;
+   }
+   CATCH_DUMP_ATTR
+
+ /*!
+  * Send context attribute and calendar to file server, it must be done once by context file server
+  * \param[in] client : context client to send   
+  */  
+  void CContext::sendContextToFileServer(CContextClient* client)
+  {
+    if (sendToFileServer_done_.count(client)!=0) return ;
+    else sendToFileServer_done_.insert(client) ;
+    
+    this->sendAllAttributesToServer(client); // Send all attributes of current context to server
+    CCalendarWrapper::get(CCalendarWrapper::GetDefName())->sendAllAttributesToServer(client); // Send all attributes of current cale
+  }
+
+ 
    void CContext::readAttributesOfEnabledFieldsInReadModeFiles()
    TRY
@@ -748,104 +1246,4 @@
    CATCH_DUMP_ATTR
 
-   void CContext::sendGridComponentEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
-   TRY
-   {
-     int size = activeFiles.size();
-     for (int i = 0; i < size; ++i)
-     {       
-       activeFiles[i]->sendGridComponentOfEnabledFields();
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
-      Send active (enabled) fields in file from a client to others
-      \param [in] activeFiles files contains enabled fields to send
-   */
-   void CContext::sendGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
-   TRY
-   {
-     int size = activeFiles.size();
-     for (int i = 0; i < size; ++i)
-     {       
-       activeFiles[i]->sendGridOfEnabledFields();
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::checkGridEnabledFields()
-   TRY
-   {
-     int size = enabledFiles.size();
-     for (int i = 0; i < size; ++i)
-     {
-       enabledFiles[i]->checkGridOfEnabledFields();       
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
-      Check grid of active (enabled) fields in file 
-      \param [in] activeFiles files contains enabled fields whose grid needs checking
-   */
-   void CContext::checkGridEnabledFieldsInFiles(const std::vector<CFile*>& activeFiles)
-   TRY
-   {
-     int size = activeFiles.size();
-     for (int i = 0; i < size; ++i)
-     {
-       activeFiles[i]->checkGridOfEnabledFields();       
-     }
-   }
-   CATCH_DUMP_ATTR
-
-    /*!
-      Go up the hierachical tree via field_ref and do check of attributes of fields
-      This can be done in a client then all computed information will be sent from this client to others
-      \param [in] sendToServer Flag to indicate whether calculated information will be sent
-   */
-   void CContext::solveOnlyRefOfEnabledFields(bool sendToServer)
-   TRY
-   {
-     int size = this->enabledFiles.size();
-     for (int i = 0; i < size; ++i)
-     {
-       this->enabledFiles[i]->solveOnlyRefOfEnabledFields(sendToServer);
-     }
-
-     for (int i = 0; i < size; ++i)
-     {
-       this->enabledFiles[i]->generateNewTransformationGridDest();
-     }
-   }
-   CATCH_DUMP_ATTR
-
-    /*!
-      Go up the hierachical tree via field_ref and do check of attributes of fields.
-      The transformation can be done in this step.
-      All computed information will be sent from this client to others.
-      \param [in] sendToServer Flag to indicate whether calculated information will be sent
-   */
-   void CContext::solveAllRefOfEnabledFieldsAndTransform(bool sendToServer)
-   TRY
-   {
-     int size = this->enabledFiles.size();
-     for (int i = 0; i < size; ++i)
-     {
-       this->enabledFiles[i]->solveAllRefOfEnabledFieldsAndTransform(sendToServer);
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::buildFilterGraphOfEnabledFields()
-   TRY
-   {
-     int size = this->enabledFiles.size();
-     for (int i = 0; i < size; ++i)
-     {
-       this->enabledFiles[i]->buildFilterGraphOfEnabledFields(garbageCollector);
-     }
-   }
-   CATCH_DUMP_ATTR
 
    void CContext::postProcessFilterGraph()
@@ -896,34 +1294,19 @@
   TRY
   {
-    fieldsWithReadAccess.clear();
+    fieldsWithReadAccess_.clear();
     const vector<CField*> allFields = CField::getAll();
     for (size_t i = 0; i < allFields.size(); ++i)
     {
       CField* field = allFields[i];
-
-      if (field->file && !field->file->mode.isEmpty() && field->file->mode == CFile::mode_attr::read)
-        field->read_access = true;
-      else if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
-        fieldsWithReadAccess.push_back(field);
+      if (!field->read_access.isEmpty() && field->read_access && (field->enabled.isEmpty() || field->enabled))
+      {
+        fieldsWithReadAccess_.push_back(field);
+        field->setModelOut() ;
+      }
     }
   }
   CATCH_DUMP_ATTR
 
-  void CContext::solveAllRefOfFieldsWithReadAccess()
-  TRY
-  {
-    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
-      fieldsWithReadAccess[i]->solveAllReferenceEnabledField(false);
-  }
-  CATCH_DUMP_ATTR
-
-  void CContext::buildFilterGraphOfFieldsWithReadAccess()
-  TRY
-  {
-    for (size_t i = 0; i < fieldsWithReadAccess.size(); ++i)
-      fieldsWithReadAccess[i]->buildFilterGraph(garbageCollector, true);
-  }
-  CATCH_DUMP_ATTR
-
+  
    void CContext::solveAllInheritance(bool apply)
    TRY
@@ -935,11 +1318,18 @@
      // RÃ©solution des hÃ©ritages par rÃ©fÃ©rence au niveau des fichiers.
       const vector<CFile*> allFiles=CFile::getAll();
+      const vector<CCouplerIn*> allCouplerIn=CCouplerIn::getAll();
+      const vector<CCouplerOut*> allCouplerOut=CCouplerOut::getAll();
       const vector<CGrid*> allGrids= CGrid::getAll();
 
-      if (hasClient && !hasServer)
-      //if (hasClient)
+      if (serviceType_==CServicesManager::CLIENT)
       {
         for (unsigned int i = 0; i < allFiles.size(); i++)
           allFiles[i]->solveFieldRefInheritance(apply);
+
+        for (unsigned int i = 0; i < allCouplerIn.size(); i++)
+          allCouplerIn[i]->solveFieldRefInheritance(apply);
+
+        for (unsigned int i = 0; i < allCouplerOut.size(); i++)
+          allCouplerOut[i]->solveFieldRefInheritance(apply);
       }
 
@@ -947,5 +1337,5 @@
       unsigned int i = 0;
       for (i = 0; i < vecSize; ++i)
-        allGrids[i]->solveDomainAxisRefInheritance(apply);
+        allGrids[i]->solveElementsRefInheritance(apply);
 
    }
@@ -1004,5 +1394,36 @@
    CATCH_DUMP_ATTR
 
-   void CContext::distributeFiles(void)
+   void CContext::findEnabledCouplerIn(void)
+   TRY
+   {
+      const std::vector<CCouplerIn*> allCouplerIn = CCouplerIn::getAll();
+      bool enabled ;
+      for (size_t i = 0; i < allCouplerIn.size(); i++)
+      {
+        if (allCouplerIn[i]->enabled.isEmpty()) enabled=true ;
+        else enabled=allCouplerIn[i]->enabled ;
+        if (enabled) enabledCouplerIn.push_back(allCouplerIn[i]) ;
+      }
+   }
+   CATCH_DUMP_ATTR
+
+   void CContext::findEnabledCouplerOut(void)
+   TRY
+   {
+      const std::vector<CCouplerOut*> allCouplerOut = CCouplerOut::getAll();
+      bool enabled ;
+      for (size_t i = 0; i < allCouplerOut.size(); i++)
+      {
+        if (allCouplerOut[i]->enabled.isEmpty()) enabled=true ;
+        else enabled=allCouplerOut[i]->enabled ;
+        if (enabled) enabledCouplerOut.push_back(allCouplerOut[i]) ;
+      }
+   }
+   CATCH_DUMP_ATTR
+
+
+
+
+   void CContext::distributeFiles(const vector<CFile*>& files)
    TRY
    {
@@ -1010,184 +1431,155 @@
      distFileMemory=CXios::getin<bool>("server2_dist_file_memory", distFileMemory);
 
-     if (distFileMemory) distributeFileOverMemoryBandwith() ;
-     else distributeFileOverBandwith() ;
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::distributeFileOverBandwith(void)
+     if (distFileMemory) distributeFileOverMemoryBandwith(files) ;
+     else distributeFileOverBandwith(files) ;
+   }
+   CATCH_DUMP_ATTR
+
+   void CContext::distributeFileOverBandwith(const vector<CFile*>& files)
    TRY
    {
      double eps=std::numeric_limits<double>::epsilon()*10 ;
      
-     // If primary server
-     if (hasServer && hasClient)
-     {
-       std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
-       int nbPools = clientPrimServer.size();
-
-       // (1) Find all enabled files in write mode
-       // for (int i = 0; i < this->enabledFiles.size(); ++i)
-       // {
-       //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
-       //    enabledWriteModeFiles.push_back(enabledFiles[i]);
-       // }
-
-       // (2) Estimate the data volume for each file
-       int size = this->enabledWriteModeFiles.size();
-       std::vector<std::pair<double, CFile*> > dataSizeMap;
-       double dataPerPool = 0;
-       int nfield=0 ;
-       ofs<<size<<endl ;
-       for (size_t i = 0; i < size; ++i)
+     std::ofstream ofs(("distribute_file_"+getId()+".dat").c_str(), std::ofstream::out);
+     int nbPools = clientPrimServer.size();
+
+     // (1) Find all enabled files in write mode
+     // for (int i = 0; i < this->enabledFiles.size(); ++i)
+     // {
+     //   if (enabledFiles[i]->mode.isEmpty() || (!enabledFiles[i]->mode.isEmpty() && enabledFiles[i]->mode.getValue() == CFile::mode_attr::write ))
+     //    enabledWriteModeFiles.push_back(enabledFiles[i]);
+     // }
+
+     // (2) Estimate the data volume for each file
+     int size = files.size();
+     std::vector<std::pair<double, CFile*> > dataSizeMap;
+     double dataPerPool = 0;
+     int nfield=0 ;
+     ofs<<size<<endl ;
+     for (size_t i = 0; i < size; ++i)
+     {
+       CFile* file = files[i];
+       ofs<<file->getId()<<endl ;
+       StdSize dataSize=0;
+       std::vector<CField*> enabledFields = file->getEnabledFields();
+       size_t numEnabledFields = enabledFields.size();
+       ofs<<numEnabledFields<<endl ;
+       for (size_t j = 0; j < numEnabledFields; ++j)
        {
-         CFile* file = this->enabledWriteModeFiles[i];
-         ofs<<file->getId()<<endl ;
-         StdSize dataSize=0;
-         std::vector<CField*> enabledFields = file->getEnabledFields();
-         size_t numEnabledFields = enabledFields.size();
-         ofs<<numEnabledFields<<endl ;
-         for (size_t j = 0; j < numEnabledFields; ++j)
+         dataSize += enabledFields[j]->getGlobalWrittenSize() ;
+         ofs<<enabledFields[j]->getGrid()->getId()<<endl ;
+         ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
+       }
+       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
+       double dataSizeSec= dataSize/ outFreqSec;
+       ofs<<dataSizeSec<<endl ;
+       nfield++ ;
+// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
+       dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
+       dataPerPool += dataSizeSec;
+     }
+     dataPerPool /= nbPools;
+     std::sort(dataSizeMap.begin(), dataSizeMap.end());
+
+     // (3) Assign contextClient to each enabled file
+
+     std::multimap<double,int> poolDataSize ;
+// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
+
+     int j;
+     double dataSize ;
+     for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ;  
+             
+     for (int i = dataSizeMap.size()-1; i >= 0; --i)
+     {
+       dataSize=(*poolDataSize.begin()).first ;
+       j=(*poolDataSize.begin()).second ;
+       dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
+       dataSize+=dataSizeMap[i].first;
+       poolDataSize.erase(poolDataSize.begin()) ;
+       poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
+     }
+
+     for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ;
+   }
+   CATCH_DUMP_ATTR
+
+   void CContext::distributeFileOverMemoryBandwith(const vector<CFile*>& filesList)
+   TRY
+   {
+     int nbPools = clientPrimServer.size();
+     double ratio=0.5 ;
+     ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
+
+     int nFiles = filesList.size();
+     vector<SDistFile> files(nFiles);
+     vector<SDistGrid> grids;
+     map<string,int> gridMap ;
+     string gridId; 
+     int gridIndex=0 ;
+
+     for (size_t i = 0; i < nFiles; ++i)
+     {
+       StdSize dataSize=0;
+       CFile* file = filesList[i];
+       std::vector<CField*> enabledFields = file->getEnabledFields();
+       size_t numEnabledFields = enabledFields.size();
+
+       files[i].id_=file->getId() ;
+       files[i].nbGrids_=numEnabledFields;
+       files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
+         
+       for (size_t j = 0; j < numEnabledFields; ++j)
+       {
+         gridId=enabledFields[j]->getGrid()->getId() ;
+         if (gridMap.find(gridId)==gridMap.end())
          {
-           dataSize += enabledFields[j]->getGlobalWrittenSize() ;
-           ofs<<enabledFields[j]->grid->getId()<<endl ;
-           ofs<<enabledFields[j]->getGlobalWrittenSize()<<endl ;
+            gridMap[gridId]=gridIndex  ;
+            SDistGrid newGrid; 
+            grids.push_back(newGrid) ;
+            gridIndex++ ;
          }
-         double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
-         double dataSizeSec= dataSize/ outFreqSec;
-         ofs<<dataSizeSec<<endl ;
-         nfield++ ;
-// add epsilon*nField to dataSizeSec in order to  preserve reproductive ordering when sorting
-         dataSizeMap.push_back(make_pair(dataSizeSec + dataSizeSec * eps * nfield , file));
-         dataPerPool += dataSizeSec;
+         files[i].assignedGrid_[j]=gridMap[gridId] ;
+         grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
+         dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
        }
-       dataPerPool /= nbPools;
-       std::sort(dataSizeMap.begin(), dataSizeMap.end());
-
-       // (3) Assign contextClient to each enabled file
-
-       std::multimap<double,int> poolDataSize ;
-// multimap is not garanty to preserve stable sorting in c++98 but it seems it does for c++11
-
-       int j;
-       double dataSize ;
-       for (j = 0 ; j < nbPools ; ++j) poolDataSize.insert(std::pair<double,int>(0.,j)) ;  
-              
-       for (int i = dataSizeMap.size()-1; i >= 0; --i)
+       double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
+       files[i].bandwith_= dataSize/ outFreqSec ;
+     }
+
+     double bandwith=0 ;
+     double memory=0 ;
+   
+     for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
+     for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
+
+     for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
+     for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
+       
+     distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
+
+     vector<double> memorySize(nbPools,0.) ;
+     vector< set<int> > serverGrids(nbPools) ;
+     vector<double> bandwithSize(nbPools,0.) ;
+       
+     for (size_t i = 0; i < nFiles; ++i)
+     {
+       bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
+       for(int j=0 ; j<files[i].nbGrids_;j++)
        {
-         dataSize=(*poolDataSize.begin()).first ;
-         j=(*poolDataSize.begin()).second ;
-         dataSizeMap[i].second->setContextClient(clientPrimServer[j]);
-         dataSize+=dataSizeMap[i].first;
-         poolDataSize.erase(poolDataSize.begin()) ;
-         poolDataSize.insert(std::pair<double,int>(dataSize,j)) ; 
+         if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
+         {
+           memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
+           serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
+         }
        }
-
-       for (std::multimap<double,int>:: iterator it=poolDataSize.begin() ; it!=poolDataSize.end(); ++it) info(30)<<"Load Balancing for servers (perfect=1) : "<<it->second<<" :  ratio "<<it->first*1./dataPerPool<<endl ;
- 
-       for (int i = 0; i < this->enabledReadModeFiles.size(); ++i)
-       {
-         enabledReadModeFiles[i]->setContextClient(client);          
-       }
-     }
-     else
-     {
-       for (int i = 0; i < this->enabledFiles.size(); ++i)
-         enabledFiles[i]->setContextClient(client);
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   void CContext::distributeFileOverMemoryBandwith(void)
-   TRY
-   {
-     // If primary server
-     if (hasServer && hasClient)
-     {
-       int nbPools = clientPrimServer.size();
-       double ratio=0.5 ;
-       ratio=CXios::getin<double>("server2_dist_file_memory_ratio", ratio);
-
-       int nFiles = this->enabledWriteModeFiles.size();
-       vector<SDistFile> files(nFiles);
-       vector<SDistGrid> grids;
-       map<string,int> gridMap ;
-       string gridId; 
-       int gridIndex=0 ;
-
-       for (size_t i = 0; i < nFiles; ++i)
-       {
-         StdSize dataSize=0;
-         CFile* file = this->enabledWriteModeFiles[i];
-         std::vector<CField*> enabledFields = file->getEnabledFields();
-         size_t numEnabledFields = enabledFields.size();
-
-         files[i].id_=file->getId() ;
-         files[i].nbGrids_=numEnabledFields;
-         files[i].assignedGrid_ = new int[files[i].nbGrids_] ;
-         
-         for (size_t j = 0; j < numEnabledFields; ++j)
-         {
-           gridId=enabledFields[j]->grid->getId() ;
-           if (gridMap.find(gridId)==gridMap.end())
-           {
-              gridMap[gridId]=gridIndex  ;
-              SDistGrid newGrid; 
-              grids.push_back(newGrid) ;
-              gridIndex++ ;
-           }
-           files[i].assignedGrid_[j]=gridMap[gridId] ;
-           grids[files[i].assignedGrid_[j]].size_=enabledFields[j]->getGlobalWrittenSize() ;
-           dataSize += enabledFields[j]->getGlobalWrittenSize() ; // usefull
-         }
-         double outFreqSec = (Time)(calendar->getCurrentDate()+file->output_freq)-(Time)(calendar->getCurrentDate()) ;
-         files[i].bandwith_= dataSize/ outFreqSec ;
-       }
-
-       double bandwith=0 ;
-       double memory=0 ;
-   
-       for(int i=0; i<nFiles; i++)  bandwith+=files[i].bandwith_ ;
-       for(int i=0; i<nFiles; i++)  files[i].bandwith_ = files[i].bandwith_/bandwith * ratio ;
-
-       for(int i=0; i<grids.size(); i++)  memory+=grids[i].size_ ;
-       for(int i=0; i<grids.size(); i++)  grids[i].size_ = grids[i].size_ / memory * (1.0-ratio) ;
-       
-       distributeFileOverServer2(nbPools, grids.size(), &grids[0], nFiles, &files[0]) ;
-
-       vector<double> memorySize(nbPools,0.) ;
-       vector< set<int> > serverGrids(nbPools) ;
-       vector<double> bandwithSize(nbPools,0.) ;
-       
-       for (size_t i = 0; i < nFiles; ++i)
-       {
-         bandwithSize[files[i].assignedServer_] += files[i].bandwith_* bandwith /ratio ;
-         for(int j=0 ; j<files[i].nbGrids_;j++)
-         {
-           if (serverGrids[files[i].assignedServer_].find(files[i].assignedGrid_[j]) == serverGrids[files[i].assignedServer_].end())
-           {
-             memorySize[files[i].assignedServer_]+= grids[files[i].assignedGrid_[j]].size_ * memory / (1.0-ratio);
-             serverGrids[files[i].assignedServer_].insert(files[i].assignedGrid_[j]) ;
-           }
-         }
-         enabledWriteModeFiles[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
-         delete [] files[i].assignedGrid_ ;
-       }
-
-       for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ;
-       for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
-
-
-       for (int i = 0; i < this->enabledReadModeFiles.size(); ++i)
-       {
-         enabledReadModeFiles[i]->setContextClient(client);          
-       }
-
-   }
-   else
-   {
-     for (int i = 0; i < this->enabledFiles.size(); ++i)
-        enabledFiles[i]->setContextClient(client);
-   }
-}
+       filesList[i]->setContextClient(clientPrimServer[files[i].assignedServer_]) ;
+       delete [] files[i].assignedGrid_ ;
+     }
+
+     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned file bandwith "<<bandwithSize[i]*86400.*4./1024/1024.<<" Mb / days"<<endl ;
+     for (int i = 0; i < nbPools; ++i) info(100)<<"Pool server level2 "<<i<<"   assigned grid memory "<<memorySize[i]*100/1024./1024.<<" Mb"<<endl ;
+
+   }
    CATCH_DUMP_ATTR
 
@@ -1265,19 +1657,20 @@
              return true;
              break;
-           case EVENT_ID_POST_PROCESS:
-             recvPostProcessing(event);
-             return true;
-            case EVENT_ID_SEND_REGISTRY:
+           case EVENT_ID_SEND_REGISTRY:
              recvRegistry(event);
              return true;
              break;
-            case EVENT_ID_POST_PROCESS_GLOBAL_ATTRIBUTES:
-             recvPostProcessingGlobalAttributes(event);
+           case EVENT_ID_COUPLER_IN_READY:
+             recvCouplerInReady(event);
              return true;
              break;
-            case EVENT_ID_PROCESS_GRID_ENABLED_FIELDS:
-             recvProcessingGridOfEnabledFields(event);
+           case EVENT_ID_COUPLER_IN_CLOSE_DEFINITION:
+             recvCouplerInCloseDefinition(event);
              return true;
              break;
+           case EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED:
+             recvCouplerInContextFinalized(event);
+             return true;
+             break;  
            default :
              ERROR("bool CContext::dispatchEvent(CEventServer& event)",
@@ -1290,20 +1683,22 @@
 
    //! Client side: Send a message to server to make it close
+   // ym obsolete
    void CContext::sendCloseDefinition(void)
    TRY
    {
-     // Use correct context client to send message
-     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
-     for (int i = 0; i < nbSrvPools; ++i)
-     {
-       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
+    int nbSrvPools ;
+    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
+    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
+    else nbSrvPools = 0 ;
+    CContextClient* contextClientTmp ;
+
+    for (int i = 0; i < nbSrvPools; ++i)
+     {
+       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
+       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
        CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
        if (contextClientTmp->isServerLeader())
        {
          CMessage msg;
-         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)
@@ -1315,4 +1710,22 @@
    }
    CATCH_DUMP_ATTR
+   
+   //  ! Client side: Send a message to server to make it close
+   void CContext::sendCloseDefinition(CContextClient* client)
+   TRY
+   {
+      if (sendCloseDefinition_done_.count(client)!=0) return ;
+      else sendCloseDefinition_done_.insert(client) ;
+
+      CEventClient event(getType(),EVENT_ID_CLOSE_DEFINITION);
+      if (client->isServerLeader())
+      {
+        CMessage msg;
+        for(auto rank : client->getRanksServerLeader()) event.push(rank,1,msg);
+        client->sendEvent(event);
+      }
+     else client->sendEvent(event);
+   }
+   CATCH_DUMP_ATTR
 
    //! Server side: Receive a message of client announcing a context close
@@ -1321,7 +1734,5 @@
    {
       CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;
-      get(id)->closeDefinition();
+      getCurrent()->closeDefinition();
    }
    CATCH
@@ -1331,24 +1742,15 @@
    TRY
    {
-     // Use correct context client to send message
-    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
-     for (int i = 0; i < nbSrvPools; ++i)
-     {
-       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
-       CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
-
-         if (contextClientTmp->isServerLeader())
-         {
-           CMessage msg;
-           if (hasServer)
-             msg<<this->getIdServer(i)<<step;
-           else
-             msg<<this->getIdServer()<<step;
-           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
-           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
-             event.push(*itRank,1,msg);
-           contextClientTmp->sendEvent(event);
-         }
-         else contextClientTmp->sendEvent(event);
+     CEventClient event(getType(),EVENT_ID_UPDATE_CALENDAR);
+     for(auto client : slaveServers_) 
+     {
+       if (client->isServerLeader())
+       {
+         CMessage msg;
+         msg<<step;
+         for (auto& rank : client->getRanksServerLeader() ) event.push(rank,1,msg);
+         client->sendEvent(event);
+       }
+       else client->sendEvent(event);
      }
    }
@@ -1360,7 +1762,5 @@
    {
       CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;
-      get(id)->recvUpdateCalendar(*buffer);
+      getCurrent()->recvUpdateCalendar(*buffer);
    }
    CATCH
@@ -1373,5 +1773,5 @@
       buffer>>step;
       updateCalendar(step);
-      if (hasClient && hasServer)
+      if (serviceType_==CServicesManager::GATHERER)
       {        
         sendUpdateCalendar(step);
@@ -1384,10 +1784,14 @@
    TRY
    {
-     // Use correct context client to send message
-     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
-     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
+     int nbSrvPools ;
+     if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
+     else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
+     else nbSrvPools = 0 ;
+     CContextClient* contextClientTmp ;
+
      for (int i = 0; i < nbSrvPools; ++i)
      {
-       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
+       if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
+       else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
        CEventClient event(getType(),EVENT_ID_CREATE_FILE_HEADER);
 
@@ -1395,8 +1799,4 @@
        {
          CMessage msg;
-         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)
@@ -1414,7 +1814,5 @@
    {
       CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;
-      get(id)->recvCreateFileHeader(*buffer);
+      getCurrent()->recvCreateFileHeader(*buffer);
    }
    CATCH
@@ -1424,281 +1822,60 @@
    TRY
    {
-      if (!hasClient && hasServer) 
+      if (serviceType_==CServicesManager::IO_SERVER || serviceType_==CServicesManager::OUT_SERVER) 
         createFileHeader();
    }
    CATCH_DUMP_ATTR
 
-   //! Client side: Send a message to do some post processing on server
-   void CContext::sendProcessingGridOfEnabledFields()
-   TRY
-   {
-      // Use correct context client to send message
-     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
-     for (int i = 0; i < nbSrvPools; ++i)
-     {
-       CContextClient* contextClientTmp = (0 != clientPrimServer.size()) ? clientPrimServer[i] : client;
-       CEventClient event(getType(),EVENT_ID_PROCESS_GRID_ENABLED_FIELDS);
-
-       if (contextClientTmp->isServerLeader())
-       {
-         CMessage msg;
-         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)
-           event.push(*itRank,1,msg);
-         contextClientTmp->sendEvent(event);
-       }
-       else contextClientTmp->sendEvent(event);
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   //! Server side: Receive a message to do some post processing
-   void CContext::recvProcessingGridOfEnabledFields(CEventServer& event)
-   TRY
-   {
-      CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;      
-   }
-   CATCH
-
-   //! Client side: Send a message to do some post processing on server
-   void CContext::sendPostProcessing()
-   TRY
-   {
-      // Use correct context client to send message
-     // int nbSrvPools = (hasServer) ? clientPrimServer.size() : 1;
-     int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
-     for (int i = 0; i < nbSrvPools; ++i)
-     {
-       CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
-       CEventClient event(getType(),EVENT_ID_POST_PROCESS);
-       if (contextClientTmp->isServerLeader())
-       {
-         CMessage msg;
-         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)
-         event.push(*itRank,1,msg);
-         contextClientTmp->sendEvent(event);
-       }
-       else contextClientTmp->sendEvent(event);
-     }
-   }
-   CATCH_DUMP_ATTR
-
-   //! Server side: Receive a message to do some post processing
-   void CContext::recvPostProcessing(CEventServer& event)
-   TRY
-   {
-      CBufferIn* buffer=event.subEvents.begin()->buffer;
-      string id;
-      *buffer>>id;
-      get(id)->recvPostProcessing(*buffer);
-   }
-   CATCH
-
-   //! Server side: Receive a message to do some post processing
-   void CContext::recvPostProcessing(CBufferIn& buffer)
-   TRY
-   {
-      CCalendarWrapper::get(CCalendarWrapper::GetDefName())->createCalendar();
-      postProcessing();
-   }
-   CATCH_DUMP_ATTR
-
-   const StdString& CContext::getIdServer()
-   TRY
-   {
-      if (hasClient)
-      {
-        idServer_ = this->getId();
-        idServer_ += "_server";
-        return idServer_;
-      }
-      if (hasServer) return (this->getId());
-   }
-   CATCH_DUMP_ATTR
-
-   const StdString& CContext::getIdServer(const int i)
-   TRY
-   {
-     idServer_ = this->getId();
-     idServer_ += "_server_";
-     idServer_ += std::to_string(static_cast<unsigned long long>(i));
-     return idServer_;
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
-   \brief Do some simple post processings after parsing xml file
-      After the xml file (iodef.xml) is parsed, it is necessary to build all relations among
-   created object, e.g: inhertance among fields, domain, axis. After that, all fiels as well as their parents (reference fields),
-   which will be written out into netcdf files, are processed
-   */
-   void CContext::postProcessing()
-   TRY
-   {
-     if (isPostProcessed) return;
-
-      // Make sure the calendar was correctly created
-      if (!calendar)
-        ERROR("CContext::postProcessing()", << "A calendar must be defined for the context \"" << getId() << "!\"")
-      else if (calendar->getTimeStep() == NoneDu)
-        ERROR("CContext::postProcessing()", << "A timestep must be defined for the context \"" << getId() << "!\"")
-      // Calendar first update to set the current date equals to the start date
-      calendar->update(0);
-
-      // Find all inheritance in xml structure
-      this->solveAllInheritance();
-
-//      ShowTree(info(10));
-
-      // Check if some axis, domains or grids are eligible to for compressed indexed output.
-      // Warning: This must be done after solving the inheritance and before the rest of post-processing
-      checkAxisDomainsGridsEligibilityForCompressedOutput();      
-
-      // Check if some automatic time series should be generated
-      // Warning: This must be done after solving the inheritance and before the rest of post-processing      
-
-      // The timeseries should only be prepared in client
-      if (hasClient && !hasServer) prepareTimeseries();
-
-      //Initialisation du vecteur 'enabledFiles' contenant la liste des fichiers Ã  sortir.
-      findEnabledFiles();
-      findEnabledWriteModeFiles();
-      findEnabledReadModeFiles();
-
-      // For now, only read files with client and only one level server
-      // if (hasClient && !hasServer) findEnabledReadModeFiles();      
-
-      // Find all enabled fields of each file      
-      findAllEnabledFieldsInFiles(this->enabledWriteModeFiles);
-      findAllEnabledFieldsInFiles(this->enabledReadModeFiles);
-
-      // For now, only read files with client and only one level server
-      // if (hasClient && !hasServer) 
-      //   findAllEnabledFieldsInFiles(this->enabledReadModeFiles);      
-
-      if (hasClient && !hasServer)
-      {
-        initReadFiles();
-        // Try to read attributes of fields in file then fill in corresponding grid (or domain, axis)
-        this->readAttributesOfEnabledFieldsInReadModeFiles();
-      }
-
-      // Only search and rebuild all reference objects of enable fields, don't transform
-      this->solveOnlyRefOfEnabledFields(false);
-
-      // Search and rebuild all reference object of enabled fields, and transform
-      this->solveAllRefOfEnabledFieldsAndTransform(false);
-
-      // Find all fields with read access from the public API
-      if (hasClient && !hasServer) findFieldsWithReadAccess();
-      // and solve the all reference for them
-      if (hasClient && !hasServer) solveAllRefOfFieldsWithReadAccess();
-
-      isPostProcessed = true;
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
-    * Compute the required buffer size to send the attributes (mostly those grid related).
-    * \param maxEventSize [in/out] the size of the bigger event for each connected server
-    * \param [in] contextClient
-    * \param [in] bufferForWriting True if buffers are used for sending data for writing
-      This flag is only true for client and server-1 for communication with server-2
-    */
-   std::map<int, StdSize> CContext::getAttributesBufferSize(std::map<int, StdSize>& maxEventSize,
-                                                           CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
-   TRY
-   {
-	 // As calendar attributes are sent even if there are no active files or fields, maps are initialized according the size of calendar attributes
-     std::map<int, StdSize> attributesSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
-     maxEventSize = CCalendarWrapper::get(CCalendarWrapper::GetDefName())->getMinimumBufferSizeForAttributes(contextClient);
-
-     std::vector<CFile*>& fileList = this->enabledFiles;
-     size_t numEnabledFiles = fileList.size();
-     for (size_t i = 0; i < numEnabledFiles; ++i)
-     {
-//         CFile* file = this->enabledWriteModeFiles[i];
-        CFile* file = fileList[i];
-        std::vector<CField*> enabledFields = file->getEnabledFields();
-        size_t numEnabledFields = enabledFields.size();
-        for (size_t j = 0; j < numEnabledFields; ++j)
+   void CContext::createCouplerInterCommunicator(void)
+   TRY
+   {
+      int rank=this->getIntraCommRank() ;
+      map<string,list<CCouplerOut*>> listCouplerOut ;  
+      map<string,list<CCouplerIn*>> listCouplerIn ;  
+
+      for(auto couplerOut : enabledCouplerOut) listCouplerOut[couplerOut->getCouplingContextId()].push_back(couplerOut) ;
+      for(auto couplerIn : enabledCouplerIn) listCouplerIn[couplerIn->getCouplingContextId()].push_back(couplerIn) ;
+
+      CCouplerManager* couplerManager = CXios::getCouplerManager() ;
+      if (rank==0)
+      {
+        for(auto couplerOut : listCouplerOut) couplerManager->registerCoupling(this->getContextId(),couplerOut.first) ;
+        for(auto couplerIn : listCouplerIn) couplerManager->registerCoupling(couplerIn.first,this->getContextId()) ;
+      }
+
+      do
+      {
+        for(auto couplerOut : listCouplerOut) 
         {
-          const std::map<int, StdSize> mapSize = enabledFields[j]->getGridAttributesBufferSize(contextClient, bufferForWriting);
-          std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.end();
-          for (; it != itE; ++it)
+          bool isNextCoupling ;
+          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(this->getContextId(),couplerOut.first) ;
+          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
+          if (isNextCoupling) 
           {
-		     // If attributesSize[it->first] does not exist, it will be zero-initialized
-		     // so we can use it safely without checking for its existence
-             if (attributesSize[it->first] < it->second)
-			   attributesSize[it->first] = it->second;
-
-		     if (maxEventSize[it->first] < it->second)
-			   maxEventSize[it->first] = it->second;
-          }
+            addCouplingChanel(couplerOut.first, true) ;
+            listCouplerOut.erase(couplerOut.first) ;
+            break ;
+          }            
         }
-     }
-     return attributesSize;
-   }
-   CATCH_DUMP_ATTR
-
-   /*!
-    * Compute the required buffer size to send the fields data.
-    * \param maxEventSize [in/out] the size of the bigger event for each connected server
-    * \param [in] contextClient
-    * \param [in] bufferForWriting True if buffers are used for sending data for writing
-      This flag is only true for client and server-1 for communication with server-2
-    */
-   std::map<int, StdSize> CContext::getDataBufferSize(std::map<int, StdSize>& maxEventSize,
-                                                      CContextClient* contextClient, bool bufferForWriting /*= "false"*/)
-   TRY
-   {
-     std::map<int, StdSize> dataSize;
-
-     // Find all reference domain and axis of all active fields
-     std::vector<CFile*>& fileList = bufferForWriting ? this->enabledWriteModeFiles : this->enabledReadModeFiles;
-     size_t numEnabledFiles = fileList.size();
-     for (size_t i = 0; i < numEnabledFiles; ++i)
-     {
-       CFile* file = fileList[i];
-       if (file->getContextClient() == contextClient)
-       {
-         std::vector<CField*> enabledFields = file->getEnabledFields();
-         size_t numEnabledFields = enabledFields.size();
-         for (size_t j = 0; j < numEnabledFields; ++j)
-         {
-           // const std::vector<std::map<int, StdSize> > mapSize = enabledFields[j]->getGridDataBufferSize(contextClient);
-           const std::map<int, StdSize> mapSize = enabledFields[j]->getGridDataBufferSize(contextClient,bufferForWriting);
-           std::map<int, StdSize>::const_iterator it = mapSize.begin(), itE = mapSize.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;
-           }
-         }
-       }
-     }
-     return dataSize;
-   }
-   CATCH_DUMP_ATTR
-
-   //! Client side: Send infomation of active files (files are enabled to write out)
+        for(auto couplerIn : listCouplerIn) 
+        {
+          bool isNextCoupling ;
+          if (rank==0) isNextCoupling = couplerManager->isNextCoupling(couplerIn.first,this->getContextId());
+          MPI_Bcast(&isNextCoupling,1,MPI_C_BOOL, 0, getIntraComm()) ; 
+          if (isNextCoupling) 
+          {
+            addCouplingChanel(couplerIn.first, false) ;
+            listCouplerIn.erase(couplerIn.first) ;
+            break ;
+          }           
+        }
+
+      } while (!listCouplerOut.empty() || !listCouplerIn.empty()) ;
+
+   }
+   CATCH_DUMP_ATTR
+
+  
+     //! Client side: Send infomation of active files (files are enabled to write out)
    void CContext::sendEnabledFiles(const std::vector<CFile*>& activeFiles)
    TRY
@@ -1734,30 +1911,9 @@
    CATCH_DUMP_ATTR
 
-   //! Client side: Check if the defined axis, domains and grids are eligible for compressed indexed output
-   void CContext::checkAxisDomainsGridsEligibilityForCompressedOutput()
-   TRY
-   {
-     if (!hasClient) return;
-
-     const vector<CAxis*> allAxis = CAxis::getAll();
-     for (vector<CAxis*>::const_iterator it = allAxis.begin(); it != allAxis.end(); it++)
-       (*it)->checkEligibilityForCompressedOutput();
-
-     const vector<CDomain*> allDomains = CDomain::getAll();
-     for (vector<CDomain*>::const_iterator it = allDomains.begin(); it != allDomains.end(); it++)
-       (*it)->checkEligibilityForCompressedOutput();
-
-     const vector<CGrid*> allGrids = CGrid::getAll();
-     for (vector<CGrid*>::const_iterator it = allGrids.begin(); it != allGrids.end(); it++)
-       (*it)->checkEligibilityForCompressedOutput();
-   }
-   CATCH_DUMP_ATTR
-
+  
    //! Client side: Prepare the timeseries by adding the necessary files
    void CContext::prepareTimeseries()
    TRY
    {
-     if (!hasClient) return;
-
      const std::vector<CFile*> allFiles = CFile::getAll();
      for (size_t i = 0; i < allFiles.size(); i++)
@@ -1856,45 +2012,10 @@
    CATCH_DUMP_ATTR
 
-   //! Client side: Send information of reference grid of active fields
-   void CContext::sendRefGrid(const std::vector<CFile*>& activeFiles)
-   TRY
-   {
-     std::set<StdString> gridIds;
-     int sizeFile = activeFiles.size();
-     CFile* filePtr(NULL);
-
-     // Firstly, find all reference grids of all active fields
-     for (int i = 0; i < sizeFile; ++i)
-     {
-       filePtr = activeFiles[i];
-       std::vector<CField*> enabledFields = filePtr->getEnabledFields();
-       int sizeField = enabledFields.size();
-       for (int numField = 0; numField < sizeField; ++numField)
-       {
-         if (0 != enabledFields[numField]->getRelGrid())
-           gridIds.insert(CGrid::get(enabledFields[numField]->getRelGrid())->getId());
-       }
-     }
-
-     // Create all reference grids on server side
-     StdString gridDefRoot("grid_definition");
-     CGridGroup* gridPtr = CGridGroup::get(gridDefRoot);
-     std::set<StdString>::const_iterator it, itE = gridIds.end();
-     for (it = gridIds.begin(); it != itE; ++it)
-     {
-       gridPtr->sendCreateChild(*it);
-       CGrid::get(*it)->sendAllAttributesToServer();
-       CGrid::get(*it)->sendAllDomains();
-       CGrid::get(*it)->sendAllAxis();
-       CGrid::get(*it)->sendAllScalars();
-     }
-   }
-   CATCH_DUMP_ATTR
-
+  
    //! Client side: Send information of reference domain, axis and scalar of active fields
    void CContext::sendRefDomainsAxisScalars(const std::vector<CFile*>& activeFiles)
    TRY
    {
-     std::set<StdString> domainIds, axisIds, scalarIds;
+     std::set<pair<StdString,CContextClient*>> domainIds, axisIds, scalarIds;
 
      // Find all reference domain and axis of all active fields
@@ -1906,8 +2027,9 @@
        for (int j = 0; j < numEnabledFields; ++j)
        {
+         CContextClient* contextClient=enabledFields[j]->getContextClient() ;
          const std::vector<StdString>& prDomAxisScalarId = enabledFields[j]->getRefDomainAxisIds();
-         if ("" != prDomAxisScalarId[0]) domainIds.insert(prDomAxisScalarId[0]);
-         if ("" != prDomAxisScalarId[1]) axisIds.insert(prDomAxisScalarId[1]);
-         if ("" != prDomAxisScalarId[2]) scalarIds.insert(prDomAxisScalarId[2]);
+         if ("" != prDomAxisScalarId[0]) domainIds.insert(make_pair(prDomAxisScalarId[0],contextClient));
+         if ("" != prDomAxisScalarId[1]) axisIds.insert(make_pair(prDomAxisScalarId[1],contextClient));
+         if ("" != prDomAxisScalarId[2]) scalarIds.insert(make_pair(prDomAxisScalarId[2],contextClient));
        }
      }
@@ -1919,11 +2041,11 @@
      StdString scalarDefRoot("scalar_definition");
      CScalarGroup* scalarPtr = CScalarGroup::get(scalarDefRoot);
-     itE = scalarIds.end();
-     for (itScalar = scalarIds.begin(); itScalar != itE; ++itScalar)
-     {
-       if (!itScalar->empty())
+     
+     for (auto itScalar = scalarIds.begin(); itScalar != scalarIds.end(); ++itScalar)
+     {
+       if (!itScalar->first.empty())
        {
-         scalarPtr->sendCreateChild(*itScalar);
-         CScalar::get(*itScalar)->sendAllAttributesToServer();
+         scalarPtr->sendCreateChild(itScalar->first,itScalar->second);
+         CScalar::get(itScalar->first)->sendAllAttributesToServer(itScalar->second);
        }
      }
@@ -1931,11 +2053,11 @@
      StdString axiDefRoot("axis_definition");
      CAxisGroup* axisPtr = CAxisGroup::get(axiDefRoot);
-     itE = axisIds.end();
-     for (itAxis = axisIds.begin(); itAxis != itE; ++itAxis)
-     {
-       if (!itAxis->empty())
+     
+     for (auto itAxis = axisIds.begin(); itAxis != axisIds.end(); ++itAxis)
+     {
+       if (!itAxis->first.empty())
        {
-         axisPtr->sendCreateChild(*itAxis);
-         CAxis::get(*itAxis)->sendAllAttributesToServer();
+         axisPtr->sendCreateChild(itAxis->first, itAxis->second);
+         CAxis::get(itAxis->first)->sendAllAttributesToServer(itAxis->second);
        }
      }
@@ -1944,12 +2066,20 @@
      StdString domDefRoot("domain_definition");
      CDomainGroup* domPtr = CDomainGroup::get(domDefRoot);
-     itE = domainIds.end();
-     for (itDom = domainIds.begin(); itDom != itE; ++itDom)
-     {
-       if (!itDom->empty()) {
-          domPtr->sendCreateChild(*itDom);
-          CDomain::get(*itDom)->sendAllAttributesToServer();
+     
+     for (auto itDom = domainIds.begin(); itDom != domainIds.end(); ++itDom)
+     {
+       if (!itDom->first.empty()) {
+          domPtr->sendCreateChild(itDom->first, itDom->second);
+          CDomain::get(itDom->first)->sendAllAttributesToServer(itDom->second);
        }
      }
+   }
+   CATCH_DUMP_ATTR
+
+   void CContext::triggerLateFields(void)
+   TRY
+   {
+    for(auto& field : fileInFields_) field->triggerLateField() ;
+    for(auto& field : couplerInFields_) field->triggerLateField() ;
    }
    CATCH_DUMP_ATTR
@@ -1963,7 +2093,7 @@
       if (prevStep < step)
       {
-        if (hasClient && !hasServer) // For now we only use server level 1 to read data
+        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
         {
-          doPreTimestepOperationsForEnabledReadModeFiles();
+          triggerLateFields();
         }
 
@@ -1975,5 +2105,5 @@
   #endif
 
-        if (hasClient && !hasServer) // For now we only use server level 1 to read data
+        if (serviceType_==CServicesManager::CLIENT) // For now we only use server level 1 to read data
         {
           doPostTimestepOperationsForEnabledReadModeFiles();
@@ -2007,6 +2137,6 @@
       vector<CFile*>::const_iterator it;
 
-      for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
-      // for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
+      //for (it=enabledFiles.begin(); it != enabledFiles.end(); it++)
+      for (it=enabledWriteModeFiles.begin(); it != enabledWriteModeFiles.end(); it++)
       {
          (*it)->initWrite();
@@ -2064,7 +2194,5 @@
   {
     CBufferIn* buffer=event.subEvents.begin()->buffer;
-    string id;
-    *buffer>>id;
-    get(id)->recvRegistry(*buffer);
+    getCurrent()->recvRegistry(*buffer);
   }
   CATCH
@@ -2087,27 +2215,195 @@
     registryOut->hierarchicalGatherRegistry() ;
 
-    // Use correct context client to send message
-    int nbSrvPools = (this->hasServer) ? (this->hasClient ? this->clientPrimServer.size() : 0) : 1;
+    int nbSrvPools ;
+    if (serviceType_==CServicesManager::CLIENT) nbSrvPools = 1 ;
+    else if (serviceType_==CServicesManager::GATHERER) nbSrvPools = this->clientPrimServer.size() ;
+    else nbSrvPools = 0 ;
+    CContextClient* contextClientTmp ;
+
     for (int i = 0; i < nbSrvPools; ++i)
     {
-      CContextClient* contextClientTmp = (hasServer) ? clientPrimServer[i] : client;
+      if (serviceType_==CServicesManager::CLIENT) contextClientTmp = client ;
+      else if (serviceType_==CServicesManager::GATHERER ) contextClientTmp = clientPrimServer[i] ;
+
       CEventClient event(CContext::GetType(), CContext::EVENT_ID_SEND_REGISTRY);
-        if (contextClientTmp->isServerLeader())
-        {
-           CMessage msg ;
-           if (hasServer)
-             msg<<this->getIdServer(i);
-           else
-             msg<<this->getIdServer();
-           if (contextClientTmp->clientRank==0) msg<<*registryOut ;
-           const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
-           for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+      if (contextClientTmp->isServerLeader())
+      {
+        CMessage msg ;
+        if (contextClientTmp->clientRank==0) msg<<*registryOut ;
+        const std::list<int>& ranks = contextClientTmp->getRanksServerLeader();
+        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
              event.push(*itRank,1,msg);
-           contextClientTmp->sendEvent(event);
-         }
-         else contextClientTmp->sendEvent(event);
+        contextClientTmp->sendEvent(event);
+      }
+      else contextClientTmp->sendEvent(event);
     }
   }
   CATCH_DUMP_ATTR
+
+  
+  void CContext::sendFinalizeClient(CContextClient* contextClient, const string& contextClientId)
+  TRY
+  {
+    CEventClient event(getType(),EVENT_ID_CONTEXT_FINALIZE_CLIENT);
+    if (contextClient->isServerLeader())
+    {
+      CMessage msg;
+      msg<<contextClientId ;
+      const std::list<int>& ranks = contextClient->getRanksServerLeader();
+      for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank)
+           event.push(*itRank,1,msg);
+      contextClient->sendEvent(event);
+    }
+    else contextClient->sendEvent(event);
+  }
+  CATCH_DUMP_ATTR
+
+ 
+  void CContext::recvFinalizeClient(CEventServer& event)
+  TRY
+  {
+    CBufferIn* buffer=event.subEvents.begin()->buffer;
+    string id;
+    *buffer>>id;
+    get(id)->recvFinalizeClient(*buffer);
+  }
+  CATCH
+
+  void CContext::recvFinalizeClient(CBufferIn& buffer)
+  TRY
+  {
+    countChildContextFinalized_++ ;
+  }
+  CATCH_DUMP_ATTR
+
+
+
+
+ //! Client side: Send a message  announcing that context can receive grid definition from coupling
+   void CContext::sendCouplerInReady(CContextClient* client)
+   TRY
+   {
+      if (sendCouplerInReady_done_.count(client)!=0) return ;
+      else sendCouplerInReady_done_.insert(client) ;
+
+      CEventClient event(getType(),EVENT_ID_COUPLER_IN_READY);
+
+      if (client->isServerLeader())
+      {
+        CMessage msg;
+        msg<<this->getId();
+        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
+        client->sendEvent(event);
+      }
+      else client->sendEvent(event);
+   }
+   CATCH_DUMP_ATTR
+
+   //! Server side: Receive a message announcing that context can send grid definition for context coupling
+   void CContext::recvCouplerInReady(CEventServer& event)
+   TRY
+   {
+      CBufferIn* buffer=event.subEvents.begin()->buffer;
+      getCurrent()->recvCouplerInReady(*buffer);
+   }
+   CATCH
+
+   //! Server side: Receive a message announcing that context can send grid definition for context coupling
+   void CContext::recvCouplerInReady(CBufferIn& buffer)
+   TRY
+   {
+      string contextId ;
+      buffer>>contextId;
+      couplerInReady_.insert(getCouplerOutClient(contextId)) ;
+   }
+   CATCH_DUMP_ATTR
+
+
+
+
+
+ //! Client side: Send a message  announcing that a coupling context have done it closeDefinition, so data can be sent now.
+   void CContext::sendCouplerInCloseDefinition(CContextClient* client)
+   TRY
+   {
+      if (sendCouplerInCloseDefinition_done_.count(client)!=0) return ;
+      else sendCouplerInCloseDefinition_done_.insert(client) ;
+
+      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CLOSE_DEFINITION);
+
+      if (client->isServerLeader())
+      {
+        CMessage msg;
+        msg<<this->getId();
+        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
+        client->sendEvent(event);
+      }
+      else client->sendEvent(event);
+   }
+   CATCH_DUMP_ATTR
+
+   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
+   void CContext::recvCouplerInCloseDefinition(CEventServer& event)
+   TRY
+   {
+      CBufferIn* buffer=event.subEvents.begin()->buffer;
+      getCurrent()->recvCouplerInCloseDefinition(*buffer);
+   }
+   CATCH
+
+   //! Server side: Receive a message announcing that a coupling context have done it closeDefinition, so data can be sent now.
+   void CContext::recvCouplerInCloseDefinition(CBufferIn& buffer)
+   TRY
+   {
+      string contextId ;
+      buffer>>contextId;
+      couplerInCloseDefinition_.insert(getCouplerOutClient(contextId)) ;
+   }
+   CATCH_DUMP_ATTR
+
+
+
+
+//! Client side: Send a message  announcing that a coupling context have done it contextFinalize, so it can also close it own context.
+   void CContext::sendCouplerInContextFinalized(CContextClient* client)
+   TRY
+   {
+      if (sendCouplerInContextFinalized_done_.count(client)!=0) return ;
+      else sendCouplerInContextFinalized_done_.insert(client) ;
+
+      CEventClient event(getType(),EVENT_ID_COUPLER_IN_CONTEXT_FINALIZED);
+
+      if (client->isServerLeader())
+      {
+        CMessage msg;
+        msg<<this->getId();
+        for (auto& rank : client->getRanksServerLeader()) event.push(rank,1,msg);
+        client->sendEvent(event);
+      }
+      else client->sendEvent(event);
+   }
+   CATCH_DUMP_ATTR
+
+   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
+   void CContext::recvCouplerInContextFinalized(CEventServer& event)
+   TRY
+   {
+      CBufferIn* buffer=event.subEvents.begin()->buffer;
+      getCurrent()->recvCouplerInContextFinalized(*buffer);
+   }
+   CATCH
+
+   //! Server side: Receive a message announcing that a coupling context have done it contextFinalize, so it can also close it own context.
+   void CContext::recvCouplerInContextFinalized(CBufferIn& buffer)
+   TRY
+   {
+      string contextId ;
+      buffer>>contextId;
+      couplerInContextFinalized_.insert(getCouplerOutClient(contextId)) ;
+   }
+   CATCH_DUMP_ATTR
+
+
+
 
   /*!
