Skip to content

Use single-affect VCC constructor in _track_callback#1446

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:cc/vcc-single-affect-constructor
May 20, 2026
Merged

Use single-affect VCC constructor in _track_callback#1446
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:cc/vcc-single-affect-constructor

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

Please ignore until reviewed by @ChrisRackauckas.

Summary

  • _track_callback(cb::VectorContinuousCallback, ...) was still calling the VCC constructor with a leftover nothing argument in the old affect_neg! slot. After the recent refactor that dropped affect_neg! from VCC, the constructor signature is (condition, affect!, len, ...) — the stray nothing made len::Nothing instead of Int, so the constructor threw a MethodError on every adjoint pass through any VCC, regardless of Julia version.
  • Drop the stray nothing and forward initializealg, saved_clock_partitions, maybe_discontinuity, and initialize_save_discretes from the original callback so the tracked VCC round-trips all the user-supplied configuration.

Test plan

Reproduced the failure locally on Julia 1.12 via test/callbacks/vector_continuous_callbacks.jl. Before the fix: all 4 sub-testsets in this file error with MethodError: no method matching SciMLBase.VectorContinuousCallback(...). After the fix:

  • MSE loss function bouncing-ball like → callback with linear affect — runs, with 4 numerical assertion failures (separate latent issue, see note below).
  • Test condition function that depends on time only — passes.
  • Structural simultaneous fire (algebraically tied conditions) — passes.
  • Coincidental simultaneous fire (corner trap) — passes.

Note on remaining numerical failure

The callback with linear affect testset now reaches its assertions but they fail with ~7% mismatch on the u[3]/u[4] gradient components vs ForwardDiff. Both BacksolveAdjoint and GaussAdjoint agree with each other and disagree with ForwardDiff in exactly the same way, so this is a latent issue in the implicit ∇τ correction for VCC, not a regression from this PR. Master has been red on Callbacks2 for over a month and the MethodError was masking this. I deliberately kept this PR small and focused on the constructor fix per CLAUDE.md "small, focused PRs" guidance — the numerical issue deserves its own investigation and PR.

VectorContinuousCallback no longer has an affect_neg! field — VCC's
per-fire mask carries directionality through to the reverse pass — but
_track_callback was still calling the constructor as if affect_neg!
slotted between affect! and len. The leftover `nothing` made the third
positional argument `Nothing` instead of `Int` (len), so the constructor
threw a MethodError on every adjoint pass through any VCC, regardless
of Julia version. Drop the stray `nothing` and forward the new
initializealg / saved_clock_partitions / maybe_discontinuity /
initialize_save_discretes fields so the tracked callback round-trips
all the user-supplied configuration.

Fixes the MethodError surfaced in test/callbacks/vector_continuous_callbacks.jl
(Callbacks2 testset), which had been blocking all VCC adjoint tests on
master.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review May 20, 2026 17:12
@ChrisRackauckas ChrisRackauckas merged commit e0ea390 into SciML:master May 20, 2026
39 of 50 checks passed
@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor Author

Update: also includes the test-point fix

Pushed commit 090adfe4 shifting u0[4] from 2.0 to 2.01 in test_vector_continuous_callback. This is the proper resolution to the numerical mismatch I noted in the original PR body — verified via central finite differences (see closed #1447 for the full check) that the failing assertions were at a jump discontinuity where ForwardDiff and adjoint legitimately compute different one-sided derivatives, not an algorithmic bug.

With both commits applied, all 11 tests in test/callbacks/vector_continuous_callbacks.jl pass on Julia 1.12.6 locally.

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor Author

Correction: test-point fix moved to its own PR

Pushed a force-update reverting commit 090adfe4 from this PR. The test-point shift now lives in #1448 as a separate small PR. This PR is back to a single concern: the constructor MethodError fix in src/callback_tracking.jl.

Order doesn't matter — either PR can land first. With this one alone, 3/4 testsets in test/callbacks/vector_continuous_callbacks.jl pass and the 4th (callback with linear affect) fails numerically at a jump discontinuity (see closed #1447 for the central-FD writeup). #1448 then shifts the test parameter off the discontinuity so all 4 pass.

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.

2 participants