조회 수: 12(최근 30일)

표시 이전 댓글

Hello Community,

i have a large sparse block structured matrix.

with this quadratic sparse Matrix L:

is there any faster way to get a solution.

here is my code: (a tol of 1e-6 works the best for my problem)

opt.setup = milu;

[A,B]=ilu(L,opt.setup);

[sol,flag]=gmres(L,f,[],1e-6,size(L,1),A,B);

Best Regards,

Marko

Fabio Freschi
2021년 9월 7일

I would let the backslash operator work on this matrix

sol = L\f;

Can you share the original matrix to make other attempts?

Fabio Freschi
2021년 9월 8일

I made some tests to with your matrix and rhs.

clear variables, close all

load('Lf.mat');

figure,spy(L)

% gmres w/o preconditioned

tic

[x0,flag0,relres0,iter0,resvec0] = gmres(L,f,[],1e-6,size(L,1));

toc

% gmres w/ preconditioning

tic

[M1,M2] = ilu(L);

[x1,flag1,relres1,iter1,resvec1] = gmres(L,f,[],1e-6,size(L,1),M1,M2);

toc

% convergence plot

figure

semilogy(0:length(resvec0)-1,resvec0/norm(f),'-o')

hold on

semilogy(0:length(resvec1)-1,resvec1/norm(M2\(M1\f)),'-o')

% backslash

tic

x2 = L\f;

toc

% error

norm(L*x2-f)

% LU factorization

tic

[L0,U0,ip,iq,D0] = lu(L,'vector');

x3(iq) = U0\(L0\(D0(ip,ip)\f(ip)));

toc

% error

norm(L*x3-f)

It seems that the sparse solver does not worry to much about the singularity (but, again, this issue must be investigated). The LU factorization looks fast enough to me, also because if the problem is nonlinear, you can reuse the factors L0 and U0 and change only the rhs f. Note that most of the computation time is for the LU factorization and not in the forward/backward solution.

% LU factorization

tic

[L0,U0,ip,iq,D0] = lu(L,'vector');

for i = 1:100

x3(iq) = U0\(L0\(D0(ip,ip)\f(ip)));

end

toc

As you can see you can solve the same system 100 times with a little more effort.

In case you can produce a block matrix without zeroing the rows, it could be possible to try to exploit the block-matrix nature of the matrix. See for example section 2.5 of the preprint of the paper attached. A part from the formulation details, that are not of interest here, in that case I have a 2x2 block matrix with a diagonal block (like yours) and I exploit the fact by calculating the Schur complement, and providing the result to GMRES.

Your case is 3x3 block matrix but you can give a try to check if you have benefits.

By the way: sometimes the Schur complement improves the conditioning of the matrix, with a resulting speedup in the iteration of GMRES.

John D'Errico
2021년 9월 7일

편집: John D'Errico
2021년 9월 8일

The fact is, a 3kx3k system is not that slow to solve. So unless you are doing this solve many thousands of times, keeping it sparse may well slow you down.

It is not even really that sparse, since for a 3100x3100 matrix with 250000 nonzeros, there are on average

249155/3100

So roughly 80 non-zeros per row. That is not very sparse.

Have you tried a direct solve in sparse form, using a column ordering to reduce fill-in?

Have you compared the solve time if the matrix were a full matrix?

For example...

A = randn(3100);

b = randn(3100,1);

timeit(@() A\b)

ans =

0.1878352492155

That test was run on my computer. I was watching the actuivity monitor on my computer as it ran, and the test itself was so fast that MATLAB never even fired up multiple cores in the solve, at least that the activity monitor showed in the time slice it was watching.

Even for for a full matrix of that size, it only took a small fraction of a second to solve as a full matrix.

Are you truly needing to solve this probem many thousands of times? If not, then this entire question seems moot.

If so, then is your matrix fixed, so just different right hand sides? If so, then a matrix factorization would be right, or if you have many right hands sides, known in advance, then a direct call to backslash is absolutely correct.

Or is your real problem orders of magnitude larger?

The point of my answer is this really is a small probem, and sparse form may not even be a good choice. The amount of time tken by the incomplete LU there is often a significant fraction of the time it would take to perform the matrix factorization itself.

So if you want help, then it does help if you explain all of these things, because your question as it is does not completely make sense. Why do you think you need to solve this problem as you wish to solve it?

Edit:

I see that you have provided the matrix L. Must I point out that L is singular? You claim that \ is slow here. The probem is, that backslash, when applied to a FULL matrix of that size, is actually roughly 6 times faster for the full matrix than it is for the sparse matrix.

To remove the issue of your matrix also being singular, I'll perturb the diagonal by a small amount.

Lhat = L + speye(3139)*1e-7;

rank(full(Lhat))

ans =

3139

timeit(@() Lhat\f)

ans =

1.3129801282155

Lhatfull = full(Lhat);

timeit(@() Lhatfull\f)

ans =

0.2029861762155

So if you just store the matrix in a full form, \ is significantly faster for the full matrix! More than 6x faster.

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!