diff --git a/dune/gfe/geodesicfeassemblerwrapper.hh b/dune/gfe/geodesicfeassemblerwrapper.hh
new file mode 100644
index 0000000000000000000000000000000000000000..8dee1f1ffc276fadf8180a460c13b10eff6f3cc0
--- /dev/null
+++ b/dune/gfe/geodesicfeassemblerwrapper.hh
@@ -0,0 +1,189 @@
+#ifndef GLOBAL_GEODESIC_FE_ASSEMBLERWRAPPER_HH
+#define GLOBAL_GEODESIC_FE_ASSEMBLERWRAPPER_HH
+
+#include <dune/gfe/mixedgfeassembler.hh>
+#include <dune/common/tuplevector.hh>
+
+namespace Dune::GFE {
+
+/** \brief A wrapper that wraps a MixedGFEAssembler into an assembler that does not distinguish between the two finite element spaces
+
+    It reimplements the same methods as these two and transfers the structure of the gradient and the Hessian
+ */
+
+template <class Basis, class ScalarBasis, class TargetSpace, class MixedSpace0, class MixedSpace1>
+class 
+GeodesicFEAssemblerWrapper {
+
+    typedef typename Basis::GridView GridView;
+
+    //! Dimension of the grid.
+    enum { gridDim = GridView::dimension };
+
+    //! Dimension of the tangent space
+    enum { blocksize = TargetSpace::TangentVector::dimension };
+    enum { blocksize0 = MixedSpace0::TangentVector::dimension };
+    enum { blocksize1 = MixedSpace1::TangentVector::dimension };
+
+    //!
+    typedef Dune::FieldMatrix<double, blocksize, blocksize> MatrixBlock;
+    typedef typename MixedGFEAssembler<Basis, MixedSpace0, MixedSpace1>::MatrixType MatrixType;
+
+protected:
+    MixedGFEAssembler<Basis, MixedSpace0, MixedSpace1>* mixedAssembler_;
+
+public:
+    const ScalarBasis& basis_;
+
+    /** \brief Constructor for a given grid */
+    GeodesicFEAssemblerWrapper(MixedGFEAssembler<Basis, MixedSpace0, MixedSpace1>* mixedAssembler, ScalarBasis& basis)
+        : mixedAssembler_(mixedAssembler),
+          basis_(basis)
+    {
+        hessianMixed_ = std::make_unique<MatrixType>();
+        // The two spaces from the mixed version need to have the same embeddedDim as the Target Space
+        assert(MixedSpace0::embeddedDim + MixedSpace1::embeddedDim == TargetSpace::embeddedDim);
+        assert(blocksize0 + blocksize1 == blocksize);
+    }
+
+    /** \brief Assemble the tangent stiffness matrix and the functional gradient together
+     *
+     * 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<TargetSpace>& sol,
+                                            Dune::BlockVector<Dune::FieldVector<double, blocksize> >& gradient,
+                                            Dune::BCRSMatrix<MatrixBlock>& hessian,
+                                            bool computeOccupationPattern=true) const;
+
+    /** \brief Compute the energy of a deformation state */
+    virtual double computeEnergy(const std::vector<TargetSpace>& sol) const;
+
+    /** \brief Get the occupation structure of the Hessian */
+    virtual void getNeighborsPerVertex(Dune::MatrixIndexSet& nb) const;
+
+private:
+    Dune::TupleVector<std::vector<MixedSpace0>,std::vector<MixedSpace1>> splitVector(const std::vector<TargetSpace>& sol) const;
+    std::unique_ptr<MatrixType> hessianMixed_;
+}; // end class
+} //end namespace
+
+
+template <class Basis, class ScalarBasis, class TargetSpace, class MixedSpace0, class MixedSpace1>
+Dune::TupleVector<std::vector<MixedSpace0>,std::vector<MixedSpace1>> Dune::GFE::GeodesicFEAssemblerWrapper<Basis, ScalarBasis, TargetSpace,MixedSpace0,MixedSpace1>::
+splitVector(const std::vector<TargetSpace>& sol) const {
+    using namespace Indices;
+    // Split the solution into the Deformation and the Rotational part
+    auto n = basis_.size();
+    assert (sol.size() == n);
+    Dune::TupleVector<std::vector<MixedSpace0>,std::vector<MixedSpace1>> solutionSplit;
+    solutionSplit[_0].resize(n);
+    solutionSplit[_1].resize(n);
+    for (int i = 0; i < n; i++) {
+        solutionSplit[_0][i] = sol[i].r; // Deformation part
+        solutionSplit[_1][i] = sol[i].q; // Rotational part
+    }
+    return solutionSplit;
+}
+
+template <class Basis, class ScalarBasis, class TargetSpace, class MixedSpace0, class MixedSpace1>
+void Dune::GFE::GeodesicFEAssemblerWrapper<Basis, ScalarBasis, TargetSpace,MixedSpace0,MixedSpace1>::
+getNeighborsPerVertex(Dune::MatrixIndexSet& nb) const
+{
+    auto n = basis_.size();
+    nb.resize(n, n);
+    //Retrieve occupation structure for the mixed space and convert it to the non-mixed space
+    //In the mixed space, each index set is for one part of the composite basis
+    //So: nb00 is for the displacement part, nb11 is for the rotation part and nb01 and nb10 (where nb01^T = nb10) is for the coupling
+    Dune::MatrixIndexSet nb00, nb01, nb10, nb11;
+    mixedAssembler_->getMatrixPattern(nb00, nb01, nb10, nb11);
+    auto size0 = nb00.rows();
+    auto size1 = nb11.rows();
+    assert(size0 == size1);
+    assert(size0 == n);
+    //After checking if the sizes match, we can just copy over the occupation pattern
+    //as all occupation patterns work on the same basis combination, so they are all equal
+    nb = nb00;
+}
+
+template <class Basis, class ScalarBasis, class TargetSpace, class MixedSpace0, class MixedSpace1>
+void Dune::GFE::GeodesicFEAssemblerWrapper<Basis, ScalarBasis, TargetSpace,MixedSpace0,MixedSpace1>::
+assembleGradientAndHessian(const std::vector<TargetSpace>& sol,
+                           Dune::BlockVector<Dune::FieldVector<double, blocksize> >& gradient,
+                           Dune::BCRSMatrix<MatrixBlock>& hessian,
+                           bool computeOccupationPattern) const
+{
+    using namespace Dune::TypeTree::Indices;
+    auto n = basis_.size();
+
+    // Get a split up version of the input
+    auto solutionSplit = splitVector(sol);
+
+    // Define the Matrix and the Gradient in Block Stucture
+    Dune::BlockVector<Dune::FieldVector<double, blocksize0> > gradient0(n);
+    Dune::BlockVector<Dune::FieldVector<double, blocksize1> > gradient1(n);
+    
+    if (computeOccupationPattern) {
+        Dune::MatrixIndexSet neighborsPerVertex;
+        getNeighborsPerVertex(neighborsPerVertex);
+        neighborsPerVertex.exportIdx((*hessianMixed_)[_0][_0]);
+        neighborsPerVertex.exportIdx((*hessianMixed_)[_0][_1]);
+        neighborsPerVertex.exportIdx((*hessianMixed_)[_1][_0]);
+        neighborsPerVertex.exportIdx((*hessianMixed_)[_1][_1]);
+        neighborsPerVertex.exportIdx(hessian);
+    }
+
+    *hessianMixed_ = 0;
+    mixedAssembler_->assembleGradientAndHessian(solutionSplit[_0], solutionSplit[_1], gradient0, gradient1, *hessianMixed_, false);
+
+    // Transform gradient and hessian back to the non-mixed structure
+    hessian = 0;
+    gradient.resize(n);
+    gradient = 0;
+    for (int i = 0; i < n; i++) {
+        for (int j = 0; j < blocksize0 + blocksize1; j++)
+            gradient[i][j] = j < blocksize0 ? gradient0[i][j] : gradient1[i][j - blocksize0];
+    }
+
+    // All 4 matrices are nxn;
+    // Each FieldMatrix in (*hessianMixed_)[_0][_0] is blocksize0 x blocksize0
+    // Each FieldMatrix in (*hessianMixed_)[_1][_0] is blocksize1 x blocksize0
+    // Each FieldMatrix in (*hessianMixed_)[_0][_1] is blocksize0 x blocksize1
+    // Each FieldMatrix in (*hessianMixed_)[_1][_1] is blocksize1 x blocksize1
+    // The hessian will then be a nxn matrix where each FieldMatrix is (blocksize0+blocksize1)x(blocksize0+blocksize1)
+    
+    for (size_t l = 0; l < blocksize0; l++) {
+        // Extract Upper Left Block of mixed matrix
+        for (auto rowIt = (*hessianMixed_)[_0][_0].begin(); rowIt != (*hessianMixed_)[_0][_0].end(); ++rowIt)
+            for (auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
+                for(size_t k = 0; k < blocksize0; k++)
+                    hessian[rowIt.index()][colIt.index()][k][l] = (*colIt)[k][l];
+        // Extract Lower Left Block of mixed matrix
+        for (auto rowIt = (*hessianMixed_)[_1][_0].begin(); rowIt != (*hessianMixed_)[_1][_0].end(); ++rowIt)
+            for (auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
+                for(size_t k = 0; k < blocksize1; k++)
+                    hessian[rowIt.index()][colIt.index()][k + blocksize0][l] = (*colIt)[k][l];
+    }
+    for (size_t l = 0; l < blocksize1; l++) {
+        // Extract Upper Right Block of mixed matrix
+        for (auto rowIt = (*hessianMixed_)[_0][_1].begin(); rowIt != (*hessianMixed_)[_0][_1].end(); ++rowIt)
+            for (auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
+                for(size_t k = 0; k < blocksize0; k++)
+                        hessian[rowIt.index()][colIt.index()][k][l + blocksize0] = (*colIt)[k][l];
+        // Extract Lower Right Block of mixed matrix
+        for (auto rowIt = (*hessianMixed_)[_1][_1].begin(); rowIt != (*hessianMixed_)[_1][_1].end(); ++rowIt)
+            for (auto colIt = rowIt->begin(); colIt != rowIt->end(); ++colIt)
+                for(size_t k = 0; k < blocksize1; k++)
+                    hessian[rowIt.index()][colIt.index()][k + blocksize0][l + blocksize0] = (*colIt)[k][l];
+    }
+}
+
+template <class Basis, class ScalarBasis, class TargetSpace, class MixedSpace0, class MixedSpace1>
+double Dune::GFE::GeodesicFEAssemblerWrapper<Basis, ScalarBasis, TargetSpace,MixedSpace0,MixedSpace1>::
+computeEnergy(const std::vector<TargetSpace>& sol) const
+{
+    using namespace Dune::TypeTree::Indices;
+    auto solutionSplit = splitVector(sol);
+    return mixedAssembler_->computeEnergy(solutionSplit[_0], solutionSplit[_1]);
+}
+#endif //GLOBAL_GEODESIC_FE_ASSEMBLERWRAPPER_HH
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e28375730ca3df2d1322b4ba0f9d0586ba21583d..7f452954c2ce12749383586c23e009bd6a144542 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -26,5 +26,11 @@ dune_add_test(SOURCES harmonicmaptest.cc
               TIMEOUT 600
               CMAKE_GUARD MPI_FOUND)
 
+# Run distributed tests
+dune_add_test(SOURCES geodesicfeassemblerwrappertest.cc
+              MPI_RANKS 1 4
+              TIMEOUT 600
+              CMAKE_GUARD MPI_FOUND)
+
 # Copy the example grid used for testing into the build dir
 file(COPY grids/irregular-square.msh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/grids)
diff --git a/test/geodesicfeassemblerwrappertest.cc b/test/geodesicfeassemblerwrappertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4a44e4892e30d65562d11940702528800d60e285
--- /dev/null
+++ b/test/geodesicfeassemblerwrappertest.cc
@@ -0,0 +1,238 @@
+#include <config.h>
+
+#include <array>
+
+// Includes for the ADOL-C automatic differentiation library
+// Need to come before (almost) all others.
+#include <adolc/adouble.h>
+#include <dune/fufem/utilities/adolcnamespaceinjections.hh>
+
+#include <dune/common/typetraits.hh>
+#include <dune/common/bitsetvector.hh>
+
+#include <dune/functions/functionspacebases/compositebasis.hh>
+#include <dune/functions/functionspacebases/interpolate.hh>
+#include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
+#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
+
+#include <dune/fufem/boundarypatch.hh>
+
+#include <dune/grid/utility/structuredgridfactory.hh>
+#include <dune/grid/uggrid.hh>
+
+#include <dune/gfe/cosseratenergystiffness.hh>
+#include <dune/gfe/geodesicfeassembler.hh>
+#include <dune/gfe/harmonicenergy.hh>
+#include <dune/gfe/localgeodesicfeadolcstiffness.hh>
+#include <dune/gfe/localprojectedfefunction.hh>
+#include <dune/gfe/mixedgfeassembler.hh>
+#include <dune/gfe/mixedlocalgfeadolcstiffness.hh>
+#include <dune/gfe/riemanniantrsolver.hh>
+
+#include <dune/gfe/geodesicfeassemblerwrapper.hh>
+
+#include <dune/istl/multitypeblockmatrix.hh>
+#include <dune/istl/multitypeblockvector.hh>
+
+// grid dimension
+const int gridDim = 2;
+
+// target dimension
+const int dim = 3;
+
+//order of the finite element space
+const int displacementOrder = 2;
+const int rotationOrder = 2;
+
+using namespace Dune;
+using namespace Indices;
+
+//differentiation method: ADOL-C
+using ValueType = adouble;
+
+//Types for the mixed space
+using DisplacementVector = std::vector<RealTuple<double,dim>>;
+using RotationVector =  std::vector<Rotation<double,dim>>;
+using Vector = MultiTypeBlockVector<DisplacementVector, RotationVector>;
+const int dimCR = Rotation<double,dim>::TangentVector::dimension; //dimCorrectionRotation = Dimension of the correction for rotations
+using CorrectionType = MultiTypeBlockVector<BlockVector<FieldVector<double,dim> >, BlockVector<FieldVector<double,dimCR>>>;
+
+using MatrixRow0 = MultiTypeBlockVector<BCRSMatrix<FieldMatrix<double,dim,dim>>,  BCRSMatrix<FieldMatrix<double,dim,dimCR>>>;
+using MatrixRow1 = MultiTypeBlockVector<BCRSMatrix<FieldMatrix<double,dimCR,dim>>, BCRSMatrix<FieldMatrix<double,dimCR,dimCR>>>;
+using MatrixType = MultiTypeBlockMatrix<MatrixRow0,MatrixRow1>;
+
+//Types for the Non-mixed space
+using RBM = RigidBodyMotion<double, dim>;
+const static int blocksize = RBM::TangentVector::dimension;
+
+struct NeumannFunction
+    : public Dune::VirtualFunction<FieldVector<double,gridDim>, FieldVector<double,dim> >
+{
+    NeumannFunction(){}
+
+    void evaluate(const FieldVector<double, gridDim>& x, FieldVector<double,dim>& out) const {
+        out = 0;
+        out.axpy(1.0, values_);
+    }
+    FieldVector<double,3> values_ = {3e4,2e4,1e4};
+};  
+using CorrectionTypeWrapped = BlockVector<FieldVector<double, blocksize> >;
+using MatrixTypeWrapped = BCRSMatrix<FieldMatrix<double, blocksize, blocksize> >;
+
+int main (int argc, char *argv[])
+{
+  MPIHelper::instance(argc, argv);
+
+  /////////////////////////////////////////////////////////////////////////
+  //    Create the grid
+  /////////////////////////////////////////////////////////////////////////
+  using GridType = UGGrid<gridDim>;
+  auto grid = StructuredGridFactory<GridType>::createCubeGrid({0,0}, {1,1}, {2,2});
+  grid->globalRefine(2);
+  grid->loadBalance();
+
+  using GridView = GridType::LeafGridView;
+  GridView gridView = grid->leafGridView();
+
+  std::function<bool(FieldVector<double,gridDim>)> isNeumann = [](FieldVector<double,gridDim> coordinate) {
+    return coordinate[0] > 0.99;
+  };
+
+  BitSetVector<1> neumannVertices(gridView.size(gridDim), false);
+  const GridView::IndexSet& indexSet = gridView.indexSet();
+  
+  for (auto&& vertex : vertices(gridView))
+      neumannVertices[indexSet.index(vertex)] = isNeumann(vertex.geometry().corner(0));
+
+  BoundaryPatch<GridView> neumannBoundary(gridView, neumannVertices);
+
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Create a composite basis
+  /////////////////////////////////////////////////////////////////////////
+
+  using namespace Functions::BasisFactory;
+
+  auto compositeBasis = makeBasis(
+    gridView,
+    composite(
+      power<dim>(
+        lagrange<displacementOrder>()
+      ),
+      power<dim>(
+        lagrange<rotationOrder>()
+      )
+  ));
+
+  using CompositeBasis = decltype(compositeBasis);
+  using LocalView = typename CompositeBasis::LocalView;
+
+  /////////////////////////////////////////////////////////////////////////
+  //  Create the energy functions with their parameters
+  /////////////////////////////////////////////////////////////////////////
+
+  //Surface-Cosserat-Energy-Parameters
+  ParameterTree parameters;
+  parameters["thickness"] = "1";
+  parameters["mu"] = "2.7191e+4";
+  parameters["lambda"] = "4.4364e+4";
+  parameters["mu_c"] = "0";
+  parameters["L_c"] = "0.01";
+  parameters["q"] = "2";
+  parameters["kappa"] = "1";
+
+
+  auto neumannFunction = std::make_shared<NeumannFunction>();
+  CosseratEnergyLocalStiffness<decltype(compositeBasis), dim,adouble> cosseratEnergy(parameters,
+                                                                     &neumannBoundary,
+                                                                     neumannFunction,
+                                                                     nullptr);
+  MixedLocalGFEADOLCStiffness<CompositeBasis,
+                              RealTuple<double,dim>,
+                              Rotation<double,dim> > mixedLocalGFEADOLCStiffness(&cosseratEnergy);
+  MixedGFEAssembler<CompositeBasis,
+                    RealTuple<double,dim>,
+                    Rotation<double,dim> > mixedAssembler(compositeBasis, &mixedLocalGFEADOLCStiffness);
+
+  using RBM = RigidBodyMotion<double, dim>;
+  using DeformationFEBasis = Functions::LagrangeBasis<GridView,displacementOrder>;
+  DeformationFEBasis deformationFEBasis(gridView);
+  using GFEAssemblerWrapper = GFE::GeodesicFEAssemblerWrapper<CompositeBasis, DeformationFEBasis, RBM, RealTuple<double, dim>, Rotation<double,dim>>;
+  GFEAssemblerWrapper assembler(&mixedAssembler, deformationFEBasis);
+  
+  /////////////////////////////////////////////////////////////////////////
+  //  Prepare the iterate x where we want to assemble - identity in 2D with z = 0
+  /////////////////////////////////////////////////////////////////////////  
+  auto deformationPowerBasis = makeBasis(
+    gridView,
+    power<gridDim>(
+        lagrange<displacementOrder>()
+  ));
+  BlockVector<FieldVector<double,gridDim> > identity(compositeBasis.size({0}));
+  Functions::interpolate(deformationPowerBasis, identity, [](FieldVector<double,gridDim> x){ return x; });
+  BlockVector<FieldVector<double,dim> > initialDeformation(compositeBasis.size({0}));
+  initialDeformation = 0;
+
+  Vector x;
+  x[_0].resize(compositeBasis.size({0}));
+  x[_1].resize(compositeBasis.size({1}));
+  std::vector<RBM> xRBM(compositeBasis.size({0}));
+  for (int i = 0; i < compositeBasis.size({0}); i++) {
+    for (int j = 0; j < gridDim; j++)
+      initialDeformation[i][j] = identity[i][j];
+    x[_0][i] = initialDeformation[i];
+    for (int j = 0; j < dim; j ++) { // Displacement part
+      xRBM[i].r[j] = x[_0][i][j];
+    }
+    xRBM[i].q = x[_1][i]; // Rotation part
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //  Compute the energy, assemble the Gradient and Hessian using 
+  //  the GeodesicFEAssemblerWrapper and the MixedGFEAssembler and compare!
+  //////////////////////////////////////////////////////////////////////////////
+  CorrectionTypeWrapped gradient;
+  MatrixTypeWrapped hessianMatrix;
+  double energy = assembler.computeEnergy(xRBM);
+  assembler.assembleGradientAndHessian(xRBM, gradient, hessianMatrix, true);
+  double gradientTwoNorm = gradient.two_norm();
+  double gradientInfinityNorm = gradient.infinity_norm();
+  double matrixFrobeniusNorm = hessianMatrix.frobenius_norm();
+
+  CorrectionType gradientMixed;
+  gradientMixed[_0].resize(x[_0].size());
+  gradientMixed[_1].resize(x[_1].size());
+  MatrixType hessianMatrixMixed;
+  double energyMixed = mixedAssembler.computeEnergy(x[_0], x[_1]);
+  mixedAssembler.assembleGradientAndHessian(x[_0], x[_1], gradientMixed[_0], gradientMixed[_1], hessianMatrixMixed, true);
+  double gradientMixedTwoNorm = gradientMixed.two_norm();
+  double gradientMixedInfinityNorm = gradientMixed.infinity_norm();
+  double matrixMixedFrobeniusNorm = hessianMatrixMixed.frobenius_norm();
+
+  if (std::abs(energy - energyMixed)/energyMixed > 1e-8)
+  {
+      std::cerr << std::setprecision(9);
+      std::cerr << "The energy calculated by the GeodesicFEAssemblerWrapper is " << energy << " but "
+                << energyMixed << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
+      return 1;
+  }
+  if ( std::abs(gradientTwoNorm - gradientMixedTwoNorm)/gradientMixedTwoNorm > 1e-8 ||
+       std::abs(gradientInfinityNorm - gradientMixedInfinityNorm)/gradientMixedInfinityNorm > 1e-8)
+  {
+      std::cerr << std::setprecision(9);
+      std::cerr << "The gradient infinity norm calculated by the GeodesicFEAssemblerWrapper is " << gradientInfinityNorm << " but "
+                << gradientMixedInfinityNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
+      std::cerr << "The gradient norm calculated by the GeodesicFEAssemblerWrapper is " << gradientTwoNorm << " but "
+                << gradientMixedTwoNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
+      return 1;
+  }
+
+  if (std::abs(matrixFrobeniusNorm - matrixMixedFrobeniusNorm)/matrixMixedFrobeniusNorm > 1e-8)
+  {
+      std::cerr << std::setprecision(9);
+      std::cerr << "The matrix norm calculated by the GeodesicFEAssemblerWrapper is " << matrixFrobeniusNorm << " but "
+                << matrixMixedFrobeniusNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
+      return 1;
+  }
+}