diff --git a/backends/cbackend.py b/backends/cbackend.py
index 0997ff97e44aa2fe44406e99462dc7382d0e8560..7710c65ee6a0d09bc2d28106a9ef10a1d707f6df 100644
--- a/backends/cbackend.py
+++ b/backends/cbackend.py
@@ -1,6 +1,6 @@
 import sympy as sp
 
-from pystencils.bitoperations import xor, rightShift, leftShift
+from pystencils.bitoperations import xor, rightShift, leftShift, bitwiseAnd, bitwiseOr
 
 try:
     from sympy.utilities.codegen import CCodePrinter
@@ -210,15 +210,18 @@ class CustomSympyPrinter(CCodePrinter):
         return res
 
     def _print_Function(self, expr):
+        functionMap = {
+            xor: '^',
+            rightShift: '>>',
+            leftShift: '<<',
+            bitwiseOr: '|',
+            bitwiseAnd: '&',
+        }
         if expr.func == castFunc:
             arg, type = expr.args
             return "*((%s)(& %s))" % (PointerType(type), self._print(arg))
-        elif expr.func == xor:
-            return "(%s ^ %s" % (self._print(expr.args[0]), self._print(expr.args[1]))
-        elif expr.func == rightShift:
-            return "(%s >> %s)" % (self._print(expr.args[0]), self._print(expr.args[1]))
-        elif expr.func == leftShift:
-            return "(%s << %s)" % (self._print(expr.args[0]), self._print(expr.args[1]))
+        elif expr.func in functionMap:
+            return "(%s %s %s)" % (self._print(expr.args[0]), functionMap[expr.func], self._print(expr.args[1]))
         else:
             return super(CustomSympyPrinter, self)._print_Function(expr)
 
diff --git a/bitoperations.py b/bitoperations.py
index fa73e218f1a211324c618332972a1228c4d07d31..a5fdd7612b562c77fb25748142a6412b4d397351 100644
--- a/bitoperations.py
+++ b/bitoperations.py
@@ -2,4 +2,5 @@ import sympy as sp
 xor = sp.Function("⊻")
 rightShift = sp.Function("rshift")
 leftShift = sp.Function("lshift")
-
+bitwiseAnd = sp.Function("Bit&")
+bitwiseOr = sp.Function("Bit|")
diff --git a/boundaries/boundaryconditions.py b/boundaries/boundaryconditions.py
index 80906feb7bb7480b7d9e529aa4f6b9d2ba6bac2f..0a799cdac8722d5d42ce8c6bfb136e29cbb351f5 100644
--- a/boundaries/boundaryconditions.py
+++ b/boundaries/boundaryconditions.py
@@ -58,7 +58,7 @@ class Neumann(Boundary):
             if not field.hasFixedIndexShape:
                 raise NotImplementedError("Neumann boundary works only for fields with fixed index shape")
             indexIter = product(*(range(i) for i in field.indexShape))
-            return [sp.Eq(field[neighbor](idx), field(idx)) for idx in indexIter]
+            return [sp.Eq(field[neighbor](*idx), field(*idx)) for idx in indexIter]
 
     def __hash__(self):
         # All boundaries of these class behave equal -> should also be equal
diff --git a/boundaries/boundaryhandling.py b/boundaries/boundaryhandling.py
index 9591acad7aa92734829200017e4282d03b358af9..7787346c34e60e25097a4befa8a8c0b5b44060fc 100644
--- a/boundaries/boundaryhandling.py
+++ b/boundaries/boundaryhandling.py
@@ -7,40 +7,57 @@ from pystencils.cache import memorycache
 from pystencils.data_types import createType
 
 
+class FlagInterface:
+    FLAG_DTYPE = np.uint32
+
+    def __init__(self, dataHandling, flagFieldName):
+        self.flagFieldName = flagFieldName
+        self.domainFlag = self.FLAG_DTYPE(1 << 0)
+        self._nextFreeFlag = 1
+        self.dataHandling = dataHandling
+
+        # Add flag field to data handling if it does not yet exist
+        if dataHandling.hasData(self.flagFieldName):
+            raise ValueError("There is already a boundary handling registered at the data handling."
+                             "If you want to add multiple handlings, choose a different name.")
+
+        dataHandling.addArray(self.flagFieldName, dtype=self.FLAG_DTYPE, cpu=True, gpu=False)
+        ffGhostLayers = dataHandling.ghostLayersOfField(self.flagFieldName)
+        for b in dataHandling.iterate(ghostLayers=ffGhostLayers):
+            b[self.flagFieldName].fill(self.domainFlag)
+
+    def allocateNextFlag(self):
+        result = self.FLAG_DTYPE(1 << self._nextFreeFlag)
+        self._nextFreeFlag += 1
+        return result
+
+
 class BoundaryHandling:
 
-    def __init__(self, dataHandling, fieldName, stencil, name="boundaryHandling", target='cpu', openMP=True):
+    def __init__(self, dataHandling, fieldName, stencil, name="boundaryHandling", flagInterface=None,
+                 target='cpu', openMP=True):
         assert dataHandling.hasData(fieldName)
 
         self._dataHandling = dataHandling
         self._fieldName = fieldName
-        self._flagFieldName = name + "Flags"
         self._indexArrayName = name + "IndexArrays"
         self._target = target
         self._openMP = openMP
         self._boundaryObjectToBoundaryInfo = {}
-        self._fluidFlag = 1 << 0
-        self._nextFreeFlag = 1
         self.stencil = stencil
         self._dirty = True
-
-        # Add flag field to data handling if it does not yet exist
-        if dataHandling.hasData(self._flagFieldName) or dataHandling.hasData(self._indexArrayName):
-            raise ValueError("There is already a boundary handling registered at the data handling."
-                             "If you want to add multiple handlings, choose a different name.")
+        self.flagInterface = flagInterface if flagInterface is not None else FlagInterface(dataHandling, name + "Flags")
 
         gpu = self._target == 'gpu'
-        dataHandling.addArray(self._flagFieldName, dtype=np.uint32, cpu=True, gpu=False)
         dataHandling.addCustomClass(self._indexArrayName, self.IndexFieldBlockData, cpu=True, gpu=gpu)
 
-        ffGhostLayers = self._dataHandling.ghostLayersOfField(self._flagFieldName)
-        for b in self._dataHandling.iterate(ghostLayers=ffGhostLayers):
-            b[self._flagFieldName].fill(self._fluidFlag)
-
     @property
     def dataHandling(self):
         return self._dataHandling
 
+    def getFlag(self, boundaryObj):
+        return self._boundaryObjectToBoundaryInfo[boundaryObj].flag
+
     @property
     def shape(self):
         return self._dataHandling.shape
@@ -55,16 +72,16 @@ class BoundaryHandling:
 
     @property
     def flagArrayName(self):
-        return self._flagFieldName
+        return self.flagInterface.flagFieldName
 
     def getBoundaryNameToFlagDict(self):
         result = {bObj.name: bInfo.flag for bObj, bInfo in self._boundaryObjectToBoundaryInfo.items()}
-        result['fluid'] = self._fluidFlag
+        result['domain'] = self.flagInterface.domainFlag
         return result
 
     def getMask(self, sliceObj, boundaryObj, inverse=False):
-        if isinstance(boundaryObj, str) and boundaryObj.lower() == 'fluid':
-            flag = self._fluidFlag
+        if isinstance(boundaryObj, str) and boundaryObj.lower() == 'domain':
+            flag = self.flagInterface.domainFlag
         else:
             flag = self._boundaryObjectToBoundaryInfo[boundaryObj].flag
 
@@ -77,7 +94,8 @@ class BoundaryHandling:
                 result = np.logical_not(result)
             return result
 
-    def setBoundary(self, boundaryObject, sliceObj=None, maskCallback=None, ghostLayers=True, innerGhostLayers=True):
+    def setBoundary(self, boundaryObject, sliceObj=None, maskCallback=None, ghostLayers=True, innerGhostLayers=True,
+                    replace=True):
         """
         Sets boundary using either a rectangular slice, a boolean mask or a combination of both
 
@@ -94,20 +112,35 @@ class BoundaryHandling:
                              midpoint x coordinate smaller than 10.
         :param ghostLayers see DataHandling.iterate()
         """
-        if isinstance(boundaryObject, str) and boundaryObject.lower() == 'fluid':
-            flag = self._fluidFlag
+        if isinstance(boundaryObject, str) and boundaryObject.lower() == 'domain':
+            flag = self.flagInterface.domainFlag
         else:
-            flag = self._getFlagForBoundary(boundaryObject)
+            flag = self._addBoundary(boundaryObject)
 
         for b in self._dataHandling.iterate(sliceObj, ghostLayers=ghostLayers, innerGhostLayers=innerGhostLayers):
-            flagArr = b[self._flagFieldName]
+            flagArr = b[self.flagInterface.flagFieldName]
             if maskCallback is not None:
                 mask = maskCallback(*b.midpointArrays)
-                flagArr[mask] = flag
+                if replace:
+                    flagArr[mask] = flag
+                else:
+                    np.bitwise_or(flagArr, flag, where=mask, out=flagArr)
+                    np.bitwise_and(flagArr, ~self.flagInterface.domainFlag, where=mask, out=flagArr)
             else:
-                flagArr.fill(flag)
+                if replace:
+                    flagArr.fill(flag)
+                else:
+                    np.bitwise_or(flagArr, flag, out=flagArr)
+                    np.bitwise_and(flagArr, ~self.flagInterface.domainFlag, out=flagArr)
+
+        self._dirty = True
 
+        return flag
+
+    def setBoundaryWhereFlagIsSet(self, boundaryObject, flag):
+        self._addBoundary(boundaryObject, flag)
         self._dirty = True
+        return flag
 
     def prepare(self):
         if not self._dirty:
@@ -119,7 +152,7 @@ class BoundaryHandling:
         if self._dirty:
             self.prepare()
         else:
-            ffGhostLayers = self._dataHandling.ghostLayersOfField(self._flagFieldName)
+            ffGhostLayers = self._dataHandling.ghostLayersOfField(self.flagInterface.flagFieldName)
             for b in self._dataHandling.iterate(ghostLayers=ffGhostLayers):
                 for bObj, setter in b[self._indexArrayName].boundaryObjectToDataSetter.items():
                     self._boundaryDataInitialization(bObj, setter, **kwargs)
@@ -131,44 +164,51 @@ class BoundaryHandling:
         for b in self._dataHandling.iterate(gpu=self._target == 'gpu'):
             for bObj, idxArr in b[self._indexArrayName].boundaryObjectToIndexList.items():
                 kwargs[self._fieldName] = b[self._fieldName]
-                self._boundaryObjectToBoundaryInfo[bObj].kernel(indexField=idxArr, **kwargs)
+                kwargs['indexField'] = idxArr
+                dataUsedInKernel = (p.fieldName
+                                    for p in self._boundaryObjectToBoundaryInfo[bObj].kernel.parameters
+                                    if p.isFieldPtrArgument and p.fieldName not in kwargs)
+                kwargs.update({name: b[name] for name in dataUsedInKernel})
+
+                self._boundaryObjectToBoundaryInfo[bObj].kernel(**kwargs)
 
     def geometryToVTK(self, fileName='geometry', boundaries='all', ghostLayers=False):
         """
         Writes a VTK field where each cell with the given boundary is marked with 1, other cells are 0
         This can be used to display the simulation geometry in Paraview
         :param fileName: vtk filename
-        :param boundaries: boundary object, or special string 'fluid' for fluid cells or special string 'all' for all
+        :param boundaries: boundary object, or special string 'domain' for domain cells or special string 'all' for all
                          boundary conditions.
                          can also  be a sequence, to write multiple boundaries to VTK file
         :param ghostLayers: number of ghost layers to write, or True for all, False for none
         """
         if boundaries == 'all':
-            boundaries = list(self._boundaryObjectToBoundaryInfo.keys()) + ['fluid']
+            boundaries = list(self._boundaryObjectToBoundaryInfo.keys()) + ['domain']
         elif not hasattr(boundaries, "__len__"):
             boundaries = [boundaries]
 
         masksToName = {}
         for b in boundaries:
-            if b == 'fluid':
-                masksToName[self._fluidFlag] = 'fluid'
+            if b == 'domain':
+                masksToName[self.flagInterface.domainFlag] = 'domain'
             else:
                 masksToName[self._boundaryObjectToBoundaryInfo[b].flag] = b.name
 
-        writer = self.dataHandling.vtkWriterFlags(fileName, self._flagFieldName, masksToName, ghostLayers=ghostLayers)
+        writer = self.dataHandling.vtkWriterFlags(fileName, self.flagInterface.flagFieldName,
+                                                  masksToName, ghostLayers=ghostLayers)
         writer(1)
 
     # ------------------------------ Implementation Details ------------------------------------------------------------
 
-    def _getFlagForBoundary(self, boundaryObject):
+    def _addBoundary(self, boundaryObject, flag=None):
         if boundaryObject not in self._boundaryObjectToBoundaryInfo:
             symbolicIndexField = Field.createGeneric('indexField', spatialDimensions=1,
                                                      dtype=numpyDataTypeForBoundaryObject(boundaryObject, self.dim))
             ast = self._createBoundaryKernel(self._dataHandling.fields[self._fieldName],
                                              symbolicIndexField, boundaryObject)
-            boundaryInfo = self.BoundaryInfo(boundaryObject, flag=1 << self._nextFreeFlag, kernel=ast.compile())
-
-            self._nextFreeFlag += 1
+            if flag is None:
+                flag = self.flagInterface.allocateNextFlag()
+            boundaryInfo = self.BoundaryInfo(boundaryObject, flag=flag, kernel=ast.compile())
             self._boundaryObjectToBoundaryInfo[boundaryObject] = boundaryInfo
         return self._boundaryObjectToBoundaryInfo[boundaryObject].flag
 
@@ -178,15 +218,15 @@ class BoundaryHandling:
 
     def _createIndexFields(self):
         dh = self._dataHandling
-        ffGhostLayers = dh.ghostLayersOfField(self._flagFieldName)
+        ffGhostLayers = dh.ghostLayersOfField(self.flagInterface.flagFieldName)
         for b in dh.iterate(ghostLayers=ffGhostLayers):
-            flagArr = b[self._flagFieldName]
+            flagArr = b[self.flagInterface.flagFieldName]
             pdfArr = b[self._fieldName]
             indexArrayBD = b[self._indexArrayName]
             indexArrayBD.clear()
             for bInfo in self._boundaryObjectToBoundaryInfo.values():
-                idxArr = createBoundaryIndexArray(flagArr, self.stencil, bInfo.flag, self._fluidFlag,
-                                                  bInfo.boundaryObject, dh.ghostLayersOfField(self._flagFieldName))
+                idxArr = createBoundaryIndexArray(flagArr, self.stencil, bInfo.flag, self.flagInterface.domainFlag,
+                                                  bInfo.boundaryObject, ffGhostLayers)
                 if idxArr.size == 0:
                     continue
 
@@ -251,7 +291,7 @@ class BoundaryDataSetter:
         self.coordMap = {0: 'x', 1: 'y', 2: 'z'}
         self.ghostLayers = ghostLayers
 
-    def fluidCellPositions(self, coord):
+    def nonBoundaryCellPositions(self, coord):
         assert coord < self.dim
         return self.indexArray[self.coordMap[coord]] + self.offset[coord] - self.ghostLayers + 0.5
 
@@ -261,11 +301,11 @@ class BoundaryDataSetter:
 
     @memorycache()
     def linkPositions(self, coord):
-        return self.fluidCellPositions(coord) + 0.5 * self.linkOffsets()[:, coord]
+        return self.nonBoundaryCellPositions(coord) + 0.5 * self.linkOffsets()[:, coord]
 
     @memorycache()
     def boundaryCellPositions(self, coord):
-        return self.fluidCellPositions(coord) + self.linkOffsets()[:, coord]
+        return self.nonBoundaryCellPositions(coord) + self.linkOffsets()[:, coord]
 
     def __setitem__(self, key, value):
         if key not in self.boundaryDataNames:
diff --git a/boundaries/inkernel.py b/boundaries/inkernel.py
new file mode 100644
index 0000000000000000000000000000000000000000..777e7090a50673c616f617a24349b33053aba62b
--- /dev/null
+++ b/boundaries/inkernel.py
@@ -0,0 +1,43 @@
+import sympy as sp
+from pystencils import Field, TypedSymbol
+from pystencils.bitoperations import bitwiseAnd
+from pystencils.boundaries.boundaryhandling import FlagInterface
+from pystencils.data_types import createType
+
+
+def addNeumannBoundary(eqs, fields, flagField, boundaryFlag="neumannFlag", inverseFlag=False):
+    """
+    Replaces all neighbor accesses by flag field guarded accesses.
+    If flag in neighboring cell is set, the center value is used instead
+    :param eqs: list of equations containing field accesses to direct neighbors
+    :param fields: fields for which the Neumann boundary should be applied
+    :param flagField: integer field marking boundary cells
+    :param boundaryFlag: if flag field has value 'boundaryFlag' (no bitoperations yet) the cell is assumed to be boundary
+    :param inverseFlag: if true, boundary cells are where flagfield has not the value of boundaryFlag
+    :return: list of equations with guarded field accesses
+    """
+    if not hasattr(fields, "__len__"):
+        fields = [fields]
+    fields = set(fields)
+
+    if type(boundaryFlag) is str:
+        boundaryFlag = TypedSymbol(boundaryFlag, dtype=createType(FlagInterface.FLAG_DTYPE))
+
+    substitutions = {}
+    for eq in eqs:
+        for fa in eq.atoms(Field.Access):
+            if fa.field not in fields:
+                continue
+            if not all(offset in (-1, 0, 1) for offset in fa.offsets):
+                raise ValueError("Works only for single neighborhood stencils")
+            if all(offset == 0 for offset in fa.offsets):
+                continue
+
+            if inverseFlag:
+                condition = sp.Eq(bitwiseAnd(flagField[tuple(fa.offsets)], boundaryFlag), 0)
+            else:
+                condition = sp.Ne(bitwiseAnd(flagField[tuple(fa.offsets)], boundaryFlag), 0)
+
+            center = fa.field(*fa.index)
+            substitutions[fa] = sp.Piecewise((center, condition), (fa, True))
+    return [eq.subs(substitutions) for eq in eqs]