amgcl icon indicating copy to clipboard operation
amgcl copied to clipboard

MINRES implementation

Open ddemidov opened this issue 5 years ago • 2 comments

See #144.

An interesting discussion:

Reference implementations:

ddemidov avatar Mar 18 '20 19:03 ddemidov

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.

gdmcbain avatar Mar 18 '20 22:03 gdmcbain

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.

ddemidov avatar Mar 19 '20 08:03 ddemidov