diff --git a/lib/walberla/experimental/sweep/DomainSlices.hpp b/lib/walberla/experimental/sweep/DomainSlices.hpp
index 450316dd1c6e7bc883a61f130d46b2d1c981bd4f..0492cb53bdc2baddae1f8b4f8468eea4b95bfc02 100644
--- a/lib/walberla/experimental/sweep/DomainSlices.hpp
+++ b/lib/walberla/experimental/sweep/DomainSlices.hpp
@@ -78,4 +78,4 @@ class BorderSweep
    }
 };
 
-} // namespace walberla::experimental::sweep
\ No newline at end of file
+} // namespace walberla::experimental::sweep
diff --git a/src/walberla/codegen/boundaries/linkwise.py b/src/walberla/codegen/boundaries/linkwise.py
index 04a6491ba0712f4f17b55d386757f89cf83e4070..777e6b0a883f7000e891285d88b2cb7cc9281b31 100644
--- a/src/walberla/codegen/boundaries/linkwise.py
+++ b/src/walberla/codegen/boundaries/linkwise.py
@@ -39,8 +39,8 @@ class NoSlip(GenericLinkwiseBoundary):
         name: Name of the generated sweep class
         lb_method: lbmpy Method description
         pdf_field: Symbolic LBM PDF field
-        wall_normal: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid,
-            or `FreeSlip.IRREGULAR` to indicate a non-grid-aligned boundary
+        wall_orientation: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the fluid to the wall,
+            or `NoSlip.IRREGULAR` to indicate a non-grid-aligned boundary
         target: Target architecture for the code generator
     """
 
@@ -49,13 +49,13 @@ class NoSlip(GenericLinkwiseBoundary):
         name: str,
         lb_method: AbstractLbMethod,
         pdf_field: Field,
-        wall_normal: tuple[int, int, int] | _IrregularSentinel,
+        wall_orientation: tuple[int, int, int] | _IrregularSentinel,
         target: Target | None = None,
     ):
         self._name = name
         self._lb_method = lb_method
         self._pdf_field = pdf_field
-        self._wall_normal = wall_normal
+        self._wall_normal = wall_orientation
         self._target = target
 
     @property
@@ -86,8 +86,7 @@ class NoSlip(GenericLinkwiseBoundary):
 
         assert isinstance(self._wall_normal, tuple)
         wall_normal = self._wall_normal
-        x_w = (0,) * stencil.D
-        x_b = tuple(x + c for x, c in zip(x_w, wall_normal))
+        x_b = (0,) * stencil.D
 
         f = self._pdf_field
 
@@ -100,10 +99,10 @@ class NoSlip(GenericLinkwiseBoundary):
 
         asms = []
 
-        for i_out, c_out in enumerate(stencil):
-            if wall_aligned(c_out):
-                i_inverse = stencil.inverse_index(c_out)
-                asms.append(Assignment(f[x_w](i_out), f[x_b](i_inverse)))
+        for i_out, x_w in enumerate(stencil):
+            if wall_aligned(x_w):
+                i_inverse = stencil.inverse_index(x_w)
+                asms.append(Assignment(f[x_w](i_inverse), f[x_b](i_out)))
 
         return AssignmentCollection(asms)
 
@@ -210,7 +209,7 @@ class FreeSlip(GenericLinkwiseBoundary):
         name: Name of the generated sweep class
         lb_method: lbmpy Method description
         pdf_field: Symbolic LBM PDF field
-        wall_normal: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid,
+        wall_orientation: Vector :math:`\\vec{n} \\in \\{ -1, 0, 1 \\}^d` pointing from the wall into the fluid,
             or `FreeSlip.IRREGULAR` to indicate a non-grid-aligned boundary
         target: Target architecture for the code generator
     """
@@ -220,13 +219,13 @@ class FreeSlip(GenericLinkwiseBoundary):
         name: str,
         lb_method: AbstractLbMethod,
         pdf_field: Field,
-        wall_normal: tuple[int, int, int] | _IrregularSentinel,
+        wall_orientation: tuple[int, int, int] | _IrregularSentinel,
         target: Target | None = None,
     ):
         self._name = name
         self._lb_method = lb_method
         self._pdf_field = pdf_field
-        self._wall_normal = wall_normal
+        self._wall_normal = wall_orientation
         self._target = target
 
     @property
@@ -306,18 +305,15 @@ class FreeSlip(GenericLinkwiseBoundary):
 
     def _grid_aligned_assignments(self):
         stencil = self._lb_method.stencil
-        x_w = (0,) * stencil.D
 
         assert isinstance(self._wall_normal, tuple)
         wall_normal = self._wall_normal
-
-        x_b = tuple(x + c for x, c in zip(x_w, wall_normal))
+        inverse_wall_normal = tuple(-c for c in wall_normal)
 
         f = self._pdf_field
 
-        def wall_aligned(vec):
-            """Test if v1 is aligned with v2, i.e. v1 has the same nonzero entries as v2"""
-            for x_v, x_n in zip(vec, wall_normal):
+        def is_missing(vec):
+            for x_v, x_n in zip(vec, inverse_wall_normal):
                 if x_n != 0 and x_v != x_n:
                     return False
             return True
@@ -329,11 +325,15 @@ class FreeSlip(GenericLinkwiseBoundary):
 
         asms = []
 
-        for i_out, c_out in enumerate(stencil):
-            c_mirrored = wall_mirror(c_out)
-            i_mirrored = stencil.index(c_mirrored)
-            if wall_aligned(c_out):
-                asms.append(Assignment(f[x_w](i_out), f[x_b](i_mirrored)))
+        for i_missing, c_missing in enumerate(stencil):
+            #   Iterate all inbound populations to the fluid cell crossing the wall
+            if is_missing(c_missing):
+                x_w = tuple(-c for c in c_missing)
+                c_refl = wall_mirror(c_missing)
+                i_refl = stencil.index(c_refl)
+                x_orig = tuple(w - n for w, n in zip(x_w, wall_normal))
+
+                asms.append(Assignment(f[x_w](i_missing), f[x_orig](i_refl)))
 
         return AssignmentCollection(asms)
 
diff --git a/tests/BasicLbmScenarios/LbmAlgorithms.py b/tests/BasicLbmScenarios/LbmAlgorithms.py
index 2f9b8762139c35a59ab9fb78593ad0cf9efa8a9b..1ba0036ee6e5032d62a8141ec76f8e3c35c09b0c 100644
--- a/tests/BasicLbmScenarios/LbmAlgorithms.py
+++ b/tests/BasicLbmScenarios/LbmAlgorithms.py
@@ -97,16 +97,16 @@ with SourceFileGenerator(keep_unknown_argv=True) as sfg:
         sfg.generate(lb_init_constant_sweep)
 
     with sfg.namespace("bc_grid_aligned"):
-        sfg.generate(NoSlip("NoSlipTop", lb_update.method, f, wall_normal=(0, 0, -1)))
+        sfg.generate(NoSlip("NoSlipTop", lb_update.method, f, wall_orientation=(0, 0, 1), target=cfg.target))
 
-        sfg.generate(NoSlip("NoSlipBottom", lb_update.method, f, wall_normal=(0, 0, 1)))
+        sfg.generate(NoSlip("NoSlipBottom", lb_update.method, f, wall_orientation=(0, 0, -1), target=cfg.target))
 
         sfg.generate(
-            FreeSlip("FreeSlipTop", lb_update.method, f, wall_normal=(0, 0, -1))
+            FreeSlip("FreeSlipTop", lb_update.method, f, wall_orientation=(0, 0, 1), target=cfg.target)
         )
 
         sfg.generate(
-            FreeSlip("FreeSlipBottom", lb_update.method, f, wall_normal=(0, 0, 1))
+            FreeSlip("FreeSlipBottom", lb_update.method, f, wall_orientation=(0, 0, -1), target=cfg.target)
         )
 
     with sfg.namespace("bc_sparse"):
@@ -114,7 +114,7 @@ with SourceFileGenerator(keep_unknown_argv=True) as sfg:
             "FreeSlipIrregular",
             lb_update.method,
             f,
-            wall_normal=FreeSlip.IRREGULAR,
+            wall_orientation=FreeSlip.IRREGULAR,
             target=cfg.target,
         )
         sfg.generate(irreg_freeslip)
diff --git a/tests/BasicLbmScenarios/SimDomain.hpp b/tests/BasicLbmScenarios/SimDomain.hpp
index 50991de38916d28852543350700ab0e1b8018c68..4417699a8d2eec630f684ce46755fee0fecd45dd 100644
--- a/tests/BasicLbmScenarios/SimDomain.hpp
+++ b/tests/BasicLbmScenarios/SimDomain.hpp
@@ -103,12 +103,12 @@ struct SimDomain
 
    auto
    freeSlipBottom() {
-      return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { gpuFields.pdfsId }, 0 };
+      return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { gpuFields.pdfsId } };
    }
 
    auto
    noSlipTop() {
-      return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { gpuFields.pdfsId }, -1 };
+      return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { gpuFields.pdfsId } };
    }
 
    auto
@@ -167,6 +167,21 @@ struct SimDomain
       return { cpuFields.pdfsId, cpuFields.rhoId, cpuFields.uId, force, omega };
    }
 
+   auto
+   freeSlipTop() {
+      return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::FreeSlipTop > { blocks, gen::bc_grid_aligned::FreeSlipTop { cpuFields.pdfsId } };
+   }
+
+   auto
+   freeSlipBottom() {
+      return sweep::BorderSweep< stencil::Direction::B, gen::bc_grid_aligned::FreeSlipBottom > { blocks, gen::bc_grid_aligned::FreeSlipBottom { cpuFields.pdfsId } };
+   }
+
+   auto
+   noSlipTop() {
+      return sweep::BorderSweep< stencil::Direction::T, gen::bc_grid_aligned::NoSlipTop > { blocks, gen::bc_grid_aligned::NoSlipTop { cpuFields.pdfsId } };
+   }
+
    auto irregularFreeSlipFactory() {
       return gen::bc_sparse::FreeSlipIrregularFactory(blocks, cpuFields.pdfsId);
    }
diff --git a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
index e058065c434bba7f2ae9bc005ed84eeff2858bcb..5636011b615efe60732545be16714551baca601a 100644
--- a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
+++ b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
@@ -50,7 +50,6 @@ void fullyPeriodic(Environment& env)
    }
 }
 
-#if defined(LBM_SCENARIOS_GPU_BUILD)
 /**
  * Periodic channel flow with a no-slip boundary at the top
  * and a symmetry plane at the bottom implemented using the free-slip boundary.
@@ -64,7 +63,7 @@ void mirroredHalfChannel(Environment& env)
     * Need one more cell in z-direction for the free-slip boundary to be on the inner layer
     */
    SimDomain dom{ SimDomainBuilder{
-      .blocks = { 1, 1, 1 }, .cellsPerBlock = { 4, 4, zCells + 1 }, .periodic = { true, true, false } }
+      .blocks = { 1, 1, 1 }, .cellsPerBlock = { 4, 4, zCells }, .periodic = { true, true, false } }
                      .build() };
 
    /* Hagen-Poiseuille-law in lattice units */
@@ -106,8 +105,9 @@ void mirroredHalfChannel(Environment& env)
    auto streamCollide = dom.streamCollideSweep(omega, force);
    auto noSlipTop = dom.noSlipTop();
    auto freeSlipBottom = dom.freeSlipBottom();
+   auto velOutput = field::createVTKOutput< VectorField_T >(dom.cpuFields.uId, *dom.blocks, "vel");
 
-   for (uint_t t = 0; t < 10; ++t)
+   for (uint_t t = 0; t < 50; ++t)
    {
       dom.forAllBlocks([&](IBlock& b) { streamCollide(&b); });
       dom.syncGhostLayers();
@@ -124,10 +124,12 @@ void mirroredHalfChannel(Environment& env)
 
             real_t expected{ velocityProfile(cellCenter[2]) };
             real_t actual{ velField.get(c, 0) };
-            WALBERLA_CHECK_FLOAT_EQUAL(expected, actual);
+            WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(expected, actual, 1e-5);
          });
       });
 
+      // velOutput();
+
       dom.forAllBlocks([&](IBlock& b) {
          noSlipTop(&b);
          freeSlipBottom(&b);
@@ -135,8 +137,6 @@ void mirroredHalfChannel(Environment& env)
    }
 }
 
-#endif
-
 /**
  * Pipe flow with circular cross-section and free-slip walls.
  * The pipe flow is initialized with a constant velocity in x-direction.
@@ -251,7 +251,7 @@ void freeSlipPipe(Environment& env)
 int main(int argc, char** argv)
 {
    walberla::Environment env{ argc, argv };
-   BasicLbmScenarios::fullyPeriodic(env);
-   // BasicLbmScenarios::mirroredHalfChannel(env);
-   BasicLbmScenarios::freeSlipPipe(env);
+   // BasicLbmScenarios::fullyPeriodic(env);
+   BasicLbmScenarios::mirroredHalfChannel(env);
+   // BasicLbmScenarios::freeSlipPipe(env);
 }
diff --git a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py
index a7f5521a54facc081498c55e4ca72aeb433bbe0f..693fd68c40adaddba491218cbc2b225c0d8d2148 100644
--- a/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py
+++ b/user_manual/examples/FreeSlipBubble/LbmAlgorithms.py
@@ -55,7 +55,7 @@ with SourceFileGenerator() as sfg:
         "FreeSlip",
         lb_method,
         pdfs,
-        wall_normal=FreeSlip.IRREGULAR,
+        wall_orientation=FreeSlip.IRREGULAR,
         target=target
     )