diff --git a/lbmpy/boundaries/__init__.py b/lbmpy/boundaries/__init__.py
index 6dd746dd890c8d0b23eae9fd7f5dfeded2a2ce64..966ec65d789e3c98fc1e8c25a5b2aeb20c958e90 100644
--- a/lbmpy/boundaries/__init__.py
+++ b/lbmpy/boundaries/__init__.py
@@ -2,7 +2,9 @@ from lbmpy.boundaries.boundaryconditions import (
     UBB, FixedDensity, DiffusionDirichlet, SimpleExtrapolationOutflow,
     ExtrapolationOutflow, NeumannByCopy, NoSlip, StreamInConstant, FreeSlip)
 from lbmpy.boundaries.boundaryhandling import LatticeBoltzmannBoundaryHandling
+from lbmpy.boundaries.wall_models import WallFunctionBounce
 
 __all__ = ['NoSlip', 'FreeSlip', 'UBB', 'SimpleExtrapolationOutflow', 'ExtrapolationOutflow',
            'FixedDensity', 'DiffusionDirichlet', 'NeumannByCopy',
-           'LatticeBoltzmannBoundaryHandling', 'StreamInConstant']
+           'LatticeBoltzmannBoundaryHandling', 'StreamInConstant',
+           'WallFunctionBounce']
diff --git a/lbmpy/boundaries/wall_models.py b/lbmpy/boundaries/wall_models.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec1d3ee268ecba49a4e806e0e8e1e5744c468505
--- /dev/null
+++ b/lbmpy/boundaries/wall_models.py
@@ -0,0 +1,47 @@
+import sympy as sp
+from pystencils import Assignment
+from pystencils.stencil import offset_to_direction_string
+
+from lbmpy.advanced_streaming.indexing import MirroredStencilDirections
+from lbmpy.boundaries.boundaryconditions import LbBoundary
+
+
+class WallFunctionBounce(LbBoundary):
+    """
+    Wall function based on the bounce back idea.
+
+    Args:
+        stencil: LBM stencil which is used for the simulation
+        normal_direction: optional normal direction. If the Free slip boundary is applied to a certain side in the
+                          domain it is not necessary to calculate the normal direction since it can be stated for all
+                          boundary cells. This reduces the memory space for the index array significantly.
+        name: optional name of the boundary.
+    """
+
+    def __init__(self, stencil, normal_direction, name=None):
+        """Set an optional name here, to mark boundaries, for example for force evaluations"""
+        self.stencil = stencil
+
+        if len(normal_direction) - normal_direction.count(0) != 1:
+            raise ValueError("Only normal directions for straight walls are supported for example (0, 1, 0) for "
+                             "a WallFunctionBounce applied to the southern boundary of the domain")
+
+        self.mirror_axis = normal_direction.index(*[dir for dir in normal_direction if dir != 0])
+
+        self.normal_direction = normal_direction
+        self.dim = len(stencil[0])
+
+        if name is None:
+            name = f"WFB : {offset_to_direction_string([-x for x in normal_direction])}"
+
+        super(WallFunctionBounce, self).__init__(name)
+
+    def get_additional_code_nodes(self, lb_method):
+        return [MirroredStencilDirections(self.stencil, self.mirror_axis)]
+
+    def __call__(self, f_out, f_in, dir_symbol, inv_dir, lb_method, index_field):
+        normal_direction = self.normal_direction
+        mirrored_stencil_symbol = MirroredStencilDirections._mirrored_symbol(self.mirror_axis)
+        mirrored_direction = inv_dir[sp.IndexedBase(mirrored_stencil_symbol, shape=(1,))[dir_symbol]]
+
+        return Assignment(f_in(inv_dir[dir_symbol]), f_in[normal_direction](mirrored_direction))