From 6c6aafa4f3441f396bb93d2464780a39c0ec539a Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Mon, 6 Feb 2012 07:43:41 +0000
Subject: [PATCH] add a method that compares the energy gradient to its fd
 approximation

[[Imported from SVN: r8401]]
---
 test/cosseratenergytest.cc | 123 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 1 deletion(-)

diff --git a/test/cosseratenergytest.cc b/test/cosseratenergytest.cc
index 1ad6372f..c6b8ec11 100644
--- a/test/cosseratenergytest.cc
+++ b/test/cosseratenergytest.cc
@@ -229,11 +229,126 @@ void testFrameInvariance()
 }
 
 
+template <int domainDim>
+void testEnergyGradient()
+{
+    std::cout << " --- Testing the gradient of the Cosserat energy functional, domain dimension: " << domainDim << " ---" << std::endl;
+
+    // ////////////////////////////////////////////////////////
+    //   Make a test grid consisting of a single simplex
+    // ////////////////////////////////////////////////////////
+
+    typedef UGGrid<domainDim> GridType;
+
+    GridFactory<GridType> factory;
+
+    FieldVector<double,dim> pos(0);
+    factory.insertVertex(pos);
+
+    for (int i=0; i<domainDim+1; i++) {
+        pos = 0;
+        pos[i] = 1;
+        factory.insertVertex(pos);
+    }
+
+    std::vector<unsigned int> v(domainDim+1);
+    for (int i=0; i<domainDim+1; i++)
+        v[i] = i;
+    factory.insertElement(GeometryType(GeometryType::simplex,dim), v);
+
+    const std::auto_ptr<GridType> grid(factory.createGrid());
+
+    
+    ////////////////////////////////////////////////////////////////////////////
+    //  Create a local assembler object
+    ////////////////////////////////////////////////////////////////////////////
+    
+    PQkLocalFiniteElementCache<double,double,GridType::dimension,1> feCache;
+    typedef typename PQkLocalFiniteElementCache<double,double,GridType::dimension,1>::FiniteElementType LocalFiniteElement;
+
+    //LocalGeodesicFEFunction<domainDim,double,LocalFiniteElement,TargetSpace> f(feCache.get(element),corners);
+
+    ParameterTree materialParameters;
+    materialParameters["thickness"] = "0.1";
+    materialParameters["mu"] = "3.8462e+05";
+    materialParameters["lambda"] = "2.7149e+05";
+    materialParameters["mu_c"] = "3.8462e+05";
+    materialParameters["L_c"] = "0.1";
+    materialParameters["q"] = "2.5";
+    materialParameters["kappa"] = "0.1";
+
+    ConstantFunction<Dune::FieldVector<double,GridType::dimension>, Dune::FieldVector<double,3> > zeroFunction(Dune::FieldVector<double,3>(0));
+    
+    CosseratEnergyLocalStiffness<typename GridType::LeafGridView,LocalFiniteElement,3> assembler(materialParameters,
+                                                                                                 NULL,
+                                                                                                 &zeroFunction);
+
+    // //////////////////////////////////////////////////////////////////////////////////////////
+    //   Compare the gradient of the energy function with a finite difference approximation
+    // //////////////////////////////////////////////////////////////////////////////////////////
+
+    std::vector<TargetSpace> testPoints;
+    ValueFactory<TargetSpace>::get(testPoints);
+
+    // Set up elements of SE(3)
+    std::vector<TargetSpace> coefficients(dim+1);
+
+    MultiIndex index(dim+1, testPoints.size());
+    int numIndices = index.cycle();
+    
+    std::vector<typename RigidBodyMotion<double,3>::TangentVector> gradient(coefficients.size());
+    std::vector<typename RigidBodyMotion<double,3>::TangentVector> fdGradient(coefficients.size());
+
+    for (int i=0; i<numIndices; i++, ++index) {
+        
+        for (int j=0; j<dim+1; j++)
+            coefficients[j] = testPoints[index[j]];
+
+        // Compute the analytical gradient
+        assembler.assembleGradient(*grid->template leafbegin<0>(),
+                                   feCache.get(grid->template leafbegin<0>()->type()),
+                                   coefficients,
+                                   gradient);
+        
+        // Compute the finite difference gradient
+        assembler.LocalGeodesicFEStiffness<typename UGGrid<domainDim>::LeafGridView,
+                                           LocalFiniteElement,
+                                           RigidBodyMotion<double,3> >::assembleGradient(*grid->template leafbegin<0>(),
+                                   feCache.get(grid->template leafbegin<0>()->type()),
+                                   coefficients,
+                                   fdGradient);
+        
+        // Check whether the two are the same
+        double diff = 0;
+        for (size_t j=0; j<gradient.size(); j++)
+            for (size_t k=0; k<gradient[j].size(); k++)
+                diff = std::max(diff, std::fabs(gradient[j][k] - fdGradient[j][k]));
+
+        if (diff > 1e-4) {
+         
+            std::cout << "Analytical and FD gradients differ!" << std::endl;
+            
+            std::cout << "gradient:" << std::endl;
+            for (size_t j=0; j<gradient.size(); j++)
+                std::cout << gradient[j] << std::endl;
+
+            std::cout << "fd gradient:" << std::endl;
+            for (size_t j=0; j<fdGradient.size(); j++)
+                std::cout << fdGradient[j] << std::endl;
+
+            abort();
+        }
+        
+    }
+    
+}
+
+
 int main(int argc, char** argv) try
 {
     const int domainDim = 2;
     std::cout << " --- Testing derivative of rotation matrix, domain dimension: " << domainDim << " ---" << std::endl;
-
+    
     std::vector<Rotation<double,3> > testPoints;
     
     ValueFactory<Rotation<double,3> >::get(testPoints);
@@ -260,6 +375,12 @@ int main(int argc, char** argv) try
     //////////////////////////////////////////////////////////////////////////////////////
     
     testFrameInvariance<domainDim>();
+
+    //////////////////////////////////////////////////////////////////////////////////////
+    //   Test the gradient of the energy functional
+    //////////////////////////////////////////////////////////////////////////////////////
+    
+    testEnergyGradient<domainDim>();
     
 } catch (Exception e) {
 
-- 
GitLab