From c218cd9e9b0ba7f49b2c894ae150e1cfc43e56cc Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Fri, 13 Dec 2013 09:50:31 +0000
Subject: [PATCH] Use SymmetricMatrix for Hessian of the distance functional
 exclusively

[[Imported from SVN: r9588]]
---
 dune/gfe/averagedistanceassembler.hh | 19 +++++++++++--------
 dune/gfe/localgeodesicfefunction.hh  |  5 +++--
 dune/gfe/realtuple.hh                |  9 +++++----
 dune/gfe/rotation.hh                 | 15 ++++++++-------
 dune/gfe/unitvector.hh               | 15 ++++++++-------
 5 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/dune/gfe/averagedistanceassembler.hh b/dune/gfe/averagedistanceassembler.hh
index c426a6ba..b4def6ba 100644
--- a/dune/gfe/averagedistanceassembler.hh
+++ b/dune/gfe/averagedistanceassembler.hh
@@ -73,20 +73,23 @@ public:
                          Dune::FieldMatrix<ctype,embeddedSize,embeddedSize>& matrix) const
     {
         matrix = 0;
-        for (size_t i=0; i<coefficients_.size(); i++)
-            matrix.axpy(weights_[i], TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], x));
+        for (size_t i=0; i<coefficients_.size(); i++) {
+          Dune::SymmetricMatrix<ctype,embeddedSize> tmp = TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], x);
+          for (int j=0; j<embeddedSize; j++)
+            for (int k=0; k<=j; k++) {
+              matrix[j][k] += weights_[i] * tmp(j,k);
+              if (j!=k)
+                matrix[k][j] += weights_[i] * tmp(j,k);
+            }
+        }
     }
 
     void assembleEmbeddedHessian(const TargetSpace& x,
                          Dune::SymmetricMatrix<ctype,embeddedSize>& matrix) const
     {
         matrix = 0;
-        for (size_t i=0; i<coefficients_.size(); i++) {
-          Dune::FieldMatrix<ctype,embeddedSize,embeddedSize> tmp = TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], x);
-          for (size_t j=0; j<embeddedSize; j++)
-            for (size_t k=0; k<=j; k++)
-              matrix(j,k) += weights_[i] * tmp[j][k];
-        }
+        for (size_t i=0; i<coefficients_.size(); i++)
+            matrix.axpy(weights_[i], TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], x));
     }
 
     void assembleHessian(const TargetSpace& x,
diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh
index 0b8b5434..9eadf45e 100644
--- a/dune/gfe/localgeodesicfefunction.hh
+++ b/dune/gfe/localgeodesicfefunction.hh
@@ -497,10 +497,11 @@ evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>&
     TensorSSD<RT, embeddedDim,embeddedDim> dqdwF(coefficients_.size());
 
     for (size_t k=0; k<coefficients_.size(); k++) {
-        Dune::FieldMatrix<RT,embeddedDim,embeddedDim> hesse = TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[k], q);
+        Dune::SymmetricMatrix<RT,embeddedDim> hesse = TargetSpace::secondDerivativeOfDistanceSquaredWRTSecondArgument(coefficients_[k], q);
         for (int i=0; i<embeddedDim; i++)
             for (int j=0; j<embeddedDim; j++)
-                dqdwF(i, j, k) = hesse[i][j];
+                dqdwF(i, j, k) = dqdwF(j, i, k) = hesse(i,j);
+
     }
 
     TensorSSD<RT, embeddedDim,embeddedDim> dqdwF_times_dvq(coefficients_.size());
diff --git a/dune/gfe/realtuple.hh b/dune/gfe/realtuple.hh
index afd7396a..9fecb7e9 100644
--- a/dune/gfe/realtuple.hh
+++ b/dune/gfe/realtuple.hh
@@ -4,6 +4,7 @@
 #include <dune/common/array.hh>
 #include <dune/common/fvector.hh>
 #include <dune/gfe/tensor3.hh>
+#include <dune/gfe/symmetricmatrix.hh>
 
 
 /** \brief Implement a tuple of real numbers as a Riemannian manifold
@@ -101,12 +102,12 @@ public:
 
     Unlike the distance itself the squared distance is differentiable at zero
         */
-    static Dune::FieldMatrix<T,N,N> secondDerivativeOfDistanceSquaredWRTSecondArgument(const RealTuple& a, const RealTuple& b) {
+    static Dune::SymmetricMatrix<T,N> secondDerivativeOfDistanceSquaredWRTSecondArgument(const RealTuple& a, const RealTuple& b) {
 
-        Dune::FieldMatrix<T,N,N> result;
+        Dune::SymmetricMatrix<T,N> result;
         for (int i=0; i<N; i++)
-            for (int j=0; j<N; j++)
-                result[i][j] = 2*(i==j);
+            for (int j=0; j<=i; j++)
+                result(i,j) = 2*(i==j);
 
         return result;
     }
diff --git a/dune/gfe/rotation.hh b/dune/gfe/rotation.hh
index 24536405..3fc8f2d7 100644
--- a/dune/gfe/rotation.hh
+++ b/dune/gfe/rotation.hh
@@ -14,6 +14,7 @@
 #include <dune/gfe/tensor3.hh>
 #include <dune/gfe/unitvector.hh>
 #include <dune/gfe/skewmatrix.hh>
+#include <dune/gfe/symmetricmatrix.hh>
 
 template <class T, int dim>
 class Rotation
@@ -684,24 +685,24 @@ public:
     }
 
     /** \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) {
+    static Dune::SymmetricMatrix<T,4> secondDerivativeOfDistanceSquaredWRTSecondArgument(const Rotation<T,3>& p, const Rotation<T,3>& q) {
 
         T sp = p.globalCoordinates() * q.globalCoordinates();
 
         EmbeddedTangentVector pProjected = q.projectOntoTangentSpace(p.globalCoordinates());
 
-        Dune::FieldMatrix<T,4,4> A;
+        Dune::SymmetricMatrix<T,4> A;
         for (int i=0; i<4; i++)
-            for (int j=0; j<4; j++)
-                A[i][j] = pProjected[i]*pProjected[j];
+            for (int j=0; j<=i; j++)
+                A(i,j) = pProjected[i]*pProjected[j];
 
         A *= 4*UnitVector<T,4>::secondDerivativeOfArcCosSquared(std::abs(sp));
 
         // Compute matrix B (see notes)
-        Dune::FieldMatrix<T,4,4> Pq;
+        Dune::SymmetricMatrix<T,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];
+            for (int j=0; j<=i; j++)
+                Pq(i,j) = (i==j) - q.globalCoordinates()[i]*q.globalCoordinates()[j];
 
         // Bring it all together
         A.axpy(-4* ((sp<0) ? -1 : 1) * UnitVector<T,4>::derivativeOfArcCosSquared(std::abs(sp))*sp, Pq);
diff --git a/dune/gfe/unitvector.hh b/dune/gfe/unitvector.hh
index a218ee40..f37fa4d9 100644
--- a/dune/gfe/unitvector.hh
+++ b/dune/gfe/unitvector.hh
@@ -5,6 +5,7 @@
 #include <dune/common/fmatrix.hh>
 
 #include <dune/gfe/tensor3.hh>
+#include <dune/gfe/symmetricmatrix.hh>
 
 template <class T, int N>
 class Rotation;
@@ -189,24 +190,24 @@ public:
 
     Unlike the distance itself the squared distance is differentiable at zero
      */
-    static Dune::FieldMatrix<T,N,N> secondDerivativeOfDistanceSquaredWRTSecondArgument(const UnitVector& p, const UnitVector& q) {
+    static Dune::SymmetricMatrix<T,N> secondDerivativeOfDistanceSquaredWRTSecondArgument(const UnitVector& p, const UnitVector& q) {
 
         T sp = p.data_ * q.data_;
 
         Dune::FieldVector<T,N> pProjected = q.projectOntoTangentSpace(p.globalCoordinates());
 
-        Dune::FieldMatrix<T,N,N> A;
+        Dune::SymmetricMatrix<T,N> A;
         for (int i=0; i<N; i++)
-            for (int j=0; j<N; j++)
-                A[i][j] = pProjected[i]*pProjected[j];
+            for (int j=0; j<=i; j++)
+                A(i,j) = pProjected[i]*pProjected[j];
 
         A *= secondDerivativeOfArcCosSquared(sp);
 
         // Compute matrix B (see notes)
-        Dune::FieldMatrix<T,N,N> Pq;
+        Dune::SymmetricMatrix<T,N> Pq;
         for (int i=0; i<N; i++)
-            for (int j=0; j<N; j++)
-                Pq[i][j] = (i==j) - q.data_[i]*q.data_[j];
+            for (int j=0; j<=i; j++)
+                Pq(i,j) = (i==j) - q.data_[i]*q.data_[j];
 
         // Bring it all together
         A.axpy(-1*derivativeOfArcCosSquared(sp)*sp, Pq);
-- 
GitLab