Index: /XIOS/trunk/inputs/Version2/iodef.xml
===================================================================
--- /XIOS/trunk/inputs/Version2/iodef.xml	(revision 618)
+++ /XIOS/trunk/inputs/Version2/iodef.xml	(revision 619)
@@ -10,4 +10,6 @@
      <field id="field_A"  operation="average" freq_op="3600s" grid_ref="grid_A" />
      <field id="field_Axis"  operation="average" freq_op="3600s" grid_ref="grid_Axis" />
+     <field id="field_Two_Axis"  operation="average" freq_op="3600s" grid_ref="grid_Two_Axis" />
+     <field id="field_Axis_transformed"  operation="average" freq_op="3600s" field_ref="field_Two_Axis" grid_ref="grid_Axis_tranformed" />
      <field id="field_All_Axis" operation="average" freq_op="3600s" grid_ref="grid_All_Axis" />
      <field id="field_Scalar" operation="average" freq_op="3600s" grid_ref="ScalarGrid" />
@@ -17,8 +19,11 @@
    <file_definition type="multiple_file" par_access="collective" output_freq="6h" output_level="10" enabled=".TRUE.">
      <file id="output" name="output">
-<!--        <field field_ref="field_A" />-->
+        <field field_ref="field_A" />
      </file>
      <file id="output_Axis" name="output_Axis" type="one_file">
-        <field field_ref="field_Axis" />
+<!--        <field field_ref="field_Axis" />-->
+     </file>
+     <file id="output_Axis_transformed" name="output_Axis_transformed" type="one_file">
+        <field field_ref="field_Axis_transformed" />
      </file>
      <file id="output_All_Axis" name="output_All_Axis" type="one_file">
@@ -35,5 +40,9 @@
      <axis id="axis_B" />
      <axis id="axis_C" zoom_size="2" zoom_end="2"/>
-     <axis id="axis_D" zoom_size="2" zoom_end="3"/>
+     <axis id="axis_D" />
+     <axis id="axis_E" axis_ref="axis_B">
+        <transformation type="inverse" />
+<!--        <transformation type="zoom" />-->
+     </axis>
    </axis_definition>
 
@@ -50,4 +59,12 @@
        <grid id="grid_Axis">
          <axis axis_ref="axis_D" />
+       </grid>
+       <grid id="grid_Two_Axis">
+         <axis axis_ref="axis_A" />
+         <axis axis_ref="axis_B" />
+       </grid>
+       <grid id="grid_Axis_tranformed">
+         <axis axis_ref="axis_A" />
+         <axis axis_ref="axis_E" />
        </grid>
        <grid id="grid_All_Axis">
Index: /XIOS/trunk/src/config/node_type.conf
===================================================================
--- /XIOS/trunk/src/config/node_type.conf	(revision 618)
+++ /XIOS/trunk/src/config/node_type.conf	(revision 619)
@@ -31,4 +31,8 @@
 #endif //__XIOS_CCalendarWrapper__
 
+#ifdef __XIOS_CTransformation__
+   DECLARE_NODE(Transformation, transformation)
+#endif //__XIOS_CTransformation__
+
 #ifdef __XIOS_CContext__
    DECLARE_NODE_PAR(Context, context)
Index: /XIOS/trunk/src/config/transformation_attribute.conf
===================================================================
--- /XIOS/trunk/src/config/transformation_attribute.conf	(revision 619)
+++ /XIOS/trunk/src/config/transformation_attribute.conf	(revision 619)
@@ -0,0 +1,3 @@
+DECLARE_ATTRIBUTE(StdString, type)
+//DECLARE_ATTRIBUTE(StdString, axis_ref)
+//DECLARE_ATTRIBUTE(StdString, domain_ref)
Index: /XIOS/trunk/src/declare_virtual_node.hpp
===================================================================
--- /XIOS/trunk/src/declare_virtual_node.hpp	(revision 619)
+++ /XIOS/trunk/src/declare_virtual_node.hpp	(revision 619)
@@ -0,0 +1,31 @@
+#ifndef __XMLIO_DECLARE_VIRTUAL_NODE__
+#define __XMLIO_DECLARE_VIRTUAL_NODE__
+
+/// ///////////////////////////// Macros ///////////////////////////// ///
+
+#define DECLARE_VIRTUAL_NODE(type)                                    \
+   class CVirtual##type                                               \
+      : public CVirtualNode<C##type>                                     \
+   {                                                                  \
+      public:                                                         \
+         typedef C##type           RelType;                           \
+                                                                      \
+         CVirtual##type() : CVirtualNode<RelType> ()                  \
+         { /* Ne rien faire de plus */ }                              \
+                                                                      \
+         void setVirtual##type(RelType* newRelTypePtr)                \
+         { CVirtualNode<C##type>::setVirtualNode(newRelTypePtr); }                     \
+                                                                      \
+         void setVirtual##type()                                      \
+         { CVirtualNode<C##type>::setVirtualNode(); }                     \
+                                                                      \
+         RelType* getVirtual##type() const                            \
+         { return CVirtualNode<C##type>::getVirtualNode(); }                           \
+                                                                      \
+         virtual ~CVirtual##type()                                    \
+         { /* Ne rien faire de plus */ }                              \
+   };                                                                 \
+   typedef CVirtual##type CVirtual##type##Definition
+
+
+#endif // __XMLIO_DECLARE_VIRTUAL_NODE__
Index: /XIOS/trunk/src/filter/axis_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/axis_filter.cpp	(revision 619)
+++ /XIOS/trunk/src/filter/axis_filter.cpp	(revision 619)
@@ -0,0 +1,30 @@
+#include "axis_filter.hpp"
+#include "context.hpp"
+#include "context_client.hpp"
+
+namespace xios {
+
+CAxisFilter::CAxisFilter(CGrid* gridInput, CGrid* gridOutput)
+ : CGenericFilter(gridInput, gridOutput), isGridTransformed_(false)
+{
+  CContext* context = CContext::getCurrent();
+  CContextClient* client = context->client;
+  this->distributionClient_ = new CDistributionClient(client->clientRank, gridInput);
+}
+
+void CAxisFilter::setGridTransformed()
+{
+  isGridTransformed_ = true;
+}
+
+bool CAxisFilter::isGridTransformed()
+{
+  return isGridTransformed_;
+}
+
+const CArray<size_t,1>& CAxisFilter::getGlobalDataIndexInput() const
+{
+  return this->distributionClient_->getGlobalDataIndexSendToServer();
+}
+
+}
Index: /XIOS/trunk/src/filter/axis_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/axis_filter.hpp	(revision 619)
+++ /XIOS/trunk/src/filter/axis_filter.hpp	(revision 619)
@@ -0,0 +1,27 @@
+#ifndef __XIOS_AXIS_FILTER_HPP__
+#define __XIOS_AXIS_FILTER_HPP__
+
+#include "generic_filter.hpp"
+#include "axis.hpp"
+
+namespace xios {
+
+class CAxisFilter : public CGenericFilter
+{
+public:
+  DEFINE_VISITABLE()
+public:
+  /** Default constructor */
+  CAxisFilter(CGrid* gridInput, CGrid* gridOutput);
+
+  const CArray<size_t,1>& getGlobalDataIndexInput() const;
+  void setGridTransformed();
+  bool isGridTransformed();
+
+protected:
+  bool isGridTransformed_;
+
+};
+
+}
+#endif // __XIOS_AXIS_FILTER_HPP__
Index: /XIOS/trunk/src/filter/axis_transformation.cpp
===================================================================
--- /XIOS/trunk/src/filter/axis_transformation.cpp	(revision 619)
+++ /XIOS/trunk/src/filter/axis_transformation.cpp	(revision 619)
@@ -0,0 +1,31 @@
+#include "axis_transformation.hpp"
+
+namespace xios {
+
+CAxisTransformation::CAxisTransformation(std::vector<CAxis*> inputs, std::vector<CAxis*> outputs)
+{
+  this->setInputs(inputs);
+  this->setOutputs(outputs);
+}
+
+void CAxisTransformation::setInputs(const std::vector<CAxis*>& inputs)
+{
+  inputs_ = inputs;
+}
+
+void CAxisTransformation::setOutputs(const std::vector<CAxis*>& outputs)
+{
+  outputs_ = outputs;
+}
+
+std::vector<CAxis*> CAxisTransformation::getInputs()
+{
+  return inputs_;
+}
+
+std::vector<CAxis*> CAxisTransformation::getOutputs()
+{
+  return outputs_;
+}
+
+}
Index: /XIOS/trunk/src/filter/axis_transformation.hpp
===================================================================
--- /XIOS/trunk/src/filter/axis_transformation.hpp	(revision 619)
+++ /XIOS/trunk/src/filter/axis_transformation.hpp	(revision 619)
@@ -0,0 +1,30 @@
+#ifndef __XIOS_AXIS_TRANSFORMATION_HPP__
+#define __XIOS_AXIS_TRANSFORMATION_HPP__
+
+#include "visitable.hpp"
+#include "axis.hpp"
+
+namespace xios {
+
+class CAxisTransformation : public CGenericTransformation
+{
+public:
+  DEFINE_VISITABLE()
+public:
+  /** Default constructor */
+  CAxisTransformation(std::vector<CAxis*> inputs, std::vector<CAxis*> outputs);
+
+  std::vector<CAxis*> getOutputs();
+  std::vector<CAxis*> getInputs();
+protected:
+  void setInputs(const std::vector<CAxis*>& inputs);
+  void setOutputs(const std::vector<CAxis*>& outputs);
+
+protected:
+  std::vector<CAxis*> inputs_;
+  std::vector<CAxis*> outputs_;
+
+};
+
+}
+#endif // __XIOS_AXIS_TRANSFORMATION_HPP__
Index: /XIOS/trunk/src/filter/generic_filter.cpp
===================================================================
--- /XIOS/trunk/src/filter/generic_filter.cpp	(revision 619)
+++ /XIOS/trunk/src/filter/generic_filter.cpp	(revision 619)
@@ -0,0 +1,41 @@
+#include "generic_filter.hpp"
+
+namespace xios {
+
+CGenericFilter::CGenericFilter(CGrid* gridInput_, CGrid* gridOutput_)
+ : gridInput(gridInput_), gridOutput(gridOutput_), distributionClient_(0)
+{
+}
+
+CGenericFilter::~CGenericFilter()
+{
+  if (0 != distributionClient_) delete distributionClient_;
+}
+
+void CGenericFilter::setInputs(const std::vector<CField*>& inputs)
+{
+  fieldInputs_ = inputs;
+}
+
+void CGenericFilter::setOutputs(const std::vector<CField*>& outputs)
+{
+  fieldOutputs_ = outputs;
+}
+
+void CGenericFilter::setOutput(CField* output)
+{
+  fieldOutputs_.resize(1);
+  fieldOutputs_[0] = output;
+}
+
+const std::vector<CField*> CGenericFilter::getInputs()
+{
+  return fieldInputs_;
+}
+
+std::vector<CField*> CGenericFilter::getOutputs()
+{
+  return fieldOutputs_;
+}
+
+}
Index: /XIOS/trunk/src/filter/generic_filter.hpp
===================================================================
--- /XIOS/trunk/src/filter/generic_filter.hpp	(revision 619)
+++ /XIOS/trunk/src/filter/generic_filter.hpp	(revision 619)
@@ -0,0 +1,38 @@
+#ifndef __XIOS_GENERIC_FILTER_HPP__
+#define __XIOS_GENERIC_FILTER_HPP__
+
+#include "visitable.hpp"
+#include "field.hpp"
+#include "grid.hpp"
+#include "distribution_client.hpp"
+
+namespace xios {
+
+class CGenericFilter : public virtual CBaseVisitable<>
+{
+public:
+  DEFINE_VISITABLE()
+public:
+  CGenericFilter(CGrid* gridInput, CGrid* gridOutput);
+
+  virtual ~CGenericFilter();
+
+  void setInputs(const std::vector<CField*>& fieldInputs);
+  void setOutputs(const std::vector<CField*>& fieldOutputs);
+  void setOutput(CField* fieldOutput);
+
+  const std::vector<CField*> getInputs();
+  std::vector<CField*> getOutputs();
+
+public:
+  CGrid* gridInput;
+  CGrid* gridOutput;
+
+protected:
+  std::vector<CField*> fieldInputs_;
+  std::vector<CField*> fieldOutputs_;
+  CDistributionClient* distributionClient_;
+};
+
+}
+#endif // __XIOS_GENERIC_FILTER_HPP__
Index: /XIOS/trunk/src/filter/invert_algorithm.cpp
===================================================================
--- /XIOS/trunk/src/filter/invert_algorithm.cpp	(revision 619)
+++ /XIOS/trunk/src/filter/invert_algorithm.cpp	(revision 619)
@@ -0,0 +1,299 @@
+#include "invert_algorithm.hpp"
+#include "axis.hpp"
+#include "grid.hpp"
+#include <vector>
+#include <map>
+#include <list>
+#include <algorithm>
+#include "mpi.hpp"
+#include "context.hpp"
+#include "context_client.hpp"
+#include "field.hpp"
+#include "array_new.hpp"
+
+namespace xios {
+CInvertAlgorithm::CInvertAlgorithm()
+{
+}
+
+void CInvertAlgorithm::operate(CAxisTransformation& axisTransformation)
+{
+  std::vector<CAxis*> axisInputs = axisTransformation.getInputs();
+  std::vector<CAxis*> axisOutputs = axisTransformation.getOutputs();
+
+  // For now, only consider simple case one input - one output
+  CAxis* axisInput = axisInputs[0], *axisOutput = axisOutputs[0];
+  // Check correct size
+  if (axisInput->size.getValue() != axisOutput->size.getValue())
+  {
+    ERROR("CInvertAlgorithm::operate(CAxisTransformation& axisTransformation)",
+           << "Two axis have different size"
+           << "Size of axis source " <<axisInput->getId() << " is " << axisInput->size.getValue()  << std::endl
+           << "Size of axis destionation " <<axisOutput->getId() << " is " << axisOutput->size.getValue());
+  }
+
+  if ((axisInput->ni.isEmpty()) || (axisInput->ni.getValue() == axisInput->size.getValue()))
+  {
+    // axis non-distributed
+    size_t ssize = axisInput->size.getValue();
+    axisOutput->value.resize(ssize);
+    for (size_t idx = 0; idx < ssize; ++idx)
+    {
+      (axisOutput->value)(idx) = (axisInput->value)(ssize-idx-1);
+    }
+  }
+  else
+  {
+    CContext* context = CContext::getCurrent();
+    CContextClient* client = context->client;
+    int nbClient = client->clientSize;
+
+    // Ok, now axis is distributed
+    // First of all, each of client needs to have the whole axis data
+    int localAxisSize = axisInput->ni.getValue();
+    int* recvAxisSize = new int[nbClient];
+    MPI_Allgather(&localAxisSize, 1, MPI_INT,
+                  recvAxisSize, 1, MPI_INT, client->intraComm);
+
+
+    int* displ=new int[nbClient];
+    displ[0]=0 ;
+    for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvAxisSize[n-1];
+    int recvSize=displ[nbClient-1]+recvAxisSize[nbClient-1];
+    double* recvBuff=new double[recvSize];
+
+    double* sendBuff = new double[localAxisSize];
+    for (int idx = 0; idx < localAxisSize; ++idx) sendBuff[idx] = (axisInput->value)(idx);
+
+    MPI_Allgatherv(sendBuff, localAxisSize, MPI_DOUBLE,
+                   recvBuff, recvAxisSize, displ, MPI_DOUBLE,
+                   client->intraComm);
+
+    int ibegin = axisInput->ibegin.getValue();
+    size_t ssize = axisInput->size.getValue();
+    axisOutput->value.resize(localAxisSize);
+    for (int idx = 0; idx < localAxisSize; ++idx)
+        (axisOutput->value)(idx) = recvBuff[ssize-ibegin-idx-1];
+
+    std::cout << "axisOutput value " << (axisOutput->value) << std::endl;
+
+    delete [] displ;
+    delete [] sendBuff;
+    delete [] recvBuff;
+    delete [] recvAxisSize;
+  }
+}
+
+
+void CInvertAlgorithm::operate(CAxisFilter& axisFilter)
+{
+  CContext* context = CContext::getCurrent();
+  CContextClient* client = context->client;
+  MPI_Comm clientIntraComm = client->intraComm;
+
+  CGrid* gridInput = axisFilter.gridInput;
+  CGrid* gridOutput = axisFilter.gridOutput;
+
+
+  bool isDataDistributed = (gridInput->doGridHaveDataDistributed());
+  isDataDistributed = false;
+
+  // Data distributed
+  const CArray<size_t,1>& globalDataIndexInput = axisFilter.getGlobalDataIndexInput();
+  if (sendingIndexMap.empty() && receivingIndexMap.empty() && indexMap.empty())
+    inverseGlobalDataIndex(globalDataIndexInput);
+
+
+  const std::vector<CField*> fieldInputs = axisFilter.getInputs();
+  std::vector<CField*> fieldOutputs = axisFilter.getOutputs();
+
+  CField* input  = fieldInputs[0];
+  CField* output = fieldOutputs[0];
+
+  CArray<double, 1>& dataInput  = input->data;
+  CArray<double, 1>& dataOutput = output->filteredData;
+
+  if (dataOutput.numElements() != dataInput.numElements())
+    dataOutput.resize(dataInput.numElements());
+
+  std::map<size_t,size_t>::iterator itb = indexMap.begin(), ite = indexMap.end(), it;
+  for (it = itb; it != ite; ++it)
+  {
+    dataOutput(it->first) = dataInput(it->second);
+  }
+
+   std::cout << "dataOutput 1 "<<  dataOutput <<  std::endl;
+  std::map<int, std::vector<size_t> >::iterator itbMap, itMap, iteMap;
+  int idx = 0, k = 0;
+  int sendBuffSize = 0;
+  int nbSend = sendingIndexMap.size();
+  std::vector<int> sendDispl(nbSend,0);
+  itbMap = sendingIndexMap.begin();
+  iteMap = sendingIndexMap.end();
+  for (itMap = itbMap; itMap != iteMap; ++itMap) sendBuffSize += (itMap->second).size();
+  itMap = itbMap;
+  for (idx = 1; idx < nbSend; ++itMap, ++idx) sendDispl[idx] = sendDispl[idx-1] + (itMap->second).size();
+
+  double* sendBuff, *ptr;
+  std::vector<MPI_Request> sendRequest(nbSend);
+  if (0 != sendBuffSize) sendBuff = new double[sendBuffSize];
+  for (k = 0, itMap = itbMap; itMap != iteMap; ++itMap, ++k)
+  {
+    int sendDataSize = (itMap->second).size();
+    for (int i = 0; i < sendDataSize; ++i)
+    {
+      sendBuff[sendDispl[k]+i] = dataInput((itMap->second)[i]);
+    }
+    std::cout <<  "itMap first " << itMap->first << std::endl;
+    ptr = sendBuff + sendDispl[k];
+    MPI_Isend(ptr, sendDataSize, MPI_DOUBLE,
+              itMap->first, 24, clientIntraComm, &sendRequest[k]);
+  }
+
+  MPI_Status status;
+  for (idx = 0; idx < nbSend; ++idx) MPI_Wait(&sendRequest[idx], &status);
+
+  int recvBuffSize = 0, recvBuffPos = 0;
+  int nbRecv = receivingIndexMap.size();
+  std::map<int,int> recvDispl;
+  itbMap = receivingIndexMap.begin();
+  iteMap = receivingIndexMap.end();
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    recvBuffSize += (itMap->second).size();
+    recvDispl[itMap->first] = recvBuffPos;
+    recvBuffPos += (itMap->second).size();
+  }
+
+  double* recvBuff;
+  std::map<int, MPI_Request> recvRequest;
+  std::map<int, MPI_Request>::iterator itRequest;
+  std::list<int> processedRequest;
+  int nbRemainingRecv = nbRecv;
+  if (0 != sendBuffSize) recvBuff = new double[recvBuffSize];
+
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    int rankSource = itMap->first;
+    int recvDataSize = (itMap->second).size();
+    MPI_Recv(recvBuff+recvDispl[rankSource], recvDataSize, MPI_DOUBLE,
+             rankSource, 24, clientIntraComm, &status);
+    for (int i = 0; i < recvDataSize; ++i)
+    {
+      dataOutput(receivingIndexMap[rankSource][i]) = recvBuff[recvDispl[rankSource]+recvDataSize-i-1];
+    }
+  }
+  std::cout << "dataOutput 2 "<< dataOutput <<  std::endl;
+
+//  while (0 < nbRemainingRecv)
+//  {
+//    MPI_Status status;
+//    int flag, count;
+//    MPI_Iprobe(MPI_ANY_SOURCE, 24, clientIntraComm, &flag, &status);
+//    if ((true == flag))
+//    {
+//      MPI_Get_count(&status, MPI_DOUBLE, &count);
+//      MPI_Irecv(recvBuff+recvDispl[status.MPI_SOURCE], count, MPI_DOUBLE,
+//                status.MPI_SOURCE, 24, clientIntraComm,
+//                &recvRequest[status.MPI_SOURCE]);
+//
+//    }
+//    for (itRequest = recvRequest.begin(); itRequest != recvRequest.end(); ++itRequest)
+//    {
+//      int rank = itRequest->first;
+//      processedRequest.push_back(rank);
+//      int recvDataSize = (receivingIndexMap[rank]).size();
+//      for (int i = 0; i < recvDataSize; ++i)
+//      {
+//        dataOutput(receivingIndexMap[rank][i]) = recvBuff[recvDispl[rank]+recvDataSize-i];
+//      }
+//      --nbRemainingRecv;
+//    }
+//
+//    while (!processedRequest.empty())
+//    {
+//      recvRequest.erase(processedRequest.back());
+//      processedRequest.pop_back();
+//    }
+//  }
+
+  if (0 != sendBuffSize) delete [] sendBuff;
+  if (0 != recvBuffSize) delete [] recvBuff;
+}
+
+
+void CInvertAlgorithm::inverseGlobalDataIndex(const CArray<size_t,1>& globalDataIndexInput)
+{
+  CContext* context = CContext::getCurrent();
+  CContextClient* client = context->client;
+  int nbClient = client->clientSize;
+  int clientRank = client->clientRank;
+  int idx = 0;
+
+  int dataIndexSize = globalDataIndexInput.numElements();
+  int* recvAxisSize = new int[nbClient];
+  MPI_Allgather(&dataIndexSize, 1, MPI_INT,
+                recvAxisSize, 1, MPI_INT, client->intraComm);
+
+  std::vector<int> displ(nbClient);
+  displ[0]=0 ;
+  for(int n=1;n<nbClient;n++) displ[n]=displ[n-1]+recvAxisSize[n-1];
+  int recvSize=displ[nbClient-1]+recvAxisSize[nbClient-1];
+  unsigned long* recvBuff=new unsigned long[recvSize];
+
+  unsigned long* sendBuff = new unsigned long[dataIndexSize];
+  for (int idx = 0; idx < dataIndexSize; ++idx) sendBuff[idx] = (globalDataIndexInput)(idx);
+
+  MPI_Allgatherv(sendBuff, dataIndexSize, MPI_UNSIGNED_LONG,
+                 recvBuff, recvAxisSize, &displ[0], MPI_UNSIGNED_LONG,
+                 client->intraComm);
+
+  unsigned long* ptr;
+  int receivingRank, sendingRank;
+  std::vector<int>::iterator upper, itbDispl = displ.begin(), iteDispl = displ.end();
+
+  //
+//  std::map<int, std::vector<size_t> > sendingIndexMap;
+
+  // map between client rank and (local) received data index
+//  std::map<int, std::vector<size_t> > receivingIndexMap;
+  std::vector<size_t> tmpIndexMap;
+  for (idx = 0; idx < dataIndexSize; ++idx)
+  {
+    // First of all, need to know the inversed index
+    size_t inversedIndex = recvSize - globalDataIndexInput(idx)-1;
+
+    // Find position of the inversed index in the whole received array index
+    ptr = std::find(recvBuff, recvBuff+recvSize, inversedIndex);
+    if (ptr != recvBuff+recvSize)
+    {
+      int indexPosition = std::distance(recvBuff, ptr);
+      // Determine a client from which the current client will receive data
+      upper = std::upper_bound(itbDispl, iteDispl, indexPosition);
+      sendingRank = receivingRank = std::distance(itbDispl, upper) - 1;
+      if (clientRank != receivingRank)
+      {
+        (receivingIndexMap[receivingRank]).push_back(idx);
+        (sendingIndexMap[sendingRank]).push_back(idx);
+      }
+      else
+      {
+        tmpIndexMap.push_back(idx);
+      }
+    }
+  }
+  if (!tmpIndexMap.empty())
+  {
+    int tmpSize = tmpIndexMap.size();
+    for (int idx = 0; idx < tmpSize; ++idx)
+    {
+      indexMap[tmpIndexMap[idx]] = tmpIndexMap[tmpSize - idx -1];
+    }
+  }
+
+
+  delete [] sendBuff;
+  delete [] recvBuff;
+  delete [] recvAxisSize;
+}
+}
Index: /XIOS/trunk/src/filter/invert_algorithm.hpp
===================================================================
--- /XIOS/trunk/src/filter/invert_algorithm.hpp	(revision 619)
+++ /XIOS/trunk/src/filter/invert_algorithm.hpp	(revision 619)
@@ -0,0 +1,31 @@
+#ifndef __XIOS_INVERT_ALGORITHM_HPP__
+#define __XIOS_INVERT_ALGORITHM_HPP__
+
+#include "visitor.hpp"
+#include "axis_transformation.hpp"
+#include "axis_filter.hpp"
+
+namespace xios {
+class CInvertAlgorithm :
+  public CBaseVisitor,
+  public CVisitor<CAxisTransformation>,
+  public CVisitor<CAxisFilter>
+{
+public:
+  /** Default constructor */
+  CInvertAlgorithm();
+
+  void operate(CAxisTransformation&);
+  void operate(CAxisFilter&);
+protected:
+
+  void inverseGlobalDataIndex(const CArray<size_t,1>& globalDataIndexInput);
+protected:
+  std::map<int, std::vector<size_t> > sendingIndexMap;
+  std::map<int, std::vector<size_t> > receivingIndexMap;
+  std::map<size_t, size_t> indexMap;
+private:
+};
+
+}
+#endif // __XIOS_INVERT_ALGORITHM_HPP__
Index: /XIOS/trunk/src/filter/zoom_algorithm.cpp
===================================================================
--- /XIOS/trunk/src/filter/zoom_algorithm.cpp	(revision 619)
+++ /XIOS/trunk/src/filter/zoom_algorithm.cpp	(revision 619)
@@ -0,0 +1,14 @@
+#include "zoom_algorithm.hpp"
+
+namespace xios {
+CZoomAlgorithm::CZoomAlgorithm()
+{
+  //ctor
+}
+
+void CZoomAlgorithm::operate(CAxisFilter& axisFilter)
+{
+
+}
+
+}
Index: /XIOS/trunk/src/filter/zoom_algorithm.hpp
===================================================================
--- /XIOS/trunk/src/filter/zoom_algorithm.hpp	(revision 619)
+++ /XIOS/trunk/src/filter/zoom_algorithm.hpp	(revision 619)
@@ -0,0 +1,22 @@
+#ifndef __XIOS_ZOOM_ALGORITHM_HPP__
+#define __XIOS_ZOOM_ALGORITHM_HPP__
+
+#include "visitor.hpp"
+#include "axis_filter.hpp"
+
+namespace xios {
+class CZoomAlgorithm :
+  public CBaseVisitor,
+  public CVisitor<CAxisFilter>
+{
+public:
+  /** Default constructor */
+  CZoomAlgorithm();
+
+  void operate(CAxisFilter&);
+protected:
+private:
+};
+
+}
+#endif // __XIOS_ZOOM_ALGORITHM_HPP__
Index: /XIOS/trunk/src/group_factory_decl.cpp
===================================================================
--- /XIOS/trunk/src/group_factory_decl.cpp	(revision 618)
+++ /XIOS/trunk/src/group_factory_decl.cpp	(revision 619)
@@ -25,3 +25,4 @@
   macro(CContextGroup)
   macro(CVariableGroup)
+  macro(CTransformationGroup)
 }
Index: /XIOS/trunk/src/group_template_decl.cpp
===================================================================
--- /XIOS/trunk/src/group_template_decl.cpp	(revision 618)
+++ /XIOS/trunk/src/group_template_decl.cpp	(revision 619)
@@ -6,13 +6,14 @@
 #  define macro(T) \
   template class CGroupTemplate<C##T, C##T##Group, C##T##Attributes> ;
-  
-  macro(Context) 
-  macro(Field) 
-  macro(File) 
-  macro(Domain) 
-  macro(Grid) 
-  macro(Axis) 
-  macro(Variable) 
-  
+
+  macro(Context)
+  macro(Field)
+  macro(File)
+  macro(Domain)
+  macro(Grid)
+  macro(Axis)
+  macro(Variable)
+  macro(Transformation)
+
 
 }
Index: /XIOS/trunk/src/node/axis.cpp
===================================================================
--- /XIOS/trunk/src/node/axis.cpp	(revision 618)
+++ /XIOS/trunk/src/node/axis.cpp	(revision 619)
@@ -87,5 +87,5 @@
 
       StdSize true_size = value.numElements();
-      if (size != true_size)
+      if (this->ni.getValue() != true_size)
          ERROR("CAxis::checkAttributes(void)",
                << "The array \'value\' of axis [ id = '" << getId() << "' , context = '" << CObjectFactory::GetCurrentContextId() << "' ] has a different size that the one defined by the \'size\' attribute");
@@ -306,4 +306,57 @@
   }
 
+  bool CAxis::hasTransformation()
+  {
+    return (!transformations_.empty());
+  }
+
+  void CAxis::setTransformations(const std::vector<ETransformationType>& transformations)
+  {
+    transformations_ = transformations;
+  }
+
+  void CAxis::solveInheritanceTransformation()
+  {
+    if (this->hasTransformation()) return;
+
+    std::vector<CAxis*> refAxis;
+    CAxis* refer_sptr;
+    CAxis* refer_ptr = this;
+    while (refer_ptr->hasDirectAxisReference())
+    {
+      refAxis.push_back(refer_ptr);
+      refer_sptr = refer_ptr->getDirectAxisReference();
+      refer_ptr  = refer_sptr;
+      if (refer_ptr->hasTransformation()) break;
+    }
+
+    if (refer_ptr->hasTransformation())
+      for (int idx = 0; idx < refAxis.size(); ++idx)
+        refAxis[idx]->setTransformations(refer_ptr->getTransformations());
+  }
+
+  void CAxis::parse(xml::CXMLNode & node)
+  {
+    SuperClass::parse(node);
+
+    if (node.goToChildElement())
+    {
+      StdString tranformation("transformation");
+      do
+      {
+        if (node.getElementName() == tranformation) {
+           this->getVirtualTransformationGroup()->parseChild(node);
+           transformations_.push_back(eInverse);
+        }
+      } while (node.goToNextElement()) ;
+      node.goToParentElement();
+    }
+  }
+
+  const std::vector<ETransformationType>& CAxis::getTransformations()
+  {
+    return transformations_;
+  }
+
    DEFINE_REF_FUNC(Axis,axis)
 
Index: /XIOS/trunk/src/node/axis.hpp
===================================================================
--- /XIOS/trunk/src/node/axis.hpp	(revision 618)
+++ /XIOS/trunk/src/node/axis.hpp	(revision 619)
@@ -5,11 +5,15 @@
 #include "xios_spl.hpp"
 #include "group_factory.hpp"
+#include "virtual_node.hpp"
 
 #include "declare_group.hpp"
 #include "declare_ref_func.hpp"
+#include "declare_virtual_node.hpp"
 #include "attribute_array.hpp"
 #include "attribute_enum.hpp"
 #include "attribute_enum_impl.hpp"
 #include "server_distribution_description.hpp"
+#include "transformation.hpp"
+#include "transformation_enum.hpp"
 
 namespace xios {
@@ -19,5 +23,8 @@
    class CAxisAttributes;
    class CAxis;
+   class CTransformationGroup;
+   class CVirtualTransformationGroup;
 
+   DECLARE_VIRTUAL_NODE(TransformationGroup);
    ///--------------------------------------------------------------
 
@@ -32,4 +39,5 @@
       : public CObjectTemplate<CAxis>
       , public CAxisAttributes
+      , public CVirtualTransformationGroup
    {
          enum EEventId
@@ -69,4 +77,6 @@
          virtual ~CAxis(void);
 
+         virtual void parse(xml::CXMLNode & node);
+
          /// Accesseurs statiques ///
          static StdString GetName(void);
@@ -83,4 +93,10 @@
          void sendCheckedAttributes(const std::vector<int>& globalDim, int orderPositionInGrid,
                                     CServerDistributionDescription::ServerDistributionType disType = CServerDistributionDescription::BAND_DISTRIBUTION);
+
+         bool hasTransformation();
+         void setTransformations(const std::vector<ETransformationType>&);
+         const std::vector<ETransformationType>& getTransformations();
+         void solveInheritanceTransformation();
+
       public:
         int zoom_begin_srv, zoom_end_srv, zoom_size_srv;
@@ -92,9 +108,11 @@
          void checkZoom();
 
+
+         void checkTransformation();
       private:
-
          bool isChecked;
          bool areClientAttributesChecked_;
          std::set<StdString> relFiles;
+         std::vector<ETransformationType> transformations_;
          bool isDistributed_;
 
Index: /XIOS/trunk/src/node/context.cpp
===================================================================
--- /XIOS/trunk/src/node/context.cpp	(revision 618)
+++ /XIOS/trunk/src/node/context.cpp	(revision 619)
@@ -894,6 +894,6 @@
        {
          const std::pair<StdString, StdString>& prDomAxisId = enabledFields[j]->getRefDomainAxisIds();
-         domainIds.insert(prDomAxisId.first);
-         axisIds.insert(prDomAxisId.second);
+         if ("" != prDomAxisId.first) domainIds.insert(prDomAxisId.first);
+         if ("" != prDomAxisId.second) axisIds.insert(prDomAxisId.second);
        }
      }
Index: /XIOS/trunk/src/node/field.cpp
===================================================================
--- /XIOS/trunk/src/node/field.cpp	(revision 618)
+++ /XIOS/trunk/src/node/field.cpp	(revision 619)
@@ -13,4 +13,6 @@
 #include "context_server.hpp"
 #include <set>
+#include "axis_filter.hpp"
+#include "invert_algorithm.hpp"
 
 namespace xios{
@@ -27,5 +29,5 @@
       , foperation(), hasInstantData(false), hasExpression(false)
       , active(false) , hasOutputFile(false),hasFieldOut(false), slotUpdateDate(NULL)
-      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
+      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
       , isReadDataRequestPending(false)
       { setVirtualVariableGroup(); }
@@ -40,5 +42,5 @@
       , foperation(), hasInstantData(false), hasExpression(false)
       , active(false), hasOutputFile(false), hasFieldOut(false), slotUpdateDate(NULL)
-      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false)
+      , processed(false), domAxisIds_("", ""), areAllReferenceSolved(false), areAllExpressionBuilt(false), filter(0)
       , isReadDataRequestPending(false)
    { setVirtualVariableGroup(); }
@@ -51,4 +53,5 @@
       if (hasExpression) delete expression;
       if (slotUpdateDate != NULL) delete slotUpdateDate;
+      if (0 != filter) delete filter;
 
    }
@@ -172,4 +175,6 @@
             int rank=(*it).first ;
             CArray<int,1>& index = *(it->second) ;
+                       std::cout << "rank " << index << std::endl;
+                       std::cout << "data " << data << std::endl;
             CArray<double,1> data_tmp(index.numElements()) ;
             for(int n=0;n<data_tmp.numElements();n++) data_tmp(n)=data(index(n)) ;
@@ -527,22 +532,4 @@
       return(this->last_operation);
    }
-
-   //----------------------------------------------------------------
-
-//   void CField::processEnabledField(void)
-//   {
-//      if (!processed)
-//      {
-//        processed = true;
-//        solveRefInheritance(true);
-//        solveBaseReference();
-//        solveOperation();
-//        solveGridReference();
-//
-//        if (hasDirectFieldReference()) baseRefObject->processEnabledField();
-//        buildExpression();
-//        active = true;
-//      }
-//    }
 
    void CField::solveAllReferenceEnabledField(bool doSending2Sever)
@@ -562,4 +549,8 @@
      }
      solveGridDomainAxisRef(doSending2Sever);
+     if (context->hasClient)
+     {
+       solveTransformedGrid();
+     }
      solveCheckMaskIndex(doSending2Sever);
    }
@@ -576,7 +567,5 @@
      {
        areAllExpressionBuilt = true;
-//       solveCheckMaskIndex(true);
-//       solveCheckMaskIndex();
-       if (hasDirectFieldReference()) baseRefObject->buildAllExpressionEnabledField();
+       if (hasDirectFieldReference() && (grid_ref.isEmpty())) baseRefObject->buildAllExpressionEnabledField();
        buildExpression();
        active = true;
@@ -770,4 +759,97 @@
    }
 
+   CGrid* CField::getGridRefOfBaseReference()
+   {
+     solveRefInheritance(true);
+     solveBaseReference();
+     baseRefObject->solveGridReference();
+
+     return baseRefObject->grid;
+   }
+
+   void CField::solveTransformedGrid()
+   {
+     if (!grid_ref.isEmpty() && (!field_ref.isEmpty()))
+     {
+       CField* fieldRef  = this;
+       CGrid* gridRefOfFieldRef = 0;
+       while (fieldRef->hasDirectFieldReference())
+       {
+         if ((!(fieldRef->grid_ref.isEmpty())) &&
+             (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
+         {
+           gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
+           fieldRef->addReference(this);
+           fieldRef->solveGridDomainAxisRef(false);
+           fieldRef->solveCheckMaskIndex(false);
+           break;
+         }
+         CField* tmp = fieldRef->getDirectFieldReference();
+         fieldRef = tmp;
+       }
+
+       if ((0 == gridRefOfFieldRef) &&
+           (!(fieldRef->grid_ref.isEmpty())) &&
+           (fieldRef->grid_ref.getValue() != grid_ref.getValue()))
+       {
+         gridRefOfFieldRef = fieldRef->getGridRefOfBaseReference();
+         fieldRef->addReference(this);
+         fieldRef->solveGridDomainAxisRef(false);
+         fieldRef->solveCheckMaskIndex(false);
+       }
+
+       CGrid* relGridRef = CGrid::get(grid_ref.getValue());
+       if ((0 != gridRefOfFieldRef) && (relGridRef != gridRefOfFieldRef) && (!(relGridRef->isTransformed())))
+       {
+         gridRefOfFieldRef->transformGrid(relGridRef);
+         filterSources_.push_back(fieldRef);
+         transformations_ = relGridRef->getTransformations();
+         switch (gridRefOfFieldRef->getGridElementType()) {
+         case CGrid::GRID_ONLY_AXIS:
+           filter = new CAxisFilter(gridRefOfFieldRef, relGridRef);
+           break;
+         default:
+           break;
+         }
+         setAlgorithms();
+       }
+     }
+   }
+
+
+  void CField::setAlgorithms()
+  {
+    std::vector<ETransformationType>::iterator itTrans  = transformations_.begin(),
+                                               iteTrans = transformations_.end();
+    std::set<ETransformationType> tmp;
+    for (; itTrans != iteTrans; ++itTrans)
+    {
+      if (tmp.end() == tmp.find(*itTrans))
+      {
+        switch (*itTrans) {
+        case eInverse:
+          algorithms_.push_back(new CInvertAlgorithm());
+          break;
+        default:
+          break;
+        }
+      }
+      tmp.insert(*itTrans);
+    }
+  }
+
+   const std::vector<CField*>& CField::getFilterSources()
+   {
+     return filterSources_;
+   }
+
+   void CField::applyFilter()
+   {
+     filter->setInputs(filterSources_);
+     filter->setOutput(this);
+     filter->apply(algorithms_);
+
+   }
+
    ///-------------------------------------------------------------------
 
Index: /XIOS/trunk/src/node/field.hpp
===================================================================
--- /XIOS/trunk/src/node/field.hpp	(revision 618)
+++ /XIOS/trunk/src/node/field.hpp	(revision 619)
@@ -15,4 +15,6 @@
 #include "expr_node.hpp"
 #include "declare_ref_func.hpp"
+#include "generic_filter.hpp"
+#include "transformation_enum.hpp"
 
 
@@ -28,4 +30,6 @@
    class CGrid;
    class CContext ;
+   class CGenericFilter;
+
    ///--------------------------------------------------------------
 
@@ -92,4 +96,7 @@
 
          template <int N> bool updateData(const CArray<double, N>&   data);
+         template <int N> bool updateFilteredData(CArray<double, N>&   data);
+         template<int N>
+         void updateDataWithoutOperation(const CArray<double, N>& data);
          bool updateDataFromExpression(const CArray<double, 1>&   data);
          void setDataFromExpression(const CArray<double, 1>& _data) ;
@@ -116,5 +123,6 @@
          void buildAllExpressionEnabledField();
          void solveGridDomainAxisRef(bool checkAtt);
-
+         void solveTransformedGrid();
+         CGrid* getGridRefOfBaseReference();
 
 //         virtual void fromBinary(StdIStream & is);
@@ -171,4 +179,8 @@
 
         const std::pair<StdString, StdString>& getRefDomainAxisIds();
+
+        const std::vector<CField*>& getFilterSources();
+        void applyFilter();
+        void setAlgorithms();
       public :
          /// PropriÃ©tÃ©s privÃ©es ///
@@ -193,4 +205,5 @@
          CArray<double, 1> data;
          CArray<double, 1> instantData;
+         CArray<double, 1> filteredData;
          bool hasInstantData ;
          map<int, CArray<double,1>* > data_srv ;
@@ -214,19 +227,8 @@
          std::pair<StdString,StdString> domAxisIds_;
          bool isReadDataRequestPending;
+         std::vector<CField*> filterSources_;
+         std::vector<CGenericAlgorithm*> algorithms_;
+         std::vector<ETransformationType> transformations_;
          DECLARE_REF_FUNC(Field,field)
-//       public:
-//         bool hasDirectFieldReference(void) const;
-//         CField* getDirectFieldReference(void) const;
-//         CField* getBaseFieldReference(void) const;
-//         void addReference(CField* field);
-//         const std::vector<CField*> & getAllReference(void) const;
-//void solveRefInheritance(bool apply);
-//void solveBaseReference(void);
-//         void removeRefInheritance();
-//         const StdString & getBaseFieldId(void) const;
-//
-//         std::vector<CField*> refObject;
-//         CField* baseRefObject;
-
 
    }; // class CField
Index: /XIOS/trunk/src/node/field_impl.hpp
===================================================================
--- /XIOS/trunk/src/node/field_impl.hpp	(revision 618)
+++ /XIOS/trunk/src/node/field_impl.hpp	(revision 619)
@@ -25,8 +25,27 @@
     {
       const std::vector<CField*>& refField=getAllReference();
-      std::vector<CField*>::const_iterator  it = refField.begin(), end = refField.end();
-
-      for (; it != end; it++) (*it)->setData(_data);
-      if (hasOutputFile || hasFieldOut) updateData(_data);
+      std::vector<CField*>::const_iterator  it = refField.begin(), end = refField.end(),
+                                            itFilterSrc, iteFilterSrc;
+
+      for (; it != end; it++)
+      {
+        const std::vector<CField*>& fieldFilterSources = (*it)->getFilterSources();
+        if (!fieldFilterSources.empty())
+        {
+          itFilterSrc = fieldFilterSources.begin(); iteFilterSrc = fieldFilterSources.end();
+          for (; itFilterSrc != iteFilterSrc; ++itFilterSrc) (*itFilterSrc)->updateDataWithoutOperation(_data);
+          (*it)->applyFilter();
+          std::cout << "it data " << (*it)->data << std::endl;
+          std::cout << "it filtered data " << (*it)->filteredData << std::endl;
+          if ((*it)->hasOutputFile || (*it)->hasFieldOut) (*it)->updateFilteredData((*it)->filteredData);
+        }
+        else
+        {
+          (*it)->setData(_data);
+          if (hasOutputFile || hasFieldOut) updateData(_data);
+        }
+
+      }
+
     }
   }
@@ -50,6 +69,16 @@
   }
 
-   template <int N>
-   bool CField::updateData(const CArray<double, N>& _data)
+   template<int N>
+   void CField::updateDataWithoutOperation(const CArray<double, N>& _data)
+   {
+     if (this->data.numElements() != this->grid->storeIndex_client.numElements())
+     {
+        this->data.resize(this->grid->storeIndex_client.numElements());
+        this->grid->inputField(_data, this->data);
+     }
+   }
+
+   template<int N>
+   bool CField::updateFilteredData(CArray<double, N>& filteredData)
    {
       CContext* context=CContext::getCurrent();
@@ -70,12 +99,10 @@
       if (doOperation)
       {
-         if (this->data.numElements() != this->grid->storeIndex_client.numElements())
-         {
-            this->data.resize(this->grid->storeIndex_client.numElements());
-         }
-
-         CArray<double,1> input(data.numElements());
-         this->grid->inputField(_data, input);
-         (*this->foperation)(input);
+         if (this->data.numElements() != filteredData.numElements())
+         {
+            this->data.resize(filteredData.numElements());
+         }
+
+         (*this->foperation)(filteredData);
 
          *last_operation = currDate;
@@ -106,8 +133,8 @@
          }
 
-         if (hasFieldOut)
-         {
-           fieldOut->setDataFromExpression(data);
-         }
+//         if (hasFieldOut)
+//         {
+//           fieldOut->setDataFromExpression(data);
+//         }
          return (true);
       }
@@ -116,5 +143,6 @@
    }
 
-   bool CField::updateDataFromExpression(const CArray<double, 1>& _data)
+   template <int N>
+   bool CField::updateData(const CArray<double, N>& _data)
    {
       CContext* context=CContext::getCurrent();
@@ -140,5 +168,7 @@
          }
 
-        (*this->foperation)(_data);
+         CArray<double,1> input(data.numElements());
+         this->grid->inputField(_data, input);
+         (*this->foperation)(input);
 
          *last_operation = currDate;
@@ -179,4 +209,67 @@
    }
 
+   bool CField::updateDataFromExpression(const CArray<double, 1>& _data)
+   {
+      CContext* context=CContext::getCurrent();
+      const CDate & currDate = context->getCalendar()->getCurrentDate();
+      const CDate opeDate      = *last_operation + freq_operation;
+      const CDate writeDate    = *last_Write     + freq_write;
+      bool doOperation, doWrite;
+
+
+      info(50) << "CField::updateData " << currDate <<  " : send data to " << this->getBaseFieldId() << std::endl;
+      info(50) << "Next operation "  << opeDate<<std::endl;
+
+      doOperation = (opeDate <= currDate);
+      if (isOnceOperation)
+        if (isFirstOperation) doOperation=true;
+        else doOperation=false;
+
+      if (doOperation)
+      {
+         if (this->data.numElements() != this->grid->storeIndex_client.numElements())
+         {
+            this->data.resize(this->grid->storeIndex_client.numElements());
+         }
+
+        (*this->foperation)(_data);
+
+         *last_operation = currDate;
+         info(50) << "(*last_operation = currDate) : " << *last_operation << " = " << currDate << std::endl;
+      }
+
+      doWrite = (writeDate < (currDate + freq_operation));
+      if (isOnceOperation)
+      {
+        if(isFirstOperation)
+        {
+          doWrite=true;
+          isFirstOperation=false;
+        }
+        else doWrite=false;
+      }
+
+      if (doWrite)
+      {
+         this->foperation->final();
+         *last_Write = writeDate;
+         if (hasOutputFile)
+         {
+           info(50) << "(*last_Write = currDate) : " << *last_Write << " = " << currDate << std::endl;
+           CTimer::get("XIOS Send Data").resume();
+           sendUpdateData();
+           CTimer::get("XIOS Send Data").suspend();
+         }
+
+         if (hasFieldOut)
+         {
+           fieldOut->setDataFromExpression(data);
+         }
+         return (true);
+      }
+
+      return (false);
+   }
+
   template <int N>
   void CField::getData(CArray<double, N>& _data) const
Index: /XIOS/trunk/src/node/grid.cpp
===================================================================
--- /XIOS/trunk/src/node/grid.cpp	(revision 618)
+++ /XIOS/trunk/src/node/grid.cpp	(revision 619)
@@ -14,4 +14,6 @@
 #include "array_new.hpp"
 #include "client_server_mapping_distributed.hpp"
+#include "invert_algorithm.hpp"
+#include "visitable.hpp"
 
 namespace xios {
@@ -24,5 +26,5 @@
       , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
       , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
-      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true)
+      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), algorithms_(), transformations_(), isTransformed_(false)
    {
      setVirtualDomainGroup();
@@ -35,5 +37,5 @@
       , vDomainGroup_(), vAxisGroup_(), axisList_(), isAxisListSet(false), isDomListSet(false), clientDistribution_(0), isIndexSent(false)
       , serverDistribution_(0), serverDistributionDescription_(0), clientServerMap_(0), writtenDataSize_(0), globalDim_()
-      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true)
+      , connectedDataSize_(), connectedServerRank_(), isDataDistributed_(true), algorithms_(), transformations_(), isTransformed_(false)
    {
      setVirtualDomainGroup();
@@ -51,4 +53,5 @@
     if (0 != serverDistribution_) delete serverDistribution_;
     if (0 != serverDistributionDescription_) delete serverDistributionDescription_;
+    for (std::vector<CGenericAlgorithm*>::iterator it = algorithms_.begin(); it != algorithms_.end(); ++it) delete *it;
    }
 
@@ -1093,8 +1096,115 @@
         pAxis->solveRefInheritance(apply);
         pAxis->solveBaseReference();
+        pAxis->solveInheritanceTransformation();
         if ((!pAxis->axis_ref.isEmpty()) && (pAxis->name.isEmpty()))
           pAxis->name.setValue(pAxis->getBaseAxisReference()->getId());
       }
     }
+  }
+
+  CGrid::EElementType CGrid::getGridElementType()
+  {
+    EElementType gridType = GRID_ONLY_AXIS;
+    int numElements = axis_domain_order.numElements();
+    if (1 == numElements)
+    {
+      if (true == axis_domain_order(0)) gridType = GRID_ONLY_DOMAIN;
+    }
+    else gridType = GRID_AXIS_DOMAIN;
+  }
+
+  void CGrid::solveTransformations()
+  {
+    std::vector<CAxis*> axisPtr = getAxis();
+    for (std::vector<CAxis*>::iterator it = axisPtr.begin(); it != axisPtr.end(); ++it)
+    {
+      std::vector<ETransformationType> axisTransformation = (*it)->getTransformations();
+      std::vector<ETransformationType>::iterator itTrans  = axisTransformation.begin(),
+                                                 iteTrans = axisTransformation.end();
+      for (;itTrans != iteTrans; ++ itTrans)
+        transformations_.push_back(*itTrans);
+    }
+  }
+
+  void CGrid::setTransformationAlgorithms()
+  {
+    std::vector<ETransformationType>::iterator itTrans  = transformations_.begin(),
+                                               iteTrans = transformations_.end();
+    std::set<ETransformationType> tmp;
+    for (; itTrans != iteTrans; ++itTrans)
+    {
+      if (tmp.end() == tmp.find(*itTrans))
+      {
+        switch (*itTrans) {
+        case eInverse:
+          algorithms_.push_back(new CInvertAlgorithm());
+          break;
+        default:
+          break;
+        }
+      }
+      tmp.insert(*itTrans);
+    }
+  }
+
+  std::vector<ETransformationType> CGrid::getTransformations()
+  {
+    return transformations_;
+  }
+
+  bool CGrid::isTransformed()
+  {
+    return isTransformed_;
+  }
+
+  void CGrid::setTransformed()
+  {
+    isTransformed_ = true;
+  }
+
+  const std::vector<CGenericAlgorithm*>& CGrid::getTransformationAlgo()
+  {
+    return algorithms_;
+  }
+
+  void CGrid::transformGrid(CGrid* transformedGrid)
+  {
+    if (transformedGrid->isTransformed()) return;
+    transformedGrid->setTransformed();
+    if (axis_domain_order.numElements() != transformedGrid->axis_domain_order.numElements())
+    {
+      ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
+           << "Two grids have different dimension size"
+           << "Dimension of grid source " <<this->getId() << " is " << axis_domain_order.numElements() << std::endl
+           << "Dimension of grid destination " <<transformedGrid->getId() << " is " << transformedGrid->axis_domain_order.numElements());
+    }
+    else
+    {
+      int ssize = axis_domain_order.numElements();
+      for (int i = 0; i < ssize; ++i)
+        if (axis_domain_order(i) != (transformedGrid->axis_domain_order)(i))
+          ERROR("CGrid::transformGrid(CGrid* transformedGrid)",
+                << "Grids " <<this->getId() <<" and " << transformedGrid->getId()
+                << " don't have elements in the same order");
+    }
+
+    EElementType gridType = getGridElementType();
+    CGenericTransformation* gTransform = 0;
+    switch (gridType) {
+    case GRID_ONLY_AXIS:
+      gTransform = new CAxisTransformation(this->getAxis(), transformedGrid->getAxis());
+      break;
+    case GRID_ONLY_DOMAIN:
+      break;
+    case GRID_AXIS_DOMAIN:
+      break;
+    default:
+      break;
+    }
+
+    transformedGrid->solveTransformations();
+    transformedGrid->setTransformationAlgorithms();
+    gTransform->apply(transformedGrid->algorithms_);
+    if (0 != gTransform) delete gTransform;
   }
 
Index: /XIOS/trunk/src/node/grid.hpp
===================================================================
--- /XIOS/trunk/src/node/grid.hpp	(revision 618)
+++ /XIOS/trunk/src/node/grid.hpp	(revision 619)
@@ -16,4 +16,6 @@
 #include "client_server_mapping.hpp"
 #include "utils.hpp"
+#include "transformation_enum.hpp"
+#include "visitor.hpp"
 
 namespace xios {
@@ -58,4 +60,9 @@
          } ;
 
+         enum EElementType
+         {
+           GRID_ONLY_AXIS, GRID_ONLY_DOMAIN, GRID_AXIS_DOMAIN
+         };
+
          /// Constructeurs ///
          CGrid(void);
@@ -140,4 +147,5 @@
          void solveAxisRef(bool checkAtt);
          void solveDomainAxisRefInheritance(bool apply = true);
+         void solveTransformations();
 
          void sendAddDomain(const std::string& id="");
@@ -175,4 +183,12 @@
          const CDistributionServer* getDistributionServer() const;
 
+         void transformGrid(CGrid* transformedGrid);
+         bool isTransformed();
+         void setTransformed();
+         EElementType getGridElementType();
+
+         std::vector<ETransformationType> getTransformations();
+         const std::vector<CGenericAlgorithm*>& getTransformationAlgo();
+
       public:
 
@@ -191,4 +207,5 @@
          void checkMask(void) ;
 
+         std::vector<CGenericAlgorithm*> algorithms_;
       private:
        template<int N>
@@ -214,4 +231,8 @@
         CAxisGroup* getVirtualAxisGroup() const;
         CDomainGroup* getVirtualDomainGroup() const;
+
+
+        void setTransformationAlgorithms();
+
         std::vector<int> globalDim_;
       private:
@@ -229,4 +250,8 @@
         std::vector<int> connectedServerRank_;
         bool isDataDistributed_;
+
+
+        std::vector<ETransformationType> transformations_;
+        bool isTransformed_;
    }; // class CGrid
 
Index: /XIOS/trunk/src/node/node_enum.hpp
===================================================================
--- /XIOS/trunk/src/node/node_enum.hpp	(revision 618)
+++ /XIOS/trunk/src/node/node_enum.hpp	(revision 619)
@@ -18,5 +18,6 @@
          eVariable,gVariable,
          eContext,gContext,
-         eCalendarWrapper
+         eCalendarWrapper,
+         eTransformation
 
 //#include "node_type.conf"
Index: /XIOS/trunk/src/node/node_type.hpp
===================================================================
--- /XIOS/trunk/src/node/node_type.hpp	(revision 618)
+++ /XIOS/trunk/src/node/node_type.hpp	(revision 619)
@@ -9,4 +9,5 @@
 #include "variable.hpp"
 #include "context.hpp"
+#include "transformation.hpp"
 
 #endif // __XIOS_NODE_TYPE__
Index: /XIOS/trunk/src/node/transformation.cpp
===================================================================
--- /XIOS/trunk/src/node/transformation.cpp	(revision 619)
+++ /XIOS/trunk/src/node/transformation.cpp	(revision 619)
@@ -0,0 +1,89 @@
+#include "transformation.hpp"
+#include "type.hpp"
+#include "duration.hpp"
+#include "context.hpp"
+#include <iterator>
+
+namespace xios {
+
+  /// ////////////////////// DÃ©finitions ////////////////////// ///
+
+  CTransformation::CTransformation(void)
+    : CObjectTemplate<CTransformation>(), CTransformationAttributes()
+  { /* Ne rien faire de plus */ }
+
+  CTransformation::CTransformation(const StdString & id)
+    : CObjectTemplate<CTransformation>(id), CTransformationAttributes()
+  { /* Ne rien faire de plus */ }
+
+  CTransformation::~CTransformation(void)
+  {}
+
+  //----------------------------------------------------------------
+
+  StdString CTransformation::GetName(void)    { return StdString("transformation"); }
+  StdString CTransformation::GetDefName(void) { return StdString("transformation"); }
+  ENodeType CTransformation::GetType(void)    { return eTransformation; }
+
+  StdString transTypeTmp[] = {"inverse", "zoom" };
+  CTransformation::TransformationId transTypeIdTmp[] = {CTransformation::TRANS_ID_INVERSE, CTransformation::TRANS_ID_ZOOM};
+  std::vector<StdString> CTransformation::TransformationTypes = std::vector<StdString>(transTypeTmp, transTypeTmp + sizeof(transTypeTmp) / sizeof(StdString));
+  std::vector<CTransformation::TransformationId> CTransformation::TransformationTypeIds = std::vector<CTransformation::TransformationId>(transTypeIdTmp, transTypeIdTmp + sizeof(transTypeIdTmp) / sizeof(CTransformation::TransformationId));
+  //----------------------------------------------------------------
+
+  void CTransformation::checkAttributes()
+  {
+    if (this->type.isEmpty())
+      ERROR("CTransformation::checkAttributes(void)",
+             << "Attribute <type> of the transformation in the context = '"
+             << CObjectFactory::GetCurrentContextId() << "' ] must be specified");
+    StdString transformationTypeStr = this->type.getValue();
+
+    std::vector<StdString>::const_iterator itbTrans = TransformationTypes.begin(), itTrans,
+                                           iteTrans = TransformationTypes.end();
+    itTrans = std::find(itbTrans, iteTrans,transformationTypeStr);
+    if (TransformationTypes.end() == itTrans)
+    {
+      StdString msgTmp;
+      for (std::vector<StdString>::const_iterator it = itbTrans; it != iteTrans; ++it)
+        msgTmp += *it + ", ";
+      ERROR("CTransformation::checkAttributes(void)",
+            << "Attribute <type = " << transformationTypeStr << " > is invalid"
+            << "It should be one of following: " << msgTmp);
+    }
+
+//    if (this->axis_ref.isEmpty() && this->domain_ref.isEmpty())
+//      ERROR("CTransformation::checkAttributes(void)",
+//            << "Attribute <axis_ref> or <domain_ref> of the transformation in the context = '"
+//            << CObjectFactory::GetCurrentContextId() << "' ] must be specified");
+
+
+    checkAttributesType(TransformationTypeIds[std::distance(itbTrans, itTrans)]);
+  }
+
+  void CTransformation::checkAttributesType(TransformationId& typeId)
+  {
+    switch (typeId) {
+    case TRANS_ID_ZOOM:
+      checkAttributesZoomType();
+      break;
+    case TRANS_ID_INVERSE:
+      checkAttributesInverseType();
+      break;
+    default:
+      ERROR("CTransformation::checkAttributesType(TransformationId& typeId)",
+            << "Type = " << typeId << " is invalid");
+    }
+  }
+
+  void CTransformation::checkAttributesZoomType()
+  {
+
+  }
+
+  void CTransformation::checkAttributesInverseType()
+  {
+
+  }
+
+}
Index: /XIOS/trunk/src/node/transformation.hpp
===================================================================
--- /XIOS/trunk/src/node/transformation.hpp	(revision 619)
+++ /XIOS/trunk/src/node/transformation.hpp	(revision 619)
@@ -0,0 +1,74 @@
+#ifndef __XMLIO_CTransformation__
+#define __XMLIO_CTransformation__
+
+/// xios headers ///
+#include "xmlioserver_spl.hpp"
+#include "attribute_enum.hpp"
+#include "attribute_enum_impl.hpp"
+#include "attribute_array.hpp"
+#include "declare_attribute.hpp"
+#include "object_template.hpp"
+#include "group_factory.hpp"
+#include "declare_group.hpp"
+
+namespace xios {
+
+  /// ////////////////////// DÃ©clarations ////////////////////// ///
+  class CTransformationGroup;
+  class CTransformationAttributes;
+  class CTransformation;
+  ///--------------------------------------------------------------
+
+  // Declare/Define CFileAttribute
+  BEGIN_DECLARE_ATTRIBUTE_MAP(CTransformation)
+#include "transformation_attribute.conf"
+  END_DECLARE_ATTRIBUTE_MAP(CTransformation)
+
+  ///--------------------------------------------------------------
+  /*!
+    \class CTransformation
+    This class describes transformation in xml file.
+  */
+  class CTransformation
+    : public CObjectTemplate<CTransformation>
+    , public CTransformationAttributes
+  {
+    public :
+      enum TransformationId
+      {
+        TRANS_ID_ZOOM, TRANS_ID_INVERSE
+      };
+      typedef CObjectTemplate<CTransformation> SuperClass;
+      typedef CTransformationAttributes SuperClassAttribute;
+
+    public :
+      /// Constructeurs ///
+      CTransformation(void);
+      explicit CTransformation(const StdString& id);
+
+      /// Destructeur ///
+      virtual ~CTransformation(void);
+
+      /// Accesseurs statiques ///
+      static StdString GetName(void);
+      static StdString GetDefName(void);
+      static ENodeType GetType(void);
+    private:
+      static std::vector<StdString> TransformationTypes;
+      static std::vector<TransformationId> TransformationTypeIds;
+
+    public :
+      void checkAttributes();
+
+    private:
+      void checkAttributesType(TransformationId& transType);
+      void checkAttributesZoomType();
+      void checkAttributesInverseType();
+
+    private:
+  }; // class CTransformation
+
+  DECLARE_GROUP(CTransformation);
+} // namespace xios
+
+#endif // __XMLIO_CTransformation__
Index: /XIOS/trunk/src/node/transformation_enum.hpp
===================================================================
--- /XIOS/trunk/src/node/transformation_enum.hpp	(revision 619)
+++ /XIOS/trunk/src/node/transformation_enum.hpp	(revision 619)
@@ -0,0 +1,22 @@
+#ifndef __XMLIO_TRANSFORMATION_ENUM__
+#define __XMLIO_TRANSFORMATION_ENUM__
+
+//#define DECLARE_NODE(Name_, name_)     ,e##Name_, g##Name_
+//#define DECLARE_NODE_PAR(Name_, name_) ,e##Name_, g##Name_
+
+namespace xios
+{
+      /// ////////////////////// DÃ©finitions ////////////////////// ///
+      typedef enum transformationType
+      {
+         UnknownTransformation = 0,
+         eInverse,
+         eZoom
+
+//#include "node_type.conf"
+
+      } ETransformationType;
+
+} // namespace xios
+
+#endif // __XMLIO_TRANSFORMATION_ENUM__
Index: /XIOS/trunk/src/object_factory_decl.cpp
===================================================================
--- /XIOS/trunk/src/object_factory_decl.cpp	(revision 618)
+++ /XIOS/trunk/src/object_factory_decl.cpp	(revision 619)
@@ -24,4 +24,5 @@
   macro(CCalendarWrapper)
   macro(CVariable)
+  macro(CTransformation)
 
   macro(CFieldGroup)
@@ -32,3 +33,4 @@
   macro(CContextGroup)
   macro(CVariableGroup)
+  macro(CTransformationGroup)
 }
Index: /XIOS/trunk/src/object_template_decl.cpp
===================================================================
--- /XIOS/trunk/src/object_template_decl.cpp	(revision 618)
+++ /XIOS/trunk/src/object_template_decl.cpp	(revision 619)
@@ -8,4 +8,5 @@
 #include "axis.hpp"
 #include "variable.hpp"
+#include "transformation.hpp"
 
 
@@ -20,4 +21,5 @@
   template class CObjectTemplate<CAxis>;
   template class CObjectTemplate<CVariable>;
+  template class CObjectTemplate<CTransformation>;
 
   template class CObjectTemplate<CContextGroup>;
@@ -28,3 +30,4 @@
   template class CObjectTemplate<CAxisGroup>;
   template class CObjectTemplate<CVariableGroup>;
+  template class CObjectTemplate<CTransformationGroup>;
 }
Index: /XIOS/trunk/src/test/test_new_features.f90
===================================================================
--- /XIOS/trunk/src/test/test_new_features.f90	(revision 618)
+++ /XIOS/trunk/src/test/test_new_features.f90	(revision 619)
@@ -17,5 +17,5 @@
   INTEGER,PARAMETER :: ni_glo=100
   INTEGER,PARAMETER :: nj_glo=100
-  INTEGER,PARAMETER :: llm=5
+  INTEGER,PARAMETER :: llm=10
   DOUBLE PRECISION  :: lval(llm)=1, tsTemp
   TYPE(xios_field) :: field_hdl
@@ -26,5 +26,5 @@
   DOUBLE PRECISION,DIMENSION(ni_glo,nj_glo) :: lon_glo,lat_glo
   DOUBLE PRECISION :: field_A_glo(ni_glo,nj_glo,llm), lval_ni(ni_glo), lval_nj(nj_glo)
-  DOUBLE PRECISION,ALLOCATABLE :: lon(:,:),lat(:,:),field_A(:,:,:), field_All_Axis(:,:,:), lonvalue(:) , field_Axis(:)
+  DOUBLE PRECISION,ALLOCATABLE :: lon(:,:),lat(:,:),field_A(:,:,:), field_All_Axis(:,:,:), lonvalue(:) , field_Axis(:), lvaln(:), field_Two_Axis(:,:)
   INTEGER :: ni,ibegin,iend,nj,jbegin,jend, nAxis, axisBegin, axisEnd
   INTEGER :: i,j,l,ts,n
@@ -67,13 +67,18 @@
   axisBegin = 0
   nAxis = llm
-!  DO n=0, size -1
-!    nAxis = llm/size
-!    IF (n<MOD(llm,size)) nAxis=nAxis+1
-!    IF (n==rank) exit
-!    axisBegin=axisBegin+nAxis
-!  ENDDO
+  DO n=0, size -1
+    nAxis = llm/size
+    IF (n<MOD(llm,size)) nAxis=nAxis+1
+    IF (n==rank) exit
+    axisBegin=axisBegin+nAxis
+  ENDDO
   axisEnd=axisBegin+nAxis-1
 
-  ALLOCATE(lon(ni,nj),lat(ni,nj),field_A(0:ni+1,-1:nj+2,llm),lonvalue(ni*nj), field_Axis(nAxis), field_All_Axis(1:ni,1:nj,llm))
+  DO i=1,llm
+    lval(i) = i
+  ENDDO
+
+
+  ALLOCATE(lon(ni,nj),lat(ni,nj),field_A(0:ni+1,-1:nj+2,llm),lonvalue(ni*nj), field_Axis(nAxis), field_All_Axis(1:ni,1:nj,llm), lvaln(nAxis), field_Two_Axis(ni_glo,1:nj))
   lon(:,:)=lon_glo(ibegin+1:iend+1,jbegin+1:jend+1)
   lat(:,:)=lat_glo(ibegin+1:iend+1,jbegin+1:jend+1)
@@ -81,4 +86,6 @@
   field_Axis(1:nAxis)  = field_A_glo(1,1,axisBegin+1:axisEnd+1)
   field_All_Axis(1:ni,1:nj,:) = field_A_glo(ibegin+1:iend+1,jbegin+1:jend+1,:)
+  field_Two_Axis(:,1:nAxis)  = field_A_glo(:,jbegin+1:jend+1,1)
+  lvaln(1:nAxis) = lval(axisBegin+1:axisEnd+1)
 
   CALL xios_context_initialize("test",comm)
@@ -92,5 +99,5 @@
   CALL xios_set_axis_attr("axis_B", size=nj_glo, ibegin=jbegin, ni=nj, value=lval_nj)
   CALL xios_set_axis_attr("axis_C", size=llm, value=lval)
-  CALL xios_set_axis_attr("axis_D", size=llm, ibegin=axisBegin, ni=nAxis, value=lval)
+  CALL xios_set_axis_attr("axis_D", size=llm, ibegin=axisBegin, ni=nAxis, value=lvaln)
   CALL xios_set_domain_attr("domain_A",ni_glo=ni_glo, nj_glo=nj_glo, ibegin=ibegin, ni=ni,jbegin=jbegin,nj=nj)
   CALL xios_set_domain_attr("domain_A",data_dim=2, data_ibegin=-1, data_ni=ni+2, data_jbegin=-2, data_nj=nj+4)
@@ -99,15 +106,15 @@
   CALL xios_set_fieldgroup_attr("field_definition",enabled=.TRUE.)
 
-  CALL xios_get_handle("field_definition",fieldgroup_hdl)
-  CALL xios_add_child(fieldgroup_hdl,field_hdl,"field_B")
-  CALL xios_set_attr(field_hdl,field_ref="field_A",name="field_B")
-
-  CALL xios_get_handle("output",file_hdl)
-  CALL xios_add_child(file_hdl,field_hdl)
-  CALL xios_set_attr(field_hdl,field_ref="field_A",name="field_C")
-
-  CALL xios_get_handle("output_All_Axis",file_hdl)
-  CALL xios_add_child(file_hdl,field_hdl)
-  CALL xios_set_attr(field_hdl,field_ref="field_All_Axis",name="field_C")
+!  CALL xios_get_handle("field_definition",fieldgroup_hdl)
+!  CALL xios_add_child(fieldgroup_hdl,field_hdl,"field_B")
+!  CALL xios_set_attr(field_hdl,field_ref="field_A",name="field_B")
+!
+!  CALL xios_get_handle("output",file_hdl)
+!  CALL xios_add_child(file_hdl,field_hdl)
+!  CALL xios_set_attr(field_hdl,field_ref="field_A",name="field_C")
+!
+!  CALL xios_get_handle("output_All_Axis",file_hdl)
+!  CALL xios_add_child(file_hdl,field_hdl)
+!  CALL xios_set_attr(field_hdl,field_ref="field_All_Axis",name="field_C")
 
   dtime%second = 3600
@@ -146,9 +153,11 @@
   DO ts=1,24*10
     CALL xios_update_calendar(ts)
-    CALL xios_send_field("field_A",field_A)
+!    CALL xios_send_field("field_A",field_A)
     CALL xios_send_field("field_Axis",field_Axis)
-    CALL xios_send_field("field_All_Axis",field_All_Axis)
-    tsTemp = ts
-    CALL xios_send_scalar("field_Scalar", tsTemp)
+
+    CALL xios_send_field("field_Two_Axis",field_Two_Axis)
+!    CALL xios_send_field("field_All_Axis",field_All_Axis)
+!    tsTemp = ts
+!    CALL xios_send_scalar("field_Scalar", tsTemp)
     CALL wait_us(5000) ;
   ENDDO
Index: /XIOS/trunk/src/type/type_util.hpp
===================================================================
--- /XIOS/trunk/src/type/type_util.hpp	(revision 618)
+++ /XIOS/trunk/src/type/type_util.hpp	(revision 619)
@@ -20,4 +20,6 @@
     class CVariable;
     class CVariableGroup;
+    class CTransformation;
+    class CTransformationGroup;
 
   template <typename T> inline string getStrType(void);
@@ -56,4 +58,6 @@
   macro(CVariable)
   macro(CVariableGroup)
+  macro(CTransformation)
+  macro(CTransformationGroup)
 
 #undef macro
Index: /XIOS/trunk/src/virtual_node.hpp
===================================================================
--- /XIOS/trunk/src/virtual_node.hpp	(revision 619)
+++ /XIOS/trunk/src/virtual_node.hpp	(revision 619)
@@ -0,0 +1,35 @@
+/*!
+   \file virtual_group.hpp
+   \author Ha NGUYEN
+   \date 14 Aprill 2015
+   \since 14 April 2015
+
+   \brief Class template for virtual nodes
+ */
+#ifndef __XIOS_VIRTUAL_NODE_HPP__
+#define __XIOS_VIRTUAL_NODE_HPP__
+
+namespace xios {
+/*!
+\class CVirtualNode
+On processing xml file, there are several cases in which a node contains other node type.
+These different nodes are stored in a virtual node.
+*/
+template<typename NodeType>
+class CVirtualNode
+{
+public:
+  CVirtualNode() { this->setVirtualNode(); }
+  virtual ~CVirtualNode() {}
+
+protected:
+  void setVirtualNode(NodeType* newVirtualNode) { this->virtualNode_ = newVirtualNode; }
+  void setVirtualNode() { this->setVirtualNode(NodeType::create());}
+  NodeType* getVirtualNode() const { return virtualNode_; }
+
+protected:
+  NodeType* virtualNode_;
+};
+
+}
+#endif // __XIOS_VIRTUAL_NODE_HPP__
Index: /XIOS/trunk/src/visitable.hpp
===================================================================
--- /XIOS/trunk/src/visitable.hpp	(revision 619)
+++ /XIOS/trunk/src/visitable.hpp	(revision 619)
@@ -0,0 +1,103 @@
+#ifndef __XIOS_VISITABLE_HPP
+#define __XIOS_VISITABLE_HPP
+
+#include "visitor.hpp"
+#include <vector>
+
+namespace xios {
+
+template <typename R, typename ParamType>
+struct DefaultCatchAll
+{
+  static R OnUnknownVisitor(ParamType&, CBaseVisitor&)
+  { return R(); }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// class template CBaseVisitable
+////////////////////////////////////////////////////////////////////////////////
+template
+<
+  typename R = void,
+  template <typename, class> class CatchAll = DefaultCatchAll,
+  bool ConstVisitable = false
+>
+class CBaseVisitable;
+
+template<typename R,template <typename, class> class CatchAll>
+class CBaseVisitable<R, CatchAll, false>
+{
+public:
+  typedef R ReturnType;
+  virtual ~CBaseVisitable() {}
+  virtual ReturnType apply(CBaseVisitor&) = 0;
+  virtual void apply(std::vector<CBaseVisitor*>&) = 0;
+
+protected: // give access only to the hierarchy
+  template <class T>
+  static ReturnType applyImpl(T& visited, CBaseVisitor& guest)
+  {
+    // Apply the CVisitor
+    if (CVisitor<T,R>* p = dynamic_cast<CVisitor<T,R>*>(&guest))
+    {
+        return p->operate(visited);
+    }
+    return CatchAll<R, T>::OnUnknownVisitor(visited, guest);
+  }
+};
+
+template<typename R,template <typename, class> class CatchAll>
+class CBaseVisitable<R, CatchAll, true>
+{
+public:
+  typedef R ReturnType;
+  virtual ~CBaseVisitable() {}
+  virtual ReturnType apply(CBaseVisitor&) const = 0;
+  virtual void apply(std::vector<CBaseVisitor*>&) const = 0;
+
+protected: // give access only to the hierarchy
+  template <class T>
+  static ReturnType applyImpl(const T& visited, CBaseVisitor& guest)
+  {
+    // Apply the CVisitor
+    if (CVisitor<T,R>* p = dynamic_cast<CVisitor<T,R, true>*>(&guest))
+    {
+      return p->operate(visited);
+    }
+    return CatchAll<R, T>::OnUnknownVisitor(const_cast<T&>(visited), guest);
+  }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+/// Put it in every class that you want to make guest
+/// functions (in addition to deriving it from CBaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+#define DEFINE_VISITABLE() \
+    virtual ReturnType apply(::xios::CBaseVisitor& guest) \
+    { return applyImpl(*this, guest); }                   \
+    virtual void apply(std::vector<CBaseVisitor*>& guests) \
+    {                                                             \
+      for (std::vector<CBaseVisitor*>::iterator it = guests.begin(); it != guests.end(); ++it) \
+        apply(*(*it));                                                                                \
+    }
+////////////////////////////////////////////////////////////////////////////////
+/// Put it in every class that you want to make guest by const member
+/// functions (in addition to deriving it from CBaseVisitable<R>)
+////////////////////////////////////////////////////////////////////////////////
+#define DEFINE_CONST_VISITABLE() \
+    virtual ReturnType apply(::xios::CBaseVisitor& guest) const \
+    { return applyImpl(*this, guest); }                         \
+    virtual void apply(std::vector<CBaseVisitor*>& guests) const \
+    {                                                             \
+      for (std::vector<CBaseVisitor*>::iterator it = guests.begin(); it != guests.end(); ++it) \
+        apply(*(*it));                                                                                \
+    }
+
+class CGenericTransformation : public virtual CBaseVisitable<>
+{
+public:
+  DEFINE_VISITABLE()
+};
+
+}
+#endif // __XIOS_VISITABLE_HPP
Index: /XIOS/trunk/src/visitor.hpp
===================================================================
--- /XIOS/trunk/src/visitor.hpp	(revision 619)
+++ /XIOS/trunk/src/visitor.hpp	(revision 619)
@@ -0,0 +1,38 @@
+#ifndef __XIOS_VISITOR_HPP__
+#define __XIOS_VISITOR_HPP__
+
+namespace xios {
+
+class CBaseVisitor
+{
+public:
+    virtual ~CBaseVisitor() {}
+};
+
+typedef CBaseVisitor CGenericAlgorithm;
+
+template <class T, typename R = void, bool ConstVisitor = false>
+class CVisitor;
+
+template<typename T, typename R>
+class CVisitor<T, R, false>
+{
+public:
+    typedef R ReturnType;
+    typedef T ParamType;
+    virtual ~CVisitor() {}
+    virtual ReturnType operate(ParamType&) = 0;
+};
+
+template<typename T, typename R>
+class CVisitor<T, R, true>
+{
+public:
+    typedef R ReturnType;
+    typedef const T ParamType;
+    virtual ~CVisitor() {}
+    virtual ReturnType operate(ParamType&) = 0;
+};
+
+}
+#endif // __XIOS_VISITOR_HPP__
Index: /XIOS/trunk/src/xml_parser_decl.cpp
===================================================================
--- /XIOS/trunk/src/xml_parser_decl.cpp	(revision 618)
+++ /XIOS/trunk/src/xml_parser_decl.cpp	(revision 619)
@@ -7,5 +7,5 @@
 #include "file.hpp"
 #include "variable.hpp"
-
+#include "transformation.hpp"
 
 namespace xios
@@ -14,15 +14,16 @@
   {
     template void CXMLParser::ParseInclude<CContext>(StdIStream & stream, const string& fluxId, CContext& object) ;
- 
+
  #   define macro(T) \
     template void CXMLParser::ParseInclude< CGroupTemplate<C##T, C##T##Group, C##T##Attributes> >(StdIStream & stream, const string& fluxId, CGroupTemplate<C##T, C##T##Group, C##T##Attributes>& object) ;
-    
-    macro( Context ) 
-    macro( Axis ) 
-    macro( Domain ) 
-    macro( Grid ) 
-    macro( Field ) 
-    macro( File ) 
-    macro( Variable ) 
+
+    macro( Context )
+    macro( Axis )
+    macro( Domain )
+    macro( Grid )
+    macro( Field )
+    macro( File )
+    macro( Variable )
+    macro( Transformation )
   }
 }
