Skip to content

Commit 8b11ae1

Browse files
committed
change Chebyshev to be in accordance with docs (reltol wrt initial residual instead of RHS)
1 parent 2027c5a commit 8b11ae1

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/chebyshev.jl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,7 @@ function chebyshev_iterable!(x, A, b, λmin::Real, λmax::Real;
8888
r .-= c
8989
end
9090
resnorm = norm(r)
91-
# TODO: According to the docs, the code below should use the initial residual
92-
# instead of the norm of the RHS `b` to set the relative tolerance.
93-
# tolerance = max(reltol * resnorm, abstol)
94-
tolerance = max(reltol * norm(b), abstol)
91+
tolerance = max(reltol * resnorm, abstol)
9592

9693
ChebyshevIterable(Pl, A, x, r, u, c,
9794
zero(real(T)),

test/chebyshev.jl

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Random.seed!(1234321)
2525
A = randSPD(T, n)
2626
b = rand(T, n)
2727
reltol = (eps(real(T)))
28+
abstol = reltol
2829

2930
@testset "Without preconditioner" begin
3031
λ_min, λ_max = approx_eigenvalue_bounds(A)
@@ -38,11 +39,19 @@ Random.seed!(1234321)
3839
@testset "With an initial guess" begin
3940
λ_min, λ_max = approx_eigenvalue_bounds(A)
4041
x0 = rand(T, n)
42+
initial_residual = norm(A * x0 - b)
4143
x, history = chebyshev!(x0, A, b, λ_min, λ_max, reltol=reltol, maxiter=10n, log=true)
4244
@test isa(history, ConvergenceHistory)
4345
@test history.isconverged
4446
@test x == x0
45-
@test norm(A * x - b) / norm(b) reltol
47+
@test norm(A * x - b) reltol * initial_residual
48+
49+
x0 = rand(T, n)
50+
x, history = chebyshev!(x0, A, b, λ_min, λ_max, abstol=abstol, reltol=zero(real(T)), maxiter=10n, log=true)
51+
@test isa(history, ConvergenceHistory)
52+
@test history.isconverged
53+
@test x == x0
54+
@test norm(A * x - b) 2*abstol
4655
end
4756

4857
@testset "With a preconditioner" begin
@@ -54,4 +63,31 @@ Random.seed!(1234321)
5463
@test norm(A * x - b) / norm(b) reltol
5564
end
5665
end
66+
67+
@testset "Termination criterion" begin
68+
for T in (Float32, Float64, ComplexF32, ComplexF64)
69+
A = T[ 2 -1 0
70+
-1 2 -1
71+
0 -1 2]
72+
n = size(A, 2)
73+
b = ones(T, n)
74+
x0 = A \ b
75+
perturbation = T[(-1)^i for i in 1:n]
76+
λ_min, λ_max = approx_eigenvalue_bounds(A)
77+
78+
# If the initial residual is small and a small relative tolerance is used,
79+
# many iterations are necessary
80+
x = x0 + sqrt(eps(real(T))) * perturbation
81+
initial_residual = norm(A * x - b)
82+
x, ch = chebyshev!(x, A, b, λ_min, λ_max, log=true)
83+
@test 2 niters(ch) n
84+
85+
# If the initial residual is small and a large absolute tolerance is used,
86+
# no iterations are necessary
87+
x = x0 + 10*sqrt(eps(real(T))) * perturbation
88+
initial_residual = norm(A * x - b)
89+
x, ch = chebyshev!(x, A, b, λ_min, λ_max, abstol=2*initial_residual, reltol=zero(real(T)), log=true)
90+
@test niters(ch) == 0
91+
end
92+
end
5793
end

0 commit comments

Comments
 (0)