From d82819576ee1a8d4edf1a125631e634b20e29dbd Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Sat, 2 Apr 2011 15:53:03 +0000
Subject: [PATCH] Start implementing an iteration step class for fixed-point
 iterations

So far this only works for a single rod and a single continuum

[[Imported from SVN: r7056]]
---
 dune/gfe/coupling/Makefile.am                 |   1 +
 .../coupling/rodcontinuumfixedpointstep.hh    | 818 ++++++++++++++++++
 2 files changed, 819 insertions(+)
 create mode 100644 dune/gfe/coupling/rodcontinuumfixedpointstep.hh

diff --git a/dune/gfe/coupling/Makefile.am b/dune/gfe/coupling/Makefile.am
index 85f1f6fe..27bfbff2 100644
--- a/dune/gfe/coupling/Makefile.am
+++ b/dune/gfe/coupling/Makefile.am
@@ -5,6 +5,7 @@ SUBDIRS =
 
 srcincludedir = $(includedir)/dune/common/coupling
 srcinclude_HEADERS = rodcontinuumcomplex.hh \
+                     rodcontinuumfixedpointstep.hh \
                      rodcontinuumsteklovpoincarestep.hh
 
 include $(top_srcdir)/am/global-rules
diff --git a/dune/gfe/coupling/rodcontinuumfixedpointstep.hh b/dune/gfe/coupling/rodcontinuumfixedpointstep.hh
new file mode 100644
index 00000000..60b55fb4
--- /dev/null
+++ b/dune/gfe/coupling/rodcontinuumfixedpointstep.hh
@@ -0,0 +1,818 @@
+#ifndef ROD_CONTINUUM_FIXED_POINT_STEP_HH
+#define ROD_CONTINUUM_FIXED_POINT_STEP_HH
+
+#include <vector>
+
+// #include <dune/common/shared_ptr.hh>
+// #include <dune/common/fvector.hh>
+// #include <dune/common/fmatrix.hh>
+// #include <dune/common/bitsetvector.hh>
+// 
+// #include <dune/istl/bcrsmatrix.hh>
+// #include <dune/istl/bvector.hh>
+// 
+#include <dune/fufem/assemblers/boundaryfunctionalassembler.hh>
+#include <dune/fufem/assemblers/localassemblers/neumannboundaryassembler.hh>
+
+#include <dune/gfe/coupling/rodcontinuumcomplex.hh>
+
+
+template <class RodGridType, class ContinuumGridType>
+class RodContinuumFixedPointStep
+{
+    static const int dim = ContinuumGridType::dimension;
+    
+    // The type used for rod configurations
+    typedef std::vector<RigidBodyMotion<dim> > RodConfigurationType;
+
+    // The type used for continuum configurations
+    typedef Dune::BlockVector<Dune::FieldVector<double,dim> > VectorType;
+    typedef Dune::BlockVector<Dune::FieldVector<double,dim> > ContinuumConfigurationType;
+    
+    typedef Dune::BlockVector<Dune::FieldVector<double,6> >  RodCorrectionType;
+    
+    typedef Dune::BCRSMatrix<Dune::FieldMatrix<double,3,3> > MatrixType;
+                
+    typedef typename P1NodalBasis<typename ContinuumGridType::LeafGridView,double>::LocalFiniteElement ContinuumLocalFiniteElement;
+    
+public:
+    
+    /** \brief Constructor for a complex with one rod and one continuum */
+    RodContinuumFixedPointStep(const RodContinuumComplex<RodGridType,ContinuumGridType>& complex,
+                                    double damping,
+                                    RodAssembler<typename RodGridType::LeafGridView,3>* rodAssembler,
+                                    RiemannianTrustRegionSolver<RodGridType,RigidBodyMotion<3> >* rodSolver,
+                                    const MatrixType* stiffnessMatrix3d,
+                                    const Dune::shared_ptr< ::LoopSolver<VectorType> > solver)
+      : complex_(complex),
+        damping_(damping)
+    {
+        rods_["rod"].assembler_      = rodAssembler;
+        rods_["rod"].solver_         = rodSolver;
+
+        continua_["continuum"].stiffnessMatrix_ = stiffnessMatrix3d;
+        continua_["continuum"].solver_          = solver;
+
+        mergeRodDirichletAndCouplingBoundaries();
+        mergeContinuumDirichletAndCouplingBoundaries();
+    }
+
+#if 0
+    /** \brief Constructor for a general complex */
+    RodContinuumFixedPointStep(const RodContinuumComplex<RodGridType,ContinuumGridType>& complex,
+                                    const std::string& preconditioner,
+                                    const Dune::array<double,2>& alpha,
+                                    double richardsonDamping,
+                                    const std::map<std::string,RodAssembler<typename RodGridType::LeafGridView,3>*>& rodAssembler,
+                                    const std::map<std::string,RodLocalStiffness<typename RodGridType::LeafGridView,double>*>& rodLocalStiffness,
+                                    const std::map<std::string,RiemannianTrustRegionSolver<RodGridType,RigidBodyMotion<3> >*>& rodSolver,
+                                    const std::map<std::string,const MatrixType*>& stiffnessMatrix3d,
+                                    const std::map<std::string, const Dune::shared_ptr< ::LoopSolver<VectorType> > >& solver,
+                                    const std::map<std::string,LinearLocalAssembler<ContinuumGridType, 
+                                                                                    ContinuumLocalFiniteElement, 
+                                                                                    ContinuumLocalFiniteElement,
+                                                                                    Dune::FieldMatrix<double,dim,dim> >*>& localAssembler)
+      : complex_(complex),
+        preconditioner_(preconditioner),
+        alpha_(alpha),
+        richardsonDamping_(richardsonDamping),
+        neumannRegularization_(0)
+    {
+        ///////////////////////////////////////////////////////////////////////////////////
+        //  Rod-related data
+        ///////////////////////////////////////////////////////////////////////////////////
+        for (typename std::map<std::string,RodAssembler<typename RodGridType::LeafGridView,3>*>::const_iterator it = rodAssembler.begin();
+             it != rodAssembler.end();
+             ++it)
+            rods_[it->first].assembler_ = it->second;
+        
+        for (typename std::map<std::string,RodLocalStiffness<typename RodGridType::LeafGridView,double>*>::const_iterator it = rodLocalStiffness.begin();
+             it != rodLocalStiffness.end();
+             ++it)
+            rods_[it->first].localStiffness_ = it->second;
+        
+        for (typename std::map<std::string,RiemannianTrustRegionSolver<RodGridType,RigidBodyMotion<3> >*>::const_iterator it = rodSolver.begin();
+             it != rodSolver.end();
+             ++it)
+            rods_[it->first].solver_ = it->second;
+
+        ///////////////////////////////////////////////////////////////////////////////////
+        //  Continuum-related data
+        ///////////////////////////////////////////////////////////////////////////////////
+        for (typename std::map<std::string,const MatrixType*>::const_iterator it = stiffnessMatrix3d.begin();
+             it != stiffnessMatrix3d.end();
+             ++it)
+            continua_[it->first].stiffnessMatrix_ = it->second;
+        
+        for (typename std::map<std::string,const Dune::shared_ptr< ::LoopSolver<VectorType> > >::const_iterator it = solver.begin();
+             it != solver.end();
+             ++it)
+            continua_[it->first].solver_ = it->second;
+        
+        for (typename std::map<std::string,LinearLocalAssembler<ContinuumGridType, 
+                                                                ContinuumLocalFiniteElement, 
+                                                                ContinuumLocalFiniteElement,
+                                                                Dune::FieldMatrix<double,dim,dim> >*>::const_iterator it = localAssembler.begin();
+             it != localAssembler.end();
+             ++it)
+            continua_[it->first].localAssembler_ = it->second;
+
+        mergeRodDirichletAndCouplingBoundaries();
+        mergeContinuumDirichletAndCouplingBoundaries();
+    }
+#endif
+
+    void mergeRodDirichletAndCouplingBoundaries();
+
+    void mergeContinuumDirichletAndCouplingBoundaries();
+
+    
+    /** \brief Do one Steklov-Poincare step
+     * \param[in,out] lambda The old and new iterate
+     */
+    void iterate(std::map<std::pair<std::string,std::string>, RigidBodyMotion<3> >& lambda);
+
+protected:
+    
+    std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> 
+        rodDirichletToNeumannMap(const std::string& rodName, 
+                                 const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& lambda) const;
+    
+    std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> 
+        continuumDirichletToNeumannMap(const std::string& continuumName, 
+                                       const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& lambda) const;
+                                       
+    std::set<std::string> rodsPerContinuum(const std::string& name) const;
+    
+    std::set<std::string> continuaPerRod(const std::string& name) const;
+    
+    /** \brief Add the content of one map to another, aborting rather than overwriting stuff
+     */
+    template <class X, class Y>
+    static void insert(std::map<X,Y>& map1, const std::map<X,Y>& map2)
+    {
+        int oldSize = map1.size();
+        map1.insert(map2.begin(), map2.end());
+        assert(map1.size() == oldSize + map2.size());
+    }
+    
+    //////////////////////////////////////////////////////////////////
+    //  Data members related to the coupled problem
+    //////////////////////////////////////////////////////////////////
+    const RodContinuumComplex<RodGridType,ContinuumGridType>& complex_;
+    
+    /** \brief Damping factor */
+    double damping_;
+    
+protected:
+    
+    //////////////////////////////////////////////////////////////////
+    //  Data members related to the rod problems
+    //////////////////////////////////////////////////////////////////
+    
+    struct RodData
+    {
+        Dune::BitSetVector<6> dirichletAndCouplingNodes_;
+    
+        RodAssembler<typename RodGridType::LeafGridView,3>* assembler_;
+    
+        RodLocalStiffness<typename RodGridType::LeafGridView,double>* localStiffness_;
+    
+        RiemannianTrustRegionSolver<RodGridType,RigidBodyMotion<3> >* solver_;
+    };
+    
+    /** \brief Simple const access to rods */
+    const RodData& rod(const std::string& name) const
+    {
+        assert(rods_.find(name) != rods_.end());
+        return rods_.find(name)->second;
+    }
+
+    std::map<std::string, RodData> rods_;
+    
+    typedef typename std::map<std::string, RodData>::iterator RodIterator;
+    
+public:    
+    /** \todo Should be part of RodData, too */
+    mutable std::map<std::string, RodConfigurationType> rodSubdomainSolutions_;
+protected:
+    //////////////////////////////////////////////////////////////////
+    //  Data members related to the continuum problems
+    //////////////////////////////////////////////////////////////////
+
+    struct ContinuumData
+    {
+        const MatrixType* stiffnessMatrix_;
+    
+        Dune::shared_ptr< ::LoopSolver<VectorType> > solver_;
+    
+        Dune::BitSetVector<dim> dirichletAndCouplingNodes_;
+    
+        LinearLocalAssembler<ContinuumGridType, 
+                             ContinuumLocalFiniteElement, 
+                             ContinuumLocalFiniteElement,
+                             Dune::FieldMatrix<double,dim,dim> >* localAssembler_;
+    };
+    
+    /** \brief Simple const access to continua */
+    const ContinuumData& continuum(const std::string& name) const
+    {
+        assert(continua_.find(name) != continua_.end());
+        return continua_.find(name)->second;
+    }
+
+    std::map<std::string, ContinuumData> continua_;
+
+    typedef typename std::map<std::string, ContinuumData>::iterator ContinuumIterator;
+    
+public:
+    /** \todo Should be part of ContinuumData, too */
+    mutable std::map<std::string, ContinuumConfigurationType> continuumSubdomainSolutions_;
+
+};
+
+
+template <class RodGridType, class ContinuumGridType>
+void RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+mergeRodDirichletAndCouplingBoundaries()
+{
+    ////////////////////////////////////////////////////////////////////////////////////
+    //  For each rod, merge the Dirichlet boundary with all interface boundaries
+    //
+    //  Currently, we can really only solve rod problems with complete Dirichlet
+    //  boundary.  Hence there are more direct ways to construct the
+    //  dirichletAndCouplingNodes field.  Yet like to keep the analogy to the continuum
+    //  problem.  And maybe one day we have a more flexible rod solver, too.
+    ////////////////////////////////////////////////////////////////////////////////////
+        
+    for (RodIterator rIt = rods_.begin(); rIt != rods_.end(); ++rIt) {
+            
+        // name of the current rod
+        const std::string& name = rIt->first;
+            
+        // short-cut to avoid frequent map look-up
+        Dune::BitSetVector<6>& dirichletAndCouplingNodes = rods_[name].dirichletAndCouplingNodes_;
+        
+        dirichletAndCouplingNodes.resize(complex_.rodGrid(name)->size(1));
+        
+        // first copy the true Dirichlet boundary
+        const LeafBoundaryPatch<RodGridType>& dirichletBoundary = complex_.rods_.find(name)->second.dirichletBoundary_;
+
+        for (int i=0; i<dirichletAndCouplingNodes.size(); i++)
+            dirichletAndCouplingNodes[i] = dirichletBoundary.containsVertex(i);
+        
+        // get the names of all the continua that we couple with
+        std::set<std::string> continuumNames = continuaPerRod(name);
+        
+        for (std::set<std::string>::const_iterator cIt = continuumNames.begin();
+             cIt != continuumNames.end();
+             ++cIt) {
+
+            const LeafBoundaryPatch<RodGridType>& rodInterfaceBoundary 
+                    = complex_.coupling(std::make_pair(name,*cIt)).rodInterfaceBoundary_;
+
+            /** \todo Use the BoundaryPatch iterator here, for increased efficiency */
+            for (int i=0; i<dirichletAndCouplingNodes.size(); i++) {
+                bool v = rodInterfaceBoundary.containsVertex(i);
+                for (int j=0; j<6; j++)
+                    dirichletAndCouplingNodes[i][j] = dirichletAndCouplingNodes[i][j] or v;
+            }
+        
+        }
+        
+        // We can only handle rod problems with a full Dirichlet boundary
+        assert(dirichletAndCouplingNodes.count()==12);
+        
+    }
+        
+}
+
+
+template <class RodGridType, class ContinuumGridType>
+void RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+mergeContinuumDirichletAndCouplingBoundaries()
+{
+    ////////////////////////////////////////////////////////////////////////////////////
+    //  For each continuum, merge the Dirichlet boundary with all interface boundaries
+    ////////////////////////////////////////////////////////////////////////////////////
+        
+    for (ContinuumIterator cIt = continua_.begin(); cIt != continua_.end(); ++cIt) {
+            
+        // name of the current continuum
+        const std::string& name = cIt->first;
+            
+        // short-cut to avoid frequent map look-up
+        Dune::BitSetVector<dim>& dirichletAndCouplingNodes = continua_[name].dirichletAndCouplingNodes_;
+        
+        dirichletAndCouplingNodes.resize(complex_.continuumGrid(name)->size(dim));
+        
+        // first copy the true Dirichlet boundary
+        const LeafBoundaryPatch<ContinuumGridType>& dirichletBoundary = complex_.continua_.find(name)->second.dirichletBoundary_;
+
+        for (int i=0; i<dirichletAndCouplingNodes.size(); i++)
+            dirichletAndCouplingNodes[i] = dirichletBoundary.containsVertex(i);
+        
+        // get the names of all the rods that we couple with
+        std::set<std::string> rodNames = rodsPerContinuum(name);
+        
+        for (std::set<std::string>::const_iterator rIt = rodNames.begin();
+             rIt != rodNames.end();
+             ++rIt) {
+
+            const LeafBoundaryPatch<ContinuumGridType>& continuumInterfaceBoundary 
+                    = complex_.coupling(std::make_pair(*rIt,name)).continuumInterfaceBoundary_;
+
+            /** \todo Use the BoundaryPatch iterator here, for increased efficiency */
+            for (int i=0; i<dirichletAndCouplingNodes.size(); i++) {
+                bool v = continuumInterfaceBoundary.containsVertex(i);
+                for (int j=0; j<dim; j++)
+                    dirichletAndCouplingNodes[i][j] = dirichletAndCouplingNodes[i][j] or v;
+            }
+            
+        }
+        
+    }
+        
+}
+
+
+template <class RodGridType, class ContinuumGridType>
+std::set<std::string> RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+rodsPerContinuum(const std::string& name) const
+{
+    std::set<std::string> result;
+    
+    for (typename RodContinuumComplex<RodGridType,ContinuumGridType>::ConstCouplingIterator it = complex_.couplings_.begin(); 
+         it!=complex_.couplings_.end(); ++it)
+        if (it->first.second == name)
+            result.insert(it->first.first);
+    
+    return result;
+}
+
+template <class RodGridType, class ContinuumGridType>
+std::set<std::string> RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+continuaPerRod(const std::string& name) const
+{
+    std::set<std::string> result;
+    
+    for (typename RodContinuumComplex<RodGridType,ContinuumGridType>::ConstCouplingIterator it = complex_.couplings_.begin(); 
+         it!=complex_.couplings_.end(); ++it)
+        if (it->first.first == name)
+            result.insert(it->first.second);
+    
+    return result;
+}
+
+#if 0
+template <class RodGridType, class ContinuumGridType>
+std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+rodDirichletToNeumannMap(const std::string& rodName, 
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& lambda) const
+{
+    // container for the subdomain solution
+    RodConfigurationType& rodX = rodSubdomainSolutions_[rodName];
+    rodX.resize(complex_.rodGrid(rodName)->size(1));
+    
+    ///////////////////////////////////////////////////////////
+    //  Set the complete set of Dirichlet values
+    ///////////////////////////////////////////////////////////
+    const LeafBoundaryPatch<RodGridType>& dirichletBoundary = complex_.rod(rodName).dirichletBoundary_;
+    const RodConfigurationType& dirichletValues = complex_.rod(rodName).dirichletValues_;
+    
+    for (size_t i=0; i<rodX.size(); i++)
+        if (dirichletBoundary.containsVertex(i))
+            rodX[i] = dirichletValues[i];
+    
+    typename std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >::const_iterator it = lambda.begin();
+    for (; it!=lambda.end(); ++it) {
+        
+        const std::pair<std::string,std::string>& couplingName = it->first;
+        
+        if (couplingName.first != rodName)
+            continue;
+    
+        // Use \lambda as a Dirichlet value for the rod
+        const LeafBoundaryPatch<RodGridType>& interfaceBoundary = complex_.coupling(couplingName).rodInterfaceBoundary_;
+
+        /** \todo Use the BoundaryPatch iterator, which will be a lot faster
+         * once we use EntitySeed for its implementation
+         */
+        for (size_t i=0; i<rodX.size(); i++)
+            if (interfaceBoundary.containsVertex(i))
+                rodX[i] = it->second;
+    }
+    
+    // Set the correct Dirichlet nodes
+    rod(rodName).solver_->setIgnoreNodes(rod(rodName).dirichletAndCouplingNodes_);
+
+    ////////////////////////////////////////////////////////////////////////////////
+    //  Solve the Dirichlet problem
+    ////////////////////////////////////////////////////////////////////////////////
+           
+    // Set initial iterate by interpolating between the Dirichlet values
+    RodFactory<typename RodGridType::LeafGridView> rodFactory(complex_.rodGrid(rodName)->leafView());
+    rodFactory.create(rodX);
+    
+    rod(rodName).solver_->setInitialSolution(rodX);
+    
+    // Solve the Dirichlet problem
+    rod(rodName).solver_->solve();
+
+    rodX = rod(rodName).solver_->getSol();
+
+    //   Extract Neumann values
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector > result;
+
+    for (it = lambda.begin(); it!=lambda.end(); ++it) {
+        
+        const std::pair<std::string,std::string>& couplingName = it->first;
+        
+        if (couplingName.first != rodName)
+            continue;
+        
+        const LeafBoundaryPatch<RodGridType>& couplingBoundary = complex_.coupling(couplingName).rodInterfaceBoundary_;
+
+        result[couplingName] = rod(rodName).assembler_->getResultantForce(couplingBoundary, rodX);
+    }
+    
+    return result;
+}
+#endif
+
+#if 0
+template <class RodGridType, class ContinuumGridType>
+std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+continuumDirichletToNeumannMap(const std::string& continuumName, 
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& lambda) const
+{
+    // Set initial iterate
+    VectorType& x3d = continuumSubdomainSolutions_[continuumName];
+    x3d.resize(complex_.continuumGrid(continuumName)->size(dim));
+    x3d = 0;
+
+    // Copy the true Dirichlet values into it
+    const LeafBoundaryPatch<ContinuumGridType>& dirichletBoundary = complex_.continuum(continuumName).dirichletBoundary_;
+    const VectorType& dirichletValues = complex_.continuum(continuumName).dirichletValues_;
+    
+    for (size_t i=0; i<x3d.size(); i++)
+        if (dirichletBoundary.containsVertex(i))
+            x3d[i] = dirichletValues[i];
+    
+    typename std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >::const_iterator it = lambda.begin();
+    for (; it!=lambda.end(); ++it) {
+        
+        const std::pair<std::string,std::string>& couplingName = it->first;
+        
+        if (couplingName.second != continuumName)
+            continue;
+    
+        // Turn \lambda \in TSE(3) into a Dirichlet value for the continuum
+        const LeafBoundaryPatch<ContinuumGridType>& interfaceBoundary = complex_.coupling(couplingName).continuumInterfaceBoundary_;
+        const RigidBodyMotion<dim>& referenceInterface = complex_.coupling(couplingName).referenceInterface_;
+        
+        setRotation(interfaceBoundary, x3d, referenceInterface, it->second);
+    
+    }
+    
+    // Set the correct Dirichlet nodes
+    dynamic_cast<IterationStep<VectorType>* >(continuum(continuumName).solver_->iterationStep_)->ignoreNodes_ 
+           = &continuum(continuumName).dirichletAndCouplingNodes_;
+    
+    // Right hand side vector: currently without Neumann and volume terms
+    VectorType rhs3d(x3d.size());
+    rhs3d = 0;
+    
+    // Solve the Dirichlet problem
+    assert( (dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(continuum(continuumName).solver_->iterationStep_)) );
+    dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(continuum(continuumName).solver_->iterationStep_)->setProblem(*continuum(continuumName).stiffnessMatrix_, x3d, rhs3d);
+
+    continuum(continuumName).solver_->preprocess();
+        
+    continuum(continuumName).solver_->solve();
+        
+    x3d = dynamic_cast<IterationStep<VectorType>* >(continuum(continuumName).solver_->iterationStep_)->getSol();
+            
+    // Integrate over the residual on the coupling boundary to obtain
+    // an element of T^*SE.
+    Dune::FieldVector<double,3> continuumForce, continuumTorque;
+            
+    VectorType residual = rhs3d;
+    continuum(continuumName).stiffnessMatrix_->mmv(x3d,residual);
+    
+    //////////////////////////////////////////////////////////////////////////////
+    //  Extract the residual stresses
+    //////////////////////////////////////////////////////////////////////////////
+            
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector > result;
+
+    for (it = lambda.begin(); it!=lambda.end(); ++it) {
+        
+        const std::pair<std::string,std::string>& couplingName = it->first;
+        
+        if (couplingName.second != continuumName)
+            continue;
+        
+        const LeafBoundaryPatch<ContinuumGridType>& interfaceBoundary = complex_.coupling(couplingName).continuumInterfaceBoundary_;
+
+        VectorType neumannForces(residual.size());
+        neumannForces = 0;
+        
+        weakToStrongBoundaryStress(interfaceBoundary, residual, neumannForces);
+        
+        /** \todo Is referenceInterface.r the correct center of rotation? */
+        const RigidBodyMotion<dim>& referenceInterface = complex_.coupling(couplingName).referenceInterface_;
+
+        computeTotalForceAndTorque(interfaceBoundary, 
+                                   neumannForces, 
+                                   referenceInterface.r,
+                                   continuumForce, continuumTorque);
+
+        result[couplingName][0] = continuumForce[0];
+        result[couplingName][1] = continuumForce[1];
+        result[couplingName][2] = continuumForce[2];
+        result[couplingName][3] = continuumTorque[0];
+        result[couplingName][4] = continuumTorque[1];
+        result[couplingName][5] = continuumTorque[2];
+    
+    }
+    
+    return result;
+}
+#endif
+
+
+/** \brief One preconditioned Richardson step
+*/
+template <class RodGridType, class ContinuumGridType>
+void RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+iterate(std::map<std::pair<std::string,std::string>, RigidBodyMotion<3> >& lambda)
+{
+    std::pair<std::string,std::string> interfaceName = std::make_pair("rod","continuum");
+    
+    // //////////////////////////////////////////////////
+    //   Dirichlet step for the rod
+    // //////////////////////////////////////////////////
+
+    // container for the subdomain solution
+    RodConfigurationType& rodX = rodSubdomainSolutions_["rod"];
+    rodX.resize(complex_.rodGrid("rod")->size(1));
+
+    rodX[0] = lambda[interfaceName];
+    rods_["rod"].solver_->setInitialSolution(rodX);
+    rods_["rod"].solver_->solve();
+
+    rodX = rods_["rod"].solver_->getSol();
+
+    // ///////////////////////////////////////////////////////////
+    //   Extract Neumann values and transfer it to the 3d object
+    // ///////////////////////////////////////////////////////////
+
+    RigidBodyMotion<3>::TangentVector resultantForceTorque 
+        = rod("rod").assembler_->getResultantForce(complex_.coupling(interfaceName).rodInterfaceBoundary_, rodX);
+            
+    // Flip orientation
+    resultantForceTorque  *= -1;
+
+    std::cout << "resultant force and torque: " << resultantForceTorque << std::endl;
+
+    
+    typedef P1NodalBasis<typename ContinuumGridType::LeafGridView,double> P1Basis;
+    const LeafBoundaryPatch<ContinuumGridType>& dirichletBoundary = complex_.continuum("continuum").dirichletBoundary_;
+    P1Basis basis(dirichletBoundary.gridView());
+
+    VectorType neumannValues(basis.size());
+    VectorType rhs3d;
+    
+    // Using that index 0 is always the left boundary for a uniformly refined OneDGrid
+    computeAveragePressure<typename ContinuumGridType::LeafGridView>(resultantForceTorque, 
+                                            complex_.coupling(interfaceName).continuumInterfaceBoundary_, 
+                                            rodX[0].r,
+                                            neumannValues);
+
+    BoundaryFunctionalAssembler<P1Basis> boundaryFunctionalAssembler(basis, complex_.coupling(interfaceName).continuumInterfaceBoundary_);
+    BasisGridFunction<P1Basis, VectorType> neumannValuesFunction(basis, neumannValues);
+    NeumannBoundaryAssembler<ContinuumGridType, Dune::FieldVector<double,dim> > localNeumannAssembler(neumannValuesFunction);
+    boundaryFunctionalAssembler.assemble(localNeumannAssembler, rhs3d, true);
+
+    // ///////////////////////////////////////////////////////////
+    //   Solve the Neumann problem for the continuum
+    // ///////////////////////////////////////////////////////////
+    VectorType& x3d = continuumSubdomainSolutions_["continuum"];
+
+    assert( (dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(continuum("continuum").solver_->iterationStep_)) );
+    dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(continuum("continuum").solver_->iterationStep_)->setProblem(*continuum("continuum").stiffnessMatrix_, x3d, rhs3d);
+    //multigridStep.setProblem(*continua_["continuum"].stiffnessMatrix_, x3d, rhs3d, complex_.continua_["continuum"].grid_->maxLevel()+1);
+        
+    continua_["continuum"].solver_->preprocess();
+        
+    continua_["continuum"].solver_->solve();
+        
+    x3d = dynamic_cast<IterationStep<VectorType>* >(continuum("continuum").solver_->iterationStep_)->getSol();
+
+    // ///////////////////////////////////////////////////////////
+    //   Extract new interface position and orientation
+    // ///////////////////////////////////////////////////////////
+
+    RigidBodyMotion<3> averageInterface;
+
+    computeAverageInterface(complex_.coupling(interfaceName).continuumInterfaceBoundary_, x3d, averageInterface);
+
+    std::cout << "average interface: " << averageInterface << std::endl;
+
+    std::cout << "director 0:  " << averageInterface.q.director(0) << std::endl;
+    std::cout << "director 1:  " << averageInterface.q.director(1) << std::endl;
+    std::cout << "director 2:  " << averageInterface.q.director(2) << std::endl;
+    std::cout << std::endl;
+
+    //////////////////////////////////////////////////////////////
+    //   Compute new damped interface value
+    //////////////////////////////////////////////////////////////
+    
+    const RigidBodyMotion<dim>& referenceInterface = complex_.coupling(interfaceName).referenceInterface_;
+
+    for (int j=0; j<dim; j++)
+        lambda[interfaceName].r[j] = (1-damping_) * lambda[interfaceName].r[j] 
+                                   + damping_ * (referenceInterface.r[j] + averageInterface.r[j]);
+
+        lambda[interfaceName].q = Rotation<3,double>::interpolate(lambda[interfaceName].q, 
+                                                       referenceInterface.q.mult(averageInterface.q), 
+                                                       damping_);
+
+#if 0
+    ///////////////////////////////////////////////////////////////////
+    //  Evaluate the Dirichlet-to-Neumann maps for the rods
+    ///////////////////////////////////////////////////////////////////
+
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> rodForceTorque;
+    
+    for (RodIterator it = rods_.begin(); it != rods_.end(); ++it) {
+        
+        const std::string& rodName = it->first;
+    
+        std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> forceTorque = rodDirichletToNeumannMap(rodName, lambda);
+
+        insert(rodForceTorque, forceTorque);
+        
+    }
+
+    std::cout << "resultant rod forces and torques: "  << std::endl;
+    typedef typename std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector>::iterator ForceIterator;
+    for (ForceIterator it = rodForceTorque.begin(); it != rodForceTorque.end(); ++it)
+        std::cout << "    [" << it->first.first << ", " << it->first.second << "] -- "
+                  << it->second << std::endl;
+
+    ///////////////////////////////////////////////////////////////////
+    //  Evaluate the Dirichlet-to-Neumann map for the continuum
+    ///////////////////////////////////////////////////////////////////
+    
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> continuumForceTorque; 
+
+    for (ContinuumIterator it = continua_.begin(); it != continua_.end(); ++it) {
+        
+        const std::string& continuumName = it->first;
+    
+        std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> forceTorque 
+                = continuumDirichletToNeumannMap(continuumName, lambda);
+
+        insert(continuumForceTorque, forceTorque);
+        
+    }
+
+    std::cout << "resultant continuum force and torque: " << std::endl;
+    for (ForceIterator it = continuumForceTorque.begin(); it != continuumForceTorque.end(); ++it)
+        std::cout << "    [" << it->first.first << ", " << it->first.second << "] -- "
+                  << it->second << std::endl;
+
+    ///////////////////////////////////////////////////////////////
+    //  Compute the overall Steklov-Poincare residual
+    ///////////////////////////////////////////////////////////////
+
+    // Flip orientation of all rod forces, to account for opposing normals.
+    for (ForceIterator it = rodForceTorque.begin(); it != rodForceTorque.end(); ++it)
+        it->second *= -1;
+
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> residualForceTorque = rodForceTorque;
+    
+    for (ForceIterator it = residualForceTorque.begin(), it2 = continuumForceTorque.begin(); 
+         it != residualForceTorque.end(); 
+         ++it, ++it2) {
+        assert(it->first == it2->first);
+        it->second += it2->second;
+    }
+            
+    ///////////////////////////////////////////////////////////////
+    //  Apply the preconditioner
+    ///////////////////////////////////////////////////////////////
+            
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> continuumCorrection;
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> rodCorrection;
+            
+    if (preconditioner_=="DirichletNeumann" or preconditioner_=="NeumannNeumann") {
+                
+        ////////////////////////////////////////////////////////////////////
+        //  Preconditioner is the linearized Neumann-to-Dirichlet map
+        //  of the continuum.
+        ////////////////////////////////////////////////////////////////////
+                
+        for (ContinuumIterator it = continua_.begin(); it != continua_.end(); ++it) {
+        
+            const std::string& continuumName = it->first;
+    
+            std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> continuumInterfaceCorrection
+                    = linearizedContinuumNeumannToDirichletMap(continuumName,
+                                                               continuumSubdomainSolutions_[continuumName], 
+                                                               residualForceTorque,
+                                                               lambda);
+
+            insert(continuumCorrection, continuumInterfaceCorrection);
+        
+        }
+
+        std::cout << "resultant continuum interface corrections: " << std::endl;
+        for (ForceIterator it = continuumCorrection.begin(); it != continuumCorrection.end(); ++it)
+        std::cout << "    [" << it->first.first << ", " << it->first.second << "] -- "
+                  << it->second << std::endl;
+
+
+    } 
+    
+    if (preconditioner_=="NeumannDirichlet" or preconditioner_=="NeumannNeumann") {
+            
+        ////////////////////////////////////////////////////////////////////
+        //  Preconditioner is the linearized Neumann-to-Dirichlet map
+        //  of the rod.
+        ////////////////////////////////////////////////////////////////////
+        
+        for (RodIterator it = rods_.begin(); it != rods_.end(); ++it) {
+        
+            const std::string& rodName = it->first;
+    
+            std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> rodInterfaceCorrection
+                    = linearizedRodNeumannToDirichletMap(rodName,
+                                                         rodSubdomainSolutions_[rodName], 
+                                                         residualForceTorque,
+                                                         lambda);
+
+            insert(rodCorrection, rodInterfaceCorrection);
+        
+        }
+
+        std::cout << "resultant rod interface corrections: " << std::endl;
+        for (ForceIterator it = rodCorrection.begin(); it != rodCorrection.end(); ++it)
+        std::cout << "    [" << it->first.first << ", " << it->first.second << "] -- "
+                  << it->second << std::endl;
+
+    } 
+    
+    std::map<std::pair<std::string,std::string>, RigidBodyMotion<3>::TangentVector> interfaceCorrection;
+
+    if (preconditioner_=="DirichletNeumann") {
+        
+        interfaceCorrection = continuumCorrection;
+        
+    } else if (preconditioner_=="NeumannDirichlet") {
+        
+        interfaceCorrection = rodCorrection;
+    
+    } else if (preconditioner_=="NeumannNeumann") {
+            
+        std::cout << "resultant interface corrections: " << std::endl;
+        for (ForceIterator it = rodCorrection.begin(); it != rodCorrection.end(); ++it) {
+
+            const std::pair<std::string,std::string> interfaceName = it->first;
+        
+            std::cout << "    [" << interfaceName.first << ", " << interfaceName.second << "]"
+                      << "  -- " << it->second 
+                      << "  -- " << continuumCorrection[interfaceName] << std::endl;
+
+            // Compute weighted combination of both
+            RigidBodyMotion<3>::TangentVector& correction = interfaceCorrection[interfaceName];
+            for (int j=0; j<6; j++)
+                correction[j] = (alpha_[0] * continuumCorrection[interfaceName][j] + alpha_[1] * rodCorrection[interfaceName][j])
+                                            / (alpha_[0] + alpha_[1]);
+                
+        }
+        
+    } else if (preconditioner_=="RobinRobin") {
+            
+        DUNE_THROW(Dune::NotImplemented, "Robin-Robin preconditioner not implemented yet");
+                
+    } else
+        DUNE_THROW(Dune::NotImplemented, preconditioner_ << " is not a known preconditioner");
+            
+    ///////////////////////////////////////////////////////////////////////////////
+    //  Apply the damped correction to the current interface value
+    ///////////////////////////////////////////////////////////////////////////////
+                
+    typename std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >::iterator it = lambda.begin();
+    ForceIterator fIt = interfaceCorrection.begin();
+    for (; it!=lambda.end(); ++it, ++fIt) {
+        assert(it->first == fIt->first);
+        fIt->second *= richardsonDamping_;
+        it->second = RigidBodyMotion<3>::exp(it->second, fIt->second);
+    }
+#endif
+}
+
+#endif
-- 
GitLab