From cf075276f49568ec88eda70a1789bc9ddf0d8fb1 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Thu, 12 Jan 2012 10:01:10 +0000
Subject: [PATCH] Reimplement method
 secondDerivativeOfDistanceSquaredWRTSecondArgument

Properly taking into account the two-sheet covering structure

[[Imported from SVN: r8370]]
---
 dune/gfe/rotation.hh | 35 +++++++++++++++++++++++------------
 1 file changed, 23 insertions(+), 12 deletions(-)

diff --git a/dune/gfe/rotation.hh b/dune/gfe/rotation.hh
index 9d2196f7..56ae8b5b 100644
--- a/dune/gfe/rotation.hh
+++ b/dune/gfe/rotation.hh
@@ -643,19 +643,30 @@ public:
         return result;
     }
 
-    /** \brief Compute the Hessian of the squared distance function keeping the first argument fixed
-
-    Unlike the distance itself the squared distance is differentiable at zero
-     */
+    /** \brief Compute the Hessian of the squared distance function keeping the first argument fixed */
     static Dune::FieldMatrix<T,4,4> secondDerivativeOfDistanceSquaredWRTSecondArgument(const Rotation<T,3>& p, const Rotation<T,3>& q) {
-        // use the functionality from the unitvector class
-        Dune::FieldMatrix<T,4,4> result = UnitVector<T,4>::secondDerivativeOfDistanceSquaredWRTSecondArgument(p.globalCoordinates(),
-                                                                                                                 q.globalCoordinates());
-        // The unit quaternions form a double cover of SO(3).  That means going once around the unit sphere (2\pi)
-        // means going twice around SO(3) (4\pi).  Hence there is a factor 2, which in addition we need to square,
-        // because we are considering the squared distance.
-        result *= 4;
-        return result;
+
+        T sp = p.globalCoordinates() * q.globalCoordinates();
+        
+        EmbeddedTangentVector pProjected = q.projectOntoTangentSpace(p.globalCoordinates());
+
+        Dune::FieldMatrix<T,4,4> A;
+        for (int i=0; i<4; i++)
+            for (int j=0; j<4; j++)
+                A[i][j] = pProjected[i]*pProjected[j];
+        
+        A *= 4*UnitVector<T,4>::secondDerivativeOfArcCosSquared(std::fabs(sp));
+
+        // Compute matrix B (see notes)
+        Dune::FieldMatrix<T,4,4> Pq;
+        for (int i=0; i<4; i++)
+            for (int j=0; j<4; j++)
+                Pq[i][j] = (i==j) - q.globalCoordinates()[i]*q.globalCoordinates()[j];
+
+        // Bring it all together
+        A.axpy(-4* ((sp<0) ? -1 : 1) * derivativeOfArcCosSquared(std::fabs(sp))*sp, Pq);
+        
+        return A;
     }
     
     /** \brief Compute the mixed second derivate \partial d^2 / \partial da db
-- 
GitLab