Choosing an AD backend
using OptimalControlEverything here is AD-backed, except Lift
ad, Poisson, ∂ₜ, and @Lie all differentiate under the hood; Lift is purely algebraic and never touches a backend at all.
The default
dg_ad_backend()DifferentiationInterface{CPU} (instance, id=:di)
└─ ad_backend = AutoForwardDiff [computed]
Tip: use describe(DifferentiationInterface{CPU}) to see all available options.DifferentiationInterface{CPU} over ForwardDiff, the same default used throughout CTBase/CTLie.
Reading the current backend
dg_ad_backend() (above) always returns the backend that will be used when no ad_backend= keyword is given.
Changing it globally
import CTBase: Differentiation
dg_ad_backend!(Differentiation.DifferentiationInterface())
dg_ad_backend()DifferentiationInterface{CPU} (instance, id=:di)
└─ ad_backend = AutoForwardDiff [computed]
Tip: use describe(DifferentiationInterface{CPU}) to see all available options.Changing it for one call
Every operation in this section accepts its own ad_backend=, overriding the global setting just for that call:
X(x) = [x[2], -x[1]]
f(x) = x[1]^2 + x[2]^2
ad(X, f; ad_backend=Differentiation.DifferentiationInterface())([1.0, 2.0])0.0GPU
A GPU-parameterized backend is constructed the same way, with the GPU strategy instead of CPU:
import CTBase: Differentiation, Strategies
dg_ad_backend!(Differentiation.DifferentiationInterface{Strategies.GPU}())This block is not executed on this page — no CUDA-capable GPU is available in this development environment or in CI, the same caveat as GPU on the solve side.
Introspection
describe(:di)DifferentiationInterface (strategy)
├─ id: :di
├─ hierarchy: DifferentiationInterface → AbstractADBackend → AbstractStrategy
├─ description: AD backend wrapping DifferentiationInterface.jl backends (e.g., AutoForwardDiff).
├─ family: AbstractADBackend
├─ default parameter: CPU
├─ parameters: CPU, GPU
│
├─ computed options for CPU:
│ └─ ad_backend (backend, ad)::ADTypes.AbstractADType (default: AutoForwardDiff() [computed])
│ description: DifferentiationInterface.jl backend (e.g. AutoForwardDiff() on CPU).
│
└─ computed options for GPU:
└─ ad_backend (backend, ad)::ADTypes.AbstractADType (default: ADTypes.AutoMooncake() [computed])
description: DifferentiationInterface.jl backend for GPU execution. Default: AutoMooncake(), validated end-to-end on CuArray including through a mutating in-place RHS. AutoForwardDiff() does not work on GPU (scalar-indexes a CuArray). AutoZygote() can be selected explicitly; it was found unreliable in some device call contexts (an unexpected KernelException was observed on a non-mutating call).If nothing works
If DifferentiationInterface (and a concrete AD package, such as ForwardDiff) isn't loaded, the extension that actually performs the differentiation never arms, and calling ad, Poisson, ∂ₜ, or @Lie fails. OptimalControl loads DifferentiationInterface and ForwardDiff itself, so this only bites if you're using CTLie standalone.
See also
Overview — where each operation sits relative to AD.
GPU — the same
CPU/GPUstrategy split on the solve side.Flows overview — the
method=:cpu/:gpuconstruction-time keyword onFlow.