From 55164cfc320bb005329d9c644a45190846c85bd2 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Thu, 2 Sep 2010 08:17:48 +0000 Subject: [PATCH] implement finite difference test for first and second derivative [[Imported from SVN: r6310]] --- test/unitvectortest.cc | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/test/unitvectortest.cc b/test/unitvectortest.cc index b2b35ef6..8e7019a2 100644 --- a/test/unitvectortest.cc +++ b/test/unitvectortest.cc @@ -3,11 +3,112 @@ #include <dune/gfe/unitvector.hh> #include <dune/gfe/rotation.hh> +/** \file + \brief Unit tests for the UnitVector class +*/ using namespace Dune; +const double eps = 1e-6; + +double square(double a) +{ + return a*a; +} + +template <int dim> +void testDerivativesOfSquaredDistance(const UnitVector<dim>& a, const UnitVector<dim>& b) +{ + + /////////////////////////////////////////////////////////////////// + // Test derivative with respect to second argument + /////////////////////////////////////////////////////////////////// + typename UnitVector<dim>::EmbeddedTangentVector d2 = UnitVector<dim>::derivativeOfDistanceSquaredWRTSecondArgument(a, b); + + // finite-difference approximation + typename UnitVector<dim>::EmbeddedTangentVector d2_fd; + for (size_t i=0; i<dim; i++) { + FieldVector<double,dim> bPlus = b.globalCoordinates(); + FieldVector<double,dim> bMinus = b.globalCoordinates(); + bPlus[i] += eps; + bMinus[i] -= eps; + d2_fd[i] = (square(UnitVector<dim>::distance(a,bPlus)) - square(UnitVector<dim>::distance(a,bMinus))) / (2*eps); + } + + std::cout << "Analytical: " << d2 << std::endl; + std::cout << "FD : " << d2_fd << std::endl; + + + /////////////////////////////////////////////////////////////////// + // Test second derivative with respect to second argument + /////////////////////////////////////////////////////////////////// + FieldMatrix<double,dim,dim> d2d2 = UnitVector<dim>::secondDerivativeOfDistanceSquaredWRTSecondArgument(a, b); + + // finite-difference approximation + FieldMatrix<double,dim,dim> d2d2_fd; + + for (size_t i=0; i<dim; i++) { + for (size_t j=0; j<dim; j++) { + + if (i==j) { + + FieldVector<double,dim> bPlus = b.globalCoordinates(); + FieldVector<double,dim> bMinus = b.globalCoordinates(); + bPlus[i] += eps; + bMinus[i] -= eps; + + d2d2_fd[i][i] = (square(UnitVector<dim>::distance(a,bPlus)) - 2*square(UnitVector<dim>::distance(a,b)) + square(UnitVector<dim>::distance(a,bMinus))) / (eps*eps); + } else { + + FieldVector<double,dim> bPlusPlus = b.globalCoordinates(); + FieldVector<double,dim> bPlusMinus = b.globalCoordinates(); + FieldVector<double,dim> bMinusPlus = b.globalCoordinates(); + FieldVector<double,dim> bMinusMinus = b.globalCoordinates(); + + bPlusPlus[i] += eps; bPlusPlus[j] += eps; + bPlusMinus[i] += eps; bPlusMinus[j] -= eps; + bMinusPlus[i] -= eps; bMinusPlus[j] += eps; + bMinusMinus[i] -= eps; bMinusMinus[j] -= eps; + + d2d2_fd[i][j] = (square(UnitVector<dim>::distance(a,bPlusPlus)) + square(UnitVector<dim>::distance(a,bMinusMinus)) + - square(UnitVector<dim>::distance(a,bPlusMinus)) - square(UnitVector<dim>::distance(a,bMinusPlus))) / (4*eps*eps); + } + } + } + + std::cout << "Analytical:\n" << d2d2 << std::endl; + std::cout << "FD :\n" << d2d2_fd << std::endl; + + ////////////////////////////////////////////////////////////////////////////// + // Test mixed second derivative with respect to first and second argument + ////////////////////////////////////////////////////////////////////////////// + + FieldMatrix<double,dim,dim> d1d2 = UnitVector<dim>::secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument(a, b); + + + ///////////////////////////////////////////////////////////////////////////////////////////// + // Test mixed third derivative with respect to first (once) and second (twice) argument + ///////////////////////////////////////////////////////////////////////////////////////////// + + Tensor3<double,dim,dim,dim> d1d2d2 = UnitVector<dim>::thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument(a, b); +} + int main() { + // Set up elements of S^1 + Dune::array<double,2> w0 = {{0,1}}; + UnitVector<2> uv0(w0); + Dune::array<double,2> w1 = {{1,1}}; + UnitVector<2> uv1(w1); + testDerivativesOfSquaredDistance<2>(uv0, uv1); + + Dune::array<double,3> w3_0 = {{0,1,0}}; + UnitVector<3> v3_0(w3_0); + Dune::array<double,3> w3_1 = {{1,1,0}}; + UnitVector<3> v3_1(w3_1); + testDerivativesOfSquaredDistance<3>(v3_0, v3_1); + +#if 0 // Set up elements of S^1 FieldVector<double,2> v; v[0] = 1; v[1] = 1; @@ -27,5 +128,6 @@ int main() std::cout << UnitVector<2>::secondDerivativeOfDistanceSquaredWRTSecondArgument(uv0, uv1) << std::endl; std::cout << Rotation<2,double>::secondDerivativeOfDistanceSquaredWRTSecondArgument(ro0, ro1) << std::endl; +#endif } -- GitLab