-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy paththomas.m
74 lines (66 loc) · 2.57 KB
/
thomas.m
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
function x = thomas(varargin)
% THOMAS Solves a tridiagonal linear system
%
% x = THOMAS(A,d) solves a tridiagonal linear system using the very efficient
% Thomas Algorith. The vector x is the returned answer.
%
% A*x = d; / a1 b1 0 0 0 ... 0 \ / x1 \ / d1 \
% | c1 a2 b2 0 0 ... 0 | | x2 | | d2 |
% | 0 c2 a3 b3 0 ... 0 | x | x3 | = | d3 |
% | : : : : : : : | | x4 | | d4 |
% | 0 0 0 0 cn-2 an-1 bn-1 | | : | | : |
% \ 0 0 0 0 0 cn-1 an / \ xn / \ dn /
%
% - The matrix A must be strictly diagonally dominant for a stable solution.
% - This algorithm solves this system on (5n-4) multiplications/divisions and
% (3n-3) subtractions.
%
% x = THOMAS(a,b,c,d) where a is the diagonal, b is the upper diagonal, and c is
% the lower diagonal of A also solves A*x = d for x. Note that a is size n
% while b and c is size n-1.
% If size(a)=size(d)=[L C] and size(b)=size(c)=[L-1 C], THOMAS solves the C
% independent systems simultaneously.
%
%
% ATTENTION : No verification is done in order to assure that A is a tridiagonal matrix.
% If this function is used with a non tridiagonal matrix it will produce wrong results.
%
% The form x = THOMAS(a,b,c,d) is much more efficient than the THOMAS(A,d).
[a,b,c,d] = parse_inputs(varargin{:});
% Initialization
m = zeros(size(a));
l = zeros(size(c));
y = zeros(size(d));
n = size(a,1);
%1. LU decomposition ________________________________________________________________________________
m(1,:) = a(1,:);
%2. Forward substitution (L*y=d, for y) ____________________________
y(1,:) = d(1,:);
for i = 2 : n
i_1 = i-1;
l(i_1,:) = c(i_1,:)./m(i_1,:);
m(i,:) = a(i,:) - l(i_1,:).*b(i_1,:);
%2. Forward substitution (L*y=d, for y) ____________________________
y(i,:) = d(i,:) - l(i_1,:).*y(i_1,:);
end
%3. Backward substitutions (U*x=y, for x) ____________________________________________________________
x(n,:) = y(n,:)./m(n,:);
for i = n-1 : -1 : 1
x(i,:) = (y(i,:) - b(i,:).*x(i+1,:))./m(i,:);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [a,b,c,d] = parse_inputs(varargin)
if nargin == 4
a = varargin{1};
b = varargin{2};
c = varargin{3};
d = varargin{4};
elseif nargin == 2
A = sparse(varargin{1});
a = diag(A);
b = diag(A,1);
c = diag(A,-1);
d = varargin{2};
else
error('Incorrect number of inputs.')
end