Index: XIOS/trunk/src/filter/axis_algorithm_transformation.cpp
===================================================================
--- XIOS/trunk/src/filter/axis_algorithm_transformation.cpp	(revision 620)
+++ XIOS/trunk/src/filter/axis_algorithm_transformation.cpp	(revision 620)
@@ -0,0 +1,136 @@
+#include "axis_algorithm_transformation.hpp"
+
+namespace xios {
+
+CAxisAlgorithmTransformation::CAxisAlgorithmTransformation(CAxis* axisDestination)
+ : CGenericAlgorithmTransformation()
+{
+  int niDest = axisDestination->ni.getValue();
+  int ibeginDest = axisDestination->ibegin.getValue();
+
+  for (int idx = 0; idx < niDest; ++idx) axisDestGlobalIndex_.push_back(ibeginDest+idx);
+}
+
+/*!
+  Compute an array of global index from a global index on a axis
+  \param[in] axisDestGlobalIndex global index on an axis of destination grid
+  \param[in] axisSrcGlobalIndex global index on an axis of source grid (which are needed by one index on axis destination)
+  \param[in] axisPositionInGrid position of the axis in the grid
+  \param[in] gridDestGlobalDim dimension size of destination grid (it should share the same size for all dimension, maybe except the axis on which transformation is performed)
+  \param[in] globalIndexGridDestSendToServer global index of destination grid which are to be sent to server(s)
+  \param[in/out] globalIndexDestGrid array of global index (for 2d grid, this array is a line, for 3d, this array represents a plan). It should be preallocated
+  \param[in/out] globalIndexSrcGrid array of global index of source grid (for 2d grid, this array is a line, for 3d, this array represents a plan). It should be preallocated
+*/
+void CAxisAlgorithmTransformation::computeGlobalIndexFromGlobalIndexElement(int axisDestGlobalIndex,
+                                                                          const std::vector<int>& axisSrcGlobalIndex,
+                                                                          int axisPositionInGrid,
+                                                                          const std::vector<int>& gridDestGlobalDim,
+                                                                          const CArray<size_t,1>& globalIndexGridDestSendToServer,
+                                                                          CArray<size_t,1>& globalIndexDestGrid,
+                                                                          std::vector<CArray<size_t,1> >& globalIndexSrcGrid)
+{
+  int globalDim = gridDestGlobalDim.size();
+
+  std::vector<size_t> currentIndex(globalDim);
+  std::vector<int> gridAxisGlobalDim(globalDim);
+  std::vector<int> idxLoop(globalDim, 0);
+
+  size_t ssize = 1, idx = 0, realGlobalIndexSize = 0;
+  for (int i = 0; i< globalDim; ++i)
+  {
+    if (axisPositionInGrid == i) gridAxisGlobalDim[i] = 1;
+    else gridAxisGlobalDim[i] = gridDestGlobalDim[i];
+    ssize *= gridAxisGlobalDim[i];
+  }
+
+  CArray<size_t,1>::const_iterator itbArr = globalIndexGridDestSendToServer.begin(), itArr,
+                                   iteArr = globalIndexGridDestSendToServer.end();
+
+  while (idx < ssize)
+  {
+    for (int i = 0; i < globalDim-1; ++i)
+    {
+      if (idxLoop[i] == gridAxisGlobalDim[i])
+      {
+        idxLoop[i] = 0;
+        ++idxLoop[i+1];
+      }
+    }
+
+    for (int i = 0; i < globalDim; ++i) currentIndex[i] = idxLoop[i];
+    currentIndex[axisPositionInGrid] = axisDestGlobalIndex;
+
+    size_t globIndex = currentIndex[0];
+    size_t mulDim = 1;
+    for (int k = 1; k < globalDim; ++k)
+    {
+      mulDim *= gridDestGlobalDim[k-1];
+      globIndex += (currentIndex[k])*mulDim;
+    }
+
+    itArr = std::find(itbArr, iteArr, globIndex);
+    if (iteArr != itArr) ++realGlobalIndexSize;
+    ++idxLoop[0];
+    ++idx;
+  }
+
+  if (globalIndexDestGrid.numElements() != realGlobalIndexSize)
+    globalIndexDestGrid.resize(realGlobalIndexSize);
+
+  if (axisSrcGlobalIndex.size() != globalIndexSrcGrid.size()) globalIndexSrcGrid.resize(axisSrcGlobalIndex.size());
+  for (int i = 0; i < globalIndexSrcGrid.size(); ++i)
+    if (globalIndexSrcGrid[i].numElements() != realGlobalIndexSize)
+      globalIndexSrcGrid[i].resize(realGlobalIndexSize);
+
+
+  size_t realGlobalIndex = 0;
+  idx = 0;
+  idxLoop.assign(globalDim, 0);
+  while (idx < ssize)
+  {
+    for (int i = 0; i < globalDim-1; ++i)
+    {
+      if (idxLoop[i] == gridAxisGlobalDim[i])
+      {
+        idxLoop[i] = 0;
+        ++idxLoop[i+1];
+      }
+    }
+
+    for (int i = 0; i < globalDim; ++i) currentIndex[i] = idxLoop[i];
+    currentIndex[axisPositionInGrid] = axisDestGlobalIndex;
+
+    size_t globIndex = currentIndex[0];
+    size_t mulDim = 1;
+    for (int k = 1; k < globalDim; ++k)
+    {
+      mulDim *= gridDestGlobalDim[k-1];
+      globIndex += (currentIndex[k])*mulDim;
+    }
+
+    itArr = std::find(itbArr, iteArr, globIndex);
+    if (iteArr != itArr)
+    {
+      globalIndexDestGrid(realGlobalIndex) = globIndex;
+      for (int i = 0; i < globalIndexSrcGrid.size(); ++i)
+      {
+        currentIndex[axisPositionInGrid] = axisSrcGlobalIndex[i];
+        globIndex = currentIndex[0];
+        mulDim = 1;
+        for (int k = 1; k < globalDim; ++k)
+        {
+          mulDim *= gridDestGlobalDim[k-1];
+          globIndex += (currentIndex[k])*mulDim;
+        }
+        (globalIndexSrcGrid[i])(realGlobalIndex) = globIndex;
+      }
+      ++realGlobalIndex;
+    }
+
+    ++idxLoop[0];
+    ++idx;
+  }
+}
+
+
+}
Index: XIOS/trunk/src/filter/axis_algorithm_transformation.hpp
===================================================================
--- XIOS/trunk/src/filter/axis_algorithm_transformation.hpp	(revision 620)
+++ XIOS/trunk/src/filter/axis_algorithm_transformation.hpp	(revision 620)
@@ -0,0 +1,31 @@
+#ifndef __XIOS_AXIS_ALGORITHM_TRANSFORMATION_HPP__
+#define __XIOS_AXIS_ALGORITHM_TRANSFORMATION_HPP__
+
+#include "generic_algorithm_transformation.hpp"
+#include "axis.hpp"
+
+namespace xios {
+
+class CAxisAlgorithmTransformation : public virtual CGenericAlgorithmTransformation
+{
+public:
+  CAxisAlgorithmTransformation(CAxis* axisDestination);
+  virtual ~CAxisAlgorithmTransformation() {}
+
+protected:
+  virtual void computeGlobalIndexFromGlobalIndexElement(int axisDestGlobalIndex,
+                                                        const std::vector<int>& axisSrcGlobalIndex,
+                                                        int axisPositionInGrid,
+                                                        const std::vector<int>& gridDestGlobalDim,
+                                                        const CArray<size_t,1>& globalIndexGridDestSendToServer,
+                                                        CArray<size_t,1>& globalIndexDestGrid,
+                                                        std::vector<CArray<size_t,1> >& globalIndexSrcGrid);
+  virtual void computeIndexSourceMapping() = 0;
+
+protected:
+  std::vector<int> axisDestGlobalIndex_;
+
+};
+
+}
+#endif // __XIOS_AXIS_ALGORITHM_TRANSFORMATION_HPP__
Index: XIOS/trunk/src/filter/axis_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/axis_filter.cpp	(revision 619)
+++ 	(revision )
@@ -1,30 +1,0 @@
-#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)
+++ 	(revision )
@@ -1,27 +1,0 @@
-#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_inverse.cpp
===================================================================
--- XIOS/trunk/src/filter/axis_inverse.cpp	(revision 620)
+++ XIOS/trunk/src/filter/axis_inverse.cpp	(revision 620)
@@ -0,0 +1,32 @@
+#include "axis_inverse.hpp"
+
+namespace xios {
+
+CAxisInverse::CAxisInverse(CAxis* axisDestination, CAxis* axisSource)
+ : CAxisAlgorithmTransformation(axisDestination)
+{
+  if (axisDestination->size.getValue() != axisSource->size.getValue())
+  {
+    ERROR("CAxisInverse::CAxisInverse(CAxis* axisDestination, CAxis* axisSource)",
+           << "Two axis have different size"
+           << "Size of axis source " <<axisSource->getId() << " is " << axisSource->size.getValue()  << std::endl
+           << "Size of axis destionation " <<axisDestination->getId() << " is " << axisDestination->size.getValue());
+  }
+
+  axisDestGlobalSize_ = axisDestination->size.getValue();
+
+  this->computeIndexSourceMapping();
+}
+
+void CAxisInverse::computeIndexSourceMapping()
+{
+  std::map<int, std::vector<int> >& transMap = this->transformationMapping_;
+  if (!transMap.empty()) transMap.clear();
+
+  int globalIndexSize = axisDestGlobalIndex_.size();
+  for (int idx = 0; idx < globalIndexSize; ++idx)
+    transMap[axisDestGlobalIndex_[idx]].push_back(axisDestGlobalSize_-axisDestGlobalIndex_[idx]-1);
+}
+
+
+}
Index: XIOS/trunk/src/filter/axis_inverse.hpp
===================================================================
--- XIOS/trunk/src/filter/axis_inverse.hpp	(revision 620)
+++ XIOS/trunk/src/filter/axis_inverse.hpp	(revision 620)
@@ -0,0 +1,23 @@
+#ifndef __XIOS_AXIS_ALGORITHM_INVERSE_HPP__
+#define __XIOS_AXIS_ALGORITHM_INVERSE_HPP__
+
+#include "axis_algorithm_transformation.hpp"
+#include "axis.hpp"
+
+namespace xios {
+
+class CAxisInverse : public CAxisAlgorithmTransformation
+{
+public:
+  CAxisInverse(CAxis* axisDestination, CAxis* axisSource);
+
+  virtual ~CAxisInverse() {}
+protected:
+  virtual void computeIndexSourceMapping();
+
+private:
+  int axisDestGlobalSize_;
+};
+
+}
+#endif // __XIOS_AXIS_ALGORITHM_INVERSE_HPP__
Index: XIOS/trunk/src/filter/axis_transformation.cpp
===================================================================
--- XIOS/trunk/src/filter/axis_transformation.cpp	(revision 619)
+++ 	(revision )
@@ -1,31 +1,0 @@
-#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)
+++ 	(revision )
@@ -1,30 +1,0 @@
-#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_algorithm_transformation.cpp
===================================================================
--- XIOS/trunk/src/filter/generic_algorithm_transformation.cpp	(revision 620)
+++ XIOS/trunk/src/filter/generic_algorithm_transformation.cpp	(revision 620)
@@ -0,0 +1,51 @@
+#include "generic_algorithm_transformation.hpp"
+
+namespace xios {
+
+CGenericAlgorithmTransformation::CGenericAlgorithmTransformation()
+ : transformationMapping_()
+{
+}
+
+/*!
+  This function computes the global indexes of grid source, which the grid destination is in demand.
+  \param[in] elementPositionInGrid position of an element in a grid .E.g: if grid is composed of domain and axis (in order),
+                then position of axis in grid is 2 (since a domain is considered to contain 2 elements (axis)
+  \param[in] gridDestGlobalDim global size of each dimension of grid source (all dimension must have the same size except of the one on which transformation is performed)
+  \param[in] globalIndexGridDestSendToServer global index of grid destination on the current client to send to server
+  \param[in/out] globaIndexMapFromDestToSource mapping between transformed global index of grid destination
+                    and the demanded global index of grid source
+*/
+void CGenericAlgorithmTransformation::computeGlobalSourceIndex(int elementPositionInGrid,
+                                                             const std::vector<int>& gridDestGlobalDim,
+                                                             const CArray<size_t,1>& globalIndexGridDestSendToServer,
+                                                             std::map<size_t, std::set<size_t> >& globaIndexMapFromDestToSource)
+{
+  std::map<int, std::vector<int> >::const_iterator itbTransMap = transformationMapping_.begin(),
+                                                   itTransMap = itbTransMap,
+                                                   iteTransMap = transformationMapping_.end();
+  std::vector<int>::const_iterator itbVec, itVec, iteVec;
+  std::vector<CArray<size_t,1> > globalIndexSrcGrid((itTransMap->second).size());
+  CArray<size_t,1> globalIndexDestGrid;
+
+  for (itTransMap = itbTransMap; itTransMap != iteTransMap; ++itTransMap)
+  {
+    this->computeGlobalIndexFromGlobalIndexElement(itTransMap->first,
+                                                   itTransMap->second,
+                                                   elementPositionInGrid,
+                                                   gridDestGlobalDim,
+                                                   globalIndexGridDestSendToServer,
+                                                   globalIndexDestGrid,
+                                                   globalIndexSrcGrid);
+    size_t globalIndexSize = globalIndexDestGrid.numElements();
+    for (size_t idx = 0; idx < globalIndexSize; ++idx)
+    {
+      for (int i = 0; i < globalIndexSrcGrid.size(); ++i)
+      {
+        globaIndexMapFromDestToSource[globalIndexDestGrid(idx)].insert(globalIndexSrcGrid[i](idx));
+      }
+    }
+  }
+}
+
+}
Index: XIOS/trunk/src/filter/generic_algorithm_transformation.hpp
===================================================================
--- XIOS/trunk/src/filter/generic_algorithm_transformation.hpp	(revision 620)
+++ XIOS/trunk/src/filter/generic_algorithm_transformation.hpp	(revision 620)
@@ -0,0 +1,50 @@
+#ifndef __XIOS_GENERIC_ALGORITHM_TRANSFORMATION_HPP__
+#define __XIOS_GENERIC_ALGORITHM_TRANSFORMATION_HPP__
+
+#include <map>
+#include <vector>
+#include "array_new.hpp"
+
+namespace xios {
+
+class CGenericAlgorithmTransformation
+{
+public:
+  CGenericAlgorithmTransformation();
+
+  virtual ~CGenericAlgorithmTransformation() {}
+
+  void computeGlobalSourceIndex(int elementPositionInGrid,
+                                const std::vector<int>& gridDestGlobalDim,
+                                const CArray<size_t,1>& globalIndexGridDestSendToServer,
+                                std::map<size_t, std::set<size_t> >& globaIndexMapFromDestToSource);
+protected:
+  /*!
+  Compute an array of global index from a global index on an element
+    \param[in] destGlobalIndex global index on an element of destination grid
+    \param[in] srcGlobalIndex global index(es) on an element of source grid (which are needed by one index on element destination)
+    \param[in] elementPositionInGrid position of the element in the grid (for example: a grid with one domain and one axis, position of domain is 1, position of axis is 2)
+    \param[in] gridDestGlobalDim dimension size of destination grid (it should share the same size for all dimension, maybe except the element on which transformation is performed)
+    \param[in] globalIndexGridDestSendToServer global index of destination grid which are to be sent to server(s)
+    \param[in/out] globalIndexDestGrid array of global index (for 2d grid, this array maybe a line, for 3d, this array may represent a plan). It should be preallocated
+    \param[in/out] globalIndexSrcGrid array of global index of source grid (for 2d grid, this array is a line, for 3d, this array represents a plan). It should be preallocated
+  */
+  virtual void computeGlobalIndexFromGlobalIndexElement(int destGlobalIndex,
+                                                        const std::vector<int>& srcGlobalIndex,
+                                                        int elementPositionInGrid,
+                                                        const std::vector<int>& gridDestGlobalDim,
+                                                        const CArray<size_t,1>& globalIndexGridDestSendToServer,
+                                                        CArray<size_t,1>& globalIndexDestGrid,
+                                                        std::vector<CArray<size_t,1> >& globalIndexSrcGrid) = 0;
+
+  /*!
+  Compute global index mapping from one element of destination grid to the corresponding element of source grid
+  */
+  virtual void computeIndexSourceMapping() = 0;
+
+protected:
+  std::map<int, std::vector<int> > transformationMapping_;
+};
+
+}
+#endif // __XIOS_GENERIC_ALGORITHM_TRANSFORMATION_HPP__
Index: XIOS/trunk/src/filter/generic_filter.cpp
===================================================================
--- XIOS/trunk/src/filter/generic_filter.cpp	(revision 619)
+++ 	(revision )
@@ -1,41 +1,0 @@
-#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)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#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/grid_transformation.cpp
===================================================================
--- XIOS/trunk/src/filter/grid_transformation.cpp	(revision 620)
+++ XIOS/trunk/src/filter/grid_transformation.cpp	(revision 620)
@@ -0,0 +1,208 @@
+#include "grid_transformation.hpp"
+#include "axis_inverse.hpp"
+#include "transformation_mapping.hpp"
+
+namespace xios {
+CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)
+: gridSource_(source), gridDestination_(destination)
+{
+  //Verify the compatibity between two grids
+  int numElement = gridDestination_->axis_domain_order.numElements();
+  if (numElement != gridSource_->axis_domain_order.numElements())
+    ERROR("CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)",
+       << "Two grids have different number of elements"
+       << "Number of elements of grid source " <<gridSource_->getId() << " is " << gridSource_->axis_domain_order.numElements()  << std::endl
+       << "Number of elements of grid destination " <<gridDestination_->getId() << " is " << numElement);
+
+  for (int i = 0; i < numElement; ++i)
+  {
+    if (gridDestination_->axis_domain_order(i) != gridSource_->axis_domain_order(i))
+      ERROR("CGridTransformation::CGridTransformation(CGrid* destination, CGrid* source)",
+         << "Transformed grid and its grid source have incompatible elements"
+         << "Grid source " <<gridSource_->getId() << std::endl
+         << "Grid destination " <<gridDestination_->getId());
+  }
+
+  gridSourceDimensionSize_ = gridSource_->getGlobalDimension();
+  gridDestinationDimensionSize_ = gridDestination_->getGlobalDimension();
+  initializeAlgorithms();
+}
+
+CGridTransformation::~CGridTransformation()
+{
+  std::map<int, std::vector<CGenericAlgorithmTransformation*> >::const_iterator itb = algoTransformation_.begin(), it,
+                                                                                ite = algoTransformation_.end();
+  for (it = itb; it != ite; ++it)
+    for (int idx = 0; idx < (it->second).size(); ++idx)
+      delete (it->second)[idx];
+
+  std::map<int, std::vector<CArray<int,1>* > >::const_iterator itMapRecv, iteMapRecv;
+  itMapRecv = localIndexToReceiveOnGridDest_.begin();
+  iteMapRecv = localIndexToReceiveOnGridDest_.end();
+  for (; itMapRecv != iteMapRecv; ++itMapRecv)
+  {
+    int numVec = (itMapRecv->second).size();
+    for (int idx = 0; idx < numVec; ++idx) delete (itMapRecv->second)[idx];
+  }
+
+  std::map<int, CArray<int,1>* >::const_iterator itMap, iteMap;
+  itMap = localIndexToSendFromGridSource_.begin();
+  iteMap = localIndexToSendFromGridSource_.end();
+  for (; itMap != iteMap; ++itMap) delete (itMap->second);
+}
+
+void CGridTransformation::initializeAlgorithms()
+{
+  initializeAxisAlgorithms();
+  initializeDomainAlgorithms();
+}
+
+/*!
+  Initialize the algorithms corresponding to transformation info contained in each axis.
+If an axis has transformations, these transformations will be represented in form of vector of CTransformation pointers
+In general, each axis can have several transformations performed on itself. However, should they be done seperately or combinely (of course in order)?
+For now, one approach is to do these combinely but maybe this needs changing.
+*/
+void CGridTransformation::initializeAxisAlgorithms()
+{
+  std::vector<int> axisPositionInGrid;
+  std::vector<CAxis*> axisListDestP = gridDestination_->getAxis();
+  std::vector<CAxis*> axisListSrcP = gridSource_->getAxis();
+  if (!axisListDestP.empty())
+  {
+    int idx = 0;
+    for (int i = 0; i < gridDestination_->axis_domain_order.numElements(); ++i)
+    {
+      if (false == (gridDestination_->axis_domain_order)(i))
+      {
+        axisPositionInGrid.push_back(idx);
+        ++idx;
+      }
+      else idx += 2;
+    }
+
+    for (int i = 0; i < axisListDestP.size(); ++i)
+    {
+      if (axisListDestP[i]->hasTransformation())
+      {
+        CGenericAlgorithmTransformation* algo = new CAxisInverse(axisListDestP[i], axisListSrcP[i]);
+        algoTransformation_[axisPositionInGrid[i]].push_back(algo);
+      }
+    }
+  }
+}
+
+void CGridTransformation::initializeDomainAlgorithms()
+{
+
+}
+
+void CGridTransformation::computeTransformation()
+{
+  const CArray<size_t,1>& globalIndexGridDestSendToServer = gridDestination_->getDistributionClient()->getGlobalDataIndexSendToServer();
+  std::map<int, std::vector<CGenericAlgorithmTransformation*> >::const_iterator itbMap, itMap, iteMap;
+  itbMap = algoTransformation_.begin();
+  iteMap = algoTransformation_.end();
+
+  std::vector<CGenericAlgorithmTransformation*>::const_iterator itbVec, itVec, iteVec;
+
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    int elementPosition = itMap->first;
+    itbVec = (itMap->second).begin();
+    iteVec = (itMap->second).end();
+    for (itVec = itbVec; itVec != iteVec; ++itVec)
+    {
+      (*itVec)->computeGlobalSourceIndex(elementPosition,
+                                         gridDestinationDimensionSize_,
+                                         globalIndexGridDestSendToServer,
+                                         globaIndexMapFromDestToSource_);
+    }
+  }
+}
+
+void CGridTransformation::computeTransformationMapping()
+{
+  CTransformationMapping transformationMap(gridDestination_, gridSource_);
+
+  // First of all, need to compute global index mapping representing transformation algorithms
+  computeTransformation();
+
+  // Then compute transformation mapping among clients
+  transformationMap.computeTransformationMapping(globaIndexMapFromDestToSource_);
+
+  const std::map<int,std::vector<std::vector<size_t> > >& globalIndexToReceive = transformationMap.getGlobalIndexReceivedOnGridDestMapping();
+  const std::map<int,std::vector<size_t> >& globalIndexToSend = transformationMap.getGlobalIndexSendToGridDestMapping();
+
+  CArray<int, 1> localIndexOnClientDest = gridDestination_->getDistributionClient()->getLocalDataIndexOnClient();
+  CArray<size_t,1> globalIndexOnClientDest = gridDestination_->getDistributionClient()->getGlobalDataIndexSendToServer();
+
+  CArray<int, 1> localIndexOnClientSrc = gridSource_->getDistributionClient()->getLocalDataIndexOnClient();
+  CArray<size_t,1> globalIndexOnClientSrc = gridSource_->getDistributionClient()->getGlobalDataIndexSendToServer();
+
+
+  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
+  CArray<size_t, 1>::iterator itbArr, itArr, iteArr;
+
+  std::map<int,std::vector<std::vector<size_t> > >::const_iterator itbMapRecv, itMapRecv, iteMapRecv;
+  // Find out local index on grid destination (received)
+  itbMapRecv = globalIndexToReceive.begin();
+  iteMapRecv = globalIndexToReceive.end();
+  itbArr = globalIndexOnClientDest.begin();
+  iteArr = globalIndexOnClientDest.end();
+  for (itMapRecv = itbMapRecv; itMapRecv != iteMapRecv; ++itMapRecv)
+  {
+    int sourceRank = itMapRecv->first;
+    int numGlobalIndex = (itMapRecv->second).size();
+    for (int i = 0; i < numGlobalIndex; ++i)
+    {
+      int vecSize = ((itMapRecv->second)[i]).size();
+      CArray<int,1>* ptr = new CArray<int,1>(vecSize);
+      localIndexToReceiveOnGridDest_[sourceRank].push_back(ptr);
+      for (int idx = 0; idx < vecSize; ++idx)
+      {
+        itArr = std::find(itbArr, iteArr, (itMapRecv->second)[i][idx]);
+        if (iteArr != itArr)
+        {
+          int localIdx = std::distance(itbArr, itArr);
+          (*localIndexToReceiveOnGridDest_[sourceRank][i])(idx) = localIndexOnClientDest(localIdx);
+        }
+      }
+    }
+
+  }
+
+  std::map<int,std::vector<size_t> >::const_iterator itbMap, itMap, iteMap;
+  // Find out local index on grid source (to send)
+  itbMap = globalIndexToSend.begin();
+  iteMap = globalIndexToSend.end();
+  itbArr = globalIndexOnClientSrc.begin();
+  iteArr = globalIndexOnClientSrc.end();
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    CArray<int,1>* ptr = new CArray<int,1>((itMap->second).size());
+    localIndexToSendFromGridSource_[itMap->first] = ptr;
+    int vecSize = (itMap->second).size();
+    for (int idx = 0; idx < vecSize; ++idx)
+    {
+      itArr = std::find(itbArr, iteArr, (itMap->second)[idx]);
+      if (iteArr != itArr)
+      {
+        int localIdx = std::distance(itbArr, itArr);
+        (*localIndexToSendFromGridSource_[itMap->first])(idx) = localIndexOnClientSrc(localIdx);
+      }
+    }
+  }
+}
+
+std::map<int, CArray<int,1>* > CGridTransformation::getLocalIndexToSendFromGridSource()
+{
+  return localIndexToSendFromGridSource_;
+}
+
+std::map<int, std::vector<CArray<int,1>* > > CGridTransformation::getLocalIndexToReceiveOnGridDest()
+{
+  return localIndexToReceiveOnGridDest_;
+}
+
+}
Index: XIOS/trunk/src/filter/grid_transformation.hpp
===================================================================
--- XIOS/trunk/src/filter/grid_transformation.hpp	(revision 620)
+++ XIOS/trunk/src/filter/grid_transformation.hpp	(revision 620)
@@ -0,0 +1,46 @@
+#ifndef __XIOS_GRID_TRANSFORMATION_HPP__
+#define __XIOS_GRID_TRANSFORMATION_HPP__
+
+#include <map>
+#include <vector>
+#include "grid.hpp"
+#include "generic_algorithm_transformation.hpp"
+
+namespace xios {
+
+class CGrid;
+
+class CGridTransformation
+{
+public:
+  /** Default constructor */
+  CGridTransformation(CGrid* destination, CGrid* source);
+  ~CGridTransformation();
+
+  void computeTransformationMapping();
+  std::map<int, CArray<int,1>* > getLocalIndexToSendFromGridSource();
+  std::map<int, std::vector<CArray<int,1>* > > getLocalIndexToReceiveOnGridDest();
+
+private:
+  void computeTransformation();
+  void initializeAlgorithms();
+  void initializeAxisAlgorithms();
+  void initializeDomainAlgorithms();
+
+private:
+  CGrid* gridSource_;
+  CGrid* gridDestination_;
+
+  std::vector<int> gridSourceDimensionSize_;
+  std::vector<int> gridDestinationDimensionSize_;
+
+  // Mapping between position of an element in grid and its transformation (if any)
+  std::map<int, std::vector<CGenericAlgorithmTransformation*> > algoTransformation_;
+  std::map<size_t, std::set<size_t> > globaIndexMapFromDestToSource_;
+
+  std::map<int, CArray<int,1>* > localIndexToSendFromGridSource_;
+  std::map<int, std::vector<CArray<int,1>* > > localIndexToReceiveOnGridDest_;
+};
+
+}
+#endif // __XIOS_GRID_TRANSFORMATION_HPP__
Index: XIOS/trunk/src/filter/invert_algorithm.cpp
===================================================================
--- XIOS/trunk/src/filter/invert_algorithm.cpp	(revision 619)
+++ 	(revision )
@@ -1,299 +1,0 @@
-#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)
+++ 	(revision )
@@ -1,31 +1,0 @@
-#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/transformation_mapping.cpp
===================================================================
--- XIOS/trunk/src/filter/transformation_mapping.cpp	(revision 620)
+++ XIOS/trunk/src/filter/transformation_mapping.cpp	(revision 620)
@@ -0,0 +1,160 @@
+#include "transformation_mapping.hpp"
+#include <boost/unordered_map.hpp>
+#include "context.hpp"
+#include "context_client.hpp"
+
+namespace xios {
+
+CTransformationMapping::CTransformationMapping(CGrid* destination, CGrid* source)
+  : gridSource_(source), gridDestination_(destination)
+{
+  CContext* context = CContext::getCurrent();
+  CContextClient* client=context->client;
+  int clientRank = client->clientRank;
+
+  const CArray<size_t,1>& globalIndexGridSrc = gridSource_->getDistributionClient()->getGlobalDataIndexSendToServer();
+  boost::unordered_map<size_t,int> globalIndexOfServer;
+  int globalIndexSize = globalIndexGridSrc.numElements();
+  for (int idx = 0; idx < globalIndexSize; ++idx)
+  {
+    globalIndexOfServer[globalIndexGridSrc(idx)] = clientRank;
+  }
+
+  gridIndexClientClientMapping_ = new CClientServerMappingDistributed(globalIndexOfServer,
+                                                                      client->intraComm,
+                                                                      true);
+}
+
+CTransformationMapping::~CTransformationMapping()
+{
+  if (0 != gridIndexClientClientMapping_) delete gridIndexClientClientMapping_;
+}
+
+/*!
+  Suppose that we have transformations between two grids, which are represented in form of mapping between global indexes of these two grids,
+this function tries to find out which clients a client need to send and receive these global indexes to accomplish the transformations.
+  The grid destination is the grid whose global indexes demande global indexes from the grid source
+  Grid destination and grid source are also distributed among clients but in a different manner.
+  \param [in] globaIndexMapFromDestToSource mapping representing the transformations
+*/
+void CTransformationMapping::computeTransformationMapping(const std::map<size_t, std::set<size_t> >& globaIndexMapFromDestToSource)
+{
+  CContext* context = CContext::getCurrent();
+  CContextClient* client=context->client;
+
+  int numMappingPoints = 0;
+  std::map<size_t, std::set<size_t> >::const_iterator itbMap = globaIndexMapFromDestToSource.begin(), itMap,
+                                                      iteMap = globaIndexMapFromDestToSource.end();
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    numMappingPoints += (itMap->second).size();
+  }
+
+  // All global indexes of a client on grid destination
+  CArray<size_t,1> globalIndexMap(numMappingPoints);
+  // Not only one index on grid destination can demande two indexes from grid source
+  // but an index on grid destination have to be sent to two indexes of grid destination
+  std::map<size_t, std::vector<size_t> > globalIndexMapFromSrcToDest;
+  std::set<size_t>::const_iterator itbSet, itSet, iteSet;
+  int idx = 0;
+  for (itMap = itbMap; itMap != iteMap; ++itMap)
+  {
+    itbSet = (itMap->second).begin();
+    iteSet = (itMap->second).end();
+    for (itSet = itbSet; itSet != iteSet; ++itSet)
+    {
+      globalIndexMap(idx) = *itSet;
+      globalIndexMapFromSrcToDest[*itSet].push_back(itMap->first);
+      ++idx;
+    }
+  }
+
+  // Find out on which clients the necessary indexes of grid source are.
+  gridIndexClientClientMapping_->computeServerIndexMapping(globalIndexMap);
+  const std::map<int, std::vector<size_t> >& globalIndexSentFromGridSource = gridIndexClientClientMapping_->getGlobalIndexOnServer();
+  std::map<int, std::vector<size_t> >::const_iterator itbMapSrc = globalIndexSentFromGridSource.begin(), itMapSrc,
+                                                      iteMapSrc = globalIndexSentFromGridSource.end();
+  std::vector<size_t>::const_iterator itbVec, itVec, iteVec;
+  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc)
+  {
+    int sourceRank = itMapSrc->first;
+    itbVec = (itMapSrc->second).begin();
+    iteVec = (itMapSrc->second).end();
+    for (itVec = itbVec; itVec != iteVec; ++itVec)
+    {
+       (globalIndexReceivedOnGridDestMapping_[sourceRank]).push_back(globalIndexMapFromSrcToDest[*itVec]);
+    }
+  }
+
+  // Inform client about the destination to which it needs to send global indexes
+  int nbClient = client->clientSize;
+  int* sendBuff = new int[nbClient];
+  int* recvBuff = new int[nbClient];
+  for (int i = 0; i < nbClient; ++i) sendBuff[i] = 0;
+
+  // First of all, inform the number of destination a client needs to send global index
+  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc) sendBuff[itMapSrc->first] = 1;
+  MPI_Allreduce(sendBuff, recvBuff, nbClient, MPI_INT, MPI_SUM, client->intraComm);
+  int numClientToReceive = recvBuff[client->clientRank];
+
+  // Then specify the size of receiving buffer, because we use synch send/receive so only necessary to know maximum size
+  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc) sendBuff[itMapSrc->first] = (itMapSrc->second).size();
+  MPI_Allreduce(sendBuff, recvBuff, nbClient, MPI_INT, MPI_MAX, client->intraComm);
+
+  int buffSize = recvBuff[client->clientRank];
+  unsigned long* recvBuffGlobalIndex;
+  if (0 != buffSize) recvBuffGlobalIndex = new unsigned long [buffSize];
+
+  // Inform all "source clients" about index that they need to send
+  for (itMapSrc = itbMapSrc; itMapSrc != iteMapSrc; ++itMapSrc)
+  {
+    MPI_Request request;
+    unsigned long* sendPtr = const_cast<unsigned long*>(&(itMapSrc->second)[0]);
+    MPI_Isend(sendPtr,
+              (itMapSrc->second).size(),
+              MPI_UNSIGNED_LONG,
+              itMapSrc->first,
+              11,
+              client->intraComm,
+              &request);
+  }
+
+  // Now all the "source clients" try listening messages from other "destination clients"
+  int numClientReceived = 0;  // number of client to which data has been already sent
+  int countBuff;
+  while (numClientReceived < numClientToReceive)
+  {
+    MPI_Status status;
+    MPI_Recv(recvBuffGlobalIndex,
+             buffSize,
+             MPI_UNSIGNED_LONG,
+             MPI_ANY_SOURCE,
+             11,
+             client->intraComm,
+             &status);
+
+    MPI_Get_count(&status, MPI_UNSIGNED_LONG, &countBuff);
+    int clientDestRank = status.MPI_SOURCE;
+    for (int idx = 0; idx < countBuff; ++idx)
+    {
+      globalIndexSendToGridDestMapping_[clientDestRank].push_back(recvBuffGlobalIndex[idx]);
+    }
+    ++numClientReceived;
+  }
+
+  delete [] sendBuff;
+  delete [] recvBuff;
+  if (0 != buffSize) delete [] recvBuffGlobalIndex;
+}
+
+const std::map<int,std::vector<std::vector<size_t> > >& CTransformationMapping::getGlobalIndexReceivedOnGridDestMapping() const
+{
+  return globalIndexReceivedOnGridDestMapping_;
+}
+
+const std::map<int,std::vector<size_t> >& CTransformationMapping::getGlobalIndexSendToGridDestMapping() const
+{
+  return globalIndexSendToGridDestMapping_;
+}
+
+}
Index: XIOS/trunk/src/filter/transformation_mapping.hpp
===================================================================
--- XIOS/trunk/src/filter/transformation_mapping.hpp	(revision 620)
+++ XIOS/trunk/src/filter/transformation_mapping.hpp	(revision 620)
@@ -0,0 +1,45 @@
+#ifndef __XIOS_TRANSFORMATION_MAPPING_HPP__
+#define __XIOS_TRANSFORMATION_MAPPING_HPP__
+
+#include <map>
+#include <set>
+#include "grid.hpp"
+#include "array_new.hpp"
+#include "client_server_mapping_distributed.hpp"
+
+namespace xios {
+
+/*!
+  \class CTransformationMapping
+  This class is in charge of transfer the global index form grid from grid source to grid destination in a rather generic way.
+In order to make a transformation, the grid destination will make a request to grid source about the global indexes which it needs.
+The same discovering algorithm as the case of client-server is applied to find the corresponding client which contains the demanding global index.
+*/
+class CTransformationMapping
+{
+public:
+  /** Default constructor */
+  CTransformationMapping(CGrid* destination, CGrid* source);
+  ~CTransformationMapping();
+
+  void computeTransformationMapping(const std::map<size_t, std::set<size_t> >& globaIndexMapFromDestToSource);
+  const std::map<int,std::vector<std::vector<size_t> > >& getGlobalIndexReceivedOnGridDestMapping() const;
+  const std::map<int,std::vector<size_t> >& getGlobalIndexSendToGridDestMapping() const;
+
+protected:
+  CGrid* gridSource_;  // Grid source
+  CGrid* gridDestination_; // Grid destination demande the necessary global index from grid source
+
+  //! Global index mapping of grid source and grid destination between two clients
+  CClientServerMappingDistributed* gridIndexClientClientMapping_;
+
+  //! Mapping of client rank of grid source and global index received in grid destination
+  std::map<int,std::vector<std::vector<size_t> > > globalIndexReceivedOnGridDestMapping_;
+
+  //! Mapping of client rank of grid destination and global index to send from grid source
+  std::map<int,std::vector<size_t> > globalIndexSendToGridDestMapping_;
+
+};
+
+}
+#endif // __XIOS_TRANSFORMATION_MAPPING_HPP__
Index: XIOS/trunk/src/filter/zoom_algorithm.cpp
===================================================================
--- XIOS/trunk/src/filter/zoom_algorithm.cpp	(revision 619)
+++ 	(revision )
@@ -1,14 +1,0 @@
-#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)
+++ 	(revision )
@@ -1,22 +1,0 @@
-#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__
