Newer
Older
#include <iostream>
#include <dune/common/fvector.hh>
#include <dune/grid/common/quadraturerules.hh>
#include <dune/gfe/rotation.hh>
#include <dune/gfe/realtuple.hh>
#include <dune/gfe/unitvector.hh>
#include <dune/gfe/localgeodesicfefunction.hh>
void testDerivativeTangentiality(const RealTuple<1>& x,
const FieldMatrix<double,1,domainDim>& derivative)
{
// By construction, derivatives of RealTuples are always tangent
}
// the columns of the derivative must be tangential to the manifold
template <int domainDim, int vectorDim>
void testDerivativeTangentiality(const UnitVector<vectorDim>& x,
const FieldMatrix<double,vectorDim,domainDim>& derivative)
for (int i=0; i<domainDim; i++) {
// The i-th column is a tangent vector if its scalar product with the global coordinates
// of x vanishes.
double sp = 0;
sp += x.globalCoordinates()[j] * derivative[j][i];
if (std::fabs(sp) > 1e-8)
DUNE_THROW(Dune::Exception, "Derivative is not tangential: Column: " << i << ", product: " << sp);
// the columns of the derivative must be tangential to the manifold
template <int domainDim, int vectorDim>
void testDerivativeTangentiality(const Rotation<vectorDim-1,double>& x,
const FieldMatrix<double,vectorDim,domainDim>& derivative)
{
}

Oliver Sander
committed
/** \brief Test whether interpolation is invariant under permutation of the simplex vertices
*/
template <int domainDim, class TargetSpace>

Oliver Sander
committed
void testPermutationInvariance(const std::vector<TargetSpace>& corners)
// works only for 2d domains
assert(domainDim==2);
std::vector<TargetSpace> cornersRotated1(domainDim+1);
std::vector<TargetSpace> cornersRotated2(domainDim+1);

Oliver Sander
committed
cornersRotated1[0] = cornersRotated2[2] = corners[1];
cornersRotated1[1] = cornersRotated2[0] = corners[2];
cornersRotated1[2] = cornersRotated2[1] = corners[0];
LocalGeodesicFEFunction<2,double,TargetSpace> f0(corners);
LocalGeodesicFEFunction<2,double,TargetSpace> f1(cornersRotated1);
LocalGeodesicFEFunction<2,double,TargetSpace> f2(cornersRotated2);

Oliver Sander
committed
// A quadrature rule as a set of test points
const Dune::QuadratureRule<double, domainDim>& quad
= Dune::QuadratureRules<double, domainDim>::rule(GeometryType(GeometryType::simplex,domainDim), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {

Oliver Sander
committed
const Dune::FieldVector<double,domainDim>& quadPos = quad[pt].position();
Dune::FieldVector<double,domainDim> l0 = quadPos;
Dune::FieldVector<double,domainDim> l1, l2;
// evaluate the three functions
TargetSpace v0 = f0.evaluate(l0);
TargetSpace v1 = f1.evaluate(l1);
TargetSpace v2 = f2.evaluate(l2);
assert(TargetSpace::distance(v0,v1) < eps);
assert(TargetSpace::distance(v0,v2) < eps);

Oliver Sander
committed
}
template <int domainDim, class TargetSpace>
void testDerivative(const std::vector<TargetSpace>& corners)
{
// Make local fe function to be tested
LocalGeodesicFEFunction<domainDim,double,TargetSpace> f(corners);
// A quadrature rule as a set of test points
int quadOrder = 3;
const Dune::QuadratureRule<double, domainDim>& quad
= Dune::QuadratureRules<double, domainDim>::rule(GeometryType(GeometryType::simplex,domainDim), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {
const Dune::FieldVector<double,domainDim>& quadPos = quad[pt].position();
Dune::FieldMatrix<double, TargetSpace::EmbeddedTangentVector::size, domainDim> derivative = f.evaluateDerivative(quadPos);
// evaluate fd approximation of derivative
Dune::FieldMatrix<double, TargetSpace::EmbeddedTangentVector::size, domainDim> fdDerivative = f.evaluateDerivativeFD(quadPos);
Dune::FieldMatrix<double, TargetSpace::EmbeddedTangentVector::size, domainDim> diff = derivative;
diff -= fdDerivative;
if ( diff.infinity_norm() > 100*eps ) {
std::cout << className(corners[0]) << ": Analytical gradient does not match fd approximation." << std::endl;
std::cout << "Analytical: " << derivative << std::endl;
std::cout << "FD : " << fdDerivative << std::endl;
}
testDerivativeTangentiality(f.evaluate(quadPos), derivative);
}
}
template <int domainDim, class TargetSpace>
void testDerivativeOfValueWRTCoefficients(const std::vector<TargetSpace>& corners)
{
// Make local fe function to be tested
LocalGeodesicFEFunction<domainDim,double,TargetSpace> f(corners);
// A quadrature rule as a set of test points
int quadOrder = 3;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
const Dune::QuadratureRule<double, domainDim>& quad
= Dune::QuadratureRules<double, domainDim>::rule(GeometryType(GeometryType::simplex,domainDim), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {
Dune::FieldVector<double,domainDim> quadPos = quad[pt].position();
// loop over the coefficients
for (size_t i=0; i<corners.size(); i++) {
// evaluate actual derivative
FieldMatrix<double, TargetSpace::EmbeddedTangentVector::size, TargetSpace::EmbeddedTangentVector::size> derivative;
f.evaluateDerivativeOfValueWRTCoefficient(quadPos, i, derivative);
// evaluate fd approximation of derivative
FieldMatrix<double, TargetSpace::EmbeddedTangentVector::size, TargetSpace::EmbeddedTangentVector::size> fdDerivative;
f.evaluateFDDerivativeOfValueWRTCoefficient(quadPos, i, fdDerivative);
if ( (derivative - fdDerivative).infinity_norm() > eps ) {
std::cout << className(corners[0]) << ": Analytical derivative of value does not match fd approximation." << std::endl;
std::cout << "coefficient: " << i << std::endl;
std::cout << "quad pos: " << quadPos << std::endl;
std::cout << "gfe: ";
for (int j=0; j<domainDim+1; j++)
std::cout << ", " << corners[j];
std::cout << std::endl;
std::cout << "Analytical:\n " << derivative << std::endl;
std::cout << "FD :\n " << fdDerivative << std::endl;
assert(false);
}
//testDerivativeTangentiality(f.evaluate(quadPos), derivative);
}
}
}
template <int domainDim, class TargetSpace>
void testDerivativeOfGradientWRTCoefficients(const std::vector<TargetSpace>& corners)
{
// Make local fe function to be tested
LocalGeodesicFEFunction<domainDim,double,TargetSpace> f(corners);
// A quadrature rule as a set of test points
int quadOrder = 3;
const Dune::QuadratureRule<double, domainDim>& quad
= Dune::QuadratureRules<double, domainDim>::rule(GeometryType(GeometryType::simplex,domainDim), quadOrder);
for (size_t pt=0; pt<quad.size(); pt++) {
const Dune::FieldVector<double,domainDim>& quadPos = quad[pt].position();
// loop over the coefficients
for (size_t i=0; i<corners.size(); i++) {
// evaluate actual derivative
Tensor3<double, TargetSpace::EmbeddedTangentVector::size, TargetSpace::EmbeddedTangentVector::size, domainDim> derivative;
f.evaluateDerivativeOfGradientWRTCoefficient(quadPos, i, derivative);
// evaluate fd approximation of derivative
Tensor3<double, TargetSpace::EmbeddedTangentVector::size, TargetSpace::EmbeddedTangentVector::size, domainDim> fdDerivative;
f.evaluateFDDerivativeOfGradientWRTCoefficient(quadPos, i, fdDerivative);
if ( (derivative - fdDerivative).infinity_norm() > eps ) {
std::cout << className(corners[0]) << ": Analytical derivative of gradient does not match fd approximation." << std::endl;
std::cout << "coefficient: " << i << std::endl;
std::cout << "quad pos: " << quadPos << std::endl;
std::cout << "gfe: ";
for (int j=0; j<domainDim+1; j++)
std::cout << ", " << corners[j];
std::cout << std::endl;
std::cout << "Analytical:\n " << derivative << std::endl;
std::cout << "FD :\n " << fdDerivative << std::endl;
}
//testDerivativeTangentiality(f.evaluate(quadPos), derivative);
}
}
}
std::cout << " --- Testing RealTuple<1>, domain dimension: " << domainDim << " ---" << std::endl;
typedef RealTuple<1> TargetSpace;
std::vector<TargetSpace> corners = {TargetSpace(1),
TargetSpace(2),
TargetSpace(3)};
testPermutationInvariance<domainDim>(corners);
testDerivative<domainDim>(corners);
std::cout << " --- Testing UnitVector<2>, domain dimension: " << domainDim << " ---" << std::endl;
int nTestPoints = 10;
double testPoints[10][2] = {{1,0}, {0.5,0.5}, {0,1}, {-0.5,0.5}, {-1,0}, {-0.5,-0.5}, {0,-1}, {0.5,-0.5}, {0.1,1}, {1,.1}};
// Set up elements of S^1
std::vector<TargetSpace> corners(domainDim+1);
MultiIndex<domainDim+1> index(nTestPoints);
int numIndices = index.cycle();
for (int i=0; i<numIndices; i++, ++index) {
for (int j=0; j<domainDim+1; j++) {
Dune::array<double,2> w = {{testPoints[index[j]][0], testPoints[index[j]][1]}};
corners[j] = UnitVector<2>(w);
}
bool spreadOut = false;
for (int j=0; j<domainDim+1; j++)
for (int k=0; k<domainDim+1; k++)
if (UnitVector<2>::distance(corners[j],corners[k]) > M_PI*0.98)
spreadOut = true;
if (spreadOut)
continue;
//testPermutationInvariance(corners);
testDerivative<domainDim>(corners);
testDerivativeOfValueWRTCoefficients<domainDim>(corners);
testDerivativeOfGradientWRTCoefficients<domainDim>(corners);
std::cout << " --- Testing UnitVector<3>, domain dimension: " << domainDim << " ---" << std::endl;
int nTestPoints = 10;
double testPoints[10][3] = {{1,0,0}, {0,1,0}, {-0.838114,0.356751,-0.412667},
{-0.490946,-0.306456,0.81551},{-0.944506,0.123687,-0.304319},
{-0.6,0.1,-0.2},{0.45,0.12,0.517},
{-0.1,0.3,-0.1},{-0.444506,0.123687,0.104319},{-0.7,-0.123687,-0.304319}};
// Set up elements of S^1
std::vector<TargetSpace> corners(domainDim+1);
MultiIndex<domainDim+1> index(nTestPoints);
int numIndices = index.cycle();
for (int i=0; i<numIndices; i++, ++index) {
for (int j=0; j<domainDim+1; j++) {
Dune::array<double,3> w = {{testPoints[index[j]][0], testPoints[index[j]][1], testPoints[index[j]][2]}};
corners[j] = UnitVector<3>(w);
}
//testPermutationInvariance(corners);
testDerivative<domainDim>(corners);
testDerivativeOfValueWRTCoefficients<domainDim>(corners);
testDerivativeOfGradientWRTCoefficients<domainDim>(corners);

Oliver Sander
committed
{
std::cout << " --- Testing Rotation<3>, domain dimension: " << domainDim << " ---" << std::endl;

Oliver Sander
committed
typedef Rotation<3,double> TargetSpace;
int nTestPoints = 10;
double testPoints[10][4] = {{1,0,0,0}, {0,1,0,0}, {-0.838114,0.356751,-0.412667,0.5},
{-0.490946,-0.306456,0.81551,0.23},{-0.944506,0.123687,-0.304319,-0.7},
{-0.6,0.1,-0.2,0.8},{0.45,0.12,0.517,0},
{-0.1,0.3,-0.1,0.73},{-0.444506,0.123687,0.104319,-0.23},{-0.7,-0.123687,-0.304319,0.72}};

Oliver Sander
committed
std::vector<TargetSpace> corners(domainDim+1);
MultiIndex<domainDim+1> index(nTestPoints);
int numIndices = index.cycle();
for (int i=0; i<numIndices; i++, ++index) {
for (int j=0; j<domainDim+1; j++) {
Dune::array<double,4> w = {{testPoints[index[j]][0], testPoints[index[j]][1], testPoints[index[j]][2], testPoints[index[j]][3]}};
corners[j] = Rotation<3,double>(w);
}
//testPermutationInvariance(corners);
testDerivative<domainDim>(corners);
testDerivativeOfValueWRTCoefficients<domainDim>(corners);
testDerivativeOfGradientWRTCoefficients<domainDim>(corners);
}
// choke on NaN
feenableexcept(FE_INVALID);
std::cout << std::setw(15) << std::setprecision(12);
//testRealTuples<1>();
testUnitVector2d<1>();
testUnitVector3d<1>();
testUnitVector2d<2>();
testUnitVector3d<2>();
testRotation<1>();
testRotation<2>();