diff --git a/boundaries/boundaryconditions.py b/boundaries/boundaryconditions.py
index 19d2d690e640ccd00a6a66d7cef03f49741d0863..e7146e3fb953159ac586fec7dd4f8ec088416077 100644
--- a/boundaries/boundaryconditions.py
+++ b/boundaries/boundaryconditions.py
@@ -51,6 +51,11 @@ class Boundary(object):
 
 
 class NoSlip(Boundary):
+
+    def __init__(self, name=None):
+        """Set an optional name here, to mark boundaries, for example for force evaluations"""
+        self._name = name
+
     """No-Slip, (half-way) simple bounce back boundary condition, enforcing zero velocity at obstacle"""
     def __call__(self, pdfField, directionSymbol, lbMethod, **kwargs):
         neighbor = offsetFromDir(directionSymbol, lbMethod.dim)
@@ -58,11 +63,20 @@ class NoSlip(Boundary):
         return [sp.Eq(pdfField[neighbor](inverseDir), pdfField(directionSymbol))]
 
     def __hash__(self):
-        # All boundaries of these class behave equal -> should also be equal
-        return hash("NoSlip")
+        # All boundaries of these class behave equal -> should also be equal (as long as name is equal)
+        return hash(self.name)
 
     def __eq__(self, other):
-        return type(other) == NoSlip
+        if not isinstance(other, NoSlip):
+            return False
+        return self.name == other.name
+
+    @property
+    def name(self):
+        if self._name:
+            return self._name
+        else:
+            return type(self).__name__
 
 
 class NoSlipFullWay(Boundary):
diff --git a/boundaries/forceevaluation.py b/boundaries/forceevaluation.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e741d733379b48fcfdefa3dd9199b6f77077707
--- /dev/null
+++ b/boundaries/forceevaluation.py
@@ -0,0 +1,52 @@
+import numpy as np
+from lbmpy.stencils import inverseDirection
+
+
+def calculateForceOnNoSlipBoundary(boundaryObject, boundaryHandling, pdfArray):
+    indArr = boundaryHandling.getBoundaryIndexArray(boundaryObject)
+    method = boundaryHandling.lbMethod
+
+    stencil = np.array(method.stencil)
+
+    if method.dim == 2:
+        x, y = indArr['x'], indArr['y']
+        values = 2 * pdfArray[x, y,  indArr['dir']]
+    else:
+        assert method.dim == 3
+        x, y, z = indArr['x'], indArr['y'], indArr['z']
+        values = 2 * pdfArray[x, y, z, indArr['dir']]
+
+    forces = stencil[indArr['dir']] * values[:, np.newaxis]
+    return forces.sum(axis=0)
+
+
+def calculateForceOnBoundary(boundaryObject, boundaryHandling, pdfArray):
+    indArr = boundaryHandling.getBoundaryIndexArray(boundaryObject)
+    method = boundaryHandling.lbMethod
+
+    stencil = np.array(method.stencil)
+    invDirection = np.array([method.stencil.index(inverseDirection(d))
+                            for d in method.stencil])
+
+    if method.dim == 2:
+        x, y = indArr['x'], indArr['y']
+        offsets = stencil[indArr['dir']]
+
+        fluidValues = pdfArray[x, y,  indArr['dir']]
+        boundaryValues = pdfArray[x + offsets[:, 0],
+                                  y + offsets[:, 1],
+                                  invDirection[indArr['dir']]]
+    else:
+        assert method.dim == 3
+        x, y, z = indArr['x'], indArr['y'], indArr['z']
+        offsets = stencil[indArr['dir']]
+
+        fluidValues = pdfArray[x, y, z, indArr['dir']]
+        boundaryValues = pdfArray[x + offsets[:, 0],
+                                  y + offsets[:, 1],
+                                  z + offsets[:, 2],
+                                  invDirection[indArr['dir']]]
+
+    values = fluidValues + boundaryValues
+    forces = stencil[indArr['dir']] * values[:, np.newaxis]
+    return forces.sum(axis=0)
diff --git a/boundaries/handlinginterface.py b/boundaries/handlinginterface.py
index de3f28fbc5bae24fae2fe1edba9231344a6a620a..ba768e4c448b225f4a471b9b172aff42362e995b 100644
--- a/boundaries/handlinginterface.py
+++ b/boundaries/handlinginterface.py
@@ -113,6 +113,10 @@ class GenericBoundaryHandling(object):
         if target not in ('cpu', 'gpu'):
             raise ValueError("Invalid target '%s' . Allowed values: 'cpu' or 'gpu'" % (target,))
 
+    @property
+    def lbMethod(self):
+        return self._lbMethod
+
     def getBoundaryNameToFlagDict(self):
         result = {self._flagFieldInterface.getName(o): self._flagFieldInterface.getFlag(o) for o in self._boundaryInfos}
         result['fluid'] = self._flagFieldInterface.getFlag('fluid')
diff --git a/scenarios.py b/scenarios.py
index d1ab830fc5d7b1d2fcc707822777ff2024a005e4..0687bb277f7ab345cbc361edf202efb60dfc5726 100644
--- a/scenarios.py
+++ b/scenarios.py
@@ -26,6 +26,7 @@ that defines the viscosity of the fluid (valid values being between 0 and 2).
 import numpy as np
 import sympy as sp
 
+from lbmpy.boundaries.forceevaluation import calculateForceOnBoundary, calculateForceOnNoSlipBoundary
 from lbmpy.geometry import setupChannelWalls, addParabolicVelocityInflow
 from pystencils.field import getLayoutOfArray, createNumpyArrayWithLayout
 from pystencils.slicing import sliceFromDirection, addGhostLayers, removeGhostLayers, normalizeSlice, makeSlice
@@ -346,6 +347,14 @@ class Scenario(object):
         """Equation collection defining the LBM update rule (already in simplified form)"""
         return self._lbmKernel.updateRule
 
+    def calculateForceOnBoundary(self, boundaryObject):
+        """Computes force on boundary using simple momentum exchange method"""
+        if isinstance(boundaryObject, NoSlip):
+            return calculateForceOnNoSlipBoundary(boundaryObject, self.boundaryHandling, self._pdfArrays[0])
+        else:
+            self.runBoundaryHandlingOnly()
+            return calculateForceOnBoundary(boundaryObject, self.boundaryHandling, self._pdfArrays[0])
+
     def animateVelocity(self, steps=10, **kwargs):
         import lbmpy.plot2d as plt
 
@@ -415,3 +424,11 @@ class Scenario(object):
         self._getMacroscopic(pdfs=self._pdfArrays[0], density=self._density, velocity=self._velocity,
                              **self.kernelParams)
 
+    def runBoundaryHandlingOnly(self):
+        isGpuSimulation = len(self._pdfGpuArrays) > 0
+        if isGpuSimulation:
+            self._pdfGpuArrays[0].set(self._pdfArrays[0])
+            self._boundaryHandling(pdfs=self._pdfGpuArrays[0], **self.kernelParams)
+            self._pdfGpuArrays[0].get(self._pdfArrays[0])
+        else:
+            self._boundaryHandling(pdfs=self._pdfArrays[0], **self.kernelParams)