The special case of a system of linear equations that is tridiagonal, that is, has non-zero elements only on the diagonal plus or minus one column, is one that occurs frequently. Also common are systems that are band-diagonal, with non-zero elements only along a few diagonal lines adjacent to the main diagonal (above and below).
For triadiagonal sets, the procedures \(LU\)-decomposition, forward- and back- substitution each take only \(O(n)\) operations and the whole solution can be coded very concisely. In this blog post, I am going to explore solving triadiagonal matrix systems. I closely follow Daniel Duffy’s exposition in Chapter 13 of his excellent book Financial Instrument Pricing using C++.
Let \(A\) be a \(m \times n\) general banded matrix with \(kl\) subdiagonals and \(ku\) superdiagonals. Then, \(a_{ij}=0\), when \(|i - j| > kl + ku + 1\). All non-zero elements are positioned on the main diagonal, \(kl\) subdiagonals below it and \(ku\) superdiagonals above it.
A diagonal matrix is a \(n \times n\) band matrix with \(kl = ku = 0\).
A Toeplitz matrix is a \(n \times n\) band matrix \(T_n=[t_{k,j};k,j=0,1,\ldots,n-1]\) where \(t_{k,j}=t_{k-j}\). That is, a matrix of the form: \[
T_n = \begin{bmatrix}
t_0 & t_{-1} & t_{-2} & \ldots & t_{-(n-1)}\\
t_1 & t_0 & t_{-1} & \ldots & t_{-(n-2)}\\
t_2 & t_1 & t_{0} & \ldots & t_{-(n-3)}\\
\vdots & & & \ddots & \\
t_{n-1} & t_{n-2} & t_{n-3} & \ldots & t_{0}
\end{bmatrix}
\]
We approximate the solution \(u\) by creating a discrete mesh of points defined by \(\{x_j\}\), \(j=0,\ldots,N\) where \(N\) is a positive integer. At each interior mesh point the second derivative in the Equation 1 can be approximated by a second-order divided difference. The corresponding discrete scheme is:
The Thomas algorithm is an efficient way of solving tridiagonal matrix systems. It is based on \(LU\)-decomposition in which the matrix system \(Ax=r\) is written as \(LUx=r\), where \(L\) is a lower-triangular matrix and \(U\) is an upper triangular matrix. The system can be efficiently solved by setting \(Ux=\rho\) and then solving first \(L\rho=r\) and then \(Ux=\rho\) for \(x\). The Thomas algorithm consists of two steps. In step 1, decomposing the matrix \(M = LU\) and solving \(L\rho=r\) are accomplished in a single downwards sweep, taking us straight from \(Ax=r\) to \(Ux=\rho\). In step 2, the equation \(Ux = \rho\) is solved for \(x\) in an upward sweep.
Stage 1
In the first stage, the matrix equation \(Ax=r\) is converted to the form \(Ux=\rho\). Initially, the matrix equation looks like this:
Consider a slender homogenous rod, lying along the \(x\)-axis and insulated, so that no heat can escape across its longitudinal surface. In addition, we make the simplifying assumption that the temperature in the rod is constant on each cross-section perpendicular to the \(x\)-axis, and thus that the flow of heat in the rod takes place only in the \(x\)-direction.
Consider a small segment of the rod at position \(x\) of length \(\Delta x\).
The thermal energy in this segment at time \(t\) is:
\[
E(x,x+\Delta x, t) \approx u(x,t) s \rho \Delta x
\]
where \(s\) is the constant of specific heat i.e. amount of heat required to raise one unit of mass by one unit of temperature, \(\rho\) is the mass density.
Fourier’s law of heat conduction quantifies the idea that heat flows from warmer to colder regions and states that the (rightward) heat flux density \(\phi(x,t)\) (the flow of heat energy per unit area per unit time, SI units \(J/s/m^2\)) at any point is:
\[
\phi(x,t) = -K_0 u_x (x, t)
\]
where \(K_0\) is the thermal conductivity of the rod. The negative sign shows that the heat flows from higher temperature regions to colder temperature regions.
Letting \(\Delta x \to 0\) improves the approximation and leads to the heat equation:
\[
u_t=c^2 u_{xx}
\]
where \(c^2 = \frac{K_0}{\rho s}\) is called the thermal diffusivity.
The Crank-Nicolson and Theta methods
Consider the initial boundary value problem for the \(1\)d-heat equation:
\[
\begin{align*}
u_t &= a^2 u_{xx}, \quad & 0 < x < L, t>0\\
u(x,0) &= f(x), \quad 0 \leq x \leq L \\
u(0,t) &= A, \\
u(L,t) &= B
\end{align*}
\]
In this case, we can assume without the loss of generality that \(L = 1\). Here, \(a\), \(A\) and \(B\) are constants.
We find a solution to this system in the case when \(A = B = 0\) and \(a = 1\) by the method of the separation of variables. In this case, the analytical solution is:
and we are going to use this solution as a benchmark against which the numerical solutions can be compared.
We can discretize a parabolic PDE in the space dimension (using centered difference schemes) while keeping the time variable continuous. We examine the following initial boundary value problem for the \(1\)d-heat equation on the unit interval with zero Dirichlet boundary conditions.
There are many discretization schemes. I plan to explore various finite difference schemes and their application to derivatives pricing in future posts. For now, I will concentrate on the one-step explicit and implicit methods to discretise the system of ODEs(Equation 4) as:
When the schemes are implicit, we can solve the system of equations (Equation 5) at each time level \(n+1\) using the Thomas algorithm. No matrix inversion is needed in the case of explicit schemes. The formulation (Equation 4) is called the method of lines and it corresponds to semi-discretization of the PDE in the space direction while keeping the time variable continuous (I will explore MOL in future posts).
The system (Equation 10) is tridiagonal and we can apply the Thomas algorithm to solve it. In the case of the explicit Euler scheme \((\theta = 0)\), these algorithms are not needed, because the solution at time level \(n+1\) can be explicitly computed:
I implemented the algorithm in Equation 10. This is a one-step marching scheme called BTCS(Backward in Time, Centered in Space) that computes the solution at time level \(n+1\) in terms of the solution at time \(n\). Since there are three unknowns to be computed at each time level \(n+1\), we need to use the Thomas algorithm. The main steps in the algorithm are:
Choose input parameters and generate meshes
Define the initial solution and the boundary conditions
Compute the solution at each time upto and including expiration.