diff --git a/HySoP/CMake/ParmesTests.cmake b/HySoP/CMake/ParmesTests.cmake
index 5f1bd553902eea89fa03a458db3bcae540c941ff..5888dad433261f14c4f2f71db1576bef6c5efeac 100644
--- a/HySoP/CMake/ParmesTests.cmake
+++ b/HySoP/CMake/ParmesTests.cmake
@@ -8,7 +8,7 @@ find_python_module(pytest REQUIRED)
 set(py_src_dirs
   fields
   domain
-  operator
+  #operator
   problem
   tools
   numerics
@@ -19,6 +19,11 @@ if(USE_MPI)
     ${py_src_dirs} mpi)
 endif()
 
+if(WITH_GPU)
+  set(py_src_dirs
+    ${py_src_dirs} gpu)
+endif()
+
 ### JM : Bub, GLOB_RECURSE utilse les chemins relatifs avec ../
 # foreach(testdir ${py_src_dirs})
 #   file(GLOB_RECURSE py_test_files "${test_dir}" RELATIVE_PATH parmepy/*/test_*.py)
diff --git a/HySoP/hysop/constants.py b/HySoP/hysop/constants.py
index 75e0b3b263842f5c97a151594c203dd4a118a6d0..9fc1a1d16f72b88e2e86b0613fb75015149c453f 100644
--- a/HySoP/hysop/constants.py
+++ b/HySoP/hysop/constants.py
@@ -46,7 +46,7 @@ if __DEBUG__:
                 print ' (Inherits from : ',
                 print [c.__name__ for c in args[0].__mro__[1:]], ')'
             else:
-                print 'Call : ', f.__name__, 'of ', f.__module__
+                print 'Call : ', f.__name__, 'in ', f.__code__.co_filename, f.__code__.co_firstlineno
             ## Calling f
             r = f(*args, **kw)
             if f.__name__ is '__new__':
diff --git a/HySoP/hysop/domain/domain.py b/HySoP/hysop/domain/domain.py
index 7cfd811082e1fd82b1773fed3e1449204d6bebff..c1e85e5735a64b48568c41b09b1fd3d23035243b 100644
--- a/HySoP/hysop/domain/domain.py
+++ b/HySoP/hysop/domain/domain.py
@@ -23,11 +23,19 @@ class Domain(object):
         """
         ## Domain dimension.
         self.dimension = dimension
-        ## Domain topologies
+        ## Domain topologies. List of uniques topologies.
         self.topologies = []
 
     @debug
     def addTopology(self, topo):
+        """Topology management.
+        If an equivalent topology is found in topologies, then return this
+        topology from the list and delete the other.
+        Otherwise, add the topology in the list.
+
+        @param topo : Topology to add
+        @return topology and its index in the topology list
+        """
         try:
             idTopo = self.topologies.index(topo)
             del topo
diff --git a/HySoP/hysop/fields/analytical.py b/HySoP/hysop/fields/analytical.py
index c47729ff3f26680c511f710f3f2a50c2e7297f24..acb8fd772b5618e365672f7c0a9460ebb39e2183 100644
--- a/HySoP/hysop/fields/analytical.py
+++ b/HySoP/hysop/fields/analytical.py
@@ -14,7 +14,7 @@ class AnalyticalField(Field):
     """
 
     @debug
-    def __init__(self, domain, formula, name="", vector=False):
+    def __init__(self, domain, formula, name="", isVector=False):
         """
         Create an AnalyticalField from a formula.
 
@@ -23,9 +23,10 @@ class AnalyticalField(Field):
         @param name : name of the variable (used for vtk output).
         @param vector : is variable is a vector.
 
-        @note formula is used in ScalarField or VectorField as vectorized function by numpy.
+        @note formula is used in ScalarField or VectorField as vectorized
+        function by numpy.
         """
-        Field.__init__(self, domain, name, vector)
+        Field.__init__(self, domain, name, isVector)
         ## Analytic formula.
         self.formula = formula
 
@@ -41,7 +42,8 @@ class AnalyticalField(Field):
     @debug
     def initialize(self):
         if self._fieldId == -1:
-            raise ValueError("Cannot initialise analytical field non discretized.")
+            raise ValueError(
+                "Cannot initialise analytical field non discretized.")
         print self.name,
         for dF in self.discreteField:
             dF.initialize(self.formula)
diff --git a/HySoP/hysop/fields/continuous.py b/HySoP/hysop/fields/continuous.py
index 61d83ca9b504fe90294b5d28bf27772eed617e78..6d1f8612e079620d8267dd5834772b3167b07de1 100644
--- a/HySoP/hysop/fields/continuous.py
+++ b/HySoP/hysop/fields/continuous.py
@@ -1,7 +1,7 @@
 """
 @package parmepy.fields.continuous
 
-Continuous variable description
+Continuous variable description.
 """
 from parmepy import __VERBOSE__
 from parmepy.constants import debug
@@ -22,15 +22,13 @@ class Field(object):
         Create a Field.
 
         @param domain : variable application domain.
-        @param name : name of the variable (used for vtk output).
+        @param name : name of the variable.
         @param vector : is variable is a vector.
         """
         ## Application domain of the variable.
         self.domain = domain
         ## Field dimension.
         self.dimension = self.domain.dimension
-        ## Discretisation of this field
-        self.discreteField = None
         ## Name of this field
         if(name is not None):
             self.name = name
@@ -49,9 +47,11 @@ class Field(object):
     def discretize(self, topo):
         """
         Discretization of the field on a topology.
+        In the case of this field already discretized whith the same topology,
+        a discrete object is not created.
+
         @param topo : topology specification for discretization
         @return discrete field and its index.
-
         """
         # Find if topology already use to discretize self
         try:
@@ -74,7 +74,6 @@ class Field(object):
                                                       name=nameD,
                                                       idFromParent=fieldId))
             self.topologies.insert(fieldId, topo)
-
         return self.discreteField[fieldId], fieldId
 
     @debug
diff --git a/HySoP/hysop/fields/gpu_discrete.py b/HySoP/hysop/fields/gpu_discrete.py
index c7fb28ca2aca7994b27d3d288a1e631a56aeeb90..0e2a7b023fa9d17e197a4642adfd2220b2b1c134 100644
--- a/HySoP/hysop/fields/gpu_discrete.py
+++ b/HySoP/hysop/fields/gpu_discrete.py
@@ -20,6 +20,7 @@ class GPUDiscreteField(object):
         self.initialization_kernel = None
         self.precision = precision
         self.mem_size = 0
+        self.data_on_device = False
 
     @abstractmethod
     def toHost(self):
@@ -74,47 +75,48 @@ class GPUVectorField(VectorField, GPUDiscreteField):
 
     @debug
     def initialize(self, formula=None):
-        if self.initialization_kernel is None:
-            VectorField.initialize(self, formula)
-            if self.dimension == 2:
-                self.data[0] = np.asarray(self.data[0],
-                                          dtype=self.precision, order=ORDER)
-                self.data[1] = np.asarray(self.data[1],
-                                          dtype=self.precision, order=ORDER)
-            else:
-                self.data[0] = np.asarray(self.data[0],
-                                          dtype=self.precision, order=ORDER)
-                self.data[1] = np.asarray(self.data[1],
-                                          dtype=self.precision, order=ORDER)
-                self.data[2] = np.asarray(self.data[2],
-                                          dtype=self.precision, order=ORDER)
-            data, time = self.toDevice()
-            print "Transfers : ", self.mem_size, "Bytes transfered at ",
-            print "{0:.3f} GBytes/sec".format(
-                (self.mem_size * 1e-9) / time)
-        else:
-            coord_min = np.ones(4, dtype=self.precision)
-            mesh_size = np.ones(4, dtype=self.precision)
-            coord_min[0:self.dimension] = np.asarray(self.topology.mesh.origin,
-                                                     dtype=self.precision)
-            mesh_size[0:self.dimension] = np.asarray(self.topology.mesh.space_step,
-                                                     dtype=self.precision)
-            if self.dimension == 2:
-                evt = self.initialization_kernel(self.gpu_data[0],
-                                                 self.gpu_data[1],
-                                                 coord_min,
-                                                 mesh_size)
+        if not self.data_on_device:
+            if self.initialization_kernel is None:
+                VectorField.initialize(self, formula)
+                if self.dimension == 2:
+                    self.data[0] = np.asarray(self.data[0],
+                                              dtype=self.precision, order=ORDER)
+                    self.data[1] = np.asarray(self.data[1],
+                                              dtype=self.precision, order=ORDER)
+                else:
+                    self.data[0] = np.asarray(self.data[0],
+                                              dtype=self.precision, order=ORDER)
+                    self.data[1] = np.asarray(self.data[1],
+                                              dtype=self.precision, order=ORDER)
+                    self.data[2] = np.asarray(self.data[2],
+                                              dtype=self.precision, order=ORDER)
+                data, time = self.toDevice()
+                print "Transfers : ", self.mem_size, "Bytes transfered at ",
+                print "{0:.3f} GBytes/sec".format(
+                    (self.mem_size * 1e-9) / time)
             else:
-                evt = self.initialization_kernel(self.gpu_data[0],
-                                                 self.gpu_data[1],
-                                                 self.gpu_data[2],
-                                                 coord_min,
-                                                 mesh_size)
-            self.queue.finish()
-            cTime = (evt.profile.end - evt.profile.start) * 1e-9
-            print "Computing  : ", cTime, "sec"
-        self.contains_data = False
-        self.data_on_device = True
+                coord_min = np.ones(4, dtype=self.precision)
+                mesh_size = np.ones(4, dtype=self.precision)
+                coord_min[0:self.dimension] = np.asarray(self.topology.mesh.origin,
+                                                         dtype=self.precision)
+                mesh_size[0:self.dimension] = np.asarray(self.topology.mesh.space_step,
+                                                         dtype=self.precision)
+                if self.dimension == 2:
+                    evt = self.initialization_kernel(self.gpu_data[0],
+                                                     self.gpu_data[1],
+                                                     coord_min,
+                                                     mesh_size)
+                else:
+                    evt = self.initialization_kernel(self.gpu_data[0],
+                                                     self.gpu_data[1],
+                                                     self.gpu_data[2],
+                                                     coord_min,
+                                                     mesh_size)
+                self.queue.finish()
+                cTime = (evt.profile.end - evt.profile.start) * 1e-9
+                print "Computing  : ", cTime, "sec"
+            self.contains_data = False
+            self.data_on_device = True
 
     def toDevice(self):
         """
@@ -245,29 +247,30 @@ class GPUScalarField(ScalarField, GPUDiscreteField):
 
     @debug
     def initialize(self, formula=None):
-        if self.initialization_kernel is None:
-            ScalarField.initialize(self, formula)
-            self.data = np.asarray(self.data,
-                                   dtype=self.precision, order=ORDER)
-            data, time = self.toDevice()
-            print "Transfers : ", self.mem_size, "Bytes transfered at ",
-            print "{0:.3f} GBytes/sec".format(
-                (self.mem_size * 1e-9) / time)
-        else:
-            coord_min = np.ones(4, dtype=self.precision)
-            mesh_size = np.ones(4, dtype=self.precision)
-            coord_min[0:self.dimension] = np.asarray(self.topology.mesh.origin,
-                                                     dtype=self.precision)
-            mesh_size[0:self.dimension] = np.asarray(self.topology.mesh.space_step,
-                                                     dtype=self.precision)
-            evt = self.initialization_kernel(self.gpu_data,
-                                             coord_min,
-                                             mesh_size)
-            self.queue.finish()
-            cTime = (evt.profile.end - evt.profile.start) * 1e-9
-            print "Computing  : ", cTime, "sec"
-        self.contains_data = False
-        self.data_on_device = True
+        if not self.data_on_device:
+            if self.initialization_kernel is None:
+                ScalarField.initialize(self, formula)
+                self.data = np.asarray(self.data,
+                                       dtype=self.precision, order=ORDER)
+                data, time = self.toDevice()
+                print "Transfers : ", self.mem_size, "Bytes transfered at ",
+                print "{0:.3f} GBytes/sec".format(
+                    (self.mem_size * 1e-9) / time)
+            else:
+                coord_min = np.ones(4, dtype=self.precision)
+                mesh_size = np.ones(4, dtype=self.precision)
+                coord_min[0:self.dimension] = np.asarray(self.topology.mesh.origin,
+                                                         dtype=self.precision)
+                mesh_size[0:self.dimension] = np.asarray(self.topology.mesh.space_step,
+                                                         dtype=self.precision)
+                evt = self.initialization_kernel(self.gpu_data,
+                                                 coord_min,
+                                                 mesh_size)
+                self.queue.finish()
+                cTime = (evt.profile.end - evt.profile.start) * 1e-9
+                print "Computing  : ", cTime, "sec"
+            self.contains_data = False
+            self.data_on_device = True
 
     def toDevice(self):
         """
diff --git a/HySoP/hysop/fields/scalar.py b/HySoP/hysop/fields/scalar.py
index 2887f6f83883ce97e4dc22a8acd4568906cc8bab..9c811fe5b3b959320e804c6e35b1678649798255 100644
--- a/HySoP/hysop/fields/scalar.py
+++ b/HySoP/hysop/fields/scalar.py
@@ -57,7 +57,7 @@ class ScalarField(DiscreteField):
         @li 2D : float formula(float x, float y)
         where x,y,z are point coordinates.
         """
-        if formula is not None:
+        if formula is not None and not self.contains_data:
             if __VERBOSE__:
                 print "...",
             v_formula = np.vectorize(formula)
diff --git a/HySoP/hysop/fields/vector.py b/HySoP/hysop/fields/vector.py
index 6451f34e85c89c54b6aa539f489068e2374d582c..313b3dbc07b39d375574575662d0eb8540602dd4 100644
--- a/HySoP/hysop/fields/vector.py
+++ b/HySoP/hysop/fields/vector.py
@@ -87,7 +87,7 @@ class VectorField(DiscreteField):
         @li 2D : float, float formula(float x, float y)
         where x,y,z are point coordinates.
         """
-        if formula is not None:
+        if formula is not None and not self.contains_data:
             if __VERBOSE__:
                 print "...",
             v_formula = np.vectorize(formula)
diff --git a/HySoP/hysop/gpu/cl_src/weights_m4prime.cl b/HySoP/hysop/gpu/cl_src/weights_m4prime.cl
index 866122bb746dfb17273090124f8cf3f13feb45a1..0a3337eef58bde74723f6613b18aed61d7dd0f80 100644
--- a/HySoP/hysop/gpu/cl_src/weights_m4prime.cl
+++ b/HySoP/hysop/gpu/cl_src/weights_m4prime.cl
@@ -7,10 +7,11 @@
  * @return weights
  */
 inline float alpha(float y, float s){
-  return ((y * (y * (-y + 2.0) - 1.0)) / 2.0) * s;}
+  return ((y * (y * (-y + 2.0) - 1.0)) / 2.0) * s;} //6Flops
 inline float beta(float y, float s){
-  return ((y * y * (3.0 * y - 5.0) + 2.0) / 2.0) * s;}
+  return ((y * y * (3.0 * y - 5.0) + 2.0) / 2.0) * s;} //7flops
 inline float gamma(float y, float s){
-  return ((y * (y * (-3.0 * y + 4.0) + 1.0)) / 2.0) * s;}
+  return ((y * (y * (-3.0 * y + 4.0) + 1.0)) / 2.0) * s;} //7Flops
 inline float delta(float y, float s){
-  return ((y * y * (y - 1.0)) / 2.0) * s;}
+  return ((y * y * (y - 1.0)) / 2.0) * s;} //5Flops
+//Total: 25Flops
diff --git a/HySoP/hysop/gpu/cl_src/weights_m6prime.cl b/HySoP/hysop/gpu/cl_src/weights_m6prime.cl
index cd21a32e74bff85d463b68da55d44bd8f83749ee..301b115d5ab1d1c8fd4ac11ffe31c739798d40f3 100644
--- a/HySoP/hysop/gpu/cl_src/weights_m6prime.cl
+++ b/HySoP/hysop/gpu/cl_src/weights_m6prime.cl
@@ -7,14 +7,15 @@
  * @return weights
  */
 inline float alpha(float y, float s){
-  return (y * (y * (y * (y * (13.0 - 5.0 * y) - 9.0) - 1.0) + 2.0) / 24.0) * s;}
+  return (y * (y * (y * (y * (13.0 - 5.0 * y) - 9.0) - 1.0) + 2.0) / 24.0) * s;} //11Flops
 inline float beta(float y, float s){
-  return (y * (y * (y * (y * (25.0 * y - 64.0) + 39.0) + 16.0) - 16.0) / 24.0)*s;}
+  return (y * (y * (y * (y * (25.0 * y - 64.0) + 39.0) + 16.0) - 16.0) / 24.0)*s;} //11Flops
 inline float gamma(float y, float s){
-  return (y * y * (y * (y * (126.0 - 50.0 * y) - 70.0) - 30.0) / 24.0 + 1.0)*s;}
+  return (y * y * (y * (y * (126.0 - 50.0 * y) - 70.0) - 30.0) / 24.0 + 1.0)*s;} //11Flops
 inline float delta(float y, float s){
-  return (y * (y * (y * (y * (50.0 * y - 124.0) + 66.0) + 16.0) + 16.0) / 24.0)*s;}
+  return (y * (y * (y * (y * (50.0 * y - 124.0) + 66.0) + 16.0) + 16.0) / 24.0)*s;} //11FLops
 inline float eta(float y, float s){
-  return (y * (y * (y * (y * (61.0 - 25.0 * y) - 33.0) - 1.0) - 2.0) / 24.0)*s;}
+  return (y * (y * (y * (y * (61.0 - 25.0 * y) - 33.0) - 1.0) - 2.0) / 24.0)*s;} //11Flops
 inline float zeta(float y, float s){
-  return (y * y * y * (y * (5.0 * y - 12.0) + 7.0) / 24.0)*s;}
+  return (y * y * y * (y * (5.0 * y - 12.0) + 7.0) / 24.0)*s;} //9Flops
+//Total: 65Flops
diff --git a/HySoP/hysop/gpu/rendering.py b/HySoP/hysop/gpu/rendering.py
new file mode 100644
index 0000000000000000000000000000000000000000..aad493c9f06c839ff4862a760fe84b677639a503
--- /dev/null
+++ b/HySoP/hysop/gpu/rendering.py
@@ -0,0 +1,218 @@
+"""
+@package parmepy.gpu.rendering
+
+Handle OpenGL realtime rendering through OpenCL/OpenGL interoperability.
+@see http://enja.org/2011/03/22/adventures-in-pyopencl-part-2-particles-with-pyopengl/
+@see http://www.dyn-lab.com/articles/cl-gl.html
+"""
+from parmepy.constants import np, debug
+from parmepy.operator.monitors.monitoring import Monitoring
+from parmepy.gpu.tools import get_opengl_shared_environment, build_src
+from parmepy.fields.gpu_discrete import GPUScalarField
+from parmepy.gpu import PARMES_REAL_GPU, cl, GPU_SRC
+from parmepy.numerics.gpu_kernel import KernelLauncher
+from OpenGL.GL import *
+from OpenGL.GLU import *
+from OpenGL.GLUT import *
+
+
+class OpenGLRendering(Monitoring):
+    """
+    """
+
+    @debug
+    def __init__(self, field, delay=10, frequency=1):
+        """
+        """
+        Monitoring.__init__(self, [field], frequency)
+        print "Rendering Init"
+        if not field.dimension == 2:
+            raise ValueError("Rendering implemented in 2D only.")
+        self.delay = delay
+        #mouse handling for transforming scene
+        self.mouse_down = False
+        self.mouse_old = np.array([0., 0.])
+        self.rotate = np.array([0., 0., 0.])
+        self.translate = np.array([0., 0., 0.])
+        self.translate[0:2] = -(field.domain.origin + field.domain.length / 2.)
+        self.initrans = np.array([0., 0., -2.])
+        glutInit(sys.argv)
+        width, height = 800, 800
+        glutInitWindowSize(width, height)
+        glutInitWindowPosition(0, 0)
+        glutCreateWindow('OpenCL/OpenGL Parmepy')
+
+        glViewport(0, 0, width, height)
+        glMatrixMode(GL_PROJECTION)
+        glLoadIdentity()
+        gluPerspective(30.0, width / float(height), 1.5, 2.)
+        glMatrixMode(GL_MODELVIEW)
+
+        #handle user input
+        glutKeyboardFunc(self.on_key)
+        ## Fix mouse motion
+        #glutMouseFunc(self.on_click)
+        #glutMotionFunc(self.on_mouse_motion)
+
+        self.platform, self.device, self.ctx, self.queue = \
+            get_opengl_shared_environment(platform_id=0, device_id=0,
+                                          device_type='gpu',
+                                          precision=PARMES_REAL_GPU)
+
+        glClearColor(1, 1, 1, 1)
+        glColor(0, 0, 1)
+
+    def setUp(self):
+        print "rendering SetUp"
+        for df in self.variables[0].discreteField:
+            if isinstance(df, GPUScalarField):
+                self.gpu_field = df
+        print "Rendered field: ", self.gpu_field
+        ## Create OpenGL vbo
+        self.pos_vbo = glGenBuffers(1)
+        glBindBuffer(GL_ARRAY_BUFFER, self.pos_vbo)
+        glBufferData(GL_ARRAY_BUFFER, self.gpu_field.data.nbytes * 4,
+                     None, GL_DYNAMIC_DRAW)
+        glEnableClientState(GL_VERTEX_ARRAY)
+        glVertexPointer(4, GL_FLOAT, 0, None)
+
+        self.color_vbo = glGenBuffers(1)
+        glBindBuffer(GL_ARRAY_BUFFER, self.color_vbo)
+        glBufferData(GL_ARRAY_BUFFER, self.gpu_field.data.nbytes * 4,
+                     None, GL_DYNAMIC_DRAW)
+        glEnableClientState(GL_COLOR_ARRAY)
+        glColorPointer(4, GL_FLOAT, 0, None)
+
+        self.pos = cl.GLBuffer(self.ctx,
+                               cl.mem_flags.READ_WRITE,
+                               int(self.pos_vbo))
+        self.color = cl.GLBuffer(self.ctx,
+                                 cl.mem_flags.READ_WRITE,
+                                 int(self.color_vbo))
+        self.gl_objects = [self.pos, self.color]
+        print "Device memory used for rendering: ",
+        print self.pos.size + self.color.size, " Bytes"
+
+        f = open(GPU_SRC + 'rendering.cl')
+        gpu_src = "".join(f.readlines())
+        f.close()
+        self.prg = build_src(self.device, self.ctx, gpu_src,
+                             " -cl-single-precision-constant",
+                             PARMES_REAL_GPU)
+        self.numMethod = KernelLauncher(self.prg.colorize,
+                                        self.queue,
+                                        self.gpu_field.data.shape,
+                                        None)
+
+###GL CALLBACKS
+    def timer(self, t):
+        glutTimerFunc(t, self.timer, t)
+        glutPostRedisplay()
+
+    def on_key(self, *args):
+        ESCAPE = '\033'
+        if args[0] == ESCAPE or args[0] == 'q':
+            sys.exit()
+
+    def on_click(self, button, state, x, y):
+        if state == GLUT_DOWN:
+            self.mouse_down = True
+            self.button = button
+        else:
+            self.mouse_down = False
+        self.mouse_old[0] = x
+        self.mouse_old[1] = y
+
+    def on_mouse_motion(self, x, y):
+        dx = x - self.mouse_old[0]
+        dy = y - self.mouse_old[0]
+        if self.mouse_down and self.button == 0:  # left button
+            self.rotate[0] += dy * .02
+            self.rotate[1] += dx * .02
+        elif self.mouse_down and self.button == 2:  # right button
+            self.translate[2] -= dy * .001
+        self.mouse_old[0] = x
+        self.mouse_old[1] = y
+    ###END GL CALLBACKS
+
+    def setMainLoop(self, problem):
+        """
+        """
+        print "Setting rendering main loop"
+        #this will call draw every 10ms
+        glutTimerFunc(self.delay, self.timer, self.delay)
+
+        def problem_step():
+            if not problem.timer.end:
+                if (problem.domain.topologies[0].rank == 0):
+                    print "==== Iteration : {0:3d}   t={1:6.3f} ====".format(
+                        problem.timer.ite, problem.timer.t + problem.timer.dt)
+                for op in problem.operators:
+                    op.apply(problem.timer.t, problem.timer.dt,
+                             problem.timer.ite)
+                problem.timer.step()
+        glutDisplayFunc(problem_step)
+
+    def finalize(self):
+        print "rendering finalization"
+
+    def apply(self, t, dt, ite):
+        """
+        """
+        self.queue.finish()
+        self.numMethod(self.gpu_field.gpu_data, self.pos, self.color)
+        cl.enqueue_release_gl_objects(self.queue, self.gl_objects)
+        self.queue.finish()
+
+        glFlush()
+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+        glMatrixMode(GL_MODELVIEW)
+        glLoadIdentity()
+
+        #handle mouse transformations
+        glTranslatef(self.initrans[0], self.initrans[1], self.initrans[2])
+        glRotatef(self.rotate[0], 1, 0, 0)
+        glRotatef(self.rotate[1], 0, 1, 0)  # we switched around the axis so make this rotate_z
+        glTranslatef(self.translate[0], self.translate[1], self.translate[2])
+
+        glEnable(GL_POINT_SMOOTH)
+        glPointSize(3)
+        #glEnable(GL_BLEND)
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+        glBindBuffer(GL_ARRAY_BUFFER, self.color_vbo)
+        glColorPointer(4, GL_FLOAT, 0, None)
+        glBindBuffer(GL_ARRAY_BUFFER, self.pos_vbo)
+        glVertexPointer(4, GL_FLOAT, 0, None)
+
+        glEnableClientState(GL_VERTEX_ARRAY)
+        glEnableClientState(GL_COLOR_ARRAY)
+        glDrawArrays(GL_POINTS, 0, np.prod(self.gpu_field.data.shape))
+        glDisableClientState(GL_COLOR_ARRAY)
+        glDisableClientState(GL_VERTEX_ARRAY)
+
+        #glDisable(GL_BLEND)
+        orig = np.array([0, 0, 0])
+        x_one = np.array([1, 0, 0])
+        y_one = np.array([0, 1, 0])
+        z_one = np.array([0, 0, 1])
+        glColor3f(1, 0, 0)    # red
+        self.draw_line(orig, x_one)
+        glColor3f(0, 1, 0)    # green
+        self.draw_line(orig, y_one)
+        #glColor3f(0, 0, 1)    # blue
+        #self.draw_line(orig, z_one)
+
+        glFlush()
+        cl.enqueue_acquire_gl_objects(self.queue, self.gl_objects)
+
+    def draw_line(self, v1, v2):
+        glBegin(GL_LINES)
+        glVertex3f(v1[0], v1[1], v1[2])
+        glVertex3f(v2[0], v2[1], v2[2])
+        glEnd()
+
+    def startMainLoop(self):
+        """
+        """
+        glutMainLoop()
diff --git a/HySoP/hysop/gpu/tests/test_opencl_environment.py b/HySoP/hysop/gpu/tests/test_opencl_environment.py
new file mode 100644
index 0000000000000000000000000000000000000000..1e107c4eed46df1966922e6306546c9e523c3bfa
--- /dev/null
+++ b/HySoP/hysop/gpu/tests/test_opencl_environment.py
@@ -0,0 +1,52 @@
+from parmepy.gpu.tools import get_opencl_environment, \
+    get_opengl_shared_environment
+from parmepy.gpu import PARMES_REAL_GPU, PARMES_DOUBLE_GPU
+
+
+def test_queue_unique_creation():
+    """
+    Testing that only one queue is created when multiples calls to get
+    an environment.
+    """
+    platform, device, ctx, queue = get_opencl_environment(0, 0, 'gpu',
+                                                          PARMES_REAL_GPU)
+    platform_id = id(platform)
+    device_id = id(device)
+    ctx_id = id(ctx)
+    queue_id = id(queue)
+    platformb, deviceb, ctxb, queueb = get_opencl_environment(0, 0, 'gpu',
+                                                              PARMES_REAL_GPU)
+    platformb_id = id(platformb)
+    deviceb_id = id(deviceb)
+    ctxb_id = id(ctxb)
+    queueb_id = id(queueb)
+    assert platformb_id == platform_id
+    assert deviceb_id == device_id
+    assert ctxb_id == ctx_id
+    assert queueb_id == queue_id
+
+
+def test_queue_with_gl_sharing():
+    """
+    Testing that queue and context is changed when OpenGL rendering is
+    activated. Environment, platform and device remains unchanged.
+    """
+    from OpenGL.GLUT import glutInit
+    import sys
+    glutInit(sys.argv)
+    platform, device, ctx, queue = get_opengl_shared_environment(
+        0, 0, 'gpu', PARMES_REAL_GPU)
+    platform_id = id(platform)
+    device_id = id(device)
+    ctx_id = id(ctx)
+    queue_id = id(queue)
+    platformb, deviceb, ctxb, queueb = get_opencl_environment(0, 0, 'gpu',
+                                                              PARMES_REAL_GPU)
+    platformb_id = id(platformb)
+    deviceb_id = id(deviceb)
+    ctxb_id = id(ctxb)
+    queueb_id = id(queueb)
+    assert platformb_id == platform_id
+    assert deviceb_id == device_id
+    assert ctxb_id == ctx_id
+    assert queueb_id == queue_id
diff --git a/HySoP/hysop/gpu/tools.py b/HySoP/hysop/gpu/tools.py
index 7cd2711a88c787f62207e7dc36eacf8bd36dbbb3..4c39c1281489ca632a4c3171489595bf5a83ef32 100644
--- a/HySoP/hysop/gpu/tools.py
+++ b/HySoP/hysop/gpu/tools.py
@@ -3,66 +3,145 @@
 
 Tools for gpu management.
 """
-from parmepy import __VERBOSE__
+#from parmepy import __VERBOSE__
 from parmepy.gpu import cl, PARMES_REAL_GPU
+__VERBOSE__ = True
 
 __platform, __device, __ctx, __queue = None, None, None, None
 __precision = None
 
 
+def _get_platform(platform_id):
+    """
+    """
+    #Get platform.
+    try:
+        ## OpenCL platform
+        platform = cl.get_platforms()[platform_id]
+    except IndexError:
+        print "  Incorrect platform_id :", platform_id, ".",
+        print " Only ", len(cl.get_platforms()), " available.",
+        print " Getting defalut platform. "
+        __platform = cl.get_platforms()[0]
+    if __VERBOSE__:
+        print "  Platform   "
+        print "  - Name       :", platform.name
+        print "  - Version    :", platform.version
+    return platform
+
+
+def _get_device(platform, device_id, device_type):
+    """
+    """
+    try:
+        ## OpenCL device
+        device = platform.get_devices(
+            eval("cl.device_type." + device_type.upper()))[device_id]
+    except cl.RuntimeError as e:
+        print "RuntimeError:", e
+        device = cl.create_some_context().devices[0]
+    except AttributeError as e:
+        print "AttributeError:", e
+        device = cl.create_some_context().devices[0]
+    if __VERBOSE__:
+        print "  Device"
+        print "  - Name                :",
+        print device.name
+        print "  - Type                :",
+        print cl.device_type.to_string(device.type)
+        print "  - C Version           :",
+        print device.opencl_c_version
+        print "  - Global mem size     :",
+        print device.global_mem_size / (1024 ** 3), "GB"
+    return device
+
+
+def _get_context(device, props=None):
+    """
+    """
+    if props is None:
+        ctx = cl.Context([device])
+    else:
+        ctx = cl.Context(properties=props, devices=[device])
+    if __VERBOSE__:
+        print " Context:"
+        print "  - properties           :", props
+    return ctx
+
+
+def _get_queue(ctx):
+    """
+    """
+    props = cl.command_queue_properties.PROFILING_ENABLE
+    queue = cl.CommandQueue(ctx, properties=props)
+    if __VERBOSE__:
+        print " Queue"
+        print "  - properties           :", props
+        print "==="
+    return queue
+
+
+def get_opengl_shared_environment(platform_id, device_id, device_type,
+                                  precision):
+    """
+    """
+    global __platform
+    global __device
+    global __ctx
+    global __queue
+    global __precision
+    print "Create OpenGL,", __platform, __device, __ctx, __queue
+    if __precision is None and not precision is None:
+        __precision = precision
+    if __queue is None:
+        if __VERBOSE__:
+            print "=== OpenGL shared environment ==="
+        __platform = _get_platform(platform_id)
+        #Get device.
+        __device = _get_device(__platform, device_id, device_type)
+        #Creates GPU Context
+        ## OpenCL context
+        from pyopencl.tools import get_gl_sharing_context_properties
+        import sys
+        if sys.platform == "darwin":
+            properties = get_gl_sharing_context_properties()
+        else:
+            # Some OSs prefer clCreateContextFromType, some prefer
+            # clCreateContext. Try both.
+            try:
+                properties = [
+                    (cl.context_properties.PLATFORM, platform)]
+            except:
+                properties = [
+                    (cl.context_properties.PLATFORM, platform)]
+        __ctx = _get_context(__device, properties)
+        #Create CommandQueue on the GPU Context
+        ## OpenCL command queue
+        __queue = _get_queue(__ctx)
+    return __platform, __device, __ctx, __queue
+
+
 def get_opencl_environment(platform_id, device_id, device_type, precision):
     global __platform
     global __device
     global __ctx
     global __queue
     global __precision
+    print "Create OpenCL,", __platform, __device, __ctx, __queue
     if __precision is None and not precision is None:
         __precision = precision
     if __queue is None:
         if __VERBOSE__:
             print "=== OpenCL environment ==="
-        #Get platform.
-        try:
-            ## OpenCL platform
-            __platform = cl.get_platforms()[platform_id]
-        except IndexError:
-            print "  Incorrect platform_id :", platform_id, ".",
-            print " Only ", len(cl.get_platforms()), " available.",
-            print " Getting defalut platform. "
-            __platform = cl.get_platforms()[0]
-        if __VERBOSE__:
-            print "  Platform   "
-            print "  - Name       :", __platform.name
-            print "  - Version    :", __platform.version
+        __platform = _get_platform(platform_id)
         #Get device.
-        try:
-            ## OpenCL device
-            __device = __platform.get_devices(
-                eval("cl.device_type." + device_type.upper()))[device_id]
-        except cl.RuntimeError as e:
-            print "RuntimeError:", e
-            __device = cl.create_some_context().devices[0]
-        except AttributeError as e:
-            print "AttributeError:", e
-            __device = cl.create_some_context().devices[0]
-        if __VERBOSE__:
-            print "  Device"
-            print "  - Name                :",
-            print __device.name
-            print "  - Type                :",
-            print cl.device_type.to_string(__device.type)
-            print "  - C Version           :",
-            print __device.opencl_c_version
-            print "  - Global mem size     :",
-            print __device.global_mem_size / (1024 ** 3), "GB"
-            print "===\n"
+        __device = _get_device(__platform, device_id, device_type)
         #Creates GPU Context
         ## OpenCL context
-        __ctx = cl.Context([__device])
+        __ctx = _get_context(__device)
         #Create CommandQueue on the GPU Context
         ## OpenCL command queue
-        __queue = cl.CommandQueue(
-            __ctx, properties=cl.command_queue_properties.PROFILING_ENABLE)
+        __queue = _get_queue(__ctx)
     return __platform, __device, __ctx, __queue
 
 
@@ -138,13 +217,32 @@ def explore():
     print "OpenCL exploration : "
     platforms = cl.get_platforms()
     platforms_info = ["name", "version", "vendor", "profile", "extensions"]
-    devices_info = ["name", "version", "vendor", "profile", "extensions",
-                    "available", "type", "compiler_available", "double_fp_config", "single_fp_config",
-                    "global_mem_size", "global_mem_cache_type", "global_mem_cache_size", "global_mem_cacheline_size",
-                    "local_mem_size", "local_mem_type", "max_clock_frequency", "max_compute_units",
-                    "max_constant_buffer_size", "max_mem_alloc_size", "max_work_group_size",
-                    "max_work_item_dimensions", "max_work_item_sizes",
-                    "preferred_vector_width_double", "preferred_vector_width_float", "preferred_vector_width_int"]
+    devices_info = ["name",
+                    "version",
+                    "vendor",
+                    "profile",
+                    "extensions",
+                    "available",
+                    "type",
+                    "compiler_available",
+                    "double_fp_config",
+                    "single_fp_config",
+                    "global_mem_size",
+                    "global_mem_cache_type",
+                    "global_mem_cache_size",
+                    "global_mem_cacheline_size",
+                    "local_mem_size",
+                    "local_mem_type",
+                    "max_clock_frequency",
+                    "max_compute_units",
+                    "max_constant_buffer_size",
+                    "max_mem_alloc_size",
+                    "max_work_group_size",
+                    "max_work_item_dimensions",
+                    "max_work_item_sizes",
+                    "preferred_vector_width_double",
+                    "preferred_vector_width_float",
+                    "preferred_vector_width_int"]
     for pltfm in platforms:
         print "Platform:", pltfm.name
         for pltfm_info in platforms_info:
diff --git a/HySoP/hysop/operator/advection.py b/HySoP/hysop/operator/advection.py
index b0b5f87301807e167e5e60cadaab4797b8db3a01..97de7046090094f3092bced4b8e401543f7562ce 100644
--- a/HySoP/hysop/operator/advection.py
+++ b/HySoP/hysop/operator/advection.py
@@ -106,7 +106,7 @@ class Advection(Operator):
                                                **self.config)
                 else:
                     print "Using default advection operator"
-                    if self.advectedFields.vector:
+                    if self.advectedFields.isVector:
                         raise ValueError("Not implemented yet. default" +
                                          " advection is only for " +
                                          "scalar fields")
diff --git a/HySoP/hysop/operator/analytic.py b/HySoP/hysop/operator/analytic.py
index a4c2f3733472516e14e1baece11c9e76de7864f7..7074f37961acbe4b4987f4896e552f9e31200109 100644
--- a/HySoP/hysop/operator/analytic.py
+++ b/HySoP/hysop/operator/analytic.py
@@ -25,7 +25,7 @@ class Analytic(Operator):
 
         @param fields : field
         """
-        if not callable(formula):
+        if not callable(formula) and 'gpu' in other_config.keys():
             raise ValueError("Analytic formula must be a function")
         Operator.__init__(self, [fields])
         ## velocity variable
diff --git a/HySoP/hysop/operator/monitors/printer.py b/HySoP/hysop/operator/monitors/printer.py
index 43d7b084548ced0c929a237e412f31740a462d78..83a2cdc6c94c6012c31ed1e92e7c4ca65f8f94da 100644
--- a/HySoP/hysop/operator/monitors/printer.py
+++ b/HySoP/hysop/operator/monitors/printer.py
@@ -47,7 +47,7 @@ class Printer(Monitoring):
         res = {}
         for f in self.variables:
             for df in f.discreteField:
-                if f.vector:
+                if f.isVector:
                     for d in xrange(len(df.data)):
                         if len(df.data[d].shape) == 2:
                             res[df.name + S_DIR[d]] = np.expand_dims(
@@ -106,7 +106,7 @@ class Printer(Monitoring):
                                 f.write("{0:8.12} {1:8.12} ".format(
                                         coords[0][i, 0], coords[1][0, j]))
                                 for field in self.variables:
-                                    if field.vector:
+                                    if field.isVector:
                                         f.write("{0:8.12} {1:8.12} ".format(
                                                 field.discreteField[0][0][i, j],
                                                 field.discreteField[0][1][i, j]))
@@ -123,7 +123,7 @@ class Printer(Monitoring):
                                             coords[1][0, j, 0],
                                             coords[2][0, 0, k]))
                                     for field in self.variables:
-                                        if field.vector:
+                                        if field.isVector:
                                             f.write("{0:8.12} {1:8.12} {2:8.12} ".format(
                                                     field.discreteField[0][0][i, j, k],
                                                     field.discreteField[0][1][i, j, k],
diff --git a/HySoP/hysop/operator/particle_advection.py b/HySoP/hysop/operator/particle_advection.py
index 7a2366f95ad1004b2e4e4471b52a14fbf6c7bbc7..bd933f39d7ab1a1f12b3e2f1b6b63ab73daa34eb 100644
--- a/HySoP/hysop/operator/particle_advection.py
+++ b/HySoP/hysop/operator/particle_advection.py
@@ -56,16 +56,14 @@ class ParticleAdvection(DiscreteOperator):
         ## Result position
         particle_position = Field(self.advec.advectedFields.domain,
                                   "Particle_Position",
-                                  vector=False)
-        particle_position.discretize(
-            self.advec.resolutions[self.advec.advectedFields])
+                                  isVector=False)
+        particle_position.discretize(self.advectedFields.topology)
         self.part_position = particle_position.discreteField[0]
         ## Result advectedFields
         particle_advectedFields = Field(self.advec.advectedFields.domain,
                                         "Particle_AdvectedFields",
-                                        vector=False)
-        particle_advectedFields.discretize(
-            self.advec.resolutions[self.advec.advectedFields])
+                                        isVector=False)
+        particle_advectedFields.discretize(self.advectedFields.topology)
         self.part_advectedFields = particle_advectedFields.discreteField[0]
         if self.method.find('rk2') >= 0:
             self.name += '_rk2'
diff --git a/HySoP/hysop/operator/tests/test_particle_advection.py b/HySoP/hysop/operator/tests/test_particle_advection.py
index 6706b7599c4aa6f0482d6d41f0398d7cd90ec50a..ec8bba350018215c2c18e117bc115108120ccbf7 100644
--- a/HySoP/hysop/operator/tests/test_particle_advection.py
+++ b/HySoP/hysop/operator/tests/test_particle_advection.py
@@ -11,11 +11,12 @@ def test_null_velocity():
     dom = Box(dimension=2, origin=[0., 0.], length=[1., 1.])
     resolTopo = [33, 33]
     csf = AnalyticalField(dom, formula=lambda x, y: 1.)
-    cvf = AnalyticalField(dom, vector=True, formula=lambda x, y: (0., 0.))
-    advec = Advection(cvf, csf)
-    advec.setUp(resolutions={csf: [33, 33],
-                             cvf: [33, 33]},
-                method='')
+    cvf = AnalyticalField(dom, isVector=True, formula=lambda x, y: (0., 0.))
+    advec = Advection(cvf, csf,
+                      resolutions={csf: resolTopo,
+                                   cvf: resolTopo},
+                      method='')
+    advec.setUp()
     pytest.raises(ValueError, advec.apply, 0., 1., 1)
 #    advec.apply(0., 1., 1)
 
diff --git a/HySoP/hysop/problem/problem.py b/HySoP/hysop/problem/problem.py
index 961d298cc796e1c97c34ded2a54e937fe6180540..5fcb4bcbdb1434131399f738a3cf06f31fc4d06c 100644
--- a/HySoP/hysop/problem/problem.py
+++ b/HySoP/hysop/problem/problem.py
@@ -7,18 +7,26 @@ from abc import ABCMeta, abstractmethod
 from parmepy.constants import debug
 from parmepy import __VERBOSE__
 from parmepy.operator.monitors.monitoring import Monitoring
+try:
+    from parmepy.gpu.rendering import OpenGLRendering
+except ImportError:
+    OpenGLRendering = None
 
 
 class Problem(object):
     """
     Problem representation.
 
-    Contains several operators that apply on variables.
+    Contains several operators and monitors that apply on variables.
     Variables are defined on different domains.\n
-    The problem contains a solver that define how the problem is solved.\n
-    A problem is based on a topology that deploys
-    its resolution over MPI processus.\n
-    Finally, the problem handle outputs thanks to a io object.
+    Each operator is set up and variables are initialized in a set up step.\n
+    To solve the problem, a loop over time-steps is launched. A step consists
+    in calling the apply method of each operators and monitors.\n
+    To finish, a finalize method is called.\
+
+    \remark: In case of GPU real-time rendering (i.e. use of an
+    OpenGLRendering object), The loop over time-steps is passed to the
+    OpenGL Utility Toolkit (GLUT).
     """
 
     __metaclass__ = ABCMeta
@@ -34,6 +42,7 @@ class Problem(object):
         Create a transport problem instance.
 
         @param operators : list of operators.
+        @param monitors : list of monitors.
         """
         ## Problem operators
         self.operators = operators
@@ -66,6 +75,13 @@ class Problem(object):
                 v.initialize()
         if __VERBOSE__:
             print "===="
+        ## Set the callback function to OpenGL
+        self.glRenderer = None
+        if not OpenGLRendering is None:
+            for op in self.operators:
+                if isinstance(op, OpenGLRendering):
+                    self.glRenderer = op
+                    op.setMainLoop(self)
 
     @debug
     def solve(self):
@@ -77,20 +93,22 @@ class Problem(object):
         At end of time step, call an io step.\n
         Displays timings at simulation end.
         """
-        ## Iterations counter
-        ite = 0
         print "\n\n Start solving ..."
         for op in self.operators:
             if isinstance(op, Monitoring):
-                op.apply(self.timer.t, self.timer.dt, ite)
-        while not self.timer.end:
-            ite = ite + 1
-            if (self.domain.topologies[0].rank == 0):
-                print "==== Iteration : {0:3d}   t={1:6.3f} ====".format(
-                    self.timer.ite, self.timer.t + self.timer.dt)
-            for op in self.operators:
-                op.apply(self.timer.t, self.timer.dt, ite)
-            self.timer.step()
+                op.apply(self.timer.t, self.timer.dt, ite=0)
+        ## Pass the main loop to GLUT in case of GL_Rendering
+        if not self.glRenderer is None:
+            self.glRenderer.startMainLoop()
+        ## Or run a loop normally
+        else:
+            while not self.timer.end:
+                if (self.domain.topologies[0].rank == 0):
+                    print "==== Iteration : {0:3d}   t={1:6.3f} ====".format(
+                        self.timer.ite, self.timer.t + self.timer.dt)
+                for op in self.operators:
+                    op.apply(self.timer.t, self.timer.dt, self.timer.ite)
+                self.timer.step()
         print "\n\n End solving\n"
         print "==== Finalization ===="
         for op in self.operators:
@@ -146,7 +164,7 @@ class Timer:
         ## Is simulation is terminated
         self.end = False
         ## Iteration counter
-        self.ite = 0
+        self.ite = 1
 
     def step(self):
         """