Index: XIOS/trunk/src/filter/file_writer_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/file_writer_filter.cpp	(revision 638)
+++ XIOS/trunk/src/filter/file_writer_filter.cpp	(revision 638)
@@ -0,0 +1,20 @@
+#include "file_writer_filter.hpp"
+#include "exception.hpp"
+#include "field.hpp"
+
+namespace xios
+{
+  CFileWriterFilter::CFileWriterFilter(CField* field)
+    : CInputPin(1)
+    , field(field)
+  {
+    if (!field)
+      ERROR("CFileWriterFilter::CFileWriterFilter(CField* field)",
+            "The field cannot be null.");
+  }
+
+  void CFileWriterFilter::onInputReady(std::vector<CDataPacketPtr> data)
+  {
+    field->sendUpdateData(data[0]->data);
+  }
+} // namespace xios
Index: XIOS/trunk/src/filter/file_writer_filter.hpp
===================================================================
--- XIOS/trunk/src/filter/file_writer_filter.hpp	(revision 638)
+++ XIOS/trunk/src/filter/file_writer_filter.hpp	(revision 638)
@@ -0,0 +1,37 @@
+#ifndef __XIOS_CFileWriterFilter__
+#define __XIOS_CFileWriterFilter__
+
+#include "input_pin.hpp"
+
+namespace xios
+{
+  class CField;
+
+  /*!
+   * A terminal filter which transmits the packets it receives to a field for writting in a file.
+   */
+  class CFileWriterFilter : public CInputPin
+  {
+    public:
+      /*!
+       * Constructs the filter (with one input slot) associated to the specified field.
+       *
+       * \param field the associated field
+       */
+      CFileWriterFilter(CField* field);
+
+    protected:
+      /*!
+       * Callbacks a field to write a packet to a file.
+       *
+       * \param data a vector of packets corresponding to each slot
+       */
+      void virtual onInputReady(std::vector<CDataPacketPtr> data);
+
+    private:
+      CField* field; //<! The associated field
+      std::map<Time, CDataPacketPtr> packets; //<! The stored packets
+  }; // class CFileWriterFilter
+} // namespace xios
+
+#endif //__XIOS_CFileWriterFilter__
Index: XIOS/trunk/src/filter/source_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/source_filter.cpp	(revision 638)
+++ XIOS/trunk/src/filter/source_filter.cpp	(revision 638)
@@ -0,0 +1,63 @@
+#include "source_filter.hpp"
+#include "grid.hpp"
+#include "exception.hpp"
+
+namespace xios
+{
+  CSourceFilter::CSourceFilter(CGrid* grid)
+    : grid(grid)
+  {
+    if (!grid)
+      ERROR("CSourceFilter::CSourceFilter(CGrid* grid)",
+            "Impossible to construct a source filter without providing a grid.");
+  }
+
+  template <int N>
+  void CSourceFilter::streamData(Time timestamp, const CArray<double, N>& data)
+  {
+    CDataPacketPtr packet(new CDataPacket);
+    packet->timestamp = timestamp;
+    packet->status = CDataPacket::NO_ERROR;
+
+    packet->data.resize(grid->storeIndex_client.numElements());
+    grid->inputField(data, packet->data);
+
+    deliverOuput(packet);
+  }
+
+  template void CSourceFilter::streamData<1>(Time timestamp, const CArray<double, 1>& data);
+  template void CSourceFilter::streamData<2>(Time timestamp, const CArray<double, 2>& data);
+  template void CSourceFilter::streamData<3>(Time timestamp, const CArray<double, 3>& data);
+
+  void CSourceFilter::streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data)
+  {
+    CDataPacketPtr packet(new CDataPacket);
+    packet->timestamp = timestamp;
+    packet->status = CDataPacket::NO_ERROR;
+
+    if (data.size() != grid->storeIndex_toSrv.size())
+      ERROR("CSourceFilter::streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data)",
+            << "Incoherent data received from servers,"
+            << " expected " << grid->storeIndex_toSrv.size() << " chunks but " << data.size() << " were given.");
+
+    packet->data.resize(grid->storeIndex_client.numElements());
+    std::map<int, CArray<double, 1> >::const_iterator it, itEnd = data.end();
+    for (it = data.begin(); it != itEnd; it++)
+    {
+      CArray<int,1>& index = *grid->storeIndex_toSrv[it->first];
+
+      for (int n = 0; n < index.numElements(); n++)
+        packet->data(index(n)) = it->second(n);
+    }
+
+    deliverOuput(packet);
+  }
+
+  void CSourceFilter::signalEndOfStream(Time timestamp)
+  {
+    CDataPacketPtr packet(new CDataPacket);
+    packet->timestamp = timestamp;
+    packet->status = CDataPacket::END_OF_STREAM;
+    deliverOuput(packet);
+  }
+} // namespace xios
Index: XIOS/trunk/src/filter/source_filter.hpp
===================================================================
--- XIOS/trunk/src/filter/source_filter.hpp	(revision 638)
+++ XIOS/trunk/src/filter/source_filter.hpp	(revision 638)
@@ -0,0 +1,58 @@
+#ifndef __XIOS_CSourceFilter__
+#define __XIOS_CSourceFilter__
+
+#include <map>
+
+#include "output_pin.hpp"
+
+namespace xios
+{
+  class CGrid;
+
+  /*!
+   * A source filter is the entry point of the data in the graph of filters.
+   */
+  class CSourceFilter : public COutputPin
+  {
+    public:
+      /*!
+       * Constructs a source filter accepting data attached to the specified grid.
+       *
+       * \param grid the grid to which the data is attached
+       */
+      CSourceFilter(CGrid* grid);
+
+      /*!
+       * Transforms the data received from the model into a packet and send it
+       * in the filter graph. The array containing the data can safely be reused
+       * immediately after this method returns.
+       *
+       * \param timestamp the timestamp of the data
+       * \param data an array containing the data
+       */
+      template <int N>
+      void streamData(Time timestamp, const CArray<double, N>& data);
+
+      /*!
+       * Transforms the data received from the server into a packet and send it
+       * in the filter graph. The array containing the data can safely be reused
+       * immediately after this method returns.
+       *
+       * \param timestamp the timestamp of the data
+       * \param data an array containing the data
+       */
+      void streamDataFromServer(Time timestamp, const std::map<int, CArray<double, 1> >& data);
+
+      /*!
+       * Signals the filter graph that the end of stream was reached.
+       *
+       * \param timestamp the timestamp at which the end of stream occurred
+       */
+      void signalEndOfStream(Time timestamp);
+
+    private:
+      CGrid* grid; //!< The grid attached to the data the filter can accept
+  }; // class CSourceFilter
+} // namespace xios
+
+#endif //__XIOS_CSourceFilter__
Index: XIOS/trunk/src/filter/store_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/store_filter.cpp	(revision 638)
+++ XIOS/trunk/src/filter/store_filter.cpp	(revision 638)
@@ -0,0 +1,66 @@
+#include "store_filter.hpp"
+#include "context.hpp"
+#include "grid.hpp"
+#include "timer.hpp"
+
+namespace xios
+{
+  CStoreFilter::CStoreFilter(CContext* context, CGrid* grid)
+    : CInputPin(1)
+    , context(context)
+    , grid(grid)
+  {
+    if (!context)
+      ERROR("CStoreFilter::CStoreFilter(CContext* context, CGrid* grid)",
+            "Impossible to construct a store filter without providing a context.");
+    if (!context)
+      ERROR("CStoreFilter::CStoreFilter(CContext* context, CGrid* grid)",
+            "Impossible to construct a store filter without providing a grid.");
+  }
+
+  CConstDataPacketPtr CStoreFilter::getPacket(Time timestamp)
+  {
+    CTimer timer("CStoreFilter::getPacket");
+    CConstDataPacketPtr packet;
+    const double timeout = 10; // 10 seconds timeout
+
+    do
+    {
+      timer.resume();
+
+      std::map<Time, CDataPacketPtr>::const_iterator it = packets.find(timestamp);
+      if (it != packets.end())
+        packet = it->second;
+      else // if the packet is not available yet, check if it can be received
+        context->checkBuffersAndListen();
+
+      timer.suspend();
+    } while (!packet && timer.getCumulatedTime() < timeout);
+
+    if (!packet)
+      ERROR("CConstDataPacketPtr CStoreFilter::getPacket(Time timestamp) const",
+            << "Impossible to get the packet with timestamp = " << timestamp);
+
+    return packet;
+  }
+
+  template <int N>
+  CDataPacket::StatusCode CStoreFilter::getData(Time timestamp, CArray<double, N>& data)
+  {
+    CConstDataPacketPtr packet = getPacket(timestamp);
+
+    if (packet->status == CDataPacket::NO_ERROR)
+      grid->outputField(packet->data, data);
+
+    return packet->status;
+  }
+
+  template CDataPacket::StatusCode CStoreFilter::getData<1>(Time timestamp, CArray<double, 1>& data);
+  template CDataPacket::StatusCode CStoreFilter::getData<2>(Time timestamp, CArray<double, 2>& data);
+  template CDataPacket::StatusCode CStoreFilter::getData<3>(Time timestamp, CArray<double, 3>& data);
+
+  void CStoreFilter::onInputReady(std::vector<CDataPacketPtr> data)
+  {
+    packets.insert(std::make_pair(data[0]->timestamp, data[0]));
+  }
+} // namespace xios
Index: XIOS/trunk/src/filter/store_filter.hpp
===================================================================
--- XIOS/trunk/src/filter/store_filter.hpp	(revision 638)
+++ XIOS/trunk/src/filter/store_filter.hpp	(revision 638)
@@ -0,0 +1,65 @@
+#ifndef __XIOS_CStoreFilter__
+#define __XIOS_CStoreFilter__
+
+#include "input_pin.hpp"
+
+namespace xios
+{
+  class CContext;
+  class CGrid;
+
+  /*!
+   * A terminal filter which stores all the packets it receives.
+   */
+  class CStoreFilter : public CInputPin
+  {
+    public:
+      /*!
+       * Constructs the filter with one input slot for the specified grid
+       * and context.
+       *
+       * \param context the context to which the data belongs
+       * \param grid the grid to which the data is attached
+       */
+      CStoreFilter(CContext* context, CGrid* grid);
+
+      /*!
+       * Accesses the filter storage and retuns the packet corresponding
+       * to the specified timestamp. If there is no packet available for
+       * the specified timestamp, the function waits until the data is
+       * received or a timeout occurs.
+       *
+       * \param timestamp the timestamp of the requested packet
+       * \return a pointer to a read-only packet
+       */
+      CConstDataPacketPtr getPacket(Time timestamp);
+
+      /*!
+       * Accesses the filter storage and retuns the data corresponding
+       * to the specified timestamp. If there is no data available for
+       * the specified timestamp, the function waits until the data is
+       * received or a timeout occurs.
+       *
+       * \param timestamp the timestamp of the requested data
+       * \param data the array where the data is to be copied
+       * \return the status code associated with the data
+       */
+      template <int N>
+      CDataPacket::StatusCode getData(Time timestamp, CArray<double, N>& data);
+
+    protected:
+      /*!
+       * Stores the packet for later access.
+       *
+       * \param data a vector of packets corresponding to each slot
+       */
+      void virtual onInputReady(std::vector<CDataPacketPtr> data);
+
+    private:
+      CContext* context; //!< The context to which the data belongs
+      CGrid* grid; //!< The grid attached to the data the filter can accept
+      std::map<Time, CDataPacketPtr> packets; //<! The stored packets
+  }; // class CStoreFilter
+} // namespace xios
+
+#endif //__XIOS_CStoreFilter__
Index: XIOS/trunk/src/node/field.cpp
===================================================================
--- XIOS/trunk/src/node/field.cpp	(revision 637)
+++ XIOS/trunk/src/node/field.cpp	(revision 638)
@@ -10,4 +10,5 @@
 #include "xios_spl.hpp"
 #include "type.hpp"
+#include "timer.hpp"
 #include "context_client.hpp"
 #include "context_server.hpp"
@@ -202,4 +203,60 @@
 
     for (list< CArray<double,1>* >::iterator it = list_data.begin(); it != list_data.end(); it++) delete *it;
+  }
+
+  void CField::sendUpdateData(const CArray<double,1>& data)
+  {
+    CTimer::get("XIOS Send Data").resume();
+
+    CContext* context = CContext::getCurrent();
+    CContextClient* client = context->client;
+
+    CEventClient event(getType(), EVENT_ID_UPDATE_DATA);
+
+    map<int, CArray<int,1>* >::iterator it;
+    list<CMessage> list_msg;
+    list<CArray<double,1> > list_data;
+
+    if (!grid->doGridHaveDataDistributed())
+    {
+       if (0 == client->clientRank)
+       {
+          for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
+          {
+            int rank = (*it).first;
+            CArray<int,1>& index = *(it->second);
+
+            list_msg.push_back(CMessage());
+            list_data.push_back(CArray<double,1>(index.numElements()));
+
+            CArray<double,1>& data_tmp = list_data.back();
+            for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
+
+            list_msg.back() << getId() << data_tmp;
+            event.push(rank, 1, list_msg.back());
+          }
+          client->sendEvent(event);
+       } else client->sendEvent(event);
+    }
+    else
+    {
+      for (it = grid->storeIndex_toSrv.begin(); it != grid->storeIndex_toSrv.end(); it++)
+      {
+        int rank = (*it).first;
+        CArray<int,1>& index = *(it->second);
+
+        list_msg.push_back(CMessage());
+        list_data.push_back(CArray<double,1>(index.numElements()));
+
+        CArray<double,1>& data_tmp = list_data.back();
+        for (int n = 0; n < data_tmp.numElements(); n++) data_tmp(n) = data(index(n));
+
+        list_msg.back() << getId() << data_tmp;
+        event.push(rank, grid->nbSenders[rank], list_msg.back());
+      }
+      client->sendEvent(event);
+    }
+    
+    CTimer::get("XIOS Send Data").suspend();
   }
 
Index: XIOS/trunk/src/node/field.hpp
===================================================================
--- XIOS/trunk/src/node/field.hpp	(revision 637)
+++ XIOS/trunk/src/node/field.hpp	(revision 638)
@@ -139,4 +139,5 @@
         static bool dispatchEvent(CEventServer& event) ;
         void sendUpdateData(void) ;
+        void sendUpdateData(const CArray<double,1>& data);
         static void recvUpdateData(CEventServer& event) ;
         void recvUpdateData(vector<int>& ranks, vector<CBufferIn*>& buffers) ;
