diff --git a/pystencils/datahandling/graph_datahandling.py b/pystencils/datahandling/graph_datahandling.py
index 41d16a4c3ddea7c2893712275606c6448b4eb5ba..4c9b635b75998ddcab299bfbb005ac3e0ef5af8f 100644
--- a/pystencils/datahandling/graph_datahandling.py
+++ b/pystencils/datahandling/graph_datahandling.py
@@ -15,7 +15,6 @@ import numpy as np
 import pystencils.datahandling
 import pystencils.kernel_wrapper
 from pystencils.field import FieldType
-from pystencils.integer_functions import modulo_ceil
 
 
 class DataTransferKind(str, Enum):
@@ -67,13 +66,29 @@ class KernelCall:
         return "Call " + str(self.kernel.ast.function_name)
 
 
+class TimeloopRun:
+    def __init__(self, timeloop, time_steps):
+        self.timeloop = timeloop
+        self.time_steps = time_steps
+
+    def __str__(self):
+        return (f'Timeloop:'
+                + '\nPre:\n'
+                + '\n   '.join(str(f) for f in self.timeloop._pre_run_functions)
+                + f'\n{self.time_steps} time steps:\n'
+                + '\n   '.join(str(f) for f in self.timeloop._single_step_asts)
+                + '\nPost:\n'
+                + '\n   '.join(str(f) for f in self.timeloop._post_run_functions))
+
+
 class GraphDataHandling(pystencils.datahandling.SerialDataHandling):
 
     """Docstring for GraphDataHandling. """
 
-    class TimeLoop(pystencils.TimeLoop):
+    class TimeLoop(pystencils.timeloop.TimeLoop):
         def __init__(self, parent, *args, **kwargs):
             self.parent = parent
+            self._single_step_asts = []
             super().__init__(*args, **kwargs)
 
         def add_pre_run_function(self, f):
@@ -86,13 +101,16 @@ class GraphDataHandling(pystencils.datahandling.SerialDataHandling):
             self._single_step_functions.append(f)
 
         def add_call(self, functor, argument_list):
+            for argument_dict in argument_list:
+                self._single_step_asts.append((functor, argument_dict) if not hasattr(functor, 'ast') else functor.ast)
+
             if hasattr(functor, 'kernel'):
                 functor = functor.kernel
             if not isinstance(argument_list, list):
                 argument_list = [argument_list]
 
-            for argument_dict in argument_list:
-                self._call_data.append((functor, argument_dict))
+        def run(self, time_steps=1):
+            super().run(time_steps)
 
     def __init__(self, *args, **kwargs):
 
@@ -136,12 +154,15 @@ class GraphDataHandling(pystencils.datahandling.SerialDataHandling):
 
     def run_kernel(self, kernel_function, **kwargs):
         self.call_queue.append(KernelCall(kernel_function, kwargs))
+        super().run_kernel(kernel_function, **kwargs)
         # skip calling super
 
     def to_cpu(self, name):
+        super().to_cpu(name)
         self.call_queue.append(DataTransfer(self._fields[name], DataTransferKind.HOST_TO_DEVICE))
 
     def to_gpu(self, name):
+        super().to_gpu(name)
         if name in self._custom_data_transfer_functions:
             self.call_queue.append('Custom Tranfer Function')
         else:
@@ -151,17 +172,18 @@ class GraphDataHandling(pystencils.datahandling.SerialDataHandling):
         for name in names:
             gpu = target == 'cpu'
             self.call_queue.append(Communication(self._fields[name], stencil, gpu))
+        super().synchronization_function(names, stencil=None, target=None, **_)
 
     def __str__(self):
-        return '\n'.join(str(self.call_queue))
+        return '\n'.join(str(c) for c in self.call_queue)
 
     def create_timeloop(self, *args, **kwargs):
         return self.TimeLoop(self, *args, **kwargs)
 
-    def fill(self, array_name: str, val, value_idx,
+    def fill(self, array_name: str, val, value_idx=None,
              slice_obj=None, ghost_layers=False, inner_ghost_layers=False) -> None:
-        self.call_queue('Fill ' + array_name)
-        super().fill(self, array_name, val, value_idx, slice_obj, ghost_layers, inner_ghost_layers)
+        self.call_queue.append('Fill ' + array_name)
+        super().fill(array_name, val, value_idx, slice_obj, ghost_layers, inner_ghost_layers)
 
     # TODO
     # def reduce_float_sequence(self, sequence, operation, all_reduce=False) -> np.array:
diff --git a/pystencils_tests/test_graph_datahandling.py b/pystencils_tests/test_graph_datahandling.py
index d494576baa612613d0e5e7f3890b9934431a994a..441b9ff38f4cb4d28a5baee5302f48fc96b68385 100644
--- a/pystencils_tests/test_graph_datahandling.py
+++ b/pystencils_tests/test_graph_datahandling.py
@@ -20,7 +20,7 @@ from pystencils.slicing import slice_from_direction
 pytest.importorskip('lbmpy')
 
 
-def create_lid_driven_cavity(domain_size=None, lid_velocity=0.005, lbm_kernel=None, parallel=False,
+def create_lid_driven_cavity(domain_size=None, lid_velocity=0.005, lbm_kernel=None,
                              data_handling=None, **kwargs):
     """Creates a lid driven cavity scenario.
 
@@ -42,7 +42,11 @@ def create_lid_driven_cavity(domain_size=None, lid_velocity=0.005, lbm_kernel=No
                                           periodicity=False,
                                           default_ghost_layers=1,
                                           default_target=target)
-    step = LatticeBoltzmannStep(data_handling=data_handling, lbm_kernel=lbm_kernel, name="ldc", **kwargs)
+    step = LatticeBoltzmannStep(data_handling=data_handling,
+                                lbm_kernel=lbm_kernel,
+                                name="ldc",
+                                timeloop_creation_function=data_handling.create_timeloop,
+                                **kwargs)
 
     my_ubb = UBB(velocity=[lid_velocity, 0, 0][:step.method.dim])
     step.boundary_handling.set_boundary(my_ubb, slice_from_direction('N', step.dim))
@@ -55,7 +59,7 @@ def create_lid_driven_cavity(domain_size=None, lid_velocity=0.005, lbm_kernel=No
 def ldc_setup(**kwargs):
     ldc = create_lid_driven_cavity(relaxation_rate=1.7, **kwargs)
     ldc.run(50)
-    return ldc.density_slice()
+    return ldc
 
 
 def test_graph_datahandling():
@@ -64,5 +68,5 @@ def test_graph_datahandling():
     print("--- LDC 2D test ---")
 
     opt_params = {'target': 'gpu', 'gpu_indexing_params': {'block_size': (8, 4, 2)}}
-    lbm_step: LatticeBoltzmannStep = ldc_setup(domain_size=(10, 15), parallel=False, optimization=opt_params)
+    lbm_step: LatticeBoltzmannStep = ldc_setup(domain_size=(10, 15), optimization=opt_params)
     print(lbm_step._data_handling)