From 85cb77bd84dbde357a7dc17c388d37632b595149 Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Fri, 25 Feb 2022 11:40:21 +0100
Subject: [PATCH] Modernize target space finite difference testing

---
 test/targetspacetest.cc | 77 +++++++++++++++++------------------------
 1 file changed, 32 insertions(+), 45 deletions(-)

diff --git a/test/targetspacetest.cc b/test/targetspacetest.cc
index 61c92a08..d24e6651 100644
--- a/test/targetspacetest.cc
+++ b/test/targetspacetest.cc
@@ -29,23 +29,17 @@ double diameter(const std::vector<TargetSpace>& v)
 const double eps = 1e-4;
 
 template <class TargetSpace>
-double energy(const TargetSpace& a, const TargetSpace& b)
+double distanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
-    return TargetSpace::distance(a,b) * TargetSpace::distance(a,b);
+    return Dune::power(TargetSpace::distance(a,b), 2);
 }
 
+// Squared distance between two points slightly off the manifold.
+// This is required for finite difference approximations.
 template <class TargetSpace, int dim>
-double energy(const TargetSpace& a, const FieldVector<double,dim>& b)
+double distanceSquared(const FieldVector<double,dim>& a, const FieldVector<double,dim>& b)
 {
-#warning Cast where there should not be one
-    return TargetSpace::distance(a,TargetSpace(b)) * TargetSpace::distance(a,TargetSpace(b));
-}
-
-template <class TargetSpace, int dim>
-double energy(const FieldVector<double,dim>& a, const FieldVector<double,dim>& b)
-{
-#warning Cast where there should not be one
-    return TargetSpace::distance(TargetSpace(a),TargetSpace(b)) * TargetSpace::distance(TargetSpace(a),TargetSpace(b));
+    return Dune::power(TargetSpace::distance(TargetSpace(a),TargetSpace(b)), 2);
 }
 
 /** \brief Compute the Riemannian Hessian of the squared distance function in global coordinates
@@ -67,15 +61,15 @@ FieldMatrix<double,worldDim,worldDim> getSecondDerivativeOfSecondArgumentFD(cons
     for (size_t i=0; i<spaceDim; i++) {
         for (size_t j=0; j<spaceDim; j++) {
 
-            FieldVector<double,worldDim> epsXi = B[i];    epsXi *= eps;
-            FieldVector<double,worldDim> epsEta = B[j];   epsEta *= eps;
+            FieldVector<double,worldDim> epsXi  = eps * B[i];
+            FieldVector<double,worldDim> epsEta = eps * B[j];
             
-            FieldVector<double,worldDim> minusEpsXi  = epsXi;   minusEpsXi  *= -1;
-            FieldVector<double,worldDim> minusEpsEta = epsEta;  minusEpsEta *= -1;
+            FieldVector<double,worldDim> minusEpsXi  = -1 * epsXi;
+            FieldVector<double,worldDim> minusEpsEta = -1 * epsEta;
             
-            double forwardValue  = energy(a,TargetSpace::exp(b,epsXi+epsEta)) - energy(a, TargetSpace::exp(b,epsXi)) - energy(a,TargetSpace::exp(b,epsEta));
-            double centerValue   = energy(a,b)                   - energy(a,b)              - energy(a,b);
-            double backwardValue = energy(a,TargetSpace::exp(b,minusEpsXi + minusEpsEta)) - energy(a, TargetSpace::exp(b,minusEpsXi)) - energy(a,TargetSpace::exp(b,minusEpsEta));
+            double forwardValue  = distanceSquared(a,TargetSpace::exp(b,epsXi+epsEta)) - distanceSquared(a, TargetSpace::exp(b,epsXi)) - distanceSquared(a,TargetSpace::exp(b,epsEta));
+            double centerValue   = distanceSquared(a,b) - distanceSquared(a,b) - distanceSquared(a,b);
+            double backwardValue = distanceSquared(a,TargetSpace::exp(b,minusEpsXi + minusEpsEta)) - distanceSquared(a, TargetSpace::exp(b,minusEpsXi)) - distanceSquared(a,TargetSpace::exp(b,minusEpsEta));
             
             d2d2_fd[i][j] = 0.5 * (forwardValue - 2*centerValue + backwardValue) / (eps*eps);
             
@@ -111,7 +105,7 @@ void testOrthonormalFrame(const TargetSpace& a)
 }
 
 template <class TargetSpace>
-void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testDerivativeOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     static const size_t embeddedDim = TargetSpace::embeddedDim;
     
@@ -126,14 +120,12 @@ void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
     typename TargetSpace::TangentVector d2_fd;
     for (size_t i=0; i<TargetSpace::TangentVector::dimension; i++) {
         
-        typename TargetSpace::EmbeddedTangentVector fwVariation = B[i];
-        typename TargetSpace::EmbeddedTangentVector bwVariation = B[i];
-        fwVariation *= eps;
-        bwVariation *= -eps;
+        typename TargetSpace::EmbeddedTangentVector fwVariation =  eps * B[i];
+        typename TargetSpace::EmbeddedTangentVector bwVariation = -eps * B[i];
         TargetSpace bPlus  = TargetSpace::exp(b,fwVariation);
         TargetSpace bMinus = TargetSpace::exp(b,bwVariation);
 
-        d2_fd[i] = (energy(a,bPlus) - energy(a,bMinus)) / (2*eps);
+        d2_fd[i] = (distanceSquared(a,bPlus) - distanceSquared(a,bMinus)) / (2*eps);
     }
 
     // transform into embedded coordinates
@@ -150,7 +142,7 @@ void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
 }
 
 template <class TargetSpace>
-void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     static const int embeddedDim = TargetSpace::embeddedDim;
     
@@ -162,9 +154,7 @@ void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
     // finite-difference approximation
     FieldMatrix<double,embeddedDim,embeddedDim> d2d2_fd = getSecondDerivativeOfSecondArgumentFD<TargetSpace,embeddedDim>(a,b);
     
-    FieldMatrix<double,embeddedDim,embeddedDim> d2d2_diff = d2d2;
-    d2d2_diff -= d2d2_fd;
-    if ( (d2d2_diff).infinity_norm() > 200*eps) {
+    if ( (d2d2 - d2d2_fd).infinity_norm() > 200*eps) {
         std::cout << className(a) << ": Analytical second derivative does not match fd approximation." << std::endl;
         std::cout << "d2d2 Analytical:" << std::endl << d2d2 << std::endl;
         std::cout << "d2d2 FD        :" << std::endl << d2d2_fd << std::endl;
@@ -174,7 +164,7 @@ void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
 }
 
 template <class TargetSpace>
-void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testMixedDerivativesOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     static const size_t embeddedDim = TargetSpace::embeddedDim;
     
@@ -200,16 +190,13 @@ void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpa
             bPlus[j]  += eps;
             bMinus[j] -= eps;
                 
-            d1d2_fd[i][j] = (energy<TargetSpace>(aPlus,bPlus) + energy<TargetSpace>(aMinus,bMinus)
-                            - energy<TargetSpace>(aPlus,bMinus) - energy<TargetSpace>(aMinus,bPlus)) / (4*eps*eps);
+            d1d2_fd[i][j] = (distanceSquared<TargetSpace>(aPlus,bPlus) + distanceSquared<TargetSpace>(aMinus,bMinus)
+                            - distanceSquared<TargetSpace>(aPlus,bMinus) - distanceSquared<TargetSpace>(aMinus,bPlus)) / (4*eps*eps);
 
         }
     }
     
-    FieldMatrix<double,embeddedDim,embeddedDim> d1d2_diff = d1d2;
-    d1d2_diff -= d1d2_fd;
-
-    if ( (d1d2_diff).infinity_norm() > 200*eps ) {
+    if ( (d1d2 - d1d2_fd).infinity_norm() > 200*eps ) {
         std::cout << className(a) << ": Analytical mixed second derivative does not match fd approximation." << std::endl;
         std::cout << "d1d2 Analytical:" << std::endl << d1d2 << std::endl;
         std::cout << "d1d2 FD        :" << std::endl << d1d2_fd << std::endl;
@@ -220,7 +207,7 @@ void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpa
 
 
 template <class TargetSpace>
-void testDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testDerivativeOfHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     static const size_t embeddedDim = TargetSpace::embeddedDim;
     
@@ -259,7 +246,7 @@ void testDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const Target
 
 
 template <class TargetSpace>
-void testMixedDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testMixedDerivativeOfHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     static const size_t embeddedDim = TargetSpace::embeddedDim;
     
@@ -298,38 +285,38 @@ void testMixedDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const T
 
 
 template <class TargetSpace>
-void testDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
+void testDerivativesOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
 {
     
     ///////////////////////////////////////////////////////////////////
     //  Test derivative with respect to second argument
     ///////////////////////////////////////////////////////////////////
     
-    testDerivativeOfSquaredDistance<TargetSpace>(a,b);
+    testDerivativeOfDistanceSquared<TargetSpace>(a,b);
     
     ///////////////////////////////////////////////////////////////////
     //  Test second derivative with respect to second argument
     ///////////////////////////////////////////////////////////////////
 
-    testHessianOfSquaredDistance<TargetSpace>(a,b);
+    testHessianOfDistanceSquared<TargetSpace>(a,b);
 
     //////////////////////////////////////////////////////////////////////////////
     //  Test mixed second derivative with respect to first and second argument
     //////////////////////////////////////////////////////////////////////////////
 
-    testMixedDerivativesOfSquaredDistance<TargetSpace>(a,b);
+    testMixedDerivativesOfDistanceSquared<TargetSpace>(a,b);
     
     /////////////////////////////////////////////////////////////////////////////////////////////
     //  Test third derivative with respect to second argument
     /////////////////////////////////////////////////////////////////////////////////////////////
     
-    testDerivativeOfHessianOfSquaredDistance<TargetSpace>(a,b);
+    testDerivativeOfHessianOfDistanceSquared<TargetSpace>(a,b);
 
     /////////////////////////////////////////////////////////////////////////////////////////////
     //  Test mixed third derivative with respect to first (once) and second (twice) argument
     /////////////////////////////////////////////////////////////////////////////////////////////
     
-    testMixedDerivativeOfHessianOfSquaredDistance<TargetSpace>(a,b);
+    testMixedDerivativeOfHessianOfDistanceSquared<TargetSpace>(a,b);
 
 }
 
@@ -357,7 +344,7 @@ void test()
             if (diameter(testPointPair) > TargetSpace::convexityRadius)
                 continue;
 
-            testDerivativesOfSquaredDistance<TargetSpace>(testPoints[i], testPoints[j]);
+            testDerivativesOfDistanceSquared<TargetSpace>(testPoints[i], testPoints[j]);
             
         }
         
-- 
GitLab