Skip to content

Shift VCC test u0[4] off saveat-coincident event time#1448

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:cc/vcc-test-saveat-shift
May 21, 2026
Merged

Shift VCC test u0[4] off saveat-coincident event time#1448
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:cc/vcc-test-saveat-shift

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Please ignore until reviewed by @ChrisRackauckas.

Summary

In test_vector_continuous_callback (test/callbacks/vector_continuous_callbacks.jl), shift u0[4] from 2.0 to 2.01 so the "callback with linear affect" event (condition u[3] = 10) lands at τ ≈ 4.975 instead of exactly 5.0 — off the saveat = 0.5 grid.

At τ = saveat, the cost has a true jump discontinuity in u0[3] and u0[4]: the post-affect state (u[4] ← -p[2]·u[4] = -1.8) propagates to the saveat-5.0 sample on one side of the corner and the pre-affect state (u[4] = 2.0) on the other. The Float64 forward rootfinder converges 1 ULP below 5.0; ForwardDiff's Dual rootfinder converges ~6 ULPs above. Both compute valid one-sided derivatives, but BS ≈ FD rtol=1e-5 then compares opposite-side derivatives and fails by design — not an algorithmic bug.

Verification

Central finite differences ((L(+h) − L(−h)) / 2h) at u0 = [50, 0, 0, 2.0]:

  • Smooth components 1, 2, 5, 6: FD ≈ BS ≈ CFD ✓
  • Components 3, 4: CFD ∝ 1/h — classic jump signature ([323, 1.70e5, 1.70e7] for h ∈ {1e-3, 1e-5, 1e-7})

At u0[4] = 2.01 (τ ≈ 4.975, off-grid): FD ≈ BS ≈ GA ≈ CFD to 5–6 digits across all components.

Full FD writeup in closed issue #1447.

Relationship to #1446

#1446 fixes a MethodError in the VCC tracking constructor that masked these tests entirely. Once #1446 lands, the constructor works but this testset numerically fails at the corner. This PR is the right resolution for the numerical failure.

The two PRs can land in either order — this one is a pure test-data tweak with no functional impact; #1446 is an src/ fix that's still correct without this change.

Refs

Test plan

The "callback with linear affect" testset uses condition `u[3] - 10` which,
combined with u[3](t) = u0[4]*t, puts the event at τ = 10/u0[4]. With the
original u0[4] = 2.0, τ = 5.0 exactly — landing on the saveat=0.5 grid.

At a saveat-coincident event time the cost is jump-discontinuous in u0[3]
and u0[4]: the post-event state propagates to that saveat sample, and the
Float64 rootfinder versus ForwardDiff's Dual rootfinder converge to
opposite ULP sides of the saveat. Both compute valid one-sided derivatives
of a discontinuous cost; rtol comparisons between them fail by design at
that point. Verified via central finite differences (1/h blow-up on
components 3 and 4 at u0[4]=2.0; clean 5+ digit agreement among FD, BS,
GA at u0[4]=2.01 with τ ≈ 4.975).

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review May 21, 2026 01:42
@ChrisRackauckas ChrisRackauckas merged commit 0f23b2f into SciML:master May 21, 2026
38 of 50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BacksolveAdjoint/GaussAdjoint: incorrect ∇τ correction when event time coincides with a saveat point within float ULP

2 participants