Accessors
Building a flow doesn't throw away what it was built from — a flow remembers its Hamiltonian, its vector field, the control law you passed in, and the underlying integrator. This page is the map of what you can pull back out, and from which kind of flow.
using OptimalControl
using OrdinaryDiffEqTsit5
using NLPModelsIpoptWhat a flow remembers
Every flow wraps a system (the mathematical object — a Hamiltonian, a vector field, a pseudo-Hamiltonian plus a law...) and an integrator. The four accessors below read off the system; the last section reaches the integrator directly.
The Hamiltonian
h(x, p) = 0.5 * (x^2 + p^2)
f = Flow(Hamiltonian(h))
H = hamiltonian(f)
H(0.0, 1.0, 0.0, 1.0) # H(t, x, p, v)0.5The Hamiltonian vector field
hamiltonian_vector_field(f)HamiltonianVectorField: autonomous, fixed (no variable), out-of-place
natural call: f(x, p)
uniform call: f(t, x, p, v)Returns a HamiltonianVectorField —
The pseudo-Hamiltonian and the control law
Only available on flows built from a pseudo-Hamiltonian (or an OCP, which is one under the hood) plus a law:
htilde(x, p, u) = p * u - 0.5 * u^2
law_fun(x, p) = p
f_ph = Flow(PseudoHamiltonian(htilde), DynClosedLoop(law_fun))
H̃ = pseudo_hamiltonian(f_ph)
H̃(0.0, 1.0, 0.0, 1.0, 1.0) # H̃(t, x, p, u, v)-0.5control_law(f_ph)(1.0, 0.5) # the law you passed in, u(x, p)0.5Gradients
Four functions, each returning a struct-wrapped callable (not a bare function or a vector) — expect (t, x, p, v)-shaped arguments when calling what they return:
get_hamiltonian_gradient(f_ph)CTFlows.Systems.HamiltonianGradient{ComposedHamiltonian{CTBase.Traits.Autonomous, CTBase.Traits.Fixed, PseudoHamiltonian{typeof(Main.htilde), CTBase.Traits.Autonomous, CTBase.Traits.Fixed}, ControlLaw{typeof(Main.law_fun), CTBase.Traits.DynClosedLoopFeedback, CTBase.Traits.Autonomous, CTBase.Traits.Fixed}}, CTBase.Differentiation.DifferentiationInterface{CPU, CTBase.Strategies.StrategyOptions{@NamedTuple{ad_backend::CTBase.Options.OptionValue{AutoForwardDiff{nothing, Nothing}}}}}}(ComposedHamiltonian: autonomous, fixed (no variable)
natural call: h(x, p)
uniform call: h(t, x, p, v), DifferentiationInterface{CPU}(ad_backend=AutoForwardDiff))get_variable_gradient(f_ph)CTFlows.Systems.HamiltonianVariableGradient{ComposedHamiltonian{CTBase.Traits.Autonomous, CTBase.Traits.Fixed, PseudoHamiltonian{typeof(Main.htilde), CTBase.Traits.Autonomous, CTBase.Traits.Fixed}, ControlLaw{typeof(Main.law_fun), CTBase.Traits.DynClosedLoopFeedback, CTBase.Traits.Autonomous, CTBase.Traits.Fixed}}, CTBase.Differentiation.DifferentiationInterface{CPU, CTBase.Strategies.StrategyOptions{@NamedTuple{ad_backend::CTBase.Options.OptionValue{AutoForwardDiff{nothing, Nothing}}}}}}(ComposedHamiltonian: autonomous, fixed (no variable)
natural call: h(x, p)
uniform call: h(t, x, p, v), DifferentiationInterface{CPU}(ad_backend=AutoForwardDiff))get_pseudo_hamiltonian_gradient(f_ph) and get_pseudo_variable_gradient(f_ph) mirror the two above, taken on
Building the Hamiltonian vector field from a Hamiltonian, without a flow
hamiltonian_vector_field also works directly on an AbstractHamiltonian, no Flow needed:
hamiltonian_vector_field(Hamiltonian(h))HamiltonianVectorField: autonomous, fixed (no variable), out-of-place
natural call: f(x, p)
uniform call: f(t, x, p, v)What is available on which flow
Not every accessor makes sense on every flow — and the failure mode differs by why it doesn't apply, confirmed live rather than assumed uniform:
| Built from | hamiltonian | hamiltonian_vector_field | pseudo_hamiltonian | control_law |
|---|---|---|---|---|
Hamiltonian(h) | ✅ | ✅ | ✗ IncorrectArgument | ✗ IncorrectArgument |
HamiltonianVectorField(hvf) | ✗ IncorrectArgument | ✅ | ✗ MethodError | ✗ MethodError |
PseudoHamiltonian(h̃), law | ✅ | ✅ | ✅ | ✅ |
ocp, law | ✅ | ✅ | ✅ | ✅ |
VectorField(f) | ✗ MethodError | ✗ MethodError (use vector_field) | ✗ MethodError | ✗ MethodError |
IncorrectArgument shows up where the flow could answer in principle but deliberately doesn't have enough information (a HamiltonianVectorField-built flow has no scalar Hamiltonian to hand back, only its vector field — the error says so and suggests hamiltonian_vector_field instead). MethodError shows up where the accessor simply has no method for that system type at all — a VectorField-built flow was never given anything Hamiltonian-shaped, so none of the four Hamiltonian-side accessors apply; use vector_field instead:
vector_field(Flow(VectorField(x -> -x)))VectorField: autonomous, fixed (no variable), out-of-place
natural call: f(x)
uniform call: f(t, x, v)julia> hamiltonian(Flow(HamiltonianVectorField((x, p) -> (p, -x))))
IncorrectArgument → top-level scope, REPL[1]:2
│
│ no scalar Hamiltonian available for a HamiltonianVectorFieldSystem
│
│ Got a HamiltonianVectorFieldSystem (stores the vector field directly, no AD)
│ Expected a HamiltonianSystem or PseudoHamiltonianSystem (built from a scalar Hamiltonian with AD)
│
│ Context hamiltonian(sys::HamiltonianVectorFieldSystem)
│ Hint use hamiltonian_vector_field(flow) to retrieve X_H, or build the flow from a scalar Hamiltonian
└─The underlying system and integrator
Escape hatch, for when nothing above is specific enough — system/integrator stay deliberately unexported (too generic a name for a DSL surface), reach them qualified:
CTFlows.Flows.system(f)HamiltonianSystem
├─ time_dependence: Autonomous
├─ variable_dependence: Fixed
├─ Hamiltonian: autonomous, fixed (no variable)
│ natural call: h(x, p)
│ uniform call: h(t, x, p, v)
└─ backend: DifferentiationInterface{CPU}(ad_backend=AutoForwardDiff)CTFlows.Flows.integrator(f)SciML{CPU} (instance, id=:sciml)
├─ internalnorm = real_norm [default]
├─ alg = Tsit5 [default]
├─ reltol = 1.0e-8 [default]
├─ save_everystep = auto [default]
├─ abstol = 1.0e-8 [default]
├─ save_start = auto [default]
└─ dense = auto [default]
Tip: use describe(SciML{CPU}) to see all available options.See also
From an OCP — the most common source of a flow with all four accessors available.
From Hamiltonians and vector fields — every constructor in the table above, built and shown in full.
Geometry — the Lie-theoretic tools these systems are built on.