\documentclass{article}

% Language setting
\usepackage[english]{babel}

% Set page size and margins
\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}

% Useful packages
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage{amsfonts}
\usepackage{float} % For better table and figure placement
\usepackage[colorlinks=true, allcolors=blue]{hyperref}
\usepackage{array} % For better table column definitions

\title{MATH 6601 - Project 2 Report}
\author{Zhe Yuan (yuan.1435)}
\date{Nov 2025}

\begin{document}
\maketitle

\section*{Common Iterative Methods for Both Problems}
This project implements five iterative methods to solve large, sparse, symmetric positive-definite (SPD) linear systems of the form $Ax=b$. The implemented methods are:
\begin{itemize}
    \item Jacobi method
    \item Gauss-Seidel method
    \item Successive Over-Relaxation (SOR) method
    \item Steepest Descent method
    \item Conjugate Gradient method
\end{itemize}
All five methods are implemented in Python. The core logic for each solver is contained in the `iterative\_solvers.py' file. The specific problems are set up and solved in `problem1.py' and `problem2.py', respectively.

The initial guess was $x^{(0)}=0$, and the stopping condition was $\|r^{(k)}\|_2 / \|r^{(0)}\|_2 < 10^{-10}$. All $A$ were not explicitly constructed.

\section{Problem 1: Ordinary Differential Equations}
This problem solves the boundary value problem $-u'' = t$ on $(0,1)$ with $u(0)=u(1)=0$. To solve the problem numerically, the interval $(0,1)$ is discretized into $n+1$ subintervals of width $h=1/(n+1)$. The second derivative $u''(t_i)$ is approximated using a central difference scheme:
\[ u''(t_i) = -t_i \approx \frac{u(t_{i-1}) - 2u(t_i) + u(t_{i+1})}{h^2} \quad \implies \quad -u_{i-1} + 2u_i - u_{i+1} = h^2 t_i \]
for the internal grid points $i=1, \dots, n$. Combined with the boundary conditions $u_0=0$ and $u_{n+1}=0$, this forms a linear system $Au=b$, where $u = [u_1, \dots, u_n]^T$. The matrix $A \in \mathbb{R}^{n \times n}$ is a tridiagonal matrix, and the vector $b \in \mathbb{R}^n$ is given by:
\[
A = \begin{pmatrix}
    2 & -1 & & & \\
    -1 & 2 & -1 & & \\
    & \ddots & \ddots & \ddots & \\
    & & -1 & 2 & -1 \\
    & & & -1 & 2
\end{pmatrix}, \quad
b = h^2 \begin{pmatrix} t_1 \\ t_2 \\ \vdots \\ t_n \end{pmatrix}
\]

\subsection*{(a) Exact Solution}
The boundary value problem is given by $-u'' = t$ on the interval $(0, 1)$ with boundary conditions $u(0) = u(1) = 0$.
Integrating twice gives the general solution:
\[ u(t) = -\frac{t^3}{6} - C_1 t - C_2 \]
Applying the boundary conditions $u(0)=0$ and $u(1)=0$, we find the constants $C_2=0$ and $C_1 = -1/6$. Thus, the exact solution is:
\[ u(t) = \frac{t - t^3}{6} \]
The plot of this exact solution is shown in Figure~\ref{fig:p1_exact_solution}.
\begin{figure}[H]
    \centering
    \includegraphics[width=0.8\textwidth]{problem1_exact_solution.png}
    \caption{Plot of the exact solution $u(t) = (t-t^3)/6$.}
    \label{fig:p1_exact_solution}
\end{figure}

\subsection*{(b, c) Iteration Solution}
According to the requirments from 1(b), The linear system was solved for $n=20$ and $n=40$. For SOR, the optimal relaxation parameter $\omega = \frac{2}{1+\sin(\pi h)}$ was used. The number of iterations required for each method to converge is summarized in Table~\ref{tab:p1_iterations}.

\begin{table}[H]
\centering
\begin{tabular}{|l|r|r|}
\hline
\textbf{Method} & \textbf{Iterations (n=20)} & \textbf{Iterations (n=40)} \\
\hline
Jacobi & 2031 & 7758 \\
Gauss-Seidel & 1018 & 3882 \\
SOR & 94 & 183 \\
Steepest Descent & 2044 & 7842\\
Conjugate Gradient & 20 & 40 \\
\hline
\end{tabular}
\caption{Number of iterations for each method for Problem 1.}
\label{tab:p1_iterations}
\end{table}

\noindent \textbf{Observations:}
\begin{enumerate}
    \item The Conjugate Gradient method is the most efficient, requiring the fewest iterations. SOR is the second-best with a significant speedup over Gauss-Seidel. Gauss-Seidel converges about twice as fast as Jacobi. The Steepest Descent method performs poorly, rivaling Jacobi in its slow convergence.
    \item As $n$ doubles, the number of iterations increases for all methods. The iteration count for Jacobi, Gauss-Seidel, and Steepest Descent increases by a factor of roughly 4, while for SOR and CG, the increase is closer to a factor of 2.
\end{enumerate}

\subsection*{(d) Convergence History}
The convergence history is shown in Figures~\ref{fig:p1_conv_n20} and \ref{fig:p1_conv_n40}. The stationary methods and SD show linear convergence, while CG shows superlinear convergence.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.8\textwidth]{problem1_convergence_n20.png}
    \caption{Convergence history for Problem 1 with n=20.}
    \label{fig:p1_conv_n20}
\end{figure}

\begin{figure}[H]
    \centering
    \includegraphics[width=0.8\textwidth]{problem1_convergence_n40.png}
    \caption{Convergence history for Problem 1 with n=40.}
    \label{fig:p1_conv_n40}
\end{figure}

\newpage
\section{Problem 2: Partial Differential Equation}
This problem involves solving the PDE $-\nabla^2 u + u = 1$ (this should be $-\nabla^2 u + u = 1$ instead of $-\nabla u(\text{vector}) + u(\text{scalar}) = 1$ in question) on the unit square $[0,1]^2$ with zero boundary conditions. To solve the problem numerically, a finite difference approximation on an $n \times n$ grid of interior points leads to the discrete equations:
\[ (4+h^2)u_{i,j} - u_{i-1,j} - u_{i,j-1} - u_{i+1,j} - u_{i,j+1} = h^2, \quad i,j=1,\dots,n \]
To formulate this as a standard matrix system $Ax=b$, we reshape the 2D array of unknowns $u_{i,j}$ into a single 1D vector $x$ of length $N=n^2$. After flattening, $u_{i,j}$ maps to the index $k = (i-1)n + j$ in the vector $x$, the matrix $A \in \mathbb{R}^{N \times N}$ becomes a large, sparse, block tridiagonal matrix:
\[
A = \begin{pmatrix}
    T & -I & & & \\
    -I & T & -I & & \\
    & \ddots & \ddots & \ddots & \\
    & & -I & T & -I \\
    & & & -I & T
\end{pmatrix}_{n^2 \times n^2}
\]
where $I$ is the $n \times n$ identity matrix, and $T$ is an $n \times n$ tridiagonal matrix given by:
\[
T = \begin{pmatrix}
    4+h^2 & -1 & & & \\
    -1 & 4+h^2 & -1 & & \\
    & \ddots & \ddots & \ddots & \\
    & & -1 & 4+h^2 & -1 \\
    & & & -1 & 4+h^2
\end{pmatrix}_{n \times n}
\]
The right-hand side vector $b \in \mathbb{R}^{N}$ is a constant vector where every element is $h^2$. So:

\[
(A_{i,i}=T)_{j,j}x_{(i-1)n + j} = (4+h^2)u_{i,j}, (A_{i-1,i}=I)_{j,j}x_{(i-2)n + j} = u_{i-1,j},\dots
\]

\subsection*{(a) Iterative Solution}
The system was solved for $n=16$ ($N=256$) and $n=32$ ($N=1024$) using the same five iterative methods. The number of iterations to reach convergence is reported in Table~\ref{tab:p2_iterations}.

\begin{table}[H]
\centering
\begin{tabular}{|l|r|r|}
\hline
\textbf{Method} & \textbf{Iterations (n=16)} & \textbf{Iterations (n=32)} \\
\hline
Jacobi & 1268 & 4792 \\
Gauss-Seidel & 635 & 2397 \\
SOR & 71 & 138 \\
Steepest Descent & 1247 & 4807 \\
Conjugate Gradient & 31 & 66 \\
\hline
\end{tabular}
\caption{Number of iterations for each method for Problem 2.}
\label{tab:p2_iterations}
\end{table}

\noindent \textbf{Observations:}
The relative performance of the methods remains consistent with Problem 1: CG is the fastest, followed by SOR, Gauss-Seidel, Jacobi, and Steepest Descent. Doubling $n$ from 16 to 32 quadruples the number of unknowns. Again, the iteration counts for slower methods increase by a factor of approximately 4, while for CG and SOR, the increase is only about a factor of 2. This reinforces the conclusion that CG and SOR scale much better with problem size.

\subsection*{(b) Convergence History}
The convergence history plots are shown in Figures~\ref{fig:p2_conv_n16} and \ref{fig:p2_conv_n32}.

\begin{figure}[H]
    \centering
    \includegraphics[width=0.8\textwidth]{problem2_convergence_n16.png}
    \caption{Convergence history for Problem 2 with n=16.}
    \label{fig:p2_conv_n16}
\end{figure}

\begin{figure}[H]
    \centering
    \includegraphics[width=0.8\textwidth]{problem2_convergence_n32.png}
    \caption{Convergence history for Problem 2 with n=32.}
    \label{fig:p2_conv_n32}
\end{figure}

\subsection*{(c) Advantages of Iterative Methods}
For large, sparse linear systems arising from PDE discretizations, iterative methods offer significant advantages over direct methods:
\begin{enumerate}
    \item Iterative methods typically only require storing a few vectors of size $N$, leading to a memory complexity of $O(N)$. In contrast, direct methods require denser helper matrices like $Q$ and $R$. 
    \item The cost per iteration for these problems is dominated by the sparse matrix-vector product, which is $O(N)$. If the method converges in $K$ iterations, the total cost is $O(KN)$. If a good iterative method is used, $K$ can be much smaller than $N$ (like C.G.). Direct sparse solvers often have a higher complexity. When $N$ is very large, iterative methods can be much faster.
    \item Implementing iterative methods is often simpler than implementing a direct solver for sparse matrix.
\end{enumerate}

\end{document}
