From 0ec44c7d75b880a902d4af9092328da3f79fa6b0 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Sat, 2 Apr 2011 17:01:22 +0000
Subject: [PATCH] merge the continuum Neumann-to-Dirichlet map from the
 Steklov-Poincare step class

[[Imported from SVN: r7063]]
---
 .../coupling/rodcontinuumfixedpointstep.hh    | 155 ++++++++++--------
 1 file changed, 85 insertions(+), 70 deletions(-)

diff --git a/dune/gfe/coupling/rodcontinuumfixedpointstep.hh b/dune/gfe/coupling/rodcontinuumfixedpointstep.hh
index f850ef3f..99ab514b 100644
--- a/dune/gfe/coupling/rodcontinuumfixedpointstep.hh
+++ b/dune/gfe/coupling/rodcontinuumfixedpointstep.hh
@@ -113,10 +113,11 @@ protected:
         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::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector>
+    continuumNeumannToDirichletMap(const std::string& continuumName,
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector>& forceTorque,
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& centerOfTorque) const;
+
     std::set<std::string> rodsPerContinuum(const std::string& name) const;
     
     std::set<std::string> continuaPerRod(const std::string& name) const;
@@ -413,106 +414,120 @@ rodDirichletToNeumannMap(const std::string& rodName,
     return result;
 }
 
-#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
+std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> 
+RodContinuumFixedPointStep<RodGridType,ContinuumGridType>::
+continuumNeumannToDirichletMap(const std::string& continuumName,
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector>& forceTorque,
+                               const std::map<std::pair<std::string,std::string>,RigidBodyMotion<3> >& centerOfTorque) const
 {
-    // Set initial iterate
-    VectorType& x3d = continuumSubdomainSolutions_[continuumName];
-    x3d.resize(complex_.continuumGrid(continuumName)->size(dim));
-    x3d = 0;
+    ////////////////////////////////////////////////////
+    //  Assemble the linearized problem
+    ////////////////////////////////////////////////////
 
-    // Copy the true Dirichlet values into it
+    /** \todo We are actually assembling standard linear elasticity,
+    * i.e. the linearization at zero
+    */
+    typedef P1NodalBasis<typename ContinuumGridType::LeafGridView,double> P1Basis;
     const LeafBoundaryPatch<ContinuumGridType>& dirichletBoundary = complex_.continuum(continuumName).dirichletBoundary_;
-    const VectorType& dirichletValues = complex_.continuum(continuumName).dirichletValues_;
+    P1Basis basis(dirichletBoundary.gridView());
+    OperatorAssembler<P1Basis,P1Basis> assembler(basis, basis);
+
+    MatrixType stiffnessMatrix;
+    assembler.assemble(*continuum(continuumName).localAssembler_, stiffnessMatrix);
     
-    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) {
+    /////////////////////////////////////////////////////////////////////
+    //  Turn the input force and torque into a Neumann boundary field
+    /////////////////////////////////////////////////////////////////////
+    
+    // The weak form of the volume and Neumann data
+    /** \brief Not implemented yet! */
+    VectorType rhs(complex_.continuumGrid(continuumName)->size(dim));
+    rhs = 0;
+
+    typedef typename std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector>::const_iterator ForceIterator;
+    
+    for (ForceIterator it = forceTorque.begin(); it!=forceTorque.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
+        
+        // Use 'forceTorque' as a Neumann value for the rod
         const LeafBoundaryPatch<ContinuumGridType>& interfaceBoundary = complex_.coupling(couplingName).continuumInterfaceBoundary_;
-        const RigidBodyMotion<dim>& referenceInterface = complex_.coupling(couplingName).referenceInterface_;
         
-        setRotation(interfaceBoundary, x3d, referenceInterface, it->second);
-    
+        // 
+        VectorType localNeumannValues;
+        computeAveragePressure<typename ContinuumGridType::LeafGridView>(forceTorque.find(couplingName)->second, 
+                                        interfaceBoundary, 
+                                        centerOfTorque.find(couplingName)->second.r,
+                                        localNeumannValues);
+        
+        BoundaryFunctionalAssembler<P1Basis> boundaryFunctionalAssembler(basis, interfaceBoundary);
+        BasisGridFunction<P1Basis,VectorType> neumannValuesFunction(basis,localNeumannValues);
+        NeumannBoundaryAssembler<ContinuumGridType, Dune::FieldVector<double,3> > localNeumannAssembler(neumannValuesFunction);
+        boundaryFunctionalAssembler.assemble(localNeumannAssembler, rhs, false);
+
     }
     
     // Set the correct Dirichlet nodes
+    /** \brief Don't write this BitSetVector at each iteration */
+    Dune::BitSetVector<dim> dirichletNodes(rhs.size(),false);
+    for (size_t i=0; i<dirichletNodes.size(); i++)
+        dirichletNodes[i] = dirichletBoundary.containsVertex(i);
     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;
+           = &dirichletNodes;
+
+    //  Initial iterate is 0,  all Dirichlet values are 0 (because we solve a correction problem
+    VectorType x(dirichletNodes.size());
+    x = 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);
+    dynamic_cast<LinearIterationStep<MatrixType,VectorType>* >(continuum(continuumName).solver_->iterationStep_)->setProblem(stiffnessMatrix, x, rhs);
 
-    continuum(continuumName).solver_->preprocess();
+    //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;
+    x = continuum(continuumName).solver_->iterationStep_->getSol();
 
-    for (it = lambda.begin(); it!=lambda.end(); ++it) {
+    /////////////////////////////////////////////////////////////////////////////////
+    //  Average the continuum displacement on the coupling boundary
+    /////////////////////////////////////////////////////////////////////////////////
+    std::map<std::pair<std::string,std::string>,RigidBodyMotion<3>::TangentVector> interfaceCorrection;
+
+    for (ForceIterator it = forceTorque.begin(); it!=forceTorque.end(); ++it) {
         
         const std::pair<std::string,std::string>& couplingName = it->first;
-        
+
         if (couplingName.second != continuumName)
             continue;
         
+        // Use 'forceTorque' as a Neumann value for the rod
         const LeafBoundaryPatch<ContinuumGridType>& interfaceBoundary = complex_.coupling(couplingName).continuumInterfaceBoundary_;
-
-        VectorType neumannForces(residual.size());
-        neumannForces = 0;
         
-        weakToStrongBoundaryStress(interfaceBoundary, residual, neumannForces);
+        RigidBodyMotion<3> averageInterface;
+        computeAverageInterface(interfaceBoundary, x, averageInterface);
+        
+        // Compute the linearization
+        /** \todo We could loop directly over interfaceCorrection (and save the name lookup)
+         * if we could be sure that interfaceCorrection contains all possible entries already
+         */
+        interfaceCorrection[couplingName][0] = averageInterface.r[0];
+        interfaceCorrection[couplingName][1] = averageInterface.r[1];
+        interfaceCorrection[couplingName][2] = averageInterface.r[2];
+        
+        Dune::FieldVector<double,3> infinitesimalRotation = Rotation<3,double>::expInv(averageInterface.q);
+        interfaceCorrection[couplingName][3] = infinitesimalRotation[0];
+        interfaceCorrection[couplingName][4] = infinitesimalRotation[1];
+        interfaceCorrection[couplingName][5] = infinitesimalRotation[2];
         
-        /** \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;
+    return interfaceCorrection;
 }
-#endif
 
 
 /** \brief One preconditioned Richardson step
-- 
GitLab