1.1.7.1. Tri-Diagonal Matrix Algorithm¶
1.1.7.1.1. Use of the Tri-Diagonal Matrix Algorithm¶
The Tri-Diagonal Matrix Algorithm (TDMA) or Thomas Algorithm is a simplified form of Gaussian elimination that can be used to solve tri-diagonal systems of equations.
Advantages of the TDMA:
Less calculations and less storage than Gaussian Elimination
Cost per unknown is independent of the number of unknowns (good scaling w.r.t. iterative methods)
Disadvantages of the TDMA:
Round off error is still significant
May not be suitable for non-linear problems unless equations can be linearised using the Jacobian
Not stable in general, but it is stable if the matrix is diagonally dominant or symmetric positive definite
Usually direct calculation using TDMA is not used, but instead iterative solvers are used such as:
Jacobi
Gauss-Seidel
SOR
Conjugate Gradient
Multi-grid
Parallel Multi-grid
1.1.7.1.2. Matrix Configuration¶
Tri-diagonal systems for \(nx\) unknowns may be written as:
We know the values at the boundaries (\(B\)):
So the matrix looks like this, with known coefficients \(a, b, c, d\). The vector \(u\) is unknown.
1.1.7.1.3. Influence of the Boundary Values¶
Notice the equation on Line 1 can be re-arranged, since we don’t need to solve for \(u_0\), since it equals \(B_0\):
Hence:
Similarly with line \(nx-2\), we don’t need to solve for \(u_{nx-1}\) since it equals \(B_{nx-1}\):
Hence:
1.1.7.1.4. Re-arrangement of the Matrix¶
1.1.7.1.4.1. Step 1¶
Forward elimination adjusts the upper diagonal & RHS and eliminates lower diagonal:
1.1.7.1.4.2. Step 2¶
The solution is then obtained by back substitution:
1.1.7.1.4.3. Alternative Step 1¶
Forward elimination adjusts the central diagonal & RHS and elminates the lower diagonal (From Ferziger and Peric)
The line at i=1 is unchanged
1.1.7.1.4.4. Alternative Step 2¶
The solution is obtained by back substitution:
Ferziger and Peric omitted this, but it’s true:
Then
1.1.7.1.5. How does this translate into Python Code?¶
For the Implicit Beam-Warming Method:
For the inviscid Burgers’ Equation:
And:
Identifying \(a, b, c\) and \(d\):
Modification of the first and last values of the \(d\) vector:
1.1.7.1.6. Use a TDMA Solver¶
This is from Ofan’s Blog:
try:
import numpypy as np # for compatibility with numpy in pypy
except:
import numpy as np # if using numpy in cpython
## Tri Diagonal Matrix Algorithm(a.k.a Thomas algorithm) solver
def TDMAsolver(a, b, c, d):
'''
TDMA solver, a b c d can be NumPy array type or Python list type.
refer to http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
'''
nf = len(a) # number of equations
ac, bc, cc, dc = map(np.array, (a, b, c, d)) # copy the array
for it in xrange(1, nf):
mc = ac[it]/bc[it-1]
bc[it] = bc[it] - mc*cc[it-1]
dc[it] = dc[it] - mc*dc[it-1]
xc = ac
xc[-1] = dc[-1]/bc[-1]
for il in xrange(nf-2, -1, -1):
xc[il] = (dc[il]-cc[il]*xc[il+1])/bc[il]
del bc, cc, dc # delete variables from memory
return xc
1.1.7.1.7. When implementing this, change the index of the coefficients¶
Change index of coefficients, so that they run from \(0\) to \(nx-3\) (i.e. we need two less coefficients than there are in the \(u\) vector).
1.1.7.1.8. Introduction of Damping¶
The Beam-Warming method may become unstable. Therefore introduce fourth order damping term onto the RHS
i.e. with fourth order CD:
For the points \(i=0\) and \(i=1\), the values of \(u_{-1}\) and \(u_{-2}\) are unknown, so set them to 1 (as no periodic boundaries are used).
For the points \(i=nx-1\) and \(i=nx-2\) the values of \(u_{nx}\) and \(u_{nx+1}\) are unknown, so set them equal to 0 (for the same reason)