Fix VR_FRM + noise_rate_prototype + adaptive SDE solver hang (#592)#593
Merged
ChrisRackauckas merged 1 commit intoMay 23, 2026
Conversation
`mul!(c::ExtendedJumpArray, A, u)` only writes to `c.u` when `A` matches the original state size. The adaptive LambaEM step reuses the same scratchpad ExtendedJumpArray and writes scalar error estimates into `c.jump_u`, so the next step reads back those stale values as a noise contribution on the jump-rate-integral state. With VR_FRM the state-side integrator never observes `jump_u` crossing zero, so no variable-rate jumps ever fire. Zero `c.jump_u` after the partial mul! so the result reflects the true semantics (no noise contribution on the jump-rate-integral state) and the scratchpad cannot leak between adaptive steps. Adds direct unit tests on `mul!` semantics and a regression test that reproduces the hybrid CLE→SSA hang from the issue. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Contributor
Author
|
CI summary:
Investigating the master docs failure separately. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ignore until reviewed by @ChrisRackauckas.
Closes #592.
Summary
mul!(c::ExtendedJumpArray, A, u)only writes toc.uwhensize(A, 1) == length(c.u)(the noise rate matrix is sized for the original state, not the extended state). The adaptiveLambaEMstep (and other adaptive non-diagonal SDE solvers) reuses the same scratchpadExtendedJumpArrayand writes scalar error-estimate values intoc.jump_uduring the error calculation. On the next step'smul!,c.jump_uis left untouched — so the SDE solver reads back those stale values and adds them to the integrator state as if they were a noise contribution on the jump-rate-integral component. The result is thatjump_uis driven to ±1e15 within a few steps, the VR_FRM continuous-callback condition (u.jump_u[idx]) never crosses zero, and no variable-rate jumps ever fire.The MRE in the issue (hybrid CLE↔SSA birth-death with
noise_rate_prototype = zeros(1, 2)) reproduces this: after the CLE→SSA callback fires,ugets pinned at the threshold (95.0) forever even though the SSA rates are non-zero, because the corresponding continuous callbacks for the variable-rate jumps never trigger.Fix
Zero
c.jump_uafter the partialmul!. Semantically: when the noise matrix only addresses thec.uportion, the noise contribution toc.jump_uis exactly zero, andmul!has overwrite semantics, so the result should reflect that — not whatever happened to be in the scratchpad.Tests
test/extended_jump_array.jl: direct unit tests for bothmul!branches.test/variable_rate.jl: regression test that reproduces the hybrid CLE→SSA scenario from Potential bug when switching from SDE to SSA using Callbacks #592 withnoise_rate_prototypeandLambaEM(adaptive=true). The test verifiesjump_ustays bounded (the bug drove it past ±1e15 within a few steps) and that the post-switch SSA jumps actually fire.Test plan
Run Tests(InterfaceI / InterfaceII)Spell Check,Downgrade,Thread Safety Teststest/variable_rate.jlpasses locally on Julia 1.11 with patched sourcetest/extended_jump_array.jlpasses locally on Julia 1.11 with patched sourceudecays from 95 → 17 overtspan = (0, 10)instead of getting pinned at 95)🤖 Generated with Claude Code