diff --git a/HySoP/hysop/fields/continuous.py b/HySoP/hysop/fields/continuous.py
index 70c3c66b01d2011d4d01c9f1c8d561306b422941..33c8d421102aaa1085c741444381b9d38d6ab448 100644
--- a/HySoP/hysop/fields/continuous.py
+++ b/HySoP/hysop/fields/continuous.py
@@ -128,10 +128,10 @@ class Field(object):
         """
         if self.topoInit is None:
             self.discreteFields.values()[0].initialize(
-                self._formula,*(args + self.extraParameters))
+                self._formula, *(args + self.extraParameters))
         else:
             self.discreteFields[self.topoInit].initialize(
-                self._formula,*(args + self.extraParameters))
+                self._formula, *(args + self.extraParameters))
 
     def value(self, *pos):
         """
diff --git a/HySoP/hysop/numerics/differentialOperator.py b/HySoP/hysop/numerics/differentialOperator.py
deleted file mode 100755
index 7e377277eff801ff7e757265342eeb24d21e31d6..0000000000000000000000000000000000000000
--- a/HySoP/hysop/numerics/differentialOperator.py
+++ /dev/null
@@ -1,683 +0,0 @@
-# -*- codingind utf-8 -*-
-"""
-@file differentialOperator.py
-Discrete stretching representation
-"""
-import numpy as np
-from parmepy.constants import np, PARMES_REAL, ORDER
-from parmepy.numerics.method import NumMethod
-#from parmepy.tools.cpu_data_transfer import Synchronize
-from parmepy.tools.cpu_data_transfer_S import SynchronizeS
-
-
-class DifferentialOperator(NumMethod):
-    """
-    Operator representation.
-    DiscreteOperator.DiscreteOperator specialization.
-    """
-
-    def __init__(self, field1, field2, method='', choice=''):
-        """
-        Constructor.
-        Create a Stretching operator on a given continuous domain.
-        Work on a given field2 and field1 to compute the stretching term.
-
-        @param field1 : field n1 (vorticity).
-        @param field2 : field n2 (velocity or density).
-        @param method : name and order of the spacial discretization method.
-        @param choice : differential operator to discretize
-        """
-        self.name = "Differential Operator Discretization"
-        self.field1 = field1
-        self.field2 = field2
-        self.choice = choice
-        self.method = method
-        self.compute_time = 0.
-        self.topology = self.field2.topology
-        self.meshSize = self.topology.mesh.space_step
-
-#    def setUp(self):
-#        pass
-
-    def __call__(self, synchroOp=None):
-        """
-        Apply operator.
-        """
-        ind0a = self.topology.mesh.local_start[0]
-        ind0b = self.topology.mesh.local_end[0] + 1
-        ind1a = self.topology.mesh.local_start[1]
-        ind1b = self.topology.mesh.local_end[1] + 1
-        ind2a = self.topology.mesh.local_start[2]
-        ind2b = self.topology.mesh.local_end[2] + 1
-        ind0 = np.arange(ind0a, ind0b)
-        ind1 = np.arange(ind1a, ind1b)
-        ind2 = np.arange(ind2a, ind2b)
-        if self.choice.find('divWU') >= 0:
-
-            # Ghosts synchronization
-#            linenb = 0
-#            if (self.topology.rank == 0):
-#                time.sleep(2)
-#                print 'Bligne 1', field1[:,linenb,linenb]
-#                time.sleep(2)
-#                print 'Bligne 2', field1[linenb,:,linenb]
-#                time.sleep(2)
-#                print 'Bligne 3', field1[linenb,linenb,:]
-#                time.sleep(2)
-
-#            if (self.topology.rank == 0):
-#                time.sleep(2)
-#                print 'Aligne 1', field1[:,linenb,linenb]
-#                time.sleep(2)
-#                print 'Aligne 2', field1[linenb,:,linenb]
-#                time.sleep(2)
-#                print 'Aligne 3', field1[linenb,linenb,:]
-#                time.sleep(2)
-            OpSynchronize = Synchronize(self.topology)
-            OpSynchronize.apply(self.field2, self.field1)
-
-            synchroOp.apply()
-            if self.method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
-##           X components of temp and result
-#            temp1 = (
-#                self.field1[0][ind+1, ind, ind] *
-#                self.field2[0][ind+1, ind, ind] -
-#                self.field1[0][ind-1, ind, ind] *
-#                self.field2[0][ind-1, ind, ind]
-#            ) / (2. * self.meshSize[0])
-
-#            temp2 = (
-#                self.field1[1][ind, ind+1, ind] *
-#                self.field2[0][ind, ind+1, ind] -
-#                self.field1[1][ind, ind-1, ind] *
-#                self.field2[0][ind, ind-1, ind]
-#            ) / (2. * self.meshSize[1])
-#
-#            temp3 = (
-#                self.field1[2][ind, ind, ind+1] *
-#                self.field2[0][ind, ind, ind+1] -
-#                self.field1[2][ind, ind, ind-1] *
-#                self.field2[0][ind, ind, ind-1]
-#            ) / (2. * self.meshSize[2])
-
-#            self.result[0][ind, ind]=  temp1 + temp2 + temp3
-
-##           Y components of temp and result
-#            temp1 = (
-#                self.field1[0][ind+1, ind, ind] *
-#                self.field2[1][ind+1, ind, ind] -
-#                self.field1[0][ind-1, ind, ind] *
-#                self.field2[1][ind-1, ind, ind]
-#            ) / (2. * self.meshSize[0])
-
-#            temp2 = (
-#                self.field1[1][ind, ind+1, ind] *
-#                self.field2[1][ind, ind+1, ind] -
-#                self.field1[1][ind, ind-1, ind] *
-#                self.field2[1][ind, ind-1, ind]
-#            ) / (2. * self.meshSize[1])
-#
-#            temp3 = (
-#                self.field1[2][ind, ind, ind+1] *
-#                self.field2[1][ind, ind, ind+1] -
-#                self.field1[2][ind, ind, ind-1] *
-#                self.field2[1][ind, ind, ind-1]
-#            ) / (2. * self.meshSize[2])
-
-#            self.result[1][ind, ind]= temp1 + temp2 + temp3
-
-##           Z components of temp and result
-#            temp1 = (
-#                self.field1[0][ind+1, ind, ind] *
-#                self.field2[2][ind+1, ind, ind] -
-#                self.field1[0][ind-1, ind, ind] *
-#                self.field2[2][ind-1, ind, ind]
-#            ) / (2. * self.meshSize[0])
-
-#            temp2 = (
-#                self.field1[1][ind, ind+1, ind] *
-#                self.field2[2][ind, ind+1, ind] -
-#                self.field1[1][ind, ind-1, ind] *
-#                self.field2[2][ind, ind-1, ind]
-#            ) / (2. * self.meshSize[1])
-#
-#            temp3 = (
-#                self.field1[2][ind, ind, ind+1] *
-#                self.field2[2][ind, ind, ind+1] -
-#                self.field1[2][ind, ind, ind-1] *
-#                self.field2[2][ind, ind, ind-1]
-#            ) / (2. * self.meshSize[2])
-
-            else:
-#               X components of temp and result
-                temp1 = self.field2[0][...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[0][ind0-2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[0][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field1[0][ind0-1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[0][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field1[0][ind0+1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[0][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field1[0][ind0+2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[0][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-                temp2 = self.field2[0][...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[1][ind0a:ind0b, ind1-2, ind2a:ind2b] *
-                    self.field2[0][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field1[1][ind0a:ind0b, ind1-1, ind2a:ind2b] *
-                    self.field2[0][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field1[1][ind0a:ind0b, ind1+1, ind2a:ind2b] *
-                    self.field2[0][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field1[1][ind0a:ind0b, ind1+2, ind2a:ind2b] *
-                    self.field2[0][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-                temp3 = self.field2[0][...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-2] *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-1] *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+1] *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+2] *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-#                tmp1 = np.array([temp1 + temp2 + temp3])
-                tmp1 = temp1 + temp2 + temp3
-
-#               Y components of temp and result
-                temp1 = self.field2[1][...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[0][ind0-2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[1][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field1[0][ind0-1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[1][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field1[0][ind0+1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[1][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field1[0][ind0+2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[1][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-                temp2 = self.field2[1][...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[1][ind0a:ind0b, ind1-2, ind2a:ind2b] *
-                    self.field2[1][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field1[1][ind0a:ind0b, ind1-1, ind2a:ind2b] *
-                    self.field2[1][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field1[1][ind0a:ind0b, ind1+1, ind2a:ind2b] *
-                    self.field2[1][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field1[1][ind0a:ind0b, ind1+2, ind2a:ind2b] *
-                    self.field2[1][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-                temp3 = self.field2[1][...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-2] *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-1] *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+1] *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+2] *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-#                tmp2 = np.array([temp1 + temp2 + temp3])
-                tmp2 = temp1 + temp2 + temp3
-
-#               Z components of temp and result
-                temp1 = self.field2[2][...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[0][ind0-2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[2][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field1[0][ind0-1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[2][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field1[0][ind0+1, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[2][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field1[0][ind0+2, ind1a:ind1b, ind2a:ind2b] *
-                    self.field2[2][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-                temp2 = self.field2[2][...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[1][ind0a:ind0b, ind1-2, ind2a:ind2b] *
-                    self.field2[2][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field1[1][ind0a:ind0b, ind1-1, ind2a:ind2b] *
-                    self.field2[2][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field1[1][ind0a:ind0b, ind1+1, ind2a:ind2b] *
-                    self.field2[2][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field1[1][ind0a:ind0b, ind1+2, ind2a:ind2b] *
-                    self.field2[2][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-                temp3 = self.field2[2][...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-2] *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2-1] *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+1] *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field1[2][ind0a:ind0b, ind1a:ind1b, ind2+2] *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-#                tmp3 = np.array([temp1 + temp2 + temp3])
-                tmp3 = temp1 + temp2 + temp3
-                result = np.concatenate((
-                    np.array(tmp1), np.array(tmp2), np.array(tmp3)))
-#            return result
-            return tmp1, tmp2, tmp3
-
-        elif self.choice.find('gradV') >= 0:
-
-            # Ghosts synchronization
-            synchroOp.apply()
-#            OpSynchronize = Synchronize(self.topology)
-#            OpSynchronize.apply(self.field2)
-            if self.method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
-
-            else:
-                maxArray = np.zeros(5, dtype=PARMES_REAL, order=ORDER)
-
-##              Fourth order scheme
-#               X components of temp and result
-#               temp1 = np.zeros(
-#                    (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp1 = self.field2[0][...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[0][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field2[0][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field2[0][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field2[0][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-#               temp2 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp2 = self.field2[0][...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[0][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field2[0][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field2[0][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field2[0][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-#               temp3 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp3 = self.field2[0][...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-                maxstr1 = np.max(abs(temp1) + abs(temp2) + abs(temp3))
-                maxadv1 = np.max(abs(temp1))
-
-#               Y components of temp and result
-#               temp4 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp4 = self.field2[1][...] * 0.
-                temp4[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[1][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field2[1][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field2[1][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field2[1][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-#               temp5 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp5 = self.field2[1][...] * 0.
-                temp5[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[1][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field2[1][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field2[1][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field2[1][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-#               temp6 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp6 = self.field2[1][...] * 0.
-                temp6[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-                maxstr2 = np.max(abs(temp4)+abs(temp5)+abs(temp6))
-                maxadv2 = np.max(abs(temp5))
-
-#               Z components of temp and result
-#               temp7 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp7 = self.field2[2][...] * 0.
-                temp7[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[2][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field2[2][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field2[2][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field2[2][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-#               temp8 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp8 = self.field2[2][...] * 0.
-                temp8[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[2][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field2[2][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field2[2][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field2[2][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-#               temp9 = np.zeros(
-#                   (self.resolution), dtype=PARMES_REAL, order=ORDER)
-                temp9 = self.field2[2][...] * 0.
-                temp9[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-                maxstr3 = np.max(abs(temp7)+abs(temp8)+abs(temp9))
-                maxadv3 = np.max(abs(temp9))
-
-                # grad(V) result
-                result = np.concatenate((
-                    np.array([temp1, temp2, temp3]),
-                    np.array([temp4, temp5, temp6]),
-                    np.array([temp7, temp8, temp9])
-                ))
-                # div(V) result
-                divergence = np.array(temp1 + temp5 + temp9)
-
-                # maxima of partial derivatives : needed for stab conditions
-                    # advection stab
-                maxArray[0] = max(maxstr1, maxstr2, maxstr3)
-                    # stretching stab
-                maxArray[1] = max(maxadv1, maxadv2, maxadv3)
-
-            return result, maxArray, divergence
-
-        elif (self.choice.find('gradS') >= 0):
-
-            # Ghosts synchronization
-            #OpSynchronize = SynchronizeS(self.topology)
-            #OpSynchronize.apply(self.field2)
-            synchroOp.apply()
-
-            if self.method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
-
-            else:
-                # Fourth order scheme
-                temp1 = self.field2[...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field2[ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field2[ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field2[ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-                temp2 = self.field2[...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field2[ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field2[ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field2[ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-                temp3 = self.field2[...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field2[ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field2[ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field2[ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field2[ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-                result = np.array([temp1, temp2, temp3])
-
-            return result
-
-        elif self.choice.find('laplacianV') >= 0:
-
-            # Ghosts synchronization
-#            OpSynchronize = Synchronize(self.topology)
-#            OpSynchronize.apply(self.field2)
-            
-            synchroOp.apply()
-            if self.method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
-
-            else:
-##              Fourth order scheme for the laplacian operator
-#               X components of temp and result
-                temp1 = self.field2[0][...] * 0.
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    - 1. / 12. *
-                    self.field2[0][ind0-2, ind1a:ind1b, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[0][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    - 5. / 2. *
-                    self.field2[0][ind0+0, ind1a:ind1b, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[0][ind0+1, ind1a:ind1b, ind2a:ind2b] +
-                    - 1. / 12. *
-                    self.field2[0][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (self.meshSize[0]**2)
-
-                temp2 = self.field2[0][...] * 0.
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1./12. *
-                    self.field2[0][ind0a:ind0b, ind1-2, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[0][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    -5. / 2. *
-                    self.field2[0][ind0a:ind0b, ind1+0, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[0][ind0a:ind0b, ind1+1, ind2a:ind2b] +
-                    -1. / 12. *
-                    self.field2[0][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (self.meshSize[1]**2)
-
-                temp3 = self.field2[0][...] * 0.
-                temp3[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-2] +
-                    4. / 3. *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    -5. / 2. *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+0] +
-                    4. / 3. *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+1] +
-                    -1. / 12. *
-                    self.field2[0][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (self.meshSize[2]**2)
-                temp1 = temp1 + temp2 + temp3
-
-#               Y components of temp and result
-                temp4 = self.field2[1][...] * 0.
-                temp4[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[1][ind0-2, ind1a:ind1b, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[1][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    - 5. / 2. *
-                    self.field2[1][ind0+0, ind1a:ind1b, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[1][ind0+1, ind1a:ind1b, ind2a:ind2b] +
-                    -1. / 12. *
-                    self.field2[1][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (self.meshSize[0]**2)
-
-                temp5 = self.field2[1][...] * 0.
-                temp5[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[1][ind0a:ind0b, ind1-2, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[1][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    -5. / 2. *
-                    self.field2[1][ind0a:ind0b, ind1+0, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[1][ind0a:ind0b, ind1+1, ind2a:ind2b] +
-                    -1. / 12. *
-                    self.field2[1][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (self.meshSize[1]**2)
-
-                temp6 = self.field2[1][...] * 0.
-                temp6[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-2] +
-                    4. / 3. *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    -5. / 2. *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+0] +
-                    4. / 3. *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+1] +
-                    -1. / 12. *
-                    self.field2[1][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (self.meshSize[2]**2)
-                temp4 = temp4 + temp5 + temp6
-
-#               Z components of temp and result
-                temp7 = self.field2[2][...] * 0.
-                temp7[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[2][ind0-2, ind1a:ind1b, ind2a:ind2b] +
-                    4./3. *
-                    self.field2[2][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    - 5. / 2. *
-                    self.field2[2][ind0+0, ind1a:ind1b, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[2][ind0+1, ind1a:ind1b, ind2a:ind2b] +
-                    -1. / 12. *
-                    self.field2[2][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (self.meshSize[0]**2)
-
-                temp8 = self.field2[2][...] * 0.
-                temp8[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[2][ind0a:ind0b, ind1-2, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[2][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    -5. / 2. *
-                    self.field2[2][ind0a:ind0b, ind1+0, ind2a:ind2b] +
-                    4. / 3. *
-                    self.field2[2][ind0a:ind0b, ind1+1, ind2a:ind2b] +
-                    -1. / 12. *
-                    self.field2[2][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (self.meshSize[1]**2)
-
-                temp9 = self.field2[2][...] * 0.
-                temp9[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    -1. / 12. *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-2] +
-                    4. / 3. *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    -5. / 2. *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+0] +
-                    4. / 3. *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+1] +
-                    -1. / 12. *
-                    self.field2[2][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (self.meshSize[2]**2)
-                temp7 = temp7 + temp8 + temp9
-
-                result = np.concatenate((
-                    np.array([temp1]), np.array([temp4]), np.array([temp7])
-                ))
-
-            return result
-
-        elif self.choice.find('curl') >= 0:
-
-            # Ghosts synchronization
-#            OpSynchronize = Synchronize(self.topology)
-#            OpSynchronize.apply(self.field1)
-
-            synchroOp.apply()
-            if self.method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
-
-            else:
-                temp1 = self.field1[0][...] * 0.
-                temp2 = self.field1[0][...] * 0.
-
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[2][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field1[2][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field1[2][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field1[2][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[1][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field1[1][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field1[1][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field1[1][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-                res1 = temp1 - temp2
-
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[0][ind0a:ind0b, ind1a:ind1b, ind2-2] -
-                    8.0 * self.field1[0][ind0a:ind0b, ind1a:ind1b, ind2-1] +
-                    8.0 * self.field1[0][ind0a:ind0b, ind1a:ind1b, ind2+1] -
-                    1.0 * self.field1[0][ind0a:ind0b, ind1a:ind1b, ind2+2]
-                ) / (12. * self.meshSize[2])
-
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[2][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field1[2][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field1[2][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field1[2][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-                res2 = temp1 - temp2
-
-                temp1[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[1][ind0-2, ind1a:ind1b, ind2a:ind2b] -
-                    8.0 * self.field1[1][ind0-1, ind1a:ind1b, ind2a:ind2b] +
-                    8.0 * self.field1[1][ind0+1, ind1a:ind1b, ind2a:ind2b] -
-                    1.0 * self.field1[1][ind0+2, ind1a:ind1b, ind2a:ind2b]
-                ) / (12. * self.meshSize[0])
-
-                temp2[ind0a:ind0b, ind1a:ind1b, ind2a:ind2b] = (
-                    1.0 * self.field1[0][ind0a:ind0b, ind1-2, ind2a:ind2b] -
-                    8.0 * self.field1[0][ind0a:ind0b, ind1-1, ind2a:ind2b] +
-                    8.0 * self.field1[0][ind0a:ind0b, ind1+1, ind2a:ind2b] -
-                    1.0 * self.field1[0][ind0a:ind0b, ind1+2, ind2a:ind2b]
-                ) / (12. * self.meshSize[1])
-                res3 = temp1 - temp2
-                result = np.concatenate((
-                    np.array([res1]), np.array([res2]), np.array([res3])
-                ))
-            return result
-
-        else:
-            raise ValueError(
-                "Unknown differiential operator property " +
-                str(self.choice))
-
-    def printComputeTime(self):
-        self.timings_info[0] = "\"Differential Operator total\""
-        self.timings_info[1] = str(self.total_time)
-        self.timings_info[1] += str(self.compute_time[0]) + "  " +\
-            str(self.compute_time[1]) + "  " + str(self.compute_time[2]) + "  "
-        print "Differential Operator total time ind ", self.total_time
-        print "\t Differential Operator ind", self.compute_time
-
-    def __str__(self):
-        s = "DifferentialOperator (DiscreteOperator). " +\
-            DiscreteOperator.__str__(self)
-        return s
-
-if __name__ == "__main__":
-    print __doc__
-    print "- Provided class ind DifferentialOperator"
-    print DifferentialOperator.__doc__
diff --git a/HySoP/hysop/numerics/differential_operations.py b/HySoP/hysop/numerics/differential_operations.py
index ac936b6a11399f3772865e8830bd09617da3c843..3ceb9ce43ddb1a282a0c46ed4070b5d6986682ff 100755
--- a/HySoP/hysop/numerics/differential_operations.py
+++ b/HySoP/hysop/numerics/differential_operations.py
@@ -28,63 +28,103 @@ class Curl(DifferentialOperation):
     """
     Computes \f$ \nabla \ times (f) \f$, f being a vector field.
     """
-    def __init__(self, topo, method=None):
+    def __init__(self, topo, method='FD_C_4', memshape=None):
+
+        if method.find('FD_order2') >= 0:
+            raise ValueError("2nd order scheme Not yet implemented")
+
+        elif method.find('FD_C_4_work') >= 0:
+            # - 4th ordered FD,
+            # - work space provided by used during function call,
+            #   i.e. memshape not required,
+            # - fd.compute method
+
+            # declare and create fd scheme
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
+            # connect to fd function call
+            self.fcall = self.FDCentral4_with_work
 
-        DifferentialOperation.__init__(self, topo)
-        if method is not None and method.find('FD_order2') >= 0:
-                raise ValueError("2nd order scheme Not yet implemented")
         else:
-            assert (topo.ghosts >= 2).all(),\
-                'you need a ghost layer for FD4 scheme.'
-            self.fcall = self.FDCentral4
+            # - 4th ordered FD,
+            # - local work space => memshape required,
+            # - fd.compute method
+            if memshape is None:
+                raise ValueError("memshape required for this method")
+            self._worklength = 1
+            # declare and create fd scheme
             self.fd_scheme = FD_C_4(topo.mesh.space_step)
-            self.indices = topo.mesh.iCompute
-            self.fd_scheme.computeIndices(self.indices)
-        self.nbComponents = topo.domain.dimension
+            # connect to finite differences function ...
+            self.fcall = self.FDCentral4
+            # allocate local workspace
+            self._work = [npw.zeros(memshape)
+                          for i in xrange(self._worklength)]
 
-    def __call__(self, variable, data=None):
-        return self.fcall(variable, data)
+        self._indices = topo.mesh.iCompute
+        # initialize fd scheme
+        self.fd_scheme.computeIndices(self._indices)
+        # check ghosts ... must be updated when
+        # other fd schemes will be implemented.
+        assert (topo.ghosts >= 2).all(),\
+            'you need a ghost layer for FD4 scheme.'
 
-    def FDCentral4(self, variable, data=None):
+    def __call__(self, variable, result, work=None):
+        return self.fcall(variable, result, work)
+
+    def FDCentral4(self, variable, result, work=None):
         """
-        @param variable : a list of numpy arrays
+        @param variable : input vector field
+        @param result : list of numpy arrays to save result
         """
-        # Get slices for subarrays ...
-       # init (if required) return data
-        if data is None:
-            data = []
-            for i in xrange(self.nbComponents):
-                data.append(variable[i].copy())
-                #data[i][...] = 0.0
-
-        #data[0][...] = 0.0
-        #data[1][...] = 0.0
-        #data[2][...] = 0.0
-
-        #--  d/dy vz -- in data[XDIR]
-        self.fd_scheme.compute(variable[ZDIR], YDIR, data[XDIR])
-        # -- -d/dz vy -- in data[YDIR]
-        work = data[YDIR]
-        self.fd_scheme.compute(variable[YDIR], ZDIR, work)
-        # data_x = d/dy vz - d/dz vy
-        data[XDIR][self.indices] -= work[self.indices]
-
-        #--  d/dz vx -- in data[YDIR]
-        self.fd_scheme.compute(variable[XDIR], ZDIR, data[YDIR])
-        # -- -d/dx vz -- in data[ZDIR]
-        work = data[ZDIR]
-        self.fd_scheme.compute(variable[ZDIR], XDIR, work)
-
-        # data_y = d/dz vx - d/dx vz
-        data[YDIR][self.indices] -= work[self.indices]
-
-        # - d/dy vx in data[ZDIR]
-        self.fd_scheme.compute(variable[XDIR], YDIR, data[ZDIR])
-        data[ZDIR][self.indices] *= -1.
-        # add d/dx vy, add to data[ZDIR]
-        self.fd_scheme.compute_and_add(variable[YDIR], XDIR, data[ZDIR])
+        #--  d/dy vz -- in result[XDIR]
+        self.fd_scheme.compute(variable[ZDIR], YDIR, result[XDIR])
+        # -- -d/dz vy -- in work
+        self.fd_scheme.compute(variable[YDIR], ZDIR, self._work[0])
+        # result_x = d/dy vz - d/dz vy
+        result[XDIR][self._indices] -= self._work[0][self._indices]
+
+        #--  d/dz vx -- in result[YDIR]
+        self.fd_scheme.compute(variable[XDIR], ZDIR, result[YDIR])
+        # -- -d/dx vz -- in work
+        self.fd_scheme.compute(variable[ZDIR], XDIR, self._work[0])
+        # result_y = d/dz vx - d/dx vz
+        result[YDIR][self._indices] -= self._work[0][self._indices]
+
+        #-- d/dx vy in result[ZDIR]
+        self.fd_scheme.compute(variable[YDIR], XDIR, result[ZDIR])
+        # result_z = d/dx vy - d/dy vx
+        self.fd_scheme.compute(variable[XDIR], YDIR, self._work[0])
+        result[ZDIR][self._indices] -= self._work[0][self._indices]
 
-        return data
+        return result
+
+    def FDCentral4_with_work(self, variable, result, work):
+        """
+        @param variable : input vector field
+        @param result : list of numpy arrays to save result
+        """
+        assert len(work) >= 1
+        assert work[0].shape == variable[0].shape
+        #--  d/dy vz -- in result[XDIR]
+        self.fd_scheme.compute(variable[ZDIR], YDIR, result[XDIR])
+        # -- -d/dz vy -- in work
+        self.fd_scheme.compute(variable[YDIR], ZDIR, work[0])
+        # result_x = d/dy vz - d/dz vy
+        result[XDIR][self._indices] -= work[0][self._indices]
+
+        #--  d/dz vx -- in result[YDIR]
+        self.fd_scheme.compute(variable[XDIR], ZDIR, result[YDIR])
+        # -- -d/dx vz -- in work
+        self.fd_scheme.compute(variable[ZDIR], XDIR, work[0])
+        # result_y = d/dz vx - d/dx vz
+        result[YDIR][self._indices] -= work[0][self._indices]
+
+        #-- d/dx vy in result[ZDIR]
+        self.fd_scheme.compute(variable[YDIR], XDIR, result[ZDIR])
+        # result_z = d/dx vy - d/dy vx
+        self.fd_scheme.compute(variable[XDIR], YDIR, work[0])
+        result[ZDIR][self._indices] -= work[0][self._indices]
+
+        return result
 
 
 class DivV(DifferentialOperation):
@@ -133,7 +173,7 @@ class DivV(DifferentialOperation):
             # - fd.compute method
 
             # declare and create fd scheme
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             # connect to fd function call
             self.fcall = self.FDCentral4_with_work
 
@@ -144,7 +184,7 @@ class DivV(DifferentialOperation):
             # - fd.compute_and_add method
 
             # declare and create fd scheme
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             # connect to fd function call
             self.fcall = self.FDCentral4_CAA_with_work
 
@@ -157,14 +197,14 @@ class DivV(DifferentialOperation):
 
             # Max nb of components of input fields.
             self.nbComponents = len(memshape)
-            self._WORKLENGTH = 1
+            self._worklength = 1
             # declare and create fd scheme
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             # connect to finite differences function ...
             self.fcall = self.FDCentral4_CAA
             # allocate local workspace
             self._work = [npw.zeros(memshape)
-                          for i in xrange(self._WORKLENGTH)]
+                          for i in xrange(self._worklength)]
 
         else:
             # - 4th ordered FD,
@@ -176,16 +216,16 @@ class DivV(DifferentialOperation):
             # Max nb of components of input fields.
             self.nbComponents = len(memshape)
             if self.nbComponents == 1:  # 1D case
-                self._WORKLENGTH = 1
+                self._worklength = 1
             else:  # 2 and 3D cases
-                self._WORKLENGTH = 2
+                self._worklength = 2
             # declare and create fd scheme
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             # connect to finite differences function ...
             self.fcall = self.FDCentral4
             # allocate local workspace
             self._work = [npw.zeros(memshape)
-                          for i in xrange(self._WORKLENGTH)]
+                          for i in xrange(self._worklength)]
 
         self._indices = topo.mesh.iCompute
         # initialize fd scheme
@@ -354,8 +394,8 @@ class DivT(DifferentialOperation):
     each component with the same size as var1[i].
 
     """
-    def __init__(self, topo, method=None, memshape=None):
-        if method is not None and method.find('FD_order2') >= 0:
+    def __init__(self, topo, method='FD_C_4', memshape=None):
+        if method.find('FD_order2') >= 0:
                 raise ValueError("2nd order scheme Not yet implemented")
         elif method.find('FD_C_4_work') >= 0:
             # - 4th ordered FD,
@@ -390,10 +430,10 @@ class DivT(DifferentialOperation):
 
             # Max nb of components of input fields.
             self.nbComponents = len(memshape)
-            self._WORKLENGTH = 1
+            self._worklength = 1
             # allocate local workspace
             self._work = [npw.zeros(memshape)
-                          for i in xrange(self._WORKLENGTH)]
+                          for i in xrange(self._worklength)]
 
             # connect call function
             self.fcall = self.FDCentral4
@@ -412,12 +452,12 @@ class DivT(DifferentialOperation):
             # Max nb of components of input fields.
             self.nbComponents = len(memshape)
             if self.nbComponents == 1:  # 1D case
-                self._WORKLENGTH = 1
+                self._worklength = 1
             else:
-                self._WORKLENGTH = 2
+                self._worklength = 2
             # allocate local workspace
             self._work = [npw.zeros(memshape)
-                          for i in xrange(self._WORKLENGTH)]
+                          for i in xrange(self._worklength)]
 
             # connect call function
             self.fcall = self.FDCentral4
@@ -467,7 +507,7 @@ class GradS(DifferentialOperation):
                 raise ValueError("2nd order scheme Not yet implemented")
         elif method.find('FD_C_4') >= 0:
             self.fcall = self.FDCentral4
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
         else:
             raise ValueError("FD scheme Not yet implemented")
 
@@ -530,41 +570,91 @@ class GradVxW(DifferentialOperation):
     Computes \f$ [\nabla(V)][W] \f$, with
     \f$V\f$ and \f$W\f$ some vector fields.
     """
-    def __init__(self, topo, method='FD_C_4'):
+    def __init__(self, topo, method='FD_C_4', memshape=None):
+
+        # dimension of the fields
+        self._dim = topo.domain.dimension
+
+        if self._dim == 1:
+            self._worklength = 1
+        elif self._dim == 2:
+            self._worklength = 2
+        else:
+            self._worklength = 2
+
         if method.find('FD_order2') >= 0:
             raise ValueError("2nd order scheme Not yet implemented")
+        elif method.find('FD_C_4_diag_work') >= 0:
+            # - 4th ordered FD
+            # - work space provided by used during function call,
+            # - fd.compute method
+            # - performs diagnostcis computation
+
+            # declare and create fd scheme
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
+            # connect to fd function call
+            self.fcall = self.FDCentral4_work_diag
+
         elif method.find('FD_C_4_diag') >= 0:
             # - 4th ordered FD, with diagnostics in output
-            # - work space provided by used during function call,
+            # - use local work space
             # - fd.compute method
 
             # declare and create fd scheme
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             # connect to fd function call
             self.fcall = self.FDCentral4_diag
+            if memshape is None:
+                raise ValueError("memshape required for this method")
+            # allocate local workspace
+            self._work = [npw.zeros(memshape)
+                          for i in xrange(self._worklength)]
         else:
-            self.fd_scheme = FD_C_4((topo.mesh.space_step))
+            # - 4th ordered FD
+            # - use local work space
+            # - fd.compute method
+            self.fd_scheme = FD_C_4(topo.mesh.space_step)
             self.fcall = self.FDCentral4
+            if memshape is None:
+                raise ValueError("memshape required for this method")
+            # allocate local workspace
+            self._work = [npw.zeros(memshape)
+                          for i in xrange(self._worklength)]
 
         self._indices = topo.mesh.iCompute
         self.fd_scheme.computeIndices(self._indices)
         assert (topo.ghosts >= 2).all(),\
             'you need a ghost layer for FD4 scheme.'
 
-        # dimension of the fields
-        self._dim = topo.domain.dimension
+    def __call__(self, var1, var2, result, diagnostics=None, work=None):
+        return self.fcall(var1, var2, result, diagnostics, work)
 
-        if self._dim == 1:
-            self._worklength = 1
-        elif self._dim == 2:
-            self._worklength = 2
-        else:
-            self._worklength = 2
- 
-    def __call__(self, var1, var2, result, work, diagnostics=None):
-        return self.fcall(var1, var2, result, work, diagnostics)
+    def FDCentral4_diag(self, var1, var2, result, diagnostics, work=None):
+        """
+        """
+        assert len(result) == self._dim
+        nbc = len(var1)
+        diagnostics[:] = 0.0
+        for comp in xrange(nbc):
+            result[comp][...] = 0.0
+            self._work[1][...] = 0.0
+            for cdir in xrange(self._dim):
+                # self._work = d/dcdir (var1_comp)
+                self.fd_scheme.compute(var1[comp], cdir, self._work[0])
+                # some diagnostics ...
+                if cdir == comp:
+                    tmp = np.max(abs(self._work[0]))
+                    diagnostics[0] = max(diagnostics[0], tmp)
+                self._work[1][...] += abs(self._work[0])
+
+                # compute self._work = self._work.var2[cdir]
+                self._work[0][...] = self._work[0] * var2[cdir]
+                # sum to obtain nabla(var_comp) . var2, saved into result[comp]
+                np.add(result[comp], self._work[0], result[comp])
+            diagnostics[1] = max(diagnostics[1], np.max(self._work[1]))
+        return result, diagnostics
 
-    def FDCentral4_diag(self, var1, var2, result, work, diagnostics):
+    def FDCentral4_work_diag(self, var1, var2, result, diagnostics, work):
         """
         """
         assert len(result) == self._dim
@@ -590,21 +680,20 @@ class GradVxW(DifferentialOperation):
             diagnostics[1] = max(diagnostics[1], np.max(work[1]))
         return result, diagnostics
 
-    def FDCentral4(self, var1, var2, result, work, diagnostics=None):
+    def FDCentral4(self, var1, var2, result, diagnostics=None, work=None):
         """
         """
         assert len(result) == self._dim
-        assert len(work) == self._worklength
         nbc = len(var1)
         for comp in xrange(nbc):
             result[comp][...] = 0.0
             for cdir in xrange(self._dim):
-                # work = d/dcdir (var1_comp)
-                self.fd_scheme.compute(var1[comp], cdir, work[0])
-                # compute work = work.var2[cdir]
-                work[0][...] = work[0] * var2[cdir]
+                # self._work = d/dcdir (var1_comp)
+                self.fd_scheme.compute(var1[comp], cdir, self._work[0])
+                # compute self._work = self._work.var2[cdir]
+                self._work[0][...] = self._work[0] * var2[cdir]
                 # sum to obtain nabla(var_comp) . var2, saved into result[comp]
-                np.add(result[comp], work[0], result[comp])
+                np.add(result[comp], self._work[0], result[comp])
 
         return result
 
diff --git a/HySoP/hysop/numerics/tests/test_diffOp.py b/HySoP/hysop/numerics/tests/test_diffOp.py
index 12f29c6638896383c50fd251fb718a628377a15d..b0f160fc60fe552dbb13f2d32d51095b8be3e7d5 100755
--- a/HySoP/hysop/numerics/tests/test_diffOp.py
+++ b/HySoP/hysop/numerics/tests/test_diffOp.py
@@ -1,250 +1,123 @@
 # -*- coding: utf-8 -*-
 import parmepy as pp
 import numpy as np
-from parmepy.constants import PARMES_REAL, ORDER
-from parmepy.domain.box import Box
 from parmepy.fields.continuous import Field
 from parmepy.mpi.topology import Cartesian
-from parmepy.numerics.differential_operations import DivT, GradVxW, GradS, Curl, DivStressTensor3D
+from parmepy.numerics.differential_operations import DivT, GradVxW, Curl
 import parmepy.tools.numpywrappers as npw
-import numpy.testing as npt
 import math as m
+pi = m.pi
+cos = m.cos
+sin = m.sin
 
 
-def testDivWV():
-    """Basic test for conservative formulation of the stretching term using FD scheme 
-    (comparison with periodic analytical solution based on Taylor Green benchmark)
-    """
-    # Domain and topologies definitions
-    nb = 65
-    Lx = Ly = Lz = 2. * np.pi
-    box = Box(dimension=3, length=[Lx, Ly, Lz], 
-              origin=[0., 0., 0.])
-    resol = [nb, nb, nb]
-    nbghosts = 2
-    ghosts = np.ones((box.dimension)) * nbghosts
-    topoG = Cartesian(box, box.dimension, resol,
-                     ghosts=ghosts)
-    topoNoG = Cartesian(box, box.dimension, resol)
-
-    # Velocity, Vorticity and result fields
-    velo = Field(domain=box, formula=vitesse, 
-                 name='Velocity', isVector=True)
-    velo_d = velo.discretize(topoG)
-    velo.initialize()
-
-    vorti = Field(domain=box, formula=vorticite, 
-                  name='Vorticity', isVector=True)
-    vorti_d = vorti.discretize(topoG)
-    vorti.initialize()
-
-    result = np.zeros_like(vorti_d.data)
-
-    # Analytical field
-    analyt = Field(domain=box, formula=analyticalDivWV, 
-                   name='Analytical', isVector=True)
-    analyt_d = analyt.discretize(topoNoG)
-    analyt.initialize()
-
-    # Div operator
-    FD_method = 'FD_order4'
-    StretchOp = DivT(topoG, FD_method, memshape=velo_d.data[0].shape)
-    result = StretchOp(velo_d.data, vorti_d.data, result)
-
-    # Numerical VS analytical
-    ind = topoG.mesh.iCompute
-    errX = errY = errZ = (Lx / (nb - 1)) ** 4
-    print 'err = O(h**4) =', errX
-    print '=============='
-    print 'div(WU) test'
-    print '=============='
-    print 'Is the numerical solution equal to the analytical one at the order 4 ? :'
-    print np.allclose(analyt_d[0], result[0][ind], rtol=errX)
-    print np.allclose(analyt_d[1], result[1][ind], rtol=errY)
-    print np.allclose(analyt_d[2], result[2][ind], rtol=errZ)
-
-
-def testGradVxW():
-    """Basic test for non conservative formulation of the stretching term using FD scheme 
-    (comparison with periodic analytical solution based on Taylor Green benchmark)
-    """
-    # Domain and topologies definitions
-    nb = 64
-    Lx = Ly = Lz = 2. * np.pi
-    box = Box(dimension=3, length=[Lx, Ly, Lz], 
-              origin=[0., 0., 0.])
-    resol = [nb, nb, nb]
-    nbghosts = 2
-    ghosts = np.ones((box.dimension)) * nbghosts
-    topoG = Cartesian(box, box.dimension, resol,
-                     ghosts=ghosts)
-    topoNoG = Cartesian(box, box.dimension, resol)
-
-    # Velocity, Vorticity and result fields
-    velo = Field(domain=box, formula=vitesse, 
-                 name='Velocity', isVector=True)
-    velo_d = velo.discretize(topoG)
-    velo.initialize()
-
-    vorti = Field(domain=box, formula=vorticite, 
-                  name='Vorticity', isVector=True)
-    vorti_d = vorti.discretize(topoG)
-    vorti.initialize()
-
-    result = np.zeros_like(vorti_d.data)
-
-    # Analytical field
-    analyt = Field(domain=box, formula=analyticalGradVxW, 
-                   name='Analytical', isVector=True)
-    analyt_d = analyt.discretize(topoNoG)
-    analyt.initialize()
-
-    # Grad operator
-    FD_method = 'FD_order4'
-    StretchOp = GradVxW(topoG, FD_method)
-    result, diag = StretchOp(velo_d.data, vorti_d.data)
-
-    # Numerical VS analytical
-    ind = topoG.mesh.iCompute
-    errX = errY = errZ = (Lx / (nb - 1)) ** 4
-    print 'err = O(h**4) =', errX
-    print '=============='
-    print 'grad(U).W test'
-    print '=============='
-    print 'Is the numerical solution equal to the analytical one at the order 4 ? :'
-    print np.allclose(analyt_d[0], result[0][ind], rtol=errX)
-    print np.allclose(analyt_d[1], result[1][ind], rtol=errY)
-    print np.allclose(analyt_d[2], result[2][ind], rtol=errZ)
-
-def testCurl():
-    """Basic test for Curl operator using FD scheme 
-    (comparison with periodic analytical solution)
-    """
-    # Domain and topologies definitions
-    nb = 64
-    Lx = Ly = Lz = 2. * np.pi
-    box = Box(dimension=3, length=[Lx, Ly, Lz], 
-              origin=[0., 0., 0.])
-    resol = [nb, nb, nb]
-    nbghosts = 2
-    ghosts = np.ones((box.dimension)) * nbghosts
-    topoG = Cartesian(box, box.dimension, resol,
-                     ghosts=ghosts)
-    topoNoG = Cartesian(box, box.dimension, resol)
-
-    # Velocity and result fields
-    velo = Field(domain=box, formula=vitesse, 
-                 name='Velocity', isVector=True)
-    velo_d = velo.discretize(topoG)
-    velo.initialize()
-    resCurl = np.zeros_like(velo_d.data)
-
-    # Analytical field
-    analyt = Field(domain=box, formula=vorticite, 
-                    name='analytical', isVector=True)
-    analyt_d = analyt.discretize(topoNoG)
-    analyt.initialize()
-
-    # Curl operator
-    FD_method = 'FD_order4'
-    CurlOp = Curl(topoG, FD_method)
-    resCurl = CurlOp(velo_d.data)
-
-    # Numerical VS analytical
-    ind = topoG.mesh.iCompute
-    errX = errY = errZ = (Lx / (nb - 1)) ** 4
-    print 'err = O(h**4) =', errX
-    print '=============='
-    print 'curl(U) test'
-    print '=============='
-    print 'Is the numerical solution equal to the analytical one at the order 4 ? :'
-    print np.allclose(analyt_d[0], resCurl[0][ind], rtol=errX)
-    print np.allclose(analyt_d[1], resCurl[1][ind], rtol=errY)
-    print np.allclose(analyt_d[2], resCurl[2][ind], rtol=errZ)
-
-def testDivStressTensor():
-    """Basic test for divergence of stress tensor T 
-    (comparison with periodic analytical solution based on Taylor Green benchmark)
-    """
-    # Domain and topologies definitions
-    nb = 64
-    Lx = Ly = Lz = 2. * np.pi
-    box = Box(dimension=3, length=[Lx, Ly, Lz], 
-              origin=[0., 0., 0.])
-    resol = [nb, nb, nb]
-    nbghosts = 2
-    ghosts = np.ones((box.dimension)) * nbghosts
-    topoG = Cartesian(box, box.dimension, resol,
-                     ghosts=ghosts)
-    topoNoG = Cartesian(box, box.dimension, resol)
-
-    # Velocity, work and result fields
-    velo = Field(domain=box, formula=vitesse, 
-                 name='Velocity', isVector=True)
-    velo_d = velo.discretize(topoG)
-    velo.initialize()
-
-    result = npw.zeros_like(velo_d.data)
-    work = npw.zeros_like(velo_d.data)
-
-    # Analytical field
-    analyt = Field(domain=box, formula=analyticalDivStressTensor, 
-                   name='Analytical', isVector=True)
-    analyt_d = analyt.discretize(topoNoG)
-    analyt.initialize()
-
-    # Grad operator
-    FD_method = 'FD_order4'
-    ind = topoG.mesh.iCompute
-    divT = DivStressTensor3D(topoG, FD_method)
-    result = divT(velo_d.data, result, work, ind)
-
-    # Numerical VS analytical
-    errX = errY = errZ = (Lx / (nb - 1)) ** 4
-    print 'err = O(h**4) =', errX
-    print '=============='
-    print 'div(T) test'
-    print '=============='
-    print 'Is the numerical solution equal to the analytical one at the order 4 ? :'
-    print np.allclose(analyt_d[0], result[0][ind], rtol=errX)
-    print np.allclose(analyt_d[1], result[1][ind], rtol=errY)
-    print np.allclose(analyt_d[2], result[2][ind], rtol=errZ)
-
-
-def vitesse(x, y, z):
-    vx = m.sin(x) * m.cos(y) * m.cos(z)
-    vy = - m.cos(x) * m.sin(y) * m.cos(z)
+## Function to compute TG velocity
+def computeVel(x, y, z):
+    vx = sin(x) * cos(y) * cos(z)
+    vy = - cos(x) * sin(y) * cos(z)
     vz = 0.
     return vx, vy, vz
 
-def vorticite(x, y, z):
-    wx = - m.cos(x) * m.sin(y) * m.sin(z)
-    wy = - m.sin(x) * m.cos(y) * m.sin(z)
-    wz = 2. * m.sin(x) * m.sin(y) * m.cos(z)
+
+## Function to compute reference vorticity
+def computeVort(x, y, z):
+    wx = - cos(x) * sin(y) * sin(z)
+    wy = - sin(x) * cos(y) * sin(z)
+    wz = 2. * sin(x) * sin(y) * cos(z)
     return wx, wy, wz
 
+
 def analyticalDivWV(x, y, z):
-    ax = - m.sin(y) * m.cos(y) * m.sin(z) * m.cos(z) * (- m.sin(x) * m.sin(x) + m.cos(x) * m.cos(x)) + \
-         2. * m.cos(x) * m.cos(x) * m.sin(z) * m.cos(z) * m.sin(y) * m.cos(y)
-    ay = - 2. * m.cos(y) * m.cos(y) * m.sin(z) * m.cos(z) * m.sin(x) * m.cos(x) + \
-         m.sin(x) * m.cos(x) * m.sin(z) * m.cos(z) * (m.cos(y) * m.cos(y) - m.sin(y) * m.sin(y))
+    ax = - sin(y) * cos(y) * sin(z) * cos(z) * \
+        (- sin(x) * sin(x) + cos(x) * cos(x)) + \
+        2. * cos(x) * cos(x) * sin(z) * cos(z) * sin(y) * cos(y)
+
+    ay = - 2. * cos(y) * cos(y) * sin(z) * cos(z) * sin(x) * cos(x) + \
+        sin(x) * cos(x) * sin(z) * cos(z) * (cos(y) * cos(y)
+                                             - sin(y) * sin(y))
+
     az = 0.
     return ax, ay, az
 
+
 def analyticalGradVxW(x, y, z):
-    ax = - m.sin(y) * m.cos(y) * m.sin(z) * m.cos(z)
-    ay = m.sin(x) * m.cos(x) * m.sin(z) * m.cos(z)
+    ax = - sin(y) * cos(y) * sin(z) * cos(z)
+    ay = sin(x) * cos(x) * sin(z) * cos(z)
     az = 0.
     return ax, ay, az
 
+
 def analyticalDivStressTensor(x, y, z):
-    ax = - 3. * m.sin(x) * m.cos(y) * m.cos(z)
-    ay = 2. * m.sin(x) * m.cos(y) * m.cos(z) - m.sin(x) * m.sin(y) * m.sin(z)
+    ax = - 3. * sin(x) * cos(y) * cos(z)
+    ay = 2. * sin(x) * cos(y) * cos(z) - sin(x) * sin(y) * sin(z)
     az = 0.
     return ax, ay, az
 
-if __name__ == "__main__":
-#    testDivWV()
-#    testGradVxW()
-#    testCurl()
-    testDivStressTensor()
+
+nb = 65
+box = pp.Box(3, length=[2.0 * pi, 2.0 * pi, 2.0 * pi])
+nbElem = [nb] * 3
+topo = Cartesian(box, box.dimension, nbElem,
+                 ghosts=[2, 2, 2])
+velo = Field(domain=box, formula=computeVel,
+             name='Velocity', isVector=True)
+vorti = Field(domain=box, formula=computeVort,
+              name='Vorticity', isVector=True)
+vorti.setTopoInit(topo)
+velo.discretize(topo)
+vorti.discretize(topo)
+velo.initialize()
+vorti.initialize()
+wd = vorti.discreteFields[topo]
+vd = velo.discreteFields[topo]
+ind = topo.mesh.iCompute
+
+
+def testCurl():
+    memshape = vd.data[0].shape
+    result = [npw.zeros(memshape) for i in xrange(3)]
+    curlOp = Curl(topo, memshape=memshape)
+    result = curlOp(vd.data, result)
+
+    for i in xrange(3):
+        assert np.allclose(wd.data[i][ind], result[i][ind])
+
+
+def testDivWV():
+    # Reference field
+    ref = Field(domain=box, formula=analyticalDivWV,
+                name='Analytical', isVector=True)
+    ref.discretize(topo)
+    ref.initialize()
+    refd = ref.discreteFields[topo]
+    memshape = vd.data[0].shape
+    # Div operator
+    divOp = DivT(topo, memshape=memshape)
+    result = [npw.zeros(memshape) for i in xrange(3)]
+    result = divOp(vd.data, wd.data, result)
+
+    # Numerical VS analytical
+    Lx = box.length[0]
+    errX = (Lx / (nb - 1)) ** 4
+    for i in xrange(3):
+        assert np.allclose(refd[i][ind], result[i][ind], rtol=errX)
+
+
+def testGradVxW():
+    # Reference field
+    ref = Field(domain=box, formula=analyticalGradVxW,
+                name='Analytical', isVector=True)
+    ref.discretize(topo)
+    ref.initialize()
+    refd = ref.discreteFields[topo]
+    memshape = vd.data[0].shape
+
+    gradOp = GradVxW(topo, memshape=memshape)
+    result = [npw.zeros(memshape) for i in xrange(3)]
+    result = gradOp(vd.data, wd.data, result)
+
+    # Numerical VS analytical
+    Lx = box.length[0]
+    errX = (Lx / (nb - 1)) ** 4
+    for i in xrange(3):
+        assert np.allclose(refd[i][ind], result[i][ind], rtol=errX)
diff --git a/HySoP/hysop/operator/curl.py b/HySoP/hysop/operator/curl.py
deleted file mode 100644
index 11a35350331f820d1d5bae210b9b453255fa0d68..0000000000000000000000000000000000000000
--- a/HySoP/hysop/operator/curl.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""
-@file operator/curl.py
-
-Curl of a field.
-"""
-from parmepy.constants import debug, np
-from parmepy.operator.continuous import Operator
-from parmepy.operator.discrete.curl import CurlFD
-from parmepy.operator.updateGhosts import UpdateGhosts
-
-
-class Curl(Operator):
-    """
-    Computes \f$ outVar = \nabla \times inVar \f$
-    """
-
-    @debug
-    def __init__(self, invar, outvar, resolution, method=None, ghosts=None,
-                 topo=None):
-        """
-        Create an operator to compute the curl of a field.
-        @param invar : the input vector field
-        @param outvar : curl of input vector field
-        @param resolution : resolution (global) of the fields
-        @param method : method used (default = finite difference, 4th order)
-        @param topo : a predefined topology to discretize invar/outvar
-        """
-
-        Operator.__init__(self, [invar, outvar], method, ghosts=ghosts,
-                          topo=topo)
-
-        ## Dict of resolutions (one per variable)
-        self.resolution = resolution
-        self.output = [outvar]
-        self.input = [invar]
-        self.invar = invar
-        self.outvar = outvar
-        if self.method is None:
-            self.method = 'FD_C4'
-        ## An operator to update ghost points of input var.
-        self.ghostsOperator = None
-
-    @debug
-    def setUp(self):
-        if self.method.find('FD_order2') >= 0:
-            nbGhosts = 1
-        elif self.method.find('FD_C4') >= 0:
-            nbGhosts = 2
-        else:
-            nbGhosts = 0
-
-        # get (or create) the topology
-        if self._predefinedTopo is not None:
-            assert (self._predefinedTopo.ghosts >= nbGhosts).all()
-            topo = self._predefinedTopo
-
-        else:
-            # same topo for all variables
-            if self.ghosts is not None:
-                self.ghosts[self.ghosts < nbGhosts] = nbGhosts
-            else:
-                self.ghosts = np.ones(self.domain.dimension) * nbGhosts
-
-            # default topology constructor, with global resolution
-            # and domain
-            topo = self.domain.getOrCreateTopology(self.domain.dimension,
-                                                   self.resolution,
-                                                   ghosts=self.ghosts)
-        # Now, discretisation of the variables
-        for v in self.variables:
-            self.discreteFields[v] = v.discretize(topo)
-
-        # Create a discrete operator, according to the chosen method
-        # (only finite differences at the time).
-        self.discreteOperator = CurlFD(self.discreteFields[self.invar],
-                                       self.discreteFields[self.outvar],
-                                       method=self.method)
-        self.discreteOperator.setUp()
-        # ghost op
-        self.ghostsOperator = UpdateGhosts(self.input, topo=topo)
-
-        self._isUpToDate = True
-
-    def apply(self, simulation=None):
-        # update ghost points, if required
-        if self.ghostsOperator is not None:
-            self.ghostsOperator.apply()
-        # computation ...
-        self.discreteOperator.apply(simulation)
-
-if __name__ == "__main__":
-    print __doc__
-    print "- Provided class : Curl"
-    print Curl.__doc__
diff --git a/HySoP/hysop/operator/differential.py b/HySoP/hysop/operator/differential.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa8044b145daa4af4e7ca82b9822097c8f3929c5
--- /dev/null
+++ b/HySoP/hysop/operator/differential.py
@@ -0,0 +1,162 @@
+"""
+@file operator/differential.py
+
+Differential operators
+"""
+from parmepy.constants import debug, np
+from parmepy.operator.continuous import Operator
+from parmepy.operator.discrete.differential import CurlFD, GradFD
+from parmepy.operator.updateGhosts import UpdateGhosts
+from abc import ABCMeta, abstractmethod
+
+
+class Differential(Operator):
+    __metaclass__ = ABCMeta
+
+    ## @debug
+    ## def __new__(cls, *args, **kw):
+    ##     return object.__new__(cls, *args, **kw)
+
+    @debug
+    @abstractmethod
+    def __init__(self, invar, outvar, resolutions, method=None,
+                 topo=None, ghosts=None, ghostUpdate=None, name=None):
+
+        Operator.__init__(self, [invar, outvar], method, topo=topo,
+                          ghosts=ghosts, name=name)
+        ## input variable
+        self.invar = invar
+        ## Curl of input
+        self.outvar = outvar
+        ## Grid resolution for each variable (dictionnary)
+        self.resolutions = resolutions
+        if self.method is None:
+            self.method = 'FD_C_4'
+        ## If ghostupdate == True, the operator will manage
+        ## ghost points update. Else, this must be done somewhere else ...
+        ## Default = yes
+        if ghostUpdate is None:
+            self.ghostUpdate = True
+        else:
+            self.ghostUpdate = ghostUpdate
+        self.output = [outvar]
+        self.input = [invar]
+
+    def pre_setUp(self):
+        if self.method.find('FD_order2') >= 0:
+            nbGhosts = 1
+        elif self.method.find('FD_C_4') >= 0:
+            nbGhosts = 2
+        else:
+            nbGhosts = 0
+
+        # get (or create) the topology
+        if self._predefinedTopo is not None:
+            assert (self._predefinedTopo.ghosts >= nbGhosts).all()
+            topo = self._predefinedTopo
+            for v in self.variables:
+                self.discreteFields[v] = v.discretize(topo)
+
+        else:
+            # same topo for all variables
+            if self.ghosts is not None:
+                self.ghosts[self.ghosts < nbGhosts] = nbGhosts
+            else:
+                self.ghosts = np.ones(self.domain.dimension) * nbGhosts
+
+            # default topology constructor, with global resolution
+            # and domain
+            for v in self.variables:
+                topo = self.domain.getOrCreateTopology(self.domain.dimension,
+                                                       self.resolutions[v],
+                                                       ghosts=self.ghosts)
+                self.discreteFields[v] = v.discretize(topo)
+
+        assert self.discreteFields[self.invar].topology == \
+            self.discreteFields[self.outvar].topology, \
+            'Operator not yet implemented for multiple resolutions.'
+
+        if self.ghostUpdate:
+            topov = self.discreteFields[self.invar].topology
+            self.synchronize = UpdateGhosts(self.invar, topo=topov)
+            self.synchronize.setUp()
+
+    def apply(self, simulation=None):
+        if self.ghostUpdate:
+            self.synchronize.apply()
+        # computation ...
+        self.discreteOperator.apply(simulation)
+
+
+class Curl(Differential):
+    """
+    Computes \f$ outVar = \nabla inVar \f$
+    """
+
+    @debug
+    def __init__(self, invar, outvar, resolutions, method=None,
+                 topo=None, ghosts=None, ghostUpdate=None):
+        """
+        Create an operator to compute the curl of a field.
+        @param invar : the input vector field
+        @param outvar : curl of input vector field
+        @param resolution : resolution (global) of the fields
+        @param method : method used (default = finite difference, 4th order)
+        @param topo : a predefined topology to discretize invar/outvar
+        @param ghostUpdate : true if this operator has to update its ghost
+        """
+
+        Differential.__init__(self, invar, outvar, resolutions, method=method,
+                              topo=topo, ghosts=ghosts,
+                              ghostUpdate=ghostUpdate, name='Curl')
+
+    @debug
+    def setUp(self):
+        self.pre_setUp()
+        # Create a discrete operator, according to the chosen method
+        # (only finite differences at the time).
+        self.discreteOperator = CurlFD(self.discreteFields[self.invar],
+                                       self.discreteFields[self.outvar],
+                                       method=self.method)
+        self.discreteOperator.setUp()
+        self._isUpToDate = True
+
+
+class Grad(Differential):
+    """
+    Computes \f$ outVar = \nabla inVar \f$
+    """
+
+    @debug
+    def __init__(self, invar, outvar, resolutions, method=None,
+                 topo=None, ghosts=None, ghostUpdate=None):
+        """
+        Create an operator to compute the curl of a field.
+        @param invar : the input vector field
+        @param outvar : curl of input vector field
+        @param resolution : resolution (global) of the fields
+        @param method : method used (default = finite difference, 4th order)
+        @param topo : a predefined topology to discretize invar/outvar
+        @param ghostUpdate : true if this operator has to update its ghost
+        """
+        Differential.__init__(self, invar, outvar, resolutions, method=method,
+                              topo=topo, ghosts=ghosts,
+                              ghostUpdate=ghostUpdate, name='Grad')
+
+    @debug
+    def setUp(self):
+        self.pre_setUp()
+        # Create a discrete operator, according to the chosen method
+        # (only finite differences at the time).
+        self.discreteOperator = GradFD(self.discreteFields[self.invar],
+                                       self.discreteFields[self.outvar],
+                                       method=self.method)
+
+        self.discreteOperator.setUp()
+
+        self._isUpToDate = True
+
+if __name__ == "__main__":
+    print "- Provided class : Curl, Grad"
+    print Curl.__doc__
+    print Grad.__doc__
diff --git a/HySoP/hysop/operator/discrete/curl.py b/HySoP/hysop/operator/discrete/curl.py
deleted file mode 100644
index 78e2e991b709c130dba6289faf1ef342544446c3..0000000000000000000000000000000000000000
--- a/HySoP/hysop/operator/discrete/curl.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-@file discrete/curl.py
-
-Discretisation of the curl operator
-"""
-from parmepy.constants import debug
-from discrete import DiscreteOperator
-from parmepy.tools.timers import timed_function
-from parmepy.numerics.differential_operations import Curl
-
-
-class CurlFD(DiscreteOperator):
-    """
-    Compute the curl of a discrete field.
-    """
-
-    @debug
-    def __init__(self, invar, outvar, method=None):
-        """
-        @param[in] invar : input field
-        @param[in,out] outvar : curl of the input field
-        @param[in] method : how to compute the curl? Default = finite
-        differences, 4th order.
-        """
-        self.invar = invar
-        self.outvar = outvar
-        DiscreteOperator.__init__(self, [self.invar, self.outvar], method)
-        self.input = [self.invar]
-        self.output = [self.outvar]
-        self.curlFunction = Curl(self.invar.topology, self.method)
-
-    @debug
-    @timed_function
-    def apply(self, simulation=None):
-
-        self.curlFunction(self.invar, self.outvar)
-
-
-if __name__ == "__main__":
-    print __doc__
-    print "- Provided class : CurlFD"
-    print CurlFD.__doc__
diff --git a/HySoP/hysop/operator/discrete/differential.py b/HySoP/hysop/operator/discrete/differential.py
new file mode 100644
index 0000000000000000000000000000000000000000..82874f9408dbed18402886fa2f61879f39c7839d
--- /dev/null
+++ b/HySoP/hysop/operator/discrete/differential.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+"""
+@file discrete/differential.py
+
+Discretisation of the differential operators (curl, grad ...)
+"""
+from parmepy.constants import debug
+from discrete import DiscreteOperator
+from parmepy.tools.timers import timed_function
+from parmepy.numerics.differential_operations import Curl, GradV
+import parmepy.tools.numpywrappers as npw
+from abc import ABCMeta, abstractmethod
+
+
+class Differential(DiscreteOperator):
+    __metaclass__ = ABCMeta
+
+    ## @debug
+    ## def __new__(cls, *args, **kw):
+    ##     return object.__new__(cls, *args, **kw)
+
+    @debug
+    @abstractmethod
+    def __init__(self, invar, outvar, method='FD_C_4', name=None):
+        """
+        @param[in] invar : input field
+        @param[in,out] outvar : Grad of the input field.
+        Warning : must be a field with dim * invar.nbcomponents,
+        dim being the domain dimension.
+        @param[in] method : how to compute the grad? Default = finite
+        differences, 4th order.
+        """
+        self.invar = invar
+        self.outvar = outvar
+        DiscreteOperator.__init__(self, [self.invar, self.outvar],
+                                  method=method, name=name)
+        self.input = [self.invar]
+        self.output = [self.outvar]
+        self._dim = self.invar.topology.domain.dimension
+
+
+class CurlFD(Differential):
+    """
+    Compute the curl of a discrete field, using finite differences.
+    """
+
+    @debug
+    def __init__(self, invar, outvar, method=None):
+        """
+        @param[in] invar : input field
+        @param[in,out] outvar : Curl of the input field.
+        Warning : must be a field with dim * invar.nbcomponents,
+        dim being the domain dimension.
+        @param[in] method : how to compute the curl? Default = finite
+        differences, 4th order.
+        """
+        Differential.__init__(self, invar, outvar, method='FD_C_4_work',
+                              name='Curl')
+
+        assert self.outvar.nbComponents == self.invar.nbComponents
+        self._function = Curl(self.invar.topology, self.method)
+        memshape = self.invar.data[0].shape
+        self._work = [npw.zeros(memshape)]
+
+    @debug
+    @timed_function
+    def apply(self, simulation=None):
+
+        self.outvar.data = self._function(self.invar.data,
+                                          self.outvar.data, self._work)
+
+
+class GradFD(Differential):
+    """
+    Compute the grad of a discrete field, using finite differences.
+    """
+
+    @debug
+    def __init__(self, invar, outvar, method='FD_C_4'):
+        """
+        @param[in] invar : input field
+        @param[in,out] outvar : Grad of the input field.
+        Warning : must be a field with dim * invar.nbcomponents,
+        dim being the domain dimension.
+        @param[in] method : how to compute the grad? Default = finite
+        differences, 4th order.
+        """
+        Differential.__init__(self, invar, outvar, method=method, name='Grad')
+        assert self.outvar.nbComponents == self._dim * self.invar.nbComponents
+        self._function = GradV(self.invar.topology, self.method)
+
+    @debug
+    @timed_function
+    def apply(self, simulation=None):
+
+        self.outvar.data = self._function(self.invar.data, self.outvar.data)
+
+if __name__ == "__main__":
+    print __doc__
+    print "- Provided class : CurlFD"
+    print CurlFD.__doc__
diff --git a/HySoP/hysop/operator/discrete/stretching.py b/HySoP/hysop/operator/discrete/stretching.py
index 95c8a1612acf9064ed798460e923cbe27bdfd150..96c2ca7622ce2086b37dea28a6e7917b4a40189b 100755
--- a/HySoP/hysop/operator/discrete/stretching.py
+++ b/HySoP/hysop/operator/discrete/stretching.py
@@ -46,7 +46,6 @@ class ConservativeStretching(DiscreteOperator):
         assert self.velocity.topology == self.vorticity.topology,\
             'Multiresolution case not yet implemented.'
 
-        # We must have a topo for this operator ...
         # A function to compute the gradient of a vector field
         self.divFunc = DivT(self.velocity.topology, method=method,
                             memshape=self.velocity.data[0].shape)
@@ -56,36 +55,35 @@ class ConservativeStretching(DiscreteOperator):
             result = self.divFunc(y, self.velocity.data, result)
             return result
 
-        shape = self.velocity.data[0].shape
+        memshape = self.velocity.data[0].shape
         self.nbc = 3  # Stretching only in 3D and for vector fields.
-        # Todo : check fd call with numpy and/or parmes fields.
+
         # stability constant
         self.cststretch = 0.
         # set time integration method
         if self.method.find('Euler') >= 0:
             self.num_method = Euler
             self.cststretch = 2.0
-            self._workspace = [npw.zeros(shape)
+            self._workspace = [npw.zeros(memshape)
                                for i in xrange(2 * self.nbc)]
         elif self.method.find('RK2') >= 0:
             self.num_method = RK2
             self.cststretch = 2.0
-            self._workspace = [npw.zeros(shape)
+            self._workspace = [npw.zeros(memshape)
                                for i in xrange(2 * self.nbc)]
         elif self.method.find('RK4') >= 0:
             self.num_method = RK4
             self.cststretch = 2.7853
-            self._workspace = [npw.zeros(shape)
+            self._workspace = [npw.zeros(memshape)
                                for i in xrange(3 * self.nbc)]
         else:  # self.method.find('RK3') >= 0:
             self.num_method = RK3
             self.cststretch = 2.5127
-            self._workspace = [npw.zeros(shape)
+            self._workspace = [npw.zeros(memshape)
                                for i in xrange(3 * self.nbc)]
         # Create the time integrator
         self.timeIntegrator = self.num_method(self.nbc, rhs, optim=WITH_GUESS)
         # Prepare buffers used for send/recv operations in time integrator
-        memshape = self.velocity.data[0].shape
         self.timeIntegrator.setUp(self.velocity.topology, memshape)
 
     @timed_function
@@ -107,7 +105,7 @@ class ConservativeStretching(DiscreteOperator):
         self.vorticity.data = self.timeIntegrator(t, self.vorticity.data, dt,
                                                   work=self._workspace,
                                                   result=self.vorticity.data)
-               
+
 
 class GradStretching(DiscreteOperator):
     """
@@ -116,7 +114,7 @@ class GradStretching(DiscreteOperator):
     """
 
     @debug
-    def __init__(self, velocity, vorticity, method=None):
+    def __init__(self, velocity, vorticity, method='FD_C_4'):
         """
         @param velocity : discrete field
         @param vorticity : discrete field
@@ -138,52 +136,54 @@ class GradStretching(DiscreteOperator):
         assert self.velocity.topology == self.vorticity.topology,\
             'Multiresolution case not yet implemented.'
 
-        # We must have a topo for this operator ...
-        # A function to compute the gradient of a vector field
-        self.graduv = GradVxW(self.velocity.topology, method=method)
-        print 'grad UV'
+        memshape = self.velocity.data[0].shape
+        # A function to compute the gradient of a vector field:
+        # grad(V) x vorticity with some diagnostics as output.
+        self.graduv = GradVxW(self.velocity.topology,
+                              method='FD_C_4_diag', memshape=memshape)
 
         # Time integration scheme.
         def rhs(t, y, result):
-            result, diagnostics =\
-                self.graduv(self.velocity.data, y)
-            #result, diag = self.graduv(self.velocity.data, y)
+            result, self.diagnostics =\
+                self.graduv(self.velocity.data, y, result, self.diagnostics)
             return result
 
-        # Todo : check fd call with numpy and/or parmes fields.
+        self.nbc = 3  # Stretching only in 3D and for vector fields.
+
         # stability constant
         self.cststretch = 0.
         # set time integration method
         if self.method.find('Euler') >= 0:
             self.num_method = Euler
             self.cststretch = 2.0
+            self._workspace = [npw.zeros(memshape)
+                               for i in xrange(2 * self.nbc)]
         elif self.method.find('RK2') >= 0:
             self.num_method = RK2
             self.cststretch = 2.0
-        elif self.method.find('RK3') >= 0:
-            self.num_method = RK3
-            self.cststretch = 2.5127
+            self._workspace = [npw.zeros(memshape)
+                               for i in xrange(2 * self.nbc)]
         elif self.method.find('RK4') >= 0:
             self.num_method = RK4
             self.cststretch = 2.7853
-        else:
+            self._workspace = [npw.zeros(memshape)
+                               for i in xrange(3 * self.nbc)]
+        else:  # self.method.find('RK3') >= 0:
             self.num_method = RK3
             self.cststretch = 2.5127
-        shape = self.velocity.data[0].shape
-        self.nbc = 3  # Stretching only in 3D and for vector fields.
-        self._workspace = [npw.zeros(shape)
-                           for i in xrange(3 * self.nbc)]
+            self._workspace = [npw.zeros(memshape)
+                               for i in xrange(3 * self.nbc)]
 
-        ## time integrator
-        self.timeIntegrator = self.num_method(self.vorticity.nbComponents, rhs,
-                                              optim=WITH_GUESS)
-        ## a vector of float with diagnostics computed
-        ## from GradVxW (max div ...)
-        self.diagnostics = npw.ones((5))
+        # Create the time integrator
+        self.timeIntegrator = self.num_method(self.nbc, rhs, optim=WITH_GUESS)
+        # Prepare buffers used for send/recv operations in time integrator
+        self.timeIntegrator.setUp(self.velocity.topology, memshape)
+
+         ## a vector to save diagnostics computed from GradVxW (max div ...)
+        self.diagnostics = npw.ones((2))
 
     @timed_function
     def apply(self, simulation):
-        ind = self.velocity.topology.mesh.iCompute
         if simulation is None:
             raise ValueError("Missing simulation value for computation.")
 
@@ -191,30 +191,22 @@ class GradStretching(DiscreteOperator):
         dt = simulation.timeStep
         # current time
         t = simulation.time
-        #self.diagnostics = self.graduv(self.velocity, self.vorticity, self.diagnostics)[1]
+
         # Compute the number of required subcycles
         ndt, subdt = self.checkStability(dt)
-        # Call time integrator
-        print "time steps ...", dt, subdt
-        print "pre apply Grad...", self.vorticity.data[0].max()
-
         assert sum(subdt) == dt
+
+        # Init workspace with a first evaluation of the
+        # rhs of the integrator
         for i in xrange(ndt):
-            print "Update workspace/Grad, pre", self._workspace[0][ind].max()
-            self._workspace[:self.vorticity.nbComponents] = \
+            self._workspace[:self.nbc] = \
                 self.timeIntegrator.f(t, self.vorticity.data,
-                                      self._workspace
-                                      [:self.vorticity.nbComponents])
-            print "Update workspace/Grad, post", self._workspace[0][ind].max()
+                                      self._workspace[:self.nbc])
             # perform integration and save result in-place
-            self.vorticity.data = self.timeIntegrator(
-                t, self.vorticity.data,
-                subdt[i],
-                work=self._workspace,
-                result=self.vorticity.data)
-            #self.vorticity.data[0], self.vorticity.data[1],\
-            #    self.vorticity.data[2] =\
-            #    self.timeIntegrator(t, self.vorticity.data, subdt[i])
+            self.vorticity.data = \
+                self.timeIntegrator(t, self.vorticity.data, subdt[i],
+                                    work=self._workspace,
+                                    result=self.vorticity.data)
 
     def checkStability(self, dt):
         """
diff --git a/HySoP/hysop/operator/discrete/synchronizeGhosts.py b/HySoP/hysop/operator/discrete/synchronizeGhosts.py
deleted file mode 100644
index 0eff6764f7709d4d2a2d1e546845794a850854a2..0000000000000000000000000000000000000000
--- a/HySoP/hysop/operator/discrete/synchronizeGhosts.py
+++ /dev/null
@@ -1,493 +0,0 @@
-"""
-@file operator/discrete/synchronizeGhosts.py
-
-Update ghost points for some fields defined on a specific topology.
-"""
-from parmepy.constants import debug, ORDER, PARMES_INTEGER, PARMES_REAL
-from parmepy.mpi.main_var import main_comm, main_rank
-from discrete import DiscreteOperator
-from parmepy.tools.timers import timed_function
-import numpy as np
-
-
-class SynchronizeGhosts_d(DiscreteOperator):
-    """
-    Ghost points synchronization.
-    """
-
-    @debug
-    def __init__(self, fieldslist, topology, transferMethod='greaterSend'):
-        """
-        Defines a way to send/recv values at ghosts points for a list
-        of fields, discretized on a given topology.
-
-        @param  fieldslist : a list of fields
-        @param topology : the topology common to all fields.
-        @param transferMethod : which type of exchange is used.
-        """
-        DiscreteOperator.__init__(self, fieldslist, method=transferMethod,
-                                  name="Ghosts Synchronization")
-        self.input = fieldslist
-        self.output = fieldslist
-        self.compute_time = 0.
-        self.fieldslist = fieldslist
-        self.topology = topology
-        if (main_rank == 0):
-            print 'CUT SPACE', self.topology.dims
-        self.transferMethod = transferMethod
-
-    @debug
-    def setUp(self):
-
-        self.topoMPI = \
-            self.topology.comm.Create_cart(
-                self.topology.dims,
-                periods=self.topology.periods)
-        ghosts = self.topology.ghosts
-        resolution = self.topology.mesh.resolution
-        self.fieldslist = np.asarray([self.fieldslist])
-        if (self.transferMethod == 'SendRecv'):
-            # Allocation of space for reciev data
-            self.dataRecvX = np.zeros((
-                ghosts[0], resolution[1], resolution[2]),
-                dtype=PARMES_REAL, order=ORDER)
-            self.dataRecvY = np.zeros((
-                resolution[0], ghosts[1], resolution[2]),
-                dtype=PARMES_REAL, order=ORDER)
-            self.dataRecvZ = np.zeros((
-                resolution[0], resolution[1], ghosts[2]),
-                dtype=PARMES_REAL, order=ORDER)
-            self.SendRecvList = np.zeros(
-                self.topology.dim * 2,
-                order=ORDER, dtype=PARMES_INTEGER)
-            self.SendRecvList[0], self.SendRecvList[1] = \
-                self.topology.Shift(0, 1)
-            self.SendRecvList[2], self.SendRecvList[3] = \
-                self.topology.Shift(1, 1)
-            if (self.topology.dim > 2):
-                self.SendRecvList[4], self.SendRecvList[5] = \
-                    self.topology.Shift(2, 1)
-
-        if (self.transferMethod == 'greaterSend'):
-            tab = self.topology.neighbours
-            self.tabSort = np.zeros(
-                [self.topology.dim * 2, 2],
-                order=ORDER, dtype=PARMES_INTEGER)
-            self.tabSort[:, 1] = range(self.topology.dim * 2)
-            self.tabSort[0, 0] = tab[0, 0]
-            self.tabSort[1, 0] = tab[1, 0]
-            self.tabSort[2, 0] = tab[0, 1]
-            self.tabSort[3, 0] = tab[1, 1]
-            if(self.topology.dim > 2):
-                self.tabSort[4, 0] = tab[0, 2]
-                self.tabSort[5, 0] = tab[1, 2]
-            tabSort1 = self.tabSort[self.tabSort[:, 0] <= main_rank]
-            tabSort2 = self.tabSort[self.tabSort[:, 0] > main_rank]
-            if (np.asarray(tabSort1[:, 0].shape) > 0):
-                tabSort1 = tabSort1[tabSort1[:, 0].argsort()]
-            if (np.asarray(tabSort2[:, 0].shape) > 0):
-                tabSort2 = tabSort2[tabSort2[:, 0].argsort()]
-                tabSort2 = self.TabInvSort(tabSort2)
-            self.tabSort = np.concatenate((tabSort1, tabSort2))
-
-        if ((self.transferMethod == 'greaterSend') or
-                (self.transferMethod == 'SendRecv')):
-            # Allocation of space for send and reciev data
-            self.dataSendX = np.zeros((
-                ghosts[0], resolution[1], resolution[2]),
-                dtype=PARMES_REAL, order=ORDER)
-            self.dataSendY = np.zeros((
-                resolution[0], ghosts[1], resolution[2]),
-                dtype=PARMES_REAL, order=ORDER)
-            self.dataSendZ = np.zeros((
-                resolution[0], resolution[1], ghosts[2]),
-                dtype=PARMES_REAL, order=ORDER)
-        # 1 - get discrete fields arrays
-        # 2 - get list of ghosts area
-        # 3 - get neighbours
-        # 4 - find what is to be send/recv, the size of the arrays and
-        # allocate buffers if required
-        # 5 - set send/recv order
-        #self.discreteOperator.setUp()
-
-    @debug
-    @timed_function
-    def apply(self, simulation=None):
-        self.resolution = self.topology.mesh.resolution
-        resolution = self.topology.mesh.resolution
-        ghosts = self.topology.ghosts
-        dim = self.topology.dim
-        # Do the send/recv as defined in setup.
-        #### if args is None: \todo : A verifier.
-#        args = self.fieldslist
-#        self.fieldslist = np.asarray([self.fieldslist])
-        if (self.transferMethod == 'SendRecv'):
-            for f in fieldslist:
-                # DOWN
-                if (main_rank != self.SendRecvList[0]):
-                    self.dataSendZ = f[j][:, :, ghosts[2]:2. * ghosts[2]]
-                    main_comm.Sendrecv(
-                        self.dataSendZ,
-                        dest=self.SendRecvList[0],
-                        sendtag=22,
-                        recvbuf=self.dataRecvZ,
-                        source=main_rank,
-                        recvtag=11, status=None)
-                    f[j][:, :, resolution[2] - ghosts[2]: resolution[2]] = \
-                        self.dataRecvZ
-                else:
-                    f[j][:, :, resolution[2] - ghosts[2]: resolution[2]
-                         ] = f[j][:, :, ghosts[2]:2 * ghosts[2]]
-                # UP
-                if (main_rank != self.SendRecvList[1]):
-                    self.dataSendZ = np.array(np.copy(f[j][
-                        :, :,
-                        resolution[2] - ghosts[2]:resolution[2]],
-                        order=ORDER, dtype=PARMES_REAL))
-                    main_comm.Sendrecv(
-                        self.dataSendZ,
-                        dest=self.SendRecvList[1],
-                        sendtag=11,
-                        recvbuf=self.dataRecvZ,
-                        source=main_rank,
-                        recvtag=22, status=None)
-                else:
-                    f[j][:, :, ghosts[2]:2 * ghosts[2]
-                         ] = \
-                        f[j][:, :, resolution[2] - ghosts[2]:resolution[2]]
-                # SOUTH
-                if (main_rank != self.SendRecvList[2]):
-                    self.dataSendY = f[j][:, ghosts[1]:2. * ghosts[1], :]
-                    main_comm.Sendrecv(
-                        self.dataSendY,
-                        dest=self.SendRecvList[2],
-                        sendtag=44,
-                        recvbuf=self.dataRecvY,
-                        source=main_rank,
-                        recvtag=33, status=None)
-                    f[j][:, resolution[2] - ghosts[2]:resolution[2], :] \
-                        = self.dataRecvY
-                else:
-                    f[j][:, resolution[1] - ghosts[1]:resolution[1], :
-                         ] = f[j][:, ghosts[1]:2 * ghosts[1], :]
-                # NORTH
-                if (main_rank != self.SendRecvList[3]):
-                    self.dataSendY = np.array(np.copy(f[j][
-                        :,
-                        resolution[1] - ghosts[1]:resolution[1],
-                        :],
-                        order=ORDER, dtype=PARMES_REAL))
-                    main_comm.Sendrecv(
-                        self.dataSendY,
-                        dest=self.SendRecvList[3],
-                        sendtag=33,
-                        recvbuf=self.dataRecvY,
-                        source=main_rank,
-                        recvtag=44, status=None)
-                else:
-                    f[j][:, ghosts[1]:2 * ghosts[1], :] =\
-                        f[j][:, resolution[1] - ghosts[1]:resolution[1], :]
-                # EAST
-                if (main_rank != self.SendRecvList[4]):
-                    self.dataSendX = f[j][ghosts[0]:2. * ghosts[0], :, :]
-                    main_comm.Sendrecv(
-                        self.dataSendX,
-                        dest=self.SendRecvList[4],
-                        sendtag=66,
-                        recvbuf=self.dataRecvX,
-                        source=main_rank,
-                        recvtag=55, status=None)
-                    f[j][resolution[0] - ghosts[0]:resolution[0], :, :] \
-                        = self.dataRecvX
-                else:
-                    f[j][resolution[0] - ghosts[0]:resolution[0], :, :
-                         ] = f[j][:, :, ghosts[2]:2 * ghosts[2]]
-                # WEST
-                if (main_rank != self.SendRecvList[5]):
-                    self.dataSendX = np.array(np.copy(f[j][
-                        resolution[0] - ghosts[0]:resolution[0],
-                        :, :],
-                        order=ORDER, dtype=PARMES_REAL))
-                    main_comm.Sendrecv(
-                        self.dataSendX,
-                        dest=self.SendRecvList[5],
-                        sendtag=55,
-                        recvbuf=self.dataRecvX,
-                        source=main_rank,
-                        recvtag=66, status=None)
-                else:
-                    f[j][ghosts[0]:2 * ghosts[0], :, :] =\
-                        f[j][resolution[0] - ghosts[0]:resolution[0], :, :]
-
-        if (self.transferMethod == 'greaterSend'):
-            for f in self.fieldslist:
-#                print 'tabsort', main_rank, self.tabSort
-                for i in xrange(self.tabSort[:, 0].shape[0]):
-#                    print 'Cours', main_rank, self.tabSort[i, :]
-                    if (main_rank == self.tabSort[i, 0]):
-                        ## Without communication
-                        # WEST
-                        if (self.tabSort[i, 1] == 0):
-                            for j in xrange(dim):
-                                #print '\nTEST', resolution,  f[j][...].shape, '\t' , ghosts
-                                f[j][resolution[0] - ghosts[0]: resolution[0],
-                                     :, :] =\
-                                    f[j][ghosts[0]:2 * ghosts[0], :, :]
-                        # EAST
-                        if (self.tabSort[i, 1] == 1):
-                            for j in xrange(dim):
-                                f[j][0:ghosts[0], :, :] =\
-                                    f[j][
-                                        resolution[0] - 2 *
-                                        ghosts[0]:resolution[0] - ghosts[0],
-                                        :, :]
-
-                        # SOUTH
-                        if (self.tabSort[i, 1] == 2):
-                            for j in xrange(dim):
-                                f[j][:, resolution[1] -
-                                     ghosts[1]:resolution[1], :] =\
-                                    f[j][:, ghosts[1]:2 * ghosts[1], :]
-                        #NORTH
-                        if(self.tabSort[i, 1] == 3):
-                            for j in xrange(dim):
-                                f[j][:, 0:ghosts[1], :] =\
-                                    f[j][
-                                        :,
-                                        resolution[1] - 2 *
-                                        ghosts[1]:resolution[1] - ghosts[1],
-                                        :]
-
-                        # DOWN
-                        if(self.tabSort[i, 1] == 4):
-                            for j in xrange(dim):
-                                f[j][:, :, resolution[2] -
-                                     ghosts[2]:resolution[2]] =\
-                                    f[j][:, :, ghosts[2]:2 * ghosts[2]]
-                        # UP
-                        if(self.tabSort[i, 1] == 5):
-                            for j in xrange(dim):
-                                f[j][:, :, 0:ghosts[2]] =\
-                                    f[j][
-                                        :, :,
-                                        resolution[2] - 2 *
-                                        ghosts[2]:resolution[2] - ghosts[2]]
-#                        print 'ok', main_rank, self.tabSort[i, :]
-                    else:
-                       ### PART COMMUNICATION
-                        # WEST
-                        if(self.tabSort[i, 1] == 0):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.WESTsend(self.tabSort[i, 0], f)
-                            else:
-                                self.WESTrecv(self.tabSort[i, 0], f)
-                        # EST
-                        if (self.tabSort[i, 1] == 1):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.EASTsend(self.tabSort[i, 0], f)
-                            else:
-                                self.EASTrecv(self.tabSort[i, 0], f)
-                        # SOUTH
-                        if(self.tabSort[i, 1] == 2):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.SOUTHsend(self.tabSort[i, 0], f)
-                            else:
-                                self.SOUTHrecv(self.tabSort[i, 0], f)
-                        # NORTH
-                        if (self.tabSort[i, 1] == 3):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.NORTHsend(self.tabSort[i, 0], f)
-                            else:
-                                self.NORTHrecv(self.tabSort[i, 0], f)
-                        # DOWN
-                        if (self.tabSort[i, 1] == 4):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.DOWNsend(self.tabSort[i, 0], f)
-                            else:
-                                self.DOWNrecv(self.tabSort[i, 0], f)
-                        # UP
-                        if (self.tabSort[i, 1] == 5):
-                            if (main_rank < self.tabSort[i, 0]):
-                                self.UPsend(self.tabSort[i, 0], f)
-                            else:
-                                self.UPrecv(self.tabSort[i, 0], f)
-#                        print 'ok', main_rank, self.tabSort[i, :]
-#        return self.discreteOperator.apply(*args)
-
-    def TabInvSort(self, tab):
-        tmp = tab[0, 0]
-        deb = 0
-        tabcont = 0
-        tabfinal = np.copy(tab)
-        if tab[:, 0].shape[0] == 1:
-            return tab
-        for i in xrange(1, tab[:, 0].shape[0]):
-            if tmp == tab[i, 0]:
-                tabcont = tabcont + 1
-            else:
-                tmp = tab[i, 0]
-                if tabcont == 0:
-                    tabfinal[deb, :] = tab[deb, :]
-                else:
-                    tabNew = tab[deb:i, :]
-#                    for l in xrange(int(tabNew[:,1].shape[0] / 2)):
-#                        tmp = tabNew[2 * l, 1]
-#                        tabNew[2 * l, 1] = tabNew[2 * l + 1,1]
-#                        tabNew[2 * l + 1, 1] = tmp
-                    tabNew = tabNew[np.invert(tabNew[:, 1].argsort())]
-                    tabfinal[deb:i, :] = tabNew
-                deb = i
-                tabcont = 0
-                if deb == tab[:, 0].shape[0]:
-                    tabfinal[deb, :] = tab[deb, :]
-        if tabcont > 0:
-            tabNew = tab[deb:tab[:, 0].shape[0], :]
-            tabNew = tabNew[np.invert(tabNew[:, 1].argsort())]
-            tabfinal[deb:tab[:, 0].shape[0], :] = tabNew
-        return tabfinal
-
-    def WESTsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendX = np.array(np.copy(listFields[i][
-                ghosts[0]:ghosts[0] * 2, :, :]), order=ORDER)
-            main_comm.Ssend(self.dataSendX, dest=proc, tag=66)
-            main_comm.Recv(self.dataSendX, source=proc, tag=55)
-            listFields[i][0:ghosts[0], :, :] = self.dataSendX
-
-    def EASTsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendX = np.array(np.copy(listFields[i][
-                resolution[0] - 2 * ghosts[0]:resolution[0] - ghosts[0],
-                :, :]),
-                order=ORDER)
-            main_comm.Ssend(self.dataSendX, dest=proc, tag=66)
-            main_comm.Recv(self.dataSendX, source=proc, tag=55)
-            listFields[i][resolution[0] - ghosts[0]:resolution[0], :, :] =\
-                self.dataSendX
-
-    def SOUTHsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendY = np.array(np.copy(listFields[i][
-                :, ghosts[1]:2 * ghosts[1], :]), order=ORDER)
-            main_comm.Ssend(self.dataSendY, dest=proc, tag=44)
-            main_comm.Recv(self.dataSendY, source=proc, tag=33)
-            listFields[i][:, 0:ghosts[1], :] = self.dataSendY
-
-    def NORTHsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendY = np.array(np.copy(listFields[i][
-                :,
-                resolution[1] - 2 * ghosts[1]:resolution[1] - ghosts[1], :]),
-                order=ORDER)
-            main_comm.Ssend(self.dataSendY, dest=proc, tag=33)
-            main_comm.Recv(self.dataSendY, source=proc, tag=44)
-            listFields[i][:, resolution[1] - ghosts[1]:resolution[1], :] =\
-                self.dataSendY
-
-    def DOWNsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendZ = np.array(np.copy(listFields[i][
-                :, :, ghosts[2]:2 * ghosts[2]]), order=ORDER)
-            main_comm.Ssend(self.dataSendZ, dest=proc, tag=11)
-            main_comm.Recv(self.dataSendZ, source=proc, tag=22)
-            listFields[i][:, :, 0:ghosts[2]] = self.dataSendZ
-
-    def UPsend(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            self.dataSendZ = np.array(np.copy(listFields[i][
-                :, :,
-                resolution[2] - 2 * ghosts[2]:resolution[2] - ghosts[2]
-            ]), order=ORDER)
-            main_comm.Ssend(self.dataSendZ, dest=proc, tag=22)
-            main_comm.Recv(self.dataSendZ, source=proc, tag=11)
-            listFields[i][
-                :, :,
-                resolution[2] - ghosts[2]:resolution[2]] =\
-                self.dataSendZ
-
-    def WESTrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendX, source=proc, tag=66)
-            listFields[i][0:ghosts[0], :, :] = self.dataSendX
-            self.dataSendX = np.array(np.copy(listFields[i][
-                ghosts[0]:2 * ghosts[0], :, :]), order=ORDER)
-            main_comm.Ssend(self.dataSendX, dest=proc, tag=55)
-
-    def EASTrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendX, source=proc, tag=66)
-            listFields[i][resolution[0] - ghosts[0]:resolution[0], :, :] =\
-                self.dataSendX
-            self.dataSendX = np.array(np.copy(listFields[i][
-                resolution[0] - 2 * ghosts[0]:resolution[0] - ghosts[0],
-                :, :]),
-                order=ORDER)
-            main_comm.Ssend(self.dataSendX, dest=proc, tag=55)
-
-    def SOUTHrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendY, source=proc, tag=33)
-            listFields[i][:, 0:ghosts[1], :] = self.dataSendY
-            self.dataSendY = np.array(np.copy(listFields[i][
-                :, ghosts[1]:2 * ghosts[1], :]), order=ORDER)
-            main_comm.Ssend(self.dataSendY, dest=proc, tag=44)
-
-    def NORTHrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendY, source=proc, tag=44)
-            listFields[i][:, resolution[1] - ghosts[1]:resolution[1], :] =\
-                self.dataSendY
-            self.dataSendY = np.array(np.copy(listFields[i][
-                :, resolution[1] - 2 * ghosts[1]:resolution[1] -
-                ghosts[1], :]),
-                order=ORDER)
-            main_comm.Ssend(self.dataSendY, dest=proc, tag=33)
-
-    def DOWNrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendZ, source=proc, tag=22)
-            listFields[i][:, :, 0:ghosts[2]] = self.dataSendZ
-            data = np.array(np.copy(listFields[i][
-                :, :, ghosts[2]:ghosts[2] * 2]), order=ORDER)
-            main_comm.Ssend(self.dataSendZ, dest=proc, tag=11)
-
-    def UPrecv(self, proc, listFields):
-        ghosts = self.topology.ghosts
-        resolution = self.resolution
-        for i in xrange(self.topology.dim):
-            main_comm.Recv(self.dataSendZ, source=proc, tag=11)
-            listFields[i][:, :, resolution[2] - ghosts[2]:resolution[2]] =\
-                self.dataSendZ
-            self.dataSendZ = np.array(np.copy(listFields[i][
-                :, :,
-                resolution[2] - 2 * ghosts[2]:resolution[2] - ghosts[2]
-            ]), order=ORDER)
-            main_comm.Ssend(self.dataSendZ, dest=proc, tag=22)
-
-
-if (__name__ == "__main__"):
-    print __doc__
-    print "- Provided class : SynchronizeGhosts"
-    print SynchronizeGhosts_d.__doc__
diff --git a/HySoP/hysop/operator/energy_enstrophy.py b/HySoP/hysop/operator/energy_enstrophy.py
index ad2a8623a05a221f528ba7298907df9eb87d432e..b12115b85a7b12ade43836477dbe9381a6a3c564 100644
--- a/HySoP/hysop/operator/energy_enstrophy.py
+++ b/HySoP/hysop/operator/energy_enstrophy.py
@@ -4,7 +4,7 @@
 Compute Energy and Enstrophy
 """
 import numpy as np
-from parmepy.constants import debug  # , PARMES_MPI_REAL
+from parmepy.constants import debug, XDIR  # , PARMES_MPI_REAL
 from parmepy.operator.monitors.monitoring import Monitoring
 from parmepy.mpi import MPI
 from parmepy.tools.timers import timed_function
@@ -113,8 +113,9 @@ class Energy_enstrophy(Monitoring):
         # get the list of computation points (no ghosts)
         nbc = vd.nbComponents
         # Integrate (locally) velocity ** 2
+        self._work[...] = vd[XDIR][self.ind] ** 2
         [np.add(self._work[...], vd[i][self.ind] ** 2, self._work[...])
-         for i in xrange(nbc)]
+         for i in xrange(1, nbc)]
         local_energy = np.sum(self._work)
 
         # --- Enstrophy computation ---
diff --git a/HySoP/hysop/operator/stretching.py b/HySoP/hysop/operator/stretching.py
index 956bc5f39ee787ffd1eaefb38c243bf6eb7dd4f5..51151730b2200af8b760c051e1f0bf8b1ad4beb0 100755
--- a/HySoP/hysop/operator/stretching.py
+++ b/HySoP/hysop/operator/stretching.py
@@ -36,6 +36,8 @@ class Stretching(Operator):
         @param topo : a predefined topology to discretize velocity/vorticity
         @param ghosts : number of ghosts points. Default depends on the method.
         Autom. computed if not set.
+        @param ghostUpdate : true if this operator has to update its ghost
+        points.
         """
         Operator.__init__(self, [velocity, vorticity], method, topo=topo,
                           ghosts=ghosts, name="Stretching")
@@ -56,8 +58,9 @@ class Stretching(Operator):
             self.formulation = formulation
         else:
             self.formulation = CONSERVATIVE
-        ## Do this operator deals with ghost points update?
-        ## default = yes
+        ## If ghostupdate == True, the operator will manage
+        ## ghost points update. Else, this must be done somewhere else ...
+        ## Default = yes
         if ghostUpdate is None:
             self.ghostUpdate = True
         else:
@@ -122,9 +125,8 @@ class Stretching(Operator):
 
     def apply(self, simulation=None):
         # update ghost points, if required, for velocity and vorticity
-        #if self.synchronize is not None:
-        #    print 'synchr ...'
-        self.synchronize.apply()
+        if self.synchronize is not None:
+            self.synchronize.apply()
         # computation ...
         self.discreteOperator.apply(simulation)
         #if self.synchronize is not None:
diff --git a/HySoP/hysop/operator/synchronizeGhosts.py b/HySoP/hysop/operator/synchronizeGhosts.py
deleted file mode 100644
index 652a8e99ab68e4a9e9594e4ed5cc6a386210f69d..0000000000000000000000000000000000000000
--- a/HySoP/hysop/operator/synchronizeGhosts.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""
-@file operator/synchronizeGhosts.py
-
-Update ghost points for some fields defined on a specific topology.
-"""
-from parmepy.operator.continuous import Operator
-from parmepy.operator.discrete.synchronizeGhosts import SynchronizeGhosts_d
-from parmepy.constants import debug
-from parmepy.fields.vector import VectorField
-from parmepy.fields.scalar import ScalarField
-
-class SynchronizeGhosts(Operator):
-    """
-    Ghost points synchronization.
-    """
-
-    @debug
-    def __init__(self, fieldslist, resolution=None,
-                 method='', topology=None, **other_config):
-        """
-        Defines a way to send/recv values at ghosts points for a list
-        of fields, discretized on a given topology.
-
-        @param  fieldslist : a list of fields
-        """
-        if isinstance(fieldslist, list):
-            Operator.__init__(self, fieldslist, method,
-                              name="Ghost Synchronization")
-        else:
-            Operator.__init__(self, [fieldslist], method,
-                              name="Ghost Synchronization")
-        self.fieldslist = fieldslist
-        self.resolution = resolution
-        self.method = method
-        self.topology = topology
-        self.config = other_config
-
-    @debug
-    def setUp(self, ghosts=None):
-        """
-        SynchroGhost operator discretization method.
-        Create an discrete SynchroGhost operator from given specifications.
-
-        """
-        Operator.setUp(self)
-        for v in self.variables:
-        # the topology for v ...
-            if self.topology is not None:
-                topo = self.topology
-            else:
-                if ghosts is None:
-                    topo = self.domain.getOrCreateTopology(
-                        self.domain.dimension,
-                        self.resolution[v])
-                else:
-                    topo = self.domain.getOrCreateTopology(
-                        self.domain.dimension,
-                        self.resolution[v],
-                        ghosts=ghosts)
-                topo.ghosts = ghosts
-            # ... and the corresponding discrete field
-                if v.__class__ is VectorField or v.__class__ is ScalarField:
-                    self.discreteOperator = \
-                        SynchronizeGhosts_d(v, topo, self.method)
-                else:
-                    self.discreteFields[v] = v.discretize(topo)
-                    self.discreteOperator = \
-                        SynchronizeGhosts_d(self.discreteFields[v],
-                        topo, self.method)
-
-        self.discreteOperator.setUp()
-        self._isUpToDate = True
-
-
-if (__name__ == "__main__"):
-    print __doc__
-    print "- Provided class : SynchronizeGhosts"
-    print SynchronizeGhosts.__doc__