Skip to content
Snippets Groups Projects
Commit 85cb77bd authored by Sander, Oliver's avatar Sander, Oliver
Browse files

Modernize target space finite difference testing

parent 06a9cb0d
No related branches found
No related tags found
1 merge request!93Enable more tests for the various TargetSpace classes
......@@ -29,23 +29,17 @@ double diameter(const std::vector<TargetSpace>& v)
const double eps = 1e-4;
template <class TargetSpace>
double energy(const TargetSpace& a, const TargetSpace& b)
double distanceSquared(const TargetSpace& a, const TargetSpace& b)
{
return TargetSpace::distance(a,b) * TargetSpace::distance(a,b);
return Dune::power(TargetSpace::distance(a,b), 2);
}
// Squared distance between two points slightly off the manifold.
// This is required for finite difference approximations.
template <class TargetSpace, int dim>
double energy(const TargetSpace& a, const FieldVector<double,dim>& b)
double distanceSquared(const FieldVector<double,dim>& a, const FieldVector<double,dim>& b)
{
#warning Cast where there should not be one
return TargetSpace::distance(a,TargetSpace(b)) * TargetSpace::distance(a,TargetSpace(b));
}
template <class TargetSpace, int dim>
double energy(const FieldVector<double,dim>& a, const FieldVector<double,dim>& b)
{
#warning Cast where there should not be one
return TargetSpace::distance(TargetSpace(a),TargetSpace(b)) * TargetSpace::distance(TargetSpace(a),TargetSpace(b));
return Dune::power(TargetSpace::distance(TargetSpace(a),TargetSpace(b)), 2);
}
/** \brief Compute the Riemannian Hessian of the squared distance function in global coordinates
......@@ -67,15 +61,15 @@ FieldMatrix<double,worldDim,worldDim> getSecondDerivativeOfSecondArgumentFD(cons
for (size_t i=0; i<spaceDim; i++) {
for (size_t j=0; j<spaceDim; j++) {
FieldVector<double,worldDim> epsXi = B[i]; epsXi *= eps;
FieldVector<double,worldDim> epsEta = B[j]; epsEta *= eps;
FieldVector<double,worldDim> epsXi = eps * B[i];
FieldVector<double,worldDim> epsEta = eps * B[j];
FieldVector<double,worldDim> minusEpsXi = epsXi; minusEpsXi *= -1;
FieldVector<double,worldDim> minusEpsEta = epsEta; minusEpsEta *= -1;
FieldVector<double,worldDim> minusEpsXi = -1 * epsXi;
FieldVector<double,worldDim> minusEpsEta = -1 * epsEta;
double forwardValue = energy(a,TargetSpace::exp(b,epsXi+epsEta)) - energy(a, TargetSpace::exp(b,epsXi)) - energy(a,TargetSpace::exp(b,epsEta));
double centerValue = energy(a,b) - energy(a,b) - energy(a,b);
double backwardValue = energy(a,TargetSpace::exp(b,minusEpsXi + minusEpsEta)) - energy(a, TargetSpace::exp(b,minusEpsXi)) - energy(a,TargetSpace::exp(b,minusEpsEta));
double forwardValue = distanceSquared(a,TargetSpace::exp(b,epsXi+epsEta)) - distanceSquared(a, TargetSpace::exp(b,epsXi)) - distanceSquared(a,TargetSpace::exp(b,epsEta));
double centerValue = distanceSquared(a,b) - distanceSquared(a,b) - distanceSquared(a,b);
double backwardValue = distanceSquared(a,TargetSpace::exp(b,minusEpsXi + minusEpsEta)) - distanceSquared(a, TargetSpace::exp(b,minusEpsXi)) - distanceSquared(a,TargetSpace::exp(b,minusEpsEta));
d2d2_fd[i][j] = 0.5 * (forwardValue - 2*centerValue + backwardValue) / (eps*eps);
......@@ -111,7 +105,7 @@ void testOrthonormalFrame(const TargetSpace& a)
}
template <class TargetSpace>
void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testDerivativeOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
static const size_t embeddedDim = TargetSpace::embeddedDim;
......@@ -126,14 +120,12 @@ void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
typename TargetSpace::TangentVector d2_fd;
for (size_t i=0; i<TargetSpace::TangentVector::dimension; i++) {
typename TargetSpace::EmbeddedTangentVector fwVariation = B[i];
typename TargetSpace::EmbeddedTangentVector bwVariation = B[i];
fwVariation *= eps;
bwVariation *= -eps;
typename TargetSpace::EmbeddedTangentVector fwVariation = eps * B[i];
typename TargetSpace::EmbeddedTangentVector bwVariation = -eps * B[i];
TargetSpace bPlus = TargetSpace::exp(b,fwVariation);
TargetSpace bMinus = TargetSpace::exp(b,bwVariation);
d2_fd[i] = (energy(a,bPlus) - energy(a,bMinus)) / (2*eps);
d2_fd[i] = (distanceSquared(a,bPlus) - distanceSquared(a,bMinus)) / (2*eps);
}
// transform into embedded coordinates
......@@ -150,7 +142,7 @@ void testDerivativeOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
}
template <class TargetSpace>
void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
static const int embeddedDim = TargetSpace::embeddedDim;
......@@ -162,9 +154,7 @@ void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
// finite-difference approximation
FieldMatrix<double,embeddedDim,embeddedDim> d2d2_fd = getSecondDerivativeOfSecondArgumentFD<TargetSpace,embeddedDim>(a,b);
FieldMatrix<double,embeddedDim,embeddedDim> d2d2_diff = d2d2;
d2d2_diff -= d2d2_fd;
if ( (d2d2_diff).infinity_norm() > 200*eps) {
if ( (d2d2 - d2d2_fd).infinity_norm() > 200*eps) {
std::cout << className(a) << ": Analytical second derivative does not match fd approximation." << std::endl;
std::cout << "d2d2 Analytical:" << std::endl << d2d2 << std::endl;
std::cout << "d2d2 FD :" << std::endl << d2d2_fd << std::endl;
......@@ -174,7 +164,7 @@ void testHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
}
template <class TargetSpace>
void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testMixedDerivativesOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
static const size_t embeddedDim = TargetSpace::embeddedDim;
......@@ -200,16 +190,13 @@ void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpa
bPlus[j] += eps;
bMinus[j] -= eps;
d1d2_fd[i][j] = (energy<TargetSpace>(aPlus,bPlus) + energy<TargetSpace>(aMinus,bMinus)
- energy<TargetSpace>(aPlus,bMinus) - energy<TargetSpace>(aMinus,bPlus)) / (4*eps*eps);
d1d2_fd[i][j] = (distanceSquared<TargetSpace>(aPlus,bPlus) + distanceSquared<TargetSpace>(aMinus,bMinus)
- distanceSquared<TargetSpace>(aPlus,bMinus) - distanceSquared<TargetSpace>(aMinus,bPlus)) / (4*eps*eps);
}
}
FieldMatrix<double,embeddedDim,embeddedDim> d1d2_diff = d1d2;
d1d2_diff -= d1d2_fd;
if ( (d1d2_diff).infinity_norm() > 200*eps ) {
if ( (d1d2 - d1d2_fd).infinity_norm() > 200*eps ) {
std::cout << className(a) << ": Analytical mixed second derivative does not match fd approximation." << std::endl;
std::cout << "d1d2 Analytical:" << std::endl << d1d2 << std::endl;
std::cout << "d1d2 FD :" << std::endl << d1d2_fd << std::endl;
......@@ -220,7 +207,7 @@ void testMixedDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpa
template <class TargetSpace>
void testDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testDerivativeOfHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
static const size_t embeddedDim = TargetSpace::embeddedDim;
......@@ -259,7 +246,7 @@ void testDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const Target
template <class TargetSpace>
void testMixedDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testMixedDerivativeOfHessianOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
static const size_t embeddedDim = TargetSpace::embeddedDim;
......@@ -298,38 +285,38 @@ void testMixedDerivativeOfHessianOfSquaredDistance(const TargetSpace& a, const T
template <class TargetSpace>
void testDerivativesOfSquaredDistance(const TargetSpace& a, const TargetSpace& b)
void testDerivativesOfDistanceSquared(const TargetSpace& a, const TargetSpace& b)
{
///////////////////////////////////////////////////////////////////
// Test derivative with respect to second argument
///////////////////////////////////////////////////////////////////
testDerivativeOfSquaredDistance<TargetSpace>(a,b);
testDerivativeOfDistanceSquared<TargetSpace>(a,b);
///////////////////////////////////////////////////////////////////
// Test second derivative with respect to second argument
///////////////////////////////////////////////////////////////////
testHessianOfSquaredDistance<TargetSpace>(a,b);
testHessianOfDistanceSquared<TargetSpace>(a,b);
//////////////////////////////////////////////////////////////////////////////
// Test mixed second derivative with respect to first and second argument
//////////////////////////////////////////////////////////////////////////////
testMixedDerivativesOfSquaredDistance<TargetSpace>(a,b);
testMixedDerivativesOfDistanceSquared<TargetSpace>(a,b);
/////////////////////////////////////////////////////////////////////////////////////////////
// Test third derivative with respect to second argument
/////////////////////////////////////////////////////////////////////////////////////////////
testDerivativeOfHessianOfSquaredDistance<TargetSpace>(a,b);
testDerivativeOfHessianOfDistanceSquared<TargetSpace>(a,b);
/////////////////////////////////////////////////////////////////////////////////////////////
// Test mixed third derivative with respect to first (once) and second (twice) argument
/////////////////////////////////////////////////////////////////////////////////////////////
testMixedDerivativeOfHessianOfSquaredDistance<TargetSpace>(a,b);
testMixedDerivativeOfHessianOfDistanceSquared<TargetSpace>(a,b);
}
......@@ -357,7 +344,7 @@ void test()
if (diameter(testPointPair) > TargetSpace::convexityRadius)
continue;
testDerivativesOfSquaredDistance<TargetSpace>(testPoints[i], testPoints[j]);
testDerivativesOfDistanceSquared<TargetSpace>(testPoints[i], testPoints[j]);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment