diff --git a/dumux/python/common/fvproblem.hh b/dumux/python/common/fvproblem.hh
index 2f9a1ec8bcdcc8b32292f9bdfe7f9c54672c26b6..5da3adc73700e7f94f4850b1bae381864163facc 100644
--- a/dumux/python/common/fvproblem.hh
+++ b/dumux/python/common/fvproblem.hh
@@ -42,11 +42,12 @@ namespace Dumux::Python {
  * \ingroup Common
  * \brief A C++ wrapper for a Python problem
  */
-template<class GridGeometry_, class PrimaryVariables>
+template<class GridGeometry_, class PrimaryVariables, class SpatialParams_>
 class FVProblem
 {
 public:
     using GridGeometry = GridGeometry_;
+    using SpatialParams = SpatialParams_;
     using Scalar = typename PrimaryVariables::value_type;
     using NumEqVector = Dune::FieldVector<Scalar, PrimaryVariables::dimension>;
     using Element = typename GridGeometry::GridView::template Codim<0>::Entity;
@@ -59,8 +60,12 @@ public:
     static constexpr std::size_t numEq = static_cast<std::size_t>(PrimaryVariables::dimension);
     using BoundaryTypes = Dumux::BoundaryTypes<PrimaryVariables::dimension>;
 
-    FVProblem(std::shared_ptr<const GridGeometry> gridGeometry, pybind11::object pyProblem)
-    : gridGeometry_(gridGeometry), pyProblem_(pyProblem)
+    FVProblem(std::shared_ptr<const GridGeometry> gridGeometry,
+              std::shared_ptr<const SpatialParams> spatialParams,
+              pybind11::object pyProblem)
+    : gridGeometry_(gridGeometry)
+    , spatialParams_(spatialParams)
+    , pyProblem_(pyProblem)
     {}
 
     std::string name() const
@@ -128,6 +133,15 @@ public:
         return pyProblem_.attr("sourceAtPos")(globalPos).template cast<NumEqVector>();
     }
 
+    template<class ElementVolumeVariables>
+    NumEqVector scvPointSources(const Element& element,
+                                const FVElementGeometry& fvGeometry,
+                                const ElementVolumeVariables& elemVolVars,
+                                const SubControlVolume& scv) const
+    {
+        return pyProblem_.attr("scvPointSources")(element, fvGeometry, scv).template cast<NumEqVector>();
+    }
+
     template<class Entity>
     PrimaryVariables initial(const Entity& entity) const
     {
@@ -142,11 +156,43 @@ public:
         return pyProblem_.attr("extrusionFactor")(element, scv).template cast<Scalar>();
     }
 
+    Scalar temperatureAtPos(const GlobalPosition& globalPos) const
+    {
+        return pyProblem_.attr("temperatureAtPos")(globalPos).template cast<Scalar>();
+    }
+
+    const std::string paramGroup() const
+    {
+        return pyProblem_.attr("paramGroup")().template cast<std::string>();
+    }
+
+    static constexpr bool enableInternalDirichletConstraints()
+    { return false; } // TODO
+
+    /*!
+     * \brief Add source term derivative to the Jacobian
+     * \note Only needed in case of analytic differentiation and solution dependent sources
+     */
+    template<class MatrixBlock, class VolumeVariables>
+    void addSourceDerivatives(MatrixBlock& block,
+                              const Element& element,
+                              const FVElementGeometry& fvGeometry,
+                              const VolumeVariables& volVars,
+                              const SubControlVolume& scv) const
+    {
+        pyProblem_.attr("addSourceDerivatives")(block, element, fvGeometry, scv).template cast<Scalar>();
+    }
+
+
     const GridGeometry& gridGeometry() const
     { return *gridGeometry_; }
 
+    const SpatialParams& spatialParams() const
+    { return *spatialParams_; }
+
 private:
     std::shared_ptr<const GridGeometry> gridGeometry_;
+    std::shared_ptr<const SpatialParams> spatialParams_;
     pybind11::object pyProblem_;
 };
 
@@ -158,8 +204,11 @@ void registerFVProblem(pybind11::handle scope, pybind11::class_<Problem, options
     using namespace Dune::Python;
 
     using GridGeometry = typename Problem::GridGeometry;
-    cls.def(pybind11::init([](std::shared_ptr<const GridGeometry> gridGeometry, pybind11::object p){
-        return std::make_shared<Problem>(gridGeometry, p);
+    using SpatialParams = typename Problem::SpatialParams;
+    cls.def(pybind11::init([](std::shared_ptr<const GridGeometry> gridGeometry,
+                              std::shared_ptr<const SpatialParams> spatialParams,
+                              pybind11::object p){
+        return std::make_shared<Problem>(gridGeometry, spatialParams, p);
     }));
 
     cls.def_property_readonly("name", &Problem::name);
diff --git a/dumux/python/material/spatialparams/spatialparams.hh b/dumux/python/material/spatialparams/spatialparams.hh
index e072d9bdd928b9c1e72136e832da4cae2a1d44d4..448a981491bcfca1747799614d79ee7be53d6b3b 100644
--- a/dumux/python/material/spatialparams/spatialparams.hh
+++ b/dumux/python/material/spatialparams/spatialparams.hh
@@ -24,22 +24,73 @@
 #ifndef DUMUX_PYTHON_MATERIAL_SPATIAL_PARAMS_HH
 #define DUMUX_PYTHON_MATERIAL_SPATIAL_PARAMS_HH
 
-
 #include <dune/python/pybind11/pybind11.h>
 #include <dune/python/pybind11/stl.h>
 
+#include <dumux/material/spatialparams/fv1p.hh>
+
 namespace Dumux::Python {
 
+template<class GridGeometry, class Scalar, class PT>
+class FVSpatialParamsOneP
+: public Dumux::FVSpatialParamsOneP<GridGeometry, Scalar, FVSpatialParamsOneP<GridGeometry, Scalar, PT>>
+{
+    using ThisType = FVSpatialParamsOneP<GridGeometry, Scalar, PT>;
+    using ParentType = Dumux::FVSpatialParamsOneP<GridGeometry, Scalar, ThisType>;
+    using Element = typename GridGeometry::GridView::template Codim<0>::Entity;
+    using SubControlVolume = typename GridGeometry::SubControlVolume;
+    using GlobalPosition = typename GridGeometry::GridView::template Codim<0>::Geometry::GlobalCoordinate;
+
+public:
+
+    using PermeabilityType = PT;
+
+    FVSpatialParamsOneP(std::shared_ptr<const GridGeometry> gridGeometry,
+                        pybind11::object pySpatialParams)
+    : ParentType(gridGeometry)
+    , pySpatialParams_(pySpatialParams)
+    {}
+
+    template<class ElementSolution>
+    PermeabilityType permeability(const Element& element,
+                                  const SubControlVolume& scv,
+                                  const ElementSolution& elemSol) const
+    {
+        if (pybind11::hasattr(pySpatialParams_, "permeability"))
+            return pySpatialParams_.attr("permeability")(element, scv, elemSol).template cast<PermeabilityType>();
+        else
+            return pySpatialParams_.attr("permeabilityAtPos")(scv.center()).template cast<PermeabilityType>();
+    }
+
+    template<class ElementSolution>
+    Scalar porosity(const Element& element,
+                              const SubControlVolume& scv,
+                              const ElementSolution& elemSol) const
+    {
+        if (pybind11::hasattr(pySpatialParams_, "porosity"))
+            return pySpatialParams_.attr("porosity")(element, scv, elemSol).template cast<Scalar>();
+        else
+            return pySpatialParams_.attr("porosityAtPos")(scv.center()).template cast<Scalar>();
+    }
+
+private:
+    pybind11::object pySpatialParams_;
+};
+
+
+
 template <class SP, class... options>
-void registerSpatialParams(pybind11::handle scope,
-                           pybind11::class_<SP, options...> cls)
+void registerOnePSpatialParams(pybind11::handle scope,
+                               pybind11::class_<SP, options...> cls)
 {
     using pybind11::operator""_a;
     using GridGeometry = std::decay_t<decltype(std::declval<SP>().gridGeometry())>;
 
-    cls.def(pybind11::init([](std::shared_ptr<GridGeometry> gridGeometry){
-        return std::make_shared<SP>(gridGeometry);
-    }), "gridGeometry"_a);
+    cls.def(pybind11::init([](std::shared_ptr<GridGeometry> gridGeometry, pybind11::object sp){
+        return std::make_shared<SP>(gridGeometry, sp);
+    }));
+
+    cls.def("gravity", &SP::gravity);
 }
 
 } // namespace Dumux::Python
diff --git a/python/dumux/common/__init__.py b/python/dumux/common/__init__.py
index 49c69da9f02af50c91ef77590885884130787fb9..516a08206cb06b45709008331541f1347f606d4c 100644
--- a/python/dumux/common/__init__.py
+++ b/python/dumux/common/__init__.py
@@ -13,13 +13,14 @@ from dune.common.hashit import hashIt
 # class MyProblem:
 #    ...
 #
-def FVProblem(gridGeometry):
+def FVProblem(gridGeometry, spatialParams):
 
     def createModule(numEq):
         priVarType = "Dune::FieldVector<double, {}>".format(numEq)
         ggType = gridGeometry._typeName
-        problemType = "Dumux::Python::FVProblem<{}, {}>".format(ggType, priVarType)
-        includes = gridGeometry._includes + ["dumux/python/common/fvproblem.hh"]
+        spatialParamsType = spatialParams._typeName
+        problemType = "Dumux::Python::FVProblem<{}, {}, {}>".format(ggType, priVarType, spatialParamsType)
+        includes = gridGeometry._includes + spatialParams._includes + ["dumux/python/common/fvproblem.hh"]
         moduleName = "fvproblem_" + hashIt(problemType)
         holderType = "std::shared_ptr<{}>".format(problemType)
         generator = SimpleGenerator("FVProblem", "Dumux::Python")
@@ -30,7 +31,7 @@ def FVProblem(gridGeometry):
         module = createModule(Cls.numEq)
 
         def createFVProblem():
-            return module.FVProblem(gridGeometry, Cls())
+            return module.FVProblem(gridGeometry, spatialParams, Cls())
         return createFVProblem
 
     return FVProblemDecorator
diff --git a/python/dumux/material/__init__.py b/python/dumux/material/__init__.py
index dd20d3b3700effd3a40512aa63d34c7534b82248..48795f40e8c8ee5cc53e8e1f17aa44963148448e 100644
--- a/python/dumux/material/__init__.py
+++ b/python/dumux/material/__init__.py
@@ -1,3 +1,3 @@
 from dumux.material.fluidsystems import FluidSystem
 from dumux.material.components import Component
-from dumux.material.spatialparams import SpatialParams
+from dumux.material.spatialparams import OnePSpatialParams
diff --git a/python/dumux/material/spatialparams/__init__.py b/python/dumux/material/spatialparams/__init__.py
index 63472d5ca9f0cf4d5d2db113fb1cf3b4142eccf3..a2d3bbae36a982753cc70740fa371298cb635cef 100644
--- a/python/dumux/material/spatialparams/__init__.py
+++ b/python/dumux/material/spatialparams/__init__.py
@@ -1,14 +1,58 @@
 from dune.generator.generator import SimpleGenerator
+from dumux.common import Property
+import numpy as np
 
-def SpatialParams(gridGeometry, scalar):
-    moduleName = 'spatialparams'
-    typeName = "Dumux::FVSpatialParamsOnePConstant<{}, {}>".format(gridGeometry._typeName, scalar._typeName)
-    includes = ["dumux/material/spatialparams/fv1pconstant.hh"]
-    includes += ["dumux/python/material/spatialparams/spatialparams.hh"]
-    includes += gridGeometry._includes
-    holderType = "std::shared_ptr<{}>".format(typeName)
 
-    generator = SimpleGenerator("SpatialParams", "Dumux::Python")
-    module = generator.load(includes, typeName, moduleName, options=[holderType])
+def OnePSpatialParams(*, gridGeometry, scalar=None):
+    moduleName = "spatialparams"
+    dim = gridGeometry.gridView.dimension
+    includes = gridGeometry._includes + [
+        "dumux/python/material/spatialparams/spatialparams.hh",
+        "dune/common/fmatrix.hh",
+    ]
 
-    return module.SpatialParams(gridGeometry)
+    if scalar is None:
+        scalar = Property(type="double")
+
+    typeName = f"Dumux::Python::FVSpatialParamsOneP<{gridGeometry._typeName}, {scalar._typeName}, Dune::FieldMatrix<{scalar._typeName}, {dim}, {dim}>>"
+
+    def OnePSpatialParamsDecorator(Cls):
+        generator = SimpleGenerator("OnePSpatialParams", "Dumux::Python")
+        module = generator.load(includes, typeName, moduleName, holder="std::shared_ptr")
+
+        def maybeConvertScalarToMatrix(permeabilityValue):
+            if isinstance(permeabilityValue, float):
+                matrix = np.zeros(shape=(dim, dim))
+                np.fill_diagonal(matrix, permeabilityValue)
+                return matrix.tolist()
+            else:
+                return permeabilityValue
+
+        class Permeability:
+            def __init__(self, permeabilityFunction):
+                self.permeabilityFunction = permeabilityFunction
+
+            def __call__(self, element, scv, elemSol):
+                result = self.permeabilityFunction(element, scv, elemSol)
+                return maybeConvertScalarToMatrix(result)
+
+        class PermeabilityAtPos:
+            def __init__(self, permeabilityFunction):
+                self.permeabilityFunction = permeabilityFunction
+
+            def __call__(self, globalPos):
+                result = self.permeabilityFunction(globalPos)
+                return maybeConvertScalarToMatrix(result)
+
+        def createSpatialParams():
+            sp = Cls()
+            if hasattr(Cls, "permeability"):
+                Cls.permeability = Permeability(sp.permeability)
+            else:
+                Cls.permeabilityAtPos = PermeabilityAtPos(sp.permeabilityAtPos)
+            spatialParams = module.OnePSpatialParams(gridGeometry, sp)
+            return spatialParams
+
+        return createSpatialParams
+
+    return OnePSpatialParamsDecorator