diff --git a/HySoP/hysop/mpi/topology.py b/HySoP/hysop/mpi/topology.py
index bc49433c9dfdea6ac31c4b4a9781501b0655a4c4..286a08c6d25b9ec334d4693f277c99e8aa11add8 100644
--- a/HySoP/hysop/mpi/topology.py
+++ b/HySoP/hysop/mpi/topology.py
@@ -799,13 +799,13 @@ class Bridge_intercomm(object):
                                                other_slices[other_rk, 0::2])
             intersect_slice[1::2] = np.minimum(my_slices[1::2],
                                                other_slices[other_rk, 1::2])
-            # Convert intersection to local slices
+            # Convert intersection to local slices, exluding ghosts
             if not (intersect_slice[0::2] > intersect_slice[1::2]).any():
                 # compatible intersection (else nothing to transfer)
                 self.transfers[other_rk] = [
-                    (i - s, j + 1 - s) for i, j, s in zip(
+                    (g + i - s, g + j + 1 - s) for i, j, s, g in zip(
                         intersect_slice[0::2],
-                        intersect_slice[1::2], my_start)]
+                        intersect_slice[1::2], my_start, self.topo.ghosts)]
 
     @debug
     def setUp(self):
diff --git a/HySoP/hysop/operator/monitors/compute_forces.py b/HySoP/hysop/operator/monitors/compute_forces.py
index 021e9ab10c734903dc22c4eceb2e728c83d1715e..d8d239a140a3c0f6c15a540d4ab5f755c0123c52 100644
--- a/HySoP/hysop/operator/monitors/compute_forces.py
+++ b/HySoP/hysop/operator/monitors/compute_forces.py
@@ -10,7 +10,7 @@ from parmepy.numerics.differential_operations import Laplacian,\
     DivStressTensor3D
 from parmepy.numerics.finite_differences import FD_C_2
 from parmepy.operator.monitors.monitoring import Monitoring
-from parmepy.mpi import main_comm, main_rank, MPI
+from parmepy.mpi import MPI
 from parmepy.tools.timers import timed_function
 import parmepy.tools.numpywrappers as npw
 import scitools.filetable as ft
@@ -326,7 +326,7 @@ class Forces(Monitoring):
     Compute the forces according the Noca s formula
     """
 
-    def __init__(self, velocity, vorticity, topo, 
+    def __init__(self, velocity, vorticity, topo,
                  obstacle, boxMin= None, boxMax=None, Reynolds=None,
                  uinf=1.0, method=FD_C_2, frequency=None, prefix=None):
         """
@@ -362,7 +362,7 @@ class Forces(Monitoring):
         self.output = []
         self.topo = self._predefinedTopo
 
-        # Compute coef used to determine drag coefficient : 
+        # Compute coef used to determine drag coefficient :
         # cD = coef.Fx = 2.Fx/rho.uinf**2.D
         self.bufferForce = 0.
         rho = 1.0
@@ -385,14 +385,14 @@ class Forces(Monitoring):
         self._synchronize = UpdateGhosts(self.topo,
                                          self.velocity.nbComponents)
 
-        # Function for the computation of div(T) where 
+        # Function for the computation of div(T) where
         # T is the stress tensor: T = Nabla(U) + Nabla(U)t
         self.divT = DivStressTensor3D(self.topo, method=self.method)
         self.fd_scheme = FD_C_2(self.topo.mesh.space_step)
 
         self._isUpToDate = True
 
-        if (main_rank == 0):
+        if (self.topo.comm.Get_rank() == 0):
             self.f = open(self.prefix, 'w')
 
     def compute_control_box(self, obst) :
@@ -470,14 +470,14 @@ class Forces(Monitoring):
             # there is no part of the volume control inside the local domain
                 self.isForceComputationNeeded = False
 
-#        print 'coord_start, coord_end', main_rank, self.coord_start, self.coord_end
-#        print 'distMin, distMax, step, res', main_rank, distMin, distMax, self.step, self.res
-#        print 'ind_bound_ChiX-', main_rank, ind_boundaries[0][0], coord_boundaries[0][0], self.coords[0][ind_boundaries[0][0], :, :]
-#        print 'ind_bound_ChiX+', main_rank, ind_boundaries[0][1], coord_boundaries[0][1], self.coords[0][ind_boundaries[0][1], :, :]
-#        print 'ind_bound_ChiY-', main_rank, ind_boundaries[1][0], coord_boundaries[1][0], self.coords[1][:, ind_boundaries[1][0], :]
-#        print 'ind_bound_ChiY+', main_rank, ind_boundaries[1][1], coord_boundaries[1][1], self.coords[1][:, ind_boundaries[1][1], :]
-#        print 'ind_bound_ChiZ-', main_rank, ind_boundaries[2][0], coord_boundaries[2][0], self.coords[2][:, :, ind_boundaries[2][0]]
-#        print 'ind_bound_ChiZ+', main_rank, ind_boundaries[2][1], coord_boundaries[2][1], self.coords[2][:, :, ind_boundaries[2][1]]
+#        print 'coord_start, coord_end', self.topo.comm.Get_rank(), self.coord_start, self.coord_end
+#        print 'distMin, distMax, step, res', self.topo.comm.Get_rank(), distMin, distMax, self.step, self.res
+#        print 'ind_bound_ChiX-', self.topo.comm.Get_rank(), ind_boundaries[0][0], coord_boundaries[0][0], self.coords[0][ind_boundaries[0][0], :, :]
+#        print 'ind_bound_ChiX+', self.topo.comm.Get_rank(), ind_boundaries[0][1], coord_boundaries[0][1], self.coords[0][ind_boundaries[0][1], :, :]
+#        print 'ind_bound_ChiY-', self.topo.comm.Get_rank(), ind_boundaries[1][0], coord_boundaries[1][0], self.coords[1][:, ind_boundaries[1][0], :]
+#        print 'ind_bound_ChiY+', self.topo.comm.Get_rank(), ind_boundaries[1][1], coord_boundaries[1][1], self.coords[1][:, ind_boundaries[1][1], :]
+#        print 'ind_bound_ChiZ-', self.topo.comm.Get_rank(), ind_boundaries[2][0], coord_boundaries[2][0], self.coords[2][:, :, ind_boundaries[2][0]]
+#        print 'ind_bound_ChiZ+', self.topo.comm.Get_rank(), ind_boundaries[2][1], coord_boundaries[2][1], self.coords[2][:, :, ind_boundaries[2][1]]
 
         # definition of the indicator functions of box boundaries
         self.chi_x_minus = [slice(ind_boundaries[0][0], ind_boundaries[0][0] +1),
@@ -570,9 +570,9 @@ class Forces(Monitoring):
             localForce = self.integrateOnBox(localForce, vort, self.chi_box, dt)
 
             # Reduction operation
-            if main_rank == 0:
+            if self.topo.comm.Get_rank() == 0:
                 comm = self.topo.comm
-                comm.Reduce([localForce, MPI.DOUBLE], [force, MPI.DOUBLE], 
+                comm.Reduce([localForce, MPI.DOUBLE], [force, MPI.DOUBLE],
                             op=MPI.SUM, root=0)
                 force = force * self.coef
                 # Print drag, lift and side force coefficients in output file
@@ -616,10 +616,10 @@ class Forces(Monitoring):
     ## WARNING : this routine is available inly if velo and vort
     ## topologies have the same global mesh resolution !!!
         """
-        Compute integrals on surface normal to "direc" axis to calculate forces 
+        Compute integrals on surface normal to "direc" axis to calculate forces
         acting on the body. See (2.1) of Noca 1999 or (52) of Plouhmans 2002.
         Returns \f$ \int_{S}\mathbf{n}\cdot\gamma\, dS \f$, where
-        \f$ \mathbf{n}\cdot\gamma = [(\frac{1}{2} (\mathbf{u}\cdot\mathbf{u})\mathbf{n} - 
+        \f$ \mathbf{n}\cdot\gamma = [(\frac{1}{2} (\mathbf{u}\cdot\mathbf{u})\mathbf{n} -
         (\mathbf{n}\cdot\mathbf{u})\mathbf{u}) -
         \frac{1}{N-1}(\mathbf{n}\cdot\mathbf{u})(\mathbf{x}\wedge\mathbf{\omega}) +
         \frac{1}{N-1}(\mathbf{n}\cdot\mathbf{\omega})(\mathbf{x}\wedge\mathbf{u})] +
@@ -648,8 +648,8 @@ class Forces(Monitoring):
             self.n_T = self.part3_Zdir
 
         # ====================== part 1 =======================
-        # part 1 = 1/2(velocity.velocity)n - 
-        # (n.velocity)velocity - 
+        # part 1 = 1/2(velocity.velocity)n -
+        # (n.velocity)velocity -
         # 1/(dim-1)(n.velocity)(coord X vorticity) +
         # 1/(dim-1)(n.vorticity)(coord X velocity)
 
@@ -814,8 +814,3 @@ class Forces(Monitoring):
     def __str__(self):
         s = "Compute_forces. "
         return s
-
-if __name__ == "__main__":
-    print __doc__
-    print "- Provided class : Compute_forces"
-    print Compute_forces.__doc__
diff --git a/HySoP/hysop/operator/redistribute.py b/HySoP/hysop/operator/redistribute.py
index 211dfd4363883cd1d3bd684751e6e6a6bbc27f18..52ed863cd7a32017fe235db216637e1b4ecfc968 100644
--- a/HySoP/hysop/operator/redistribute.py
+++ b/HySoP/hysop/operator/redistribute.py
@@ -20,7 +20,7 @@ a variable defined on several meshes.
 
 """
 from parmepy import __VERBOSE__
-from parmepy.constants import debug, PARMES_MPI_REAL, ORDERMPI, np
+from parmepy.constants import debug, PARMES_MPI_REAL, ORDERMPI, np, S_DIR
 from parmepy.operator.continuous import Operator
 from parmepy.mpi.topology import Bridge
 from parmepy.mpi import main_rank, main_comm
@@ -80,6 +80,13 @@ class Redistribute(Operator):
         else:
             # Only the given component is considered
             self._range_components = lambda v: [component]
+        self.r_request = {}
+        self.s_request = {}
+        self._r_types = {}
+        self._s_types = {}
+        for v in self.variables:
+            self._r_types[v] = {}
+            self._s_types[v] = {}
 
     def discretize(self):
         pass
@@ -173,6 +180,37 @@ class Redistribute(Operator):
                 len(self.bridges[v].recvFrom.keys()) == 0 and \
                 len(self.bridges[v].sendTo.keys()) == 0
 
+        # Build MPI subarrays
+        dim = self.domain.dimension
+        for v in self.variables:
+            br = self.bridges[v]
+            vTo = self.opTo.discreteFields[v].data[0]
+            vFrom = self.opFrom.discreteFields[v].data[0]
+            for rk in br.recvFrom.keys():
+                subvshape = tuple([br.recvFrom[rk][i].stop -
+                                   br.recvFrom[rk][i].start
+                                   for i in range(dim)])
+                substart = tuple([br.recvFrom[rk][i].start
+                                  for i in range(dim)])
+                self._r_types[v][rk] = \
+                    PARMES_MPI_REAL.Create_subarray(vTo.shape,
+                                                    subvshape,
+                                                    substart,
+                                                    order=ORDERMPI)
+                self._r_types[v][rk].Commit()
+            for rk in br.sendTo.keys():
+                subvshape = tuple([br.sendTo[rk][i].stop -
+                                   br.sendTo[rk][i].start
+                                   for i in range(dim)])
+                substart = tuple([br.sendTo[rk][i].start
+                                  for i in range(dim)])
+                self._s_types[v][rk] = \
+                    PARMES_MPI_REAL.Create_subarray(vFrom.shape,
+                                                    subvshape,
+                                                    substart,
+                                                    order=ORDERMPI)
+                self._s_types[v][rk].Commit()
+
         self._isUpToDate = True
 
     def _apply_toHost_bridges_toDevice(self, simulation=None):
@@ -229,8 +267,7 @@ class Redistribute(Operator):
         # (use buffers for mpi send/recv? )
         # - move MPI datatypes into the bridge? --> and free MPI type properly
         if __VERBOSE__:
-            print "{"+str(main_rank)+"}", "_apply_bridges"
-        dim = self.domain.dimension
+            print "{" + str(main_rank) + "}", "_apply_bridges"
         self.r_request = {}
         self.s_request = {}
         for v in self.variables:
@@ -238,48 +275,24 @@ class Redistribute(Operator):
             # Apply for each component considered
             for d in self._range_components(v):
                 if __VERBOSE__:
-                    print "{"+str(main_rank)+"}", "_apply_bridges", \
+                    print "{" + str(main_rank) + "}", "_apply_bridges", \
                         self.opFrom.discreteFields[v].name, '->', \
                         self.opTo.discreteFields[v].name
                 vTo = self.opTo.discreteFields[v].data[d]
                 vFrom = self.opFrom.discreteFields[v].data[d]
-                v_name = self.opTo.discreteFields[v].name
+                v_name = self.opFrom.discreteFields[v].name + S_DIR[d]
                 if br.hasLocalInter:
                     vTo[br.ito] = vFrom[br.ifrom]
 
                 for rk in br.recvFrom.keys():
-                    ind = v_name + str(rk) + '-' + str(d)
-                    subvshape = tuple([br.recvFrom[rk][i].stop -
-                                       br.recvFrom[rk][i].start
-                                       for i in range(dim)])
-                    substart = tuple([br.recvFrom[rk][i].start
-                                      for i in range(dim)])
-                    recvTYPE = PARMES_MPI_REAL.Create_subarray(vTo.shape,
-                                                               subvshape,
-                                                               substart,
-                                                               order=ORDERMPI)
-                    recvTYPE.Commit()
-                    self.r_request[ind] = main_comm.Irecv([vTo, 1,
-                                                           recvTYPE],
-                                                          source=rk,
-                                                          tag=rk)
+                    self.r_request[v_name + str(rk)] = \
+                        main_comm.Irecv([vTo, 1, self._r_types[v][rk]],
+                                        source=rk, tag=rk)
                     self._hasRequests = True
                 for rk in br.sendTo.keys():
-                    ind = v_name + str(rk) + '-' + str(d)
-                    subvshape = tuple([br.sendTo[rk][i].stop -
-                                       br.sendTo[rk][i].start
-                                       for i in range(dim)])
-                    substart = tuple([br.sendTo[rk][i].start
-                                      for i in range(dim)])
-                    sendTYPE = PARMES_MPI_REAL.Create_subarray(vFrom.shape,
-                                                               subvshape,
-                                                               substart,
-                                                               order=ORDERMPI)
-                    sendTYPE.Commit()
-                    self.s_request[ind] = main_comm.Issend([vFrom, 1,
-                                                            sendTYPE],
-                                                           dest=rk,
-                                                           tag=main_rank)
+                    self.s_request[v_name + str(rk)] = \
+                        main_comm.Issend([vFrom, 1, self._s_types[v][rk]],
+                                         dest=rk, tag=main_rank)
                     self._hasRequests = True
 
     def _wait_host(self):
@@ -288,7 +301,7 @@ class Redistribute(Operator):
         of all communication requests.
         """
         if __VERBOSE__:
-            print "{"+str(main_rank)+"}", "WAITING MPI", self._hasRequests
+            print "{" + str(main_rank) + "}", "WAITING MPI", self._hasRequests
         if self._hasRequests:
             for rk in self.r_request.keys():
                 self.r_request[rk].Wait()
@@ -298,7 +311,7 @@ class Redistribute(Operator):
 
     def _wait_device(self):
         if __VERBOSE__:
-            print "{"+str(main_rank)+"}", "WAITING OPENCL"
+            print "{" + str(main_rank) + "}", "WAITING OPENCL"
         for dv in self._toDevice_fields + self._toHost_fields:
             dv.wait()
 
@@ -313,11 +326,11 @@ class Redistribute(Operator):
         else check for sending to rsend or
         receiving from rrecv. Process ranks
         should be given in main_comm.
-        @param rsend : rank of the process
+        @param rsend : discrete variable name + S_DIR + rank of the process
         to which a message has been sent
         and for which we want to test
         message completion.
-        @param  rrecv : rank of the process
+        @param  rrecv : discrete variable name + S_DIR + rank of the process
         from which a message has been receive
         and for which we want to test
         message completion.
diff --git a/HySoP/hysop/operator/redistribute_intercomm.py b/HySoP/hysop/operator/redistribute_intercomm.py
index 9da815298b883ced57298e6337a056d98ade3b49..a4119ccd8bdc1d201b502a2db11890655feb0226 100644
--- a/HySoP/hysop/operator/redistribute_intercomm.py
+++ b/HySoP/hysop/operator/redistribute_intercomm.py
@@ -7,7 +7,7 @@ the destination.
 
 It relies on a Bridge_intercomm.
 """
-from parmepy.constants import debug, PARMES_MPI_REAL, ORDERMPI
+from parmepy.constants import debug, PARMES_MPI_REAL, ORDERMPI, S_DIR
 from parmepy.operator.continuous import Operator
 from parmepy.mpi.topology import Bridge_intercomm
 
@@ -58,9 +58,18 @@ class RedistributeIntercomm(Operator):
             # Only the given component is considered
             self._range_components = lambda v: [component]
 
+        self._parent_rank = self.parent_comm.Get_rank()
+        self._my_rank = self.topo.comm.Get_rank()
+        self._dim = self.topo.domain.dimension
+
         self.bridges = {}
         self.r_request = {}
         self.s_request = {}
+        self._r_types = {}
+        self._s_types = {}
+        for v in self.variables:
+            self._r_types[v] = {}
+            self._s_types[v] = {}
 
     def discretize(self):
         pass
@@ -78,54 +87,102 @@ class RedistributeIntercomm(Operator):
                                        self.id_from, self.id_to,
                                        self.proc_tasks)
 
+        for v in self.variables:
+            dv = v.discreteFields[self.topo]
+            transfers = self.bridge.transfers
+            # Set reception
+            if self.proc_tasks[self._parent_rank] == self.id_to:
+                for from_rk in transfers.keys():
+                    subshape = tuple(
+                        [transfers[from_rk][i][1] - transfers[from_rk][i][0]
+                         for i in range(self._dim)])
+                    substart = tuple(
+                        [transfers[from_rk][i][0] for i in range(self._dim)])
+                    self._r_types[v][from_rk] = \
+                        PARMES_MPI_REAL.Create_subarray(dv[0].shape,
+                                                        subshape,
+                                                        substart,
+                                                        order=ORDERMPI)
+                    self._r_types[v][from_rk].Commit()
+            # Set Sending
+            if self.proc_tasks[self._parent_rank] == self.id_from:
+                for to_rk in transfers.keys():
+                    subshape = tuple(
+                        [transfers[to_rk][i][1] - transfers[to_rk][i][0]
+                         for i in range(self._dim)])
+                    substart = tuple(
+                        [transfers[to_rk][i][0] for i in range(self._dim)])
+                    self._r_types[v][to_rk] = \
+                        PARMES_MPI_REAL.Create_subarray(dv[0].shape,
+                                                        subshape,
+                                                        substart,
+                                                        order=ORDERMPI)
+                    self._r_types[v][to_rk].Commit()
+
     def apply(self, simulation=None):
         """
         Proceed with data redistribution from opFrom to opTo
         """
-        self.r_request = {}
-        self.s_request = {}
-        parent_rank = self.parent_comm.Get_rank()
-        my_rank = self.topo.comm.Get_rank()
-        dim = self.topo.domain.dimension
         self.parent_comm.Barrier()
 
+        self.r_request = {}
+        self.s_request = {}
         for v in self.variables:
             dv = v.discreteFields[self.topo]
             transfers = self.bridge.transfers
             for d in self._range_components(v):
+                v_name = dv.name + S_DIR[d]
                 # Set reception
-                if self.proc_tasks[parent_rank] == self.id_to:
+                if self.proc_tasks[self._parent_rank] == self.id_to:
                     for from_rk in transfers.keys():
-                        subshape = tuple([
-                                transfers[from_rk][i][1] -
-                                transfers[from_rk][i][0] for i in range(dim)])
-                        substart = tuple([
-                                transfers[from_rk][i][0] for i in range(dim)])
-                        recv_type = PARMES_MPI_REAL.Create_subarray(
-                            dv[d].shape, subshape, substart, order=ORDERMPI)
-                        recv_type.Commit()
-                        ind = str(from_rk) + '->' + str(my_rank)
-                        self.r_request[ind] = self.bridge.inter_comm.Irecv(
-                            [dv[d], 1, recv_type], source=from_rk, tag=from_rk)
+                        self.r_request[v_name + str(from_rk)] = \
+                            self.bridge.inter_comm.Irecv(
+                                [dv[d], 1, self._r_types[v][from_rk]],
+                                source=from_rk, tag=from_rk)
                 # Set Sending
-                if self.proc_tasks[parent_rank] == self.id_from:
+                if self.proc_tasks[self._parent_rank] == self.id_from:
                     for to_rk in transfers.keys():
-                        subshape = tuple([
-                                transfers[to_rk][i][1] -
-                                transfers[to_rk][i][0] for i in range(dim)])
-                        substart = tuple([
-                                transfers[to_rk][i][0] for i in range(dim)])
-                        send_type = PARMES_MPI_REAL.Create_subarray(
-                            dv[d].shape, subshape, substart, order=ORDERMPI)
-                        send_type.Commit()
-                        ind = str(my_rank) + '->' + str(to_rk)
-                        self.s_request[ind] = self.bridge.inter_comm.Isend(
-                            [dv[d], 1, send_type], dest=to_rk, tag=my_rank)
+                        self.s_request[v_name + str(to_rk)] = \
+                            self.bridge.inter_comm.Issend(
+                                [dv[d], 1, self._r_types[v][to_rk]],
+                                dest=to_rk, tag=self._my_rank)
 
     def wait(self, simulation=None):
         """Wait for requests completion."""
-        for rk in self.r_request.keys():
+        for rk in self.r_request:
             self.r_request[rk].Wait()
-        for rk in self.s_request.keys():
+        for rk in self.s_request:
             self.s_request[rk].Wait()
         self.parent_comm.Barrier()
+        self.r_request = []
+        self.s_request = []
+
+    def test(self, rsend=None, rrecv=None):
+        """
+        if neither rsend or rrecv is given return
+        True if all communication request are complete
+        else check for sending to rsend or
+        receiving from rrecv. Process ranks
+        should be given in local communicator.
+        @param rsend : variable name + S_DIR + rank
+        @param rrecv : variable name + S_DIR + rank
+        """
+        if(rsend is not None or rrecv is not None):
+            send_res = True
+            recv_res = True
+            if rsend is not None:
+                send_res = self.s_request[rsend].Test()
+            if rrecv is not None:
+                recv_res = self.r_request[rrecv].Test()
+            res = send_res and recv_res
+        else:
+            res = True
+            for rk in self.r_request.keys():
+                res = self.r_request[rk].Test()
+                if not res:
+                    return res
+            for rk in self.s_request.keys():
+                res = self.s_request[rk].Test()
+                if not res:
+                    return res
+        return res
diff --git a/HySoP/hysop/operator/reprojection.py b/HySoP/hysop/operator/reprojection.py
index c6d0f53552b7cfd183e40fed63e33439976f7cfe..51f6085a3731dc9d68d97d94c3900a356fd86f6d 100644
--- a/HySoP/hysop/operator/reprojection.py
+++ b/HySoP/hysop/operator/reprojection.py
@@ -11,7 +11,7 @@ from parmepy.numerics.finite_differences import FD_C_4, FD_C_2
 from parmepy.numerics.differential_operations import GradV
 import parmepy.tools.numpywrappers as npw
 from parmepy.numerics.updateGhosts import UpdateGhosts
-from parmepy.mpi import main_rank, MPI
+from parmepy.mpi import main_rank, main_comm, main_size, MPI
 from parmepy.tools.timers import timed_function