/** @file test_suite.cpp * @brief Test suite for project 2 * * This is where all the tests for the project are implemented. * The tests test the creation of symmetrical tridiagonals, * finding the largest off-diagonal absolute value of a symmetric matrix, * and the Jacobi rotation method. * * @author Cory Alexander Balaton (coryab) * @author Janita Ovidie Sandtrøen Willumsen (janitaws) * @bug No known bugs */ #include #include #include #include "utils.hpp" #include "matrix.hpp" #include "jacobi.hpp" void test_create_symmetric_tridiagonal() { double tol = 10e-8; double diff; int N = 6; double h = 1. / (double) (N+1); double a = -1. / (h*h), d = 2. / (h*h); arma::mat A = create_symmetric_tridiagonal(N, a, d); arma::vec eigval; arma::mat eigvec; arma::eig_sym(eigval, eigvec, A); // Test eigenvalues for (int i=0; i < N; i++) { diff = eigval(i) - (d + 2.*a*std::cos(((i+1.)*M_PI)/(N+1.))); assert(std::abs(diff) < tol); } // Test eigenvectors arma::vec v, res, analytic_vec = arma::vec(N); for (int i=0; i < N; i++) { v = eigvec.col(i); // Build the analytic vector for (int j=0; j < N; j++) { analytic_vec(j) = std::sin(((j+1.)*(i+1.)*M_PI) / (N+1.)); } analytic_vec = arma::normalise(analytic_vec); // Flip the sign of the analytic vector if they are different if (analytic_vec(0)*v(0) < 0.) { analytic_vec *= -1; } res = v - analytic_vec; for (int j=0; j < N; j++) { assert(std::abs(res(j)) < tol); } } } void test_max_off_diag_symmetric() { arma::mat A = arma::mat(4,4,arma::fill::eye); double tol = 10e-8; A(0, 3) = .5; A(3, 0) = .5; A(1, 2) = -.7; A(2, 1) = -.7; int k,l; assert(max_offdiag_symmetric(A, k, l) - .7 < tol); assert(k == 1 && l == 2); } void test_jacobi_eigensolver() { double tol = 10e-8; double diff; int N = 6; double h = 1. / (double) (N+1); double a = -1. / (h*h), d = 2. / (h*h); arma::mat A = create_symmetric_tridiagonal(N, a, d); arma::vec eigval; arma::mat eigvec; int iters; bool converged; jacobi_eigensolver(A, 10e-14, eigval, eigvec, 10000, iters, converged); // Test eigenvalues for (int i=0; i < N; i++) { diff = eigval(i) - (d + 2.*a*std::cos(((i+1.)*M_PI)/(N+1.))); assert(std::abs(diff) < tol); } // Test eigenvectors arma::vec v, res, analytic_vec = arma::vec(N); for (int i=0; i < N; i++) { v = eigvec.col(i); // Build the analytic vector for (int j=0; j < N; j++) { analytic_vec(j) = std::sin(((j+1.)*(i+1.)*M_PI) / (N+1.)); } analytic_vec = arma::normalise(analytic_vec); // Flip the sign of the analytic vector if they are different if (analytic_vec(0)*v(0) < 0.) { analytic_vec *= -1; } res = v - analytic_vec; for (int j=0; j < N; j++) { assert(std::abs(res(j)) < tol); } } } int main() { test_create_symmetric_tridiagonal(); test_max_off_diag_symmetric(); test_jacobi_eigensolver(); return 0; }