diff --git a/pystencils/datahandling/pycuda.py b/pystencils/datahandling/pycuda.py
new file mode 100644
index 0000000000000000000000000000000000000000..7309c54aee2a49e7c96dd4e1d044113edfbeb28a
--- /dev/null
+++ b/pystencils/datahandling/pycuda.py
@@ -0,0 +1,42 @@
+try:
+    import pycuda.gpuarray as gpuarray
+except ImportError:
+    gpuarray = None
+import numpy as np
+
+import pystencils
+
+
+class PyCudaArrayHandler:
+
+    def __init__(self):
+        import pycuda.autoinit  # NOQA
+
+    def zeros(self, shape, dtype=np.float64, order='C'):
+        return gpuarray.zeros(shape, dtype, order)
+
+    def ones(self, shape, dtype, order='C'):
+        return gpuarray.ones(shape, dtype, order)
+
+    def empty(self, shape, dtype=np.float64, layout=None):
+        if layout:
+            cpu_array = pystencils.field.create_numpy_array_with_layout(shape, dtype, layout)
+            return self.from_numpy(cpu_array)
+        else:
+            return gpuarray.empty(shape, dtype)
+
+    def from_numpy(self, array, dtype=np.float64, layout=None):
+        return gpuarray.to_gpu(array)
+
+    def to_gpu(self, shape, dtype=np.float64, order='C'):
+        gpuarray.ones(shape, dtype, order)
+
+    def upload(gpuarray, numpy_array):
+        gpuarray.set(numpy_array)
+
+    def download(gpuarray, numpy_array):
+        gpuarray.get(numpy_array)
+
+    def randn(self, shape, dtype=np.float64):
+        cpu_array = np.random.randn(*shape).astype(dtype)
+        return self.from_numpy(cpu_array)
diff --git a/pystencils/datahandling/pyopencl.py b/pystencils/datahandling/pyopencl.py
new file mode 100644
index 0000000000000000000000000000000000000000..acc99ef298a949f4998fece481cee2450f923a74
--- /dev/null
+++ b/pystencils/datahandling/pyopencl.py
@@ -0,0 +1,40 @@
+try:
+    import pyopencl.array as gpuarray
+except ImportError:
+    gpuarray = None
+
+import numpy as np
+
+import pystencils
+
+
+class PyOpenClArrayHandler:
+
+    def __init__(self, queue):
+        self.queue = queue
+
+    def zeros(self, shape, dtype=np.float64, order='C'):
+        return gpuarray.zeros(shape, dtype, order)
+
+    def ones(self, shape, dtype, order='C'):
+        return gpuarray.ones(self.queue, shape, dtype, order)
+
+    def empty(self, shape, dtype=np.float64, layout=None):
+        if layout:
+            cpu_array = pystencils.field.create_numpy_array_with_layout(shape, dtype, layout)
+            return self.from_numpy(cpu_array)
+        else:
+            return gpuarray.empty(shape, dtype)
+
+    def from_numpy(self, array):
+        return gpuarray.to_device(self.queue, array)
+
+    def upload(self, gpuarray, numpy_array):
+        gpuarray.set(self.queue, numpy_array)
+
+    def download(self, gpuarray, numpy_array):
+        gpuarray.get(numpy_array)
+
+    def randn(self, shape, dtype=np.float64):
+        cpu_array = np.random.randn(*shape).astype(dtype)
+        return self.from_numpy(cpu_array)
diff --git a/pystencils/datahandling/serial_datahandling.py b/pystencils/datahandling/serial_datahandling.py
index 8c79a0931f06fad7c7ab58143cf7058a3f52dbac..8287a36f210c7d313f1f0def5f4ca9b76c9998dc 100644
--- a/pystencils/datahandling/serial_datahandling.py
+++ b/pystencils/datahandling/serial_datahandling.py
@@ -6,22 +6,24 @@ import numpy as np
 
 from pystencils.datahandling.blockiteration import SerialBlock
 from pystencils.datahandling.datahandling_interface import DataHandling
+from pystencils.datahandling.pycuda import PyCudaArrayHandler
+from pystencils.datahandling.pyopencl import PyOpenClArrayHandler
 from pystencils.field import (
     Field, create_numpy_array_with_layout, layout_string_to_tuple, spatial_layout_string_to_tuple)
 from pystencils.slicing import normalize_slice, remove_ghost_layers
 from pystencils.utils import DotDict
 
-try:
-    import pycuda.gpuarray as gpuarray
-    import pycuda.autoinit  # NOQA
-except ImportError:
-    gpuarray = None
-
 
 class SerialDataHandling(DataHandling):
 
-    def __init__(self, domain_size: Sequence[int], default_ghost_layers: int = 1, default_layout: str = 'SoA',
-                 periodicity: Union[bool, Sequence[bool]] = False, default_target: str = 'cpu') -> None:
+    def __init__(self,
+                 domain_size: Sequence[int],
+                 default_ghost_layers: int = 1,
+                 default_layout: str = 'SoA',
+                 periodicity: Union[bool, Sequence[bool]] = False,
+                 default_target: str = 'cpu',
+                 opencl_queue=None,
+                 array_handler=None) -> None:
         """
         Creates a data handling for single node simulations.
 
@@ -43,6 +45,19 @@ class SerialDataHandling(DataHandling):
         self.custom_data_gpu = DotDict()
         self._custom_data_transfer_functions = {}
 
+        if array_handler:
+            self.array_handler = array_handler
+        else:
+            try:
+                self.array_handler = PyCudaArrayHandler()
+            except Exception:
+                self.array_handler = None
+
+            if opencl_queue:
+                default_target = 'gpu'
+                assert opencl_queue
+                self.array_handler = PyOpenClArrayHandler(opencl_queue)
+
         if periodicity is None or periodicity is False:
             periodicity = [False] * self.dim
         if periodicity is True:
@@ -125,7 +140,7 @@ class SerialDataHandling(DataHandling):
         if gpu:
             if name in self.gpu_arrays:
                 raise ValueError("GPU Field with this name already exists")
-            self.gpu_arrays[name] = gpuarray.to_gpu(cpu_arr)
+            self.gpu_arrays[name] = self.array_handler.to_gpu(cpu_arr)
 
         assert all(f.name != name for f in self.fields.values()), "Symbolic field with this name already exists"
         self.fields[name] = Field.create_from_numpy_array(name, cpu_arr, index_dimensions=index_dimensions)
@@ -234,14 +249,14 @@ class SerialDataHandling(DataHandling):
             transfer_func = self._custom_data_transfer_functions[name][1]
             transfer_func(self.custom_data_gpu[name], self.custom_data_cpu[name])
         else:
-            self.gpu_arrays[name].get(self.cpu_arrays[name])
+            self.array_handler.download(self.gpu_arrays[name], self.cpu_arrays[name])
 
     def to_gpu(self, name):
         if name in self._custom_data_transfer_functions:
             transfer_func = self._custom_data_transfer_functions[name][0]
             transfer_func(self.custom_data_gpu[name], self.custom_data_cpu[name])
         else:
-            self.gpu_arrays[name].set(self.cpu_arrays[name])
+            self.array_handler.upload(self.gpu_arrays[name], self.cpu_arrays[name])
 
     def is_on_gpu(self, name):
         return name in self.gpu_arrays
diff --git a/pystencils/gpucuda/kernelcreation.py b/pystencils/gpucuda/kernelcreation.py
index 4430abba6e8aaacfd4d2b00286af46d9eb879741..eecfe278e4378cdbed8738275d2cfe813d350d7b 100644
--- a/pystencils/gpucuda/kernelcreation.py
+++ b/pystencils/gpucuda/kernelcreation.py
@@ -20,7 +20,7 @@ def create_cuda_kernel(assignments,
     all_fields = fields_read.union(fields_written)
     read_only_fields = set([f.name for f in fields_read - fields_written])
 
-    buffers = set([f for f in all_fields if FieldType.is_buffer(f)])
+    buffers = set([f for f in all_fields if FieldType.is_buffer(f) or FieldType.is_custom(f)])
     fields_without_buffers = all_fields - buffers
 
     field_accesses = set()