diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..8e88968d8a341cb5c265d56e0042305040387be3
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,17 @@
+# $Id: Makefile.am 1867 2007-12-31 15:45:00Z sander@PCPOOL.MI.FU-BERLIN.DE $
+
+# possible options
+LDADD = $(UG_LDFLAGS) $(AMIRAMESH_LDFLAGS) $(UG_LIBS) $(AMIRAMESH_LIBS)
+AM_CPPFLAGS += $(UG_CPPFLAGS) $(AMIRAMESH_CPPFLAGS) -Wall
+
+check_PROGRAMS = frameinvariancetest rotationtest fdcheck
+
+frameinvariancetest_SOURCES = frameinvariancetest.cc
+
+rotationtest_SOURCES = rotationtest.cc
+
+fdcheck_SOURCES = fdcheck.cc
+
+# don't follow the full GNU-standard
+# we need automake 1.5
+AUTOMAKE_OPTIONS = foreign 1.5
diff --git a/test/fdcheck.cc b/test/fdcheck.cc
new file mode 100644
index 0000000000000000000000000000000000000000..079caa45b5ef85188ca94d04951b4adcaf6b5cb9
--- /dev/null
+++ b/test/fdcheck.cc
@@ -0,0 +1,326 @@
+#include <config.h>
+
+#include <dune/common/bitfield.hh>
+#include <dune/common/configparser.hh>
+
+#include <dune/grid/onedgrid.hh>
+
+#include <dune/istl/io.hh>
+
+
+#include "../common/iterativesolver.hh"
+
+#include "src/configuration.hh"
+#include "src/quaternion.hh"
+#include "src/rodassembler.hh"
+
+#include "fdcheck.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 testDDExp()
+{
+    std::tr1::array<FieldVector<double,3>, 125> v;
+    int ct = 0;
+    double eps = 1e-4;
+
+    for (int i=-2; i<3; i++)
+        for (int j=-2; j<3; j++)
+            for (int k=-2; k<3; k++) {
+                v[ct][0] = i;
+                v[ct][1] = j;
+                v[ct][2] = k;
+                ct++;
+            }
+
+    for (size_t i=0; i<v.size(); i++) {
+
+        // Compute FD approximation of second derivative of exp
+        Dune::array<Dune::FieldMatrix<double,3,3>, 4> fdDDExp;
+
+        for (int j=0; j<3; j++) {
+
+            for (int k=0; k<3; k++) {
+
+                if (j==k) {
+
+                    Quaternion<double> forwardQ  = Quaternion<double>::exp(v[i][0] + (j==0)*eps,
+                                                                           v[i][1] + (j==1)*eps,
+                                                                           v[i][2] + (j==2)*eps);
+                    Quaternion<double> centerQ   = Quaternion<double>::exp(v[i][0],v[i][1],v[i][2]);
+                    Quaternion<double> backwardQ = Quaternion<double>::exp(v[i][0] - (j==0)*eps,
+                                                                           v[i][1] - (j==1)*eps,
+                                                                           v[i][2] - (j==2)*eps);
+
+                    for (int l=0; l<4; l++)
+                        fdDDExp[l][j][j] = (forwardQ[l] - 2*centerQ[l] + backwardQ[l]) / (eps*eps);
+
+
+                } else {
+
+                    FieldVector<double,3> ffV = v[i];      ffV[j] += eps;     ffV[k] += eps;
+                    FieldVector<double,3> fbV = v[i];      fbV[j] += eps;     fbV[k] -= eps;
+                    FieldVector<double,3> bfV = v[i];      bfV[j] -= eps;     bfV[k] += eps;
+                    FieldVector<double,3> bbV = v[i];      bbV[j] -= eps;     bbV[k] -= eps;
+
+                    Quaternion<double> forwardForwardQ = Quaternion<double>::exp(ffV);
+                    Quaternion<double> forwardBackwardQ = Quaternion<double>::exp(fbV);
+                    Quaternion<double> backwardForwardQ = Quaternion<double>::exp(bfV);
+                    Quaternion<double> backwardBackwardQ = Quaternion<double>::exp(bbV);
+
+                    for (int l=0; l<4; l++)
+                        fdDDExp[l][j][k] = (forwardForwardQ[l] + backwardBackwardQ[l]
+                                            - forwardBackwardQ[l] - backwardForwardQ[l]) / (4*eps*eps);
+
+                }
+
+            }
+
+        }
+
+        // Compute analytical second derivative of exp
+        Dune::array<Dune::FieldMatrix<double,3,3>, 4> ddExp;
+        Quaternion<double>::DDexp(v[i], ddExp);
+
+        for (int m=0; m<4; m++)
+            for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                    if ( std::abs(fdDDExp[m][j][k] - ddExp[m][j][k]) > eps) {
+                        std::cout << "Error at v = " << v[i] 
+                                  << "[" << m << ", " << j << ", " << k << "] " 
+                                  << "    fd: " << fdDDExp[m][j][k]
+                                  << "    analytical: " << ddExp[m][j][k] << std::endl;
+                    }
+    }
+}
+
+void testDerivativeOfInterpolatedPosition()
+{
+    std::tr1::array<Quaternion<double>, 6> q;
+
+    FieldVector<double,3>  xAxis(0);    xAxis[0] = 1;
+    FieldVector<double,3>  yAxis(0);    yAxis[1] = 1;
+    FieldVector<double,3>  zAxis(0);    zAxis[2] = 1;
+
+    q[0] = Quaternion<double>(xAxis, 0);
+    q[1] = Quaternion<double>(xAxis, M_PI/2);
+    q[2] = Quaternion<double>(yAxis, 0);
+    q[3] = Quaternion<double>(yAxis, M_PI/2);
+    q[4] = Quaternion<double>(zAxis, 0);
+    q[5] = Quaternion<double>(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::tr1::array<Quaternion<double>,6> fdGrad;
+
+                // ///////////////////////////////////////////////////////////
+                //   First: test the interpolated position
+                // ///////////////////////////////////////////////////////////
+                fdGrad[0] =  Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(eps,0,0)), q[j], s);
+                fdGrad[0] -= Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(-eps,0,0)), q[j], s);
+                fdGrad[0] /= 2*eps;
+
+                fdGrad[1] =  Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(0,eps,0)), q[j], s);
+                fdGrad[1] -= Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(0,-eps,0)), q[j], s);
+                fdGrad[1] /= 2*eps;
+
+                fdGrad[2] =  Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(0,0,eps)), q[j], s);
+                fdGrad[2] -= Quaternion<double>::interpolate(q[i].mult(Quaternion<double>::exp(0,0,-eps)), q[j], s);
+                fdGrad[2] /= 2*eps;
+
+                fdGrad[3] =  Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(eps,0,0)), s);
+                fdGrad[3] -= Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(-eps,0,0)), s);
+                fdGrad[3] /= 2*eps;
+
+                fdGrad[4] =  Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(0,eps,0)), s);
+                fdGrad[4] -= Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(0,-eps,0)), s);
+                fdGrad[4] /= 2*eps;
+
+                fdGrad[5] =  Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(0,0,eps)), s);
+                fdGrad[5] -= Quaternion<double>::interpolate(q[i], q[j].mult(Quaternion<double>::exp(0,0,-eps)), s);
+                fdGrad[5] /= 2*eps;
+
+                // Compute analytical gradient
+                std::tr1::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 (int l=1; l<7; l++) {
+
+                    double intervalLength = l/(double(3));
+                    
+                    fdGrad[0] =  Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(eps,0,0)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[0] -= Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(-eps,0,0)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[0] /= 2*eps;
+                    
+                    fdGrad[1] =  Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(0,eps,0)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[1] -= Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(0,-eps,0)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[1] /= 2*eps;
+                    
+                    fdGrad[2] =  Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(0,0,eps)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[2] -= Quaternion<double>::interpolateDerivative(q[i].mult(Quaternion<double>::exp(0,0,-eps)), 
+                                                                           q[j], s, intervalLength);
+                    fdGrad[2] /= 2*eps;
+                    
+                    fdGrad[3] =  Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(eps,0,0)), s, intervalLength);
+                    fdGrad[3] -= Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(-eps,0,0)), s, intervalLength);
+                    fdGrad[3] /= 2*eps;
+                    
+                    fdGrad[4] =  Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(0,eps,0)), s, intervalLength);
+                    fdGrad[4] -= Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(0,-eps,0)), s, intervalLength);
+                    fdGrad[4] /= 2*eps;
+                    
+                    fdGrad[5] =  Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(0,0,eps)), s, intervalLength);
+                    fdGrad[5] -= Quaternion<double>::interpolateDerivative(q[i], q[j].mult(Quaternion<double>::exp(0,0,-eps)), s, intervalLength);
+                    fdGrad[5] /= 2*eps;
+                    
+                    // Compute analytical velocity vector gradient
+                    RodLocalStiffness<OneDGrid,double>::interpolationVelocityDerivative(q[i], q[j], s, 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;
+                        }
+                        
+                    }
+
+                }
+
+            }
+
+        }
+
+    }
+
+}
+
+
+int main (int argc, char *argv[]) try
+{
+    // //////////////////////////////////////////////
+    //   Test second derivative of exp
+    // //////////////////////////////////////////////
+    testDDExp();
+
+    // //////////////////////////////////////////////
+    //   Test derivative of interpolated position
+    // //////////////////////////////////////////////
+    testDerivativeOfInterpolatedPosition();
+    exit(0);
+    typedef std::vector<Configuration> SolutionType;
+
+    // ///////////////////////////////////////
+    //    Create the grid
+    // ///////////////////////////////////////
+    typedef OneDGrid GridType;
+    GridType grid(1, 0, 1);
+
+    SolutionType x(grid.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
+    // ///////////////////////////////////////////
+    RodAssembler<GridType> rodAssembler(grid);
+    //rodAssembler.setShapeAndMaterial(0.01, 0.0001, 0.0001, 2.5e5, 0.3);
+    //rodAssembler.setParameters(0,0,0,0,1,0);
+    rodAssembler.setParameters(0,0,100,0,0,0);
+
+    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.assembleGradient(x, rhs);
+    rodAssembler.assembleMatrix(x, hessianMatrix);
+    
+    gradientFDCheck(x, rhs, rodAssembler);
+    hessianFDCheck(x, hessianMatrix, rodAssembler);
+        
+    // //////////////////////////////
+ } catch (Exception e) {
+
+    std::cout << e << std::endl;
+
+ }
diff --git a/test/fdcheck.hh b/test/fdcheck.hh
new file mode 100644
index 0000000000000000000000000000000000000000..09159862202a925217a4dbad7e623813f17b0e23
--- /dev/null
+++ b/test/fdcheck.hh
@@ -0,0 +1,479 @@
+#ifndef ASSEMBLER_FINITE_DIFFERENCE_CHECK
+#define ASSEMBLER_FINITE_DIFFERENCE_CHECK
+
+#define ABORT_ON_ERROR
+
+void infinitesimalVariation(Configuration& c, double eps, int i)
+{
+    if (i<3)
+        c.r[i] += eps;
+    else
+        c.q = c.q.mult(Quaternion<double>::exp((i==3)*eps, 
+                                               (i==4)*eps, 
+                                               (i==5)*eps));
+}
+
+template <class GridType>
+void strainFD(const std::vector<Configuration>& x, 
+              double pos,
+              Dune::array<Dune::FieldMatrix<double,2,6>, 6>& fdStrainDerivatives,
+              const RodAssembler<GridType>& assembler) 
+{
+    assert(x.size()==2);
+    double eps = 1e-8;
+
+    typename GridType::template Codim<0>::EntityPointer element = assembler.grid_->template leafbegin<0>();
+
+    // ///////////////////////////////////////////////////////////
+    //   Compute gradient by finite-difference approximation
+    // ///////////////////////////////////////////////////////////
+    std::vector<Configuration> forwardSolution = x;
+    std::vector<Configuration> 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 GridType>
+void strain2ndOrderFD(const std::vector<Configuration>& x, 
+                      double pos,
+                      Dune::array<Dune::Matrix<Dune::FieldMatrix<double,6,6> >, 3>& translationDer,
+                      Dune::array<Dune::Matrix<Dune::FieldMatrix<double,3,3> >, 3>& rotationDer,
+                      const RodAssembler<GridType>& assembler) 
+{
+    assert(x.size()==2);
+    double eps = 1e-3;
+
+    typename GridType::template Codim<0>::EntityPointer element = assembler.grid_->template leafbegin<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<Configuration> forwardSolution = x;
+    std::vector<Configuration> backwardSolution = x;
+    
+    std::vector<Configuration> forwardForwardSolution = x;
+    std::vector<Configuration> forwardBackwardSolution = x;
+    std::vector<Configuration> backwardForwardSolution = x;
+    std::vector<Configuration> 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<Configuration>& x, 
+                       double pos,
+                       Dune::FieldVector<double,1> shapeGrad[2],
+                       Dune::FieldVector<double,1> shapeFunction[2],
+                       Dune::array<Dune::Matrix<Dune::FieldMatrix<double,6,6> >, 3>& translationDer,
+                       Dune::array<Dune::Matrix<Dune::FieldMatrix<double,3,3> >, 3>& rotationDer,
+                       const RodAssembler<GridType>& 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<Configuration> forwardSolution = x;
+    std::vector<Configuration> 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);
+                
+            Dune::array<Dune::FieldMatrix<double,2,6>, 6> forwardStrainDer;
+            assembler.strainDerivative(forwardSolution, pos, shapeGrad, shapeFunction, forwardStrainDer);
+
+            Dune::array<Dune::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
+    // ///////////////////////////////////////////////////////////
+    FieldVector<double,3> forward;
+    FieldVector<double,3> backward;
+    
+    FieldVector<double,3> forwardForward;
+    FieldVector<double,3> forwardBackward;
+    FieldVector<double,3> backwardForward;
+    FieldVector<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[i]  += eps;
+                backward[i] -= eps;
+                
+                // Second derivative
+                //                         fdHessian[j][k] = (assembler.computeEnergy(forward) 
+                //                                            - 2*assembler.computeEnergy(x) 
+                //                                            + assembler.computeEnergy(backward)) / (eps*eps);
+                
+                hessian  = Quaternion<double>::exp(forward);
+                hessian += Quaternion<double>::exp(backward);
+                hessian.axpy(-2, Quaternion<double>::exp(0,0,0));
+                hessian /= eps*eps;
+                
+            } else {
+                
+                forwardForward = forwardBackward = 0;
+                backwardForward = backwardBackward = 0;
+
+                forwardForward[i]   += eps;
+                forwardForward[j]   += eps;
+                forwardBackward[i]  += eps;
+                forwardBackward[j]  -= eps;
+                backwardForward[i]  -= eps;
+                backwardForward[j]  += eps;
+                backwardBackward[i] -= eps;
+                backwardBackward[j] -= eps;
+                
+                
+                hessian  = Quaternion<double>::exp(forwardForward);
+                hessian += Quaternion<double>::exp(backwardBackward);
+                hessian -= Quaternion<double>::exp(forwardBackward);
+                hessian -= Quaternion<double>::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<Configuration>& x, 
+                     const Dune::BlockVector<Dune::FieldVector<double,6> >& gradient, 
+                     const RodAssembler<GridType>& 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<Configuration> forwardSolution = x;
+    std::vector<Configuration> 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<Configuration>& x, 
+                    const Dune::BCRSMatrix<Dune::FieldMatrix<double,6,6> >& hessian, 
+                    const RodAssembler<GridType>& 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<Configuration> forwardSolution = x;
+    std::vector<Configuration> backwardSolution = x;
+
+    std::vector<Configuration> forwardForwardSolution = x;
+    std::vector<Configuration> forwardBackwardSolution = x;
+    std::vector<Configuration> backwardForwardSolution = x;
+    std::vector<Configuration> backwardBackwardSolution = x;
+    
+
+    // ///////////////////////////////////////////////////////////////
+    //   Loop over all blocks of the outer matrix
+    // ///////////////////////////////////////////////////////////////
+    for (int 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
+
+}
+
+#endif
diff --git a/test/frameinvariancetest.cc b/test/frameinvariancetest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3f8b7f848b0d590809fc2635e2c2235951c7a06e
--- /dev/null
+++ b/test/frameinvariancetest.cc
@@ -0,0 +1,107 @@
+#include <config.h>
+
+//#define DUNE_EXPRESSIONTEMPLATES
+#include <dune/grid/onedgrid.hh>
+
+#include <dune/istl/io.hh>
+
+#include <dune/common/bitfield.hh>
+#include "src/quaternion.hh"
+
+#include "src/rodassembler.hh"
+
+#include "src/configuration.hh"
+#include "src/rodwriter.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;
+using std::string;
+
+
+int main (int argc, char *argv[]) try
+{
+    // Some types that I need
+    typedef BCRSMatrix<FieldMatrix<double, blocksize, blocksize> > MatrixType;
+    typedef BlockVector<FieldVector<double, blocksize> >           CorrectionType;
+    typedef std::vector<Configuration>                              SolutionType;
+
+    // Problem settings
+    const int numRodBaseElements = 1;
+    
+    // ///////////////////////////////////////
+    //    Create the grid
+    // ///////////////////////////////////////
+    typedef OneDGrid GridType;
+    GridType grid(numRodBaseElements, 0, 1);
+
+    SolutionType x(grid.size(1));
+
+    // //////////////////////////
+    //   Initial solution
+    // //////////////////////////
+
+    for (size_t i=0; i<x.size(); i++) {
+        x[i].r[0] = 0;    // x
+        x[i].r[1] = 0;
+        x[i].r[2] = double(i)/(x.size()-1);                 // z
+        x[i].q = Quaternion<double>::identity();
+        //x[i].q = Quaternion<double>(zAxis, (double(i)*M_PI)/(2*(x.size()-1)) );
+    }
+
+    FieldVector<double,3> zAxis(0);  zAxis[2]=1;
+    x.back().q = Quaternion<double>(zAxis, M_PI/4);
+
+    // /////////////////////////////////////////////////////////////////////
+    //   Create a second, rotated copy of the configuration
+    // /////////////////////////////////////////////////////////////////////
+
+    FieldVector<double,3> displacement;
+    displacement[0] = 0;
+    displacement[1] = 0;
+    displacement[2] = 0;
+
+    FieldVector<double,3> axis(0);  axis[0]=1;
+    Quaternion<double> rotation(axis,M_PI/2);
+//     std::cout << "Rotation:" << std::endl;
+//     std::cout << "director 0:  " << rotation.director(0) << std::endl;
+//     std::cout << "director 1:  " << rotation.director(1) << std::endl;
+//     std::cout << "director 2:  " << rotation.director(2) << std::endl;
+
+    SolutionType rotatedX = x;
+
+    for (size_t i=0; i<rotatedX.size(); i++) {
+
+        rotatedX[i].r = rotation.rotate(x[i].r);
+        rotatedX[i].r += displacement;
+
+        rotatedX[i].q = rotation.mult(x[i].q);
+
+//         std::cout << "Vertex " << i << ": (" << rotatedX[i].r << ")" << std::endl;
+// //         std::cout << "Right boundary orientation:" << std::endl;
+//         std::cout << "director 0:  " << rotatedX[i].q.director(0) << std::endl;
+//         std::cout << "director 1:  " << rotatedX[i].q.director(1) << std::endl;
+//         std::cout << "director 2:  " << rotatedX[i].q.director(2) << std::endl;
+    }
+
+    writeRod(x,"rod");
+    writeRod(rotatedX, "rotated");
+
+    RodLocalStiffness<GridType,double> assembler;
+
+    for (int i=1; i<2; i++) {
+
+        double p = double(i)/2;
+
+        assembler.getStrain(x,grid.lbegin<0>(0), p);
+        assembler.getStrain(rotatedX,grid.lbegin<0>(0), p);
+
+    }
+
+ } catch (Exception e) {
+
+    std::cout << e << std::endl;
+
+ }
diff --git a/test/rotationtest.cc b/test/rotationtest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f781aa2eb84844adfcca91c2128801ea848cd075
--- /dev/null
+++ b/test/rotationtest.cc
@@ -0,0 +1,124 @@
+#include <config.h>
+
+#include <iostream>
+
+#include <dune/common/fmatrix.hh>
+
+#include "src/quaternion.hh"
+#include "src/svd.hh"
+
+using namespace Dune;
+
+void testUnitQuaternion(Quaternion<double> q)
+{
+    // Make sure it really is a unit quaternion
+    q.normalize();
+
+    assert(std::abs(1-q.two_norm()) < 1e-12);
+
+    // Turn it into a matrix
+    FieldMatrix<double,3,3> matrix;
+    q.matrix(matrix);
+
+    // make sure it is an orthogonal matrix
+    if (std::abs(1-matrix.determinant()) > 1e-12 )
+        DUNE_THROW(Exception, "Expected determinant 1, but the computed value is " << matrix.determinant());
+
+    assert( std::abs( matrix[0]*matrix[1] ) < 1e-12 );
+    assert( std::abs( matrix[0]*matrix[2] ) < 1e-12 );
+    assert( std::abs( matrix[1]*matrix[2] ) < 1e-12 );
+
+    // Turn the matrix back into a quaternion, and check whether it is the same one
+    // Since the quaternions form a double covering of SO(3), we may either get q back
+    // or -q.  We have to check both.
+    Quaternion<double> newQ;
+    newQ.set(matrix);
+
+    Quaternion<double> diff = newQ;
+    diff -= q;
+
+    Quaternion<double> sum  = newQ;
+    sum += q;
+
+    if (diff.infinity_norm() > 1e-12 && sum.infinity_norm() > 1e-12)
+        DUNE_THROW(Exception, "Backtransformation failed for " << q << ". ");
+
+    // //////////////////////////////////////////////////////
+    //   Check the director vectors
+    // //////////////////////////////////////////////////////
+
+    for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++)
+            assert( std::abs(matrix[i][j] - q.director(j)[i]) < 1e-12 );
+
+    // //////////////////////////////////////////////////////
+    //   Check multiplication with another unit quaternion
+    // //////////////////////////////////////////////////////
+
+    for (int i=-2; i<2; i++)
+        for (int j=-2; j<2; j++)
+            for (int k=-2; k<2; k++)
+                for (int l=-2; l<2; l++)
+                    if (i!=0 || j!=0 || k!=0 || l!=0) {
+
+                        Quaternion<double> q2(i,j,k,l);
+                        q2.normalize();
+
+                        // set up corresponding rotation matrix
+                        FieldMatrix<double,3,3> q2Matrix;
+                        q2.matrix(q2Matrix);
+
+                        // q2 = q2 * q   Quaternion multiplication
+                        q2 = q2.mult(q);
+
+                        // q2 = q2 * q   Matrix multiplication
+                        q2Matrix.rightmultiply(matrix);
+
+                        FieldMatrix<double,3,3> productMatrix;
+                        q2.matrix(productMatrix);
+
+                        // Make sure we got identical results
+                        productMatrix -= q2Matrix;
+                        assert(productMatrix.infinity_norm() < 1e-10);
+
+                    }
+
+    // ////////////////////////////////////////////////////////////////
+    //   Check the operators 'B' that create an orthonormal basis of H
+    // ////////////////////////////////////////////////////////////////
+
+    Quaternion<double> Bq[4];
+    Bq[0] = q;
+    Bq[1] = q.B(0);
+    Bq[2] = q.B(1);
+    Bq[3] = q.B(2);
+
+    for (int i=0; i<4; i++) {
+
+        for (int j=0; j<4; j++) {
+
+            double prod = Bq[i]*Bq[j];
+            assert( std::abs( prod - (i==j) ) < 1e-6 );
+
+        }
+
+    }
+
+}
+
+int main (int argc, char *argv[]) try
+{
+    // Make a few random unit quaternions and pipe them into the test
+    for (int i=-5; i<5; i++)
+        for (int j=-5; j<5; j++)
+            for (int k=-5; k<5; k++)
+                for (int l=-5; l<5; l++)
+                    if (i!=0 || j!=0 || k!=0 || l!=0)
+                        testUnitQuaternion(Quaternion<double>(i,j,k,l));
+    
+
+ } catch (Exception e) {
+
+    std::cout << e << std::endl;
+
+ }