AMS 209: Project: Fortran Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has one subroutine which reads parameters (dimension and equation !! set from the init file 'setup.init'. !!------------------------------------------------------------------ module setup_module contains subroutine setup_init(eq_set, n) implicit none integer, intent(out) :: eq_set, n open(unit=10, file="setup.init") read(10,*) eq_set read(10,*) n close(10) end subroutine setup_init end module setup_module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has two subroutines which reads in matrix A !! and vector b from 'A_i.dat' and 'b_i.dat' files. !!------------------------------------------------------------------ module read_data integer :: i contains subroutine read_matrix(eq_set, A, n) implicit none integer, intent(in) :: eq_set, n real (kind=8), dimension(n, n) :: A if (eq_set == 1) then open(unit=10, file="A_1.dat") do i = 1, n read(10, *) A(i, :) end do close(10) elseif (eq_set == 2) then open(unit=10, file="A_2.dat") do i = 1, n read(10, *) A(i, :) end do close(10) elseif (eq_set == 3) then open(unit=10, file="A_3.dat") do i = 1, n read(10, *) A(i, :) end do close(10) else print *, "Incorrect value entered!" end if end subroutine read_matrix subroutine read_vector(eq_set, b, n) implicit none integer, intent(in) :: eq_set, n real (kind=8), dimension(n) :: b if (eq_set == 1) then open(unit=10, file="b_1.dat") do i = 1, n read(10, *) b(i) end do close(10) elseif (eq_set == 2) then open(unit=10, file="b_2.dat") do i = 1, n read(10, *) b(i) end do close(10) elseif (eq_set == 3) then open(unit=10, file="b_3.dat") do i = 1, n read(10, *) b(i) end do close(10) else print *, "Incorrect value entered!" end if end subroutine read_vector end module read_data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has two subroutines: one prints the solution vector x !! on the screen and another which writes x to a file 'x_i.dat'. !!------------------------------------------------------------------ module write_data integer :: i contains subroutine show_x(x, n) implicit none integer, intent(in) :: n real (kind=8), dimension(n) :: x print *, "Solution x: " do i=1, n print *, x(i) end do end subroutine show_x subroutine write_x_to_file(eq_set, x, n) implicit none integer, intent(in) :: eq_set, n real (kind=8), dimension(n) :: x if (eq_set == 1) then open(unit=10, file="x_1.dat") do i = 1, n write(10, *) x(i) end do close(10) elseif (eq_set == 2) then open(unit=10, file="x_2.dat") do i = 1, n write(10, *) x(i) end do close(10) elseif (eq_set == 3) then open(unit=10, file="x_3.dat") do i = 1, n write(10, *) x(i) end do close(10) else print *, "Incorrect value entered!" end if end subroutine write_x_to_file end module write_data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 !!------------------------------------------------------------------ !! Fortran code for solving Ax=b using gaussian elimination !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! !! * Two methods of iteration: !! 1. With partial pivoting !! 2. Without partial pivoting !! !! * This routine is a driver routine which calls subroutines: !! !! linear_solve: !! |- read_init (from setup_module) !! | !! |- read_matrix (from read_data) !! |- read_vector (from read_data) !! | !! |- write_to_console (from write_to_screen) !! | !! | / GE_without_pivoting (from LU_decomp) !! |- | !! | \ GE_with_pivoting (from LU_decomp) !! | !! |- solve_for_y (from forward_solve) !! | !! |- solve_for_x (from backward_solve) !! | !! |- show_x (from write_data) !! |- write_x_to_file (from write_data) !! !!------------------------------------------------------------------ program linear_solve !! Begining of the real implementation of the driver !! Define usages of module variables and subroutines use setup_module, only : setup_init use read_data, only : read_matrix, read_vector use write_to_screen, only : write_to_console use LU_decomp, only : GE_without_pivoting, GE_with_pivoting use forward_solve, only : solve_for_y use backward_solve, only : solve_for_x use write_data, only : show_x, write_x_to_file implicit none integer :: eq_set, n logical :: errorFlag real (kind=8), dimension(:,:), allocatable :: A real (kind=8), dimension(:,:), allocatable :: L real (kind=8), dimension(:,:), allocatable :: U real (kind=8), dimension(:), allocatable :: b real (kind=8), dimension(:), allocatable :: x real (kind=8), dimension(:), allocatable :: y character(1) :: pivot_flag !! Initialize parameters call setup_init(eq_set, n) allocate(A(n,n)) allocate(L(n,n)) allocate(U(n,n)) allocate(b(n)) allocate(y(n)) allocate(x(n)) !! Read values for A and b from .dat files call read_matrix(eq_set, A, n) call read_vector(eq_set, b, n) !! Print A and b to screen call write_to_console(A, b, n) !! Choose method print *, "Use pivoting? (y/n)" read *, pivot_flag if (pivot_flag == "y") then !! Gaussian Elimination without pivoting call GE_without_pivoting(A, L, U, n) elseif (pivot_flag == "n") then !! Gaussian Elimination with pivoting call GE_with_pivoting(A, L, U, b, n) else print *, "Error!!!" call exit(0) end if !! Forward substitution call solve_for_y(L, y, b, n) !! Backward substitution call solve_for_x(U, x, y, n) !! Print solution to screen call show_x(x, n) !! Write x to file call write_x_to_file(eq_set, x, n) deallocate(A) deallocate(L) deallocate(U) deallocate(b) deallocate(x) deallocate(y) end program linear_solve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has two subroutines that implement Gaussian !! elimination with and without pivoting. !!------------------------------------------------------------------ module LU_decomp contains subroutine GE_without_pivoting(A, L, U, n) implicit none integer, intent(in) :: n real (kind=8), dimension(n, n) :: A real (kind=8), dimension(n, n) :: L real (kind=8), dimension(n, n) :: U integer :: i, j, k !! Initialize L and U matrices do i=1, n do j=1, n L(i,j) = 0 U(i,j) = A(i,j) if (i == j) then L(i,j) = 1 end if end do end do do k=1, (n-1) if (U(k,k) == 0) exit do i=(k+1), n L(i,k) = U(i,k)/U(k,k) end do do j=(k+1), n do i=(k+1), n U(i,j) = U(i,j) - (L(i,k)*U(k,j)) end do end do end do do i=2, n do j=1, (i-1) U(i,j) = 0 end do end do end subroutine GE_without_pivoting subroutine GE_with_pivoting(A, L, U, b, n) implicit none integer, intent(in) :: n real (kind=8) :: pivot, b_temp real (kind=8), dimension(n, n) :: A real (kind=8), dimension(n,n) :: L real (kind=8), dimension(n,n) :: U real (kind=8), dimension(n) :: b real (kind=8), dimension(n) :: LU_temp integer :: i, j, k, ind, p !! Initialize L and U matrices do i=1, n do j=1, n L(i,j) = 0 U(i,j) = A(i,j) if (i == j) then L(i,j) = 1 end if end do end do do k=1, (n-1) ind = k pivot = abs(U(k,k)) !! Find pivot index do p=(k+1), n if (abs(U(p,k)) > pivot) then ind = p pivot = abs(U(p,k)) end if end do !! Interchange rows if (ind /= k) then b_temp = b(ind) b(ind) = b(k) b(k) = b_temp do i=k, n LU_temp(i) = U(ind,i) U(ind,i) = U(k,i) U(k,i) = LU_temp(i) end do do i=1, (k-1) LU_temp(i) = L(ind,i) L(ind,i) = L(k,i) L(k,i) = LU_temp(i) end do end if if (U(k,k) /= 0) then do j=(k+1), n L(j,k) = U(j,k)/U(k,k) do i=k, n U(j,i) = U(j,i)-(L(j,k)*U(k,i)) end do end do end if end do end subroutine GE_with_pivoting end module LU_decomp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has one subroutine that implements backward !! substitution and solves Ux = y. !!------------------------------------------------------------------ module backward_solve contains subroutine solve_for_x(U, x, y, n) implicit none integer, intent(in) :: n real (kind=8), dimension(n) :: x real (kind=8), dimension(n) :: y real (kind=8), dimension(n,n) :: U real (kind=8) :: temp integer :: j, k x(n) = y(n)/U(n,n) do k=(n-1), 1, -1 temp = 0 do j=(k+1), n temp = temp + (x(j)*U(k,j)) end do x(k) = (y(k)-temp)/U(k,k) end do end subroutine solve_for_x end module backward_solve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has one subroutine that implements forward !! substitution and solves Ly = b. !!------------------------------------------------------------------ module forward_solve contains subroutine solve_for_y(L, y, b, n) implicit none integer, intent(in) :: n real (kind=8), dimension(n) :: y real (kind=8), dimension(n,n) :: L real (kind=8), dimension(n) :: b real (kind=8) :: temp integer :: j, k y(1) = b(1) do k=2, n temp = 0 do j=1, (k-1) temp = temp + (y(j)*L(k,j)) end do y(k) = b(k) - temp end do end subroutine solve_for_y end module forward_solve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 !!------------------------------------------------------------------ !! Final Project Type A – Numerical Linear Algebra: !! Gaussian Elimination with and without Pivoting for Solving Linear !! Systems !! !! This code is written by Geetanjali Rakshit for AMS 209. !! !! This module has one subroutine which writes matrix A !! and vector b to screen. !!------------------------------------------------------------------ module write_to_screen contains subroutine write_to_console(A, b, n) implicit none integer, intent(in) :: n real (kind=8), dimension(n, n) :: A real (kind=8), dimension(n) :: b integer :: i print *, "A: " do i=1, n print *, A(i,:) end do print *, "b: " do i=1, n print *, b(i) end do end subroutine write_to_console end module write_to_screen