1function [X,flag] = ctmc_gmres_multi(A,B,tol,restart,maxit)
2% [X,FLAG]=CTMC_GMRES_MULTI(A,B,TOL,RESTART,MAXIT)
4% Solve A*X=B
for every
column of B by restarted GMRES, reusing one ILUT
5% factorization across all of them and starting each
column from
the previous
6% solution. This
is the shape of
the stochastic complement, whose right-hand
7% side
is a whole block of
the generator: refactorizing per
column would cost
8% more than
the direct solve it replaces.
10% Preparation follows CTMC_GMRES: rows are equilibrated to unit max norm and
the
11% states reordered by reverse Cuthill-McKee, without which
the unpivoted
12% elimination overflows on a chain of a few thousand states.
14% FLAG
is 0 only
if every
column converged. On any other value X must be
15% discarded and
the caller must fall back to
the direct solve; returning a
16% partial block would leave
the fallback ambiguous.
18% Copyright (c) 2012-2026, Imperial College London
21% Relative threshold below which ILUT discards a fill-in entry.
26if nargin<3 || isempty(tol) || tol<=0
29if nargin<4 || isempty(restart) || restart<=0
32restart = min(restart,n);
33if nargin<5 || isempty(maxit) || maxit<=0
34 maxit = ceil(n/restart);
36maxit = max(1,min(maxit,n));
42rownorm = full(max(abs(A),[],2));
43rownorm(rownorm==0) = 1;
44A = spdiags(1./rownorm,0,n,n)*A;
47p = symrcm(spones(A)+spones(A)
');
54 [L,U] = ilu(A,struct('type
','ilutp
','droptol
',ILUT_DROP_TOL,'udiag
',1));
55 if any(~isfinite(nonzeros(L))) || any(~isfinite(nonzeros(U)))
67 L = spdiags(1./d,0,n,n);
73warnstate = warning('off
','MATLAB:gmres:tooSmallTolerance
');
76 [xc,fc] = gmres(A,full(B(:,c)),restart,tol,maxit,L,U,guess);