Skip to content

Commit 192c12f

Browse files
Fix SplitODEProblem regression for non-IMEX ESDIRK methods (Kvaerno3/4/5) (#3653)
* add issplit(alg) conditions * add issplit(alg) conditions * add test
1 parent dabe16d commit 192c12f

2 files changed

Lines changed: 30 additions & 6 deletions

File tree

lib/OrdinaryDiffEqSDIRK/src/generic_imex_perform_step.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,13 @@ end
445445
return quote
446446
$setup
447447
if tab.explicit_first_stage
448-
if integrator.f isa SplitFunction && tab.fsal && !repeat_step && !integrator.last_stepfail
448+
if integrator.f isa SplitFunction && issplit(alg) && tab.fsal && !repeat_step && !integrator.last_stepfail
449449
f_impl(zs[1], integrator.uprev, p, integrator.t)
450450
zs[1] .*= dt
451451
else
452452
@.. broadcast = false zs[1] = dt * integrator.fsalfirst
453453
end
454-
if integrator.f isa SplitFunction
454+
if integrator.f isa SplitFunction && issplit(alg)
455455
@.. broadcast = false ks[1] = dt * integrator.fsalfirst - zs[1]
456456
end
457457
$stages_efs_true
@@ -482,7 +482,7 @@ end
482482

483483
$adaptive
484484

485-
if integrator.f isa SplitFunction
485+
if integrator.f isa SplitFunction && issplit(alg)
486486
integrator.f(integrator.fsallast, u, p, t + dt)
487487
elseif tab.explicit_fsallast
488488
integrator.f(integrator.fsallast, u, p, t + tab.fsallast_c * dt)
@@ -690,12 +690,12 @@ end
690690
return quote
691691
$setup
692692
if tab.explicit_first_stage
693-
if integrator.f isa SplitFunction
693+
if integrator.f isa SplitFunction && issplit(alg)
694694
$z1 = dt * f_impl(uprev, p, t)
695695
else
696696
$z1 = dt * integrator.fsalfirst
697697
end
698-
if integrator.f isa SplitFunction
698+
if integrator.f isa SplitFunction && issplit(alg)
699699
$k1 = dt * integrator.fsalfirst - $z1
700700
end
701701
$stages_efs_true
@@ -726,7 +726,7 @@ end
726726

727727
$adaptive
728728

729-
if integrator.f isa SplitFunction
729+
if integrator.f isa SplitFunction && issplit(alg)
730730
integrator.k[1] = integrator.fsalfirst
731731
integrator.fsallast = integrator.f(u, p, t + dt)
732732
integrator.k[2] = integrator.fsallast

lib/OrdinaryDiffEqSDIRK/test/sdirk_convergence_tests.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,27 @@ end
183183
sim_iip = test_convergence(dts, prob_iip, ARS343())
184184
@test sim_iip.𝒪est[:l∞] 3 atol = testTol
185185
end
186+
187+
# Regression test: Kvaerno3/4/5 with SplitODEProblem must integrate the full RHS (f1+f2),
188+
# not just f1. These are non-IMEX (issplit=false) methods, so f.f2 must flow through
189+
# fsalfirst rather than being split off into the explicit ks arrays (which have Ae=be=0).
190+
# f = f1 + f2 = -u + 2u = u => exact solution u(t) = exp(t) * u0
191+
@testset "Kvaerno SplitODEProblem" begin
192+
dts = 1 .// 2 .^ (8:-1:4)
193+
194+
f1_oop = (u, p, t) -> -u
195+
f2_oop = (u, p, t) -> 2u
196+
ff_oop = SplitFunction(f1_oop, f2_oop; analytic = (u0, p, t) -> exp(t) * u0)
197+
prob_oop = SplitODEProblem(ff_oop, 1.0, (0.0, 1.0))
198+
199+
f1_iip! = (du, u, p, t) -> (du .= -u)
200+
f2_iip! = (du, u, p, t) -> (du .= 2u)
201+
ff_iip = SplitFunction(f1_iip!, f2_iip!; analytic = (u0, p, t) -> exp(t) .* u0)
202+
prob_iip = SplitODEProblem(ff_iip, [1.0, 0.5], (0.0, 1.0))
203+
204+
sim_oop = test_convergence(dts, prob_oop, Kvaerno4())
205+
@test sim_oop.𝒪est[:l∞] 4 atol = testTol
206+
207+
sim_iip = test_convergence(dts, prob_iip, Kvaerno4())
208+
@test sim_iip.𝒪est[:l∞] 4 atol = testTol
209+
end

0 commit comments

Comments
 (0)