diff --git a/dirneucoupling.cc b/dirneucoupling.cc
index 8a6a28eda09e3a8cbf77ee466532fe8fc5a6118b..4589e8a0b60319e46c55b9e7afa3b65a1b92968a 100644
--- a/dirneucoupling.cc
+++ b/dirneucoupling.cc
@@ -50,6 +50,113 @@ using std::vector;
 typedef vector<RigidBodyMotion<dim> >              RodSolutionType;
 typedef BlockVector<FieldVector<double, 6> >       RodDifferenceType;
 
+template <class GridView, class MatrixType, class VectorType>
+class LinearizedContinuumNeumannToDirichletMap
+{
+public:
+    
+    /** \brief Constructor 
+     * 
+     */
+    LinearizedContinuumNeumannToDirichletMap(const BoundaryPatchBase<GridView>& interface,
+                                             const VectorType& weakVolumeAndNeumannTerm,
+                                             const VectorType& dirichletValues,
+                                             const LinearLocalAssembler<typename GridView::Grid,
+                                                                  typename P1NodalBasis<GridView,double>::LocalFiniteElement,
+                                                                  typename P1NodalBasis<GridView,double>::LocalFiniteElement,
+                                                                  Dune::FieldMatrix<double,3,3> >* localAssembler,
+                                             const shared_ptr<LoopSolver<VectorType> >& solver
+                                            )
+    : interface_(interface),
+      weakVolumeAndNeumannTerm_(weakVolumeAndNeumannTerm),
+      dirichletValues_(dirichletValues),
+      solver_(solver),
+      localAssembler_(localAssembler)
+    {}
+    
+    /** \brief Map a Neumann value to a Dirichlet value
+     * 
+     * \param currentIterate The continuum configuration that we are linearizing about
+     * 
+     * \return The averaged Dirichlet value
+     */
+    RigidBodyMotion<3> apply(const VectorType& currentIterate,
+                             const Dune::FieldVector<double,3>& force,
+                             const Dune::FieldVector<double,3>& torque,
+                             const Dune::FieldVector<double,3>& centerOfTorque
+                            )
+    {
+        ////////////////////////////////////////////////////
+        //  Assemble the linearized problem
+        ////////////////////////////////////////////////////
+
+        /** \todo We are actually assembling standard linear elasticity,
+         * i.e. the linearization at zero
+         */
+        typedef P1NodalBasis<GridView,double> P1Basis;
+        P1Basis basis(interface_.gridView());
+        OperatorAssembler<P1Basis,P1Basis> assembler(basis, basis);
+
+        MatrixType stiffnessMatrix;
+        assembler.assemble(*localAssembler_, stiffnessMatrix);
+    
+    
+        /////////////////////////////////////////////////////////////////////
+        //  Turn the input force and torque into a Neumann boundary field
+        /////////////////////////////////////////////////////////////////////
+        VectorType neumannValues(stiffnessMatrix.N());
+        neumannValues = 0;
+
+        // 
+        computeAveragePressure<GridView>(force, torque, 
+                                         interface_, 
+                                         centerOfTorque,
+                                         neumannValues);
+
+        // The weak form of the Neumann data
+        VectorType rhs = weakVolumeAndNeumannTerm_;
+        assembleAndAddNeumannTerm<GridView, VectorType>(interface_,
+                                                        neumannValues,
+                                                        rhs);
+
+        //   Solve the Neumann problem for the continuum
+        VectorType x = dirichletValues_;
+        assert( (dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(solver_->iterationStep_)) );
+        dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(solver_->iterationStep_)->setProblem(stiffnessMatrix, x, rhs);
+        
+        //solver.preprocess();
+        solver_->iterationStep_->preprocess();
+        
+        solver_->solve();
+        
+        x = solver_->iterationStep_->getSol();
+        
+        std::cout << "x:\n" << x << std::endl;
+
+        //  Average the continuum displacement on the coupling boundary
+        RigidBodyMotion<3> averageInterface;
+        computeAverageInterface(interface_, x, averageInterface);
+        
+        std::cout << "Average interface: " << averageInterface << std::endl;
+        
+        return averageInterface;
+     }
+     
+private:
+    
+    const VectorType& weakVolumeAndNeumannTerm_;
+    
+    const VectorType& dirichletValues_;
+    
+    const shared_ptr<LoopSolver<VectorType> > solver_;
+    
+    const BoundaryPatchBase<GridView>& interface_;
+    
+    const LinearLocalAssembler<typename GridView::Grid,
+                         typename P1NodalBasis<GridView,double>::LocalFiniteElement,
+                         typename P1NodalBasis<GridView,double>::LocalFiniteElement,
+                         Dune::FieldMatrix<double,3,3> >* localAssembler_;
+};
 
 int main (int argc, char *argv[]) try
 {
@@ -211,7 +318,7 @@ int main (int argc, char *argv[]) try
     //   Assemble 3d linear elasticity problem
     // //////////////////////////////////////////
 
-    typedef Q1NodalBasis<GridType::LeafGridView,double> FEBasis;
+    typedef P1NodalBasis<GridType::LeafGridView,double> FEBasis;
     FEBasis basis(grid.leafView());
     OperatorAssembler<FEBasis,FEBasis> assembler(basis, basis);
 
@@ -307,12 +414,12 @@ int main (int argc, char *argv[]) try
 
     EnergyNorm<MatrixType, VectorType> energyNorm(multigridStep);
 
-    LoopSolver<VectorType> solver(&multigridStep,
-                                                   // IPOpt doesn't like to be started in the solution
-                                                   (numLevels!=1) ? multigridIterations : 1,
-                                                   mgTolerance,
-                                                   &energyNorm,
-                                                   Solver::QUIET);
+    shared_ptr<LoopSolver<VectorType> > solver = shared_ptr<LoopSolver<VectorType> >( new LoopSolver<VectorType>(&multigridStep,
+                                                                                                                // IPOpt doesn't like to be started in the solution
+                                                                                                                (numLevels!=1) ? multigridIterations : 1,
+                                                                                                                mgTolerance,
+                                                                                                                &energyNorm,
+                                                                                                                Solver::QUIET) );
 
     // ////////////////////////////////////
     //   Create the transfer operators
@@ -405,10 +512,10 @@ int main (int argc, char *argv[]) try
             // ///////////////////////////////////////////////////////////
             multigridStep.setProblem(stiffnessMatrix3d, x3d, rhs3d, grid.maxLevel()+1);
         
-            solver.preprocess();
+            solver->preprocess();
             multigridStep.preprocess();
         
-            solver.solve();
+            solver->solve();
         
             x3d = multigridStep.getSol();
 
@@ -478,10 +585,10 @@ int main (int argc, char *argv[]) try
             // Solve the Dirichlet problem
             multigridStep.setProblem(stiffnessMatrix3d, x3d, rhs3d, grid.maxLevel()+1);
         
-            solver.preprocess();
+            solver->preprocess();
             multigridStep.preprocess();
         
-            solver.solve();
+            solver->solve();
         
             x3d = multigridStep.getSol();
             
@@ -515,32 +622,13 @@ int main (int argc, char *argv[]) try
                 //  of the continuum.
                 ////////////////////////////////////////////////////////////////////
                 
-                VectorType neumannValues(rhs3d.size());
-
-                // Using that index 0 is always the left boundary for a uniformly refined OneDGrid
-                computeAveragePressure<GridType::LevelGridView>(resultantForce, resultantTorque, 
-                                              interfaceBoundary[grid.maxLevel()], 
-                                              rodX[0].r,
-                                              neumannValues);
-
-                rhs3d = 0;
-                assembleAndAddNeumannTerm<GridType::LevelGridView, VectorType>(interfaceBoundary[grid.maxLevel()],
-                                                        neumannValues,
-                                                        rhs3d);
-
-                //   Solve the Neumann problem for the continuum
-                multigridStep.setProblem(stiffnessMatrix3d, x3d, rhs3d, grid.maxLevel()+1);
-        
-                solver.preprocess();
-                multigridStep.preprocess();
-        
-                solver.solve();
-        
-                x3d = multigridStep.getSol();
-
-                //  Average the continuum displacement on the coupling boundary
-                computeAverageInterface(interfaceBoundary[toplevel], x3d, averageInterface);
-                
+                LinearizedContinuumNeumannToDirichletMap<GridType::LevelGridView,MatrixType,VectorType>
+                        linContNtDMap(interfaceBoundary.back(),
+                                      rhs3d,
+                                      dirichletValues.back(),
+                                      &localAssembler,
+                                      solver);
+                averageInterface = linContNtDMap.apply(x3d, residualForce, residualTorque, rodX[0].r);
                 
             } else if (preconditioner=="NeumannDirichlet") {