From 663c54cdcf25d98d2501ea3d9dac071229328e1a Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Sun, 8 Nov 2020 21:19:36 +0100
Subject: [PATCH] Remove the RodAssembler class

GeodesicFEAssembler can replace it without problems.
---
 dune/gfe/rodassembler.cc    | 430 --------------------------
 dune/gfe/rodassembler.hh    | 148 ---------
 src/rod3d.cc                |  36 ++-
 test/CMakeLists.txt         |   1 -
 test/frameinvariancetest.cc |  33 +-
 test/rodassemblertest.cc    | 587 ------------------------------------
 test/rotationtest.cc        | 127 --------
 7 files changed, 49 insertions(+), 1313 deletions(-)
 delete mode 100644 dune/gfe/rodassembler.cc
 delete mode 100644 dune/gfe/rodassembler.hh
 delete mode 100644 test/rodassemblertest.cc

diff --git a/dune/gfe/rodassembler.cc b/dune/gfe/rodassembler.cc
deleted file mode 100644
index 01b5e2d7..00000000
--- a/dune/gfe/rodassembler.cc
+++ /dev/null
@@ -1,430 +0,0 @@
-#include <dune/istl/bcrsmatrix.hh>
-#include <dune/common/fmatrix.hh>
-#include <dune/istl/matrixindexset.hh>
-#include <dune/istl/matrix.hh>
-
-#include <dune/geometry/quadraturerules.hh>
-
-#include <dune/localfunctions/lagrange/p1.hh>
-
-#include <dune/gfe/rodlocalstiffness.hh>
-
-
-
-template <class Basis>
-void RodAssembler<Basis,3>::
-assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol,
-                 Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const
-{
-    using namespace Dune;
-
-    if (sol.size()!=this->basis_.size())
-        DUNE_THROW(Exception, "Solution vector doesn't match the grid!");
-
-    grad.resize(sol.size());
-    grad = 0;
-
-    // A view on the FE basis on a single element
-    auto localView = this->basis_.localView();
-
-    // Loop over all elements
-    for (const auto& element : Dune::elements(this->basis_.gridView()))
-    {
-        localView.bind(element);
-
-        // A 1d grid has two vertices
-        static const int nDofs = 2;
-
-        // Extract local solution
-        std::vector<RigidBodyMotion<double,3> > localSolution(nDofs);
-
-        for (int i=0; i<nDofs; i++)
-            localSolution[i] = sol[localView.index(i)];
-
-        // Assemble local gradient
-        std::vector<FieldVector<double,blocksize> > localGradient(nDofs);
-
-        this->localStiffness_->assembleGradient(localView,
-                                                localSolution,
-                                                localGradient);
-
-        // Add to global gradient
-        for (int i=0; i<nDofs; i++)
-            grad[localView.index(i)] += localGradient[i];
-
-    }
-
-}
-
-
-template <class GridView>
-void RodAssembler<GridView,2>::
-assembleMatrix(const std::vector<RigidBodyMotion<double,2> >& sol,
-               Dune::BCRSMatrix<MatrixBlock>& matrix)
-{
-    Dune::MatrixIndexSet neighborsPerVertex;
-    this->getNeighborsPerVertex(neighborsPerVertex);
-
-    matrix = 0;
-
-    Dune::Matrix<MatrixBlock> mat;
-
-    for (const auto& element : Dune::elements(this->basis_.gridView()))
-    {
-        const int numOfBaseFct = 2;
-
-        // Extract local solution
-        std::vector<RigidBodyMotion<double,2> > localSolution(numOfBaseFct);
-
-        for (int i=0; i<numOfBaseFct; i++)
-            localSolution[i] = sol[this->basis_.index(element,i)];
-
-        // setup matrix
-        getLocalMatrix(element, localSolution, mat);
-
-        // Add element matrix to global stiffness matrix
-        for(int i=0; i<numOfBaseFct; i++) {
-
-            int row = this->basis_.index(element,i);
-
-            for (int j=0; j<numOfBaseFct; j++ ) {
-
-                int col = this->basis_.index(element,j);
-                matrix[row][col] += mat[i][j];
-
-            }
-        }
-
-    }
-
-}
-
-
-
-
-
-
-template <class GridView>
-void RodAssembler<GridView,2>::
-getLocalMatrix( EntityType &entity,
-                const std::vector<RigidBodyMotion<double,2> >& localSolution,
-                Dune::Matrix<MatrixBlock>& localMat) const
-{
-    /* ndof is the number of vectors of the element */
-    int ndof = localSolution.size();
-
-    localMat.setSize(ndof,ndof);
-    localMat = 0;
-
-    Dune::P1LocalFiniteElement<double,double,gridDim> localFiniteElement;
-
-    // Get quadrature rule
-    const Dune::QuadratureRule<double, gridDim>& quad = Dune::QuadratureRules<double, gridDim>::rule(entity.type(), 2);
-
-    /* Loop over all integration points */
-    for (int ip=0; ip<quad.size(); ip++) {
-
-        // Local position of the quadrature point
-        const Dune::FieldVector<double,gridDim>& quadPos = quad[ip].position();
-
-        // calc Jacobian inverse before integration element is evaluated
-        const Dune::FieldMatrix<double,gridDim,gridDim>& inv = entity.geometry().jacobianInverseTransposed(quadPos);
-        const double integrationElement = entity.geometry().integrationElement(quadPos);
-
-        /* Compute the weight of the current integration point */
-        double weight = quad[ip].weight() * integrationElement;
-
-        /**********************************************/
-        /* compute gradients of the shape functions   */
-        /**********************************************/
-        std::vector<Dune::FieldMatrix<double,1,gridDim> > referenceElementGradients(ndof);
-        localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceElementGradients);
-
-        std::vector<Dune::FieldVector<double,gridDim> > shapeGrad(ndof);
-
-        // multiply with jacobian inverse
-        for (int dof=0; dof<ndof; dof++)
-            inv.mv(referenceElementGradients[dof][0], shapeGrad[dof]);
-
-
-        std::vector<Dune::FieldVector<double,1> > shapeFunction;
-        localFiniteElement.localBasis().evaluateFunction(quadPos,shapeFunction);
-
-        // //////////////////////////////////
-        //   Interpolate
-        // //////////////////////////////////
-
-        double x_s     = localSolution[0].r[0]*shapeGrad[0][0] + localSolution[1].r[0]*shapeGrad[1][0];
-        double y_s     = localSolution[0].r[1]*shapeGrad[0][0] + localSolution[1].r[1]*shapeGrad[1][0];
-
-        double theta   = localSolution[0].q.angle_*shapeFunction[0] + localSolution[1].q.angle_*shapeFunction[1];
-
-        for (int i=0; i<localMat.N(); i++) {
-
-            for (int j=0; j<localMat.M(); j++) {
-
-                // \partial J^2 / \partial x_i \partial x_j
-                localMat[i][j][0][0] += weight * shapeGrad[i][0] * shapeGrad[j][0]
-                    * (A1 * cos(theta) * cos(theta) + A3 * sin(theta) * sin(theta));
-
-                // \partial J^2 / \partial x_i \partial y_j
-                localMat[i][j][0][1] += weight * shapeGrad[i][0] * shapeGrad[j][0]
-                    * (-A1 + A3) * sin(theta)* cos(theta);
-
-                // \partial J^2 / \partial x_i \partial theta_j
-                localMat[i][j][0][2] += weight * shapeGrad[i][0] * shapeFunction[j]
-                    * (-A1 * (x_s*sin(theta) + y_s*cos(theta)) * cos(theta)
-                       - A1* (x_s*cos(theta) - y_s*sin(theta)) * sin(theta)
-                       +A3 * (x_s*cos(theta) - y_s*sin(theta)) * sin(theta)
-                       +A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * cos(theta));
-
-                // \partial J^2 / \partial y_i \partial x_j
-                localMat[i][j][1][0] += weight * shapeGrad[i][0] * shapeGrad[j][0]
-                    * (-A1 * sin(theta)* cos(theta) + A3 * cos(theta) * sin(theta));
-
-                // \partial J^2 / \partial y_i \partial y_j
-                localMat[i][j][1][1] += weight * shapeGrad[i][0] * shapeGrad[j][0]
-                    * (A1 * sin(theta)*sin(theta) + A3 * cos(theta)*cos(theta));
-
-                // \partial J^2 / \partial y_i \partial theta_j
-                localMat[i][j][1][2] += weight * shapeGrad[i][0] * shapeFunction[j]
-                    * (A1  * (x_s * sin(theta) + y_s * cos(theta)) * sin(theta)
-                       -A1 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta)
-                       +A3 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta)
-                       -A3 * (x_s * sin(theta) + y_s * cos(theta) - 1) * sin(theta));
-
-                // \partial J^2 / \partial theta_i \partial x_j
-                localMat[i][j][2][0] += weight * shapeFunction[i] * shapeGrad[j][0]
-                    * (-A1 * (x_s*sin(theta) + y_s*cos(theta)) * cos(theta)
-                       - A1* (x_s*cos(theta) - y_s*sin(theta)) * sin(theta)
-                       +A3 * (x_s*cos(theta) - y_s*sin(theta)) * sin(theta)
-                       +A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * cos(theta));
-
-                // \partial J^2 / \partial theta_i \partial y_j
-                localMat[i][j][2][1] += weight * shapeFunction[i] * shapeGrad[j][0]
-                    * (A1  * (x_s * sin(theta) + y_s * cos(theta)) * sin(theta)
-                       -A1 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta)
-                       +A3 * (x_s * cos(theta) - y_s * sin(theta)) * cos(theta)
-                       -A3 * (x_s * sin(theta) + y_s * cos(theta) - 1) * sin(theta));
-
-                // \partial J^2 / \partial theta_i \partial theta_j
-                localMat[i][j][2][2] += weight * B * shapeGrad[i][0] * shapeGrad[j][0];
-                localMat[i][j][2][2] += weight * shapeFunction[i] * shapeFunction[j]
-                    * (+ A1 * (x_s*sin(theta) + y_s*cos(theta)) * (x_s*sin(theta) + y_s*cos(theta))
-                       + A1 * (x_s*cos(theta) - y_s*sin(theta)) * (-x_s*cos(theta)+ y_s*sin(theta))
-                       + A3 * (x_s*cos(theta) - y_s*sin(theta)) * (x_s*cos(theta) - y_s*sin(theta))
-                       - A3 * (x_s*sin(theta) + y_s*cos(theta) - 1) * (x_s*sin(theta) + y_s*cos(theta)));
-
-
-
-            }
-
-        }
-
-
-    }
-
-#if 0
-    static int eleme = 0;
-    printf("********* Element %d **********\n", eleme++);
-    for (int row=0; row<matSize; row++) {
-
-        for (int rcomp=0; rcomp<dim; rcomp++) {
-
-            for (int col=0; col<matSize; col++) {
-
-                for (int ccomp=0; ccomp<dim; ccomp++)
-                    std::cout << mat[row][col][rcomp][ccomp] << "  ";
-
-                std::cout << "    ";
-
-            }
-
-            std::cout << std::endl;
-
-        }
-
-        std::cout << std::endl;
-
-    }
-    exit(0);
-#endif
-
-}
-
-template <class GridView>
-void RodAssembler<GridView,2>::
-assembleGradient(const std::vector<RigidBodyMotion<double,2> >& sol,
-                 Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const
-{
-    if (sol.size()!=this->basis_.size())
-        DUNE_THROW(Dune::Exception, "Solution vector doesn't match the grid!");
-
-    grad.resize(sol.size());
-    grad = 0;
-
-    // Loop over all elements
-    for (const auto& element : Dune::elements(this->basis_gridView()))
-    {
-        // Extract local solution on this element
-        Dune::P1LocalFiniteElement<double,double,gridDim> localFiniteElement;
-        const int numOfBaseFct = localFiniteElement.localBasis().size();
-
-        RigidBodyMotion<double,2> localSolution[numOfBaseFct];
-
-        for (int i=0; i<numOfBaseFct; i++)
-            localSolution[i] = sol[this->basis_.index(element,i)];
-
-        // Get quadrature rule
-        const auto& quad = Dune::QuadratureRules<double, gridDim>::rule(element.type(), 2);
-
-        for (int pt=0; pt<quad.size(); pt++) {
-
-            // Local position of the quadrature point
-            const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position();
-
-            const Dune::FieldMatrix<double,1,1>& inv = element.geometry().jacobianInverseTransposed(quadPos);
-            const double integrationElement = element.geometry().integrationElement(quadPos);
-
-            double weight = quad[pt].weight() * integrationElement;
-
-            /**********************************************/
-            /* compute gradients of the shape functions   */
-            /**********************************************/
-            std::vector<Dune::FieldMatrix<double,1,gridDim> > referenceElementGradients(numOfBaseFct);
-            localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceElementGradients);
-
-            std::vector<Dune::FieldVector<double,gridDim> > shapeGrad(numOfBaseFct);
-
-            // multiply with jacobian inverse
-            for (int dof=0; dof<numOfBaseFct; dof++)
-                inv.mv(referenceElementGradients[dof][0], shapeGrad[dof]);
-
-            // Get the values of the shape functions
-            std::vector<Dune::FieldVector<double,1> > shapeFunction;
-            localFiniteElement.localBasis().evaluateFunction(quadPos,shapeFunction);
-
-            // //////////////////////////////////
-            //   Interpolate
-            // //////////////////////////////////
-
-            double x_s     = localSolution[0].r[0]*shapeGrad[0][0] + localSolution[1].r[0]*shapeGrad[1][0];
-            double y_s     = localSolution[0].r[1]*shapeGrad[0][0] + localSolution[1].r[1]*shapeGrad[1][0];
-            double theta_s = localSolution[0].q.angle_*shapeGrad[0][0] + localSolution[1].q.angle_*shapeGrad[1][0];
-
-            double theta   = localSolution[0].q.angle_*shapeFunction[0] + localSolution[1].q.angle_*shapeFunction[1];
-
-            // /////////////////////////////////////////////
-            //   Sum it all up
-            // /////////////////////////////////////////////
-
-            double partA1 = A1 * (x_s * cos(theta) - y_s * sin(theta));
-            double partA3 = A3 * (x_s * sin(theta) + y_s * cos(theta) - 1);
-
-            for (int dof=0; dof<numOfBaseFct; dof++) {
-
-                int globalDof = this->basis_.index(element,dof);
-
-                //printf("globalDof: %d   partA1: %g   partA3: %g\n", globalDof, partA1, partA3);
-
-                // \partial J / \partial x^i
-                grad[globalDof][0] += weight * (partA1 * cos(theta) + partA3 * sin(theta)) * shapeGrad[dof][0];
-
-                // \partial J / \partial y^i
-                grad[globalDof][1] += weight * (-partA1 * sin(theta) + partA3 * cos(theta)) * shapeGrad[dof][0];
-
-                // \partial J / \partial \theta^i
-                grad[globalDof][2] += weight * (B * theta_s * shapeGrad[dof][0]
-                                               + partA1 * (-x_s * sin(theta) - y_s * cos(theta)) * shapeFunction[dof]
-                                               + partA3 * ( x_s * cos(theta) - y_s * sin(theta)) * shapeFunction[dof]);
-
-            }
-
-
-        }
-
-    }
-
-}
-
-
-template <class GridView>
-double RodAssembler<GridView,2>::
-computeEnergy(const std::vector<RigidBodyMotion<double,2> >& sol) const
-{
-    double energy = 0;
-
-    if (sol.size()!=this->basis_.size())
-        DUNE_THROW(Dune::Exception, "Solution vector doesn't match the grid!");
-
-    // Loop over all elements
-    for (const auto& element : Dune::elements(this->basis_gridView()))
-    {
-        // Extract local solution on this element
-        Dune::P1LocalFiniteElement<double,double,gridDim> localFiniteElement;
-
-        int numOfBaseFct = localFiniteElement.localBasis().size();
-
-        std::vector<RigidBodyMotion<double,2> > localSolution(numOfBaseFct);
-
-        for (int i=0; i<numOfBaseFct; i++)
-            localSolution[i] = sol[this->basis_.index(element,i)];
-
-        // Get quadrature rule
-        const auto& quad = Dune::QuadratureRules<double, gridDim>::rule(element.type(), 2);
-
-        for (int pt=0; pt<quad.size(); pt++) {
-
-            // Local position of the quadrature point
-            const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position();
-
-            const Dune::FieldMatrix<double,1,1>& inv = element.geometry().jacobianInverseTransposed(quadPos);
-            const double integrationElement = element.geometry().integrationElement(quadPos);
-
-            double weight = quad[pt].weight() * integrationElement;
-
-            /**********************************************/
-            /* compute gradients of the shape functions   */
-            /**********************************************/
-            std::vector<Dune::FieldMatrix<double,1,gridDim> > referenceElementGradients(numOfBaseFct);
-            localFiniteElement.localBasis().evaluateJacobian(quadPos,referenceElementGradients);
-
-            std::vector<Dune::FieldVector<double,gridDim> > shapeGrad(numOfBaseFct);
-
-            // multiply with jacobian inverse
-            for (int dof=0; dof<numOfBaseFct; dof++)
-                inv.mv(referenceElementGradients[dof][0], shapeGrad[dof]);
-
-            // Get the value of the shape functions
-            std::vector<Dune::FieldVector<double,1> > shapeFunction;
-            localFiniteElement.localBasis().evaluateFunction(quadPos,shapeFunction);
-
-            // //////////////////////////////////
-            //   Interpolate
-            // //////////////////////////////////
-
-            double x_s     = localSolution[0].r[0]*shapeGrad[0][0] + localSolution[1].r[0]*shapeGrad[1][0];
-            double y_s     = localSolution[0].r[1]*shapeGrad[0][0] + localSolution[1].r[1]*shapeGrad[1][0];
-            double theta_s = localSolution[0].q.angle_*shapeGrad[0][0] + localSolution[1].q.angle_*shapeGrad[1][0];
-
-            double theta   = localSolution[0].q.angle_*shapeFunction[0] + localSolution[1].q.angle_*shapeFunction[1];
-
-            // /////////////////////////////////////////////
-            //   Sum it all up
-            // /////////////////////////////////////////////
-
-            double partA1 = x_s * cos(theta) - y_s * sin(theta);
-            double partA3 = x_s * sin(theta) + y_s * cos(theta) - 1;
-
-
-            energy += 0.5 * weight * (B * theta_s * theta_s
-                                      + A1 * partA1 * partA1
-                                      + A3 * partA3 * partA3);
-
-        }
-
-    }
-
-    return energy;
-
-}
diff --git a/dune/gfe/rodassembler.hh b/dune/gfe/rodassembler.hh
deleted file mode 100644
index 70ab003e..00000000
--- a/dune/gfe/rodassembler.hh
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef DUNE_EXTENSIBLE_ROD_ASSEMBLER_HH
-#define DUNE_EXTENSIBLE_ROD_ASSEMBLER_HH
-
-#include <dune/istl/bcrsmatrix.hh>
-#include <dune/common/fmatrix.hh>
-#include <dune/istl/matrixindexset.hh>
-#include <dune/istl/matrix.hh>
-
-#include <dune/fufem/boundarypatch.hh>
-
-#include <dune/gfe/localgeodesicfefdstiffness.hh>
-#include "rigidbodymotion.hh"
-#include "rodlocalstiffness.hh"
-#include "geodesicfeassembler.hh"
-
-/** \brief The FEM operator for an extensible, shearable rod in 3d
- */
-template <class Basis, int spaceDim>
-class RodAssembler
-{
-    static_assert(spaceDim==2 || spaceDim==3,
-                       "You can only instantiate the class RodAssembler for 2d and 3d spaces");
-};
-
-/** \brief The FEM operator for an extensible, shearable rod in 3d
- */
-template <class Basis>
-class RodAssembler<Basis,3> : public GeodesicFEAssembler<Basis, RigidBodyMotion<double,3> >
-{
-  typedef typename Basis::GridView GridView;
-
-  //! Dimension of the grid.
-  enum { gridDim = GridView::dimension };
-  static_assert(gridDim==1, "RodAssembler can only be used with one-dimensional grids!");
-
-        enum { elementOrder = 1};
-
-        //! Each block is x, y, theta in 2d, T (R^3 \times SO(3)) in 3d
-        enum { blocksize = 6 };
-
-public:
-        //! ???
-    RodAssembler(const Basis& basis,
-                 LocalGeodesicFEStiffness<Basis, RigidBodyMotion<double,3> >& localStiffness)
-    : GeodesicFEAssembler<Basis, RigidBodyMotion<double,3> >(basis,localStiffness)
-        {
-            std::vector<RigidBodyMotion<double,3> > referenceConfiguration(basis.size());
-
-    for (const auto vertex : Dune::vertices(basis.gridView()))
-    {
-      auto idx = basis.gridView().indexSet().index(vertex);
-
-                referenceConfiguration[idx].r[0] = 0;
-                referenceConfiguration[idx].r[1] = 0;
-      referenceConfiguration[idx].r[2] = vertex.geometry().corner(0)[0];
-                referenceConfiguration[idx].q = Rotation<double,3>::identity();
-            }
-
-    rodEnergy()->setReferenceConfiguration(referenceConfiguration);
-        }
-
-    auto rodEnergy()
-    {
-      // TODO: Does not work for other stiffness implementations
-      auto localFDStiffness = std::dynamic_pointer_cast<LocalGeodesicFEFDStiffness<Basis, RigidBodyMotion<double,3> > >(this->localStiffness_);
-      return const_cast<RodLocalStiffness<GridView,double>*>(dynamic_cast<const RodLocalStiffness<GridView,double>*>(localFDStiffness->localEnergy_));
-    }
-
-        std::vector<RigidBodyMotion<double,3> > getRefConfig()
-    {
-      return rodEnergy()->referenceConfiguration_;
-        }
-
-  virtual void assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol,
-                                Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const override;
-
-    }; // end class
-
-
-/** \brief The FEM operator for a 2D extensible, shearable rod
- */
-template <class Basis>
-class RodAssembler<Basis,2> : public GeodesicFEAssembler<Basis, RigidBodyMotion<double,2> >
-{
-
-    typedef typename Basis::GridView GridView;
-    typedef typename GridView::template Codim<0>::Entity EntityType;
-
-  //! Dimension of the grid.
-  enum { gridDim = GridView::dimension };
-  static_assert(gridDim==1, "RodAssembler can only be used with one-dimensional grids!");
-
-    enum { elementOrder = 1};
-
-    //! Each block is x, y, theta
-    enum { blocksize = 3 };
-
-    //!
-    typedef Dune::FieldMatrix<double, blocksize, blocksize> MatrixBlock;
-
-    /** \brief Material constants */
-    double B;
-    double A1;
-    double A3;
-
-public:
-
-    //! ???
-    RodAssembler(const GridView &gridView)
-        : GeodesicFEAssembler<Basis, RigidBodyMotion<double,2> >(gridView,nullptr)
-    {
-        B = 1;
-        A1 = 1;
-        A3 = 1;
-    }
-
-    ~RodAssembler() {}
-
-    void setParameters(double b, double a1, double a3) {
-        B  = b;
-        A1 = a1;
-        A3 = a3;
-    }
-
-    /** \brief Assemble the tangent stiffness matrix and the right hand side
-     */
-    void assembleMatrix(const std::vector<RigidBodyMotion<double,2> >& sol,
-                        Dune::BCRSMatrix<MatrixBlock>& matrix);
-
-    virtual void assembleGradient(const std::vector<RigidBodyMotion<double,2> >& sol,
-                          Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const override;
-
-    /** \brief Compute the energy of a deformation state */
-    virtual double computeEnergy(const std::vector<RigidBodyMotion<double,2> >& sol) const override;
-
-protected:
-
-    /** \brief Compute the element tangent stiffness matrix  */
-    void getLocalMatrix( EntityType &entity,
-                         const std::vector<RigidBodyMotion<double,2> >& localSolution,
-                         Dune::Matrix<MatrixBlock>& mat) const;
-
-}; // end class
-
-#include "rodassembler.cc"
-
-#endif
-
diff --git a/src/rod3d.cc b/src/rod3d.cc
index e803181a..26054037 100644
--- a/src/rod3d.cc
+++ b/src/rod3d.cc
@@ -13,9 +13,11 @@
 #include <dune/solvers/norms/energynorm.hh>
 
 #include <dune/gfe/cosseratvtkwriter.hh>
+#include <dune/gfe/geodesicfeassembler.hh>
+#include <dune/gfe/localgeodesicfefdstiffness.hh>
 #include <dune/gfe/rigidbodymotion.hh>
+#include <dune/gfe/rodlocalstiffness.hh>
 #include <dune/gfe/rotation.hh>
-#include <dune/gfe/rodassembler.hh>
 #include <dune/gfe/riemanniantrsolver.hh>
 
 typedef RigidBodyMotion<double,3> TargetSpace;
@@ -118,16 +120,35 @@ int main (int argc, char *argv[]) try
     dirichletNodes[0] = true;
     dirichletNodes.back() = true;
     
+    //////////////////////////////////////////////
+    //  Create the stress-free configuration
+    //////////////////////////////////////////////
+
+    auto localRodEnergy = std::make_shared<RodLocalStiffness<GridView, double> >(gridView,
+                                                                                 A, J1, J2, E, nu);
+
+    std::vector<RigidBodyMotion<double,3> > referenceConfiguration(gridView.size(1));
+
+    for (const auto vertex : vertices(gridView))
+    {
+        auto idx = gridView.indexSet().index(vertex);
+
+        referenceConfiguration[idx].r[0] = 0;
+        referenceConfiguration[idx].r[1] = 0;
+        referenceConfiguration[idx].r[2] = vertex.geometry().corner(0)[0];
+        referenceConfiguration[idx].q = Rotation<double,3>::identity();
+    }
+
+    localRodEnergy->setReferenceConfiguration(referenceConfiguration);
+
     // ///////////////////////////////////////////
     //   Create a solver for the rod problem
     // ///////////////////////////////////////////
 
-    RodLocalStiffness<GridView,double> localStiffness(gridView,
-                                                      A, J1, J2, E, nu);
+    LocalGeodesicFEFDStiffness<FEBasis,
+                               TargetSpace> localStiffness(localRodEnergy.get());
 
-    LocalGeodesicFEFDStiffness<FEBasis,RigidBodyMotion<double,3> > localFDStiffness(&localStiffness);
-
-    RodAssembler<FEBasis,3> rodAssembler(gridView, localFDStiffness);
+    GeodesicFEAssembler<FEBasis,TargetSpace> rodAssembler(gridView, localStiffness);
 
     RiemannianTrustRegionSolver<FEBasis,RigidBodyMotion<double,3> > rodSolver;
 
@@ -161,9 +182,6 @@ int main (int argc, char *argv[]) try
     // //////////////////////////////
     CosseratVTKWriter<GridType>::write<FEBasis>(feBasis,x, resultPath + "rod3d-result");
 
-    BlockVector<FieldVector<double, 6> > strain(x.size()-1);
-    rodAssembler.getStrain(x,strain);
-
 } catch (Exception& e)
 {
     std::cout << e.what() << std::endl;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e1952d1a..6b82573a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -9,7 +9,6 @@ set(TESTS
   localprojectedfefunctiontest
   orthogonalmatrixtest
   rigidbodymotiontest
-  rodassemblertest
   rotationtest
   svdtest
   targetspacetest
diff --git a/test/frameinvariancetest.cc b/test/frameinvariancetest.cc
index dcf53d48..fe1c1ccc 100644
--- a/test/frameinvariancetest.cc
+++ b/test/frameinvariancetest.cc
@@ -5,14 +5,9 @@
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 
 #include <dune/gfe/quaternion.hh>
-
-#include <dune/gfe/rodassembler.hh>
-
 #include <dune/gfe/rigidbodymotion.hh>
+#include <dune/gfe/rodlocalstiffness.hh>
 
-// Number of degrees of freedom: 
-// 7 (x, y, z, q_1, q_2, q_3, q_4) for a spatial rod
-const int blocksize = 6;
 
 using namespace Dune;
 
@@ -74,14 +69,30 @@ int main (int argc, char *argv[]) try
         rotatedX[i].q = rotation.mult(x[i].q);
     }
 
-    RodLocalStiffness<GridView,double> localRodFirstOrderModel(gridView,
-                                                               1,1,1,1e6,0.3);
+    RodLocalStiffness<GridView,double> localRodEnergy(gridView,
+                                                      1,1,1,1e6,0.3);
+
+    std::vector<RigidBodyMotion<double,3> > referenceConfiguration(gridView.size(1));
+
+    for (const auto vertex : vertices(gridView))
+    {
+        auto idx = gridView.indexSet().index(vertex);
+
+        referenceConfiguration[idx].r[0] = 0;
+        referenceConfiguration[idx].r[1] = 0;
+        referenceConfiguration[idx].r[2] = vertex.geometry().corner(0)[0];
+        referenceConfiguration[idx].q = Rotation<double,3>::identity();
+    }
+
+    localRodEnergy.setReferenceConfiguration(referenceConfiguration);
 
-    LocalGeodesicFEFDStiffness<FEBasis,RigidBodyMotion<double,3> > localFDStiffness(&localRodFirstOrderModel);
+    auto localView = feBasis.localView();
+    localView.bind(*gridView.begin<0>());
 
-    RodAssembler<FEBasis,3> assembler(feBasis, localFDStiffness);
+    SolutionType localX = {x[0], x[1]};
+    SolutionType localRotatedX = {rotatedX[0], rotatedX[1]};
 
-    if (std::abs(assembler.computeEnergy(x) - assembler.computeEnergy(rotatedX)) > 1e-6)
+    if (std::abs(localRodEnergy.energy(localView, localX) - localRodEnergy.energy(localView, localRotatedX)) > 1e-6)
         DUNE_THROW(Dune::Exception, "Rod energy not invariant under rigid body motions!");
 
  } catch (Exception& e) {
diff --git a/test/rodassemblertest.cc b/test/rodassemblertest.cc
deleted file mode 100644
index 55400783..00000000
--- a/test/rodassemblertest.cc
+++ /dev/null
@@ -1,587 +0,0 @@
-#include <config.h>
-
-#include <array>
-
-#include <dune/grid/onedgrid.hh>
-
-#include <dune/istl/io.hh>
-
-#include <dune/gfe/rigidbodymotion.hh>
-#include <dune/gfe/rodassembler.hh>
-
-// Number of degrees of freedom: 
-// 7 (x, y, z, q_1, q_2, q_3, q_4) for a spatial rod
-const int blocksize = 6;
-
-using namespace Dune;
-
-void infinitesimalVariation(RigidBodyMotion<double,3>& c, double eps, int i)
-{
-    if (i<3)
-        c.r[i] += eps;
-    else {
-        Dune::FieldVector<double,3> axial(0);
-        axial[i-3] = eps;
-        SkewMatrix<double,3> variation(axial);
-        c.q = c.q.mult(Rotation<double,3>::exp(variation));
-    }
-}
-
-template <class FEBasis>
-void strainFD(const std::vector<RigidBodyMotion<double,3> >& x, 
-              double pos,
-              std::array<FieldMatrix<double,2,6>, 6>& fdStrainDerivatives,
-              const RodAssembler<FEBasis,3>& assembler)
-{
-    assert(x.size()==2);
-    double eps = 1e-8;
-
-    auto element = assembler.basis_.gridView_.template begin<0>();
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-    std::vector<RigidBodyMotion<double,3> > forwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardSolution = x;
-    
-    for (size_t i=0; i<x.size(); i++) {
-        
-        Dune::FieldVector<double,6> fdGradient;
-        
-        for (int j=0; j<6; j++) {
-            
-            infinitesimalVariation(forwardSolution[i], eps, j);
-            infinitesimalVariation(backwardSolution[i], -eps, j);
-            
-//             fdGradient[j] = (assembler.computeEnergy(forwardSolution) - assembler.computeEnergy(backwardSolution))
-//                 / (2*eps);
-            Dune::FieldVector<double,6> strain;
-            strain = assembler.getStrain(forwardSolution, element, pos);
-            strain -= assembler.getStrain(backwardSolution, element, pos);
-            strain /= 2*eps;
-            
-            for (int m=0; m<6; m++)
-                fdStrainDerivatives[m][i][j] = strain[m];
-
-            forwardSolution[i] = x[i];
-            backwardSolution[i] = x[i];
-        }
-        
-    }
-
-}
-
-
-template <class FEBasis>
-void strain2ndOrderFD(const std::vector<RigidBodyMotion<double,3> >& x, 
-                      double pos,
-                      std::array<Matrix<FieldMatrix<double,6,6> >, 3>& translationDer,
-                      std::array<Matrix<FieldMatrix<double,3,3> >, 3>& rotationDer,
-                      const RodAssembler<FEBasis,3>& assembler)
-{
-    assert(x.size()==2);
-    double eps = 1e-3;
-
-    auto element = assembler.basis_.gridView_.template begin<0>();
-
-    for (int m=0; m<3; m++) {
-        
-        translationDer[m].setSize(2,2);
-        translationDer[m] = 0;
-        
-        rotationDer[m].setSize(2,2);
-        rotationDer[m] = 0;
-
-    }
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-    std::vector<RigidBodyMotion<double,3> > forwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardSolution = x;
-    
-    std::vector<RigidBodyMotion<double,3> > forwardForwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > forwardBackwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardForwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardBackwardSolution = x;
-
-    for (int i=0; i<2; i++) {
-        
-        for (int j=0; j<3; j++) {
-
-            for (int k=0; k<2; k++) {
-
-                for (int l=0; l<3; l++) {
-
-                    if (i==k && j==l) {
-
-                        infinitesimalVariation(forwardSolution[i], eps, j+3);
-                        infinitesimalVariation(backwardSolution[i], -eps, j+3);
-            
-                        // Second derivative
-//                         fdHessian[j][k] = (assembler.computeEnergy(forwardSolution) 
-//                                            - 2*assembler.computeEnergy(x) 
-//                                            + assembler.computeEnergy(backwardSolution)) / (eps*eps);
-                        
-                        Dune::FieldVector<double,6> strain;
-                        strain = assembler.getStrain(forwardSolution, element, pos);
-                        strain += assembler.getStrain(backwardSolution, element, pos);
-                        strain.axpy(-2, assembler.getStrain(x, element, pos));
-                        strain /= eps*eps;
-            
-                        for (int m=0; m<3; m++)
-                            rotationDer[m][i][k][j][l] = strain[3+m];
-
-                        forwardSolution = x;
-                        backwardSolution = x;
-
-                    } else {
-
-                        infinitesimalVariation(forwardForwardSolution[i],   eps, j+3);
-                        infinitesimalVariation(forwardForwardSolution[k],   eps, l+3);
-                        infinitesimalVariation(forwardBackwardSolution[i],  eps, j+3);
-                        infinitesimalVariation(forwardBackwardSolution[k], -eps, l+3);
-                        infinitesimalVariation(backwardForwardSolution[i], -eps, j+3);
-                        infinitesimalVariation(backwardForwardSolution[k],  eps, l+3);
-                        infinitesimalVariation(backwardBackwardSolution[i],-eps, j+3);
-                        infinitesimalVariation(backwardBackwardSolution[k],-eps, l+3);
-
-
-//                         fdHessian[j][k] = (assembler.computeEnergy(forwardForwardSolution)
-//                                            + assembler.computeEnergy(backwardBackwardSolution)
-//                                            - assembler.computeEnergy(forwardBackwardSolution)
-//                                            - assembler.computeEnergy(backwardForwardSolution)) / (4*eps*eps);
-
-                        Dune::FieldVector<double,6> strain;
-                        strain  = assembler.getStrain(forwardForwardSolution, element, pos);
-                        strain += assembler.getStrain(backwardBackwardSolution, element, pos);
-                        strain -= assembler.getStrain(forwardBackwardSolution, element, pos);
-                        strain -= assembler.getStrain(backwardForwardSolution, element, pos);
-                        strain /= 4*eps*eps;
-
-
-                        for (int m=0; m<3; m++)
-                            rotationDer[m][i][k][j][l] = strain[3+m];
-                        
-                        forwardForwardSolution   = x;
-                        forwardBackwardSolution  = x;
-                        backwardForwardSolution  = x;
-                        backwardBackwardSolution = x;
-
-
-                    }
-
-                }
-
-            }
-        }
-        
-    }
-
-}
-
-
-template <class GridType>
-void strain2ndOrderFD2(const std::vector<RigidBodyMotion<double,3> >& x, 
-                       double pos,
-                       Dune::FieldVector<double,1> shapeGrad[2],
-                       Dune::FieldVector<double,1> shapeFunction[2],
-                       std::array<Matrix<FieldMatrix<double,6,6> >, 3>& translationDer,
-                       std::array<Matrix<FieldMatrix<double,3,3> >, 3>& rotationDer,
-                       const RodAssembler<GridType,3>& assembler) 
-{
-    assert(x.size()==2);
-    double eps = 1e-3;
-
-    for (int m=0; m<3; m++) {
-        
-        translationDer[m].setSize(2,2);
-        translationDer[m] = 0;
-        
-        rotationDer[m].setSize(2,2);
-        rotationDer[m] = 0;
-
-    }
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-    std::vector<RigidBodyMotion<double,3> > forwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardSolution = x;
-    
-    for (int k=0; k<2; k++) {
-        
-        for (int l=0; l<3; l++) {
-
-            infinitesimalVariation(forwardSolution[k], eps, l+3);
-            infinitesimalVariation(backwardSolution[k], -eps, l+3);
-                
-            std::array<FieldMatrix<double,2,6>, 6> forwardStrainDer;
-            assembler.strainDerivative(forwardSolution, pos, shapeGrad, shapeFunction, forwardStrainDer);
-
-            std::array<FieldMatrix<double,2,6>, 6> backwardStrainDer;
-            assembler.strainDerivative(backwardSolution, pos, shapeGrad, shapeFunction, backwardStrainDer);
-            
-            for (int i=0; i<2; i++) {
-                for (int j=0; j<3; j++) {
-                    for (int m=0; m<3; m++) {
-                        rotationDer[m][i][k][j][l] = (forwardStrainDer[m][i][j]-backwardStrainDer[m][i][j]) / (2*eps);
-                    }
-                }
-            }
-
-            forwardSolution = x;
-            backwardSolution = x;
-            
-        }
-        
-    }
-    
-}
-
-
-
-
-
-template <class GridType>
-void expHessianFD()
-{
-    using namespace Dune;
-    double eps = 1e-3;
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-    SkewMatrix<double,3> forward;
-    SkewMatrix<double,3> backward;
-    
-    SkewMatrix<double,3> forwardForward;
-    SkewMatrix<double,3> forwardBackward;
-    SkewMatrix<double,3> backwardForward;
-    SkewMatrix<double,3> backwardBackward;
-
-    for (int i=0; i<3; i++) {
-        
-        for (int j=0; j<3; j++) {
-
-            Quaternion<double> hessian;
-
-            if (i==j) {
-
-                forward = backward = 0;
-                forward.axial()[i]  += eps;
-                backward.axial()[i] -= eps;
-                
-                // Second derivative
-                //                         fdHessian[j][k] = (assembler.computeEnergy(forward) 
-                //                                            - 2*assembler.computeEnergy(x) 
-                //                                            + assembler.computeEnergy(backward)) / (eps*eps);
-                
-                hessian  = Rotation<double,3>::exp(forward);
-                hessian += Rotation<double,3>::exp(backward);
-                SkewMatrix<double,3> zero(0);
-                hessian.axpy(-2, Rotation<double,3>::exp(zero));
-                hessian /= eps*eps;
-                
-            } else {
-                
-                forwardForward = forwardBackward = 0;
-                backwardForward = backwardBackward = 0;
-
-                forwardForward.axial()[i]   += eps;
-                forwardForward.axial()[j]   += eps;
-                forwardBackward.axial()[i]  += eps;
-                forwardBackward.axial()[j]  -= eps;
-                backwardForward.axial()[i]  -= eps;
-                backwardForward.axial()[j]  += eps;
-                backwardBackward.axial()[i] -= eps;
-                backwardBackward.axial()[j] -= eps;
-                
-                
-                hessian  = Rotation<double,3>::exp(forwardForward);
-                hessian += Rotation<double,3>::exp(backwardBackward);
-                hessian -= Rotation<double,3>::exp(forwardBackward);
-                hessian -= Rotation<double,3>::exp(backwardForward);
-                hessian /= 4*eps*eps;
-                
-            }
-
-            printf("i: %d,  j: %d    ", i, j);
-            std::cout << hessian << std::endl;
-            
-        }
-        
-    }
-}
-
-
-template <class GridType>
-void gradientFDCheck(const std::vector<RigidBodyMotion<double,3> >& x, 
-                     const Dune::BlockVector<Dune::FieldVector<double,6> >& gradient, 
-                     const RodAssembler<GridType,3>& assembler)
-{
-#ifndef ABORT_ON_ERROR
-    static int gradientError = 0;
-    double maxError = -1;
-#endif
-    double eps = 1e-6;
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-
-    std::vector<RigidBodyMotion<double,3> > forwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardSolution = x;
-
-    for (size_t i=0; i<x.size(); i++) {
-        
-        Dune::FieldVector<double,6> fdGradient;
-        
-        for (int j=0; j<6; j++) {
-            
-            infinitesimalVariation(forwardSolution[i],   eps, j);
-            infinitesimalVariation(backwardSolution[i], -eps, j);
-            
-            fdGradient[j] = (assembler.computeEnergy(forwardSolution) - assembler.computeEnergy(backwardSolution))
-                / (2*eps);
-            
-            forwardSolution[i] = x[i];
-            backwardSolution[i] = x[i];
-        }
-        
-        if ( (fdGradient-gradient[i]).two_norm() > 1e-6 ) {
-#ifdef ABORT_ON_ERROR
-            std::cout << "Differing gradients at " << i 
-                      << "!  (" << (fdGradient-gradient[i]).two_norm() / gradient[i].two_norm()
-                      << ")    Analytical: " << gradient[i] << ",  fd: " << fdGradient << std::endl;
-            //std::cout << "Current configuration " << std::endl;
-            for (size_t j=0; j<x.size(); j++)
-                std::cout << x[j] << std::endl;
-            //abort();
-#else
-            gradientError++;
-            maxError = std::max(maxError, (fdGradient-gradient[i]).two_norm());
-#endif
-        }
-        
-    }
-
-#ifndef ABORT_ON_ERROR
-    std::cout << gradientError << " errors in the gradient corrected  (max: " << maxError << ")!" << std::endl;
-#endif
-
-}
-
-
-template <class GridType>
-void hessianFDCheck(const std::vector<RigidBodyMotion<double,3> >& x, 
-                    const Dune::BCRSMatrix<Dune::FieldMatrix<double,6,6> >& hessian, 
-                    const RodAssembler<GridType,3>& assembler)
-{
-#ifndef ABORT_ON_ERROR
-    static int hessianError = 0;
-#endif
-    double eps = 1e-2;
-
-    typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<double,6,6> >::row_type::const_iterator ColumnIterator;
-
-    // ///////////////////////////////////////////////////////////
-    //   Compute gradient by finite-difference approximation
-    // ///////////////////////////////////////////////////////////
-    std::vector<RigidBodyMotion<double,3> > forwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardSolution = x;
-
-    std::vector<RigidBodyMotion<double,3> > forwardForwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > forwardBackwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardForwardSolution = x;
-    std::vector<RigidBodyMotion<double,3> > backwardBackwardSolution = x;
-    
-
-    // ///////////////////////////////////////////////////////////////
-    //   Loop over all blocks of the outer matrix
-    // ///////////////////////////////////////////////////////////////
-    for (size_t i=0; i<hessian.N(); i++) {
-
-        ColumnIterator cIt    = hessian[i].begin();
-        ColumnIterator cEndIt = hessian[i].end();
-
-        for (; cIt!=cEndIt; ++cIt) {
-
-            // ////////////////////////////////////////////////////////////////////////////
-            //   Compute a finite-difference approximation of this hessian matrix block
-            // ////////////////////////////////////////////////////////////////////////////
-
-            Dune::FieldMatrix<double,6,6> fdHessian;
-
-            for (int j=0; j<6; j++) {
-
-                for (int k=0; k<6; k++) {
-
-                    if (i==cIt.index() && j==k) {
-
-                        infinitesimalVariation(forwardSolution[i],   eps, j);
-                        infinitesimalVariation(backwardSolution[i], -eps, j);
-
-                        // Second derivative
-                        fdHessian[j][k] = (assembler.computeEnergy(forwardSolution) 
-                                           + assembler.computeEnergy(backwardSolution) 
-                                           - 2*assembler.computeEnergy(x) 
-                                           ) / (eps*eps);
-
-                        forwardSolution[i]  = x[i];
-                        backwardSolution[i] = x[i];
-
-                    } else {
-
-                        infinitesimalVariation(forwardForwardSolution[i],             eps, j);
-                        infinitesimalVariation(forwardForwardSolution[cIt.index()],   eps, k);
-                        infinitesimalVariation(forwardBackwardSolution[i],            eps, j);
-                        infinitesimalVariation(forwardBackwardSolution[cIt.index()], -eps, k);
-                        infinitesimalVariation(backwardForwardSolution[i],           -eps, j);
-                        infinitesimalVariation(backwardForwardSolution[cIt.index()],  eps, k);
-                        infinitesimalVariation(backwardBackwardSolution[i],          -eps, j);
-                        infinitesimalVariation(backwardBackwardSolution[cIt.index()],-eps, k);
-
-
-                        fdHessian[j][k] = (assembler.computeEnergy(forwardForwardSolution)
-                                           + assembler.computeEnergy(backwardBackwardSolution)
-                                           - assembler.computeEnergy(forwardBackwardSolution)
-                                           - assembler.computeEnergy(backwardForwardSolution)) / (4*eps*eps);
-
-                        forwardForwardSolution[i]             = x[i];
-                        forwardForwardSolution[cIt.index()]   = x[cIt.index()];
-                        forwardBackwardSolution[i]            = x[i];
-                        forwardBackwardSolution[cIt.index()]  = x[cIt.index()];
-                        backwardForwardSolution[i]            = x[i];
-                        backwardForwardSolution[cIt.index()]  = x[cIt.index()];
-                        backwardBackwardSolution[i]           = x[i];
-                        backwardBackwardSolution[cIt.index()] = x[cIt.index()];
-                        
-                    }
-                            
-                }
-
-            }
-                //exit(0);
-            // /////////////////////////////////////////////////////////////////////////////
-            //   Compare analytical and fd Hessians
-            // /////////////////////////////////////////////////////////////////////////////
-
-            Dune::FieldMatrix<double,6,6> diff = fdHessian;
-            diff -= *cIt;
-
-            if ( diff.frobenius_norm() > 1e-5 ) {
-#ifdef ABORT_ON_ERROR
-                std::cout << "Differing hessians at [(" << i << ", "<< cIt.index() << ")]!" << std::endl
-                          << "Analytical: " << std::endl << *cIt << std::endl
-                          << "fd: " << std::endl << fdHessian << std::endl;
-                abort();
-#else
-                hessianError++;
-#endif
-            }
-
-        }
-
-    }
-
-#ifndef ABORT_ON_ERROR
-    std::cout << hessianError << " errors in the Hessian corrected!" << std::endl;
-#endif
-
-}
-
-
-int main (int argc, char *argv[]) try
-{
-    typedef std::vector<RigidBodyMotion<double,3> > SolutionType;
-
-    // ///////////////////////////////////////
-    //    Create the grid
-    // ///////////////////////////////////////
-    typedef OneDGrid GridType;
-    GridType grid(1, 0, 1);
-
-    using GridView = GridType::LeafGridView;
-    GridView gridView = grid.leafGridView();
-
-    SolutionType x(gridView.size(1));
-
-    // //////////////////////////
-    //   Initial solution
-    // //////////////////////////
-    FieldVector<double,3>  xAxis(0);
-    xAxis[0] = 1;
-    FieldVector<double,3>  zAxis(0);
-    zAxis[2] = 1;
-
-    for (size_t i=0; i<x.size(); i++) {
-        x[i].r[0] = 0;    // x
-        x[i].r[1] = 0;                 // y
-        x[i].r[2] = double(i)/(x.size()-1);                 // z
-        //x[i].r[2] = i+5;
-        x[i].q = Quaternion<double>::identity();
-        //x[i].q = Quaternion<double>(zAxis, M_PI/2 * double(i)/(x.size()-1));
-    }
-
-    //x.back().r[1] = 0.1;
-    //x.back().r[2] = 2;
-    //x.back().q = Quaternion<double>(zAxis, M_PI/4);
-
-    std::cout << "Left boundary orientation:" << std::endl;
-    std::cout << "director 0:  " << x[0].q.director(0) << std::endl;
-    std::cout << "director 1:  " << x[0].q.director(1) << std::endl;
-    std::cout << "director 2:  " << x[0].q.director(2) << std::endl;
-    std::cout << std::endl;
-    std::cout << "Right boundary orientation:" << std::endl;
-    std::cout << "director 0:  " << x[x.size()-1].q.director(0) << std::endl;
-    std::cout << "director 1:  " << x[x.size()-1].q.director(1) << std::endl;
-    std::cout << "director 2:  " << x[x.size()-1].q.director(2) << std::endl;
-//     exit(0);
-
-    //x[0].r[2] = -1;
-
-    // ///////////////////////////////////////////
-    //   Create a solver for the rod problem
-    // ///////////////////////////////////////////
-
-    using Basis = Functions::LagrangeBasis<GridView,1>;
-    Basis basis(gridView);
-
-    RodLocalStiffness<GridView,double> localStiffness(gridView,
-                                                                    0.01, 0.0001, 0.0001, 2.5e5, 0.3);
-
-    LocalGeodesicFEFDStiffness<Basis,RigidBodyMotion<double,3> > localFDStiffness(&localStiffness);
-
-    RodAssembler<Basis,3> rodAssembler(basis, localFDStiffness);
-
-    std::cout << "Energy: " << rodAssembler.computeEnergy(x) << std::endl;
-
-    double pos = (argc==2) ? atof(argv[1]) : 0.5;
-
-    FieldVector<double,1> shapeGrad[2];
-    shapeGrad[0] = -1;
-    shapeGrad[1] =  1;
-
-    FieldVector<double,1> shapeFunction[2];
-    shapeFunction[0] = 1-pos;
-    shapeFunction[1] =  pos;
-
-    exit(0);
-    BlockVector<FieldVector<double,6> > rhs(x.size());
-    BCRSMatrix<FieldMatrix<double,6,6> > hessianMatrix;
-    MatrixIndexSet indices(grid.size(1), grid.size(1));
-    rodAssembler.getNeighborsPerVertex(indices);
-    indices.exportIdx(hessianMatrix);
-
-    rodAssembler.assembleGradientAndHessian(x, rhs, hessianMatrix);
-    
-    gradientFDCheck(x, rhs, rodAssembler);
-    hessianFDCheck(x, hessianMatrix, rodAssembler);
-        
-    // //////////////////////////////
- } catch (Exception& e) {
-
-    std::cout << e.what() << std::endl;
-
- }
diff --git a/test/rotationtest.cc b/test/rotationtest.cc
index ac4f2f6a..7b51c0a0 100644
--- a/test/rotationtest.cc
+++ b/test/rotationtest.cc
@@ -5,12 +5,7 @@
 
 #include <dune/common/fmatrix.hh>
 
-#warning Do not include onedgrid.hh
-#include <dune/grid/onedgrid.hh>
-
 #include <dune/gfe/rotation.hh>
-#warning Do not include rodlocalstiffness.hh
-#include <dune/gfe/rodlocalstiffness.hh>
 #include "valuefactory.hh"
 
 using namespace Dune;
@@ -94,123 +89,6 @@ void testDDExp()
     }
 }
 
-void testDerivativeOfInterpolatedPosition()
-{
-    std::array<Rotation<double,3>, 6> q;
-
-    FieldVector<double,3>  xAxis = {1,0,0};
-    FieldVector<double,3>  yAxis = {0,1,0};
-    FieldVector<double,3>  zAxis = {0,0,1};
-
-    q[0] = Rotation<double,3>(xAxis, 0);
-    q[1] = Rotation<double,3>(xAxis, M_PI/2);
-    q[2] = Rotation<double,3>(yAxis, 0);
-    q[3] = Rotation<double,3>(yAxis, M_PI/2);
-    q[4] = Rotation<double,3>(zAxis, 0);
-    q[5] = Rotation<double,3>(zAxis, M_PI/2);
-
-    double eps = 1e-7;
-
-    for (int i=0; i<6; i++) {
-
-        for (int j=0; j<6; j++) {
-
-            for (int k=0; k<7; k++) {
-
-                double s = k/6.0;
-
-                std::array<Quaternion<double>,6> fdGrad;
-
-                // ///////////////////////////////////////////////////////////
-                //   First: test the interpolated position
-                // ///////////////////////////////////////////////////////////
-                for (int l=0; l<3; l++) {
-                    SkewMatrix<double,3> forward(FieldVector<double,3>(0));
-                    SkewMatrix<double,3> backward(FieldVector<double,3>(0));
-                    forward.axial()[l] += eps;
-                    backward.axial()[l] -= eps;
-                    fdGrad[l] =  Rotation<double,3>::interpolate(q[i].mult(Rotation<double,3>::exp(forward)), q[j], s);
-                    fdGrad[l] -= Rotation<double,3>::interpolate(q[i].mult(Rotation<double,3>::exp(backward)), q[j], s);
-                    fdGrad[l] /= 2*eps;
-
-                    fdGrad[3+l] =  Rotation<double,3>::interpolate(q[i], q[j].mult(Rotation<double,3>::exp(forward)), s);
-                    fdGrad[3+l] -= Rotation<double,3>::interpolate(q[i], q[j].mult(Rotation<double,3>::exp(backward)), s);
-                    fdGrad[3+l] /= 2*eps;
-                }
-
-                // Compute analytical gradient
-                std::array<Quaternion<double>,6> grad;
-                RodLocalStiffness<OneDGrid,double>::interpolationDerivative(q[i], q[j], s, grad);
-
-                for (int l=0; l<6; l++) {
-                    Quaternion<double> diff = fdGrad[l];
-                    diff -= grad[l];
-                    if (diff.two_norm() > 1e-6) {
-                        std::cout << "Error in position " << l << ":  fd: " << fdGrad[l]
-                                  << "    analytical: " << grad[l] << std::endl;
-                    }
-
-                }
-
-                // ///////////////////////////////////////////////////////////
-                //   Second: test the interpolated velocity vector
-                // ///////////////////////////////////////////////////////////
-
-                for (const double intervalLength : {1.0/3, 2.0/3, 3.0/3, 4.0/3, 5.0/3, 6.0/3, 7.0/3})
-                {
-                    Dune::FieldVector<double,3> variation;
-
-                    for (int m=0; m<3; m++) {
-                        variation = 0;
-                        variation[m] = eps;
-                        fdGrad[m] =  Rotation<double,3>::interpolateDerivative(q[i].mult(Rotation<double,3>::exp(SkewMatrix<double,3>(variation))),
-                                                                               q[j], s);
-                        variation = 0;
-                        variation[m] = -eps;
-                        fdGrad[m] -= Rotation<double,3>::interpolateDerivative(q[i].mult(Rotation<double,3>::exp(SkewMatrix<double,3>(variation))),
-                                                                               q[j], s);
-                        fdGrad[m] /= 2*eps;
-
-                        variation = 0;
-                        variation[m] = eps;
-                        fdGrad[3+m] =  Rotation<double,3>::interpolateDerivative(q[i], q[j].mult(Rotation<double,3>::exp(SkewMatrix<double,3>(variation))), s);
-                        variation = 0;
-                        variation[m] = -eps;
-                        fdGrad[3+m] -= Rotation<double,3>::interpolateDerivative(q[i], q[j].mult(Rotation<double,3>::exp(SkewMatrix<double,3>(variation))), s);
-                        fdGrad[3+m] /= 2*eps;
-
-                    }
-
-                    // Scale the finite difference gradient with the interval length
-                    for (auto& parDer : fdGrad)
-                        parDer /= intervalLength;
-
-                    // Compute analytical velocity vector gradient
-                    RodLocalStiffness<OneDGrid,double>::interpolationVelocityDerivative(q[i], q[j], s*intervalLength, intervalLength, grad);
-
-                    for (int m=0; m<6; m++) {
-                        Quaternion<double> diff = fdGrad[m];
-                        diff -= grad[m];
-                        if (diff.two_norm() > 1e-6) {
-                            std::cout << "Error in velocity " << m
-                                      << ":  s = " << s << " of (" << intervalLength << ")"
-                                      << "   fd: " << fdGrad[m] << "    analytical: " << grad[m] << std::endl;
-                        }
-
-                    }
-
-                }
-
-            }
-
-        }
-
-    }
-
-}
-
-
-
 void testRotation(Rotation<double,3> q)
 {
     // Make sure it really is a unit quaternion
@@ -388,11 +266,6 @@ int main (int argc, char *argv[]) try
     // //////////////////////////////////////////////
     testDDExp();
 
-    // //////////////////////////////////////////////
-    //   Test derivative of interpolated position
-    // //////////////////////////////////////////////
-    testDerivativeOfInterpolatedPosition();
-
     return not passed;
 
  } catch (Exception& e) {
-- 
GitLab