Preconditioned LOBPCG solver for large non-periodic problems (v0.4.0) - #8
Merged
Conversation
New opt-in solver = lobpcg (input files and API): LOBPCG with a tensor-product kinetic preconditioner - the kinetic operator is approximated by the Kronecker sum of the per-dimension 1D stencil operators, whose shifted inverse is applied exactly through small per-dimension eigenbasis transforms, so no factorization of the full operator and no 3D fill-in. Measured on the 3D harmonic oscillator (solver time): 9.7x faster than Arpack shift-invert at 51^3 (13.8 s vs 133.8 s), 3.8x at 35^3, with eigenvalue agreement at 1e-12; end-to-end 3.7x at 51^3. Accuracy safeguards, since correctness outranks speed: - every iterative solve is verified after the fact: the kept eigenpairs' relative residuals are computed against the actual Hamiltonian, near-zero eigenvectors count as infinitely loose (a silently collapsed block can never pass), and lobpcg results that fail verification are re-solved with Arpack shift-invert - lobpcg breakdowns (its internal factorizations can fail) retry with a fresh random block, then fall back to Arpack - never worse than the previous solver in either accuracy or robustness - complex Hermitian (periodic) problems are rejected with a clear error; arpack remains the default everywhere Adds IterativeSolvers as a dependency; version 0.4.0.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8 +/- ##
==========================================
+ Coverage 97.02% 97.20% +0.18%
==========================================
Files 32 33 +1
Lines 1645 1752 +107
==========================================
+ Hits 1596 1703 +107
Misses 49 49 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Benchmark Results (Julia v1)Time benchmarks
Memory benchmarks
|
…r accuracy claim Codecov flagged src/preconditioner.jl and src/solve.jl at ~87% patch coverage on PR #8: the uncovered lines were the lobpcg retry/fallback and residual-escalation branches, which had only been exercised by chance (RNG-dependent) rather than deliberately, so coverage varied by platform/session. - Expose lobpcg_maxiter and krylov_maxiter as tunable keywords on solveWrapper and use them to deterministically force the three failure modes these safety nets exist for, using genuine solver behavior rather than mocks: * IterativeSolvers.lobpcg refuses to run (throws) when the matrix is smaller than 3x the block size - reliably fails both retry attempts, forcing the arpack fallback * lobpcg_maxiter = 1 produces an under-converged (not thrown) result - caught by the residual verifier, re-solved with arpack * krylov_maxiter = 1 similarly under-converges KrylovKit's solver, exercising the generic (non-escalating) residual warning for solvers with no further fallback - Add test_KineticPreconditioner, verifying the preconditioner against an independently-derived dense reference (not calling any of its own internals) across 1D/2D/3D and a periodic dimension, through all four ldiv! dispatches While building that reference, discovered that the preconditioner's Kronecker-sum kinetic operator is only an EXACT match to the true production operator for 1D and 2D (buildLaplace_2d's Laplacian is separable - dividing by 2^(dimension-1) recovers the Kronecker sum bit-for-bit); buildLaplace_3d uses a more elaborate, non-separable stencil, so for 3D the preconditioner is a heuristic approximation. This does not affect correctness - every result is independently residual-verified regardless of preconditioner quality - but the docstring previously implied a close approximation to the true operator in all cases, which was wrong for 3D. Corrected the wording and added a regression assertion for the 1D/2D exactness. Local coverage of both flagged files is now 0 uncovered lines.
…input validation gaps - solveWrapper: re-check the residual after the lobpcg->arpack escalation solve, instead of returning it unconditionally - the rescue itself can land above tolerance for ill-conditioned Hamiltonians and was previously returned without any warning. - setupSystem: reject solver=lobpcg for reciprocal (periodic k-point) runs as soon as reciprocal is known, before any output file is touched - previously this only threw deep in solve(), after main.jl had already deleted a pre-existing eigenvalues.dat. - api.jl: extend the n_eigenvalues+5 < grid size guard to :lobpcg and :krylov, not just :arpack - lobpcg transparently falls back to arpack and was raising an opaque BoundsError instead of a clear ArgumentError. - preconditioner.jl: correct the docstring's claim that the preconditioner is exact for all 2D problems - it is only exact for the 5-point stencil, not the package's default (9); broaden the regression test accordingly. - test_3Dsmoke: seed the RNG and assert no fallback/escalation warning fires in the lobpcg-vs-arpack degenerate-cluster check, so the test actually proves lobpcg converged rather than merely that the pipeline's answer is correct (measured a 1/20-7/20 unseeded fallback rate that the old assertions couldn't distinguish from genuine convergence).
Member
Author
|
Pushed a follow-up commit after a deeper self-review pass:
Full suite (1000 tests) passes. Heads-up for whoever merges this and #9: both branches independently add |
# Conflicts: # Project.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
solver = lobpcg(input files and API, opt-in —arpackstays default): LOBPCG with a tensor-product kinetic preconditioner built from per-dimension 1D stencil operators, applied exactly via small per-dimension eigenbasis transforms — no full-operator factorization, so no 3D fill-in.Solver time (3D harmonic oscillator)
Accuracy safeguards
Adds IterativeSolvers to deps. Version 0.4.0.