Lie derivative and Lie bracket
The single function ad ("adjoint action") computes two related objects, dispatching on the output of its second argument:
if the second argument is scalar-valued,
adreturns the Lie derivative;if it is vector-valued,
adreturns the Lie bracket.
Both are computed by automatic differentiation, so the AD backend extension must be loaded.
Lie derivative
The Lie derivative of a scalar function
It measures the infinitesimal rate of change of
Lie bracket
The Lie bracket of two vector fields
where
using CTLie # Lift, ad, Poisson, ∂ₜ, @Lie
using CTBase: Data # VectorField, Hamiltonian, … (accessed as Data.VectorField, etc.)
using CTBase: Traits # trait types (Autonomous, Variable, OutOfPlace, …)
using DifferentiationInterface: DifferentiationInterface # activates the AD backend extensionOn plain functions
For Julia Functions the traits come from the is_autonomous / is_variable keywords.
Lie derivative — energy along a rotation
The rotation field
X = x -> [x[2], -x[1]]
f = x -> x[1]^2 + x[2]^2
L = ad(X, f)
L([1.0, 2.0])0.0Lie bracket — two autonomous fields
F = x -> [x[2], 2x[1]]
G = x -> [3x[2], -x[1]]
B = ad(F, G)
B([1.0, 2.0])2-element Vector{Float64}:
7.0
-14.0Non-autonomous — (t, x)
Ft = (t, x) -> [t + x[2], -2x[1]]
Gt = (t, x) -> [t + 3x[2], -x[1]]
Bt = ad(Ft, Gt; is_autonomous=false)
Bt(1.0, [1.0, 2.0])2-element Vector{Float64}:
-5.0
11.0Variable-dependent — (x, v)
Fv = (x, v) -> [x[2] + v, 2x[1]]
Gv = (x, v) -> [3x[2], v - x[1]]
Bv = ad(Fv, Gv; is_variable=true)
Bv([1.0, 2.0], 1.0)2-element Vector{Float64}:
6.0
-15.0Non-autonomous and variable-dependent — (t, x, v)
Ftv = (t, x, v) -> [t + x[2] + v, -2x[1] - v]
Gtv = (t, x, v) -> [t + 3x[2] + v, -x[1] - v]
Btv = ad(Ftv, Gtv; is_autonomous=false, is_variable=true)
Btv(1.0, [1.0, 2.0], 1.0)2-element Vector{Float64}:
-7.0
12.0On typed vector fields
When both arguments are typed VectorFields, ad returns a typed VectorField whose traits are inherited from the operands. The two fields must share the same time- and variable-dependence (see Limitations & configuration).
X = Data.VectorField(x -> [x[2], 2x[1]]; is_autonomous=true, is_variable=false)
Y = Data.VectorField(x -> [3x[2], -x[1]]; is_autonomous=true, is_variable=false)
Z = ad(X, Y)VectorField: autonomous, fixed (no variable), out-of-place
natural call: f(x)
uniform call: f(t, x, v)Z([1.0, 2.0])2-element Vector{Float64}:
7.0
-14.0The result being itself a VectorField, brackets nest naturally:
Z2 = ad(ad(X, Y), Y)
Z2([1.0, 2.0])2-element Vector{Float64}:
-84.0
-14.0Lie derivative with a typed field
A typed VectorField against a scalar Function gives the Lie derivative, returned as a plain Function:
X = Data.VectorField(x -> [x[2], -x[1]]; is_autonomous=true)
g = x -> x[1]^2 + x[2]^2
ad(X, g)([1.0, 2.0])0.0Antisymmetry, numerically
F = Data.VectorField(x -> [x[2]^2, -2x[1]*x[2]]; is_autonomous=true)
G = Data.VectorField(x -> [x[1]*(1 + x[2]), 3x[2]^3]; is_autonomous=true)
x0 = [1.0, 2.0]
ad(F, G)(x0) ≈ -ad(G, F)(x0)trueSee also
ad— full docstring and method list.The
@Liemacro — write@Lie [X, Y]instead ofad(X, Y), with nesting and arithmetic.Limitations & configuration — no Lie operations on a
HamiltonianVectorField, no in-place fields, matching traits.