Skip to content

fix: handle ZeroTangent/AbstractZero in RecursiveArrayToolsZygoteExt adjoint#606

Merged
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-zygote-zerotangent-adjoint
Jun 6, 2026
Merged

fix: handle ZeroTangent/AbstractZero in RecursiveArrayToolsZygoteExt adjoint#606
ChrisRackauckas merged 1 commit into
SciML:masterfrom
ChrisRackauckas-Claude:fix-zygote-zerotangent-adjoint

Conversation

@ChrisRackauckas-Claude
Copy link
Copy Markdown
Contributor

Problem

The Zygote pullbacks in ext/RecursiveArrayToolsZygoteExt.jl for VectorOfArray/DiffEqArray (vofa_u_adjoint) and ArrayPartition only special-cased isnothing(d_i) for missing per-slice gradients. When a cotangent element is a ChainRulesCore.ZeroTangent (an AbstractZero, a structural zero gradient), it was passed through unchanged. The subsequent VectorOfArray/DiffEqArray construction then calls size(::ZeroTangent), throwing:

MethodError: no method matching size(::ChainRulesCore.ZeroTangent)

This breaks reverse-mode AD through DiffEqArray(vec, ts) and shows up downstream (e.g. DifferenceEquations.jl test/linear_gradients.jl:67).

Fix

Treat AbstractZero the same as nothing in the adjoints: a structural zero gradient for that slice (skip reconstruction, propagate a real zero array). AbstractZero is imported from the already-available ChainRulesCore.

Test

Added a focused regression test in test/adjoints.jl that feeds a ZeroTangent cotangent element through vofa_u_adjoint for both VectorOfArray and DiffEqArray and asserts the result is the correct zero gradient (and no longer errors). Verified the test fails on the unpatched code and passes with the fix.

Local run on Julia 1.10 (test/adjoints.jl): PASS.

Ignore until reviewed by @ChrisRackauckas.

🤖 Generated with Claude Code

…adjoint

The Zygote pullbacks for VectorOfArray/DiffEqArray (vofa_u_adjoint) and
ArrayPartition only special-cased `isnothing(d_i)` for missing per-slice
gradients. A ChainRulesCore.ZeroTangent (AbstractZero) cotangent element
was passed through unchanged, and the subsequent VectorOfArray/DiffEqArray
construction called `size(::ZeroTangent)`, throwing a MethodError. This
broke reverse-mode AD through DiffEqArray(vec, ts) (e.g. DifferenceEquations.jl
test/linear_gradients.jl).

Treat AbstractZero the same as nothing: a structural zero gradient for that
slice. Added a regression test in test/adjoints.jl exercising a ZeroTangent
cotangent element for both VectorOfArray and DiffEqArray.

Regression test run locally on Julia 1.10: PASS.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChrisRackauckas ChrisRackauckas marked this pull request as ready for review June 6, 2026 17:00
@ChrisRackauckas ChrisRackauckas merged commit 9eb46bf into SciML:master Jun 6, 2026
28 of 43 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.

2 participants