amgcl
amgcl copied to clipboard
MINRES implementation
In case you want to try that yourself, amgcl/solver/cg.hpp should be a good starting point. (#144)
Thank you for the invitation and the very informative discussion and helpful tips in #144 and sorry for hijacking that issue; anything further on MINRES, I'll add here. I'm pretty much only writing Python these days, so might not get to the implementation too soon. It is a much simpler and cleaner C++ idiom than I've had to contend with before though, very very interesting. Thanks again.
409a505b41fad1e724c983a27630b30525282d3b ports scipy version of minres into amgcl. It does seem to work, but it looks like the computed residual is too optimistic. I am computing true residual after the main loop here:
https://github.com/ddemidov/amgcl/blob/409a505b41fad1e724c983a27630b30525282d3b/amgcl/solver/minres.hpp#L323-L326
Compare the results for minres and gmres for the simple Poisson problem:
minres
$ ./solver solver.type=minres
Solver
======
Type: MINRES
Unknowns: 32768
Memory footprint: 1.75 M
Preconditioner
==============
Number of levels: 3
Operator complexity: 1.59
Grid complexity: 1.14
Memory footprint: 11.54 M
level unknowns nonzeros memory
---------------------------------------------
0 32768 223232 8.48 M (62.80%)
1 4192 114356 2.49 M (32.17%)
2 346 17898 579.04 K ( 5.03%)
Iterations: 6
Error: 0.000347444
[Profile: 0.494 s] (100.00%)
[ self: 0.008 s] ( 1.65%)
[ assembling: 0.006 s] ( 1.16%)
[ setup: 0.222 s] ( 44.91%)
[ solve: 0.259 s] ( 52.28%)
gmres
$ ./solver solver.type=gmres
Solver
======
Type: GMRES(30)
Unknowns: 32768
Memory footprint: 8.01 M
Preconditioner
==============
Number of levels: 3
Operator complexity: 1.59
Grid complexity: 1.14
Memory footprint: 11.54 M
level unknowns nonzeros memory
---------------------------------------------
0 32768 223232 8.48 M (62.80%)
1 4192 114356 2.49 M (32.17%)
2 346 17898 579.04 K ( 5.03%)
Iterations: 13
Error: 3.03338e-09
[Profile: 0.693 s] (100.00%)
[ self: 0.007 s] ( 0.96%)
[ assembling: 0.006 s] ( 0.80%)
[ setup: 0.273 s] ( 39.37%)
[ solve: 0.408 s] ( 58.88%)
It does look like minres does twice less iterations than gmres, but the true relative residual is far from requested. If I ask gmres to compute up to the tolerance reached by minres, I get the same number of iterations:
$ ./solver solver.{type=gmres,tol=3.4e-4}
Solver
======
Type: GMRES(30)
Unknowns: 32768
Memory footprint: 8.01 M
Preconditioner
==============
Number of levels: 3
Operator complexity: 1.59
Grid complexity: 1.14
Memory footprint: 11.54 M
level unknowns nonzeros memory
---------------------------------------------
0 32768 223232 8.48 M (62.80%)
1 4192 114356 2.49 M (32.17%)
2 346 17898 579.04 K ( 5.03%)
Iterations: 6
Error: 0.000326592
[Profile: 0.464 s] (100.00%)
[ self: 0.001 s] ( 0.21%)
[ assembling: 0.006 s] ( 1.21%)
[ setup: 0.158 s] ( 33.96%)
[ solve: 0.300 s] ( 64.62%)
So far minres solver does not work with complex or block value types, so I am keeping it in a separate branch.