-
Notifications
You must be signed in to change notification settings - Fork 1
/
parildu_ref.m
68 lines (58 loc) · 1.67 KB
/
parildu_ref.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
function [l d u resid] = parildu_ref(a, l0, d0, u0, numsweeps)
% [l d u resid] = pariutdu_ref(a, l0, d0, u0, numsweeps)
% compute: l*d*u, where l and u have unit diagonal and d is diagonal
% Synchronous updates
%
% a = input sparse matrix
% l0 = input guess for L, with unit diagonal
% d0 = input guess for D, usually the diagonal of A
% u0 = input guess for U, with unit diagonal
% numsweeps = number of nonlinear fixed-point sweeps
% resid = nonlinear residual norm history (optional)
if nargout > 3
pat = spones(l0+u0);
resid = zeros(numsweeps+1, 1);
resid(1) = norm((a-l0*d0*u0).*spones(pat),'fro');
end
% find nonzeros of offdiagonal l (ordering doesn't matter in synchronous case)
pat = spones(l0) - speye(size(a));
[Si1 Sj1 Sa1] = find(a.*pat + eps*pat);
m1 = length(Sa1);
% find nonzeros of u (includes diagonal)
pat = spones(u0);
[Si2 Sj2 Sa2] = find(a.*pat + eps*pat);
m2 = length(Sa2);
% allocate space
l = l0;
u = u0;
dvec = diag(d0);
dvec0 = dvec;
for iter=1:numsweeps
% lower triangular factor
for k=1:m1
i = Si1(k);
j = Sj1(k);
s = Sa1(k) - l0(i,1:j-1)*(dvec0(1:j-1).*u0(1:j-1,j));
if (i == j), error('internal error'); end
l(i,j) = s/dvec0(j);
end
% upper triangular factor and diagonal
for k=1:m2
i = Si2(k);
j = Sj2(k);
s = Sa2(k) - l0(i,1:i-1)*(dvec0(1:i-1).*u0(1:i-1,j));
if (i ~= j)
u(i,j) = s/dvec0(i);
else
dvec(i) = s;
end
end
% reuse
l0 = l;
u0 = u;
dvec0 = dvec;
if nargout > 3
resid(iter+1) = norm((a-l*diag(dvec)*u).*spones(pat),'fro');
end
end
d = diag(dvec);