make Chebyshev nodes over N+1 points instead of N
parent
9ee652c04a
commit
fe7d877352
|
@ -22,13 +22,13 @@ namespace gtsam {
|
|||
|
||||
Weights Chebyshev2::CalculateWeights(size_t N, double x, double a, double b) {
|
||||
// Allocate space for weights
|
||||
Weights weights(N);
|
||||
Weights weights(N + 1);
|
||||
|
||||
// We start by getting distances from x to all Chebyshev points
|
||||
// as well as getting smallest distance
|
||||
Weights distances(N);
|
||||
// as well as getting the smallest distance
|
||||
Weights distances(N + 1);
|
||||
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
const double dj =
|
||||
x - Point(N, j, a, b); // only thing that depends on [a,b]
|
||||
|
||||
|
@ -44,16 +44,16 @@ Weights Chebyshev2::CalculateWeights(size_t N, double x, double a, double b) {
|
|||
// Beginning of interval, j = 0, x(0) = a
|
||||
weights(0) = 0.5 / distances(0);
|
||||
|
||||
// All intermediate points j=1:N-2
|
||||
// All intermediate points j=1:N-1
|
||||
double d = weights(0), s = -1; // changes sign s at every iteration
|
||||
for (size_t j = 1; j < N - 1; j++, s = -s) {
|
||||
for (size_t j = 1; j < N; j++, s = -s) {
|
||||
weights(j) = s / distances(j);
|
||||
d += weights(j);
|
||||
}
|
||||
|
||||
// End of interval, j = N-1, x(N-1) = b
|
||||
weights(N - 1) = 0.5 * s / distances(N - 1);
|
||||
d += weights(N - 1);
|
||||
// End of interval, j = N, x(N) = b
|
||||
weights(N) = 0.5 * s / distances(N);
|
||||
d += weights(N);
|
||||
|
||||
// normalize
|
||||
return weights / d;
|
||||
|
@ -61,30 +61,30 @@ Weights Chebyshev2::CalculateWeights(size_t N, double x, double a, double b) {
|
|||
|
||||
Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
|
||||
// Allocate space for weights
|
||||
Weights weightDerivatives(N);
|
||||
Weights weightDerivatives(N + 1);
|
||||
|
||||
// toggle variable so we don't need to use `pow` for -1
|
||||
double t = -1;
|
||||
|
||||
// We start by getting distances from x to all Chebyshev points
|
||||
// as well as getting smallest distance
|
||||
Weights distances(N);
|
||||
Weights distances(N + 1);
|
||||
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
const double dj =
|
||||
x - Point(N, j, a, b); // only thing that depends on [a,b]
|
||||
if (std::abs(dj) < 1e-12) {
|
||||
// exceptional case: x coincides with a Chebyshev point
|
||||
weightDerivatives.setZero();
|
||||
// compute the jth row of the differentiation matrix for this point
|
||||
double cj = (j == 0 || j == N - 1) ? 2. : 1.;
|
||||
for (size_t k = 0; k < N; k++) {
|
||||
double cj = (j == 0 || j == N) ? 2. : 1.;
|
||||
for (size_t k = 0; k <= N; k++) {
|
||||
if (j == 0 && k == 0) {
|
||||
// we reverse the sign since we order the cheb points from -1 to 1
|
||||
weightDerivatives(k) = -(cj * (N - 1) * (N - 1) + 1) / 6.0;
|
||||
} else if (j == N - 1 && k == N - 1) {
|
||||
weightDerivatives(k) = -(cj * N * N + 1) / 6.0;
|
||||
} else if (j == N && k == N) {
|
||||
// we reverse the sign since we order the cheb points from -1 to 1
|
||||
weightDerivatives(k) = (cj * (N - 1) * (N - 1) + 1) / 6.0;
|
||||
weightDerivatives(k) = (cj * N * N + 1) / 6.0;
|
||||
} else if (k == j) {
|
||||
double xj = Point(N, j);
|
||||
double xj2 = xj * xj;
|
||||
|
@ -92,7 +92,7 @@ Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
|
|||
} else {
|
||||
double xj = Point(N, j);
|
||||
double xk = Point(N, k);
|
||||
double ck = (k == 0 || k == N - 1) ? 2. : 1.;
|
||||
double ck = (k == 0 || k == N) ? 2. : 1.;
|
||||
t = ((j + k) % 2) == 0 ? 1 : -1;
|
||||
weightDerivatives(k) = (cj / ck) * t / (xj - xk);
|
||||
}
|
||||
|
@ -111,8 +111,8 @@ Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
|
|||
double g = 0, k = 0;
|
||||
double w = 1;
|
||||
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
if (j == 0 || j == N - 1) {
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
if (j == 0 || j == N) {
|
||||
w = 0.5;
|
||||
} else {
|
||||
w = 1.0;
|
||||
|
@ -128,13 +128,13 @@ Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
|
|||
double s = 1; // changes sign s at every iteration
|
||||
double g2 = g * g;
|
||||
|
||||
for (size_t j = 0; j < N; j++, s = -s) {
|
||||
// Beginning of interval, j = 0, x0 = -1.0 and end of interval, j = N-1,
|
||||
// x0 = 1.0
|
||||
if (j == 0 || j == N - 1) {
|
||||
for (size_t j = 0; j <= N; j++, s = -s) {
|
||||
// Beginning of interval, j = 0, x0 = -1.0
|
||||
// and end of interval, j = N, x0 = 1.0
|
||||
if (j == 0 || j == N) {
|
||||
w = 0.5;
|
||||
} else {
|
||||
// All intermediate points j=1:N-2
|
||||
// All intermediate points j=1:N-1
|
||||
w = 1.0;
|
||||
}
|
||||
weightDerivatives(j) = (w * -s / (g * distances(j) * distances(j))) -
|
||||
|
@ -146,8 +146,8 @@ Weights Chebyshev2::DerivativeWeights(size_t N, double x, double a, double b) {
|
|||
|
||||
Chebyshev2::DiffMatrix Chebyshev2::DifferentiationMatrix(size_t N, double a,
|
||||
double b) {
|
||||
DiffMatrix D(N, N);
|
||||
if (N == 1) {
|
||||
DiffMatrix D(N + 1, N + 1);
|
||||
if (N + 1 == 1) {
|
||||
D(0, 0) = 1;
|
||||
return D;
|
||||
}
|
||||
|
@ -155,22 +155,22 @@ Chebyshev2::DiffMatrix Chebyshev2::DifferentiationMatrix(size_t N, double a,
|
|||
// toggle variable so we don't need to use `pow` for -1
|
||||
double t = -1;
|
||||
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
for (size_t i = 0; i <= N; i++) {
|
||||
double xi = Point(N, i);
|
||||
double ci = (i == 0 || i == N - 1) ? 2. : 1.;
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
double ci = (i == 0 || i == N) ? 2. : 1.;
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
if (i == 0 && j == 0) {
|
||||
// we reverse the sign since we order the cheb points from -1 to 1
|
||||
D(i, j) = -(ci * (N - 1) * (N - 1) + 1) / 6.0;
|
||||
} else if (i == N - 1 && j == N - 1) {
|
||||
D(i, j) = -(ci * N * N + 1) / 6.0;
|
||||
} else if (i == N && j == N) {
|
||||
// we reverse the sign since we order the cheb points from -1 to 1
|
||||
D(i, j) = (ci * (N - 1) * (N - 1) + 1) / 6.0;
|
||||
D(i, j) = (ci * N * N + 1) / 6.0;
|
||||
} else if (i == j) {
|
||||
double xi2 = xi * xi;
|
||||
D(i, j) = -xi / (2 * (1 - xi2));
|
||||
} else {
|
||||
double xj = Point(N, j);
|
||||
double cj = (j == 0 || j == N - 1) ? 2. : 1.;
|
||||
double cj = (j == 0 || j == N) ? 2. : 1.;
|
||||
t = ((i + j) % 2) == 0 ? 1 : -1;
|
||||
D(i, j) = (ci / cj) * t / (xi - xj);
|
||||
}
|
||||
|
@ -182,15 +182,15 @@ Chebyshev2::DiffMatrix Chebyshev2::DifferentiationMatrix(size_t N, double a,
|
|||
|
||||
Weights Chebyshev2::IntegrationWeights(size_t N, double a, double b) {
|
||||
// Allocate space for weights
|
||||
Weights weights(N);
|
||||
size_t K = N - 1, // number of intervals between N points
|
||||
Weights weights(N + 1);
|
||||
size_t K = N, // number of intervals between N points
|
||||
K2 = K * K;
|
||||
weights(0) = 0.5 * (b - a) / (K2 + K % 2 - 1);
|
||||
weights(N - 1) = weights(0);
|
||||
weights(N) = weights(0);
|
||||
|
||||
size_t last_k = K / 2 + K % 2 - 1;
|
||||
|
||||
for (size_t i = 1; i <= N - 2; ++i) {
|
||||
for (size_t i = 1; i <= N - 1; ++i) {
|
||||
double theta = i * M_PI / K;
|
||||
weights(i) = (K % 2 == 0) ? 1 - cos(K * theta) / (K2 - 1) : 1;
|
||||
|
||||
|
|
|
@ -62,8 +62,8 @@ class GTSAM_EXPORT Chebyshev2 : public Basis<Chebyshev2> {
|
|||
* @return double
|
||||
*/
|
||||
static double Point(size_t N, int j, double a = -1, double b = 1) {
|
||||
assert(j >= 0 && size_t(j) < N);
|
||||
const double dtheta = M_PI / (N > 1 ? (N - 1) : 1);
|
||||
assert(j >= 0 && size_t(j) <= N);
|
||||
const double dtheta = M_PI / (N > 1 ? N : 1);
|
||||
// We add -PI so that we get values ordered from -1 to +1
|
||||
// sin(-M_PI_2 + dtheta*j); also works
|
||||
return a + (b - a) * (1. + cos(-M_PI + dtheta * j)) / 2;
|
||||
|
@ -71,8 +71,8 @@ class GTSAM_EXPORT Chebyshev2 : public Basis<Chebyshev2> {
|
|||
|
||||
/// All Chebyshev points
|
||||
static Vector Points(size_t N) {
|
||||
Vector points(N);
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
Vector points(N + 1);
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
points(j) = Point(N, j);
|
||||
}
|
||||
return points;
|
||||
|
@ -92,7 +92,7 @@ class GTSAM_EXPORT Chebyshev2 : public Basis<Chebyshev2> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Evaluate Chebyshev Weights on [-1,1] at any x up to order N-1 (N values)
|
||||
* Evaluate Chebyshev Weights on [-1,1] at any x up to order N (N+1 values)
|
||||
* These weights implement barycentric interpolation at a specific x.
|
||||
* More precisely, f(x) ~ [w0;...;wN] * [f0;...;fN], where the fj are the
|
||||
* values of the function f at the Chebyshev points. As such, for a given x we
|
||||
|
@ -142,8 +142,8 @@ class GTSAM_EXPORT Chebyshev2 : public Basis<Chebyshev2> {
|
|||
template <size_t M>
|
||||
static Matrix matrix(std::function<Eigen::Matrix<double, M, 1>(double)> f,
|
||||
size_t N, double a = -1, double b = 1) {
|
||||
Matrix Xmat(M, N);
|
||||
for (size_t j = 0; j < N; j++) {
|
||||
Matrix Xmat(M, N + 1);
|
||||
for (size_t j = 0; j <= N; j++) {
|
||||
Xmat.col(j) = f(Point(N, j, a, b));
|
||||
}
|
||||
return Xmat;
|
||||
|
|
|
@ -57,7 +57,7 @@ TEST(BasisFactors, EvaluationFactor) {
|
|||
NonlinearFactorGraph graph;
|
||||
graph.add(factor);
|
||||
|
||||
Vector functionValues(N);
|
||||
Vector functionValues(N + 1);
|
||||
functionValues.setZero();
|
||||
|
||||
Values initial;
|
||||
|
@ -84,7 +84,7 @@ TEST(BasisFactors, VectorEvaluationFactor) {
|
|||
NonlinearFactorGraph graph;
|
||||
graph.add(factor);
|
||||
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N);
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N + 1);
|
||||
|
||||
Values initial;
|
||||
initial.insert<gtsam::Matrix>(key, stateMatrix);
|
||||
|
@ -132,7 +132,7 @@ TEST(BasisFactors, VectorComponentFactor) {
|
|||
NonlinearFactorGraph graph;
|
||||
graph.add(factor);
|
||||
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(P, N);
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(P, N + 1);
|
||||
|
||||
Values initial;
|
||||
initial.insert<gtsam::Matrix>(key, stateMatrix);
|
||||
|
@ -157,7 +157,7 @@ TEST(BasisFactors, ManifoldEvaluationFactor) {
|
|||
NonlinearFactorGraph graph;
|
||||
graph.add(factor);
|
||||
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(3, N);
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(3, N + 1);
|
||||
|
||||
Values initial;
|
||||
initial.insert<gtsam::Matrix>(key, stateMatrix);
|
||||
|
@ -184,7 +184,7 @@ TEST(BasisFactors, VecDerivativePrior) {
|
|||
NonlinearFactorGraph graph;
|
||||
graph.add(vecDPrior);
|
||||
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N);
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N + 1);
|
||||
|
||||
Values initial;
|
||||
initial.insert<gtsam::Matrix>(key, stateMatrix);
|
||||
|
@ -211,7 +211,7 @@ TEST(BasisFactors, ComponentDerivativeFactor) {
|
|||
graph.add(controlDPrior);
|
||||
|
||||
Values initial;
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N);
|
||||
gtsam::Matrix stateMatrix = gtsam::Matrix::Zero(M, N + 1);
|
||||
initial.insert<gtsam::Matrix>(key, stateMatrix);
|
||||
|
||||
LevenbergMarquardtParams parameters;
|
||||
|
|
|
@ -39,9 +39,9 @@ const size_t N = 32;
|
|||
|
||||
//******************************************************************************
|
||||
TEST(Chebyshev2, Point) {
|
||||
static const int N = 5;
|
||||
static const int N = 4;
|
||||
auto points = Chebyshev2::Points(N);
|
||||
Vector expected(N);
|
||||
Vector expected(N + 1);
|
||||
expected << -1., -sqrt(2.) / 2., 0., sqrt(2.) / 2., 1.;
|
||||
static const double tol = 1e-15; // changing this reveals errors
|
||||
EXPECT_DOUBLES_EQUAL(expected(0), points(0), tol);
|
||||
|
@ -57,9 +57,9 @@ TEST(Chebyshev2, Point) {
|
|||
|
||||
//******************************************************************************
|
||||
TEST(Chebyshev2, PointInInterval) {
|
||||
static const int N = 5;
|
||||
static const int N = 4;
|
||||
auto points = Chebyshev2::Points(N, 0, 20);
|
||||
Vector expected(N);
|
||||
Vector expected(N + 1);
|
||||
expected << 0., 1. - sqrt(2.) / 2., 1., 1. + sqrt(2.) / 2., 2.;
|
||||
expected *= 10.0;
|
||||
static const double tol = 1e-15; // changing this reveals errors
|
||||
|
@ -77,9 +77,9 @@ TEST(Chebyshev2, PointInInterval) {
|
|||
//******************************************************************************
|
||||
// InterpolatingPolynomial[{{-1, 4}, {0, 2}, {1, 6}}, 0.5]
|
||||
TEST(Chebyshev2, Interpolate2) {
|
||||
size_t N = 3;
|
||||
size_t N = 2;
|
||||
Chebyshev2::EvaluationFunctor fx(N, 0.5);
|
||||
Vector f(N);
|
||||
Vector f(N + 1);
|
||||
f << 4, 2, 6;
|
||||
EXPECT_DOUBLES_EQUAL(3.25, fx(f), 1e-9);
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ TEST(Chebyshev2, Interpolate2) {
|
|||
//******************************************************************************
|
||||
// InterpolatingPolynomial[{{0, 4}, {1, 2}, {2, 6}}, 1.5]
|
||||
TEST(Chebyshev2, Interpolate2_Interval) {
|
||||
Chebyshev2::EvaluationFunctor fx(3, 1.5, 0, 2);
|
||||
Chebyshev2::EvaluationFunctor fx(2, 1.5, 0, 2);
|
||||
Vector3 f(4, 2, 6);
|
||||
EXPECT_DOUBLES_EQUAL(3.25, fx(f), 1e-9);
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ TEST(Chebyshev2, Interpolate2_Interval) {
|
|||
// InterpolatingPolynomial[{{-1, 4}, {-Sqrt[2]/2, 2}, {0, 6}, {Sqrt[2]/2,3}, {1,
|
||||
// 3}}, 0.5]
|
||||
TEST(Chebyshev2, Interpolate5) {
|
||||
Chebyshev2::EvaluationFunctor fx(5, 0.5);
|
||||
Chebyshev2::EvaluationFunctor fx(4, 0.5);
|
||||
Vector f(5);
|
||||
f << 4, 2, 6, 3, 3;
|
||||
EXPECT_DOUBLES_EQUAL(4.34283, fx(f), 1e-5);
|
||||
|
@ -108,13 +108,13 @@ TEST(Chebyshev2, InterpolateVector) {
|
|||
double t = 30, a = 0, b = 100;
|
||||
const size_t N = 3;
|
||||
// Create 2x3 matrix with Vectors at Chebyshev points
|
||||
Matrix X = Matrix::Zero(2, N);
|
||||
Matrix X = Matrix::Zero(2, N + 1);
|
||||
X.row(0) = Chebyshev2::Points(N, a, b); // slope 1 ramp
|
||||
|
||||
// Check value
|
||||
Vector expected(2);
|
||||
expected << t, 0;
|
||||
Eigen::Matrix<double, /*2x2N*/ -1, -1> actualH(2, 2 * N);
|
||||
Eigen::Matrix<double, /*2x2N*/ -1, -1> actualH(2, 2 * (N + 1));
|
||||
|
||||
Chebyshev2::VectorEvaluationFunctor fx(2, N, t, a, b);
|
||||
EXPECT(assert_equal(expected, fx(X, actualH), 1e-9));
|
||||
|
@ -123,8 +123,7 @@ TEST(Chebyshev2, InterpolateVector) {
|
|||
std::function<Vector2(Matrix)> f =
|
||||
std::bind(&Chebyshev2::VectorEvaluationFunctor::operator(), fx,
|
||||
std::placeholders::_1, nullptr);
|
||||
Matrix numericalH =
|
||||
numericalDerivative11<Vector2, Matrix, 2 * N>(f, X);
|
||||
Matrix numericalH = numericalDerivative11<Vector2, Matrix, 2 * (N + 1)>(f, X);
|
||||
EXPECT(assert_equal(numericalH, actualH, 1e-9));
|
||||
}
|
||||
|
||||
|
@ -133,10 +132,10 @@ TEST(Chebyshev2, InterpolateVector) {
|
|||
TEST(Chebyshev2, InterpolatePose2) {
|
||||
double t = 30, a = 0, b = 100;
|
||||
|
||||
Matrix X(3, N);
|
||||
Matrix X(3, N + 1);
|
||||
X.row(0) = Chebyshev2::Points(N, a, b); // slope 1 ramp
|
||||
X.row(1) = Vector::Zero(N);
|
||||
X.row(2) = 0.1 * Vector::Ones(N);
|
||||
X.row(1) = Vector::Zero(N + 1);
|
||||
X.row(2) = 0.1 * Vector::Ones(N + 1);
|
||||
|
||||
Vector xi(3);
|
||||
xi << t, 0, 0.1;
|
||||
|
@ -151,8 +150,7 @@ TEST(Chebyshev2, InterpolatePose2) {
|
|||
std::function<Pose2(Matrix)> f =
|
||||
std::bind(&Chebyshev2::ManifoldEvaluationFunctor<Pose2>::operator(), fx,
|
||||
std::placeholders::_1, nullptr);
|
||||
Matrix numericalH =
|
||||
numericalDerivative11<Pose2, Matrix, 3 * N>(f, X);
|
||||
Matrix numericalH = numericalDerivative11<Pose2, Matrix, 3 * (N + 1)>(f, X);
|
||||
EXPECT(assert_equal(numericalH, actualH, 1e-9));
|
||||
}
|
||||
|
||||
|
@ -167,9 +165,9 @@ TEST(Chebyshev2, InterpolatePose3) {
|
|||
Pose3 pose(R, Point3(1, 2, 3));
|
||||
|
||||
Vector6 xi = Pose3::ChartAtOrigin::Local(pose);
|
||||
Eigen::Matrix<double, /*6x6N*/ -1, -1> actualH(6, 6 * N);
|
||||
Eigen::Matrix<double, /*6x6N*/ -1, -1> actualH(6, 6 * N + 1);
|
||||
|
||||
Matrix X = Matrix::Zero(6, N);
|
||||
Matrix X = Matrix::Zero(6, N + 1);
|
||||
X.col(11) = xi;
|
||||
|
||||
Chebyshev2::ManifoldEvaluationFunctor<Pose3> fx(N, t, a, b);
|
||||
|
@ -181,8 +179,7 @@ TEST(Chebyshev2, InterpolatePose3) {
|
|||
std::function<Pose3(Matrix)> f =
|
||||
std::bind(&Chebyshev2::ManifoldEvaluationFunctor<Pose3>::operator(), fx,
|
||||
std::placeholders::_1, nullptr);
|
||||
Matrix numericalH =
|
||||
numericalDerivative11<Pose3, Matrix, 6 * N>(f, X);
|
||||
Matrix numericalH = numericalDerivative11<Pose3, Matrix, 6 * (N + 1)>(f, X);
|
||||
EXPECT(assert_equal(numericalH, actualH, 1e-8));
|
||||
}
|
||||
#endif
|
||||
|
@ -200,16 +197,16 @@ TEST(Chebyshev2, Decomposition) {
|
|||
FitBasis<Chebyshev2> actual(sequence, model, 3);
|
||||
|
||||
// Check
|
||||
Vector expected(3);
|
||||
expected << -1, 0, 1;
|
||||
Vector expected(4);
|
||||
expected << -1, -0.5, 0.5, 1;
|
||||
EXPECT(assert_equal(expected, actual.parameters(), 1e-4));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
TEST(Chebyshev2, DifferentiationMatrix3) {
|
||||
// Trefethen00book, p.55
|
||||
const size_t N = 3;
|
||||
Matrix expected(N, N);
|
||||
const size_t N = 2;
|
||||
Matrix expected(N + 1, N + 1);
|
||||
// Differentiation matrix computed from chebfun
|
||||
expected << 1.5000, -2.0000, 0.5000, //
|
||||
0.5000, -0.0000, -0.5000, //
|
||||
|
@ -225,8 +222,8 @@ TEST(Chebyshev2, DifferentiationMatrix3) {
|
|||
//******************************************************************************
|
||||
TEST(Chebyshev2, DerivativeMatrix6) {
|
||||
// Trefethen00book, p.55
|
||||
const size_t N = 6;
|
||||
Matrix expected(N, N);
|
||||
const size_t N = 5;
|
||||
Matrix expected(N + 1, N + 1);
|
||||
expected << 8.5000, -10.4721, 2.8944, -1.5279, 1.1056, -0.5000, //
|
||||
2.6180, -1.1708, -2.0000, 0.8944, -0.6180, 0.2764, //
|
||||
-0.7236, 2.0000, -0.1708, -1.6180, 0.8944, -0.3820, //
|
||||
|
@ -238,7 +235,7 @@ TEST(Chebyshev2, DerivativeMatrix6) {
|
|||
expected = -expected;
|
||||
|
||||
Matrix actual = Chebyshev2::DifferentiationMatrix(N);
|
||||
EXPECT(assert_equal((Matrix)expected, actual, 1e-4));
|
||||
EXPECT(assert_equal(expected, actual, 1e-4));
|
||||
}
|
||||
|
||||
// test function for CalculateWeights and DerivativeWeights
|
||||
|
@ -255,8 +252,8 @@ double fprime(double x) {
|
|||
|
||||
//******************************************************************************
|
||||
TEST(Chebyshev2, CalculateWeights) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N);
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N + 1);
|
||||
for (size_t i = 0; i <= N; i++) {
|
||||
fvals(i) = f(Chebyshev2::Point(N, i));
|
||||
}
|
||||
double x1 = 0.7, x2 = -0.376;
|
||||
|
@ -269,8 +266,8 @@ TEST(Chebyshev2, CalculateWeights) {
|
|||
TEST(Chebyshev2, CalculateWeights2) {
|
||||
double a = 0, b = 10, x1 = 7, x2 = 4.12;
|
||||
|
||||
Eigen::Matrix<double, -1, 1> fvals(N);
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N + 1);
|
||||
for (size_t i = 0; i <= N; i++) {
|
||||
fvals(i) = f(Chebyshev2::Point(N, i, a, b));
|
||||
}
|
||||
|
||||
|
@ -284,8 +281,8 @@ TEST(Chebyshev2, CalculateWeights2) {
|
|||
}
|
||||
|
||||
TEST(Chebyshev2, DerivativeWeights) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N);
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N + 1);
|
||||
for (size_t i = 0; i <= N; i++) {
|
||||
fvals(i) = f(Chebyshev2::Point(N, i));
|
||||
}
|
||||
double x1 = 0.7, x2 = -0.376, x3 = 0.0;
|
||||
|
@ -307,8 +304,8 @@ TEST(Chebyshev2, DerivativeWeights) {
|
|||
TEST(Chebyshev2, DerivativeWeights2) {
|
||||
double x1 = 5, x2 = 4.12, a = 0, b = 10;
|
||||
|
||||
Eigen::Matrix<double, -1, 1> fvals(N);
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
Eigen::Matrix<double, -1, 1> fvals(N + 1);
|
||||
for (size_t i = 0; i <= N; i++) {
|
||||
fvals(i) = f(Chebyshev2::Point(N, i, a, b));
|
||||
}
|
||||
|
||||
|
@ -347,7 +344,7 @@ TEST(Chebyshev2, DerivativeWeights6) {
|
|||
const size_t N6 = 6;
|
||||
Matrix D6 = Chebyshev2::DifferentiationMatrix(N6);
|
||||
Chebyshev2::Parameters x = Chebyshev2::Points(N6); // ramp with slope 1
|
||||
EXPECT(assert_equal(Vector::Ones(N6), Vector(D6 * x)));
|
||||
EXPECT(assert_equal(Vector::Ones(N6 + 1), Vector(D6 * x)));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
@ -356,14 +353,14 @@ TEST(Chebyshev2, DerivativeWeights7) {
|
|||
const size_t N7 = 7;
|
||||
Matrix D7 = Chebyshev2::DifferentiationMatrix(N7);
|
||||
Chebyshev2::Parameters x = Chebyshev2::Points(N7); // ramp with slope 1
|
||||
EXPECT(assert_equal(Vector::Ones(N7), Vector(D7 * x)));
|
||||
EXPECT(assert_equal(Vector::Ones(N7 + 1), Vector(D7 * x)));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Check derivative in two different ways: numerical and using D on f
|
||||
Vector6 f3_at_6points = (Vector6() << 4, 2, 6, 2, 4, 3).finished();
|
||||
double proxy3(double x) {
|
||||
return Chebyshev2::EvaluationFunctor(6, x)(f3_at_6points);
|
||||
return Chebyshev2::EvaluationFunctor(5, x)(f3_at_6points);
|
||||
}
|
||||
|
||||
TEST(Chebyshev2, Derivative6) {
|
||||
|
@ -373,21 +370,23 @@ TEST(Chebyshev2, Derivative6) {
|
|||
const double x = 0.2;
|
||||
Matrix numeric_dTdx = numericalDerivative11<double, double>(proxy3, x);
|
||||
|
||||
size_t N = 5;
|
||||
|
||||
// Calculate derivatives at Chebyshev points using D3, interpolate
|
||||
Matrix D6 = Chebyshev2::DifferentiationMatrix(6);
|
||||
Matrix D6 = Chebyshev2::DifferentiationMatrix(N);
|
||||
Vector derivative_at_points = D6 * f3_at_6points;
|
||||
Chebyshev2::EvaluationFunctor fx(6, x);
|
||||
Chebyshev2::EvaluationFunctor fx(N, x);
|
||||
EXPECT_DOUBLES_EQUAL(numeric_dTdx(0, 0), fx(derivative_at_points), 1e-8);
|
||||
|
||||
// Do directly
|
||||
Chebyshev2::DerivativeFunctor dfdx(6, x);
|
||||
Chebyshev2::DerivativeFunctor dfdx(N, x);
|
||||
EXPECT_DOUBLES_EQUAL(numeric_dTdx(0, 0), dfdx(f3_at_6points), 1e-8);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// Assert that derivative also works in non-standard interval [0,3]
|
||||
double proxy4(double x) {
|
||||
return Chebyshev2::EvaluationFunctor(6, x, 0, 3)(f3_at_6points);
|
||||
return Chebyshev2::EvaluationFunctor(5, x, 0, 3)(f3_at_6points);
|
||||
}
|
||||
|
||||
TEST(Chebyshev2, Derivative6_03) {
|
||||
|
@ -397,14 +396,16 @@ TEST(Chebyshev2, Derivative6_03) {
|
|||
const double x = 0.2;
|
||||
Matrix numeric_dTdx = numericalDerivative11<double, double>(proxy4, x);
|
||||
|
||||
size_t N = 5;
|
||||
|
||||
// Calculate derivatives at Chebyshev points using D3, interpolate
|
||||
Matrix D6 = Chebyshev2::DifferentiationMatrix(6, 0, 3);
|
||||
Matrix D6 = Chebyshev2::DifferentiationMatrix(N, 0, 3);
|
||||
Vector derivative_at_points = D6 * f3_at_6points;
|
||||
Chebyshev2::EvaluationFunctor fx(6, x, 0, 3);
|
||||
Chebyshev2::EvaluationFunctor fx(N, x, 0, 3);
|
||||
EXPECT_DOUBLES_EQUAL(numeric_dTdx(0, 0), fx(derivative_at_points), 1e-8);
|
||||
|
||||
// Do directly
|
||||
Chebyshev2::DerivativeFunctor dfdx(6, x, 0, 3);
|
||||
Chebyshev2::DerivativeFunctor dfdx(N, x, 0, 3);
|
||||
EXPECT_DOUBLES_EQUAL(numeric_dTdx(0, 0), dfdx(f3_at_6points), 1e-8);
|
||||
}
|
||||
|
||||
|
@ -415,12 +416,12 @@ TEST(Chebyshev2, VectorDerivativeFunctor) {
|
|||
const double x = 0.2;
|
||||
using VecD = Chebyshev2::VectorDerivativeFunctor;
|
||||
VecD fx(M, N, x, 0, 3);
|
||||
Matrix X = Matrix::Zero(M, N);
|
||||
Matrix actualH(M, M * N);
|
||||
Matrix X = Matrix::Zero(M, N + 1);
|
||||
Matrix actualH(M, M * (N + 1));
|
||||
EXPECT(assert_equal(Vector::Zero(M), (Vector)fx(X, actualH), 1e-8));
|
||||
|
||||
// Test Jacobian
|
||||
Matrix expectedH = numericalDerivative11<Vector2, Matrix, M * N>(
|
||||
Matrix expectedH = numericalDerivative11<Vector2, Matrix, M*(N + 1)>(
|
||||
std::bind(&VecD::operator(), fx, std::placeholders::_1, nullptr), X);
|
||||
EXPECT(assert_equal(expectedH, actualH, 1e-7));
|
||||
}
|
||||
|
@ -434,24 +435,24 @@ TEST(Chebyshev2, VectorDerivativeFunctor2) {
|
|||
const Vector points = Chebyshev2::Points(N, 0, T);
|
||||
|
||||
// Assign the parameter matrix 1xN
|
||||
Matrix X(1, N);
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
Matrix X(1, N + 1);
|
||||
for (size_t i = 0; i <= N; ++i) {
|
||||
X(i) = f(points(i));
|
||||
}
|
||||
|
||||
// Evaluate the derivative at the chebyshev points using
|
||||
// VectorDerivativeFunctor.
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
for (size_t i = 0; i <= N; ++i) {
|
||||
VecD d(M, N, points(i), 0, T);
|
||||
Vector1 Dx = d(X);
|
||||
EXPECT_DOUBLES_EQUAL(fprime(points(i)), Dx(0), 1e-6);
|
||||
}
|
||||
|
||||
// Test Jacobian at the first chebyshev point.
|
||||
Matrix actualH(M, M * N);
|
||||
Matrix actualH(M, M * (N + 1));
|
||||
VecD vecd(M, N, points(0), 0, T);
|
||||
vecd(X, actualH);
|
||||
Matrix expectedH = numericalDerivative11<Vector1, Matrix, M * N>(
|
||||
Matrix expectedH = numericalDerivative11<Vector1, Matrix, M*(N + 1)>(
|
||||
std::bind(&VecD::operator(), vecd, std::placeholders::_1, nullptr), X);
|
||||
EXPECT(assert_equal(expectedH, actualH, 1e-6));
|
||||
}
|
||||
|
@ -464,11 +465,11 @@ TEST(Chebyshev2, ComponentDerivativeFunctor) {
|
|||
using CompFunc = Chebyshev2::ComponentDerivativeFunctor;
|
||||
size_t row = 1;
|
||||
CompFunc fx(M, N, row, x, 0, 3);
|
||||
Matrix X = Matrix::Zero(M, N);
|
||||
Matrix actualH(1, M * N);
|
||||
Matrix X = Matrix::Zero(M, (N + 1));
|
||||
Matrix actualH(1, M * (N + 1));
|
||||
EXPECT_DOUBLES_EQUAL(0, fx(X, actualH), 1e-8);
|
||||
|
||||
Matrix expectedH = numericalDerivative11<double, Matrix, M * N>(
|
||||
Matrix expectedH = numericalDerivative11<double, Matrix, M*(N + 1)>(
|
||||
std::bind(&CompFunc::operator(), fx, std::placeholders::_1, nullptr), X);
|
||||
EXPECT(assert_equal(expectedH, actualH, 1e-7));
|
||||
}
|
||||
|
@ -476,7 +477,7 @@ TEST(Chebyshev2, ComponentDerivativeFunctor) {
|
|||
//******************************************************************************
|
||||
TEST(Chebyshev2, IntegralWeights) {
|
||||
const size_t N7 = 7;
|
||||
Vector actual = Chebyshev2::IntegrationWeights(N7);
|
||||
Vector actual = Chebyshev2::IntegrationWeights(N7 - 1);
|
||||
Vector expected = (Vector(N7) << 0.0285714285714286, 0.253968253968254,
|
||||
0.457142857142857, 0.520634920634921, 0.457142857142857,
|
||||
0.253968253968254, 0.0285714285714286)
|
||||
|
@ -484,7 +485,7 @@ TEST(Chebyshev2, IntegralWeights) {
|
|||
EXPECT(assert_equal(expected, actual));
|
||||
|
||||
const size_t N8 = 8;
|
||||
Vector actual2 = Chebyshev2::IntegrationWeights(N8);
|
||||
Vector actual2 = Chebyshev2::IntegrationWeights(N8 - 1);
|
||||
Vector expected2 = (Vector(N8) << 0.0204081632653061, 0.190141007218208,
|
||||
0.352242423718159, 0.437208405798326, 0.437208405798326,
|
||||
0.352242423718159, 0.190141007218208, 0.0204081632653061)
|
||||
|
|
Loading…
Reference in New Issue