diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp
index 419b1b37727a73245e01c7aaf6c466f7c48a6a85..b32f103ddda25f9590a6f2d87ee1cae30bc2e47b 100644
--- a/apps/pythonmodule/PythonModule.cpp
+++ b/apps/pythonmodule/PythonModule.cpp
@@ -40,34 +40,24 @@ using namespace walberla;
    Field<walberla::real_t,1>,\
    Field<walberla::real_t,2>,\
    Field<walberla::real_t,3>,\
-   Field<walberla::real_t,4>,\
-   Field<walberla::real_t,5>,\
-   Field<walberla::real_t,6>,\
    Field<walberla::real_t,9>,\
    Field<walberla::real_t,15>,\
    Field<walberla::real_t,19>,\
    Field<walberla::real_t,27>,\
    Field<walberla::int8_t,1>,\
-   Field<walberla::int16_t,1>,\
-   Field<walberla::int32_t,1>,\
    Field<walberla::int64_t,1>,\
    Field<walberla::int64_t,2>,\
    Field<walberla::int64_t,3>,\
-   Field<walberla::int64_t,4>,\
    Field<walberla::uint8_t,1>,\
    Field<walberla::uint16_t,1>,\
    Field<walberla::uint32_t,1>
 
 #define GPU_FIELD_TYPES \
-   GPUField<double>,\
-   GPUField<float>,\
+   GPUField<real_t>,\
    GPUField<int8_t>,\
-   GPUField<int16_t>,\
    GPUField<int32_t>,\
    GPUField<int64_t>,\
    GPUField<uint8_t>,\
-   GPUField<uint16_t>,\
-   GPUField<uint32_t>,\
    GPUField<uint64_t>
 
 struct InitObject
diff --git a/python/waLBerla/callbacks.py b/python/waLBerla/callbacks.py
index f9153ec5b7f19bc6789915f470222ce48cd4f307..07f2ebc0f35ae7cda48f3958531b1f0fb11f48ac 100644
--- a/python/waLBerla/callbacks.py
+++ b/python/waLBerla/callbacks.py
@@ -149,7 +149,7 @@ class ScenarioManager:
                 cfg = None
                 while cfg is None:
                     cfg = get_config_from_scenario(scenario)
-                # walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios)))
+                walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios)))
                 yield cfg
 
         except ImportError:
diff --git a/python/waLBerla_docs/modules/core.rst b/python/waLBerla_docs/modules/core.rst
index c1253ba29577a9dcb2e6477cbf9f095f0006b4a8..ee8d985a3b8fe7f3a9582697c87c6afb519c7ac1 100644
--- a/python/waLBerla_docs/modules/core.rst
+++ b/python/waLBerla_docs/modules/core.rst
@@ -198,6 +198,10 @@ Block Structure
    .. py:method:: containsGlobalBlockInformation( )
    .. py:method:: blocksOverlappedByAABB( point, aabb )
    .. py:method:: blocksContainedWithinAABB( point, aabb )
+
+   .. py:method:: addBlockData( name, blockdata)
+
+      Adds custom data to the blockforest. This can be a Python Class for example which is then callable on all blocks
    
    .. py:method:: blockExists( point )
    .. py:method:: blockExistsLocally( point )
diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py
index 3ab25c4189bcc014200ccf9c1ffc763c421ff41b..04ab5afb43512619654425d04e40ca99c56f0238 100644
--- a/python/waLBerla_tests/test_field.py
+++ b/python/waLBerla_tests/test_field.py
@@ -18,14 +18,14 @@ class FieldModuleTest(unittest.TestCase):
 
     def testNumpyConversionWithoutGhostLayers(self):
         blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(1, 2, 3), periodic=(True, False, False))
-        field.addToStorage(blocks, 'f1', np.float64, fSize=4, ghostLayers=0, initValue=2.0)
-        field.addToStorage(blocks, 'f2', np.float64, fSize=5, ghostLayers=0, initValue=2.0)
+        field.addToStorage(blocks, 'f1', np.float64, fSize=2, ghostLayers=0, initValue=2.0)
+        field.addToStorage(blocks, 'f2', np.float64, fSize=3, ghostLayers=0, initValue=2.0)
 
         f1np = field.toArray(blocks[0]['f1'])
         f2np = field.toArray(blocks[0]['f2'])
         self.assertEqual(f1np[0, 0, 0, 0], 2.0)
-        self.assertEqual(f1np.shape, (1, 2, 3, 4))
-        self.assertEqual(f2np.shape, (1, 2, 3, 5))
+        self.assertEqual(f1np.shape, (1, 2, 3, 2))
+        self.assertEqual(f2np.shape, (1, 2, 3, 3))
 
     def testGhostLayerExtraction(self):
         size = (10, 5, 4)
diff --git a/src/python_coupling/CreateConfig.cpp b/src/python_coupling/CreateConfig.cpp
index c7e3d1b2499e510e98700bdc5ab09500ad2abcfd..5f8f9615c2f346096b567826974d20904ad2b9af 100644
--- a/src/python_coupling/CreateConfig.cpp
+++ b/src/python_coupling/CreateConfig.cpp
@@ -70,30 +70,27 @@ shared_ptr< Config > createConfigFromPythonScript(const std::string& scriptFile,
 class PythonMultipleConfigGenerator : public config::ConfigGenerator
 {
  public:
-   PythonMultipleConfigGenerator(py::list ConfigList) // NOLINT
-      : ConfigList_(ConfigList), counter(0)              // NOLINT
+   PythonMultipleConfigGenerator(py::object ScenarioConfigGenerator) // NOLINT
+      : ScenarioConfigGenerator_(ScenarioConfigGenerator)            // NOLINT
    {}
 
    shared_ptr< Config > next() override
    {
       shared_ptr< Config > config = make_shared< Config >();
-
-      if ( counter == ConfigList_.size()  )
+      try
+      {
+         py::dict configDict = ScenarioConfigGenerator_.attr("__next__")();
+         configFromPythonDict(config->getWritableGlobalBlock(), configDict);
+         return config;
+      }
+      catch (py::error_already_set&)
+      {
          return shared_ptr<Config>();
-
-      py::dict configDict = ConfigList_[counter];
-      configFromPythonDict(config->getWritableGlobalBlock(), configDict);
-
-      WALBERLA_LOG_INFO_ON_ROOT("Simulating Scenario " <<  counter + 1 << " of "  << ConfigList_.size() << ":")
-
-      counter++;
-
-      return config;
+      }
    }
 
  private:
-   py::list ConfigList_;
-   uint_t counter;
+   py::object ScenarioConfigGenerator_;
 };
 
 class PythonSingleConfigGenerator : public config::ConfigGenerator
diff --git a/src/python_coupling/export/BasicExport.cpp b/src/python_coupling/export/BasicExport.cpp
index 279e304e5adbcc032e0825fa46e3829af158c552..c4fad8eb6cf39d9442ddbbe46e4e278d5e738a4d 100644
--- a/src/python_coupling/export/BasicExport.cpp
+++ b/src/python_coupling/export/BasicExport.cpp
@@ -55,14 +55,6 @@
 
 #   include <pybind11/stl.h>
 
-// specialize operator== since == is deprecated in pybind11
-template<>
-bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==(
-   const BlockData::DataBase& rhs) const
-{
-   const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs);
-   return (rhsData == &rhs) && (data_->is(*(rhsData->data_)));
-}
 
 namespace py = pybind11;
 namespace walberla {
diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp
index 7d2c9d764a76f3c012d85d86e21efb24a4444e06..e4aae6226c92ee24cad6f4d1db07fcfce6c80a66 100644
--- a/src/python_coupling/export/BlockForestExport.cpp
+++ b/src/python_coupling/export/BlockForestExport.cpp
@@ -42,6 +42,15 @@
 #   include "BlockForestExport.h"
 #   include "python_coupling/helper/OwningIterator.h"
 
+// specialize operator== since == is deprecated in pybind11
+template<>
+bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==(
+        const BlockData::DataBase& rhs) const
+{
+    const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs);
+    return (rhsData == &rhs) && (data_->is(*(rhsData->data_)));
+}
+
 namespace walberla
 {
 namespace blockforest
@@ -257,6 +266,19 @@ bool p_blockExistsRemotely1(StructuredBlockForest& s, const std::array<real_t, 3
 
 }
 
+py::object * blockDataCreationHelper( IBlock * block,  py::object callable ) //NOLINT
+{
+    py::object * res = new py::object( callable( block ));
+    return res;
+}
+
+uint_t StructuredBlockForest_addBlockData( StructuredBlockForest & s, const std::string & name, py::object functionPtr ) //NOLINT
+{
+    BlockDataID res = s.addBlockData(name)
+            << BlockDataCreator<py::object>( std::bind( &blockDataCreationHelper, std::placeholders::_1, functionPtr ) );
+    return res;
+}
+
 bool SbF_atDomainXMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMinBorder(*b); }
 bool SbF_atDomainXMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMaxBorder(*b); }
 bool SbF_atDomainYMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainYMinBorder(*b); }
@@ -278,6 +300,7 @@ void exportBlockForest(py::module_& m)
    py::class_< StructuredBlockForest, std::shared_ptr< StructuredBlockForest > >(m, "StructuredBlockForest")
       .def("getNumberOfLevels", &StructuredBlockForest::getNumberOfLevels)
       .def_property_readonly("getDomain", &StructuredBlockForest::getDomain)
+      .def( "addBlockData", &StructuredBlockForest_addBlockData)
       .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain1)
       .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain2)
       .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain3)
diff --git a/src/python_coupling/export/FieldCommunicationExport.impl.h b/src/python_coupling/export/FieldCommunicationExport.impl.h
index 0793b26a567b7da73f8f905f604be3048c1afd59..57289631d981822f5ba10c5111279c5da1d79337 100644
--- a/src/python_coupling/export/FieldCommunicationExport.impl.h
+++ b/src/python_coupling/export/FieldCommunicationExport.impl.h
@@ -51,6 +51,119 @@ namespace internal
 {
 namespace py = pybind11;
 
+//===================================================================================================================
+//
+//  createStencilRestrictedPackInfo Export
+//
+//===================================================================================================================
+
+template< typename FieldType >
+typename std::enable_if<FieldType::F_SIZE == 27, py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID bdId )
+{
+   typedef GhostLayerField<typename FieldType::value_type, 27> GlField_T;
+   using field::communication::StencilRestrictedPackInfo;
+   return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q27> >( bdId) );
+}
+
+template< typename FieldType >
+typename std::enable_if<FieldType::F_SIZE == 19, py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID bdId )
+{
+   typedef GhostLayerField<typename FieldType::value_type, 19> GlField_T;
+   using field::communication::StencilRestrictedPackInfo;
+   return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q19> >( bdId) );
+}
+
+template< typename FieldType >
+typename std::enable_if<FieldType::F_SIZE == 15, py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID bdId )
+{
+   typedef GhostLayerField<typename FieldType::value_type, 15> GlField_T;
+   using field::communication::StencilRestrictedPackInfo;
+   return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q15> >( bdId) );
+}
+
+template< typename FieldType >
+typename std::enable_if<FieldType::F_SIZE == 7, py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID bdId )
+{
+   typedef GhostLayerField<typename FieldType::value_type, 7> GlField_T;
+   using field::communication::StencilRestrictedPackInfo;
+   return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q7> >( bdId) );
+}
+
+template< typename FieldType >
+typename std::enable_if<FieldType::F_SIZE == 9, py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID bdId )
+{
+   typedef GhostLayerField<typename FieldType::value_type, 9> GlField_T;
+   using field::communication::StencilRestrictedPackInfo;
+   return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D2Q9> >( bdId) );
+}
+
+template< typename FieldType >
+typename std::enable_if<!(FieldType::F_SIZE == 9  ||
+                          FieldType::F_SIZE == 7  ||
+                          FieldType::F_SIZE == 15 ||
+                          FieldType::F_SIZE == 19 ||
+                          FieldType::F_SIZE == 27), py::object>::type
+createStencilRestrictedPackInfoObject( BlockDataID )
+{
+   throw py::value_error("This works only for fields with fSize in 7, 9, 15, 19 or 27");
+}
+
+class StencilRestrictedPackInfoExporter
+{
+ public:
+   StencilRestrictedPackInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId)
+      : blocks_(blocks), fieldId_(fieldId)
+   {}
+
+   template< typename FieldType>
+   void operator() ( python_coupling::NonCopyableWrap<FieldType> )
+   {
+      typedef typename FieldType::value_type T;
+      const uint_t F_SIZE = FieldType::F_SIZE;
+      typedef GhostLayerField<T, F_SIZE> GlField_T;
+      IBlock * firstBlock =  & ( * blocks_->begin() );
+      if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) )
+      {
+         resultStencilRestrictedPackInfo_ = createStencilRestrictedPackInfoObject<GlField_T>(fieldId_);
+      }
+   }
+   py::object getResultStencilRestrictedPackInfo()
+   {
+      return resultStencilRestrictedPackInfo_;
+   }
+
+ private:
+   py::object resultStencilRestrictedPackInfo_;
+   shared_ptr< StructuredBlockStorage > blocks_;
+   BlockDataID fieldId_;
+};
+
+template<typename... FieldTypes>
+static py::object StencilRestrictedPackInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks,
+                                                   const std::string & blockDataName )
+{
+   BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, blockDataName );
+
+   if ( blocks->begin() == blocks->end() ) {
+      // if no blocks are on this field an arbitrary PackInfo can be returned
+      return py::cast( make_shared< field::communication::StencilRestrictedPackInfo<GhostLayerField<real_t, 9>, stencil::D2Q9> >( fieldID ) );
+   }
+
+   StencilRestrictedPackInfoExporter exporter(blocks, fieldID);
+   python_coupling::for_each_noncopyable_type< FieldTypes... >  ( std::ref(exporter) );
+   if ( ! exporter.getResultStencilRestrictedPackInfo() ) {
+      throw py::value_error("Failed to create Stencil Restricted PackInfo");
+   }
+   else {
+      return exporter.getResultStencilRestrictedPackInfo();
+   }
+}
+
 //===================================================================================================================
 //
 //  createPackInfo Export
@@ -241,6 +354,14 @@ void exportCommunicationClasses(py::module_& m)
         return internal::UniformMPIDatatypeInfoWrapper< FieldTypes... >(blocks, blockDataName, numberOfGhostLayers);
       },
       "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0));
+
+   m2.def(
+      "createStencilRestrictedPackInfo",
+      [](const shared_ptr<StructuredBlockForest> & blocks,
+         const std::string & blockDataName) {
+        return internal::StencilRestrictedPackInfoWrapper< FieldTypes... >(blocks, blockDataName);
+      },
+      "blocks"_a, "blockDataName"_a);
 }
 
 } // namespace field