Compatibility
This section says, for each way of building a flow, which state types, element types and call styles work. Each page has a table and a minimal executable example for every cell.
How these pages stay true
Results are executed. Every ✓ / ⚠ / ✗ example is an
@exampleblock re-run on each documentation build, so a result cannot drift from the code.Scope comes from a probe. Which containers and axes are tested follows the CPU capability probe,
probe/cpu/probe_cpu.jl. A new axis appears here once it is added to the probe.GPU is the exception. The documentation build has no device: the GPU page reports a run of
probe/gpu, not executed examples.
Pages
| Constructor | Builds | Page |
|---|---|---|
| (all constructors) | — | Shape contract: when a 1-D state is a scalar |
Flow(::VectorField) | StateFlow | Flow(VectorField) |
Flow(::HamiltonianVectorField) | HamiltonianFlow | Flow(HamiltonianVectorField) |
Flow(::Hamiltonian) | HamiltonianFlow | Flow(Hamiltonian) |
Flow(::ODEFunction) / Flow(::ODEProblem) | StateFlow / SciMLProblemFlow | Flow(SciML) |
Flow(ocp) (control-free) | OptimalControlFlow | Flow(ocp) |
Flow(ocp, law) | OptimalControlFlow / ControlledFlow | Flow(ocp, law) |
Flow(h̃, law) | HamiltonianFlow | Flow(h̃, law) |
Flow(h̃vf, law) | HamiltonianFlow | Flow(h̃vf, law) |
Flow(fc, law) | ControlledFlow | Flow(fc, law) |
| (all, on device) | — | GPU |
At a glance
"Containers" are scalars, Vector, Matrix (one column per trajectory), MVector / SVector and MMatrix / SMatrix. "Real" means Float64 elements.
| Constructor | Real, every container | Complex | Hand-built ForwardDiff.Dual | Caveat |
|---|---|---|---|---|
Flow(VectorField) | ✓ | ✓ | ✓ | in-place field + immutable state: works, warns |
Flow(HamiltonianVectorField) | ✓ | ✓ | ✓ | same as above |
Flow(Hamiltonian) | ✓ | ✗ | ✗ | AD-backed: differentiate the call, not a Dual state |
Flow(::ODEFunction) | ✓ | ✓ | ✓ | same as Flow(VectorField) |
Flow(::ODEProblem) | ✓ | ✓ | ✓ | no shape coercion; in-place problem + immutable state: SciML error |
Flow(ocp) | ✓ | ✗ | ✗ | the state dimension is fixed by the OCP |
Flow(ocp, DynClosedLoop) | ✓ | ✗ | ✗ | same with constraint=/multiplier=; :total = :partial for a stationary law |
Flow(ocp, OpenLoop/ClosedLoop) | ✓ | ✓ | point call only | the trajectory call computes the objective, which is not Dual-transparent |
Flow(h̃, law) | ✓ | ✗ | ✗ | DynClosedLoop only |
Flow(h̃vf, law) | ✓ | ✓ | ✓ | DynClosedLoop only; in-place + immutable: warns |
Flow(fc, law) | ✓ | ✓ | ✓ | OpenLoop/ClosedLoop only |
Why the AD-backed flows reject Complex and hand-built Dual states: the default backend, AutoForwardDiff, does not handle Complex, and a Dual passed as x0 collides with the flow's own Duals. To get sensitivities of such a flow, wrap the call in ForwardDiff.jacobian; see Flow(Hamiltonian).
On device, AD-free flows need no keyword: pass CuArrays. For AD-backed flows, AutoMooncake is the backend that handles every measured call shape; see GPU. On CPU, AutoMooncake works on every AD-backed flow too and pays off for large states; it refuses Dual states, i.e. an outer ForwardDiff through the flow.
See also
Flows overview: the data → systems → flows → trajectories pipeline.
Building a flow: the shortcut constructor and the explicit pipeline.
Integrating: call styles, variable parameters, integrator options.