Skip to content

Commit d190b98

Browse files
Unwrap AutoSpecialize in AD-over-solve paths and external wrapper extensions
Instead of relying on FunctionWrappersWrapper fallback mode, explicitly unwrap AutoSpecializeCallable in all code paths where ForwardDiff uses non-standard tags: 1. ForwardDiff sensitivity path (nonlinearsolve_forwarddiff_solve): unwrap prob.f.f before computing ∂f/∂p and ∂f/∂u Jacobians, which use closure-based ForwardDiff tags incompatible with the wrappers. Removes the now-unnecessary _is_wrapped_nlf checks and _nls_tag config overrides. 2. External wrapper extensions (LeastSquaresOptim, NLsolve, NLSolvers, SIAM, FastLevenbergMarquardt, MINPACK, PETSc, FixedPointAcceleration, SpeedMapping, Sundials): unwrap at the top of __solve since these packages do their own AD with arbitrary tags. 3. Bounds transform: unwrap before wrapping in BoundedWrapper since the transform changes argument types. 4. Restrict wrapping to supported param types only (Vector{Float64}, NullParameters) — scalar params skip wrapping entirely. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 649a8db commit d190b98

15 files changed

Lines changed: 128 additions & 64 deletions

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
2424
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
2525
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
2626
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
27+
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
2728
SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1"
2829
SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
2930
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
@@ -119,6 +120,7 @@ Reexport = "1.2.2"
119120
ReverseDiff = "1.15"
120121
SIAMFANLEquations = "1.0.1"
121122
SciMLBase = "2.153"
123+
Setfield = "1.1.2"
122124
SciMLLogging = "1.7"
123125
SimpleNonlinearSolve = "2.10"
124126
SparseArrays = "1.10"

ext/NonlinearSolveFastLevenbergMarquardtExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ using ArrayInterface: ArrayInterface
66
using FastLevenbergMarquardt: FastLevenbergMarquardt
77
using StaticArraysCore: SArray
88

9-
using NonlinearSolveBase: NonlinearSolveBase
9+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
1010
using NonlinearSolve: NonlinearSolve, FastLevenbergMarquardtJL
11-
using SciMLBase: SciMLBase, AbstractNonlinearProblem, ReturnCode
11+
using SciMLBase: SciMLBase, AbstractNonlinearProblem, ReturnCode, remake
12+
using Setfield: @set
1213

1314
const FastLM = FastLevenbergMarquardt
1415

@@ -17,6 +18,11 @@ function SciMLBase.__solve(
1718
alias_u0 = false, abstol = nothing, reltol = nothing, maxiters = 1000,
1819
termination_condition = nothing, kwargs...
1920
)
21+
# Unwrap AutoSpecialize — external packages do their own AD
22+
if is_fw_wrapped(prob.f.f)
23+
prob = @set prob.f.f = get_raw_f(prob.f.f)
24+
end
25+
2026
NonlinearSolveBase.assert_extension_supported_termination_condition(
2127
termination_condition, alg
2228
)

ext/NonlinearSolveFixedPointAccelerationExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@ module NonlinearSolveFixedPointAccelerationExt
22

33
using FixedPointAcceleration: FixedPointAcceleration, fixed_point
44

5-
using NonlinearSolveBase: NonlinearSolveBase
5+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
66
using NonlinearSolve: NonlinearSolve, FixedPointAccelerationJL
7-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
7+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
8+
using Setfield: @set
89

910
function SciMLBase.__solve(
1011
prob::NonlinearProblem, alg::FixedPointAccelerationJL, args...;
1112
abstol = nothing, maxiters = 1000, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false),
1213
show_trace::Val = Val(false), termination_condition = nothing, kwargs...
1314
)
15+
# Unwrap AutoSpecialize — external packages do their own AD
16+
if is_fw_wrapped(prob.f.f)
17+
prob = @set prob.f.f = get_raw_f(prob.f.f)
18+
end
19+
1420
if haskey(kwargs, :alias_u0)
1521
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
1622
end

ext/NonlinearSolveLeastSquaresOptimExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ module NonlinearSolveLeastSquaresOptimExt
22

33
using LeastSquaresOptim: LeastSquaresOptim
44

5-
using NonlinearSolveBase: NonlinearSolveBase, TraceMinimal
5+
using NonlinearSolveBase: NonlinearSolveBase, TraceMinimal, is_fw_wrapped, get_raw_f
66
using NonlinearSolve: NonlinearSolve, LeastSquaresOptimJL
7-
using SciMLBase: SciMLBase, AbstractNonlinearProblem, ReturnCode
7+
using SciMLBase: SciMLBase, AbstractNonlinearProblem, ReturnCode, remake
8+
using Setfield: @set
89

910
const LSO = LeastSquaresOptim
1011

@@ -14,6 +15,11 @@ function SciMLBase.__solve(
1415
trace_level = TraceMinimal(), termination_condition = nothing,
1516
show_trace::Val = Val(false), store_trace::Val = Val(false), kwargs...
1617
)
18+
# Unwrap AutoSpecialize — external packages do their own AD
19+
if is_fw_wrapped(prob.f.f)
20+
prob = @set prob.f.f = get_raw_f(prob.f.f)
21+
end
22+
1723
NonlinearSolveBase.assert_extension_supported_termination_condition(
1824
termination_condition, alg
1925
)

ext/NonlinearSolveMINPACKExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ module NonlinearSolveMINPACKExt
33
using FastClosures: @closure
44
using MINPACK: MINPACK
55

6-
using NonlinearSolveBase: NonlinearSolveBase
6+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
77
using NonlinearSolve: NonlinearSolve, CMINPACK
8-
using SciMLBase: SciMLBase, NonlinearLeastSquaresProblem, NonlinearProblem, ReturnCode
8+
using SciMLBase: SciMLBase, NonlinearLeastSquaresProblem, NonlinearProblem, ReturnCode, remake
9+
using Setfield: @set
910

1011
function SciMLBase.__solve(
1112
prob::Union{NonlinearLeastSquaresProblem, NonlinearProblem}, alg::CMINPACK, args...;
1213
abstol = nothing, maxiters = 1000, alias_u0::Bool = false,
1314
show_trace::Val = Val(false), store_trace::Val = Val(false),
1415
termination_condition = nothing, kwargs...
1516
)
17+
# Unwrap AutoSpecialize — external packages do their own AD
18+
if is_fw_wrapped(prob.f.f)
19+
prob = @set prob.f.f = get_raw_f(prob.f.f)
20+
end
21+
1622
NonlinearSolveBase.assert_extension_supported_termination_condition(
1723
termination_condition, alg
1824
)

ext/NonlinearSolveNLSolversExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ using FastClosures: @closure
55

66
using NLSolvers: NLSolvers, NEqOptions, NEqProblem
77

8-
using NonlinearSolveBase: NonlinearSolveBase
8+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
99
using NonlinearSolve: NonlinearSolve, NLSolversJL
10-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
10+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
11+
using Setfield: @set
1112

1213
const DI = DifferentiationInterface
1314

@@ -16,6 +17,11 @@ function SciMLBase.__solve(
1617
abstol = nothing, reltol = nothing, maxiters = 1000, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false),
1718
termination_condition = nothing, kwargs...
1819
)
20+
# Unwrap AutoSpecialize — external packages do their own AD
21+
if is_fw_wrapped(prob.f.f)
22+
prob = @set prob.f.f = get_raw_f(prob.f.f)
23+
end
24+
1925
if haskey(kwargs, :alias_u0)
2026
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
2127
end

ext/NonlinearSolveNLsolveExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@ module NonlinearSolveNLsolveExt
33
using LineSearches: Static
44
using NLsolve: NLsolve, OnceDifferentiable, nlsolve
55

6-
using NonlinearSolveBase: NonlinearSolveBase, Utils, TraceMinimal
6+
using NonlinearSolveBase: NonlinearSolveBase, Utils, TraceMinimal, is_fw_wrapped, get_raw_f
77
using NonlinearSolve: NonlinearSolve, NLsolveJL
8-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
8+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
9+
using Setfield: @set
910

1011
function SciMLBase.__solve(
1112
prob::NonlinearProblem, alg::NLsolveJL, args...;
1213
abstol = nothing, maxiters = 1000, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false),
1314
termination_condition = nothing, trace_level = TraceMinimal(),
1415
store_trace::Val = Val(false), show_trace::Val = Val(false), kwargs...
1516
)
17+
# Unwrap AutoSpecialize — external packages do their own AD
18+
if is_fw_wrapped(prob.f.f)
19+
prob = @set prob.f.f = get_raw_f(prob.f.f)
20+
end
21+
1622
if haskey(kwargs, :alias_u0)
1723
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
1824
end

ext/NonlinearSolvePETScExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ module NonlinearSolvePETScExt
33
using MPI: MPI
44
using PETSc: PETSc
55

6-
using NonlinearSolveBase: NonlinearSolveBase
6+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
77
using NonlinearSolve: NonlinearSolve, PETScSNES
8-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
8+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
9+
using Setfield: @set
910

1011
using SparseArrays: AbstractSparseMatrix, SparseMatrixCSC, sparse, rowvals, nonzeros, nzrange
1112

@@ -40,6 +41,11 @@ function SciMLBase.__solve(
4041
maxiters = 1000, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false), termination_condition = nothing,
4142
show_trace::Val = Val(false), kwargs...
4243
)
44+
# Unwrap AutoSpecialize — external packages do their own AD
45+
if is_fw_wrapped(prob.f.f)
46+
prob = @set prob.f.f = get_raw_f(prob.f.f)
47+
end
48+
4349
if haskey(kwargs, :alias_u0)
4450
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
4551
end

ext/NonlinearSolveSIAMFANLEquationsExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ using FastClosures: @closure
44
using SIAMFANLEquations: SIAMFANLEquations, aasol, nsol, nsoli, nsolsc, ptcsol, ptcsoli,
55
ptcsolsc, secant
66

7-
using NonlinearSolveBase: NonlinearSolveBase
7+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
88
using NonlinearSolve: NonlinearSolve, SIAMFANLEquationsJL
9-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
9+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
10+
using Setfield: @set
1011

1112
function siamfanlequations_retcode_mapping(sol)
1213
if sol.errcode == 0
@@ -42,6 +43,11 @@ function SciMLBase.__solve(
4243
abstol = nothing, reltol = nothing, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false), maxiters = 1000,
4344
termination_condition = nothing, show_trace = Val(false), kwargs...
4445
)
46+
# Unwrap AutoSpecialize — external packages do their own AD
47+
if is_fw_wrapped(prob.f.f)
48+
prob = @set prob.f.f = get_raw_f(prob.f.f)
49+
end
50+
4551
if haskey(kwargs, :alias_u0)
4652
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
4753
end

ext/NonlinearSolveSpeedMappingExt.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@ module NonlinearSolveSpeedMappingExt
22

33
using SpeedMapping: speedmapping
44

5-
using NonlinearSolveBase: NonlinearSolveBase
5+
using NonlinearSolveBase: NonlinearSolveBase, is_fw_wrapped, get_raw_f
66
using NonlinearSolve: NonlinearSolve, SpeedMappingJL
7-
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode
7+
using SciMLBase: SciMLBase, NonlinearProblem, ReturnCode, remake
8+
using Setfield: @set
89

910
function SciMLBase.__solve(
1011
prob::NonlinearProblem, alg::SpeedMappingJL, args...;
1112
abstol = nothing, maxiters = 1000, alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = false),
1213
maxtime = nothing, store_trace::Val = Val(false),
1314
termination_condition = nothing, kwargs...
1415
)
16+
# Unwrap AutoSpecialize — external packages do their own AD
17+
if is_fw_wrapped(prob.f.f)
18+
prob = @set prob.f.f = get_raw_f(prob.f.f)
19+
end
20+
1521
if haskey(kwargs, :alias_u0)
1622
alias = SciMLBase.NonlinearAliasSpecifier(alias_u0 = kwargs[:alias_u0])
1723
end

0 commit comments

Comments
 (0)