diff --git a/dune/gfe/surfacecosseratenergy.hh b/dune/gfe/surfacecosseratenergy.hh
index e6a0bb1aec297aa3090c13d648915e58eb055374..101c37b9986b73c96746603e2e8014d9bf130d7d 100644
--- a/dune/gfe/surfacecosseratenergy.hh
+++ b/dune/gfe/surfacecosseratenergy.hh
@@ -213,18 +213,15 @@ public:
   SurfaceCosseratEnergy(const Dune::ParameterTree& parameters,
     const std::vector<UnitVector<double,3> >& vertexNormals,
     const BoundaryPatch<GridView>* shellBoundary,
-    const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dim-1, dim>>& geometriesOnShellBoundary)
+    const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dim-1, dim>>& geometriesOnShellBoundary,
+    const std::function<double(Dune::FieldVector<double,dim>)> thicknessF,
+    const std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF)
   : shellBoundary_(shellBoundary),
     vertexNormals_(vertexNormals),
-    geometriesOnShellBoundary_(geometriesOnShellBoundary)
+    geometriesOnShellBoundary_(geometriesOnShellBoundary),
+    thicknessF_(thicknessF),
+    lameF_(lameF)
   {
-    // The shell thickness
-    thickness_ = parameters.template get<double>("thickness");
-
-    // Lame constants
-    mu_ = parameters.template get<double>("mu_cosserat");
-    lambda_ = parameters.template get<double>("lambda_cosserat");
-
     // Cosserat couple modulus
     mu_c_ = parameters.template get<double>("mu_c");
 
@@ -293,6 +290,13 @@ RT energy(const typename Basis::LocalView& localView,
       // Local position of the quadrature point
       const Dune::FieldVector<DT,gridDim>& quadPos = it.geometryInInside().global(quad[pt].position());;
 
+      // Global position of the quadrature point
+      auto quadPosGlobal = it.geometry().global(quad[pt].position());
+      double thickness = thicknessF_(quadPosGlobal);
+      auto lameConstants = lameF_(quadPosGlobal);
+      double mu = lameConstants[0];
+      double lambda = lameConstants[1];
+
       const DT integrationElement = boundaryGeometry.integrationElement(quad[pt].position());
 
       // The value of the local function
@@ -416,15 +420,15 @@ RT energy(const typename Basis::LocalView& localView,
       //////////////////////////////////////////////////////////
 
       // Add the membrane energy density
-      auto energyDensity = (thickness_ - K*Dune::Power<3>::eval(thickness_) / 12.0) * W_m(Ee);
-      energyDensity += (Dune::Power<3>::eval(thickness_) / 12.0 - K * Dune::Power<5>::eval(thickness_) / 80.0)*W_m(Ee*b + c*Ke);
-      energyDensity += Dune::Power<3>::eval(thickness_) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke);
-      energyDensity += Dune::Power<5>::eval(thickness_) / 80.0 * W_mp( (Ee*b + c*Ke)*b);
+      auto energyDensity = (thickness - K*Dune::Power<3>::eval(thickness) / 12.0) * W_m(Ee, mu, lambda);
+      energyDensity += (Dune::Power<3>::eval(thickness) / 12.0 - K * Dune::Power<5>::eval(thickness) / 80.0)*W_m(Ee*b + c*Ke, mu, lambda);
+      energyDensity += Dune::Power<3>::eval(thickness) / 6.0 * W_mixt(Ee, c*Ke*b - 2*H*c*Ke, mu, lambda);
+      energyDensity += Dune::Power<5>::eval(thickness) / 80.0 * W_mp( (Ee*b + c*Ke)*b, mu, lambda);
 
       // Add the bending energy density
-      energyDensity += (thickness_ - K*Dune::Power<3>::eval(thickness_) / 12.0) * W_curv(Ke)
-                     + (Dune::Power<3>::eval(thickness_) / 12.0 - K * Dune::Power<5>::eval(thickness_) / 80.0)*W_curv(Ke*b)
-                     + Dune::Power<5>::eval(thickness_) / 80.0 * W_curv(Ke*b*b);
+      energyDensity += (thickness - K*Dune::Power<3>::eval(thickness) / 12.0) * W_curv(Ke, mu)
+                     + (Dune::Power<3>::eval(thickness) / 12.0 - K * Dune::Power<5>::eval(thickness) / 80.0)*W_curv(Ke*b, mu)
+                     + Dune::Power<5>::eval(thickness) / 80.0 * W_curv(Ke*b*b, mu);
 
       // Add energy density
       energy += quad[pt].weight() * integrationElement * energyDensity;
@@ -434,26 +438,26 @@ RT energy(const typename Basis::LocalView& localView,
   return energy;
 }
 
-  RT W_m(const Dune::FieldMatrix<field_type,3,3>& S) const
+  RT W_m(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const
   {
-    return W_mixt(S,S);
+    return W_mixt(S,S, mu, lambda);
   }
 
-  RT W_mixt(const Dune::FieldMatrix<field_type,3,3>& S, const Dune::FieldMatrix<field_type,3,3>& T) const
+  RT W_mixt(const Dune::FieldMatrix<field_type,3,3>& S, const Dune::FieldMatrix<field_type,3,3>& T, double mu, double lambda) const
   {
-    return mu_ * frobeniusProduct(sym(S), sym(T))
+    return mu * frobeniusProduct(sym(S), sym(T))
          + mu_c_ * frobeniusProduct(skew(S), skew(T))
-         + lambda_ * mu_ / (lambda_ + 2*mu_) * trace(S) * trace(T);
+         + lambda * mu / (lambda + 2*mu) * trace(S) * trace(T);
   }
 
-  RT W_mp(const Dune::FieldMatrix<field_type,3,3>& S) const
+  RT W_mp(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const
   {
-    return mu_ * sym(S).frobenius_norm2() + mu_c_ * skew(S).frobenius_norm2() + lambda_ * 0.5 * traceSquared(S);
+    return mu * sym(S).frobenius_norm2() + mu_c_ * skew(S).frobenius_norm2() + lambda * 0.5 * traceSquared(S);
   }
 
-  RT W_curv(const Dune::FieldMatrix<field_type,3,3>& S) const
+  RT W_curv(const Dune::FieldMatrix<field_type,3,3>& S, double mu) const
   {
-    return mu_ * L_c_ * L_c_ * (b1_ * dev(sym(S)).frobenius_norm2() + b2_ * skew(S).frobenius_norm2() + b3_ * traceSquared(S));
+    return mu * L_c_ * L_c_ * (b1_ * dev(sym(S)).frobenius_norm2() + b2_ * skew(S).frobenius_norm2() + b3_ * traceSquared(S));
   }
 
 private:
@@ -463,11 +467,14 @@ private:
   /** \brief Stress-free geometries of the shell elements*/
   const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType, Dune::MultiLinearGeometry<double, dim-1, dim>> geometriesOnShellBoundary_;
 
-  /** \brief The normal vectors at the grid vertices.  This are used to compute the reference surface curvature. */
+  /** \brief The normal vectors at the grid vertices. They are used to compute the reference surface curvature. */
   std::vector<UnitVector<double,3> > vertexNormals_;
 
-  /** \brief The shell thickness */
-  double thickness_;
+  /** \brief The shell thickness as a function*/
+  std::function<double(Dune::FieldVector<double,dim>)> thicknessF_;
+
+  /** \brief The Lamé-parameters as a function*/
+  std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF_;
 
   /** \brief Lame constants */
   double mu_, lambda_;
diff --git a/src/film-on-substrate.cc b/src/film-on-substrate.cc
index 5e9d376a1c8f4f26ed1639f871097e732c6b8bd0..471ea478564f912ead8f141f3acc0c03caf597d9 100644
--- a/src/film-on-substrate.cc
+++ b/src/film-on-substrate.cc
@@ -434,6 +434,14 @@ int main (int argc, char *argv[]) try
     }
   }
 
+  const ParameterTree& materialParameters = parameterSet.sub("materialParameters");
+  Python::Reference surfaceShellClass = Python::import(materialParameters.get<std::string>("surfaceShellParameters"));
+  Python::Callable surfaceShellCallable = surfaceShellClass.get("SurfaceShellParameters");
+
+  Python::Reference pythonObject = surfaceShellCallable();
+  PythonFunction<Dune::FieldVector<double, dim>, double> fThickness(pythonObject.get("thickness"));
+  PythonFunction<Dune::FieldVector<double, dim>, Dune::FieldVector<double, 2>> fLame(pythonObject.get("lame"));
+
   for (int i=0; i<numHomotopySteps; i++)
   {
     double homotopyParameter = (i+1)*(1.0/numHomotopySteps);
@@ -442,7 +450,6 @@ int main (int argc, char *argv[]) try
     //   Create an assembler for the energy functional
     // ////////////////////////////////////////////////////////////
 
-    const ParameterTree& materialParameters = parameterSet.sub("materialParameters");
 
 #if DUNE_VERSION_LT(DUNE_ELASTICITY, 2, 8)
     std::shared_ptr<NeumannFunction> neumannFunction;
@@ -547,7 +554,7 @@ int main (int argc, char *argv[]) try
       vertexNormals[i] = vertexNormal;
     }
 
-    surfaceCosseratEnergy = std::make_shared<SurfaceCosseratEnergy<FEBasis,RigidBodyMotion<adouble, dim>, adouble, adouble>>(materialParameters, std::move(vertexNormals), &surfaceShellBoundary, std::move(geometriesOnShellBoundary));
+    surfaceCosseratEnergy = std::make_shared<SurfaceCosseratEnergy<FEBasis,RigidBodyMotion<adouble, dim>, adouble, adouble>>(materialParameters, std::move(vertexNormals), &surfaceShellBoundary, std::move(geometriesOnShellBoundary), fThickness, fLame);
 
     std::shared_ptr<LocalEnergyBase> totalEnergy;
     totalEnergy = std::make_shared<GFE::SumCosseratEnergy<FEBasis,RigidBodyMotion<adouble, dim>, adouble>> (elasticAndNeumann, surfaceCosseratEnergy);
diff --git a/src/film-on-substrate.parset b/src/film-on-substrate.parset
index ccfdc893004623560cf8cdb141aabce01e6c3949..645c408bf9efca144da5cdc2c0dfe1b101901442 100644
--- a/src/film-on-substrate.parset
+++ b/src/film-on-substrate.parset
@@ -97,16 +97,12 @@ energy = stvenantkirchhoff
 ## For the Wriggers L-shape example
 [materialParameters]
 
-# shell thickness
-thickness = 0.6
+surfaceShellParameters = surface-shell-parameters-1-3
 
 ## Lame parameters for stvenantkirchhoff, E = mu(3*lambda + 2*mu)/(lambda + mu)
 # mu = 2.7191e+4
 # lambda = 4.4364e+4
 
-#Lame parameters for the cosserat material
-mu_cosserat = 7.64e+6 #Parameters for E = 20.4 MPa, nu=0.335
-lambda_cosserat = 1.55e+7
 
 # Cosserat couple modulus
 mu_c = 0
@@ -144,5 +140,4 @@ mooneyrivlin_energy = log # log, square or ciarlet; different ways to compute th
 # log: Generalized Rivlin model or polynomial hyperelastic model, using  0.5*mooneyrivlin_k*log(det(∇φ)) as the volume-preserving penalty term
 # square: Generalized Rivlin model or polynomial hyperelastic model, using mooneyrivlin_k*(det(∇φ)-1)² as the volume-preserving penalty term
 
-[]
-
+[]
\ No newline at end of file
diff --git a/src/surface-shell-parameters-1-3.py b/src/surface-shell-parameters-1-3.py
new file mode 100644
index 0000000000000000000000000000000000000000..17ebcee453e862d3fcfd9fd9401f0404dd68e4a0
--- /dev/null
+++ b/src/surface-shell-parameters-1-3.py
@@ -0,0 +1,18 @@
+import math
+
+class SurfaceShellParameters:
+    def thickness(self, x):
+        if (x[1] > 50.0):
+            return 1.0
+        else:
+            return 3.0
+
+    #Lame parameters for the surface shell material:
+    #Parameters for E = 20.4 MPa, nu=0.335
+    #mu_cosserat = 7.64e+6
+    #lambda_cosserat = 1.55e+7
+    def lame(self, x):
+        if (x[1] > 50.0):
+            return [7.64e+6,1.55e+7]
+        else:
+            return [7.64e+6,1.55e+7]