From 7be1ade759c3f3b9b059430329d79cee207eb778 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Tue, 19 Oct 2010 14:39:48 +0000
Subject: [PATCH] =?UTF-8?q?Der=20Code=20zum=20analytischen=20Berechnen=20d?=
 =?UTF-8?q?es=20Gradienten=20des=20Energiefunktionals=20=C3=BCbersetzt=20j?=
 =?UTF-8?q?etzt=20und=20st=C3=BCrzt=20nicht=20ab.=20=20Es=20kommt=20allerd?=
 =?UTF-8?q?ings=20noch=20Unfug=20raus.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

[[Imported from SVN: r6451]]
---
 dune/gfe/harmonicenergystiffness.hh | 19 ++++---
 dune/gfe/localgeodesicfefunction.hh | 81 ++++++++++++++++-------------
 2 files changed, 57 insertions(+), 43 deletions(-)

diff --git a/dune/gfe/harmonicenergystiffness.hh b/dune/gfe/harmonicenergystiffness.hh
index 0113dafc..d111784d 100644
--- a/dune/gfe/harmonicenergystiffness.hh
+++ b/dune/gfe/harmonicenergystiffness.hh
@@ -1,6 +1,8 @@
 #ifndef HARMONIC_ENERGY_LOCAL_STIFFNESS_HH
 #define HARMONIC_ENERGY_LOCAL_STIFFNESS_HH
 
+//#define HARMONIC_ENERGY_FD_GRADIENT
+
 #include <dune/common/fmatrix.hh>
 #include <dune/grid/common/quadraturerules.hh>
 
@@ -27,12 +29,13 @@ public:
     /** \brief Assemble the energy for a single element */
     RT energy (const Entity& e,
                const std::vector<TargetSpace>& localSolution) const;
-               
+
+#ifndef HARMONIC_ENERGY_FD_GRADIENT
     /** \brief Assemble the gradient of the energy functional on one element */
     virtual void assembleEmbeddedGradient(const Entity& element,
                                   const std::vector<TargetSpace>& solution,
                                   std::vector<typename TargetSpace::EmbeddedTangentVector>& gradient) const;
-
+#endif
 };
 
 template <class GridView, class TargetSpace>
@@ -97,7 +100,7 @@ energy(const Entity& element,
     return 0.5 * energy;
 }
 
-
+#ifndef HARMONIC_ENERGY_FD_GRADIENT
 template <class GridView, class TargetSpace>
 void HarmonicEnergyLocalStiffness<GridView, TargetSpace>::
 assembleEmbeddedGradient(const Entity& element,
@@ -141,7 +144,7 @@ assembleEmbeddedGradient(const Entity& element,
         // loop over all the element's degrees of freedom and compute the gradient wrt it
         for (size_t i=0; i<localSolution.size(); i++) {
          
-            Dune::array<Dune::FieldMatrix<double,gridDim,TargetSpace::EmbeddedTangentVector::size>, TargetSpace::EmbeddedTangentVector::size> derivativeDerivative;
+            Tensor3<double, TargetSpace::EmbeddedTangentVector::size, gridDim,TargetSpace::EmbeddedTangentVector::size> derivativeDerivative;
             localGeodesicFEFunction.evaluateDerivativeOfGradientWRTCoefficient(quadPos, i, derivativeDerivative);
         
             for (int j=0; j<derivative.rows; j++) {
@@ -154,11 +157,11 @@ assembleEmbeddedGradient(const Entity& element,
                 
             }
             
-            
-            
         }
-    }
-}
 
+	}
+
+}
+#endif
 #endif
 
diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh
index 1f5b4943..c2fe8147 100644
--- a/dune/gfe/localgeodesicfefunction.hh
+++ b/dune/gfe/localgeodesicfefunction.hh
@@ -44,6 +44,17 @@ Dune::FieldMatrix<K,m,n> operator- ( const Dune::FieldMatrix<K, m, n> &A, const
     return ret;
 }
 
+#if 0
+template< class K, int m, int n>
+void transpose(Dune::FieldMatrix<K, m, n> &A)
+{
+   for( size_type i = 0; i < m; ++i )
+        for( size_type j = 0; j < i; ++j )
+			std::swap(A[i][j], A[j][i]);
+}
+#endif
+
+
 /** \brief A function defined by simplicial geodesic interpolation 
            from the reference element to a Riemannian manifold.
     
@@ -56,7 +67,7 @@ class LocalGeodesicFEFunction
 {
     
     typedef typename TargetSpace::EmbeddedTangentVector EmbeddedTangentVector;
-    static const int targetDim = EmbeddedTangentVector::size;
+    static const int embeddedDim = EmbeddedTangentVector::size;
 
 public:
 
@@ -77,7 +88,7 @@ public:
     /** \brief Evaluate the derivative of the gradient of the function with respect to a coefficient */
     void evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>& local,
                                                     int coefficient,
-                                                    Dune::array<Dune::FieldMatrix<double,dim,TargetSpace::EmbeddedTangentVector::size>, TargetSpace::EmbeddedTangentVector::size>& result) const;
+                                                    Tensor3<double, TargetSpace::EmbeddedTangentVector::size,dim,TargetSpace::EmbeddedTangentVector::size>& result) const;
 
 private:
 
@@ -103,22 +114,22 @@ private:
         return result;
     }
 
-    static Dune::FieldMatrix<double,targetDim,targetDim> pseudoInverse(const Dune::FieldMatrix<double,targetDim,targetDim>& A)
+    static Dune::FieldMatrix<double,embeddedDim,embeddedDim> pseudoInverse(const Dune::FieldMatrix<double,embeddedDim,embeddedDim>& A)
     {
-        Dune::FieldMatrix<double,targetDim,targetDim> U = A;
-        Dune::FieldVector<double,targetDim> W;
-        Dune::FieldMatrix<double,targetDim,targetDim> V;
+        Dune::FieldMatrix<double,embeddedDim,embeddedDim> U = A;
+        Dune::FieldVector<double,embeddedDim> W;
+        Dune::FieldMatrix<double,embeddedDim,embeddedDim> V;
 
         svdcmp(U,W,V);
 
         // pseudoInv = V W^{-1} U^T
-        Dune::FieldMatrix<double,targetDim,targetDim> UT;
+        Dune::FieldMatrix<double,embeddedDim,embeddedDim> UT;
 
-        for (int i=0; i<targetDim; i++)
-            for (int j=0; j<targetDim; j++)
+        for (int i=0; i<embeddedDim; i++)
+            for (int j=0; j<embeddedDim; j++)
                 UT[i][j] = U[j][i];
 
-        for (int i=0; i<targetDim; i++) {
+        for (int i=0; i<embeddedDim; i++) {
             if (std::abs(W[i]) > 1e-12)  // Diagonal may be zero, that's why we're using the pseudo inverse
                 UT[i] /= W[i];
             else
@@ -162,16 +173,14 @@ template <int dim, class ctype, class TargetSpace>
 Dune::FieldMatrix<ctype, TargetSpace::EmbeddedTangentVector::size, dim> LocalGeodesicFEFunction<dim,ctype,TargetSpace>::
 evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const
 {
-    const int targetDim = EmbeddedTangentVector::size;
-
-    Dune::FieldMatrix<ctype, targetDim, dim> result;
+    Dune::FieldMatrix<ctype, embeddedDim, dim> result;
 
 #if 0  // this is probably faster than the general implementation, but we leave it out for testing purposes
     if (dim==1) {
 
         EmbeddedTangentVector tmp = TargetSpace::interpolateDerivative(coefficients_[0], coefficients_[1], local[0]);
 
-        for (int i=0; i<targetDim; i++)
+        for (int i=0; i<embeddedDim; i++)
             result[i][0] = tmp[i];
 
     }
@@ -189,23 +198,23 @@ evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const
     Dune::FieldMatrix<ctype,dim+1,dim> B = referenceToBarycentricLinearPart();
 
     // compute negative derivative of F(w,q) (the derivative of the weighted distance fctl) wrt to w
-    Dune::FieldMatrix<ctype,targetDim,dim+1> dFdw;
+    Dune::FieldMatrix<ctype,embeddedDim,dim+1> dFdw;
     for (int i=0; i<dim+1; i++) {
-        Dune::FieldVector<ctype,targetDim> tmp = TargetSpace::derivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], q);
-        for (int j=0; j<targetDim; j++)
+        Dune::FieldVector<ctype,embeddedDim> tmp = TargetSpace::derivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], q);
+        for (int j=0; j<embeddedDim; j++)
             dFdw[j][i] = tmp[j];
     }
 
     dFdw *= -1;
 
     // multiply the two previous matrices: the result is the right hand side
-    Dune::FieldMatrix<ctype,targetDim,dim> RHS = dFdw * B;
+    Dune::FieldMatrix<ctype,embeddedDim,dim> RHS = dFdw * B;
 
     // the actual system matrix
     std::vector<ctype> w = barycentricCoordinates(local);
     AverageDistanceAssembler<TargetSpace> assembler(coefficients_, w);
     
-    Dune::FieldMatrix<ctype,targetDim,targetDim> dFdq(0);
+    Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdq(0);
     assembler.assembleHessian(q,dFdq);
 
     // ////////////////////////////////////
@@ -215,18 +224,18 @@ evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const
     // dFDq is not invertible, if the target space is embedded into a higher-dimensional
     // Euclidean space.  Therefore we use its pseudo inverse.  I don't think that is the
     // best way, though.
-    Dune::FieldMatrix<ctype,targetDim,targetDim> dFdqPseudoInv = pseudoInverse(dFdq);
+    Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdqPseudoInv = pseudoInverse(dFdq);
 
     for (int i=0; i<dim; i++) {
 
-        Dune::FieldVector<ctype,targetDim> rhs, x;
-        for (int j=0; j<targetDim; j++)
+        Dune::FieldVector<ctype,embeddedDim> rhs, x;
+        for (int j=0; j<embeddedDim; j++)
             rhs[j] = RHS[j][i];
 
         //dFdq.solve(x, rhs);
         dFdqPseudoInv.mv(rhs,x);
 
-        for (int j=0; j<targetDim; j++)
+        for (int j=0; j<embeddedDim; j++)
             result[j][i] = x[j];
 
     }
@@ -265,9 +274,9 @@ template <int dim, class ctype, class TargetSpace>
 void LocalGeodesicFEFunction<dim,ctype,TargetSpace>::
 evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>& local,
                                            int coefficient,
-                                           Dune::array<Dune::FieldMatrix<double,dim,TargetSpace::EmbeddedTangentVector::size>, TargetSpace::EmbeddedTangentVector::size>& result) const
+                                           Tensor3<double, TargetSpace::EmbeddedTangentVector::size,dim,TargetSpace::EmbeddedTangentVector::size>& result) const
 {
-    const int targetDim = EmbeddedTangentVector::size;
+    const int embeddedDim = EmbeddedTangentVector::size;
     
     // the function value at the point where we are evaluating the derivative
     TargetSpace q = evaluate(local);
@@ -276,10 +285,10 @@ evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>&
     Dune::FieldMatrix<ctype,dim+1,dim> B = referenceToBarycentricLinearPart();
     
     // compute derivate of F(w,q) (the derivative of the weighted distance fctl) wrt to w
-    Dune::FieldMatrix<ctype,targetDim,dim+1> dFdw;
+    Dune::FieldMatrix<ctype,embeddedDim,dim+1> dFdw;
     for (int i=0; i<dim+1; i++) {
-        Dune::FieldVector<ctype,targetDim> tmp = TargetSpace::derivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], q);
-        for (int j=0; j<targetDim; j++)
+        Dune::FieldVector<ctype,embeddedDim> tmp = TargetSpace::derivativeOfDistanceSquaredWRTSecondArgument(coefficients_[i], q);
+        for (int j=0; j<embeddedDim; j++)
             dFdw[j][i] = tmp[j];
     }
     
@@ -287,29 +296,31 @@ evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>&
     std::vector<ctype> w = barycentricCoordinates(local);
     AverageDistanceAssembler<TargetSpace> assembler(coefficients_, w);
     
-    Dune::FieldMatrix<ctype,targetDim,targetDim> dFdq(0);
+    Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdq(0);
     assembler.assembleHessian(q,dFdq);
     
    
-    Tensor3<double,dim+1,targetDim,dim+1> dcDwF;
-    for (size_t i=0; i<dcDwF.size(); i++)
-        dcDwF[i] = TargetSpace::secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument(coefficients_[i], q);
+	Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> mixedDerivative = TargetSpace::secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument(coefficients_[coefficient], q);
+    Tensor3<double,embeddedDim,embeddedDim,dim+1> dpDwF(0);
+	for (int i=0; i<embeddedDim; i++)
+		for (int j=0; j<embeddedDim; j++)
+			dpDwF[i][j][coefficient] = mixedDerivative[i][j];
     
     
     // dFDq is not invertible, if the target space is embedded into a higher-dimensional
     // Euclidean space.  Therefore we use its pseudo inverse.  I don't think that is the
     // best way, though.
-    Dune::FieldMatrix<ctype,targetDim,targetDim> dFdqPseudoInv = pseudoInverse(dFdq);
+    Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdqPseudoInv = pseudoInverse(dFdq);
     
     // Put it all together
     for (size_t i=0; i<result.size(); i++) {
         
         //
-        Tensor3<double,targetDim,targetDim,targetDim> dcDqF
+        Tensor3<double,embeddedDim,embeddedDim,embeddedDim> dcDqF
            =  TargetSpace::thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument(coefficients_[i], q);
     
     
-        result[i] = dFdqPseudoInv * ( dcDqF[i] * dFdqPseudoInv * dFdw - dcDwF[i]) * B;   
+        result[i] = dFdqPseudoInv * ( dcDqF[i] * dFdqPseudoInv * dFdw - dpDwF[i]) * B;   
      
     }
     
-- 
GitLab