From 0787ae4a453ffc9191fa33aa2c5c178ccfe2daac Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Sun, 5 Oct 2014 19:10:26 +0000 Subject: [PATCH] Also test the Riemannian Hesse matrix [[Imported from SVN: r9912]] --- test/adolctest.cc | 122 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 29 deletions(-) diff --git a/test/adolctest.cc b/test/adolctest.cc index 0d710f5a..129a9931 100644 --- a/test/adolctest.cc +++ b/test/adolctest.cc @@ -6,8 +6,13 @@ #include <boost/multiprecision/mpfr.hpp> -//typedef double FDType; +//#define MULTIPRECISION + +#ifdef MULTIPRECISION typedef boost::multiprecision::mpfr_float_50 FDType; +#else +typedef double FDType; +#endif // Includes for the ADOL-C automatic differentiation library // Need to come before (almost) all others. @@ -31,6 +36,8 @@ typedef boost::multiprecision::mpfr_float_50 FDType; #include <dune/gfe/localgeodesicfestiffness.hh> #include <dune/gfe/localgeodesicfefunction.hh> #include <dune/gfe/cosseratenergystiffness.hh> +#include <dune/gfe/localgeodesicfeadolcstiffness.hh> +#include <dune/gfe/localgeodesicfefdstiffness.hh> // grid dimension const int dim = 2; @@ -45,7 +52,7 @@ using namespace Dune; /** \brief Assembles energy gradient and Hessian with ADOL-C */ template<class GridView, class LocalFiniteElement> -class LocalGeodesicFEADOLCStiffness +class LocalADOLCStiffness { // grid types typedef typename GridView::Grid::ctype DT; @@ -62,7 +69,7 @@ public: //! Dimension of the embedding space enum { embeddedBlocksize = TargetSpace::EmbeddedTangentVector::dimension }; - LocalGeodesicFEADOLCStiffness(const LocalGeodesicFEStiffness<GridView, LocalFiniteElement, ATargetSpace>* energy) + LocalADOLCStiffness(const LocalGeodesicFEStiffness<GridView, LocalFiniteElement, ATargetSpace>* energy) : localEnergy_(energy) {} @@ -88,8 +95,8 @@ public: template <class GridView, class LocalFiniteElement> -typename LocalGeodesicFEADOLCStiffness<GridView, LocalFiniteElement>::RT -LocalGeodesicFEADOLCStiffness<GridView, LocalFiniteElement>:: +typename LocalADOLCStiffness<GridView, LocalFiniteElement>::RT +LocalADOLCStiffness<GridView, LocalFiniteElement>:: energy(const Entity& element, const LocalFiniteElement& localFiniteElement, const std::vector<TargetSpace>& localSolution) const @@ -136,7 +143,7 @@ energy(const Entity& element, // as well return it. This saves assembly time. // /////////////////////////////////////////////////////////// template <class GridType, class LocalFiniteElement> -void LocalGeodesicFEADOLCStiffness<GridType, LocalFiniteElement>:: +void LocalADOLCStiffness<GridType, LocalFiniteElement>:: assembleGradientAndHessian(const Entity& element, const LocalFiniteElement& localFiniteElement, const std::vector<TargetSpace>& localSolution, @@ -203,7 +210,7 @@ assembleGradientAndHessian(const Entity& element, /** \brief Assembles energy gradient and Hessian with finite differences */ template<class GridView, class LocalFiniteElement, class field_type=double> -class LocalGeodesicFEFDStiffness +class LocalFDStiffness { // grid types typedef typename GridView::Grid::ctype DT; @@ -220,7 +227,7 @@ public: //! Dimension of the embedding space enum { embeddedBlocksize = TargetSpace::EmbeddedTangentVector::dimension }; - LocalGeodesicFEFDStiffness(const LocalGeodesicFEStiffness<GridView, LocalFiniteElement, ATargetSpace>* energy) + LocalFDStiffness(const LocalGeodesicFEStiffness<GridView, LocalFiniteElement, ATargetSpace>* energy) : localEnergy_(energy) {} @@ -237,7 +244,7 @@ public: // Compute gradient by finite-difference approximation // /////////////////////////////////////////////////////////// template <class GridType, class LocalFiniteElement, class field_type> -void LocalGeodesicFEFDStiffness<GridType, LocalFiniteElement, field_type>:: +void LocalFDStiffness<GridType, LocalFiniteElement, field_type>:: assembleGradientAndHessian(const Entity& element, const LocalFiniteElement& localFiniteElement, const std::vector<TargetSpace>& localSolution, @@ -251,7 +258,11 @@ assembleGradientAndHessian(const Entity& element, localHessian.setSize(nDofs, nDofs); localHessian = 0; +#ifdef MULTIPRECISION const field_type eps = 1e-10; +#else + const field_type eps = 1e-4; +#endif std::vector<ATargetSpace> localASolution(localSolution.size()); std::vector<typename ATargetSpace::CoordinateType> aRaw(localSolution.size()); @@ -308,7 +319,11 @@ assembleGradientAndHessian(const Entity& element, for (int j=0; j<embeddedBlocksize; j++) { field_type foo = (forwardEnergy[i][j] - backwardEnergy[i][j]) / (2*eps); +#ifdef MULTIPRECISION localGradient[i][j] = foo.template convert_to<double>(); +#else + localGradient[i][j] = foo; +#endif } /////////////////////////////////////////////////////////////////////////// @@ -349,8 +364,11 @@ assembleGradientAndHessian(const Entity& element, field_type backwardValue = localEnergy_->energy(element, localFiniteElement, backwardSolutionXiEta) - backwardEnergy[i][i2] - backwardEnergy[j][j2]; field_type foo = 0.5 * (forwardValue - 2*centerValue + backwardValue) / (eps*eps); +#ifdef MULTIPRECISION localHessian[i][j][i2][j2] = localHessian[j][i][j2][i2] = foo.template convert_to<double>(); - +#else + localHessian[i][j][i2][j2] = localHessian[j][i][j2][i2] = foo; +#endif } } } @@ -359,15 +377,16 @@ assembleGradientAndHessian(const Entity& element, // Compare two matrices -void compareMatrices(const Matrix<FieldMatrix<double,7,7> >& matrixA, std::string nameA, - const Matrix<FieldMatrix<double,7,7> >& matrixB, std::string nameB) +template <int N> +void compareMatrices(const Matrix<FieldMatrix<double,N,N> >& matrixA, std::string nameA, + const Matrix<FieldMatrix<double,N,N> >& matrixB, std::string nameB) { double maxAbsDifference = -1; double maxRelDifference = -1; - for(int i=0; i<matrixA.N(); i++) { + for(size_t i=0; i<matrixA.N(); i++) { - for (int j=0; j<matrixA.M(); j++ ) { + for (size_t j=0; j<matrixA.M(); j++ ) { for (int ii=0; ii<matrixA[i][j].N(); ii++) for (int jj=0; jj<matrixA[i][j].M(); jj++) @@ -396,6 +415,7 @@ int main (int argc, char *argv[]) try { typedef std::vector<TargetSpace> SolutionType; enum { embeddedBlocksize = TargetSpace::EmbeddedTangentVector::dimension }; + enum { blocksize = TargetSpace::TangentVector::dimension }; // /////////////////////////////////////// // Create the grid @@ -444,28 +464,46 @@ int main (int argc, char *argv[]) try // //////////////////////////////////////////////////////////// ParameterTree materialParameters; - materialParameters["thickness"] = "2.5e-5"; - materialParameters["mu"] = "5.6452e+09"; - materialParameters["lambda"] = "2.1796e+09"; - materialParameters["mu_c"] = "5.6452e+09"; + materialParameters["thickness"] = "1"; + materialParameters["mu"] = "1"; + materialParameters["lambda"] = "1"; + materialParameters["mu_c"] = "1"; materialParameters["L_c"] = "1"; materialParameters["q"] = "2"; materialParameters["kappa"] = "1"; + /////////////////////////////////////////////////////////////////////// + // Assemblers for the Euclidean derivatives in an embedding space + /////////////////////////////////////////////////////////////////////// + // Assembler using ADOL-C CosseratEnergyLocalStiffness<GridView, FEBasis::LocalFiniteElement, 3,adouble> cosseratEnergyADOLCLocalStiffness(materialParameters, nullptr, nullptr); - LocalGeodesicFEADOLCStiffness<GridView, - FEBasis::LocalFiniteElement> localGFEADOLCStiffness(&cosseratEnergyADOLCLocalStiffness); + LocalADOLCStiffness<GridView, + FEBasis::LocalFiniteElement> localADOLCStiffness(&cosseratEnergyADOLCLocalStiffness); CosseratEnergyLocalStiffness<GridView, FEBasis::LocalFiniteElement, 3,FDType> cosseratEnergyFDLocalStiffness(materialParameters, nullptr, nullptr); + LocalFDStiffness<GridView, + FEBasis::LocalFiniteElement,FDType> localFDStiffness(&cosseratEnergyFDLocalStiffness); + + /////////////////////////////////////////////////////////////////////// + // Assemblers for the Riemannian derivatives without embedding space + /////////////////////////////////////////////////////////////////////// + + // Assembler using ADOL-C + LocalGeodesicFEADOLCStiffness<GridView, + FEBasis::LocalFiniteElement, + TargetSpace> localGFEADOLCStiffness(&cosseratEnergyADOLCLocalStiffness); + LocalGeodesicFEFDStiffness<GridView, - FEBasis::LocalFiniteElement,FDType> localGFEFDStiffness(&cosseratEnergyFDLocalStiffness); + FEBasis::LocalFiniteElement, + TargetSpace, + FDType> localGFEFDStiffness(&cosseratEnergyFDLocalStiffness); // Compute and compare matrices auto it = gridView.template begin<0>(); @@ -477,7 +515,7 @@ int main (int argc, char *argv[]) try const int numOfBaseFct = feBasis.getLocalFiniteElement(*it).localBasis().size(); - // Extract local solution + // Extract local configuration std::vector<TargetSpace> localSolution(numOfBaseFct); for (int i=0; i<numOfBaseFct; i++) @@ -488,28 +526,54 @@ int main (int argc, char *argv[]) try std::vector<Dune::FieldVector<double,embeddedBlocksize> > localFDGradient(numOfBaseFct); Matrix<FieldMatrix<double,embeddedBlocksize,embeddedBlocksize> > localADHessian; - Matrix<FieldMatrix<double,7,7> > localADVMHessian; // VM: vector-mode - Matrix<FieldMatrix<double,7,7> > localFDHessian; - - // setup local matrix and gradient - localGFEADOLCStiffness.assembleGradientAndHessian(*it, + Matrix<FieldMatrix<double,embeddedBlocksize,embeddedBlocksize> > localADVMHessian; // VM: vector-mode + Matrix<FieldMatrix<double,embeddedBlocksize,embeddedBlocksize> > localFDHessian; + if (false) { + // Assemble Euclidean derivatives + localADOLCStiffness.assembleGradientAndHessian(*it, feBasis.getLocalFiniteElement(*it), localSolution, localADGradient, localADHessian, false); // 'true' means 'vector mode' - localGFEADOLCStiffness.assembleGradientAndHessian(*it, + localADOLCStiffness.assembleGradientAndHessian(*it, feBasis.getLocalFiniteElement(*it), localSolution, localADGradient, localADVMHessian, true); // 'true' means 'vector mode' - localGFEFDStiffness.assembleGradientAndHessian(*it, feBasis.getLocalFiniteElement(*it), localSolution, localFDGradient, localFDHessian); + localFDStiffness.assembleGradientAndHessian(*it, + feBasis.getLocalFiniteElement(*it), + localSolution, + localFDGradient, + localFDHessian); + // compare compareMatrices(localADHessian, "AD", localFDHessian, "FD"); compareMatrices(localADHessian, "AD scalar", localADVMHessian, "AD vector"); + } + // Assemble Riemannian derivatives + std::vector<Dune::FieldVector<double,blocksize> > localRiemannianADGradient(numOfBaseFct); + std::vector<Dune::FieldVector<double,blocksize> > localRiemannianFDGradient(numOfBaseFct); + + Matrix<FieldMatrix<double,blocksize,blocksize> > localRiemannianADHessian; + Matrix<FieldMatrix<double,blocksize,blocksize> > localRiemannianFDHessian; + + localGFEADOLCStiffness.assembleGradientAndHessian(*it, + feBasis.getLocalFiniteElement(*it), + localSolution, + localRiemannianADGradient); + + localGFEFDStiffness.assembleGradientAndHessian(*it, + feBasis.getLocalFiniteElement(*it), + localSolution, + localRiemannianFDGradient); + + // compare + compareMatrices(localGFEADOLCStiffness.A_, "Riemannian AD", localGFEFDStiffness.A_, "Riemannian FD"); + } // ////////////////////////////// -- GitLab