diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5a7a53f0ee7e5181f346853fdb8e0616a8bc4b54..4c5eb03460d176c992c410bfa1e7f4be01231d3f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,24 +3,11 @@ project ( sfg-walberla )
 
 set(sfg_walberla_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED)
+
 list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake )
 
 include( PrepareSFG )
 
-add_library( walberla_codegen INTERFACE )
-add_library( walberla::codegen ALIAS walberla_codegen )
-
-target_sources( walberla_codegen
-    INTERFACE
-    include/sfg/SparseIteration.hpp
-    include/sfg/GenericHbbBoundary.hpp
-    include/sfg/IrregularFreeSlip.hpp
-)
-
-target_include_directories( walberla_codegen INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include )
-
-target_link_libraries(
-    walberla_codegen
-    INTERFACE
-    walberla::core walberla::stencil walberla::domain_decomposition walberla::blockforest walberla::field
-)
+add_subdirectory( lib )
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0ff9363a6f146e933622f513f66a3f777794e90f
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_library( walberla_experimental INTERFACE )
+add_library( walberla::experimental ALIAS walberla_experimental )
+
+target_sources( walberla_experimental
+    INTERFACE
+    walberla/experimental/field/SparseIndexList.hpp
+    walberla/experimental/lbm/GenericHbbBoundary.hpp
+    walberla/experimental/lbm/IrregularFreeSlip.hpp
+)
+
+target_include_directories( walberla_experimental INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} )
diff --git a/include/sfg/GenericHbbBoundary.hpp b/lib/walberla/experimental/lbm/GenericHbbBoundary.hpp
similarity index 96%
rename from include/sfg/GenericHbbBoundary.hpp
rename to lib/walberla/experimental/lbm/GenericHbbBoundary.hpp
index c9164f55c9a46730dfa9d5b0b55bf241ea263f54..c0692144282549b0d6b0fe23d905fcec382c6fa4 100644
--- a/include/sfg/GenericHbbBoundary.hpp
+++ b/lib/walberla/experimental/lbm/GenericHbbBoundary.hpp
@@ -14,11 +14,11 @@
 #include <memory>
 #include <tuple>
 
-#include "SparseIteration.hpp"
+#include "walberla/experimental/field/SparseIndexList.hpp"
 
-namespace walberla
+namespace walberla::experimental
 {
-namespace sfg
+namespace lbm
 {
 
 struct HbbLink
diff --git a/include/sfg/IrregularFreeSlip.hpp b/lib/walberla/experimental/lbm/IrregularFreeSlip.hpp
similarity index 97%
rename from include/sfg/IrregularFreeSlip.hpp
rename to lib/walberla/experimental/lbm/IrregularFreeSlip.hpp
index c887b8e7bd55d437b4a0d83160c47b7fe66682a7..3332d8afecd62f9906b25bb7e10df892fe5caa94 100644
--- a/include/sfg/IrregularFreeSlip.hpp
+++ b/lib/walberla/experimental/lbm/IrregularFreeSlip.hpp
@@ -6,13 +6,11 @@
 #include "domain_decomposition/IBlock.h"
 #include "field/GhostLayerField.h"
 #include "field/FlagField.h"
-#include "sfg/SparseIteration.hpp"
+#include "walberla/experimental/sweep/SparseIndexList.hpp"
 #include "stencil/Directions.h"
 #include <tuple>
 
-#include "SparseIteration.hpp"
-
-namespace walberla::sfg
+namespace walberla::experimental::lbm
 {
     struct IrregularFreeSlipLinkInfo
     {
@@ -46,7 +44,7 @@ namespace walberla::sfg
         class FreeSlipLinksFromFlagField
         {
         public:
-            using IndexList = SparseIndexList<IrregularFreeSlipLinkInfo>;
+            using IndexList = sweep::SparseIndexList<IrregularFreeSlipLinkInfo>;
             using flag_t = typename FlagField_T::flag_t;
 
             FreeSlipLinksFromFlagField(
diff --git a/include/sfg/SparseIteration.hpp b/lib/walberla/experimental/sweep/SparseIndexList.hpp
similarity index 97%
rename from include/sfg/SparseIteration.hpp
rename to lib/walberla/experimental/sweep/SparseIndexList.hpp
index 9862e7662b63cceb337217392aa92cb55cf06739..6fbc30ea1376343280d45c6baac67f0e2f25c863 100644
--- a/include/sfg/SparseIteration.hpp
+++ b/lib/walberla/experimental/sweep/SparseIndexList.hpp
@@ -7,7 +7,7 @@
 #include "domain_decomposition/BlockDataID.h"
 #include "blockforest/StructuredBlockForest.h"
 
-namespace walberla::sfg
+namespace walberla::experimental::sweep
 {
   namespace internal
   {
diff --git a/src/walberla/codegen/api.py b/src/walberla/codegen/api.py
index c6e27d87bcc9d4c8f4208bb7d02b98f70653442d..43ce022fafde7573f5df617e07c72d246588662f 100644
--- a/src/walberla/codegen/api.py
+++ b/src/walberla/codegen/api.py
@@ -357,7 +357,8 @@ def glfield(field: Field, ci: str | AugExpr | None = None):
 
 class SparseIndexList(AugExpr):
     _template = cpptype(
-        "walberla::sfg::SparseIndexList< {IndexStruct} >", "sfg/SparseIteration.hpp"
+        "walberla::experimental::sweep::SparseIndexList< {IndexStruct} >",
+        "walberla/experimental/sweep/SparseIndexList.hpp",
     )
 
     def __init__(
@@ -376,8 +377,8 @@ class SparseIndexList(AugExpr):
 
 class IndexListBufferPtr(AugExpr, SupportsFieldExtraction):
     _template = cpptype(
-        "walberla::sfg::internal::IndexListBuffer< {IndexStruct} >",
-        "sfg/SparseIteration.hpp",
+        "walberla::experimental::sweep::internal::IndexListBuffer< {IndexStruct} >",
+        "walberla/experimental/sweep/SparseIndexList.hpp",
     )
 
     def __init__(self, idx_struct: PsStructType):
@@ -420,5 +421,5 @@ CellIdx = PsStructType(
         ("y", create_type("int64_t")),
         ("z", create_type("int64_t")),
     ),
-    "walberla::sfg::CellIdx",
+    "walberla::experimental::sweep::CellIdx",
 )
diff --git a/src/walberla/codegen/boundaries/boundary_utils.py b/src/walberla/codegen/boundaries/boundary_utils.py
index c011ed8c69ca9e70a3ae5a9242ec3c6f98ba5e62..453d611cba1fa1c4bb7891f921befe6fd68867a2 100644
--- a/src/walberla/codegen/boundaries/boundary_utils.py
+++ b/src/walberla/codegen/boundaries/boundary_utils.py
@@ -17,7 +17,7 @@ HbbLinkType = PsStructType(
         ("z", BoundaryIndexType),
         ("dir", BoundaryIndexType),
     ],
-    "walberla::sfg::HbbLink",
+    "walberla::experimental::lbm::HbbLink",
 )
 
 
diff --git a/src/walberla/codegen/boundaries/freeslip.py b/src/walberla/codegen/boundaries/freeslip.py
index cfdc946bcb889212b36a500a8c46d071ffbeb5da..98471c31041a49fc6209c25cdcf8067b68a50143 100644
--- a/src/walberla/codegen/boundaries/freeslip.py
+++ b/src/walberla/codegen/boundaries/freeslip.py
@@ -44,7 +44,7 @@ class FreeSlip(CustomGenerator):
             self._generate_regular(sfg)
 
     def _generate_irregular(self, sfg: SfgComposer):
-        sfg.include("sfg/IrregularFreeSlip.hpp")
+        sfg.include("walberla/experimental/lbm/IrregularFreeSlip.hpp")
 
         #   Get waLBerla build config
         bc_obj = WalberlaIrregularFreeSlip()
@@ -66,7 +66,7 @@ class FreeSlip(CustomGenerator):
 
         #   Build factory
         factory_name = f"{self._name}Factory"
-        factory_crtp_base = f"walberla::sfg::IrregularFreeSlipFactory< {factory_name} >"
+        factory_crtp_base = f"walberla::experimental::lbm::IrregularFreeSlipFactory< {factory_name} >"
         index_vector = SparseIndexList(
             WalberlaIrregularFreeSlip.idx_struct_type, ref=True
         ).var("indexVector")
@@ -115,7 +115,7 @@ class WalberlaIrregularFreeSlip(LbBoundary, WalberlaLbmBoundary):
             ("source_offset_z", BoundaryIndexType),
             ("source_dir", BoundaryIndexType),
         ),
-        "walberla::sfg::IrregularFreeSlipLinkInfo",
+        "walberla::experimental::lbm::IrregularFreeSlipLinkInfo",
     )
 
     def __call__(
diff --git a/src/walberla/codegen/boundaries/hbb.py b/src/walberla/codegen/boundaries/hbb.py
index 7fe2383a6013e58e112ace4ccba91a5395ea2bd8..3e8f7a24b80a1aa87e52773c7a409a19ebedf3f9 100644
--- a/src/walberla/codegen/boundaries/hbb.py
+++ b/src/walberla/codegen/boundaries/hbb.py
@@ -45,7 +45,7 @@ class SimpleHbbBoundary(CustomGenerator):
         self._stencil = lb_method.stencil
 
     def generate(self, sfg: SfgComposer) -> None:
-        sfg.include("sfg/GenericHbbBoundary.hpp")
+        sfg.include("walberla/experimental/lbm/GenericHbbBoundary.hpp")
         sfg.include(f"stencil/{self._stencil.name}.h")
 
         knamespace = sfg.kernel_namespace(f"{self._name}_kernels")
@@ -85,7 +85,7 @@ class SimpleHbbBoundary(CustomGenerator):
         idx_vector = IndexListBufferPtr(HbbLinkType).var("indexVector")
         idx_vector_id = BlockDataID().bind("this->indexVectorsId_")
 
-        base_class = f"walberla::sfg::GenericHbbBoundary< walberla::stencil::{self._stencil.name} >"
+        base_class = f"walberla::experimental::lbm::GenericHbbBoundary< walberla::stencil::{self._stencil.name} >"
 
         sfg.klass(self._name, bases=[f"public {base_class}"])(
             *props.render(sfg),
diff --git a/src/walberla/codegen/sweep.py b/src/walberla/codegen/sweep.py
index 9aad9ceb1910fd569fb83ded620b0ee414f7ece1..6662be71660b4050fbe28fc1c8d5969f8de5b67d 100644
--- a/src/walberla/codegen/sweep.py
+++ b/src/walberla/codegen/sweep.py
@@ -423,19 +423,19 @@ class Sweep(CustomGenerator):
     ):
         if config is not None:
             cfg = config.copy()
-        else:
-            cfg = CreateKernelConfig(ghost_layers=0)
 
-        if cfg.get_option("ghost_layers") is not None:
-            raise ValueError(
-                "Specifying `ghost_layers` in your codegen config is invalid when generating a waLBerla sweep."
-            )
+            if cfg.get_option("ghost_layers") is not None:
+                raise ValueError(
+                    "Specifying `ghost_layers` in your codegen config is invalid when generating a waLBerla sweep."
+                )
 
-        if (
-            cfg.get_option("iteration_slice") is None
-            and cfg.get_option("index_field") is None
-        ):
-            cfg.ghost_layers = 0
+            if (
+                cfg.get_option("iteration_slice") is None
+                and cfg.get_option("index_field") is None
+            ):
+                cfg.ghost_layers = 0
+        else:
+            cfg = CreateKernelConfig(ghost_layers=0)
 
         target = cfg.get_target()
 
diff --git a/tests/FreeSlip/CMakeLists.txt b/tests/BasicLbmScenarios/CMakeLists.txt
similarity index 94%
rename from tests/FreeSlip/CMakeLists.txt
rename to tests/BasicLbmScenarios/CMakeLists.txt
index 8401480e24c54fcabb7a0ddca0762b32c56a74fc..94d46f2d04ccb3e63a716e59e065a4995e42759b 100644
--- a/tests/FreeSlip/CMakeLists.txt
+++ b/tests/BasicLbmScenarios/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_executable( TestIrregularFreeSlip TestIrregularFreeSlip.cpp )
 walberla_generate_sources( TestIrregularFreeSlip SCRIPTS IrregularFreeSlip.py )
-target_link_libraries( TestIrregularFreeSlip PRIVATE walberla::core walberla::blockforest walberla::field walberla::geometry walberla::codegen )
+target_link_libraries( TestIrregularFreeSlip PRIVATE walberla::core walberla::blockforest walberla::field walberla::geometry walberla::experimental )
 add_test( NAME TestIrregularFreeSlip COMMAND TestIrregularFreeSlip )
 
 add_dependencies( SfgTests TestIrregularFreeSlip )
diff --git a/tests/FreeSlip/IrregularFreeSlip.py b/tests/BasicLbmScenarios/IrregularFreeSlip.py
similarity index 100%
rename from tests/FreeSlip/IrregularFreeSlip.py
rename to tests/BasicLbmScenarios/IrregularFreeSlip.py
diff --git a/tests/FreeSlip/TestIrregularFreeSlip.cpp b/tests/BasicLbmScenarios/TestIrregularFreeSlip.cpp
similarity index 100%
rename from tests/FreeSlip/TestIrregularFreeSlip.cpp
rename to tests/BasicLbmScenarios/TestIrregularFreeSlip.cpp
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 72acde9c5dc7ca88b51038b3798c79810a812883..e821381298cce90bc9d1afb7160be741af57d367 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -23,4 +23,4 @@ include(CTest)
 
 add_custom_target( SfgTests )
 
-add_subdirectory( FreeSlip )
+add_subdirectory( BasicLbmScenarios )
diff --git a/user_manual/examples/SparseSpiral/SparseSpiral.cpp b/user_manual/examples/SparseSpiral/SparseSpiral.cpp
index 2234ba1e74e7d8b51f241c1cd6be3edad86f0863..1612e9c48b359c8df8dab570395a42ecde74acd4 100644
--- a/user_manual/examples/SparseSpiral/SparseSpiral.cpp
+++ b/user_manual/examples/SparseSpiral/SparseSpiral.cpp
@@ -3,7 +3,7 @@
 #include "field/GhostLayerField.h"
 #include "field/AddToStorage.h"
 #include "field/vtk/all.h"
-#include "sfg/SparseIteration.hpp"
+#include "walberla/experimental/field/SparseIndexList.hpp"
 
 #include <array>
 
@@ -12,6 +12,7 @@
 namespace SparseSpiral
 {
     using namespace walberla;
+    using namespace walberla::experimental;
 
     using std::array;
     using std::vector;
@@ -43,7 +44,7 @@ namespace SparseSpiral
             cpb[0], cpb[1], cpb[2]);
 
         BlockDataID fID = field::addToStorage<PointField>(blocks, "f", real_c(0.0), field::fzyx);
-        sfg::SparseIndexList indexList{*blocks};
+        field::SparseIndexList indexList{*blocks};
 
         auto isOnSpiral = [&](Cell globalCell) -> bool
         {
@@ -56,7 +57,7 @@ namespace SparseSpiral
 
         for (auto &b : *blocks)
         {
-            vector<sfg::CellIdx> & idxVec{indexList.get(b)};
+            vector< sweep::CellIdx > & idxVec{indexList.get(b)};
             for (Cell c : allCells)
             {
                 Cell globalCell{c};
diff --git a/user_manual/guides/SparseSweeps.md b/user_manual/guides/SparseSweeps.md
index 822d92fbc3894a07e09def2e2797b95d0f349e46..f3188d538119efba844d3480d61c29b9755dff50 100644
--- a/user_manual/guides/SparseSweeps.md
+++ b/user_manual/guides/SparseSweeps.md
@@ -25,7 +25,7 @@ in a field:
 In your C++ code, you must set up an index list which lists all cells the sweep should operate on.
 Due to waLBerla's block-structured nature, the index list will actually be a collection of cell vectors,
 with one vector per block.
-The SFG library provides `sfg::SparseIndexList` for this, which is defined in `sfg/SparseIteration.hpp`.
+WaLBerla provides the `SparseIndexList` class for this.
 The following code sample creates and populates an index list, using a predicate here called `isOnSpiral`.
 The index list's internal block data ID must then be passed to the sweep's constructor.