Skip to content

Commit b26c58f

Browse files
Jacobian via ForwardDiff for parabolic part only (#2513)
* Jacobian via ForwardDiff for parabolic part only * flip * Update test/test_special_elixirs.jl
1 parent 88fcef5 commit b26c58f

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

src/Trixi.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,9 @@ export trixi_include, examples_dir, get_examples, default_example,
309309

310310
export ode_norm, ode_unstable_check
311311

312-
export convergence_test, jacobian_fd, jacobian_ad_forward, linear_structure
312+
export convergence_test,
313+
jacobian_fd, jacobian_ad_forward, jacobian_ad_forward_parabolic,
314+
linear_structure
313315

314316
export DGMulti, DGMultiBasis, estimate_dt, DGMultiMesh, GaussSBP
315317

src/semidiscretization/semidiscretization.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ end
220220
221221
Uses the right-hand side operator of the semidiscretization `semi`
222222
and simple second order finite difference to compute the Jacobian `J`
223-
of the semidiscretization `semi` at state `u0_ode`.
223+
of the semidiscretization `semi` at time `t0` and state `u0_ode`.
224224
"""
225225
function jacobian_fd(semi::AbstractSemidiscretization;
226226
t0 = zero(real(semi)),
@@ -267,7 +267,7 @@ end
267267
268268
Uses the right-hand side operator of the semidiscretization `semi`
269269
and forward mode automatic differentiation to compute the Jacobian `J`
270-
of the semidiscretization `semi` at state `u0_ode`.
270+
of the semidiscretization `semi` at time `t0` and state `u0_ode`.
271271
"""
272272
function jacobian_ad_forward(semi::AbstractSemidiscretization;
273273
t0 = zero(real(semi)),

src/semidiscretization/semidiscretization_hyperbolic_parabolic.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,45 @@ function _jacobian_ad_forward(semi::SemidiscretizationHyperbolicParabolic, t0, u
375375

376376
return J
377377
end
378+
379+
"""
380+
jacobian_ad_forward_parabolic(semi::SemidiscretizationHyperbolicParabolic;
381+
t0=zero(real(semi)),
382+
u0_ode=compute_coefficients(t0, semi))
383+
384+
Uses the *parabolic part* of the right-hand side operator of the [`SemidiscretizationHyperbolicParabolic`](@ref) `semi`
385+
and forward mode automatic differentiation to compute the Jacobian `J` of the
386+
parabolic/diffusive contribution only at time `t0` and state `u0_ode`.
387+
388+
This might be useful for operator-splitting methods, e.g., the construction of optimized
389+
time integrators which optimize different methods for the hyperbolic and parabolic part separately.
390+
"""
391+
function jacobian_ad_forward_parabolic(semi::SemidiscretizationHyperbolicParabolic;
392+
t0 = zero(real(semi)),
393+
u0_ode = compute_coefficients(t0, semi))
394+
jacobian_ad_forward_parabolic(semi, t0, u0_ode)
395+
end
396+
397+
# The following version is for plain arrays
398+
function jacobian_ad_forward_parabolic(semi::SemidiscretizationHyperbolicParabolic,
399+
t0, u0_ode)
400+
du_ode = similar(u0_ode)
401+
config = ForwardDiff.JacobianConfig(nothing, du_ode, u0_ode)
402+
403+
# Use a function barrier since the generation of the `config` we use above
404+
# is not type-stable
405+
_jacobian_ad_forward_parabolic(semi, t0, u0_ode, du_ode, config)
406+
end
407+
408+
function _jacobian_ad_forward_parabolic(semi, t0, u0_ode, du_ode, config)
409+
new_semi = remake(semi, uEltype = eltype(config))
410+
# Create anonymous function passed as first argument to `ForwardDiff.jacobian` to match
411+
# `ForwardDiff.jacobian(f!, y::AbstractArray, x::AbstractArray,
412+
# cfg::JacobianConfig = JacobianConfig(f!, y, x), check=Val{true}())`
413+
J = ForwardDiff.jacobian(du_ode, u0_ode, config) do du_ode, u_ode
414+
Trixi.rhs_parabolic!(du_ode, u_ode, new_semi, t0)
415+
end
416+
417+
return J
418+
end
378419
end # @muladd

test/test_special_elixirs.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ end
138138
J = jacobian_ad_forward(semi)
139139
λ = eigvals(J)
140140
@test maximum(real, λ) < 10 * sqrt(eps(real(semi)))
141+
142+
J_parabolic = jacobian_ad_forward_parabolic(semi)
143+
λ_parabolic = eigvals(J_parabolic)
144+
# Parabolic spectrum is real and negative
145+
@test maximum(real, λ_parabolic) < 10^(-14)
146+
@test maximum(imag, λ_parabolic) < 10^(-14)
141147
end
142148

143149
@timed_testset "Compressible Euler equations" begin
@@ -219,6 +225,12 @@ end
219225
J = jacobian_ad_forward(semi)
220226
λ = eigvals(J)
221227
@test maximum(real, λ) < 0.2
228+
229+
J_parabolic = jacobian_ad_forward_parabolic(semi)
230+
λ_parabolic = eigvals(J_parabolic)
231+
# Parabolic spectrum is real and negative
232+
@test maximum(real, λ_parabolic) < 10^(-16)
233+
@test maximum(imag, λ_parabolic) < 10^(-15)
222234
end
223235

224236
@timed_testset "MHD" begin

0 commit comments

Comments
 (0)