-
Notifications
You must be signed in to change notification settings - Fork 4
/
ek_struct.m
90 lines (74 loc) · 2.73 KB
/
ek_struct.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
function [S, ST] = ek_struct(A, cholesky)
%BUILD_RK_STRUCT Build a struct for building rational Krylov subspaces.
%
if issparse(A)
if exist('cholesky', 'var') && cholesky
[R, g, pA] = chol(A);
if (g ~= 0)
% warning('Matrix is not posdef, resorting to LU');
[S, ST] = ek_struct(A, false);
return;
end
S = struct(...
'solve', @(nu, mu, x) sparse_solve(nu, mu, R', R, pA', pA, x), ...
'multiply', @(rho, eta, x) rho * A * x - eta * x, ...
'isreal', isreal(A), ...
'nrm', normest(A, 1e-2));
ST = S;
else
[LA, UA, pA, qA] = lu(A);
S = struct(...
'solve', @(nu, mu, x) sparse_solve(nu, mu, LA, UA, pA, qA, x), ...
'multiply', @(rho, eta, x) rho * A * x - eta * x, ...
'isreal', isreal(A), ...
'nrm', normest(A, 1e-2));
if nargout >= 2
ST = struct(...
'solve', @(nu, mu, x) sparse_solve(nu, mu, UA', LA', pA', qA', x), ...
'multiply', @(rho, eta, x) rho * A' * x - eta * x, ...
'isreal', S.isreal, ...
'nrm', S.nrm);
end
end
elseif isa(A, 'hm')
[LA,UA] = lu(A);
S = struct(...
... % 'solve', @(nu, mu, x) (nu * A - mu * eye(size(A), 'like', A)) \ x, ...
'solve', @(nu, mu, x) lu_solve(nu, mu, LA, UA, x),...
'multiply', @(rho, eta, x) rho * (A * x) - eta * x, ...
'isreal', isreal(A), ...
'nrm', norm(A));
if nargout >= 2
ST = struct(...
...% 'solve', @(nu, mu, x) (nu * A' - mu * eye(size(A), 'like', A)) \ x, ...
'solve', @(nu, mu, x) lu_solve(nu, mu, UA', LA', x), ...
'multiply', @(rho, eta, x) rho * (A' * x) - eta * x, ...
'isreal', S.isreal, ...
'nrm', S.nrm);
end
elseif isa(A, 'hss')
ULV = ulv(A);
S = struct(...
... % 'solve', @(nu, mu, x) (nu * A - mu * eye(size(A), 'like', A)) \ x, ...
'solve', @(nu, mu, x) ulv_solve_wrapper(nu, mu, ULV, x),...
'multiply', @(rho, eta, x) rho * (A * x) - eta * x, ...
'isreal', isreal(A), ...
'nrm', norm(A));
if nargout >= 2
ULVT = ulv(A');
ST = struct(...
...% 'solve', @(nu, mu, x) (nu * A' - mu * eye(size(A), 'like', A)) \ x, ...
'solve', @(nu, mu, x) ulv_solve_wrapper(nu, mu, ULVT, x), ...
'multiply', @(rho, eta, x) rho * (A' * x) - eta * x, ...
'isreal', S.isreal, ...
'nrm', S.nrm);
end
end
end
function y = sparse_solve(nu, mu, L, U, p, q, x)
if nu > mu
y = nu\(q*(U\(L\(p*x))));
else
y = -mu \ x;
end
end