From bb745d01f721d1df8b138fb884191b8d0cbc846b Mon Sep 17 00:00:00 2001
From: Jean-Matthieu Etancelin <jean-matthieu.etancelin@imag.fr>
Date: Tue, 10 Jul 2012 16:06:21 +0000
Subject: [PATCH] parmepy get back pure python solver workflow. (Need pure
 python code for advection and remeshing. Need GPU solver.)

---
 Examples/mainJM.py                            |  70 +++------
 HySoP/hysop/ParticularSolvers/basic.py        | 145 ++++++++---------
 .../interpolation/interpolation.py            |   2 -
 .../hysop/ParticularSolvers/remesh/method.py  |   1 -
 HySoP/hysop/__init__.py.in                    |  30 +++-
 HySoP/hysop/constants.py                      |   4 +-
 HySoP/hysop/domain/box.py                     |   8 +-
 HySoP/hysop/domain/grid.py                    |   1 +
 HySoP/hysop/fields/analytical.py              |  28 ++--
 HySoP/hysop/fields/continuous.py              |  17 +-
 HySoP/hysop/fields/discrete.py                |  50 +++---
 HySoP/hysop/fields/topology.py                |  31 ++--
 HySoP/hysop/operator/RemeshingDOp.py          | 113 --------------
 HySoP/hysop/operator/Transport.py             |   2 +-
 HySoP/hysop/operator/advection_d.py           |  29 ++--
 HySoP/hysop/operator/continuous.py            |   3 +
 HySoP/hysop/operator/discrete.py              |  35 ++++-
 HySoP/hysop/operator/remeshing.py             | 105 +++++++++++++
 HySoP/hysop/operator/splitting.py             |  55 +++++++
 HySoP/hysop/problem/problem.py                |  36 +++--
 HySoP/hysop/tools/__init__.py                 |   0
 HySoP/hysop/tools/printer.py                  | 147 +++++++++---------
 HySoP/hysop/tools/timer.py                    |  43 +++++
 HySoP/setup.py.in                             |  36 +++--
 24 files changed, 565 insertions(+), 426 deletions(-)
 delete mode 100644 HySoP/hysop/operator/RemeshingDOp.py
 create mode 100644 HySoP/hysop/operator/remeshing.py
 create mode 100644 HySoP/hysop/operator/splitting.py
 create mode 100644 HySoP/hysop/tools/__init__.py
 create mode 100644 HySoP/hysop/tools/timer.py

diff --git a/Examples/mainJM.py b/Examples/mainJM.py
index 31370b43b..4723fbfec 100644
--- a/Examples/mainJM.py
+++ b/Examples/mainJM.py
@@ -1,25 +1,29 @@
 # -*- coding: utf-8 -*-
 import time
 import parmepy as pp
+from math import *
 
 
-def vitesse(x):
-    return [1., 1., 1.]
+def vitesse(x, y, z):
+    vx = 1. + x
+    vy = - x * y
+    vz = x * y * z + 10.
+    return vx, vy, vz
 
 
-def scalaire(x):
-    if x[0] < 0.5 and x[1] < 0.5 and x[2] < 0.5:
+def scalaire(x, y, z):
+    if x < 0.5 and y < 0.5 and z < 0.5:
         return 1.
     else:
         return 0.
 
 
 def run():
-    # Parameter
-    # timeStep = 0.02
-    # FinalTime = 1.
-    # outputFilePrefix = './res/RK2_'
-    # outputModulo = 0
+    # Parameters
+    timeStep = 0.02
+    finalTime = 1.
+    outputFilePrefix = './res/RK2_'
+    outputModulo = 0
 
     t0 = time.time()
 
@@ -27,10 +31,10 @@ def run():
     box = pp.Box(3, length=[1., 1., 1.], origin=[0., 0., 0.])
 
     ## Fields
-    scal = pp.ContinuousField(domain=box, name='Scalar')
-    velo = pp.ContinuousField(domain=box, name='Velocity', vector=True)
+    scal = pp.AnalyticalField(domain=box, formula=scalaire, name='Scalar')
+    velo = pp.AnalyticalField(domain=box, formula=vitesse, name='Velocity', vector=True)
 
-    ## Operator
+    ## Operators
     advec = pp.Transport(velo, scal)
 
     ## Solver creation (discretisation of objects is done in solver initialisation)
@@ -40,49 +44,21 @@ def run():
     pb = pp.Problem(topo3D, [advec])
 
     ## Setting solver to Problem
-    pb.setSolver(pp.ParticularSolver)
+    pb.setSolver(pp.ParticularSolver, finalTime, timeStep)
 
     # ## Setting io to Problem
-    # pb.setSolver(pp.Printer(...))
+    pb.setIO(pp.Printer(fields=[scal, velo], frequency=outputModulo, outputPrefix=outputFilePrefix))
 
     t1 = time.time()
 
-    # ## Solve problem
-    # pb.solve(T=FinalTime, dt=timeStep)
+    ## Solve problem
+    pb.solve()
 
-    # tf = time.time()
+    tf = time.time()
 
-    print pb
-    print "\n TODO : -terminer l'initialisation du solver (opérateurs) \n\t -Ajouter les opérateurs annexes (timer et io) au probleme \n\t -Ecrire méthode de résolution"
-
-    # print "Total time : ", tf - t0, "sec (CPU)"
+    print "Total time : ", tf - t0, "sec (CPU)"
     print "Init time : ", t1 - t0, "sec (CPU)"
-    # print "Solving time : ", tf - t1, "sec (CPU)"
-
-
-    # InterpolationMethod = pp.Linear(grid=box.discreteDomain, gvalues=velo.discreteVariable)
-    # RemeshingMethod = pp.M6Prime(grid=box.discreteDomain, gvalues=scal.discreteVariable)
-    # ODESolver = pp.RK2(InterpolationMethod, box.discreteDomain.applyConditions)
-    # ## cpu
-    # #solver = pp.ParticularSolver(cTspPb, ODESolver, InterpolationMethod, RemeshingMethod)
-    # ## gpu
-    # solver = pp.GPUParticularSolver(cTspPb,
-    #                                 ODESolver, InterpolationMethod, RemeshingMethod,
-    #                                 device_type='gpu', src='./examples/mainJM_kernels.cl'
-    #     )
-    # #solver = pp.GPUParticularSolver_GLRender(cTspPb, ODESolver, InterpolationMethod, RemeshingMethod, device_type='gpu', dt=timeStep)
-    # cTspPb.setSolver(solver)
-    # cTspPb.setPrinter(pp.Printer(frequency=outputModulo, outputPrefix=outputFilePrefix, problem=cTspPb))
-
-    # t1 = time.time()
-
-    # cTspPb.solve(T=FinalTime, dt=timeStep)
-
-    # tf = time.time()
-
-    # print "Total time : ", tf - t0, "sec (CPU)"
-    # print "Init time : ", t1 - t0, "sec (CPU)"
-    # print "Solving time : ", tf - t1, "sec (CPU)"
+    print "Solving time : ", tf - t1, "sec (CPU)"
 
 
 if __name__ == "__main__":
diff --git a/HySoP/hysop/ParticularSolvers/basic.py b/HySoP/hysop/ParticularSolvers/basic.py
index d6f7189b1..16ffa8a14 100644
--- a/HySoP/hysop/ParticularSolvers/basic.py
+++ b/HySoP/hysop/ParticularSolvers/basic.py
@@ -5,6 +5,11 @@ Particular solver description.
 """
 from solver import Solver
 from ..fields.continuous import ContinuousField
+from ..operator.Transport import Transport
+from ..operator.remeshing import Remeshing
+from ..operator.splitting import Splitting
+from ..tools.timer import Timer
+from ..tools.printer import Printer
 
 
 class ParticularSolver(Solver):
@@ -12,76 +17,41 @@ class ParticularSolver(Solver):
     Particular solver description.
     Link with differents numericals methods used.
     """
-    def __init__(self, problem,
-                 ODESolver = None,
-                 InterpolationMethod = None,
-                 RemeshingMethod = None,
-                 splittingMethod='strang'):
+    def __init__(self, problem, t_end, dt,
+                 ODESolver=None,
+                 InterpolationMethod=None,
+                 RemeshingMethod=None,
+                 splittingMethod='strang',
+                 timer=None,
+                 io=None):
         """
         Constructor.
         Create a solver description.
         """
         Solver.__init__(self, problem)
         self.problem = problem
-        self.p_position = ContinuousField(domain=problem.domains[0], name='Particle Position')
-        self.p_scalar = ContinuousField(domain=problem.domains[0], name='Particle Scalar')
-        self.problem.addVariable([self.p_position, self.p_scalar])
-        # self.discreteProblem = problem.discreteProblem
-        # ## ODE Solver method.
-        # self.ODESolver = ODESolver
-        # ## Interpolation method.
-        # self.InterpolationMethod = InterpolationMethod
-        # ## Remeshing method.
-        # self.RemeshingMethod = RemeshingMethod
-        # ## Splitting Method
-        # self.splittingMethod = splittingMethod
-        # self.dim = self.discreteProblem.domains[0].dimension
-        # self.grid = self.discreteProblem.domains[0]
-        # self.gvelo = self.discreteProblem.advecOp.velocity
-        # self.gscal = self.discreteProblem.advecOp.scalar
-        # self.parts = ParticleField(self.grid)
-        # self.ppos = DiscreteVariable(domain=self.parts, dimension=self.gvelo.dimension, name="Particle position")
-        # self.parts.setPositions(self.ppos)
-        # self.pvelo = DiscreteVariable(domain=self.parts, dimension=self.gvelo.dimension, name="Particle velocity")
-        # self.pscal = DiscreteVariable(domain=self.parts, dimension=self.gscal.dimension, scalar=True, name="Particle scalar")
-        # #self.pbloc = DiscreteVariable(domain=self.parts, dimension=1, integer=True, initialValue=lambda x: 0, scalar=True)
-        # #self.ptag = DiscreteVariable(domain=self.parts, dimension=1, integer=True, initialValue=lambda x: 0, scalar=True)
-        # # Interpolation : particles positions, grid velocity -> particles velocity
-        # interpol = InterpolationDOp(position=self.ppos,
-        #                             velocityField=self.discreteProblem.advecOp.velocity,
-        #                             resvelo=self.pvelo,
-        #                             method=self.InterpolationMethod)
-        # if isinstance(self.RemeshingMethod, Lambda2):
-        #     # Tag particles : particles positions, particles velocities -> particles bloc, particles Tag
-        #     tag = TagDOp(partPositions=self.ppos,
-        #                  partVelocities=self.pvelo,
-        #                  grid=self.discreteProblem.domains[0],
-        #                  resbloc=self.pbloc,
-        #                  restag=self.ptag)
-        # # Remeshing : particles positions, particles scalar, particles tag, particles bloc -> grid scalar
-        # self.remesh = RemeshingDOp(partPositions=self.ppos,
-        #                       partScalar=self.pscal,
-        #                       resscal=self.discreteProblem.advecOp.scalar,
-        #                       method=self.RemeshingMethod)
-        # # Advection : grid position, grid velocity, grid scalar -> particles position, particles scalar
-        # self.discreteProblem.advecOp.setResultVariable(respos=self.ppos, resscal=self.pscal)
-        # self.discreteProblem.advecOp.setMethod(self.ODESolver)
-        # if isinstance(self.RemeshingMethod, Lambda2):
-        #     self.discreteProblem.addOperator([interpol, tag, self.remesh])
-        # else:
-        #     self.discreteProblem.addOperator([self.remesh])
-
-        # # Splitting Step TODO:Transformer le splitting en opérateur d'opérateur
-        # splitting = []
-        # if self.splittingMethod == 'strang':
-        #     [splitting.append((i, 0.5)) for i in xrange(self.dim - 1)]
-        #     splitting.append((self.dim - 1, 1.))
-        #     [splitting.append((self.dim - 2 - i, 0.5)) for i in xrange(self.dim - 1)]
-        # else:
-        #     raise ValueError("Unknown splitting method : ", self.splittingMethod)
-        # self.discreteProblem.operator_list = []
-        # [self.discreteProblem.operator_list.append((op, 1.0, 0)) for op in self.discreteProblem.operators if not op.is_splittable]
-        # [[self.discreteProblem.operator_list.append((op, i[1], i[0])) for op in self.discreteProblem.operators if op.is_splittable] for i in splitting]
+        self.advection = None
+        ## ODE Solver method.
+        self.ODESolver = ODESolver
+        ## Interpolation method.
+        self.InterpolationMethod = InterpolationMethod
+        ## Remeshing method.
+        self.RemeshingMethod = RemeshingMethod
+        ## Splitting Method
+        self.splittingMethod = splittingMethod
+        if timer is None:
+            self.problem.setTimer(Timer(t_end, dt))
+        else:
+            self.problem.setTimer(timer)
+        if io is None:
+            self.problem.setIO(Printer())
+        else:
+            self.problem.setIO(io)
+        for op in self.problem.operators:
+            if isinstance(op, Transport):
+                self.advection = op
+        if self.advection is None:
+            raise ValueError("Particular Solver : Cannot create from a problem with no Transport operator")
 
     def initialize(self):
         """
@@ -89,25 +59,34 @@ class ParticularSolver(Solver):
 
         @param discreteProblem : Problem to initialize.
         """
-        # ### Create grid.points TODO: A enlever
-        # self.grid.points = np.empty_like(self.gvelo.values, dtype=dtype_real)
-        # if self.dim == 1:
-        #     for x in xrange(self.grid.elementNumber[0]):
-        #         self.grid.points[x] = self.grid.axes[0][x]
-        # if self.dim == 2:
-        #     for x in xrange(self.grid.elementNumber[0]):
-        #         for y in xrange(self.grid.elementNumber[1]):
-        #             self.grid.points[x, y][0] = self.grid.axes[0][x]
-        #             self.grid.points[x, y][1] = self.grid.axes[1][y]
-        # if self.dim == 3:
-        #     for x in xrange(self.grid.elementNumber[0]):
-        #         for y in xrange(self.grid.elementNumber[1]):
-        #             for z in xrange(self.grid.elementNumber[2]):
-        #                 self.grid.points[x, y, z][0] = self.grid.axes[0][x]
-        #                 self.grid.points[x, y, z][1] = self.grid.axes[1][y]
-        #                 self.grid.points[x, y, z][2] = self.grid.axes[2][z]
-        # self.gvelo.init()
-        # self.gscal.init()
+        self.p_position = ContinuousField(domain=self.problem.domains[0], name='Particle Position')
+        self.p_scalar = ContinuousField(domain=self.problem.domains[0], name='Particle Scalar')
+        self.problem.addVariable([self.p_position, self.p_scalar])
+        ## Discretise domains
+        for d in self.problem.domains:
+            d.discretize(self.problem.topology.resolution)
+        ## Discretise fields and initialize
+        for v in self.problem.variables:
+            v.discretize(self.problem.topology)
+            v.initialize()
+        ## Discretise operators
+        for op in self.problem.operators:
+            if op is self.advection:
+                op.discretize(result_position=self.p_position, result_scalar=self.p_scalar, method=self.ODESolver)
+            else:
+                op.discretize()
+        ## Create remeshing operator
+        remesh = Remeshing(partPositions=self.p_position,
+                           partScalar=self.p_scalar,
+                           resscal=self.advection.scalar,
+                           method=self.RemeshingMethod)
+        for op in self.problem.operators:
+            if op.discreteOperator.needSplitting:
+                if op is self.advection:
+                    index = self.problem.operators.index(op)
+                    self.problem.operators[index] = Splitting([op, remesh])
+                else:
+                    self.problem.operators[index] = Splitting([op])
 
     def __str__(self):
         """ToString method"""
diff --git a/HySoP/hysop/ParticularSolvers/interpolation/interpolation.py b/HySoP/hysop/ParticularSolvers/interpolation/interpolation.py
index d33dd4c05..308ca5ae3 100644
--- a/HySoP/hysop/ParticularSolvers/interpolation/interpolation.py
+++ b/HySoP/hysop/ParticularSolvers/interpolation/interpolation.py
@@ -4,8 +4,6 @@
 InterpolationMethod interface.
 """
 
-providedClass = "InterpolationMethod"
-
 
 class InterpolationMethod:
     """
diff --git a/HySoP/hysop/ParticularSolvers/remesh/method.py b/HySoP/hysop/ParticularSolvers/remesh/method.py
index 5b023b992..ade97b75e 100644
--- a/HySoP/hysop/ParticularSolvers/remesh/method.py
+++ b/HySoP/hysop/ParticularSolvers/remesh/method.py
@@ -3,7 +3,6 @@
 @package Utils
 RemeshingMethod interface.
 """
-from ..Param import *
 
 
 class RemeshingMethod:
diff --git a/HySoP/hysop/__init__.py.in b/HySoP/hysop/__init__.py.in
index 86afe6a33..9bf57ac7e 100755
--- a/HySoP/hysop/__init__.py.in
+++ b/HySoP/hysop/__init__.py.in
@@ -4,26 +4,26 @@
 Python package dedicated to flow simulation using particular methods on hybrid architectures (MPI-GPU)
 
 """
-__version__=1.00
-__all__=['Box','CartesianTopology','ScalarField']
+__version__ = 1.00
+__all__ = ['Box', 'CartesianTopology', 'ScalarField']
 
 import os
 import site
 import mpi4py.MPI as MPI
 
-if(os.environ.has_key('LD_LIBRARY_PATH')):
-    os.environ['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']+':'+"@CMAKE_INSTALL_PREFIX@"
+if 'LD_LIBRARY_PATH' in os.environ:
+    os.environ['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH'] + ':' + "@CMAKE_INSTALL_PREFIX@"
 else:
     os.environ['LD_LIBRARY_PATH'] = "@CMAKE_INSTALL_PREFIX@"
 
 rank_world = MPI.COMM_WORLD.Get_rank()
 if(rank_world == 0):
-    print "Starting @PACKAGE_NAME@ version "+str(__version__)+".\n"
+    print "Starting @PACKAGE_NAME@ version " + str(__version__) + ".\n"
 
 import constants
 
 import domain.box
-## Box-type physical domain 
+## Box-type physical domain
 Box = domain.box.Box
 
 ## Cartesian grid
@@ -35,5 +35,23 @@ CartesianTopology = fields.topology.CartesianTopology
 ## Fields
 import fields.discrete
 import fields.continuous
+import fields.analytical
 ScalarField = fields.discrete.ScalarField
 ContinuousField = fields.continuous.ContinuousField
+AnalyticalField = fields.analytical.AnalyticalField
+
+## Operators
+import operator.Transport
+Transport = operator.Transport.Transport
+
+## Problem
+import problem.problem
+Problem = problem.problem.Problem
+
+## Solver
+import ParticularSolvers.basic
+ParticularSolver = ParticularSolvers.basic.ParticularSolver
+
+## Tools
+import tools.printer
+Printer = tools.printer.Printer
diff --git a/HySoP/hysop/constants.py b/HySoP/hysop/constants.py
index 2a0ab9d49..1af66a9bc 100644
--- a/HySoP/hysop/constants.py
+++ b/HySoP/hysop/constants.py
@@ -10,7 +10,7 @@ import math
 
 #
 PI = math.pi
-# Set default type for real and integer numbers 
+# Set default type for real and integer numbers
 PARMES_REAL = np.float64
 PARMES_INTEGER = np.uint32
 PARMES_REAL_GPU = np.float32
@@ -25,3 +25,5 @@ YDIR = 1
 ZDIR = 2
 ## Tag for periodic boundary conditions
 PERIODIC = 0
+## Directions string
+S_DIR = ["_X", "_Y", "_Z"]
diff --git a/HySoP/hysop/domain/box.py b/HySoP/hysop/domain/box.py
index ed0528797..c2ce204a7 100644
--- a/HySoP/hysop/domain/box.py
+++ b/HySoP/hysop/domain/box.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from ..constants import PERIODIC
+from ..constants import *
 from .domain import Domain
 from .grid import CartesianGrid
 import numpy as np
@@ -25,13 +25,13 @@ class Box(Domain):
             raise ValueError("Box parameters inconsistents dimensions")
         Domain.__init__(self, dimension)
         ##  Box length. length = max - min.
-        self.length = np.array(length)
+        self.length = np.asarray(length, dtype=PARMES_REAL)
         ##  Minimum Box position.
-        self.origin = np.array(origin)
+        self.origin = np.asarray(origin, dtype=PARMES_REAL)
         ## Maximum Box position.
         self.max = self.origin + self.length
         # Boundary conditions type :
-        self.boundaries = np.zeros((self.dimension))
+        self.boundaries = np.zeros((self.dimension), dtype=PARMES_INTEGER)
         self.boundaries[:] = PERIODIC
         self.discreteDomain = None
 
diff --git a/HySoP/hysop/domain/grid.py b/HySoP/hysop/domain/grid.py
index fe13e3149..6a32f40e4 100644
--- a/HySoP/hysop/domain/grid.py
+++ b/HySoP/hysop/domain/grid.py
@@ -16,6 +16,7 @@ class CartesianGrid(DiscreteDomain):
         self.origin = domain.origin
         self.length = domain.length
         self.resolution = resolution
+        self.size = self.length / self.resolution
 
         ## self.elementNumber = spec
         ## self.elementSize = box.length / self.elementNumber
diff --git a/HySoP/hysop/fields/analytical.py b/HySoP/hysop/fields/analytical.py
index 7e6451064..d4ec1738f 100644
--- a/HySoP/hysop/fields/analytical.py
+++ b/HySoP/hysop/fields/analytical.py
@@ -4,7 +4,8 @@
 
 """
 from .continuous import ContinuousField
-from .discrete import DiscreteField
+from .discrete import ScalarField
+from .discrete import VectorField
 
 
 class AnalyticalField(ContinuousField):
@@ -13,7 +14,7 @@ class AnalyticalField(ContinuousField):
 
     """
 
-    def __init__(self, domain, name="", formula=None):
+    def __init__(self, domain, formula, name="", vector=False):
         """
         Constructor.
         Create an AnalyticalField from a formula.
@@ -22,29 +23,24 @@ class AnalyticalField(ContinuousField):
         @param dimension : variable dimension.
         @param formula : function defining the variable.
         """
-        ContinuousField.__init__(self, domain, name)
+        ContinuousField.__init__(self, domain, name, vector)
         ## Analytic formula.
         self.formula = formula
 
-    def discretize(self, topology=None):
-        """
-        AnalyticalField discretization method.
-        Create an DiscreteField from given topology.
-        """
-        self.__fieldId += 1
-        self.discreteField.append(ScalarField(self, topology, name=self.name + "_D_" + str(self.__fieldId),
-                                              idFromParent=self.__fieldId))
-        self.discreteField[self.__fieldId].initialize(self.formula)
-        return self.discreteField[self.__fieldId], self.__fieldId
-
-    def value(self, pos):
+    def value(self, *pos):
         """
         Evaluation of the variable at a given position.
 
         @param pos : Position to evaluate.
         @return : value of the formula at the given position.
         """
-        return self.formula(pos)
+        return self.formula(*pos)
+
+    def initialize(self):
+        if self._fieldId == -1:
+            raise ValueError("Cannot initialise analytical field non discretized.")
+        for dF in self.discreteField:
+            dF.initialize(self.formula)
 
     def __str__(self):
         """ToString method"""
diff --git a/HySoP/hysop/fields/continuous.py b/HySoP/hysop/fields/continuous.py
index 284d4d404..7bfb54eb6 100644
--- a/HySoP/hysop/fields/continuous.py
+++ b/HySoP/hysop/fields/continuous.py
@@ -27,7 +27,7 @@ class ContinuousField(object):
         ## Name of this field
         self.name = name
         # number of different discretizations
-        self.__fieldId = -1
+        self._fieldId = -1
         ## list of the various discretizations of this field
         self.discreteField = []
         ## is field is a vector field
@@ -38,19 +38,22 @@ class ContinuousField(object):
         discretization of the field on a topology
 
         """
-        self.__fieldId += 1
+        self._fieldId += 1
         print "Discretisation de ", self.name,
         if self.vector:
             print "Vector Field"
             self.discreteField.append(VectorField(self, topology,
-                                                  name=self.name + "_D_" + str(self.__fieldId),
-                                                  idFromParent=self.__fieldId))
+                                                  name=self.name + "_D_" + str(self._fieldId),
+                                                  idFromParent=self._fieldId))
         else:
             print "Scalar Field"
             self.discreteField.append(ScalarField(self, topology,
-                                                  name=self.name + "_D_" + str(self.__fieldId),
-                                                  idFromParent=self.__fieldId))
-        return self.discreteField[self.__fieldId], self.__fieldId
+                                                  name=self.name + "_D_" + str(self._fieldId),
+                                                  idFromParent=self._fieldId))
+        return self.discreteField[self._fieldId], self._fieldId
+
+    def initialize(self):
+        pass
 
     def __str__(self):
         """ Field info display """
diff --git a/HySoP/hysop/fields/discrete.py b/HySoP/hysop/fields/discrete.py
index 8f05381c2..bccf1be47 100644
--- a/HySoP/hysop/fields/discrete.py
+++ b/HySoP/hysop/fields/discrete.py
@@ -27,6 +27,7 @@ class ScalarField(object):
         self.data = np.zeros((resolution), dtype=PARMES_REAL, order=ORDER)
         self.__parentField = parent
         self.__idFromParent = idFromParent
+        self.domain = self.__parentField.domain.discreteDomain
 
     def __str__(self):
         """ Display class information """
@@ -52,32 +53,20 @@ class ScalarField(object):
     def initialize(self, formula=None):
         """
         Initialize values with given formula
-        \todo Ecrire l'initialisation efficace en python.
         """
-        raise NotImplementedError("Not yet implemented")
-
-    ## def init(self):
-    ##     if not self.initialValue is None:
-    ##         if self.domain.dimension == 1:
-    ##             for x in xrange(self.shape[0]):
-    ##                 self.values[x] = self.initialValue([self.domain.axes[0][x]])
-    ##             self.contains_data = True
-    ##         elif self.domain.dimension == 2:
-    ##             for x in xrange(self.shape[0]):
-    ##                 for y in xrange(self.shape[1]):
-    ##                     self.values[x, y] = self.initialValue([self.domain.axes[0][x], self.domain.axes[1][y]])
-    ##             self.contains_data = True
-    ##         elif self.domain.dimension == 3:
-    ##             for x in xrange(self.shape[0]):
-    ##                 for y in xrange(self.shape[1]):
-    ##                     for z in xrange(self.shape[2]):
-    ##                         self.values[x, y, z] = self.initialValue([self.domain.axes[0][x], self.domain.axes[1][y], self.domain.axes[2][z]])
-    ##             self.contains_data = True
-    ##         else:
-    ##             raise ValueError("Creating DiscreteVariable with incorrect domain dimension.")
+        v_formula = np.vectorize(formula)
+        if self.dimension == 3:
+            self.data = v_formula(self.topology.mesh.coords[0],
+                                  self.topology.mesh.coords[1],
+                                  self.topology.mesh.coords[2])
+        elif self.dimension == 2:
+            self.data = v_formula(self.topology.mesh.coords[0],
+                                  self.topology.mesh.coords[1])
+        else:
+            self.data = v_formula(self.topology.mesh.coords[0])
 
     def tofile(self, filename):
-        evtk.imageToVTK(filename, pointData={"scalar": self.data})
+        evtk.imageToVTK(filename, pointData={self.name: self.data})
 
 
 class VectorField(object):
@@ -99,6 +88,7 @@ class VectorField(object):
         self.data = [np.zeros((resolution), dtype=PARMES_REAL, order=ORDER) for d in xrange(self.dimension)]
         self.__parentField = parent
         self.__idFromParent = idFromParent
+        self.domain = self.__parentField.domain.discreteDomain
 
     def __str__(self):
         """ Display class information """
@@ -141,12 +131,20 @@ class VectorField(object):
         else:
             self.data[i[-1]].__getitem__(tuple(i[0:-1]))
 
-    def initialize(self, formula):
+    def initialize(self, formula=None):
         """
         Initialize values with given formula
-        \todo Ecrire l'initialisation efficace en python.
         """
-        raise NotImplementedError("Not yet implemented")
+        #print self.topology.mesh.coords
+        if formula is not None:
+            v_formula = np.vectorize(formula)
+            if self.dimension == 3:
+                self.data[0], self.data[1], self.data[2] = v_formula(self.topology.mesh.coords[0],
+                                                                     self.topology.mesh.coords[1],
+                                                                     self.topology.mesh.coords[2])
+            elif self.dimension == 2:
+                self.data[0], self.data[1] = v_formula(self.topology.mesh.coords[0],
+                                                       self.topology.mesh.coords[1])
 
 if __name__ == "__main__":
     print __doc__
diff --git a/HySoP/hysop/fields/topology.py b/HySoP/hysop/fields/topology.py
index 0b74994e2..41448182e 100644
--- a/HySoP/hysop/fields/topology.py
+++ b/HySoP/hysop/fields/topology.py
@@ -26,11 +26,11 @@ class CartesianTopology(object):
         nbprocs = comm.Get_size()
         if(dims is None):
             assert(dim is not None)
-            self.dims = np.asarray(MPI.Compute_dims(nbprocs, dim))
+            self.dims = np.asarray(MPI.Compute_dims(nbprocs, dim), dtype=PARMES_INTEGER)
             # Topology dimension
             self.dim = dim
         else:
-            self.dims = np.asarray(dims)
+            self.dims = np.asarray(dims, dtype=PARMES_INTEGER)
             self.dim = self.dims.size
         # Define the topology
         # default period status is periodic
@@ -53,9 +53,9 @@ class CartesianTopology(object):
             self.south, self.north = self.topo.Shift(ZDIR, 1)
         # ghost layer (default = 0)
         if(ghosts is None):
-            self.ghosts = np.zeros((self.domain.dimension))
+            self.ghosts = np.zeros((self.domain.dimension), dtype=PARMES_INTEGER)
         # Global resolution
-        self.resolution = np.asarray(resolution)
+        self.resolution = np.asarray(resolution, dtype=PARMES_INTEGER)
         nbpoints = self.resolution[:self.dim] // self.dims
         remainingPoints = self.resolution[:self.dim] % self.dims
         localResolution = self.resolution.copy()
@@ -63,9 +63,9 @@ class CartesianTopology(object):
         for i in range(self.dim):
             if(self.coords[i] == self.dims[i] - 1):
                 localResolution[i] = nbpoints[i] + remainingPoints[i]
-        start = np.zeros((domain.dimension))
+        start = np.zeros((domain.dimension), dtype=PARMES_INTEGER)
         start[:self.dim] = self.coords * nbpoints
-        self.mesh = LocalMesh(self.rank, resolution=localResolution, start=start, ghosts=self.ghosts)
+        self.mesh = LocalMesh(self.rank, resolution=localResolution, start=start, dom_size=self.domain.length/self.resolution, ghosts=self.ghosts)
 
     def __str__(self):
         """ Topology info display """
@@ -87,8 +87,8 @@ class FFTTopology(object):
         self.dim = dim
         # Compute the "optimal" processus distribution for each direction of the grid topology
         dims = MPI.Compute_dims(nbprocs, dim)
-        self.dims = np.ones((dim + 1))
-        self.dims[0:dim] = np.asarray(dims)
+        self.dims = np.ones((dim + 1), dtype=PARMES_INTEGER)
+        self.dims[0:dim] = np.asarray(dims, dtype=PARMES_INTEGER)
         # Define the topology
         self.topo = comm.Create_cart(self.dims, periods=periods[0:dim + 1])
         # Size of the topology
@@ -117,7 +117,7 @@ class FFTTopology(object):
 class LocalMesh(object):
     """
     """
-    def __init__(self, rank, resolution, start, ghosts=np.zeros((3))):
+    def __init__(self, rank, resolution, start, dom_size, ghosts=np.zeros((3))):
         # Current process rank in the topology that owns this mesh
         self.rank = rank
         # Local resolution
@@ -127,6 +127,19 @@ class LocalMesh(object):
         # index of the upper point (in each dir), global mesh
         self.end = self.start + self.resolution - 1
         # Mesh step size
+        self.size = dom_size
+        # Mesh coordinates
+        coord_start = self.start * self.size
+        coord_end = (self.end + 1) * self.size
+        if self.start.size == 3:
+            self.coords = np.ogrid[coord_start[0]:coord_end[0]:self.size[0],
+                                   coord_start[1]:coord_end[1]:self.size[1],
+                                   coord_start[2]:coord_end[2]:self.size[2]]
+        elif self.start.size == 2:
+            self.coords = np.ogrid[coord_start[0]:coord_end[0]:self.size[0],
+                                   coord_start[1]:coord_end[1]:self.size[1]]
+        else:
+            self.coords = np.ogrid[coord_start[0]:coord_end[0]:self.size[0]]
 
     def __str__(self):
         """ Local mesh display """
diff --git a/HySoP/hysop/operator/RemeshingDOp.py b/HySoP/hysop/operator/RemeshingDOp.py
deleted file mode 100644
index 6942158c4..000000000
--- a/HySoP/hysop/operator/RemeshingDOp.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-@package Operator
-Operator representation
-"""
-from ..Param import *
-from DiscreteOperator import DiscreteOperator
-import pyopencl as cl
-import time
-
-
-class RemeshingDOp(DiscreteOperator):
-    """
-    Remeshing operator representation.
-    DiscreteOperator.DiscreteOperator specialization.
-    """
-
-    def __init__(self, partPositions, partScalar, resscal, method, partBloc=None, partTag=None):
-        """
-        Constructor.
-        Create a Remeshing operator on a given discrete domain.
-        Work with a particle field (positions, scalar, type and tag) to set scalar on a grid.
-
-        @param partPositions : particles positions.
-        @param partScalar : particles scalar.
-        @param partBloc : particles bloc number.
-        @param partTag : particle tag number.
-        @param resscal DiscreteVariable.DiscreteVariable : new grid scalar values.
-        """
-        DiscreteOperator.__init__(self)
-        ## Particles positions.
-        self.ppos = partPositions
-        ## Particles scalar values.
-        self.pscal = partScalar
-        ## Particles bloc
-        self.pbloc = partBloc
-        ## Particles tag
-        self.ptag = partTag
-        ## Result scalar
-        self.resultScalar = resscal
-        self.addVariable([self.ppos, self.pscal, self.resultScalar])
-        if not self.pbloc is None:
-            self.addVariable([self.pbloc])
-        if not self.ptag is None:
-            self.addVariable([self.ptag])
-        self.numMethod = method
-        self.gpu_kernel_name = "remeshing"
-        self.compute_time = [0., 0., 0.]
-        self.queued_time = 0.
-        self.submit_time = 0.
-        self.total_flop = 0
-        self.total_bytes_accessed = 0
-
-    def setResultVariable(self, resscal):
-        """
-        Set results variables
-
-        @param resscal DiscreteVariable.DiscreteVariable : new grid scalar values.
-        """
-        ## Result scalar
-        self.resultScalar = resscal
-        self.addVariable([self.resultScalar])
-
-    def applyOperator(self, t, dt, splittingDirection):
-        """
-        Apply Remeshing operator.
-        """
-        c_time = time.time()
-        if self.gpu_kernel is None:
-            c_time = time.time()
-            ## ------------------- NumPy Optimisation
-            self.resultScalar.values[...] = 0.
-            self.numMethod.remesh(self.ppos.values, self.pscal.values, splittingDirection)
-            ## -------------------
-            self.compute_time[splittingDirection] += (time.time() - c_time)
-            self.total_flop += self.numMethod.nb_flop * np.prod(self.resultScalar.values.shape)
-        else:
-            l = list(self.gpu_shape)
-            nb_ligne = l.pop(splittingDirection)
-            local_wg = list(l)
-            if len(l) == 2:
-                local_wg[0] = 1
-                local_wg = tuple(local_wg)
-            else:
-                local_wg = None
-            evt = self.gpu_kernel.remeshing(self.gpu_queue, tuple(l), local_wg,
-                self.ppos.gpu_mem_object, self.pscal.gpu_mem_object, self.resultScalar.gpu_mem_object,
-                dtype_real_gpu(t), dtype_real_gpu(dt), dtype_integer(splittingDirection), dtype_integer(nb_ligne),
-                self.resultScalar.domain.min.astype(dtype_real_gpu),
-                self.resultScalar.domain.max.astype(dtype_real_gpu),
-                self.resultScalar.domain.elementNumber.astype(dtype_integer),
-                self.resultScalar.domain.elementSize.astype(dtype_real_gpu)
-                )
-            # self.gpu_queue.finish()
-            # cl.enqueue_copy(self.gpu_queue, self.resultScalar.values, self.resultScalar.gpu_mem_object)
-            # print self.resultScalar.values
-            self.gpu_queue.finish()
-            self.queued_time += (evt.profile.submit - evt.profile.queued) * 1e-9
-            self.submit_time += (evt.profile.start - evt.profile.submit) * 1e-9
-            self.compute_time[splittingDirection] += (evt.profile.end - evt.profile.start) * 1e-9
-            self.total_flop += (75 * nb_ligne) * np.prod(l)
-            self.total_bytes_accessed += ((2 + 1) * nb_ligne) * np.prod(l) * 4  # 2 float lus + 1 float écrits
-            #print "Remeshing M'6:", self.compute_time * 1e-9
-
-    def __str__(self):
-        """ToString method"""
-        return "RemeshingDOp (DiscreteOperator)"
-
-
-if __name__ == "__main__":
-    print __doc__
-    print "- Provided class : RemeshingDOp"
-    print RemeshingDOp.__doc__
diff --git a/HySoP/hysop/operator/Transport.py b/HySoP/hysop/operator/Transport.py
index 00541de94..8bf58be17 100644
--- a/HySoP/hysop/operator/Transport.py
+++ b/HySoP/hysop/operator/Transport.py
@@ -28,7 +28,7 @@ class Transport(ContinuousOperator):
         self.scalar = scalar
         self.addVariable([velocity, scalar])
 
-    def discretize(self, idVelocityD=0, idScalarD=0, result_position=None, result_scalar=None):
+    def discretize(self, idVelocityD=0, idScalarD=0, result_position=None, result_scalar=None, method=None):
         """
         Advection operator discretization method.
         Create an AdvectionDOp.AdvectionDOp from given specifications.
diff --git a/HySoP/hysop/operator/advection_d.py b/HySoP/hysop/operator/advection_d.py
index 94084acd9..9cb78ff52 100644
--- a/HySoP/hysop/operator/advection_d.py
+++ b/HySoP/hysop/operator/advection_d.py
@@ -14,7 +14,7 @@ class Advection_P(DiscreteOperator):
     DiscreteOperator.DiscreteOperator specialization.
     """
 
-    def __init__(self, advec, idVelocityD=0, idScalarD=0, result_position=None, result_scalar=None):
+    def __init__(self, advec, idVelocityD=0, idScalarD=0, result_position=None, result_scalar=None, method=None):
         """
         Constructor.
         Create a Advection operator on a given continuous domain.
@@ -23,18 +23,20 @@ class Advection_P(DiscreteOperator):
         @param advec : Advection operator.
         """
         DiscreteOperator.__init__(self)
-        ## Velocity. \todo utiliser un vectorField
+        ## Velocity.
         self.velocity = advec.velocity.discreteField[idVelocityD]
         ## Transported scalar.
         self.scalar = advec.scalar.discreteField[idScalarD]
         ## Result position
-        self.res_position = result_position
+        self.res_position = result_position.discreteField[0]
         ## Result scalar
-        self.res_scalar = result_scalar
+        self.res_scalar = result_scalar.discreteField[0]
         ## input fields
         self.input = [self.velocity, self.scalar]
         ## output fields
         self.output = [self.res_position, self.res_scalar]
+        self.numMethod = method
+        self.needSplitting = True
         # self.gpu_kernel_name = "advection"
         # self.compute_time = [0., 0., 0.]
         # self.submit_time = 0.
@@ -42,9 +44,14 @@ class Advection_P(DiscreteOperator):
         # self.total_flop = 0
         # self.total_bytes_accessed = 0
 
-    def applyOperator(self, t, dt, splittingDirection):
-        raise NotImplementedMethod("Not yet implemented")
-    #     """
+    def apply(self, t, dt, splittingDirection):
+        c_time = time.time()
+        print "Advection operator step, direction :", splittingDirection,
+        c_time = (time.time() - c_time)
+        self.compute_time += c_time
+        if self.numMethod is None:
+            print "nothing to do"
+            #     """
     #     Apply advection operator.
 
     #     @param t : current time.
@@ -118,13 +125,7 @@ class Advection_P(DiscreteOperator):
     #         #print "Advection:", self.compute_time * 1e-9
 
     def __str__(self):
-        """ToString method"""
-        s = "Advection_P (DiscreteOperator). Applying on following fields : \n Input fields : \n"
-        for f in self.input:
-            s += str(f) + "\n"
-        s += "Output fields : \n"
-        for f in self.output:
-            s += str(f) + "\n"
+        s = "Advection_P (DiscreteOperator). " + DiscreteOperator.__str__(self)
         return s
 
 if __name__ == "__main__":
diff --git a/HySoP/hysop/operator/continuous.py b/HySoP/hysop/operator/continuous.py
index ed2b750a0..a1083989a 100644
--- a/HySoP/hysop/operator/continuous.py
+++ b/HySoP/hysop/operator/continuous.py
@@ -36,6 +36,9 @@ class ContinuousOperator:
             if self.variables.count(v) == 0:
                 self.variables.append(v)
 
+    def apply(self, *args):
+        self.discreteOperator.apply(*args)
+
     @abstractmethod
     def discretize(self, spec=None):
         """
diff --git a/HySoP/hysop/operator/discrete.py b/HySoP/hysop/operator/discrete.py
index 2578a9755..301674518 100644
--- a/HySoP/hysop/operator/discrete.py
+++ b/HySoP/hysop/operator/discrete.py
@@ -19,13 +19,16 @@ class DiscreteOperator:
         Constructor.
         Create an empty discrete operator.
         """
-        ## Application domains of the variables.
-        self.domains = []
+        self.input, self.output = None, None
+        ## variables
+        self.variables = []
         ## Operator numerical method.
         self.numMethod = []
-        self.is_splittable = True
+        self.needSplitting = False
         self.gpu_kernel = None
         self.gpu_kernel_name = ""
+        self.discreteOperator = self
+        self.compute_time = 0.
 
     def setMethod(self, method):
         """
@@ -35,8 +38,19 @@ class DiscreteOperator:
         """
         self.numMethod = method
 
+    def addVariable(self, cVariable):
+        """
+        Add an continuous variables to the operator.
+        Also add variables' domains to the operator.
+
+        @param cVariable ContinuousVariable.ContinuousVariable : variables to add.
+        """
+        for v in cVariable:
+            if self.variables.count(v) == 0:
+                self.variables.append(v)
+
     @abstractmethod
-    def applyOperator(self):
+    def apply(self):
         """
         Abstract method, apply operaton on a variable.
         Must be implemented by sub-class.
@@ -45,6 +59,19 @@ class DiscreteOperator:
         """
         raise NotImplementedError("Need to override method in a subclass of " + providedClass)
 
+    def __str__(self):
+        """ToString method"""
+        s = "Applying on following fields : \n"
+        if self.input is not None:
+            s += "Input fields : \n"
+            for f in self.input:
+                s += str(f) + "\n"
+        if self.output is not None:
+            s += "Output fields : \n"
+            for f in self.output:
+                s += str(f) + "\n"
+        return s
+
 if __name__ == "__main__":
     print __doc__
     print "- Provided class : DiscreteOperator"
diff --git a/HySoP/hysop/operator/remeshing.py b/HySoP/hysop/operator/remeshing.py
new file mode 100644
index 000000000..c49c03753
--- /dev/null
+++ b/HySoP/hysop/operator/remeshing.py
@@ -0,0 +1,105 @@
+# -*- coding: utf-8 -*-
+"""
+@package Operator
+Operator representation
+"""
+from .discrete import DiscreteOperator
+import pyopencl as cl
+import time
+
+
+class Remeshing(DiscreteOperator):
+    """
+    Remeshing operator representation.
+    DiscreteOperator.DiscreteOperator specialization.
+    """
+
+    def __init__(self, partPositions, partScalar, resscal, method):
+        """
+        Constructor.
+        Create a Remeshing operator on a given discrete domain.
+        Work with a particle field (positions, scalar, type and tag) to set scalar on a grid.
+
+        @param partPositions : particles positions.
+        @param partScalar : particles scalar.
+        @param partBloc : particles bloc number.
+        @param partTag : particle tag number.
+        @param resscal DiscreteVariable.DiscreteVariable : new grid scalar values.
+        """
+        DiscreteOperator.__init__(self)
+        ## Particles positions.
+        self.ppos = partPositions
+        ## Particles scalar values.
+        self.pscal = partScalar
+        ## Result scalar
+        self.resultScalar = resscal
+        self.addVariable([self.ppos, self.pscal, self.resultScalar])
+        self.numMethod = method
+        ## input fields
+        self.input = [self.ppos, self.pscal]
+        ## output fields
+        self.output = [self.resultScalar]
+        self.needSplitting = True
+        # self.gpu_kernel_name = "remeshing"
+        # self.compute_time = [0., 0., 0.]
+        # self.queued_time = 0.
+        # self.submit_time = 0.
+        # self.total_flop = 0
+        # self.total_bytes_accessed = 0
+
+    def apply(self, t, dt, splittingDirection):
+        """
+        Apply Remeshing operator.
+        """
+        c_time = time.time()
+        print "Remeshing operator step, direction :", splittingDirection,
+        c_time = (time.time() - c_time)
+        self.compute_time += c_time
+        if self.numMethod is None:
+            print "nothing to do"
+
+        # c_time = time.time()
+        # if self.gpu_kernel is None:
+        #     c_time = time.time()
+        #     ## ------------------- NumPy Optimisation
+        #     self.resultScalar.values[...] = 0.
+        #     self.numMethod.remesh(self.ppos.values, self.pscal.values, splittingDirection)
+        #     ## -------------------
+        #     self.compute_time[splittingDirection] += (time.time() - c_time)
+        #     self.total_flop += self.numMethod.nb_flop * np.prod(self.resultScalar.values.shape)
+        # else:
+        #     l = list(self.gpu_shape)
+        #     nb_ligne = l.pop(splittingDirection)
+        #     local_wg = list(l)
+        #     if len(l) == 2:
+        #         local_wg[0] = 1
+        #         local_wg = tuple(local_wg)
+        #     else:
+        #         local_wg = None
+        #     evt = self.gpu_kernel.remeshing(self.gpu_queue, tuple(l), local_wg,
+        #         self.ppos.gpu_mem_object, self.pscal.gpu_mem_object, self.resultScalar.gpu_mem_object,
+        #         dtype_real_gpu(t), dtype_real_gpu(dt), dtype_integer(splittingDirection), dtype_integer(nb_ligne),
+        #         self.resultScalar.domain.min.astype(dtype_real_gpu),
+        #         self.resultScalar.domain.max.astype(dtype_real_gpu),
+        #         self.resultScalar.domain.elementNumber.astype(dtype_integer),
+        #         self.resultScalar.domain.elementSize.astype(dtype_real_gpu)
+        #         )
+        #     # self.gpu_queue.finish()
+        #     # cl.enqueue_copy(self.gpu_queue, self.resultScalar.values, self.resultScalar.gpu_mem_object)
+        #     # print self.resultScalar.values
+        #     self.gpu_queue.finish()
+        #     self.queued_time += (evt.profile.submit - evt.profile.queued) * 1e-9
+        #     self.submit_time += (evt.profile.start - evt.profile.submit) * 1e-9
+        #     self.compute_time[splittingDirection] += (evt.profile.end - evt.profile.start) * 1e-9
+        #     self.total_flop += (75 * nb_ligne) * np.prod(l)
+        #     self.total_bytes_accessed += ((2 + 1) * nb_ligne) * np.prod(l) * 4  # 2 float lus + 1 float écrits
+        #     #print "Remeshing M'6:", self.compute_time * 1e-9
+
+    def __str__(self):
+        s = "Advection_P (DiscreteOperator). " + DiscreteOperator.__str__(self)
+        return s
+
+if __name__ == "__main__":
+    print __doc__
+    print "- Provided class : RemeshingDOp"
+    print RemeshingDOp.__doc__
diff --git a/HySoP/hysop/operator/splitting.py b/HySoP/hysop/operator/splitting.py
new file mode 100644
index 000000000..82b6657c1
--- /dev/null
+++ b/HySoP/hysop/operator/splitting.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+"""
+@package Operator
+Operator representation
+"""
+from .discrete import DiscreteOperator
+import time
+
+
+class Splitting(DiscreteOperator):
+    """
+    Splitting operator representation.
+    DiscreteOperator.DiscreteOperator specialization.
+    """
+
+    def __init__(self, operators=[], dim=3):
+        """
+        Constructor.
+        Create a Splittinf operator on a given discrete domain.
+        Work with a particle field (positions, scalar, type and tag) to set scalar on a grid.
+
+        """
+        DiscreteOperator.__init__(self)
+        self.operators = operators
+        self.splitting = []
+        [self.splitting.append((i, 0.5)) for i in xrange(dim - 1)]
+        self.splitting.append((dim - 1, 1.))
+        [self.splitting.append((dim - 2 - i, 0.5)) for i in xrange(dim - 1)]
+
+    def apply(self, t, dt):
+        """
+        Apply Remeshing operator.
+        """
+        print "Splitting operator step :"
+        c_time = time.time()
+        for split in self.splitting:
+            print "direction : " + str(split[0]) + " dt*" + str(split[1])
+            for op in self.operators:
+                op.apply(t, split[1] * dt, split[0])
+        c_time = (time.time() - c_time)
+        self.compute_time += c_time
+
+    def __str__(self):
+        s = "Splitting (DiscreteOperator). Splitting steps : \n"
+        for split in self.splitting:
+            s += "direction : " + str(split[0]) + " dt=" + str(split[1]) + "\n"
+        s += "Concerned operators : \n"
+        for op in self.operators:
+            s += str(op)
+        return s
+
+if __name__ == "__main__":
+    print __doc__
+    print "- Provided class : RemeshingDOp"
+    print RemeshingDOp.__doc__
diff --git a/HySoP/hysop/problem/problem.py b/HySoP/hysop/problem/problem.py
index 2aa412159..74e40d065 100644
--- a/HySoP/hysop/problem/problem.py
+++ b/HySoP/hysop/problem/problem.py
@@ -25,18 +25,27 @@ class Problem():
             self.addDomain(v.domain)
         self.topology = topology
         self.solver = None
+        self.timer = None
+        self.io = None
 
-    def setSolver(self, solver):
-        self.solver = solver(self)
-        ## Discretise domains
-        for d in self.domains:
-            d.discretize(self.topology.resolution)
-        ## Discretise fields
-        for v in self.variables:
-            v.discretize(self.topology)
-        ## Discretise operators
-        for op in self.operators:
-            op.discretize(result_position=self.solver.p_position, result_scalar=self.solver.p_scalar)
+    def setTimer(self, t):
+        self.timer = t
+
+    def setIO(self, io):
+        self.io = io
+
+    def setSolver(self, solver, t_end, dt):
+        self.solver = solver(self, t_end, dt)
+        self.solver.initialize()
+
+    def solve(self):
+        print"\n\n Start solving ..."
+        while not self.timer.end:
+            print "\n==== Iteration : " + str(self.timer.ite + 1) + "\t t=" + str(self.timer.t + self.timer.dt) + " ===="
+            for op in self.operators:
+                op.apply(self.timer.t, self.timer.dt)
+            self.timer.step()
+            self.io.step()
 
     def addVariable(self, cVariable):
         """
@@ -67,6 +76,11 @@ class Problem():
             if self.domains.count(cDomain) == 0:
                 self.domains.append(cDomain)
 
+    def addOperator(self, op, index=None):
+        if index is None:
+            if not op in self.operators:
+                self.operators.append(op)
+
     def __str__(self):
         """ToString method"""
         s = "Problem based on\n"
diff --git a/HySoP/hysop/tools/__init__.py b/HySoP/hysop/tools/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/HySoP/hysop/tools/printer.py b/HySoP/hysop/tools/printer.py
index 8fbb07ea1..0fc402187 100644
--- a/HySoP/hysop/tools/printer.py
+++ b/HySoP/hysop/tools/printer.py
@@ -3,8 +3,8 @@
 @package Utils
 Results Printer
 """
-from ..Param import *
-from ..Utils.GPUParticularSolver import GPUParticularSolver
+from ..constants import *
+import evtk.hl as evtk
 
 
 class Printer():
@@ -12,7 +12,7 @@ class Printer():
     Results printer.
     """
 
-    def __init__(self, frequency=0, outputPrefix='./out', problem=None):
+    def __init__(self, fields=[], frequency=0, outputPrefix='./out_'):
         """
         Constructor.
         Create a results printer from a ContinuousProblem.ContinuousProblem with a given output prefix (relative path) and an output frequency.
@@ -23,81 +23,88 @@ class Printer():
         """
         self.freq = frequency
         self.outputPrefix = outputPrefix
-        self.problem = problem
+        self.fields = fields
         self.ite = 0
         if self.freq != 0:
-            self.printStep = self._printStep
+            self.step = self._printStep
         else:
-            self.printStep = self._passStep
-        self.skip = 1
-        self.grid = self.problem.discreteProblem.advecOp.velocity.domain
-        self.gvelo = self.problem.discreteProblem.advecOp.velocity.values
-        self.ppos = self.problem.discreteProblem.solver.ppos.values
-        self.pscal = self.problem.discreteProblem.solver.pscal.values
-        self.gscal = self.problem.discreteProblem.advecOp.scalar.values
-        self.printStep()
+            self.step = self._passStep
+        self.__dict_data = {}
+        for f in self.fields:
+            for df in f.discreteField:
+                if f.vector:
+                    for d in xrange(len(df.data)):
+                        self.__dict_data[df.name + S_DIR[d]] = df.data[d]
+                else:
+                    self.__dict_data[df.name] = df.data
+        self.step()
 
     def _passStep(self):
         pass
 
     def _printStep(self):
-        self.skip -= 1
-        if self.skip == 0:
-            if isinstance(self.problem.discreteProblem.solver, GPUParticularSolver) and self.ite > 0:
-                self.problem.discreteProblem.solver.collect_data()
-            print "Writing file : " + self.outputPrefix + "results_{0:05d}.dat".format(self.ite)
-            self.skip = self.freq
-            f = open(self.outputPrefix + "results_{0:05d}.dat".format(self.ite), 'w')
-            dim = self.grid.dimension
-            f.write("# iteration : {0}, time = {1}".format(self.ite, self.problem.discreteProblem.t))
-            f.write("# gid({0})  gpos({1}) gvelo({2}) gscal(1) ppos({3}) pvelo({4}) pscal(1) pbloc(1) ptag(1)\n".format(dim, dim, dim, dim, dim))
-            if self.grid.dimension == 1:
-                for x in xrange(self.grid.elementNumber[0]):
-                    f.write("  {0:6d}".format(x))
-                    f.write(" {:8.12}".format(self.grid.axes[0][x]))
-                    f.write(" {:8.12}".format(self.gvelo[x][0]))
-                    f.write(" {:8.12}".format(self.gscal[x]))
-                    f.write(" {:8.12}".format(self.ppos[x][0]))
-                    f.write(" {:8.12}".format(self.pscal[x]))
-                    f.write("\n")
-                f.write("\n")
-            if self.grid.dimension == 2:
-                for x in xrange(self.grid.elementNumber[0]):
-                    for y in xrange(self.grid.elementNumber[1]):
-                        f.write("  {0:6d}".format(x))
-                        f.write("  {0:6d}".format(y))
-                        f.write(" {:8.12}".format(self.grid.axes[0][x]))
-                        f.write(" {:8.12}".format(self.grid.axes[1][y]))
-                        f.write(" {:8.12}".format(self.gvelo[x, y][0]))
-                        f.write(" {:8.12}".format(self.gvelo[x, y][1]))
-                        f.write(" {:8.12}".format(self.gscal[x, y]))
-                        #f.write(" {:8.12}".format(self.ppos[x, y][0]))
-                        #f.write(" {:8.12}".format(self.ppos[x, y][1]))
-                        f.write(" {:8.12}".format(self.pscal[x, y]))
-                        f.write("\n")
-                f.write("\n")
-            if self.grid.dimension == 3:
-                for x in xrange(self.grid.elementNumber[0]):
-                    for y in xrange(self.grid.elementNumber[1]):
-                        for z in xrange(self.grid.elementNumber[2]):
-                            f.write("  {0:6d}".format(x))
-                            f.write("  {0:6d}".format(y))
-                            f.write("  {0:6d}".format(z))
-                            f.write(" {:8.12}".format(self.grid.axes[0][x]))
-                            f.write(" {:8.12}".format(self.grid.axes[1][y]))
-                            f.write(" {:8.12}".format(self.grid.axes[2][z]))
-                            f.write(" {:8.12}".format(self.gvelo[x, y, z][0]))
-                            f.write(" {:8.12}".format(self.gvelo[x, y, z][1]))
-                            f.write(" {:8.12}".format(self.gvelo[x, y, z][2]))
-                            f.write(" {:8.12}".format(self.gscal[x, y, z]))
-                            f.write(" {:8.12}".format(self.ppos[x, y, z][0]))
-                            f.write(" {:8.12}".format(self.ppos[x, y, z][1]))
-                            f.write(" {:8.12}".format(self.ppos[x, y, z][2]))
-                            f.write(" {:8.12}".format(self.pscal[x, y, z]))
-                            f.write("\n")
-                f.write("\n")
-            f.close()
-            self.ite += 1
+        if (self.ite % self.freq) == 0:
+            filename = self.outputPrefix + "results_{0:05d}.dat".format(self.ite)
+            print "Print file : " + filename
+            evtk.imageToVTK(filename, pointData=self.__dict_data)
+        self.ite += 1
+    #     self.skip -= 1
+    #     if self.skip == 0:
+    #         if isinstance(self.problem.discreteProblem.solver, GPUParticularSolver) and self.ite > 0:
+    #             self.problem.discreteProblem.solver.collect_data()
+    #         print "Writing file : " + self.outputPrefix + "results_{0:05d}.dat".format(self.ite)
+    #         self.skip = self.freq
+    #         f = open(self.outputPrefix + "results_{0:05d}.dat".format(self.ite), 'w')
+    #         dim = self.grid.dimension
+    #         f.write("# iteration : {0}, time = {1}".format(self.ite, self.problem.discreteProblem.t))
+    #         f.write("# gid({0})  gpos({1}) gvelo({2}) gscal(1) ppos({3}) pvelo({4}) pscal(1) pbloc(1) ptag(1)\n".format(dim, dim, dim, dim, dim))
+    #         if self.grid.dimension == 1:
+    #             for x in xrange(self.grid.elementNumber[0]):
+    #                 f.write("  {0:6d}".format(x))
+    #                 f.write(" {:8.12}".format(self.grid.axes[0][x]))
+    #                 f.write(" {:8.12}".format(self.gvelo[x][0]))
+    #                 f.write(" {:8.12}".format(self.gscal[x]))
+    #                 f.write(" {:8.12}".format(self.ppos[x][0]))
+    #                 f.write(" {:8.12}".format(self.pscal[x]))
+    #                 f.write("\n")
+    #             f.write("\n")
+    #         if self.grid.dimension == 2:
+    #             for x in xrange(self.grid.elementNumber[0]):
+    #                 for y in xrange(self.grid.elementNumber[1]):
+    #                     f.write("  {0:6d}".format(x))
+    #                     f.write("  {0:6d}".format(y))
+    #                     f.write(" {:8.12}".format(self.grid.axes[0][x]))
+    #                     f.write(" {:8.12}".format(self.grid.axes[1][y]))
+    #                     f.write(" {:8.12}".format(self.gvelo[x, y][0]))
+    #                     f.write(" {:8.12}".format(self.gvelo[x, y][1]))
+    #                     f.write(" {:8.12}".format(self.gscal[x, y]))
+    #                     #f.write(" {:8.12}".format(self.ppos[x, y][0]))
+    #                     #f.write(" {:8.12}".format(self.ppos[x, y][1]))
+    #                     f.write(" {:8.12}".format(self.pscal[x, y]))
+    #                     f.write("\n")
+    #             f.write("\n")
+    #         if self.grid.dimension == 3:
+    #             for x in xrange(self.grid.elementNumber[0]):
+    #                 for y in xrange(self.grid.elementNumber[1]):
+    #                     for z in xrange(self.grid.elementNumber[2]):
+    #                         f.write("  {0:6d}".format(x))
+    #                         f.write("  {0:6d}".format(y))
+    #                         f.write("  {0:6d}".format(z))
+    #                         f.write(" {:8.12}".format(self.grid.axes[0][x]))
+    #                         f.write(" {:8.12}".format(self.grid.axes[1][y]))
+    #                         f.write(" {:8.12}".format(self.grid.axes[2][z]))
+    #                         f.write(" {:8.12}".format(self.gvelo[x, y, z][0]))
+    #                         f.write(" {:8.12}".format(self.gvelo[x, y, z][1]))
+    #                         f.write(" {:8.12}".format(self.gvelo[x, y, z][2]))
+    #                         f.write(" {:8.12}".format(self.gscal[x, y, z]))
+    #                         f.write(" {:8.12}".format(self.ppos[x, y, z][0]))
+    #                         f.write(" {:8.12}".format(self.ppos[x, y, z][1]))
+    #                         f.write(" {:8.12}".format(self.ppos[x, y, z][2]))
+    #                         f.write(" {:8.12}".format(self.pscal[x, y, z]))
+    #                         f.write("\n")
+    #             f.write("\n")
+    #         f.close()
+    #         self.ite += 1
 
 
 if __name__ == "__main__":
diff --git a/HySoP/hysop/tools/timer.py b/HySoP/hysop/tools/timer.py
new file mode 100644
index 000000000..8d8c0ba9f
--- /dev/null
+++ b/HySoP/hysop/tools/timer.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+"""
+@package Operator
+Operator representation
+"""
+import time
+
+
+class Timer:
+    """
+    Timer. Manage time steps
+    DiscreteOperator.DiscreteOperator specialization.
+    """
+
+    def __init__(self, t_end, dt, t_init=0.):
+        """
+        Constructor.
+
+        """
+        self.t_end = t_end
+        self.dt = dt
+        self.t = t_init
+        self.end = False
+        self.ite = 0
+
+    def step(self):
+        """
+        Apply Remeshing operator.
+        """
+        if self.t < self.t_end:
+            self.ite += 1
+            self.t += self.dt
+            if self.t >= self.t_end:
+                self.end = True
+
+    def __str__(self):
+        s = "Timer (DiscreteOperator). "
+        return s
+
+if __name__ == "__main__":
+    print __doc__
+    print "- Provided class : RemeshingDOp"
+    print RemeshingDOp.__doc__
diff --git a/HySoP/setup.py.in b/HySoP/setup.py.in
index 2d2fc4387..2e931b6cd 100644
--- a/HySoP/setup.py.in
+++ b/HySoP/setup.py.in
@@ -5,7 +5,8 @@ setup.py file for @PYPACKAGE_NAME@
 
 """
 from numpy.distutils.core import setup, Extension
-import os, glob
+import os
+import glob
 import sys
 # List of all directories for sources
 #os.listdir(os.path.join('ParMePy','New_ParmePy'))
@@ -16,7 +17,10 @@ name = '@PYPACKAGE_NAME@'
 packages = ['parmepy',
             'parmepy.domain',
             'parmepy.fields',
-            'parmepy.operator']
+            'parmepy.operator',
+            'parmepy.problem',
+            'parmepy.ParticularSolvers',
+            'parmepy.tools']
 #            'examples']
 #            'new_ParMePy',
 #            'new_ParMePy/Domain',
@@ -28,15 +32,20 @@ packages = ['parmepy',
 
 # Enable this to get debug info
 # DISTUTILS_DEBUG=1
-parmes_dir=['@CMAKE_BINARY_DIR@/Modules']
-parmes_libdir=['@CMAKE_BINARY_DIR@/src']
-parmeslib=['@PARMES_LIBRARY_NAME@']
-f2py_options=['--no-lower']
+parmes_dir = ['@CMAKE_BINARY_DIR@/Modules']
+parmes_libdir = ['@CMAKE_BINARY_DIR@/src']
+parmeslib = ['@PARMES_LIBRARY_NAME@']
+f2py_options = ['--no-lower']
 
 
 scales_src = glob.glob('@CMAKE_SOURCE_DIR@/parmepy/scales2py/*.f90')
-scalesModule=Extension(name='parmepy.scales2py',f2py_options=f2py_options,sources=scales_src,include_dirs=parmes_dir,
-                       library_dirs=parmes_libdir,libraries=parmeslib,define_macros = [('F2PY_REPORT_ON_ARRAY_COPY','1')])
+scalesModule = Extension(name='parmepy.scales2py',
+                         f2py_options=f2py_options,
+                         sources=scales_src,
+                         include_dirs=parmes_dir,
+                         library_dirs=parmes_libdir,
+                         libraries=parmeslib,
+                         define_macros=[('F2PY_REPORT_ON_ARRAY_COPY', '1')])
 
 ext_modules = [scalesModule]
 print ext_modules
@@ -47,8 +56,13 @@ withfftw = "@WITH_FFTW@"
 if(withfftw is "ON"):
     fortran_src = glob.glob('@CMAKE_SOURCE_DIR@/parmepy/parmesfftw2py/*.f90')
     #    sys.path.extend('config_fc -DF2PY_REPORT_ON_ARRAY_COPY'.split())
-    parpyModule=Extension(name='parmepy.fftw2py',f2py_options=f2py_options,sources=fortran_src,include_dirs=parmes_dir,
-                          library_dirs=parmes_libdir,libraries=parmeslib,define_macros = [('F2PY_REPORT_ON_ARRAY_COPY','1')])
+    parpyModule = Extension(name='parmepy.fftw2py',
+                            f2py_options=f2py_options,
+                            sources=fortran_src,
+                            include_dirs=parmes_dir,
+                            library_dirs=parmes_libdir,
+                            libraries=parmeslib,
+                            define_macros=[('F2PY_REPORT_ON_ARRAY_COPY', '1')])
     ext_modules.append(parpyModule)
 
 print ext_modules
@@ -59,7 +73,7 @@ setup(name=name,
       author_email='parmes-devel@lists.forge.imag.fr',
       url='https://forge.imag.fr/projects/parmes/',
       license='GNU public license',
-      package_dir = {'': '@CMAKE_SOURCE_DIR@'},
+      package_dir={'': '@CMAKE_SOURCE_DIR@'},
       ext_modules=ext_modules,
       packages=packages
       #data_files=[('new_ParMePy/Utils', ['./new_ParMePy/Utils/gpu_src.cl'])]
-- 
GitLab