/** @file main.cpp * @brief Main program for Project 2 * * The program performs the Jacobi rotation method. * The size of the matrix, and number of transformations * performed are written to file. * Eigenvector correstonding to the 3 smallest eigenvalues * for matrices of size 6x6 and 100x100 are written to file. * * @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 write_transformation_dense(int N) { std::ofstream ofile; ofile.open("../latex/output/transform_dense.csv"); ofile << "N,T" << std::endl; // Increase size of matrix, start at 5 to avoid logic_error of N=4 for (int i = 5; i <= N; i++) { arma::mat A = arma::mat(i, i).randn(); A = arma::symmatu(A); arma::vec eigval; arma::mat eigvec; int iters; bool converged; jacobi_eigensolver(A, 10e-14, eigval, eigvec, 100000, iters, converged); // Write size, and number of iterations to file ofile << i << "," << iters << std::endl; } ofile.close(); } void write_transformation_tridiag(int N) { std::ofstream ofile; double h; double a, d; ofile.open("../latex/output/transform_tridiag.csv"); // Write header line to file ofile << "N,T" << std::endl; // Increase size of matrix, start at 5 to avoid logic_error of N=4 for (int i = 5; i <= N; i++) { h = 1. / (double) (i+1); a = -1. / (h*h), d = 2. / (h*h); arma::mat A = create_symmetric_tridiagonal(i, a, d); arma::vec eigval; arma::mat eigvec; int iters; bool converged; jacobi_eigensolver(A, 10e-14, eigval, eigvec, 100000, iters, converged); // Write size, and number of iterations to file ofile << i << "," << iters << std::endl; } ofile.close(); } void write_eigenvec(int N) { double h = 1. / (double) (N+1); double a = -1. / (h*h); double d = 2. / (h*h); double x = 0.; // Create tridiagonal matrix arma::mat A = create_symmetric_tridiagonal(N, a, d); arma::mat analytic = arma::mat(N, N); arma::vec eigval; arma::mat eigvec; int iters; bool converged; // Solve using Jacobi rotation method jacobi_eigensolver(A, 10e-14, eigval, eigvec, 100000, iters, converged); // Build analytic eigenvectors arma::vec v, analytic_vec = arma::vec(N); for (int i=0; i < N; i++) { v = eigvec.col(i); 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; } analytic.col(i) = analytic_vec; } std::ofstream ofile; // Create file based on matrix size, and write header line to file ofile.open("../latex/output/eigenvector_" + std::to_string(N) + ".csv"); ofile << "x," << "Vector 1,Vector 2,Vector 3," << "Analytic 1,Analytic 2,Analytic 3" << std::endl; // Add boundary value for x=0 ofile << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << std::endl; // Add x-value and element i of each eigenvector to same line for (int i = 0; i < N; i++) { x += h; ofile << scientific_format(x, 16)<< "," << scientific_format(eigvec(i,0), 16) << "," << scientific_format(eigvec(i,1), 16) << "," << scientific_format(eigvec(i,2), 16) << "," << scientific_format(analytic(i,0), 16) << "," << scientific_format(analytic(i,1), 16) << "," << scientific_format(analytic(i,2), 16) << std::endl; } // Add boundary value for x=1 ofile << scientific_format(1., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << "," << scientific_format(0., 16) << std::endl; ofile.close(); } int main() { write_transformation_tridiag(100); write_transformation_dense(100); write_eigenvec(10); write_eigenvec(100); return 0; }