From ac21922a66fb9624640327f8c64c0489e09acc31 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Fri, 12 Oct 2007 08:40:59 +0000
Subject: [PATCH] proper derivative of the geodesic interpolation

[[Imported from SVN: r1677]]
---
 src/rodassembler.cc | 79 ++++++++++++++++++++++++++++++++++++++++++---
 src/rodassembler.hh |  4 +++
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/src/rodassembler.cc b/src/rodassembler.cc
index c088ae23..4f7a4347 100644
--- a/src/rodassembler.cc
+++ b/src/rodassembler.cc
@@ -17,10 +17,6 @@ energy(const EntityPointer& element,
 {
     RT energy = 0;
     
-    // Extract local solution on this element
-    const Dune::LagrangeShapeFunctionSet<double, double, 1> & baseSet 
-        = Dune::LagrangeShapeFunctions<double, double, 1>::general(element->type(), k);
-    
     // ///////////////////////////////////////////////////////////////////////////////
     //   The following two loops are a reduced integration scheme.  We integrate
     //   the transverse shear and extensional energy with a first-order quadrature
@@ -75,6 +71,81 @@ energy(const EntityPointer& element,
     return energy;
 }
 
+template <class GridType, class RT>
+template <class T>
+void RodLocalStiffness<GridType, RT>::
+interpolationDerivative(const Quaternion<T>& q0, const Quaternion<T>& q1, double s,
+                        Dune::array<Quaternion<double>,6>& grad)
+{
+    // Clear output array
+    for (int i=0; i<6; i++)
+        grad[i] = 0;
+
+    // Compute q_0^{-1}
+    Quaternion<T> q0Inv = q0;
+    q0Inv.invert();
+
+    // Compute v = s \exp^{-1} ( q_0^{-1} q_1)
+    Dune::FieldVector<T,3> v = Quaternion<T>::expInv(q0Inv.mult(q1));
+    v *= s;
+
+    Dune::FieldMatrix<T,4,3> dExp_v = Quaternion<T>::Dexp(v);
+
+    Dune::FieldMatrix<T,3,4> dExpInv = Quaternion<T>::DexpInv(q0Inv.mult(q1));
+
+    /** \todo Compute this once and for all */
+    Dune::FieldMatrix<T,4,3> dExp_v_0 = Quaternion<T>::Dexp(Dune::FieldVector<T,3>(0));
+
+    
+
+    Dune::FieldMatrix<T,4,4> mat(0);
+    for (int i=0; i<4; i++)
+        for (int j=0; j<4; j++)
+            for (int k=0; k<3; k++)
+                mat[i][j] += s * dExp_v[i][k] * dExpInv[k][j];
+
+    
+    // The derivatives with respect to w^0
+    for (int i=0; i<3; i++) {
+
+        Quaternion<T> dw;
+        for (int j=0; j<4; j++)
+            dw[j] = dExp_v_0[j][i];
+        
+        // First addend
+        Quaternion<T> grad0 = q0.mult(dw.mult(Quaternion<T>::exp(v)));
+
+        // Second addend
+        dw.conjugate();
+
+        dw[3] -= 2 * dExp_v_0[3][i];
+
+        dw = dw.mult(q0Inv.mult(q1));
+        
+        mat.umv(dw,grad[i]);
+        grad[i] = q0.mult(grad[i]);
+        
+        // Add the two addends
+        for (int j=0; j<4; j++)
+            grad[i][j] = grad0[j] + grad[i][j];
+
+    }
+
+    // The derivatives with respect to w^1
+    for (int i=3; i<6; i++) {
+
+        Quaternion<T> dw;
+        for (int j=0; j<4; j++)
+            dw[j] = dExp_v_0[j][i-3];
+        
+        dw = q0Inv.mult(q1.mult(dw));
+        
+        mat.umv(dw,grad[i]);
+        grad[i] = q0.mult(grad[i]);
+
+    }
+}
+
 template <class GridType, class RT>
 Dune::FieldVector<double, 6> RodLocalStiffness<GridType, RT>::
 getStrain(const std::vector<Configuration>& localSolution,
diff --git a/src/rodassembler.hh b/src/rodassembler.hh
index eaecc939..da2246ca 100644
--- a/src/rodassembler.hh
+++ b/src/rodassembler.hh
@@ -92,6 +92,10 @@ public:
                const std::vector<Configuration>& localReferenceConfiguration,
                int k=1);
 
+    template <class T>
+    static void interpolationDerivative(const Quaternion<T>& q0, const Quaternion<T>& q1, double s,
+                                        Dune::array<Quaternion<double>,6>& grad);
+
     Dune::FieldVector<double, 6> getStrain(const std::vector<Configuration>& localSolution,
                                            const EntityPointer& element,
                                            const Dune::FieldVector<double,1>& pos) const;
-- 
GitLab