Canonical Transformations

The canonical module provides tools for Hamiltonian-preserving transformations and the Hamilton-Jacobi equation.

Overview

Canonical transformations preserve the form of Hamilton’s equations. The module implements:

  • Generating Functions: Four types (F1, F2, F3, F4)

  • Poisson Brackets: Verify canonicity via bracket relations

  • Action-Angle Variables: For integrable systems

  • Hamilton-Jacobi Equation: Solve for Hamilton’s principal function

Theory

Generating Functions

A canonical transformation \((q, p) \to (Q, P)\) can be generated by four types of functions:

Type

Arguments

Transformation Equations

F1

F₁(q, Q)

\(p = \partial F_1/\partial q\), \(P = -\partial F_1/\partial Q\)

F2

F₂(q, P)

\(p = \partial F_2/\partial q\), \(Q = \partial F_2/\partial P\)

F3

F₃(p, Q)

\(q = -\partial F_3/\partial p\), \(P = -\partial F_3/\partial Q\)

F4

F₄(p, P)

\(q = -\partial F_4/\partial p\), \(Q = \partial F_4/\partial P\)

Poisson Brackets

Canonical transformations preserve fundamental Poisson brackets:

\[\{Q_i, Q_j\} = 0, \quad \{P_i, P_j\} = 0, \quad \{Q_i, P_j\} = \delta_{ij}\]

Hamilton-Jacobi Equation

For time-independent Hamiltonians:

\[H\left(q, \frac{\partial S}{\partial q}\right) = E\]

where \(S(q, \alpha)\) is Hamilton’s principal function.

Usage Examples

Generating Functions

from mechanics_dsl.domains.classical import (
    GeneratingFunction,
    GeneratingFunctionType,
    CanonicalTransformation
)
import sympy as sp

# Type 2 generating function: F2(q, P) = qP
# This is the identity transformation
q = sp.Symbol('q', real=True)
P = sp.Symbol('P', real=True)

F2 = q * P

gen_func = GeneratingFunction(F2, GeneratingFunctionType.F2)

# Apply transformation
transform = CanonicalTransformation()
new_vars = transform.apply_generating_function(gen_func, 'q', 'P')

print(f"p = {new_vars['p']}")  # p = P
print(f"Q = {new_vars['Q']}")  # Q = q

Point Transformation

from mechanics_dsl.domains.classical import CanonicalTransformation
import sympy as sp

transform = CanonicalTransformation()

# Cartesian to polar: x, y → r, φ
x = sp.Symbol('x', real=True)
y = sp.Symbol('y', real=True)
r = sp.Symbol('r', positive=True)
phi = sp.Symbol('phi', real=True)

# Define transformation
# r = √(x² + y²), φ = arctan(y/x)

# Verify it's canonical using Poisson brackets
is_canonical = transform.verify_canonical(['x', 'y'], ['r', 'phi'])
print(f"Canonical: {is_canonical}")  # True

Verifying Canonicity

from mechanics_dsl.domains.classical import CanonicalTransformation
import sympy as sp

transform = CanonicalTransformation()

q = transform.get_symbol('q')
p = transform.get_symbol('p')

# New variables
Q = sp.sqrt(2*p) * sp.sin(q)
P = sp.sqrt(2*p) * sp.cos(q)

# Compute Poisson bracket {Q, P}
bracket = transform.poisson_bracket(Q, P, ['q'], ['p'])

print(f"{{Q, P}} = {bracket}")  # Should be 1 for canonical

Action-Angle Variables

from mechanics_dsl.domains.classical import ActionAngleVariables
import sympy as sp

aa = ActionAngleVariables()

# Harmonic oscillator: H = p²/(2m) + mω²x²/2
m = sp.Symbol('m', positive=True)
omega = sp.Symbol('omega', positive=True)
x = sp.Symbol('x', real=True)
p = sp.Symbol('p', real=True)

H = p**2 / (2*m) + m * omega**2 * x**2 / 2

# Compute action
# I = (1/2π) ∮ p dx = E/ω
action = aa.compute_action(H, 'x', 'p')
print(f"Action: I = {action}")  # E/ω

# In action-angle: H(I) = ω*I
# Frequency: ω = ∂H/∂I = ω (constant)

Hamilton-Jacobi Equation

from mechanics_dsl.domains.classical import HamiltonJacobi
import sympy as sp

hj = HamiltonJacobi()

# Free particle: H = p²/(2m)
m = sp.Symbol('m', positive=True)
E = sp.Symbol('E', positive=True)
x = sp.Symbol('x', real=True)

# H-J equation: (∂S/∂x)²/(2m) = E
# Solution: S = √(2mE) * x

H = sp.Symbol('p')**2 / (2*m)

S = hj.solve(H, ['x'], energy=E)
print(f"Principal function: S = {S}")
# S = √(2mE) * x

Applying Transformation to Hamiltonian

from mechanics_dsl.domains.classical import CanonicalTransformation
import sympy as sp

transform = CanonicalTransformation()

# Original Hamiltonian
q = transform.get_symbol('q')
p = transform.get_symbol('p')

H = p**2 / 2 + q**2 / 2  # Harmonic oscillator

# Define generating function for action-angle
I = transform.get_symbol('I')
theta = transform.get_symbol('theta')

# Transformation makes H = I (constant action)
H_new = transform.transform_hamiltonian(H, gen_func)
# H_new = I (cyclic in θ!)

API Reference

Classes

class CanonicalTransformation

Apply and verify canonical transformations.

poisson_bracket(f, g, q_vars, p_vars)

Compute \(\{f, g\} = \sum_i (\partial f/\partial q_i)(\partial g/\partial p_i) - (\partial f/\partial p_i)(\partial g/\partial q_i)\).

verify_canonical(old_vars, new_vars)

Check if transformation preserves Poisson brackets.

apply_generating_function(gen_func, *args)

Apply transformation defined by generating function.

class GeneratingFunction(expression, func_type)

Represents a generating function for canonical transformation.

Parameters:
  • expression – Sympy expression for F

  • func_type – GeneratingFunctionType (F1, F2, F3, F4)

class ActionAngleVariables

Compute action-angle variables for integrable systems.

compute_action(H, q, p)

Compute action \(I = (1/2\pi) \oint p \, dq\).

compute_angle_frequency(H, action)

Compute \(\omega = \partial H / \partial I\).

class HamiltonJacobi

Solve Hamilton-Jacobi equation.

solve(H, coordinates, energy)

Solve for Hamilton’s principal function S.

Enums

class GeneratingFunctionType
  • F1: F₁(q, Q)

  • F2: F₂(q, P)

  • F3: F₃(p, Q)

  • F4: F₄(p, P)

See Also