Skip to content

Commit ee9d748

Browse files
Always use order-dependent formula in CVHin, clamp to hub
Instead of falling back to the conservative geometric mean sqrt(hg*hub) when the order-dependent step formula gives hnew > hub, always use the formula (2/yddnrm)^(1/(p+1)) and clamp to hub. This prevents overly small initdt for high-order explicit methods (e.g. DP5 order 5) where the geometric mean converges very slowly from hlb << hub. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
1 parent a66d63b commit ee9d748

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

lib/OrdinaryDiffEqCore/src/initdt.jl

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@
360360
end
361361
end
362362
else
363-
ydd_ok = !any(x -> any(!isfinite, x), f₁)
363+
ydd_ok = all(isfinite, f₁)
364364
end
365365

366366
if ydd_ok
@@ -390,16 +390,20 @@
390390
yddnrm = internalnorm(tmp, t) / hg * oneunit_tType
391391

392392
# Order-dependent step proposal: h ~ (2/yddnrm)^(1/(p+1))
393-
if DiffEqBase.value(yddnrm) *
394-
DiffEqBase.value(hub / oneunit_tType)^(p_order + 1) > 2
393+
# Always use the formula and clamp to hub, rather than falling back
394+
# to the conservative geometric mean sqrt(hg*hub). This prevents
395+
# overly small initdt for high-order explicit methods where the
396+
# formula naturally gives hnew > hub.
397+
if DiffEqBase.value(yddnrm) > 0
395398
hnew = convert(
396399
_tType,
397400
oneunit_tType * DiffEqBase.value(
398401
(2 / yddnrm)^(1 / (p_order + 1))
399402
)
400403
)
404+
hnew = min(hnew, hub)
401405
else
402-
hnew = sqrt(hg * hub)
406+
hnew = hub
403407
end
404408

405409
count1 == 4 && break
@@ -629,16 +633,16 @@ end
629633
) / hg * oneunit_tType
630634

631635
# Order-dependent step proposal: h ~ (2/yddnrm)^(1/(p+1))
632-
if DiffEqBase.value(yddnrm) *
633-
DiffEqBase.value(hub / oneunit_tType)^(p_order + 1) > 2
636+
if DiffEqBase.value(yddnrm) > 0
634637
hnew = convert(
635638
_tType,
636639
oneunit_tType * DiffEqBase.value(
637640
(2 / yddnrm)^(1 / (p_order + 1))
638641
)
639642
)
643+
hnew = min(hnew, hub)
640644
else
641-
hnew = sqrt(hg * hub)
645+
hnew = hub
642646
end
643647

644648
count1 == 4 && break

0 commit comments

Comments
 (0)