Skip to content

Conversation

@ChrisRackauckas
Copy link
Member

The alg_autodiff function was type-unstable because it used runtime conditionals (if/elseif/else) that could return different types:

  • AutoForwardDiff() for Val{true}
  • AutoFiniteDiff() for Val{false}
  • The original autodiff value otherwise

This caused downstream type inference failures in build_jac_config and build_grad_config, which in turn caused the cache type and solution type to be uninferred in the integrator construction.

The fix uses dispatch-based helper functions (_unwrap_autodiff) instead of runtime conditionals, which allows Julia to resolve the return type at compile time based on the input type.

This is the first step toward fixing inference for Rosenbrock DAE tests.

The alg_autodiff function was type-unstable because it used runtime
conditionals (if/elseif/else) that could return different types:
- AutoForwardDiff() for Val{true}
- AutoFiniteDiff() for Val{false}
- The original autodiff value otherwise

This caused downstream type inference failures in build_jac_config and
build_grad_config, which in turn caused the cache type and solution type
to be uninferred in the integrator construction.

The fix uses dispatch-based helper functions (_unwrap_autodiff) instead
of runtime conditionals, which allows Julia to resolve the return type
at compile time based on the input type.

This is the first step toward fixing inference for Rosenbrock DAE tests.
Comment on lines -22 to -28
if autodiff == Val(true)
return AutoForwardDiff()
elseif autodiff == Val(false)
return AutoFiniteDiff()
else
return autodiff
end
Copy link
Member

@oscardssmith oscardssmith Dec 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively, this could be

    if autodiff isa Val{true}
        return AutoForwardDiff()
    elseif autodiff isa Val{false}
        return AutoFiniteDiff()
    else
        return autodiff
    end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any true advantage of using branching over multiple dispatch for distinguishing executable code by types? I know this is very widely used in the SciML ecosystem, but this if-else by type design pattern causes a lot of trouble when trying to extend codes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can do splits to multiple dispatch, it's just a code structure thing.

Use dispatch-based patterns instead of runtime conditionals to enable
better type inference. Both functions now dispatch on Val{true/false}
based on whether config computation is needed, which allows Julia's
compiler to specialize each branch separately.

This helps the cache construction in Rosenbrock methods infer concrete
types for jac_config and grad_config fields.
Refactor build_jac_config and build_grad_config to dispatch on the
actual field values (f.jac, f.Wfact_t, f.tgrad) rather than using
Val(boolean_condition). This allows Julia to specialize based on
whether these fields have type Nothing vs a function type.

Also add function barrier _make_rosenbrock_cache to help ensure
cache construction sees concrete types.
@github-actions
Copy link
Contributor

github-actions bot commented Dec 13, 2025

Benchmark Results (Julia v1)

Time benchmarks
master 723f94b... master / 723f94b...
construction/linear_N50 27 ± 1 μs 26.5 ± 1.2 μs 1.02 ± 0.059
construction/lotka_volterra 18.1 ± 0.28 μs 17.9 ± 0.23 μs 1.01 ± 0.02
construction/rober 18 ± 0.26 μs 17.8 ± 0.19 μs 1.01 ± 0.018
nonstiff/fitzhugh_nagumo/BS3 0.129 ± 0.039 ms 0.131 ± 0.038 ms 0.987 ± 0.42
nonstiff/fitzhugh_nagumo/DP5 0.088 ± 0.031 ms 0.0866 ± 0.031 ms 1.02 ± 0.51
nonstiff/fitzhugh_nagumo/Tsit5 0.0994 ± 0.045 ms 0.101 ± 0.045 ms 0.988 ± 0.63
nonstiff/fitzhugh_nagumo/Vern6 0.115 ± 0.052 ms 0.115 ± 0.052 ms 1 ± 0.64
nonstiff/fitzhugh_nagumo/Vern7 0.1 ± 0.046 ms 0.103 ± 0.047 ms 0.968 ± 0.63
nonstiff/lotka_volterra/BS3 0.254 ± 0.012 ms 0.257 ± 0.011 ms 0.99 ± 0.065
nonstiff/lotka_volterra/DP5 0.0429 ± 0.016 ms 0.0427 ± 0.017 ms 1.01 ± 0.53
nonstiff/lotka_volterra/Tsit5 0.0548 ± 0.027 ms 0.0549 ± 0.027 ms 0.998 ± 0.7
nonstiff/lotka_volterra/Vern6 0.0663 ± 0.027 ms 0.0688 ± 0.028 ms 0.964 ± 0.56
nonstiff/lotka_volterra/Vern7 0.0582 ± 0.021 ms 0.0591 ± 0.022 ms 0.985 ± 0.52
nonstiff/pleiades/BS3 0.0853 ± 0.025 s 0.0842 ± 0.021 s 1.01 ± 0.39
nonstiff/pleiades/DP5 1.21 ± 0.15 ms 1.21 ± 0.2 ms 1 ± 0.2
nonstiff/pleiades/Tsit5 14.6 ± 8.1 ms 14.4 ± 7.6 ms 1.01 ± 0.78
nonstiff/pleiades/Vern6 6.7 s 6.72 s 0.997
nonstiff/pleiades/Vern7 7.88 s 7.77 s 1.01
scaling/brusselator_2d/16x16 0.317 ± 0.029 s 0.298 ± 0.032 s 1.06 ± 0.15
scaling/brusselator_2d/32x32 7.6 s 7.48 s 1.02
scaling/brusselator_2d/8x8 11.6 ± 0.71 ms 11.3 ± 0.43 ms 1.02 ± 0.074
scaling/linear/N10 0.0369 ± 0.017 ms 0.0357 ± 0.017 ms 1.03 ± 0.69
scaling/linear/N100 0.808 ± 0.014 ms 0.808 ± 0.017 ms 1 ± 0.027
scaling/linear/N50 0.208 ± 0.011 ms 0.208 ± 0.011 ms 1 ± 0.077
stiff/pollution/FBDF 0.592 ± 0.014 ms 0.587 ± 0.012 ms 1.01 ± 0.032
stiff/pollution/KenCarp4 0.55 ± 0.011 ms 0.545 ± 0.01 ms 1.01 ± 0.028
stiff/pollution/Rodas4 0.766 ± 0.011 ms 0.765 ± 0.0091 ms 1 ± 0.018
stiff/pollution/Rosenbrock23 1.37 ± 0.021 ms 1.36 ± 0.02 ms 1 ± 0.022
stiff/pollution/TRBDF2 0.511 ± 0.012 ms 0.512 ± 0.011 ms 0.997 ± 0.032
stiff/rober/FBDF 0.591 ± 0.037 ms 0.591 ± 0.037 ms 1 ± 0.088
stiff/rober/KenCarp4 0.7 ± 0.019 ms 0.702 ± 0.019 ms 0.997 ± 0.038
stiff/rober/Rodas4 0.369 ± 0.028 ms 0.37 ± 0.027 ms 0.996 ± 0.11
stiff/rober/Rosenbrock23 0.27 ± 0.03 ms 0.26 ± 0.029 ms 1.04 ± 0.16
stiff/rober/TRBDF2 1.65 ± 0.085 ms 1.61 ± 0.088 ms 1.03 ± 0.077
stiff/van_der_pol/FBDF 9.64 ± 0.57 ms 9.46 ± 0.57 ms 1.02 ± 0.086
stiff/van_der_pol/KenCarp4 4.58 ± 0.042 ms 4.55 ± 0.034 ms 1.01 ± 0.012
stiff/van_der_pol/Rodas4 6.79 ± 0.1 ms 6.76 ± 0.11 ms 1.01 ± 0.022
stiff/van_der_pol/Rosenbrock23 19.6 ± 0.56 ms 20.1 ± 0.53 ms 0.975 ± 0.038
stiff/van_der_pol/TRBDF2 2.85 ± 0.062 ms 2.84 ± 0.062 ms 1 ± 0.031
time_to_load 3.4 ± 0.096 s 3.35 ± 0.0098 s 1.01 ± 0.029
Memory benchmarks
master 723f94b... master / 723f94b...
construction/linear_N50 0.069 k allocs: 0.041 MB 0.069 k allocs: 0.041 MB 1
construction/lotka_volterra 0.063 k allocs: 2.36 kB 0.063 k allocs: 2.36 kB 1
construction/rober 0.063 k allocs: 2.33 kB 0.063 k allocs: 2.33 kB 1
nonstiff/fitzhugh_nagumo/BS3 3.67 k allocs: 0.158 MB 3.67 k allocs: 0.158 MB 1
nonstiff/fitzhugh_nagumo/DP5 2.62 k allocs: 0.121 MB 2.62 k allocs: 0.121 MB 1
nonstiff/fitzhugh_nagumo/Tsit5 3.98 k allocs: 0.177 MB 3.98 k allocs: 0.177 MB 1
nonstiff/fitzhugh_nagumo/Vern6 4.52 k allocs: 0.202 MB 4.52 k allocs: 0.202 MB 1
nonstiff/fitzhugh_nagumo/Vern7 3.9 k allocs: 0.176 MB 3.9 k allocs: 0.176 MB 1
nonstiff/lotka_volterra/BS3 7.86 k allocs: 0.35 MB 7.86 k allocs: 0.35 MB 1
nonstiff/lotka_volterra/DP5 1.2 k allocs: 0.0524 MB 1.2 k allocs: 0.0524 MB 1
nonstiff/lotka_volterra/Tsit5 2.16 k allocs: 0.0912 MB 2.16 k allocs: 0.0912 MB 1
nonstiff/lotka_volterra/Vern6 2.23 k allocs: 0.0967 MB 2.23 k allocs: 0.0967 MB 1
nonstiff/lotka_volterra/Vern7 1.63 k allocs: 0.0718 MB 1.63 k allocs: 0.0718 MB 1
nonstiff/pleiades/BS3 0.685 M allocs: 0.0673 GB 0.685 M allocs: 0.0673 GB 1
nonstiff/pleiades/DP5 6.65 k allocs: 0.509 MB 6.65 k allocs: 0.509 MB 1
nonstiff/pleiades/Tsit5 0.186 M allocs: 20.2 MB 0.186 M allocs: 20.2 MB 1
nonstiff/pleiades/Vern6 0.038 G allocs: 4.08 GB 0.038 G allocs: 4.08 GB 1
nonstiff/pleiades/Vern7 0.044 G allocs: 4.66 GB 0.044 G allocs: 4.66 GB 1
scaling/brusselator_2d/16x16 3.58 k allocs: 0.152 GB 3.58 k allocs: 0.152 GB 1
scaling/brusselator_2d/32x32 3.39 k allocs: 2.22 GB 3.39 k allocs: 2.22 GB 1
scaling/brusselator_2d/8x8 2.62 k allocs: 8.76 MB 2.62 k allocs: 8.76 MB 1
scaling/linear/N10 0.751 k allocs: 0.0513 MB 0.751 k allocs: 0.0513 MB 1
scaling/linear/N100 2.27 k allocs: 0.899 MB 2.27 k allocs: 0.899 MB 1
scaling/linear/N50 1.65 k allocs: 0.346 MB 1.65 k allocs: 0.346 MB 1
stiff/pollution/FBDF 1.51 k allocs: 0.287 MB 1.51 k allocs: 0.287 MB 1
stiff/pollution/KenCarp4 0.514 k allocs: 0.134 MB 0.514 k allocs: 0.134 MB 1
stiff/pollution/Rodas4 1.28 k allocs: 0.363 MB 1.28 k allocs: 0.363 MB 1
stiff/pollution/Rosenbrock23 2.77 k allocs: 0.817 MB 2.77 k allocs: 0.817 MB 1
stiff/pollution/TRBDF2 0.781 k allocs: 0.166 MB 0.781 k allocs: 0.166 MB 1
stiff/rober/FBDF 2.88 k allocs: 0.132 MB 2.88 k allocs: 0.132 MB 1
stiff/rober/KenCarp4 1.29 k allocs: 0.0556 MB 1.29 k allocs: 0.0556 MB 1
stiff/rober/Rodas4 2.18 k allocs: 0.104 MB 2.18 k allocs: 0.104 MB 1
stiff/rober/Rosenbrock23 2.49 k allocs: 0.116 MB 2.49 k allocs: 0.116 MB 1
stiff/rober/TRBDF2 7.7 k allocs: 0.344 MB 7.7 k allocs: 0.344 MB 1
stiff/van_der_pol/FBDF 0.0443 M allocs: 2.01 MB 0.0443 M allocs: 2.01 MB 1
stiff/van_der_pol/KenCarp4 4.27 k allocs: 0.185 MB 4.27 k allocs: 0.185 MB 1
stiff/van_der_pol/Rodas4 0.0377 M allocs: 1.74 MB 0.0377 M allocs: 1.74 MB 1
stiff/van_der_pol/Rosenbrock23 0.213 M allocs: 9.51 MB 0.213 M allocs: 9.51 MB 1
stiff/van_der_pol/TRBDF2 5.02 k allocs: 0.245 MB 5.02 k allocs: 0.245 MB 1
time_to_load 0.145 k allocs: 11 kB 0.145 k allocs: 11 kB 1

Convert remaining runtime conditional to type-based dispatch:
- _build_jac_config_alg(::Nothing, ::Nothing) -> compute config
- _build_jac_config_alg(::Nothing, linsolve) -> check needs_concrete_A
- _build_jac_config_alg(::Bool, linsolve) -> check bool value

For default Rodas5P (concrete_jac=nothing, linsolve=nothing), this
dispatches directly to the config computation without any runtime
conditionals, enabling full type inference.
@ChrisRackauckas ChrisRackauckas merged commit 2d6a2ac into master Dec 14, 2025
292 of 435 checks passed
@ChrisRackauckas ChrisRackauckas deleted the claude/fix-rosenbrock-inference-01HJCdwyyMxVHCrV6qJHPqGj branch December 14, 2025 21:46
@ChrisRackauckas
Copy link
Member Author

accidentally merged and reverted

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.

5 participants