diff --git a/CHANGELOG.md b/CHANGELOG.md
index 663fa3503d2277a580c5b21362f6362585158746..556901d5fb71f9468ef36b402fb3c8ced40c84da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Master
 
+- The `SimoFoxEnergy` class (formerly known as `SimoFoxEnergyLocalStiffness`)
+  does not accept a surface load density anymore. Use the
+  `NeumannEnergy` class for assembling surface loads.
+
 - The classes `LocalGeodesicFEFunction` and `LocalProjectedFEFunction`
   now take a `dune-functions` basis as their first arguments, instead
   of a `LocalFiniteElement`.
diff --git a/dune/gfe/assemblers/mixedgfeassembler.hh b/dune/gfe/assemblers/mixedgfeassembler.hh
index 426096d456df5da22e23df44c151535eeb5ce3a8..b38628c6299eed3d2f8f264a7b40e2c8b563280f 100644
--- a/dune/gfe/assemblers/mixedgfeassembler.hh
+++ b/dune/gfe/assemblers/mixedgfeassembler.hh
@@ -70,16 +70,16 @@ namespace Dune::GFE
      * This is more efficient than computing them separately, because you need the gradient
      * anyway to compute the Riemannian Hessian.
      */
-    virtual void assembleGradientAndHessian(const std::vector<TargetSpace0>& configuration0,
-                                            const std::vector<TargetSpace1>& configuration1,
-                                            Dune::BlockVector<Dune::FieldVector<double, blocksize0> >& gradient0,
-                                            Dune::BlockVector<Dune::FieldVector<double, blocksize1> >& gradient1,
-                                            MatrixType& hessian,
-                                            bool computeOccupationPattern=true) const;
+    void assembleGradientAndHessian(const std::vector<TargetSpace0>& configuration0,
+                                    const std::vector<TargetSpace1>& configuration1,
+                                    Dune::BlockVector<Dune::FieldVector<double, blocksize0> >& gradient0,
+                                    Dune::BlockVector<Dune::FieldVector<double, blocksize1> >& gradient1,
+                                    MatrixType& hessian,
+                                    bool computeOccupationPattern=true) const;
 
     /** \brief Compute the energy of a deformation state */
-    virtual double computeEnergy(const std::vector<TargetSpace0>& configuration0,
-                                 const std::vector<TargetSpace1>& configuration1) const;
+    double computeEnergy(const std::vector<TargetSpace0>& configuration0,
+                         const std::vector<TargetSpace1>& configuration1) const;
 
     //protected:
     void getMatrixPattern(Dune::MatrixIndexSet& nb00,
diff --git a/dune/gfe/assemblers/simofoxenergy.hh b/dune/gfe/assemblers/simofoxenergy.hh
index 424376beb1d0090b037dc20456f4fe5c6845b744..821dd1d198fefa6a4413ec6c89947754914cfc96 100644
--- a/dune/gfe/assemblers/simofoxenergy.hh
+++ b/dune/gfe/assemblers/simofoxenergy.hh
@@ -6,7 +6,6 @@
 #include <dune/common/transpose.hh>
 #include <dune/common/tuplevector.hh>
 #include <dune/functions/functionspacebases/subspacebasis.hh>
-#include <dune/fufem/boundarypatch.hh>
 #include <dune/geometry/quadraturerules.hh>
 #include <dune/gfe/linearalgebra.hh>
 #include <dune/gfe/assemblers/localenergy.hh>
@@ -50,7 +49,7 @@ namespace Dune::GFE
    * and director field.
    */
   template <class Basis, template <typename, typename> typename LocalFEFunction, typename field_type = double>
-  class SimoFoxEnergyLocalStiffness
+  class SimoFoxEnergy
     : public LocalEnergy<Basis, ProductManifold<RealTuple<field_type, 3>,
           UnitVector<field_type, 3> > >
   {
@@ -71,13 +70,9 @@ namespace Dune::GFE
      * \param parameters The material parameters
      * \param x0 reference configuration
      */
-    SimoFoxEnergyLocalStiffness(const Dune::ParameterTree &parameters, const BoundaryPatch<GridView> *neumannBoundary,
-                                const std::function<Dune::FieldVector<double, 3>(Dune::FieldVector<double, 2>)> neumannFunction,
-                                const std::function<Dune::FieldVector<double, 3>(Dune::FieldVector<double, 2>)> volumeLoad,
-                                const Dune::TupleVector<std::vector<RealTuple<double, 3> >, std::vector<UnitVector<double, 3> > > &x0)
-      : neumannBoundary_(neumannBoundary),
-      neumannFunction_(neumannFunction),
-      thickness_{parameters.template get<double>("thickness")},      // The sheeqll thickness
+    SimoFoxEnergy(const Dune::ParameterTree &parameters,
+                  const Dune::TupleVector<std::vector<RealTuple<double, 3> >, std::vector<UnitVector<double, 3> > > &x0)
+      : thickness_{parameters.template get<double>("thickness")},      // The sheeqll thickness
       mu_{parameters.template get<double>("mu")},                    // Lame constant 1
       lambda_{parameters.template get<double>("lambda")},            // Lame constant 2
       kappa_{parameters.template get<double>("kappa")},              // Shear correction factor
@@ -144,15 +139,6 @@ namespace Dune::GFE
     /** \brief Calculate the Green-Lagrange strain components */
     static Dune::FieldVector<RT, 8> calculateGreenLagrangianStrains(const KinematicVariables &kin);
 
-    /** \brief Save all tangent base matrices for all nodes in one place*/
-    Dune::BlockVector<Dune::FieldMatrix<field_type, 2, 3> > directorTangentSpaces;
-
-    /** \brief The Neumann boundary */
-    const BoundaryPatch<GridView> *neumannBoundary_;
-
-    /** \brief The function implementing the Neumann data */
-    const std::function<Dune::FieldVector<double, 3>(Dune::FieldVector<double, dimworld>)> neumannFunction_;
-
     /** \brief The shell thickness */
     double thickness_;
 
@@ -165,9 +151,6 @@ namespace Dune::GFE
     /** \brief Material tangent matrix */
     Dune::FieldMatrix<double, 8, 8> CMat_;
 
-    /** \brief The function implementing a volume load */
-    const std::function<Dune::FieldVector<double, 3>(Dune::FieldVector<double, dimworld>)> volumeLoad_;
-
     /** \brief Stores the reference configuration of the midsurface and the director field */
     const std::vector<RealTuple<double, 3> > &midSurfaceRefConfig;
     const std::vector<UnitVector<double, 3> > &directorRefConfig;
@@ -181,7 +164,7 @@ namespace Dune::GFE
    * gamma_1 and gamma_2 are the transverse shear in the two parametric directions
    * Paper Equation 4.10 */
   template <class Basis, template <typename, typename> typename LocalFEFunction, typename field_type>
-  Dune::FieldVector<field_type, 8> SimoFoxEnergyLocalStiffness<Basis, LocalFEFunction, field_type>::calculateGreenLagrangianStrains(
+  Dune::FieldVector<field_type, 8> SimoFoxEnergy<Basis, LocalFEFunction, field_type>::calculateGreenLagrangianStrains(
     const KinematicVariables &kin)
   {
     Dune::FieldVector<RT, 8> egl;
@@ -210,28 +193,28 @@ namespace Dune::GFE
   template <class Basis, template <typename, typename> typename LocalFEFunction, typename field_type>
   template <typename Element, typename LocalDirectorFunction, typename LocalMidSurfaceFunction, typename LocalDirectorReferenceFunction,
       typename LocalMidSurfaceReferenceFunction, typename IntegrationPointPosition>
-  auto SimoFoxEnergyLocalStiffness<Basis, LocalFEFunction, field_type>::kinematicVariablesFactory(
+  auto SimoFoxEnergy<Basis, LocalFEFunction, field_type>::kinematicVariablesFactory(
     const Element &element, const LocalDirectorFunction &directorFunction, const LocalDirectorReferenceFunction &directorReferenceFunction,
     const LocalMidSurfaceFunction &midSurfaceFunction, const LocalMidSurfaceReferenceFunction &midSurfaceReferenceFunction,
     const LocalMidSurfaceFunction &midSurfaceDisplacementFunction, const IntegrationPointPosition &quadPos)
   {
     KinematicVariables kin{};
 
-    const auto jInvT = element.geometry().jacobianInverseTransposed(quadPos);
+    const auto geometryJacobianInverse = element.geometry().jacobianInverse(quadPos);
 
     kin.t           = directorFunction.evaluate(quadPos).globalCoordinates();
     kin.t0          = directorReferenceFunction.evaluate(quadPos).globalCoordinates();
-    kin.a1anda2     = transpose(midSurfaceFunction.evaluateDerivative(quadPos) * transpose(jInvT));
-    kin.A1andA2     = transpose(midSurfaceReferenceFunction.evaluateDerivative(quadPos) * transpose(jInvT));
-    kin.ud1andud2   = transpose(midSurfaceDisplacementFunction.evaluateDerivative(quadPos) * transpose(jInvT));
-    kin.t0d1Andt0d2 = transpose(directorReferenceFunction.evaluateDerivative(quadPos) * transpose(jInvT));
-    kin.td1Andtd2   = transpose(directorFunction.evaluateDerivative(quadPos) * transpose(jInvT));
+    kin.a1anda2     = transpose(midSurfaceFunction.evaluateDerivative(quadPos) * geometryJacobianInverse);
+    kin.A1andA2     = transpose(midSurfaceReferenceFunction.evaluateDerivative(quadPos) * geometryJacobianInverse);
+    kin.ud1andud2   = transpose(midSurfaceDisplacementFunction.evaluateDerivative(quadPos) * geometryJacobianInverse);
+    kin.t0d1Andt0d2 = transpose(directorReferenceFunction.evaluateDerivative(quadPos) * geometryJacobianInverse);
+    kin.td1Andtd2   = transpose(directorFunction.evaluateDerivative(quadPos) * geometryJacobianInverse);
 
     return kin;
   }
 
   template <class Basis, template <typename, typename> typename LocalFEFunction, typename field_type>
-  auto SimoFoxEnergyLocalStiffness<Basis, LocalFEFunction, field_type>::getReferenceLocalConfigurations(
+  auto SimoFoxEnergy<Basis, LocalFEFunction, field_type>::getReferenceLocalConfigurations(
     const typename Basis::LocalView &localView) const {
     using namespace Dune::Indices;
     const int nDofs0 = localView.tree().child(_0, 0).finiteElement().size();
@@ -269,8 +252,8 @@ namespace Dune::GFE
    *  see for details Paper Equation 4.11,4.10 and 10.1
    */
   template <class Basis, template <typename, typename> typename LocalFEFunction, typename field_type>
-  typename SimoFoxEnergyLocalStiffness<Basis, LocalFEFunction, field_type>::RT
-  SimoFoxEnergyLocalStiffness<Basis, LocalFEFunction, field_type>::energy(
+  typename SimoFoxEnergy<Basis, LocalFEFunction, field_type>::RT
+  SimoFoxEnergy<Basis, LocalFEFunction, field_type>::energy(
     const typename Basis::LocalView &localView,
     const typename Impl::LocalEnergyTypes<TargetSpace>::CompositeCoefficients &localConfiguration) const
   {
@@ -327,36 +310,6 @@ namespace Dune::GFE
       energy +=  0.5 * Egl * (CMat_ * Egl) * curQuad.weight() * integrationElement;
     }
 
-    //////////////////////////////////////////////////////////////////////////////
-    //   Assemble boundary contributions
-    //////////////////////////////////////////////////////////////////////////////
-
-    if (not neumannFunction_) return energy;
-
-    for (auto &&it : intersections(neumannBoundary_->gridView(), element))
-    {
-      if (not neumannBoundary_ or not neumannBoundary_->contains(it)) continue;
-
-      const auto &quadLine = QuadratureRules<DT, gridDim - 1>::rule(it.type(), quadOrder);
-
-      for (const auto &curQuad : quadLine)
-      {
-        // Local position of the quadrature point
-        const FieldVector<DT, gridDim> &quadPos = it.geometryInInside().global(curQuad.position());
-
-        const DT integrationElement = it.geometry().integrationElement(curQuad.position());
-
-        // The value of the local function
-        RealTuple<field_type, 3> deformationValue = localMidSurfaceFunction.evaluate(quadPos);
-
-        // Value of the Neumann data at the current position
-        auto neumannValue = neumannFunction_(it.geometry().global(curQuad.position()));
-
-        // Only translational dofs are affected by the Neumann force
-        for (size_t i = 0; i < neumannValue.size(); i++)
-          energy -= (neumannValue[i] * deformationValue.globalCoordinates()[i]) * curQuad.weight() * integrationElement;
-      }
-    }
     return energy;
   }
 
diff --git a/dune/gfe/densities/duneelasticitydensity.hh b/dune/gfe/densities/duneelasticitydensity.hh
index 4d104077e7ec9d6f90e63d57e429b6cefe99b8fa..b3e1de3a36c03f709134c4bc234c9fecda63343e 100644
--- a/dune/gfe/densities/duneelasticitydensity.hh
+++ b/dune/gfe/densities/duneelasticitydensity.hh
@@ -73,7 +73,7 @@ namespace Dune::GFE
     }
 
     // Construct a copy of this density but using 'adouble' as the number type
-    virtual std::unique_ptr<LocalDensity<ElementOrIntersection,ATargetSpace> > makeActiveDensity() const
+    virtual std::unique_ptr<LocalDensity<ElementOrIntersection,ATargetSpace> > makeActiveDensity() const override
     {
       // The active dune-elasticity density
       auto activeDensity = elasticityDensity_->makeActiveDensity();
diff --git a/dune/gfe/densities/localdensity.hh b/dune/gfe/densities/localdensity.hh
index 6bc6b4c220447d2f01c200f0c6f169b35f24155c..8f6e50abc12ac99d4af765979d226dbaf8be92b9 100644
--- a/dune/gfe/densities/localdensity.hh
+++ b/dune/gfe/densities/localdensity.hh
@@ -63,7 +63,7 @@ namespace Dune::GFE
 
     }
 
-    ~LocalDensity()
+    virtual ~LocalDensity()
     {
       myfree3(densityTangent_);
       myfree3(Yppp_);
diff --git a/src/simofoxshell.cc b/src/simofoxshell.cc
index f437dab615561da64944b1d6e55aa1db5af0cf64..72e7291b60cdf8c28482907634e9edaeac960a73 100644
--- a/src/simofoxshell.cc
+++ b/src/simofoxshell.cc
@@ -28,10 +28,12 @@
 #include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh>
 #include <dune/gfe/assemblers/simofoxenergy.hh>
 #include <dune/gfe/assemblers/mixedgfeassembler.hh>
+#include <dune/gfe/assemblers/sumenergy.hh>
 #include <dune/gfe/functions/embeddedglobalgfefunction.hh>
 #include <dune/gfe/functions/localgeodesicfefunction.hh>
 #include <dune/gfe/functions/localprojectedfefunction.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
+#include <dune/gfe/neumannenergy.hh>
 #include <dune/gfe/spaces/unitvector.hh>
 
 #if !MIXED_SPACE
@@ -195,10 +197,10 @@ int main(int argc, char *argv[]) try
   }
 
   BoundaryPatch<GridView> dirichletBoundary(gridView, dirichletVertices);
-  BoundaryPatch<GridView> neumannBoundary(gridView, neumannVertices);
+  auto neumannBoundary = std::make_shared<BoundaryPatch<GridView> >(gridView, neumannVertices);
 
   if (mpiHelper.rank() == 0)
-    std::cout << "Neumann boundary has " << neumannBoundary.numFaces() << " faces\n";
+    std::cout << "Neumann boundary has " << neumannBoundary->numFaces() << " faces\n";
 
   BitSetVector<1> deformationDirichletNodes(midsurfaceFEBasis.size(), false);
 #if DUNE_VERSION_GTE(DUNE_FUFEM, 2, 10)
@@ -209,9 +211,9 @@ int main(int argc, char *argv[]) try
 
   BitSetVector<1> neumannNodes(midsurfaceFEBasis.size(), false);
 #if DUNE_VERSION_GTE(DUNE_FUFEM, 2, 10)
-  Fufem::markBoundaryPatchDofs(neumannBoundary, directorFEBasis, neumannNodes);
+  Fufem::markBoundaryPatchDofs(*neumannBoundary, directorFEBasis, neumannNodes);
 #else
-  constructBoundaryDofs(neumannBoundary, directorFEBasis, neumannNodes);
+  constructBoundaryDofs(*neumannBoundary, directorFEBasis, neumannNodes);
 #endif
 
   BitSetVector<3> deformationDirichletDofs(midsurfaceFEBasis.size(), false);
@@ -316,19 +318,25 @@ int main(int argc, char *argv[]) try
       materialParameters.report();
     }
 
-    // Assembler using ADOL-C
-    auto simoFoxEnergyLocalStiffness
-      = std::make_shared<GFE::SimoFoxEnergyLocalStiffness<decltype(compositeBasis),
+    // The total energy on one element
+    auto sumEnergy = std::make_shared<GFE::SumEnergy<decltype(compositeBasis), GFE::RealTuple<adouble,3>,GFE::UnitVector<adouble,3> > >();
+
+    // Internal energy of the shell
+    auto simoFoxEnergy
+      = std::make_shared<GFE::SimoFoxEnergy<decltype(compositeBasis),
         LocalFEFunction,
-        adouble> > (materialParameters,
-                    &neumannBoundary,
-                    neumannFunction,
-                    nullptr, x0);
+        adouble> > (materialParameters, x0);
+    sumEnergy->addLocalEnergy(simoFoxEnergy);
+
+    // The Neumann surface load term
+    auto neumannEnergy = std::make_shared<GFE::NeumannEnergy<decltype(compositeBasis), GFE::RealTuple<adouble,3>, GFE::UnitVector<adouble,3> > >(neumannBoundary,neumannFunction);
+    sumEnergy->addLocalEnergy(neumannEnergy);
 
     using TargetSpace = GFE::ProductManifold<GFE::RealTuple<double,3>,GFE::UnitVector<double,3> >;
 
+    // Use ADOL-C to assemble the element stiffness matrices
     GFE::LocalGeodesicFEADOLCStiffness<decltype(compositeBasis),
-        TargetSpace> localGFEADOLCStiffness(simoFoxEnergyLocalStiffness);
+        TargetSpace> localGFEADOLCStiffness(sumEnergy);
 
     GFE::MixedGFEAssembler<decltype(compositeBasis),TargetSpace> assembler(compositeBasis, localGFEADOLCStiffness);
     ////////////////////////////////////////////////////////