diff --git a/tests/BasicLbmScenarios/LbmAlgorithms.py b/tests/BasicLbmScenarios/LbmAlgorithms.py
index 66c5add1a8c6b7eb797034e7cd66be5c2b4bf3a0..fab81e8bc4c242282668dccda60b883dedd33180 100644
--- a/tests/BasicLbmScenarios/LbmAlgorithms.py
+++ b/tests/BasicLbmScenarios/LbmAlgorithms.py
@@ -2,7 +2,14 @@ import sympy as sp
 from pystencilssfg import SourceFileGenerator
 
 from pystencils import fields, Field
-from lbmpy import LBStencil, Stencil, LBMConfig, LBMOptimisation, create_lb_update_rule
+from lbmpy import (
+    LBStencil,
+    Stencil,
+    LBMConfig,
+    LBMOptimisation,
+    create_lb_update_rule,
+    ForceModel,
+)
 from lbmpy.macroscopic_value_kernels import macroscopic_values_setter
 
 from walberla.codegen import Sweep
@@ -19,6 +26,7 @@ with SourceFileGenerator() as sfg:
     f, f_tmp, rho, u = fields(
         f"f({q}), f_tmp({q}), rho, u({d}): double[{d}D]", layout="fzyx"
     )  # type: ignore
+    force = sp.symbols(f"F_:{d}")
 
     stencil_name = stencil.name
     sfg.include(f"stencil/{stencil_name}.h")
@@ -27,6 +35,8 @@ with SourceFileGenerator() as sfg:
     lbm_config = LBMConfig(
         stencil=stencil,
         output={"density": rho, "velocity": u},
+        force=force,
+        force_model=ForceModel.HE,
     )
     lbm_opt = LBMOptimisation(
         symbolic_field=f,
@@ -43,13 +53,22 @@ with SourceFileGenerator() as sfg:
 
         lb_init = macroscopic_values_setter(
             lb_update.method,
-            density=sp.Symbol("density"),
+            density=rho.center,
             velocity=u.center_vector,
             pdfs=f,
         )
-        lb_init_sweep = Sweep("LbInit", lb_init)
+        lb_init_sweep = Sweep("LbInitFromFields", lb_init)
         sfg.generate(lb_init_sweep)
 
+        lb_init_constant = macroscopic_values_setter(
+            lb_update.method,
+            density=sp.Symbol("density"),
+            velocity=sp.symbols(f"velocity_:{d}"),
+            pdfs=f,
+        )
+        lb_init_constant_sweep = Sweep("LbInitConstant", lb_init_constant)
+        sfg.generate(lb_init_constant_sweep)
+
     with sfg.namespace("bc_sparse"):
         irreg_freeslip = FreeSlip(
             "FreeSlipIrregular", lb_update.method, f, wall_normal=FreeSlip.IRREGULAR
diff --git a/tests/BasicLbmScenarios/SimDomain.hpp b/tests/BasicLbmScenarios/SimDomain.hpp
index b3693e5c86ec419d5b626c144ff12d1810469f23..f26337473cf760d1014ea17dbdb59df1fdf199ab 100644
--- a/tests/BasicLbmScenarios/SimDomain.hpp
+++ b/tests/BasicLbmScenarios/SimDomain.hpp
@@ -5,6 +5,7 @@
 #include "core/all.h"
 
 #include "field/all.h"
+#include "field/communication/StencilRestrictedPackInfo.h"
 
 #include <memory>
 
@@ -44,6 +45,49 @@ struct SimDomain
       const BlockDataID uId;
    } gpuFields;
 
+#else
+
+   void initFromFields(const Vector3< real_t > force)
+   {
+      gen::bulk::LbInitFromFields initialize{ cpuFields.pdfsId, cpuFields.rhoId, cpuFields.uId, force };
+
+      for (auto& b : *blocks)
+      {
+         initialize(&b);
+      }
+   }
+
+   void initConstant(const real_t rho, const Vector3< real_t > u, const Vector3< real_t > force)
+   {
+      gen::bulk::LbInitConstant initialize{ cpuFields.pdfsId, force, rho, u };
+
+      for (auto& b : *blocks)
+      {
+         initialize(&b);
+      }
+   }
+
+   gen::bulk::LbStreamCollide streamCollideSweep(const real_t omega, const Vector3< real_t > force)
+   {
+      return { cpuFields.pdfsId, cpuFields.rhoId, cpuFields.uId, force, omega };
+   }
+
+   void sync() { /* NOP */ }
+
+   void forAllBlocks(std::function< void(IBlock&) > func)
+   {
+      for (auto& block : *blocks)
+         func(block);
+   }
+
+   void forAllCells(std::function< void(Cell) > func)
+   {
+      for (uint_t z = 0; z < blocks->getNumberOfZCellsPerBlock(); ++z)
+         for (uint_t y = 0; y < blocks->getNumberOfYCellsPerBlock(); ++y)
+            for (uint_t x = 0; x < blocks->getNumberOfXCellsPerBlock(); ++x)
+               func({ x, y, z });
+   }
+
 #endif
 };
 
diff --git a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
index 04413de31eb8a6f0f271842f919e64860f4e095a..55fdf16b0354abec90c50a68a498572785b935a2 100644
--- a/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
+++ b/tests/BasicLbmScenarios/TestBasicLbmScenarios.cpp
@@ -3,10 +3,6 @@
 
 #include "core/all.h"
 
-#include "field/all.h"
-#include "field/communication/PackInfo.h"
-#include "field/communication/StencilRestrictedPackInfo.h"
-
 #include "geometry/all.h"
 
 #include "vtk/all.h"
@@ -19,6 +15,39 @@ namespace BasicLbmScenarios
 {
 using namespace walberla;
 
+void fullyPeriodic(Environment& env)
+{
+   SimDomain dom{ SimDomainBuilder{
+      .blocks = { 1, 1, 1 }, .cellsPerBlock = { 32, 32, 32 }, .periodic = { true, true, true } }
+                     .build() };
+
+   const Vector3< real_t > force { 0.005, 0., 0. };
+
+   dom.initConstant(1.0, Vector3< real_t > { 0.0 }, force);
+   
+   auto streamCollide = dom.streamCollideSweep( 1.0, force );
+
+   for(uint_t t = 0; t < 10; ++t){
+      dom.comm();
+      
+      dom.forAllBlocks([&](IBlock & b){
+         streamCollide(&b);
+      });
+
+      dom.sync();
+
+      dom.forAllBlocks([&](auto & block){
+         const VectorField_T & velField = *block.template getData< VectorField_T >(dom.cpuFields.uId);
+
+         dom.forAllCells([&](Cell c){
+            real_t expected { real_c(t) * force[0] };
+            real_t actual { velField.get(c, 0) };
+            WALBERLA_CHECK_FLOAT_EQUAL(expected, actual);
+         });
+      });
+   }
+}
+
 /**
  * Pipe flow with circular cross-section and free-slip walls.
  * The pipe flow is initialized with a constant velocity in x-direction.
@@ -45,12 +74,14 @@ void freeSlipPipe(Environment& env)
    const real_t pipeRadius{ 14.0 };
    const Vector3< real_t > pipeAnchor{ 0.0, 16.0, 16.0 };
    const real_t maxVelocity{ 0.02 };
+   const Vector3< real_t > force{ 0., 0., 0. };
 
    for (auto& block : *dom.blocks)
    {
       FlagField_T& flagField = *block.getData< FlagField_T >(dom.cpuFields.flagFieldId);
       const uint8_t freeSlipFlag{ flagField.getOrRegisterFlag(freeSlipFlagUID) };
 
+      ScalarField_T& densField = *block.getData< ScalarField_T >(dom.cpuFields.rhoId);
       VectorField_T& velField = *block.getData< VectorField_T >(dom.cpuFields.uId);
 
       for (Cell c : allCellsWithGl)
@@ -69,6 +100,7 @@ void freeSlipPipe(Environment& env)
          }
          else { initVelocity = Vector3< real_t >{ maxVelocity, 0., 0. }; }
 
+         densField.get(c, 0) = 1.0;
          velField.get(c, 0) = initVelocity[0];
          velField.get(c, 1) = initVelocity[1];
          velField.get(c, 2) = initVelocity[2];
@@ -80,19 +112,14 @@ void freeSlipPipe(Environment& env)
    auto flagsOutput = field::createVTKOutput< FlagField_T >(dom.cpuFields.flagFieldId, *dom.blocks, "flags");
    flagsOutput();
 
-   gen::bulk::LbInit initialize{ dom.cpuFields.pdfsId, dom.cpuFields.uId, 1.0 };
-
-   for (auto& b : *dom.blocks)
-   {
-      initialize(&b);
-   }
+   dom.initFromFields(force);
 
    gen::bc_sparse::FreeSlipIrregular freeSlip{
       gen::bc_sparse::FreeSlipIrregularFactory(dom.blocks, dom.cpuFields.pdfsId)
          .fromFlagField< FlagField_T >(dom.cpuFields.flagFieldId, freeSlipFlagUID, fluidFlagUid)
    };
 
-   gen::bulk::LbStreamCollide streamCollide{ dom.cpuFields.pdfsId, dom.cpuFields.rhoId, dom.cpuFields.uId, 1.0 };
+   auto streamCollide = dom.streamCollideSweep(1.0, force);
 
    auto velOutput = field::createVTKOutput< VectorField_T >(dom.cpuFields.uId, *dom.blocks, "vel");
 
@@ -128,5 +155,6 @@ void freeSlipPipe(Environment& env)
 int main(int argc, char** argv)
 {
    walberla::Environment env{ argc, argv };
+   BasicLbmScenarios::fullyPeriodic(env);
    BasicLbmScenarios::freeSlipPipe(env);
 }