Euler-Lagrange Library Functions

EulerLagrange.DegenerateLagrangianSystemType
DegenerateLagrangianSystem(K, H, t, x, v, params = NamedTuple(); simplify = false,
                           scalarize = true, cse = true, nanmath = false)

The equations of motion of a degenerate Lagrangian $L = K - H$, generated symbolically.

A degenerate Lagrangian is already first order in $n$ equations, so ω is the $n × n$ two-form $ω_{ij} = ∂ϑ_i/∂q_j - ∂ϑ_j/∂q_i$. See LagrangianSystem for the regular, $2n × 2n$ case.

The secondary constraint ψ takes both time derivatives, matching the LDAE interface: ψ(out, t, q, v, p, q̇, ṗ, params), computing $\dot p - \dot q \cdot ∇ϑ(t, q)$.

Keyword arguments

  • simplify: apply Symbolics.simplify to K and H before differentiating, and to the inverse two-form σ = inv(ω) and the resulting vector field. Off by default; see LagrangianSystem for the measurements. It is worth at most ~10% on the evaluation of the σ ∇H vector field here, against ~270× the construction cost.
  • scalarize: apply Symbolics.scalarize to K and H, expanding array expressions.
  • cse: eliminate common subexpressions in the generated code. On by default; it binds constant nodes to temporaries as well, so results may differ from cse = false in the last bit.
  • nanmath: emit NaNMath variants of functions like log, sqrt and ^, which return NaN outside their real domain instead of throwing a DomainError. Off by default, so the generated code uses the ordinary Base functions and an out-of-domain state is reported as an error rather than propagating silently.
source
EulerLagrange.HamiltonianSystemType
HamiltonianSystem(H, t, q, p, params = NamedTuple(); simplify = false, scalarize = true,
                  cse = true, nanmath = false)

The equations of motion of the Hamiltonian H, generated symbolically.

Keyword arguments

  • simplify: apply Symbolics.simplify to H before differentiating. Off by default; see LagrangianSystem for the measurements behind that choice.
  • scalarize: apply Symbolics.scalarize to H, expanding array expressions into components.
  • cse: eliminate common subexpressions in the generated code. On by default; it binds constant nodes to temporaries as well, so results may differ from cse = false in the last bit.
  • nanmath: emit NaNMath variants of functions like log, sqrt and ^, which return NaN outside their real domain instead of throwing a DomainError. Off by default, so the generated code uses the ordinary Base functions and an out-of-domain state is reported as an error rather than propagating silently.
source
EulerLagrange.LagrangianSystemType
LagrangianSystem(L, t, x, v, params = NamedTuple(); simplify = false, scalarize = true,
                 cse = true, nanmath = false)

The equations of motion of a regular Lagrangian L, generated symbolically.

Since L is regular, the system is second order in $n$ equations, equivalently first order in $2n$; accordingly ω is the $2n × 2n$ two-form on $(q, \dot q)$. See DegenerateLagrangianSystem for the first-order, $n × n$ case.

Keyword arguments

  • simplify: apply Symbolics.simplify to L before differentiating. Off by default, because it is at best neutral and often much worse: it rewrites a sum of fractions into a common-denominator form whose derivatives are far more expensive both to build and to evaluate. Measured across every EulerLagrange-based problem in GeometricProblems (88 generated functions), simplify = true was never faster to evaluate and up to 15× slower, at 23× the total construction cost.
  • scalarize: apply Symbolics.scalarize to L, expanding array expressions into components.
  • cse: eliminate common subexpressions in the generated code. On by default: measured over 45 generated functions in GeometricProblems it was faster to evaluate 18 times, slower once, and equal otherwise, with the wins concentrated in the forces (up to 8.4× on the 18-degree-of-freedom N-body force). Note that it emits larger code in most cases — it binds constant nodes to temporaries as well as shared subexpressions — so size is not a proxy for speed here. Binding constants also means results may differ from cse = false in the last bit.
  • nanmath: emit NaNMath variants of functions like log, sqrt and ^, which return NaN outside their real domain instead of throwing a DomainError. Off by default, so the generated code uses the ordinary Base functions and an out-of-domain state is reported as an error rather than propagating silently.
source
EulerLagrange.substitute_accelerationMethod
substitute_acceleration(equ, dv, Λ)

Replace the time derivatives of the velocities, dv = d/dt(v), by the algebraic variable Λ.

Any quantity built from Dt(∂L/∂v)g, and hence EL = f - g and ψ = ṗ - g — contains the acceleration. substitute_ẋ_with_v removes only the first derivatives d/dt(x), so without this the generated code refers to an unevaluated Differential(t)(v[i]): a variable that does not exist, which makes the function throw as soon as it is called. Λ is the slot the generated signatures already carry for exactly this purpose.

source
EulerLagrange.substitute_parametersMethod
substitute_parameters(code, params)

Rewrite the anonymous function code built by Symbolics.build_function so that it takes a single params argument in place of one argument per entry of params.

symbolize names the symbolic stand-in for parameter k as kₚ, so build_function emits a signature like (ˍ₋out, t, X, V, Gₚ, mₚ) and a body referring to Gₚ and mₚ. This returns the equivalent (ˍ₋out, t, X, V, params) with params.G and params.m in the body. When params is empty, only the params argument is appended.

This walks the expression rather than round-tripping it through string and Meta.parse. The generated code reaches ~1 MB for a matrix-valued quantity in 18 degrees of freedom, where the text round-trip is both slow and dependent on how Base.show happens to render an Expr.

source
EulerLagrange.substitute_time_derivativesMethod
substitute_time_derivatives(equ, dq, V, dp, F)

Replace the time derivatives dq = d/dt(q) and dp = d/dt(p) by the algebraic variables V, F.

The residual forms EHq = q̇ - ∂H/∂p and EHp = ṗ + ∂H/∂q contain those derivatives, and nothing else in the pipeline removes them, so without this they reach build_function as derivatives of variables the generated function never receives.

source