diff --git a/dune/gfe/assemblers/cosseratenergystiffness.hh b/dune/gfe/assemblers/cosseratenergystiffness.hh
index d506ea8d19107f496278806287f39884ee727dba..25d2a2fb37c314348918ead3a9d6b3167eaad1e2 100644
--- a/dune/gfe/assemblers/cosseratenergystiffness.hh
+++ b/dune/gfe/assemblers/cosseratenergystiffness.hh
@@ -1,6 +1,14 @@
 #ifndef COSSERAT_ENERGY_LOCAL_STIFFNESS_HH
 #define COSSERAT_ENERGY_LOCAL_STIFFNESS_HH
 
+#define DONT_USE_CURL
+
+//#define QUADRATIC_2006 //only relevant for gridDim == 3
+// Use the formula for the quadratic membrane energy (first equation of (4.4)) in Neff's paper from 2006: A geometrically exact planar Cosserat shell model with microstructure: Existence of minimizers for zero Cosserat couple modulus
+// instead of the equation (2.27) of 2019: Refined dimensional reduction for isotropic elastic Cosserat shells with initial curvature
+
+//#define QUADRATIC_MEMBRANE_ENERGY //only relevant for gridDim == 2
+
 #include <dune/common/fmatrix.hh>
 #include <dune/common/parametertree.hh>
 #include <dune/common/version.hh>
@@ -10,6 +18,7 @@
 #include <dune/fufem/boundarypatch.hh>
 
 #include <dune/gfe/assemblers/localenergy.hh>
+#include <dune/gfe/densities/bulkcosseratdensity.hh>
 #ifdef PROJECTED_INTERPOLATION
 #include <dune/gfe/localprojectedfefunction.hh>
 #else
@@ -22,16 +31,6 @@
 #include <dune/gfe/spaces/realtuple.hh>
 #include <dune/gfe/spaces/rotation.hh>
 
-#define DONT_USE_CURL
-
-#define CURVATURE_WITH_WRYNESS //only relevant for gridDim == 3
-
-//#define QUADRATIC_2006 //only relevant for gridDim == 3
-// Use the formula for the quadratic membrane energy (first equation of (4.4)) in Neff's paper from 2006: A geometrically exact planar Cosserat shell model with microstructure: Existence of minimizers for zero Cosserat couple modulus
-// instead of the equation (2.27) of 2019: Refined dimensional reduction for isotropic elastic Cosserat shells with initial curvature
-
-//#define QUADRATIC_MEMBRANE_ENERGY //only relevant for gridDim == 2
-
 /** \brief Get LocalFiniteElements from a localView, for different tree depths of the local view
  *
  * We instantiate the CosseratEnergyLocalStiffness class with two different kinds of Basis:
@@ -101,6 +100,7 @@ public:
    * \param parameters The material parameters
    */
   CosseratEnergyLocalStiffness(const Dune::ParameterTree& parameters)
+  : bulkDensity_(parameters)
   {
     // The shell thickness // only relevant for dim == 2
     thickness_ = parameters.template get<double>("thickness");
@@ -120,11 +120,6 @@ public:
 
     // Shear correction factor // only relevant for dim == 2
     kappa_ = parameters.template get<double>("kappa");
-
-    // Curvature parameters
-    b1_ = parameters.template get<double>("b1");
-    b2_ = parameters.template get<double>("b2");
-    b3_ = parameters.template get<double>("b3");
   }
 
   /** \brief Constructor with material parameters and external loads
@@ -137,7 +132,8 @@ public:
                                const BoundaryPatch<GridView>* neumannBoundary,
                                const std::function<Dune::FieldVector<double,3>(Dune::FieldVector<double,dimworld>)> neumannFunction,
                                const std::function<Dune::FieldVector<double,3>(Dune::FieldVector<double,dimworld>)> volumeLoad)
-    : neumannBoundary_(neumannBoundary),
+    : bulkDensity_(parameters),
+    neumannBoundary_(neumannBoundary),
     neumannFunction_(neumannFunction),
     volumeLoad_(volumeLoad)
   {
@@ -159,11 +155,6 @@ public:
 
     // Shear correction factor // only relevant for dim == 2
     kappa_ = parameters.template get<double>("kappa");
-
-    // Curvature parameters
-    b1_ = parameters.template get<double>("b1");
-    b2_ = parameters.template get<double>("b2");
-    b3_ = parameters.template get<double>("b3");
   }
 
   /** \brief Assemble the energy for a single element */
@@ -283,37 +274,6 @@ public:
 #endif
   }
 
-  RT curvatureWithWryness(const Dune::FieldMatrix<field_type,dim,dim>& R, const Tensor3<field_type,3,3,gridDim>& DR) const
-  {
-    // construct Wryness tensor \Gamma as in "Refined dimensional reduction for isotropic elastic Cosserat shells with initial curvature"
-    Dune::FieldMatrix<field_type,3,3> dRx1(0);     //Derivative of R with respect to x1
-    Dune::FieldMatrix<field_type,3,3> dRx2(0);     //Derivative of R with respect to x2
-    Dune::FieldMatrix<field_type,3,3> dRx3(0);     //Derivative of R with respect to x3, this of course only exists if gridDim = 3 (then dim = 3 also, because dim >= gridDim, always)
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++) {
-        dRx1[i][j] = DR[i][j][0];
-        dRx2[i][j] = DR[i][j][1];
-        dRx3[i][j] = gridDim == 3 ? DR[i][j][2] : 0;
-      }
-
-    Dune::FieldMatrix<field_type,3,3> wryness(0);
-
-    auto axialVectorx1 = SkewMatrix<field_type,3>(transpose(R)*dRx1).axial();
-    auto axialVectorx2 = SkewMatrix<field_type,3>(transpose(R)*dRx2).axial();
-    auto axialVectorx3 = SkewMatrix<field_type,3>(transpose(R)*dRx3).axial();
-
-    for (int i=0; i<3; i++) {
-      wryness[i][0] = axialVectorx1[i];
-      wryness[i][1] = axialVectorx2[i];
-      wryness[i][2] = gridDim == 3 ? axialVectorx3[i] : 0;
-    }
-
-    // The choice for the Frobenius norm here is b1=b2=1 and b3 = 1/3
-    return mu_ * L_c_ * L_c_ * (b1_ * Dune::GFE::dev(Dune::GFE::sym(wryness)).frobenius_norm2()
-                                + b2_ * Dune::GFE::skew(wryness).frobenius_norm2() + b3_ * Dune::GFE::traceSquared(wryness));
-  }
-
-
   RT bendingEnergy(const Dune::FieldMatrix<field_type,dim,dim>& R, const Tensor3<field_type,3,3,gridDim>& DR) const
   {
     // left-multiply the derivative of the third director (in DR[][2][]) with R^T
@@ -328,6 +288,9 @@ public:
            + mu_*lambda_/(2*mu_+lambda_) * Dune::GFE::traceSquared(RT_DR3);
   }
 
+  /** The energy density if the grid is three-dimensional */
+  Dune::GFE::BulkCosseratDensity<Dune::FieldVector<double,3>,field_type> bulkDensity_;
+
   /** \brief The shell thickness */
   double thickness_;
 
@@ -346,9 +309,6 @@ public:
   /** \brief Shear correction factor */
   double kappa_;
 
-  /** \brief Curvature parameters */
-  double b1_, b2_, b3_;
-
   /** \brief The Neumann boundary */
   const BoundaryPatch<GridView>* neumannBoundary_ = nullptr;
 
@@ -434,7 +394,7 @@ energy(const typename Basis::LocalView& localView,
     Tensor3<field_type,3,3,gridDim> DR = value[_1].quaternionTangentToMatrixTangent(orientationDerivative);
 
     // Add the local energy density
-    if (gridDim==2) {
+    if constexpr (gridDim==2) {
 #ifdef QUADRATIC_MEMBRANE_ENERGY
       //energy += weight * thickness_ * quadraticMembraneEnergy(U.matrix());
       energy += weight * thickness_ * longQuadraticMembraneEnergy(U);
@@ -444,13 +404,10 @@ energy(const typename Basis::LocalView& localView,
 #endif
       energy += weight * thickness_ * curvatureEnergy(DR);
       energy += weight * std::pow(thickness_,3) / 12.0 * bendingEnergy(R,DR);
-    } else if (gridDim==3) {
-      energy += weight * quadraticMembraneEnergy(U);
-#ifdef CURVATURE_WITH_WRYNESS
-      energy += weight * curvatureWithWryness(R,DR);
-#else
-      energy += weight * curvatureEnergy(DR);
-#endif
+    } else if constexpr (gridDim==3) {
+      energy += weight * bulkDensity_(quadPos,
+                                      value.globalCoordinates(),
+                                      derivative);
     } else
       DUNE_THROW(Dune::NotImplemented, "CosseratEnergyStiffness for 1d grids");
 
@@ -559,6 +516,10 @@ energy(const typename Basis::LocalView& localView,
     RealTuple<field_type,dim> deformationValue = localDeformationGFEFunction.evaluate(quadPos);
     Rotation<field_type,dim>  orientationValue = localOrientationGFEFunction.evaluate(quadPos);
 
+    TargetSpace value;
+    value[_0] = deformationValue;
+    value[_1] = orientationValue;
+
     // The derivative of the local function defined on the reference element
     typename LocalDeformationGFEFunctionType::DerivativeType deformationReferenceDerivative = localDeformationGFEFunction.evaluateDerivative(quadPos,deformationValue);
     typename LocalOrientationGFEFunctionType::DerivativeType orientationReferenceDerivative = localOrientationGFEFunction.evaluateDerivative(quadPos,orientationValue);
@@ -573,6 +534,16 @@ energy(const typename Basis::LocalView& localView,
     for (size_t comp=0; comp<orientationReferenceDerivative.N(); comp++)
       jacobianInverseTransposed.mv(orientationReferenceDerivative[comp], orientationDerivative[comp]);
 
+    // The derivative of both factors together
+    typename Dune::FieldMatrix<field_type,deformationDerivative.N() + orientationDerivative.N(), gridDim> derivative(0);
+
+    size_t rowCount = 0;
+    for (auto&& row : deformationDerivative)
+      derivative[rowCount++] = row;
+
+    for (auto&& row : orientationDerivative)
+      derivative[rowCount++] = row;
+
     /////////////////////////////////////////////////////////
     // compute U, the Cosserat strain
     /////////////////////////////////////////////////////////
@@ -592,7 +563,7 @@ energy(const typename Basis::LocalView& localView,
     Tensor3<field_type,3,3,gridDim> DR = orientationValue.quaternionTangentToMatrixTangent(orientationDerivative);
 
     // Add the local energy density
-    if (gridDim==2) {
+    if constexpr (gridDim==2) {
 #ifdef QUADRATIC_MEMBRANE_ENERGY
       //energy += weight * thickness_ * quadraticMembraneEnergy(U.matrix());
       energy += weight * thickness_ * longQuadraticMembraneEnergy(U);
@@ -601,13 +572,10 @@ energy(const typename Basis::LocalView& localView,
 #endif
       energy += weight * thickness_ * curvatureEnergy(DR);
       energy += weight * std::pow(thickness_,3) / 12.0 * bendingEnergy(R,DR);
-    } else if (gridDim==3) {
-      energy += weight * quadraticMembraneEnergy(U);
-#ifdef CURVATURE_WITH_WRYNESS
-      energy += weight * curvatureWithWryness(R,DR);
-#else
-      energy += weight * curvatureEnergy(DR);
-#endif
+    } else if constexpr (gridDim==3) {
+      energy += weight * bulkDensity_(quadPos,
+                                      value.globalCoordinates(),
+                                      derivative);
     } else
       DUNE_THROW(Dune::NotImplemented, "CosseratEnergyStiffness for 1d grids");