Skip to content

Commit 2fde8ed

Browse files
Improve computation of epsilon in jacobian_fd (#2522)
* improve computation of epsilon in jacobian_fd * add link to comment * add tests
1 parent d9236b6 commit 2fde8ed

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

src/semidiscretization/semidiscretization.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,13 @@ function jacobian_fd(semi::AbstractSemidiscretization;
240240
# use second order finite difference to estimate Jacobian matrix
241241
for idx in eachindex(u0_ode)
242242
# determine size of fluctuation
243-
epsilon = sqrt(eps(typeof(u0_ode[idx])))
243+
# This is the approach used by FiniteDiff.jl to compute the
244+
# step size, which assures that the finite difference is accurate
245+
# for very small and very large absolute values `u0_ode[idx]`.
246+
# See https://github.com/trixi-framework/Trixi.jl/pull/2514#issuecomment-3190534904.
247+
absstep = sqrt(eps(typeof(u0_ode[idx])))
248+
relstep = absstep
249+
epsilon = max(relstep * abs(u0_ode[idx]), absstep)
244250

245251
# plus fluctuation
246252
u_ode[idx] = u0_ode[idx] + epsilon

test/test_special_elixirs.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,37 @@ end
110110
@test A * x Ax
111111
end
112112

113+
@testset "Test Jacobian of DG (1D)" begin
114+
@timed_testset "Linear advection" begin
115+
trixi_include(@__MODULE__,
116+
joinpath(EXAMPLES_DIR, "tree_1d_fdsbp",
117+
"elixir_advection_upwind.jl"),
118+
tspan = (0.0, 0.0))
119+
120+
A, _ = linear_structure(semi)
121+
122+
J = jacobian_ad_forward(semi)
123+
@test Matrix(A) J
124+
λ = eigvals(J)
125+
@test maximum(real, λ) < 10 * sqrt(eps(real(semi)))
126+
127+
J = jacobian_fd(semi)
128+
@test Matrix(A) J
129+
λ = eigvals(J)
130+
@test maximum(real, λ) < 10 * sqrt(eps(real(semi)))
131+
132+
# See https://github.com/trixi-framework/Trixi.jl/pull/2514
133+
@test count(real.(λ) .>= -10) > 5
134+
# See https://github.com/trixi-framework/Trixi.jl/pull/2522
135+
t0 = zero(real(semi))
136+
u0_ode = 1e9 * compute_coefficients(t0, semi)
137+
J = jacobian_fd(semi; t0, u0_ode)
138+
λ = eigvals(J)
139+
@test count((-200 .<= real.(λ) .<= -10) .&& (-100 .<= imag.(λ) .<= 100)) == 0
140+
@test count(isapprox.(imag.(λ), 0.0, atol = 10 * sqrt(eps(real(semi))))) == 2
141+
end
142+
end
143+
113144
@testset "Test Jacobian of DG (2D)" begin
114145
@timed_testset "Linear advection" begin
115146
trixi_include(@__MODULE__,

0 commit comments

Comments
 (0)