Fix Enzyme compatibility: Add extension for EnzymeAdjoint gradient computation #320
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.
Summary
Fixes #319 - Resolves NaN gradient values when using
EnzymeAdjointsensitivity algorithm withSciMLOperators.Problem
When using
SciMLOperatorswithEnzymeAdjointfor sensitivity analysis, gradients were computed as[NaN, NaN]instead of the correct numerical values. The issue was specific to operators with parameter-dependent coefficients (likeScalarOperatorwith update functions).Root Cause
SciMLOperatorsstore update functions as closures in Function-typed fields (e.g.,ScalarOperator.update_func,MatrixOperator.update_func). These closures capture mutable state from parameters. When Enzyme attempted automatic differentiation, it tried to differentiate through these Function objects, which led to incorrect gradient computation.Solution
Created a new Enzyme extension (
ext/SciMLOperatorsEnzymeExt.jl) that provides custom differentiation rules for Enzyme:DEFAULT_UPDATE_FUNCandpreprocess_update_funcmul!,*,+), so the operator structures just orchestrate these operations without being differentiated themselvesChanges
ext/SciMLOperatorsEnzymeExt.jlwith Enzyme custom rulesProject.toml:Enzymefrom[deps]to[weakdeps](optional dependency)SciMLOperatorsEnzymeExt = "Enzyme"to[extensions]SparseArraysto[weakdeps]to resolve circular dependency warningsEnzyme = "0.13"Testing
Verified the fix resolves the issue reported in #319. The gradient computation now produces correct values instead of NaN.
Notes
The extension uses Julia's package extension system, so Enzyme is only loaded when users explicitly use it. This adds no overhead for users not using Enzyme.
🤖 Generated with Claude Code