diff --git a/test/adolctest.cc b/test/adolctest.cc new file mode 100644 index 0000000000000000000000000000000000000000..d7d627e7d0e4824f81e20d574a9b196d6a5fdfa0 --- /dev/null +++ b/test/adolctest.cc @@ -0,0 +1,274 @@ +/*---------------------------------------------------------------------------- + ADOL-C -- Automatic Differentiation by Overloading in C++ + File: speelpenning.cpp + Revision: $Id: speelpenning.cpp 299 2012-03-21 16:08:40Z kulshres $ + Contents: speelpennings example, described in the manual + + Copyright (c) Andrea Walther, Andreas Griewank, Andreas Kowarz, + Hristo Mitev, Sebastian Schlenkrich, Jean Utke, Olaf Vogel + + This file is part of ADOL-C. This software is provided as open source. + Any use, reproduction, or distribution of the software constitutes + recipient's acceptance of the terms of the accompanying license file. + +---------------------------------------------------------------------------*/ + +/****************************************************************************/ +/* INCLUDES */ +#include "config.h" + +#include <adolc/adouble.h> // use of active doubles +#include <adolc/drivers/drivers.h> // use of "Easy to Use" drivers +// gradient(.) and hessian(.) +#include <adolc/taping.h> // use of taping + +#include <iostream> +#include <vector> + +#include <cstdlib> +#include <math.h> + +namespace std +{ + adouble max(adouble a, adouble b) { + return fmax(a,b); + } + + adouble sqrt(adouble a) { + return sqrt(a); + } + + adouble abs(adouble a) { + return fabs(a); + } + + adouble pow(const adouble& a, const adouble& b) { + return pow(a,b); + } + + bool isnan(adouble a) { + return std::isnan(a.value()); + } + + bool isinf(adouble a) { + return std::isinf(a.value()); + } + +} + +#include <dune/grid/yaspgrid.hh> +#include <dune/geometry/quadraturerules.hh> + +#include <dune/localfunctions/lagrange/q1.hh> + +#include <dune/gfe/realtuple.hh> +#include <dune/gfe/localgeodesicfefunction.hh> +#include <dune/gfe/harmonicenergystiffness.hh> + +using namespace Dune; + + +#if 1 +template <class GridView, class LocalFiniteElement, class TargetSpace> +double +energy(const typename GridView::template Codim<0>::Entity& element, + const LocalFiniteElement& localFiniteElement, + const std::vector<TargetSpace>& localPureSolution) +{ + double pureEnergy; + typedef RealTuple<adouble,1> ADTargetSpace; + std::vector<ADTargetSpace> localSolution(localPureSolution.size()); + + typedef typename TargetSpace::template rebind<adouble>::other ATargetSpace; + + HarmonicEnergyLocalStiffness<GridView,LocalFiniteElement,ATargetSpace> assembler; + + trace_on(1); + + adouble energy = 0; + + for (size_t i=0; i<localSolution.size(); i++) + localSolution[i] <<= localPureSolution[i]; + + energy = assembler.energy(element,localFiniteElement,localSolution); + + energy >>= pureEnergy; + + trace_off(1); + + return pureEnergy; +} +#endif + +#if 0 +template <class GridView, class LocalFiniteElement, class TargetSpace> +double +energy(const typename GridView::template Codim<0>::Entity& element, + const LocalFiniteElement& localFiniteElement, + const std::vector<TargetSpace>& localPureSolution) +{ + typedef RealTuple<adouble,1> ADTargetSpace; + std::vector<ADTargetSpace> localSolution(localPureSolution.size()); + + trace_on(1); + + for (size_t i=0; i<localSolution.size(); i++) + localSolution[i] <<= localPureSolution[i]; + + assert(element.type() == localFiniteElement.type()); + + static const int gridDim = GridView::dimension; + typedef typename GridView::template Codim<0>::Entity::Geometry Geometry; + + double pureEnergy; + adouble energy = 0; + LocalGeodesicFEFunction<gridDim, adouble, LocalFiniteElement, ADTargetSpace> localGeodesicFEFunction(localFiniteElement, + localSolution); + + int quadOrder = (element.type().isSimplex()) ? (localFiniteElement.localBasis().order()-1) * 2 + : localFiniteElement.localBasis().order() * 2 * gridDim; + + + + const Dune::QuadratureRule<double, gridDim>& quad + = Dune::QuadratureRules<double, gridDim>::rule(element.type(), quadOrder); + + for (size_t pt=0; pt<quad.size(); pt++) { + + // Local position of the quadrature point + const Dune::FieldVector<double,gridDim>& quadPos = quad[pt].position(); + + const double integrationElement = element.geometry().integrationElement(quadPos); + + const typename Geometry::JacobianInverseTransposed& jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos); + + double weight = quad[pt].weight() * integrationElement; + + // The derivative of the local function defined on the reference element + Dune::FieldMatrix<adouble, TargetSpace::EmbeddedTangentVector::dimension, gridDim> referenceDerivative = localGeodesicFEFunction.evaluateDerivative(quadPos); + + // The derivative of the function defined on the actual element + Dune::FieldMatrix<adouble, TargetSpace::EmbeddedTangentVector::dimension, gridDim> derivative(0); + + for (size_t comp=0; comp<referenceDerivative.N(); comp++) + jacobianInverseTransposed.umv(referenceDerivative[comp], derivative[comp]); + + // Add the local energy density + // The Frobenius norm is the correct norm here if the metric of TargetSpace is the identity. + // (And if the metric of the domain space is the identity, which it always is here.) + energy += weight * derivative.frobenius_norm2(); + + } + + energy *= 0.5; + energy >>= pureEnergy; + + trace_off(1); + + return pureEnergy; +} +#endif + +/****************************************************************************/ +/* MAIN PROGRAM */ +int main() { + + size_t n = 4; + + //std::cout << className< decltype(adouble() / double()) >() << std::endl; + + const int dim = 2; + typedef YaspGrid<dim> GridType; + FieldVector<double,dim> l(1); + std::array<int,dim> elements = {{1, 1}}; + GridType grid(l,elements); + + typedef Q1LocalFiniteElement<double,double,dim> LocalFE; + LocalFE localFiniteElement; + + typedef RealTuple<double,1> TargetSpace; + std::vector<TargetSpace> localSolution(n); + localSolution[0] = TargetSpace(0); + localSolution[1] = TargetSpace(0); + localSolution[2] = TargetSpace(1); + localSolution[3] = TargetSpace(1); + + double laplaceEnergy = energy<GridType::LeafGridView,LocalFE, TargetSpace>(*grid.leafbegin<0>(), localFiniteElement, localSolution); + + std::cout << "Laplace energy: " << laplaceEnergy << std::endl; + + std::vector<double> xp(n); + for (size_t i=0; i<n; i++) + xp[i] = 1; + + double** H = (double**) malloc(n*sizeof(double*)); + for(size_t i=0; i<n; i++) + H[i] = (double*)malloc((i+1)*sizeof(double)); + hessian(1,n,xp.data(),H); // H equals (n-1)g since g is + + std::cout << "Hessian:" << std::endl; + for(size_t i=0; i<n; i++) { + for (size_t j=0; j<n; j++) { + double value = (j<=i) ? H[i][j] : H[j][i]; + std::cout << value << " "; + } + std::cout << std::endl; + } + + // Get gradient +#if 0 + int n,i,j; + size_t tape_stats[STAT_SIZE]; + + cout << "SPEELPENNINGS PRODUCT (ADOL-C Documented Example)\n\n"; + cout << "number of independent variables = ? \n"; + cin >> n; + + std::vector<double> xp(n); + double yp = 0.0; + std::vector<adouble> x(n); + adouble y = 1; + + for(i=0; i<n; i++) + xp[i] = (i+1.0)/(2.0+i); // some initialization + + trace_on(1); // tag = 1, keep = 0 by default + for(i=0; i<n; i++) { + x[i] <<= xp[i]; // or x <<= xp outside the loop + y *= x[i]; + } // end for + y >>= yp; + trace_off(1); + + tapestats(1,tape_stats); // reading of tape statistics + cout<<"maxlive "<<tape_stats[NUM_MAX_LIVES]<<"\n"; + // ..... print other tape stats + + double* g = new double[n]; + gradient(1,n,xp.data(),g); // gradient evaluation + + double** H = (double**) malloc(n*sizeof(double*)); + for(i=0; i<n; i++) + H[i] = (double*)malloc((i+1)*sizeof(double)); + hessian(1,n,xp.data(),H); // H equals (n-1)g since g is + + + + + double errg = 0; // homogeneous of degree n-1. + double errh = 0; + for(i=0; i<n; i++) + errg += fabs(g[i]-yp/xp[i]); // vanishes analytically. + for(i=0; i<n; i++) { + for(j=0; j<n; j++) { + if (i>j) // lower half of hessian + errh += fabs(H[i][j]-g[i]/xp[j]); + } // end for + } // end for + cout << yp-1/(1.0+n) << " error in function \n"; + cout << errg <<" error in gradient \n"; + cout << errh <<" consistency check \n"; +#endif + return 0; +} // end main +