Skip to content

Fix the Chebyshev iteration recurrence - #376

Merged
haampie merged 1 commit into
JuliaLinearAlgebra:masterfrom
haampie-bot:fix-chebyshev-recurrence
Sep 14, 2026
Merged

haampie merged 1 commit into
JuliaLinearAlgebra:masterfrom
haampie-bot:fix-chebyshev-recurrence

Conversation

@haampie-bot

@haampie-bot haampie-bot commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #367 / #375. That fix stops the divergence, but the iteration still does not produce the Chebyshev residual polynomial r_k = T_k((μI - A)/ρ) r_0 / T_k(μ/ρ):

  • the iteration counter starts at 0, so the iteration == 1 branch ran on the second step, resetting the direction and using α = 2/μ;
  • α = 1/(μ - β) mixes a dimensionless β with an eigenvalue (Templates has 1/(μ - β/α_prev));
  • the β on the second step must be half the generic value, because the three-term recurrence starts from T_{-1} = T_1, not T_0.

iterate is rewritten in the coupled two-term form (Sleijpen, lecture notes Ex. 5.11): track ζ_k = T_k(μ/ρ)/T_{k-1}(μ/ρ) with ζ_{k+1} = 2μ/ρ - 1/ζ_k, β_k = 1/ζ_k², α_k = 2/(ρ ζ_{k+1}).

Residual norm on Diagonal(range(1, 100, length=200)), b = ones:

k exact Chebyshev master (after #367) before #367 this PR
10 2.6e0 1.4e0 3.3e2 2.6e0
30 4.9e-2 5.7e-1 4.7e5 4.9e-2
60 1.2e-4 2.2e-1 4.1e10 1.2e-4

The existing tests did not catch any of this because their matrix has condition number < 3. The new test compares the residual history against the exact polynomial evaluated per eigenvalue (diagonal A, with and without a diagonal left preconditioner, real and complex eltypes); it fails on current master and passes here to ~1e-15 relative.

Also fixes the maxiter docstring, which mentioned GMRES.

After JuliaLinearAlgebra#367 the iteration converges, but it still does not produce the
Chebyshev residual polynomial r_k = T_k((μI - A)/ρ) r_0 / T_k(μ/ρ):

- the iteration counter starts at 0, so the `iteration == 1` branch ran
  on the second step instead of the first, resetting the direction and
  using α = 2/μ there;
- `α = 1/(μ - β)` mixed a dimensionless β with an eigenvalue; the
  Templates form is α = 1/(μ - β/α_prev);
- the β used on the second step must be half the generic value, since the
  three-term recurrence starts from T_{-1} = T_1 rather than T_0.

Rewrite `iterate` in the coupled two-term form of Sleijpen's lecture
notes (Exercise 5.11), tracking ζ_k = T_k(μ/ρ) / T_{k-1}(μ/ρ) with
ζ_{k+1} = 2μ/ρ - 1/ζ_k, β_k = 1/ζ_k² and α_k = 2/(ρ ζ_{k+1}).

On a diagonal SPD matrix with spectrum in [1, 100] the residual norm after
60 iterations is now 1.2e-4 (the exact Chebyshev value), where the
previous code gave 2.2e-1 and, before JuliaLinearAlgebra#367, diverged to 4e10. The
existing tests did not catch this because their matrix has condition
number below 3.

Add a test that checks the residual history against the exact Chebyshev
polynomial evaluated per eigenvalue, with and without a diagonal left
preconditioner, for real and complex element types. Also fix the
`maxiter` docstring, which mentioned GMRES.

Fixes JuliaLinearAlgebra#375.
@haampie-bot
haampie-bot force-pushed the fix-chebyshev-recurrence branch from bdaac24 to 51c6e44 Compare September 14, 2026 13:03
@haampie
haampie merged commit 65fa3e4 into JuliaLinearAlgebra:master Sep 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants