From e57583acba2946095185c670e255740898b8937d Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Sun, 10 Apr 2011 13:37:51 +0000
Subject: [PATCH] add a method with an fd approximation of the derivative of
 the function gradient.  only for testing purposes

[[Imported from SVN: r7130]]
---
 dune/gfe/localgeodesicfefunction.hh | 82 +++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh
index cfa886ad..93280009 100644
--- a/dune/gfe/localgeodesicfefunction.hh
+++ b/dune/gfe/localgeodesicfefunction.hh
@@ -92,6 +92,11 @@ public:
                                                     int coefficient,
                                                     Tensor3<double, TargetSpace::EmbeddedTangentVector::size,TargetSpace::EmbeddedTangentVector::size,dim>& result) const;
 
+    /** \brief Evaluate the derivative of the gradient of the function with respect to a coefficient */
+    void evaluateFDDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>& local,
+                                                    int coefficient,
+                                                    Tensor3<double, TargetSpace::EmbeddedTangentVector::size,TargetSpace::EmbeddedTangentVector::size,dim>& result) const;
+
 private:
 
     /** \brief The linear part of the map that turns coordinates on the reference simplex into coordinates on the standard simplex 
@@ -322,8 +327,85 @@ evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>&
     dvDqF = w[coefficient] * dvDqF;
        
     // Put it all together
+#if 0
     for (size_t i=0; i<result.size(); i++)
         result[i] = dFdqPseudoInv * ( dvDqF[i] * dFdqPseudoInv * dFdw - dvDwF[i]) * B;   
+#else
+    Dune::FieldMatrix<ctype, TargetSpace::EmbeddedTangentVector::size, dim> derivative = evaluateDerivative(local);
+    Tensor3<double, TargetSpace::EmbeddedTangentVector::size,TargetSpace::EmbeddedTangentVector::size,dim> foo;
+    foo = -1 * dvDwF * B - dvDqF*derivative;
+    result = 0;
+    for (int i=0; i<embeddedDim; i++)
+        for (int j=0; j<embeddedDim; j++)
+            for (int k=0; k<dim; k++)
+                for (int l=0; l<embeddedDim; l++)
+                    result[i][j][k] += dFdqPseudoInv[j][l] * foo[i][l][k];
+#endif
+}
+
+
+template <int dim, class ctype, class TargetSpace>
+void LocalGeodesicFEFunction<dim,ctype,TargetSpace>::
+evaluateFDDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>& local,
+                                           int coefficient,
+                                           Tensor3<double, TargetSpace::EmbeddedTangentVector::size,TargetSpace::EmbeddedTangentVector::size,dim>& result) const
+{
+    double eps = 1e-6;
+    for (int j=0; j<TargetSpace::EmbeddedTangentVector::size; j++) {
+                
+        std::vector<TargetSpace> cornersPlus  = coefficients_;
+        std::vector<TargetSpace> cornersMinus = coefficients_;
+        typename TargetSpace::CoordinateType aPlus  = coefficients_[coefficient].globalCoordinates();
+        typename TargetSpace::CoordinateType aMinus = coefficients_[coefficient].globalCoordinates();
+        aPlus[j]  += eps;
+        aMinus[j] -= eps;
+        cornersPlus[coefficient]  = TargetSpace(aPlus);
+        cornersMinus[coefficient] = TargetSpace(aMinus);
+        LocalGeodesicFEFunction<dim,double,TargetSpace> fPlus(cornersPlus);
+        LocalGeodesicFEFunction<dim,double,TargetSpace> fMinus(cornersMinus);
+                
+        Dune::FieldMatrix<double,TargetSpace::EmbeddedTangentVector::size,dim> h      = evaluateDerivative(local);
+        Dune::FieldMatrix<double,TargetSpace::EmbeddedTangentVector::size,dim> hPlus  = fPlus.evaluateDerivative(local);
+        Dune::FieldMatrix<double,TargetSpace::EmbeddedTangentVector::size,dim> hMinus = fMinus.evaluateDerivative(local);
+                
+#if 0
+        double l      = sqrt(h[0][0]*h[0][0] + h[1][0]*h[1][0]);
+        double lPlus  = sqrt(hPlus[0][0]*hPlus[0][0] + hPlus[1][0]*hPlus[1][0]);
+        double lMinus = sqrt(hMinus[0][0]*hMinus[0][0] + hMinus[1][0]*hMinus[1][0]);
+        std::cout << "h:\n" << h  << "length: " << l << std::endl<< std::endl;
+        std::cout << "hPlus:\n" << hPlus  << "length: " << lPlus << std::endl<< std::endl;
+        std::cout << "hMinus:\n" << hMinus << "length: " << lMinus << std::endl << std::endl;
+#endif
+/*                h /= l;
+                hPlus /= lPlus;
+                hMinus /= lMinus;*/
+                
+/*                hPlus -= h;
+                h -= hMinus;*/
+                
+/*                std::cout << "forward:\n" << hPlus << std::endl;
+                std::cout << "backward:\n" << h << std::endl;*/
+                
+        result[j]  = hPlus;
+        result[j] -= hMinus;
+        result[j] /= 2*eps;
+                
+        TargetSpace q = evaluate(local);
+        Dune::FieldVector<double,TargetSpace::EmbeddedTangentVector::size> foo;
+        for (int l=0; l<dim; l++) {
+                    
+            for (int k=0; k<TargetSpace::EmbeddedTangentVector::size; k++)
+                foo[k] = result[j][k][l];
+
+            foo = q.projectOntoTangentSpace(foo);
+
+            for (int k=0; k<TargetSpace::EmbeddedTangentVector::size; k++)
+                result[j][k][l] = foo[k];
+                    
+        }
+        
+    }
     
 }
+
 #endif
-- 
GitLab