diff --git a/dune/elasticity/assemblers/feassembler.hh b/dune/elasticity/assemblers/feassembler.hh
index 50692f4f48ce7784f6cc67182c32bd52bbc8f4d9..c52d50af4bd69ce37b9169bed2fb3dc070a18f37 100644
--- a/dune/elasticity/assemblers/feassembler.hh
+++ b/dune/elasticity/assemblers/feassembler.hh
@@ -5,13 +5,15 @@
 #include <dune/common/fmatrix.hh>
 #include <dune/istl/matrixindexset.hh>
 #include <dune/istl/matrix.hh>
+#include <dune/istl/multitypeblockmatrix.hh>
+#include <dune/istl/multitypeblockvector.hh>
 
-#include "localfestiffness.hh"
+// #include "localfestiffness.hh"
 
 
 /** \brief A global FE assembler for variational problems
  */
-template <class Basis, class VectorType>
+template <class Basis, class VectorType, class LocalFEStiffness>
 class FEAssembler {
 
     typedef typename Basis::GridView GridView;
@@ -33,15 +35,13 @@ public:
 
 protected:
 
-    LocalFEStiffness<GridView,
-                             typename Basis::LocalFiniteElement,
-                             VectorType>* localStiffness_;
+    LocalFEStiffness* localStiffness_;
 
 public:
 
     /** \brief Constructor for a given grid */
     FEAssembler(const Basis& basis,
-                LocalFEStiffness<GridView,typename Basis::LocalFiniteElement, VectorType>* localStiffness)
+                LocalFEStiffness* localStiffness)
         : basis_(basis),
           localStiffness_(localStiffness)
     {}
@@ -65,8 +65,8 @@ public:
 
 
 
-template <class Basis, class TargetSpace>
-void FEAssembler<Basis,TargetSpace>::
+template <class Basis, class TargetSpace, class LocalFEStiffness>
+void FEAssembler<Basis,TargetSpace,LocalFEStiffness>::
 getNeighborsPerVertex(Dune::MatrixIndexSet& nb) const
 {
     int n = basis_.size();
@@ -94,8 +94,8 @@ getNeighborsPerVertex(Dune::MatrixIndexSet& nb) const
 
 }
 
-template <class Basis, class VectorType>
-void FEAssembler<Basis,VectorType>::
+template <class Basis, class VectorType, class LocalFEStiffness>
+void FEAssembler<Basis,VectorType,LocalFEStiffness>::
 assembleGradientAndHessian(const VectorType& sol,
                            Dune::BlockVector<Dune::FieldVector<double, blocksize> >& gradient,
                            Dune::BCRSMatrix<MatrixBlock>& hessian,
@@ -152,8 +152,8 @@ assembleGradientAndHessian(const VectorType& sol,
 }
 
 
-template <class Basis, class VectorType>
-double FEAssembler<Basis, VectorType>::
+template <class Basis, class VectorType, class LocalFEStiffness>
+double FEAssembler<Basis, VectorType, LocalFEStiffness>::
 computeEnergy(const VectorType& sol) const
 {
     double energy = 0;
@@ -179,4 +179,301 @@ computeEnergy(const VectorType& sol) const
     return energy;
 
 }
+
+
+
+
+
+
+
+/** \brief MultiTypeBlockvector extension of FEAssembler
+ *  The Basis is assumed to be in correct shape
+ *
+ *  Basis: We expect here a Dune::Functions basis
+ */
+template <class Basis, class BlockVectorType0, class BlockVectorType1, class LocalFEStiffness>
+class FEAssembler<Basis,Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>, LocalFEStiffness>
+{
+
+    using GridView = typename Basis::GridView;
+
+    //! Dimension of the grid.
+    enum { gridDim = GridView::dimension };
+
+    using VectorType = Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>;
+
+    using BT0 = typename BlockVectorType0::block_type;
+    using BT1 = typename BlockVectorType1::block_type;
+
+    using DT = typename BlockVectorType0::field_type;
+    static_assert(std::is_same<DT,typename BlockVectorType1::field_type>::value);
+
+    //!
+    using MatrixType = Dune::MultiTypeBlockMatrix<
+            Dune::MultiTypeBlockVector<Dune::BCRSMatrix<Dune::FieldMatrix<DT, BT0::dimension, BT0::dimension>>, Dune::BCRSMatrix<Dune::FieldMatrix<DT, BT0::dimension, BT1::dimension>> >,
+            Dune::MultiTypeBlockVector<Dune::BCRSMatrix<Dune::FieldMatrix<DT, BT1::dimension, BT0::dimension>>, Dune::BCRSMatrix<Dune::FieldMatrix<DT, BT1::dimension, BT1::dimension>> > >;
+
+public:
+    const Basis basis_;
+
+    //! Partitions to assemble the Gradient and Hessian, is interior here, because when doing parallel calculations, the assembled matrix and gradient are treated as if they do not overlap
+    static constexpr auto paritionsOverlap = Dune::Partitions::interiorBorder;
+
+protected:
+
+    std::shared_ptr<LocalFEStiffness> localStiffness_;
+
+public:
+
+    /** \brief Constructor for a given grid */
+    FEAssembler(const Basis& basis,
+                std::shared_ptr<LocalFEStiffness> localStiffness)
+        : basis_(basis),
+          localStiffness_(localStiffness)
+    {}
+
+    /** \brief Assemble the tangent stiffness matrix and the functional gradient together
+     *
+     * This may be more efficient than computing them separately
+     */
+    virtual void assembleGradientAndHessian(const VectorType& sol,
+                                            VectorType& gradient,
+                                            MatrixType& hessian,
+                                            bool computeOccupationPattern=true) const;
+
+    /** \brief Compute the energy of a deformation state */
+    virtual double computeEnergy(const VectorType& sol) const;
+
+    //protected:
+    void getNeighborsPerVertex(std::array<std::array<Dune::MatrixIndexSet,2>,2>& nb) const;
+
+}; // end class
+
+
+
+template <class Basis, class BlockVectorType0, class BlockVectorType1, class LocalFEStiffness>
+void FEAssembler<Basis,Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>,LocalFEStiffness>::
+getNeighborsPerVertex(std::array<std::array<Dune::MatrixIndexSet,2>,2>& nb) const
+{
+    using namespace Dune::Indices;
+
+      // Set sizes of the 2x2 submatrices
+    for (size_t i=0; i<2; i++)
+        for (size_t j=0; j<2; j++)
+    {
+        nb[i][j].resize(basis_.size({i}), basis_.size({j}));
+    }
+
+    // A view on the FE basis on a single element
+    auto localView = basis_.localView();
+
+    // Loop over all leaf elements
+    for(const auto& e : elements(basis_.gridView()))
+    {
+        // Bind the local FE basis view to the current element
+        localView.bind(e);
+
+        // Add element stiffness matrix onto the global stiffness matrix
+        for (size_t i=0; i<localView.size(); i++)
+        {
+            // The global index of the i-th local degree of freedom of the element 'e'
+            auto row = localView.index(i);
+
+            for (size_t j=0; j<localView.size(); j++ )
+            {
+                // The global index of the j-th local degree of freedom of the element 'e'
+                auto col = localView.index(j);
+
+                nb[row[0]][col[0]].add(row[1],col[1]);
+            }
+        }
+    }
+}
+
+template <class Basis, class BlockVectorType0, class BlockVectorType1, class LocalFEStiffness>
+void FEAssembler<Basis,Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>,LocalFEStiffness>::
+assembleGradientAndHessian(const VectorType& sol,
+                           VectorType& gradient,
+                           MatrixType& hessian, // type too long
+                           bool computeOccupationPattern) const
+{
+    using namespace Dune::Indices;
+
+    if (computeOccupationPattern) {
+
+        std::array<std::array<Dune::MatrixIndexSet,2>,2> neighborsPerVertex;
+        getNeighborsPerVertex(neighborsPerVertex);
+        neighborsPerVertex[0][0].exportIdx(hessian[_0][_0]);
+        neighborsPerVertex[0][1].exportIdx(hessian[_0][_1]);
+        neighborsPerVertex[1][0].exportIdx(hessian[_1][_0]);
+        neighborsPerVertex[1][1].exportIdx(hessian[_1][_1]);
+
+    }
+
+    using namespace Dune::Indices;
+    using VectorType = Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>;
+
+    hessian = 0;
+
+    gradient[_0].resize(sol[_0].size());
+    gradient[_1].resize(sol[_1].size());
+    gradient = 0;
+
+    for (const auto& element : elements(basis_.gridView(), paritionsOverlap))
+    {
+        auto localView = basis_.localView();
+        localView.bind(element);
+
+        // size of all dof'S
+        auto flatSize0 = localView.tree().child(_0).size();
+        auto flatSize1 = localView.tree().child(_1).size();
+
+        // block sizes of the vector spaces
+        auto blockSize0 = BlockVectorType0::block_type::dimension;
+        auto blockSize1 = BlockVectorType1::block_type::dimension;
+
+        // entries in the two solution blocks
+        auto numOfBaseFct0 = flatSize0/blockSize0;
+        auto numOfBaseFct1 = flatSize1/blockSize1;
+
+        // Extract local solution
+        VectorType localSolution;
+        localSolution[_0].resize(numOfBaseFct0);
+        localSolution[_1].resize(numOfBaseFct1);
+
+        for (int i=0; i<numOfBaseFct0; i++)
+        {
+            // HACK
+            // get in global index of the i-th vertex of the element => this is the index of the P1 function
+            auto index = basis_.gridView().indexSet().subIndex(element,i,gridDim);
+            localSolution[_0][i] = sol[_0][index]; // vector copy!
+        }
+
+        if ( numOfBaseFct1 != 1 )
+            DUNE_THROW(Dune::Exception,"XXX");
+
+        // get in global index of the element => index of P0 elements
+        auto index = basis_.gridView().indexSet().index(element);
+        localSolution[_1][index] = sol[_1][index]; // vector copy!
+
+        VectorType localGradient;
+        localGradient[_0].resize(numOfBaseFct0);
+        localGradient[_1].resize(numOfBaseFct1);
+
+        // setup local matrix and gradient
+        const auto& lfe0 = localView.tree().child(_0,0).finiteElement();
+
+        localStiffness_->assembleGradientAndHessian(element, lfe0, localSolution, localGradient);
+
+        // Add element matrix to global stiffness matrix
+        for(int i=0; i<flatSize0; i++)
+        {
+            auto row = localView.index(i);
+
+            for (int j=0; j<flatSize0; j++ )
+            {
+                auto col = localView.index(j);
+                hessian[_0][_0][row[1]][col[1]][row[2]][col[2]] += localStiffness_->A_[i][j];
+            }
+            // continue counting
+            for (int j=flatSize0; j<flatSize0+flatSize1; j++ )
+            {
+                auto col = localView.index(j);
+                hessian[_0][_1][row[1]][col[1]][row[2]][col[2]] += localStiffness_->A_[i][j];
+            }
+        }
+        for(int i=flatSize0; i<flatSize0+flatSize1; i++)
+        {
+            auto row = localView.index(i);
+
+            for (int j=0; j<flatSize0; j++ )
+            {
+                auto col = localView.index(j);
+                hessian[_1][_0][row[1]][col[1]][row[2]][col[2]] += localStiffness_->A_[i][j];
+            }
+            for (int j=flatSize0; j<flatSize0+flatSize1; j++ )
+            {
+                auto col = localView.index(j);
+                hessian[_1][_1][row[1]][col[1]][row[2]][col[2]] += localStiffness_->A_[i][j];
+            }
+        }
+
+        // Add local gradient to global gradient
+        for (int i=0; i<numOfBaseFct0; i++)
+        {
+            // HACK
+            // get in global index of the i-th vertex of the element => this is the index of the P1 function
+            auto index = basis_.gridView().indexSet().subIndex(element,i,gridDim);
+            gradient[_0][index] += localGradient[_0][i];
+        }
+
+        if ( numOfBaseFct1 != 1 )
+            DUNE_THROW(Dune::Exception,"XXX");
+
+        // get in global index of the element => index of P0 elements
+        index = basis_.gridView().indexSet().index(element);
+        gradient[_1][index] += localGradient[_1][0];
+    }
+}
+
+
+template <class Basis, class BlockVectorType0, class BlockVectorType1, class LocalFEStiffness>
+double FEAssembler<Basis,Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>, LocalFEStiffness>::
+computeEnergy(const VectorType& sol) const
+{
+    using namespace Dune::Indices;
+    double energy = 0;
+
+    if (sol[_0].size()!=basis_.size({_0}) || sol[_1].size()!=basis_.size({_1}))
+        DUNE_THROW(Dune::Exception, "Solution vector doesn't match the basis!");
+
+    auto localView = basis_.localView();
+
+    // Loop over all elements
+    for (const auto& element : elements(basis_.gridView(), paritionsOverlap))
+    {
+        localView.bind(element);
+
+        // size of all dof'S
+        auto flatSize0 = localView.tree().child(_0).size();
+        auto flatSize1 = localView.tree().child(_1).size();
+
+        // block sizes of the vector spaces
+        auto blockSize0 = BlockVectorType0::block_type::dimension;
+        auto blockSize1 = BlockVectorType1::block_type::dimension;
+
+        // entries in the two solution blocks
+        auto numOfBaseFct0 = flatSize0/blockSize0;
+        auto numOfBaseFct1 = flatSize1/blockSize1;
+
+        std::cerr << flatSize0 << " " << flatSize1 << " " << blockSize0 << " " << blockSize1 << std::endl;
+
+        // Extract local solution
+        VectorType localSolution;
+        localSolution[_0].resize(numOfBaseFct0);
+        localSolution[_1].resize(numOfBaseFct1);
+
+        for (int i=0; i<numOfBaseFct0; i++)
+        {
+            // get in global index of the i-th vertex of the element => this is the index of the P1 function
+            auto index = basis_.gridView().indexSet().subIndex(element,i,gridDim);
+            localSolution[_0][i] = sol[_0][index]; // vector copy!
+        }
+
+        if ( numOfBaseFct1 != 1 )
+            DUNE_THROW(Dune::Exception,"XXX");
+
+        // get in global index of the element => index of P0 elements
+        auto index = basis_.gridView().indexSet().index(element);
+        localSolution[_1][index] = sol[_1][index]; // vector copy!
+
+        const auto& lfe0 = localView.tree().child(_0,0).finiteElement();
+
+        energy += localStiffness_->energy(element, lfe0, localSolution);
+
+    }
+
+    return energy;
+
+}
 #endif
diff --git a/dune/elasticity/assemblers/localadolcstiffness.hh b/dune/elasticity/assemblers/localadolcstiffness.hh
index 8afcfade68ff54ab8a8f659bd3c31c3accedb5c0..69c7f39261296438bea6f422ba4d3a5e23b278a8 100644
--- a/dune/elasticity/assemblers/localadolcstiffness.hh
+++ b/dune/elasticity/assemblers/localadolcstiffness.hh
@@ -10,10 +10,15 @@
 #include <dune/fufem/utilities/adolcnamespaceinjections.hh>
 
 #include <dune/common/fmatrix.hh>
+#include <dune/common/indices.hh>
+
 #include <dune/istl/matrix.hh>
+#include <dune/istl/multitypeblockvector.hh>
+#include <dune/istl/bvector.hh>
 
 #include <dune/elasticity/assemblers/localfestiffness.hh>
 
+
 //#define ADOLC_VECTOR_MODE
 
 /** \brief Assembles energy gradient and Hessian with ADOL-C (automatic differentiation)
@@ -195,4 +200,269 @@ assembleGradientAndHessian(const Entity& element,
 #endif
 }
 
+
+
+
+
+
+/** \brief Extension of LocalADOLCStiffness for MultiTypeVector formats
+ */
+template<class GV, class LFE, class BlockVectorType0, class BlockVectorType1>
+class LocalADOLCStiffness<GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>>
+    : public LocalFEStiffness<GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>>
+{
+    using GridView = GV;
+    using LocalFiniteElement = LFE;
+
+    // grid types
+    typedef typename GridView::Grid::ctype DT;
+    typedef typename GridView::template Codim<0>::Entity Entity;
+
+    // some other sizes
+    enum {gridDim=GridView::dimension};
+
+    using VectorType = Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>;
+
+    using BT0 = typename BlockVectorType0::block_type;
+    using BT1 = typename BlockVectorType1::block_type;
+
+    // HACK -> we convert the BlockTypes to same-looking types with value "abouble"
+    using AVectorType = Dune::MultiTypeBlockVector<Dune::BlockVector<Dune::FieldVector<adouble,BT0::dimension>>,
+                                                   Dune::BlockVector<Dune::FieldVector<adouble,BT1::dimension>>>;
+
+public:
+
+    LocalADOLCStiffness(const Dune::Elasticity::LocalEnergy<GridView, LocalFiniteElement, AVectorType>* energy)
+    : localEnergy_(energy)
+    {}
+
+    /** \brief Compute the energy at the current configuration */
+    virtual double energy (const Entity& e,
+               const LocalFiniteElement& localFiniteElement,
+               const VectorType& localConfiguration) const;
+
+    /** \brief Assemble the local stiffness matrix at the current position
+
+    This uses the automatic differentiation toolbox ADOL_C.
+    */
+    virtual void assembleGradientAndHessian(const Entity& e,
+                         const LocalFiniteElement& localFiniteElement,
+                         const VectorType& localConfiguration,
+                         VectorType& localGradient);
+
+    const Dune::Elasticity::LocalEnergy<GridView, LocalFiniteElement, AVectorType>* localEnergy_;
+
+};
+
+
+template<class GV, class LFE, class BlockVectorType0, class BlockVectorType1>
+double LocalADOLCStiffness<GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>>::
+energy(const Entity& element,
+       const LocalFiniteElement& localFiniteElement,
+       const VectorType& localSolution) const
+{
+    using namespace Dune::Indices;
+
+    int rank = Dune::MPIHelper::getCollectiveCommunication().rank();
+    double pureEnergy;
+
+    using BT0 = typename BlockVectorType0::block_type;
+    using BT1 = typename BlockVectorType1::block_type;
+
+    // HACK -> we convert the BlockTypes to same-looking types with value "abouble"
+    using AVectorType = Dune::MultiTypeBlockVector<Dune::BlockVector<Dune::FieldVector<adouble,BT0::dimension>>,
+                                                   Dune::BlockVector<Dune::FieldVector<adouble,BT1::dimension>>>;
+
+    AVectorType localASolution;
+    localASolution[_0].resize(localSolution[_0].size());
+    localASolution[_1].resize(localSolution[_1].size());
+
+
+    trace_on(rank);
+
+    adouble energy = 0;
+
+    for (size_t i=0; i<localSolution[_0].size(); i++)
+      for (size_t j=0; j<localSolution[_0][i].size(); j++)
+        localASolution[_0][i][j] <<= localSolution[_0][i][j];
+
+    for (size_t i=0; i<localSolution[_1].size(); i++)
+      for (size_t j=0; j<localSolution[_1][i].size(); j++)
+        localASolution[_1][i][j] <<= localSolution[_1][i][j];
+
+    energy = localEnergy_->energy(element,localFiniteElement,localASolution);
+
+    energy >>= pureEnergy;
+
+    trace_off(rank);
+
+    return pureEnergy;
+}
+
+
+
+// ///////////////////////////////////////////////////////////
+//   Compute gradient and Hessian together
+//   To compute the Hessian we need to compute the gradient anyway, so we may
+//   as well return it.  This saves assembly time.
+// ///////////////////////////////////////////////////////////
+template<class GV, class LFE, class BlockVectorType0, class BlockVectorType1>
+void LocalADOLCStiffness<GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>>::
+assembleGradientAndHessian(const Entity& element,
+                const LocalFiniteElement& localFiniteElement,
+                const VectorType& localSolution,
+                VectorType& localGradient)
+{
+    using namespace Dune::Indices;
+
+    int rank = Dune::MPIHelper::getCollectiveCommunication().rank();
+    // Tape energy computation.  We may not have to do this every time, but it's comparatively cheap.
+    energy(element, localFiniteElement, localSolution);
+
+    /////////////////////////////////////////////////////////////////
+    // Compute the energy gradient
+    /////////////////////////////////////////////////////////////////
+
+    using BT0 = typename BlockVectorType0::block_type;
+    using BT1 = typename BlockVectorType1::block_type;
+
+    // Compute the actual gradient
+    size_t nDofs0 = localSolution[_0].size();
+    size_t nDofs1 = localSolution[_1].size();
+    size_t blocksize0 = BT0::dimension;
+    size_t blocksize1 = BT1::dimension;
+
+    size_t nDoubles = nDofs0 * blocksize0 + nDofs1 * blocksize1;
+
+    std::vector<double> xp(nDoubles);
+    int idx=0;
+    for (size_t i=0; i<nDofs0; i++)
+        for (size_t j=0; j<blocksize0; j++)
+            xp[idx++] = localSolution[_0][i][j];
+
+    for (size_t i=0; i<nDofs1; i++)
+        for (size_t j=0; j<blocksize1; j++)
+            xp[idx++] = localSolution[_1][i][j];
+
+  // Compute gradient
+    std::vector<double> g(nDoubles);
+    gradient(rank,nDoubles,xp.data(),g.data());                  // gradient evaluation
+
+    // Copy into Dune type
+    localGradient[_0].resize(localSolution[_0].size());
+    localGradient[_1].resize(localSolution[_1].size());
+
+    idx=0;
+    for (size_t i=0; i<nDofs0; i++)
+        for (size_t j=0; j<blocksize0; j++)
+            localGradient[_0][i][j] = g[idx++];
+
+    for (size_t i=0; i<nDofs1; i++)
+        for (size_t j=0; j<blocksize1; j++)
+            localGradient[_1][i][j] = g[idx++];
+
+    /////////////////////////////////////////////////////////////////
+    // Compute Hessian
+    /////////////////////////////////////////////////////////////////
+
+    // we use a flat matrix format for the local hessian
+    this->A_.setSize(nDoubles,nDoubles);
+
+#ifndef ADOLC_VECTOR_MODE
+    std::vector<double> v(nDoubles);
+    std::vector<double> w(nDoubles);
+
+    std::fill(v.begin(), v.end(), 0.0);
+
+    for ( size_t i=0; i<nDoubles; i++ )
+    {
+        // set the i-th unit vector
+        v[i] = 1.;
+
+        int rc= 3;
+        MINDEC(rc, hess_vec(rank, nDoubles, xp.data(), v.data(), w.data()));
+        if (rc < 0)
+          DUNE_THROW(Dune::Exception, "ADOL-C has returned with error code " << rc << "!");
+
+        for (size_t j=0; j<nDoubles; j++)
+          this->A_[i][j] = w[j];
+
+        // reset the i-th unit vector
+        v[i] = 0.;
+    }
+
+
+//     for (size_t i=0; i<nDofs0; i++)
+//       for (size_t ii=0; ii<blocksize0; ii++)
+//       {
+//         // Evaluate Hessian in the direction of each vector of the orthonormal frame
+//         for (size_t k=0; k<blocksize0; k++)
+//           v[i*blocksize0 + k] = (k==ii);
+//
+//         int rc= 3;
+//         MINDEC(rc, hess_vec(rank, nDoubles, xp.data(), v.data(), w.data()));
+//         if (rc < 0)
+//           DUNE_THROW(Dune::Exception, "ADOL-C has returned with error code " << rc << "!");
+//
+//         for (size_t j=0; j<nDoubles; j++)
+//           this->A_[i*blocksize0 + ii][j] = w[j];
+//
+//         // Make v the null vector again
+//         std::fill(&v[i*blocksize0], &v[(i+1)*blocksize0], 0.0);
+//       }
+//     for (size_t i=0; i<nDofs1; i++)
+//       for (size_t ii=0; ii<blocksize1; ii++)
+//       {
+//         // Evaluate Hessian in the direction of each vector of the orthonormal frame
+//         for (size_t k=0; k<blocksize1; k++)
+//           v[i*blocksize1 + k] = (k==ii);
+//
+//         int rc= 3;
+//         MINDEC(rc, hess_vec(rank, nDoubles, xp.data(), v.data(), w.data()));
+//         if (rc < 0)
+//           DUNE_THROW(Dune::Exception, "ADOL-C has returned with error code " << rc << "!");
+//
+//         for (size_t j=0; j<nDofs0*blocksize0; j++)
+//           this->A_[_1][_0][i][j/blocksize0][ii][j%blocksize0] = w[j];
+//         for (size_t j=0; j<nDofs1*blocksize1; j++)
+//           this->A_[_1][_1][i][j/blocksize1][ii][j%blocksize1] = w[j + nDofs0*blocksize0];
+//
+//         // Make v the null vector again
+//         std::fill(&v[i*blocksize1], &v[(i+1)*blocksize1], 0.0);
+//       }
+#else
+    DUNE_THROW(Dune::NotImplemented,"this code should never be touched");
+//     int n = nDoubles;
+//     int nDirections = nDofs * blocksize;
+//     double* tangent[nDoubles];
+//     for(size_t i=0; i<nDoubles; i++)
+//         tangent[i] = (double*)malloc(nDirections*sizeof(double));
+//
+//     double* rawHessian[nDoubles];
+//     for(size_t i=0; i<nDoubles; i++)
+//         rawHessian[i] = (double*)malloc(nDirections*sizeof(double));
+//
+//     for (int j=0; j<nDirections; j++)
+//     {
+//       for (int i=0; i<n; i++)
+//         tangent[i][j] = 0.0;
+//
+//       for (int i=0; i<embeddedBlocksize; i++)
+//         tangent[(j/blocksize)*embeddedBlocksize+i][j] = orthonormalFrame[j/blocksize][j%blocksize][i];
+//     }
+//
+//     hess_mat(rank,nDoubles,nDirections,xp.data(),tangent,rawHessian);
+//
+//     // Copy Hessian into Dune data type
+//     for(size_t i=0; i<nDoubles; i++)
+//       for (size_t j=0; j<nDirections; j++)
+//         this->A_[j/blocksize][i/embeddedBlocksize][j%blocksize][i%embeddedBlocksize] = rawHessian[i][j];
+//
+//     for(size_t i=0; i<nDoubles; i++) {
+//         free(rawHessian[i]);
+//         free(tangent[i]);
+//     }
+#endif
+}
+
 #endif
diff --git a/dune/elasticity/assemblers/localenergy.hh b/dune/elasticity/assemblers/localenergy.hh
index 475ed7f340e276b67e4b0d2c50f3709a7badd54e..a5df849e110c14d6a1796024e5f4f5b2c3ab8704 100644
--- a/dune/elasticity/assemblers/localenergy.hh
+++ b/dune/elasticity/assemblers/localenergy.hh
@@ -11,11 +11,12 @@ namespace Elasticity {
 template<class GridView, class LocalFiniteElement, class VectorType>
 class LocalEnergy
 {
-    typedef typename VectorType::value_type::field_type RT;
     typedef typename GridView::template Codim<0>::Entity Element;
 
 public:
 
+  using RT = typename VectorType::value_type::field_type;
+
   /** \brief Compute the energy
    *
    * \param element A grid element
@@ -29,6 +30,33 @@ public:
 
 };
 
+
+/** \brief Extension of LocalEnergy for MultiTypeBlockVectors */
+template<class GV, class LFE, class BlockVectorType0, class BlockVectorType1>
+class LocalEnergy<GV, LFE, MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>>
+{
+    using Element = typename GV::template Codim<0>::Entity;
+    using VectorType = MultiTypeBlockVector<BlockVectorType0, BlockVectorType1>;
+
+    using RT = typename BlockVectorType0::value_type::field_type;
+    // check for same type
+    static_assert(std::is_same<RT,typename BlockVectorType1::value_type::field_type>::value);
+
+public:
+
+  /** \brief Compute the energy
+   *   *
+   * \param element A grid element
+   * \param LocalFiniteElement A finite element on the reference element
+   * \param localConfiguration The coefficients of a FE function on the current element
+   */
+  /** \brief Compute the energy at the current configuration */
+  virtual RT energy (const Element& element,
+                     const LFE& localFiniteElement,
+                     const VectorType& localConfiguration) const = 0;
+
+};
+
 }  // namespace Elasticity
 
 }  // namespace Dune
diff --git a/dune/elasticity/assemblers/localfestiffness.hh b/dune/elasticity/assemblers/localfestiffness.hh
index f2d13cb54d0c3f5da2fdcfe30c70efa5bfa2ca17..82e568cb7f184727336913069a43f059f28691cd 100644
--- a/dune/elasticity/assemblers/localfestiffness.hh
+++ b/dune/elasticity/assemblers/localfestiffness.hh
@@ -3,6 +3,7 @@
 
 #include <dune/common/fmatrix.hh>
 #include <dune/istl/matrix.hh>
+#include <dune/istl/bvector.hh>
 
 #include <dune/elasticity/assemblers/localenergy.hh>
 
@@ -35,5 +36,46 @@ public:
 
 };
 
+
+
+/** \brief Extension of LocalFEStiffness with MultiTypeBlockVector arguments
+ *  It assembles into a Dune::MultiTypeBlockMatrix
+ *  Currently, only available for exactly two blocks
+ * */
+template<class GV, class LFE, class BlockVectorType0, class BlockVectorType1>
+class LocalFEStiffness< GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0, BlockVectorType1> >
+: public Dune::Elasticity::LocalEnergy< GV, LFE, Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1> >
+{
+    // grid types
+    using Entity = typename GV::template Codim<0>::Entity;
+
+    using BT0 = typename BlockVectorType0::block_type;
+    using BT1 = typename BlockVectorType1::block_type;
+
+    using RT = typename BlockVectorType0::field_type;
+    static_assert(std::is_same<RT,typename BlockVectorType1::field_type>::value);
+
+    using VectorType = Dune::MultiTypeBlockVector<BlockVectorType0,BlockVectorType1>;
+
+    // we use a flat matrix type for best compatibility with Dune::Functions
+    using MatrixType = Dune::Matrix<Dune::FieldMatrix<RT,1,1> >;
+
+    // some other sizes
+    enum {gridDim=GV::dimension};
+
+public:
+
+    /** \brief Assemble the local gradient and tangent matrix at the current position
+    */
+    virtual void assembleGradientAndHessian(const Entity& e,
+                                 const LFE& localFiniteElement,
+                                 const VectorType& localConfiguration,
+                                 VectorType& localGradient) = 0;
+
+    // assembled data
+    MatrixType A_;
+
+};
+
 #endif
 
diff --git a/dune/elasticity/materials/integralenergy.hh b/dune/elasticity/materials/integralenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..35e2e4c9db9dbbdbfd7ce314aedaa4b4deb0feaf
--- /dev/null
+++ b/dune/elasticity/materials/integralenergy.hh
@@ -0,0 +1,98 @@
+#ifndef DUNE_ELASTICITY_MATERIALS_INTEGRALENERGY_HH
+#define DUNE_ELASTICITY_MATERIALS_INTEGRALENERGY_HH
+
+#include <dune/common/fmatrix.hh>
+#include <dune/common/parametertree.hh>
+
+#include <dune/geometry/quadraturerules.hh>
+
+#include <dune/elasticity/assemblers/localfestiffness.hh>
+#include <dune/elasticity/assemblers/localenergy.hh>
+
+namespace Dune::Elasticity {
+
+template<class Basis, class EnergyDensity, class field_type=double>
+class IntegralEnergy
+  : public Elasticity::LocalEnergy<typename Basis::GridView,
+                                   typename Basis::LocalView::Tree::FiniteElement,
+                                   std::vector<Dune::FieldVector<field_type,Basis::GridView::dimension> > >
+{
+  // grid types
+  using GridView = typename Basis::GridView;
+  using DT = typename GridView::ctype;
+  using Element = typename GridView::template Codim<0>::Entity;
+  using LocalFiniteElement = typename Basis::LocalView::Tree::FiniteElement;
+
+  // some other sizes
+  constexpr static auto gridDim = GridView::dimension;
+
+public:
+
+  /** \brief Constructor with a set of material parameters
+   * \param parameters The material parameters
+   */
+  IntegralEnergy(const EnergyDensity& energyDensity)
+  : energyDensity_(energyDensity)
+  {}
+
+  /** \brief Assemble the energy for a single element */
+  field_type energy (const Element& e,
+                     const LocalFiniteElement& localFiniteElement,
+                     const std::vector<Dune::FieldVector<field_type, gridDim> >& localConfiguration) const;
+
+  const EnergyDensity energyDensity_;
+};
+
+template <class Basis, class EnergyDensity, class field_type>
+field_type
+IntegralEnergy<Basis, EnergyDensity, field_type>::
+energy(const Element& element,
+       const LocalFiniteElement& localFiniteElement,
+       const std::vector<Dune::FieldVector<field_type, gridDim> >& localConfiguration) const
+{
+  assert(element.type() == localFiniteElement.type());
+
+  field_type energy = 0;
+
+  // store gradients of shape functions and base functions
+  std::vector<FieldMatrix<DT,1,gridDim> > referenceGradients(localFiniteElement.size());
+  std::vector<FieldVector<DT,gridDim> > gradients(localFiniteElement.size());
+
+  int quadOrder = (element.type().isSimplex()) ? localFiniteElement.localBasis().order()
+                                               : localFiniteElement.localBasis().order() * gridDim;
+
+  const auto& quad = Dune::QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
+
+  for (const auto& qp : quad)
+  {
+    const DT integrationElement = element.geometry().integrationElement(qp.position());
+
+    const auto jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(qp.position());
+
+    // Global position
+    auto x = element.geometry().global(qp.position());
+
+    // Get gradients of shape functions
+    localFiniteElement.localBasis().evaluateJacobian(qp.position(), referenceGradients);
+
+    // compute gradients of base functions
+    for (size_t i=0; i<gradients.size(); ++i)
+      jacobianInverseTransposed.mv(referenceGradients[i][0], gradients[i]);
+
+    // Deformation gradient
+    FieldMatrix<field_type,gridDim,gridDim> deformationGradient(0);
+    for (size_t i=0; i<gradients.size(); i++)
+      for (int j=0; j<gridDim; j++)
+        deformationGradient[j].axpy(localConfiguration[i][j], gradients[i]);
+
+    // Integrate the energy density
+    energy += qp.weight() * integrationElement * energyDensity_(x, deformationGradient);
+  }
+
+  return energy;
+}
+
+}  // namespace Dune::Elasticity
+
+#endif   //#ifndef DUNE_ELASTICITY_MATERIALS_INTEGRALENERGY_HH
+
diff --git a/dune/elasticity/materials/mooneyrivlinenergy.hh b/dune/elasticity/materials/mooneyrivlinenergy.hh
index bb40a824f207559d0ba81c5209ff2bc99939b99d..2cce10a9f550e956d7a285fb01dc5de908798e37 100644
--- a/dune/elasticity/materials/mooneyrivlinenergy.hh
+++ b/dune/elasticity/materials/mooneyrivlinenergy.hh
@@ -71,8 +71,80 @@ public:
               mooneyrivlin_03,
               mooneyrivlin_k;
   std::string mooneyrivlin_energy;
+
+  field_type energyDensity(const Dune::FieldVector<field_type,gridDim>& x, const Dune::FieldMatrix<field_type, gridDim, gridDim>& derivative)
+  {
+    field_type strainEnergyCiarlet = 0;
+    field_type strainEnergy = 0;
+    field_type strainEnergyWithLog = 0;
+    field_type strainEnergyWithSquare = 0;
+
+    Dune::FieldMatrix<field_type,gridDim,gridDim> C(0);
+
+    for (int i=0; i<gridDim; i++) {
+      for (int j=0; j<gridDim; j++) {
+        for (int k=0; k<gridDim; k++)
+          C[i][j] += derivative[k][i] * derivative[k][j];
+      }
+    }
+
+    //////////////////////////////////////////////////////////
+    //  Eigenvalues of FTF
+    //////////////////////////////////////////////////////////
+
+    // eigenvalues of C, i.e., squared singular values \sigma_i of F
+    Dune::FieldVector<field_type, dim> sigmaSquared;
+    FMatrixHelp::eigenValues(C, sigmaSquared);
+
+    field_type normFSquared = derivative.frobenius_norm2();
+    field_type detF = derivative.determinant();
+
+    field_type normFinvSquared = 0;
+
+    field_type c2Tilde = 0;
+    for (int i = 0; i < dim; i++) {
+      normFinvSquared += 1/sigmaSquared[i];
+      // compute D, which is the sum of the squared eigenvalues
+      for (int j = i+1; j < dim; j++)
+        c2Tilde += sigmaSquared[j]*sigmaSquared[i];
+    }
+
+    field_type trCTildeMinus3 = normFSquared/pow(detF, 2.0/dim) - 3;
+    // \tilde{D} = \frac{1}{\det{F}^{4/3}}D -> divide by det(F)^(4/3)= det(C)^(2/3)
+    c2Tilde /= pow(detF, 4.0/dim);
+    field_type c2TildeMinus3 = c2Tilde - 3;
+    field_type detFMinus1 = detF - 1;
+
+    // Add the local energy density
+    strainEnergyCiarlet += (mooneyrivlin_a*normFSquared + mooneyrivlin_b*normFinvSquared*detF + mooneyrivlin_c*detF*detF - ((dim-1)*mooneyrivlin_a + mooneyrivlin_b + 2*mooneyrivlin_c)*log(detF));
+    strainEnergy = 0;
+    strainEnergy = mooneyrivlin_10 * trCTildeMinus3 +
+                  mooneyrivlin_01 * c2TildeMinus3 +
+                  mooneyrivlin_20 * trCTildeMinus3 * trCTildeMinus3 +
+                  mooneyrivlin_02 * c2TildeMinus3 * c2TildeMinus3 +
+                  mooneyrivlin_11 * trCTildeMinus3 * c2TildeMinus3 +
+                  mooneyrivlin_30 * trCTildeMinus3 * trCTildeMinus3 * trCTildeMinus3 +
+                  mooneyrivlin_21 * trCTildeMinus3 * trCTildeMinus3 * c2TildeMinus3 +
+                  mooneyrivlin_12 * trCTildeMinus3 * c2TildeMinus3 * c2TildeMinus3 +
+                  mooneyrivlin_03 * c2TildeMinus3 * c2TildeMinus3 * c2TildeMinus3;
+    field_type logDetF = log(detF);
+    strainEnergyWithLog += ( strainEnergy + 0.5 * mooneyrivlin_k* logDetF * logDetF );
+    strainEnergyWithSquare += ( strainEnergy + mooneyrivlin_k* detFMinus1 * detFMinus1);
+
+    std::cout << std::scientific;
+    if (mooneyrivlin_energy == "log") {
+        return strainEnergyWithLog;
+    } else if (mooneyrivlin_energy == "square") {
+        return strainEnergyWithSquare;
+    }
+    std::cout << std::fixed;
+
+    return strainEnergyCiarlet;
+  };
+
 };
 
+
 template <class GridView, class LocalFiniteElement, class field_type>
 field_type
 MooneyRivlinEnergy<GridView, LocalFiniteElement, field_type>::
@@ -80,6 +152,9 @@ energy(const Entity& element,
        const LocalFiniteElement& localFiniteElement,
        const std::vector<Dune::FieldVector<field_type, gridDim> >& localConfiguration) const
 {
+    return 0;
+}
+#if 0
 
   assert(element.type() == localFiniteElement.type());
   typedef typename GridView::template Codim<0>::Entity::Geometry Geometry;
@@ -160,7 +235,7 @@ energy(const Entity& element,
     field_type detFMinus1 = detF - 1;
 
     // Add the local energy density
-    strainEnergyCiarlet += weight * (mooneyrivlin_a*normFSquared + mooneyrivlin_b*normFinvSquared*detF + mooneyrivlin_c*detF*detF - ((dim-1)*mooneyrivlin_a + mooneyrivlin_b + 2*mooneyrivlin_c)*std::log(detF));
+    strainEnergyCiarlet += weight * (mooneyrivlin_a*normFSquared + mooneyrivlin_b*normFinvSquared*detF + mooneyrivlin_c*detF*detF - ((dim-1)*mooneyrivlin_a + mooneyrivlin_b + 2*mooneyrivlin_c)*log(detF));
     strainEnergy = 0;
     strainEnergy = mooneyrivlin_10 * trCTildeMinus3 +
                   mooneyrivlin_01 * c2TildeMinus3 +
@@ -171,7 +246,7 @@ energy(const Entity& element,
                   mooneyrivlin_21 * trCTildeMinus3 * trCTildeMinus3 * c2TildeMinus3 +
                   mooneyrivlin_12 * trCTildeMinus3 * c2TildeMinus3 * c2TildeMinus3 +
                   mooneyrivlin_03 * c2TildeMinus3 * c2TildeMinus3 * c2TildeMinus3;
-    field_type logDetF = std::log(detF);
+    field_type logDetF = log(detF);
     strainEnergyWithLog += weight * ( strainEnergy + 0.5 * mooneyrivlin_k* logDetF * logDetF );
     strainEnergyWithSquare += weight * ( strainEnergy + mooneyrivlin_k* detFMinus1 * detFMinus1);
   }
@@ -187,6 +262,27 @@ energy(const Entity& element,
   return strainEnergyCiarlet;
 }
 
+
+
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 }  // namespace Dune
 
 #endif   //#ifndef DUNE_ELASTICITY_MATERIALS_MOONEYRIVLINENERGY_HH
diff --git a/src/finite-strain-elasticity.cc b/src/finite-strain-elasticity.cc
index 657179223c07b3fdf2f6f29ffdb6cd4edec1530d..ca7377f22416ebccf161984b1b40679d55cef6bc 100644
--- a/src/finite-strain-elasticity.cc
+++ b/src/finite-strain-elasticity.cc
@@ -41,6 +41,7 @@
 #include <dune/elasticity/materials/neohookeenergy.hh>
 #include <dune/elasticity/materials/neumannenergy.hh>
 #include <dune/elasticity/materials/sumenergy.hh>
+#include <dune/elasticity/materials/integralenergy.hh>
 
 // grid dimension
 const int dim = 3;