mechanics_dsl package
Submodules
mechanics_dsl.compiler module
Main compiler and system serialization for MechanicsDSL
- class mechanics_dsl.compiler.SystemSerializer[source]
Bases:
objectSerialize and deserialize compiled physics systems
- static export_system(compiler: PhysicsCompiler, filename: str, format: str = 'json') bool[source]
Export compiled system to file
- Parameters:
compiler – PhysicsCompiler instance
filename – Output filename
format – Export format (‘json’ or ‘pickle’)
- Returns:
True if successful
- static import_system(filename: str, allow_pickle: bool = False) dict | None[source]
Import system state from file with validation.
- Parameters:
filename – Input filename (validated)
allow_pickle – Required to be True to load .pkl/.pickle files. Pickle deserialization can execute arbitrary code, so this is refused by default. Only enable for fully trusted local files (e.g. ones you produced yourself).
- Returns:
System state dictionary or None if failed
- Raises:
TypeError – If filename is not a string
ValueError – If filename is invalid
FileNotFoundError – If file doesn’t exist
- class mechanics_dsl.compiler.ParticleGenerator[source]
Bases:
objectGenerates discrete particle positions from geometric regions
- class mechanics_dsl.compiler.PhysicsCompiler[source]
Bases:
objectMain compiler class.
Production-ready physics DSL compiler with comprehensive validation, cross-platform support, and security hardening.
Features: - Cross-platform timeout support (Windows/Unix) - Safe AST-based parsing (no eval()) - Comprehensive input validation - Specific exception handling - Extensive type hints - Production-ready error recovery
Example
>>> compiler = PhysicsCompiler() >>> result = compiler.compile_dsl("\system{pendulum}\lagrangian{x^2}") >>> if result['success']: ... solution = compiler.simulate((0, 10)) ... compiler.animate(solution)
- compile_dsl(dsl_source: str, use_hamiltonian: bool = False, use_constraints: bool = True) dict[source]
Complete compilation pipeline with comprehensive validation.
- Parameters:
dsl_source – DSL source code (must be non-empty string)
use_hamiltonian – Force Hamiltonian formulation
use_constraints – Apply constraint handling
- Returns:
Compilation result dictionary with ‘success’ key
- Raises:
TypeError – If dsl_source is not a string
ValueError – If dsl_source is empty or invalid
Example
>>> compiler = PhysicsCompiler() >>> result = compiler.compile_dsl(r"\system{test}\lagrangian{x^2}") >>> assert result['success']
- get_coordinates() List[str][source]
Extract generalized coordinates (exclude constants).
Uses the registry module’s is_likely_coordinate() function to determine which variables are dynamic coordinates vs. constants/parameters.
- Returns:
List of coordinate variable names
- derive_equations() Dict[str, Expr][source]
Derive equations using Lagrangian formulation (Patched for Forces)
- derive_constrained_equations() Dict[str, Expr][source]
Derive equations with constraints using Lagrange multipliers
- derive_hamiltonian_equations() Tuple[List[Expr], List[Expr]][source]
Derive equations using Hamiltonian formulation
- simulate(t_span: Tuple[float, float] = (0, 10), num_points: int = 1000, **kwargs) dict[source]
Run numerical simulation
- export_animation(solution: dict, filename: str, fps: int = 30, dpi: int = 100) str[source]
Export animation to file
- export(target: str, filename: str) str[source]
Generate standalone simulation code for a target language.
- Parameters:
target – Target language identifier (see _GENERATOR_REGISTRY for the list, e.g. ‘cpp’, ‘python’, ‘rust’, ‘julia’, ‘cuda’, …).
filename – Output file path for the generated source.
- Returns:
Path to the generated file.
- Raises:
ValueError – If target is not supported or the compiler has no equations yet.
IOError – If the file cannot be written.
- static import_system(filename: str, allow_pickle: bool = False) PhysicsCompiler | None[source]
Import system state from file.
See
SystemSerializer.import_systemfor the semantics ofallow_pickle; pickle loading is refused by default.
- compile_to_cpp(filename: str = 'simulation.cpp', target: str = 'standard', compile_binary: bool = True) bool[source]
Generate C++ code for multiple targets.
- Parameters:
filename – Output filename
target – ‘standard’, ‘raylib’, ‘arduino’, ‘wasm’, ‘openmp’, ‘python’
compile_binary – Whether to run the compiler (g++, emcc, etc.)
mechanics_dsl.solver module
MechanicsDSL Solver Package
This package provides numerical simulation capabilities for physics systems defined in MechanicsDSL.
- Modules:
core: Main NumericalSimulator class symplectic: Structure-preserving symplectic integrators for Hamiltonian systems variational: Discrete variational integrators from Hamilton’s principle
- Symplectic Integrators:
StormerVerlet, Leapfrog, Yoshida4, Ruth3, McLachlan4 - Preserve symplectic structure and bounded energy error - Ideal for long-time integration of Hamiltonian systems
- Variational Integrators:
MidpointVariational, TrapezoidalVariational, GalerkinVariational - Derived from discrete Hamilton’s principle - Exactly preserve momentum maps (Noether’s theorem)
- Quick Start:
>>> from mechanics_dsl.solver import NumericalSimulator >>> from mechanics_dsl.solver.symplectic import StormerVerlet >>> verlet = StormerVerlet() >>> result = verlet.integrate(t_span, q0, p0, h, grad_T, grad_V)
- class mechanics_dsl.solver.NumericalSimulator(symbolic_engine: SymbolicEngine)[source]
Bases:
objectEnhanced numerical simulator with better stability and diagnostics
- compile_equations(accelerations: Dict[str, Expr], coordinates: List[str])[source]
Compile symbolic equations to numerical functions
- compile_hamiltonian_equations(q_dots: List[Expr], p_dots: List[Expr], coordinates: List[str])[source]
Compile Hamiltonian equations
- equations_of_motion(t: float, y: ndarray) ndarray[source]
ODE system for numerical integration with comprehensive bounds checking and validation.
- Parameters:
t – Current time
y – State vector
- Returns:
Derivative vector dydt
- simulate(t_span: Tuple[float, float], num_points: int = 1000, method: str = None, rtol: float = None, atol: float = None, detect_stiff: bool = True) dict[source]
Run numerical simulation with adaptive integration and diagnostics.
- Parameters:
t_span – Time span (t_start, t_end) where t_start < t_end
num_points – Number of output points (must be >= 2)
method – Integration method (‘RK45’, ‘LSODA’, ‘Radau’, etc.)
rtol – Relative tolerance (must be in (0, 1))
atol – Absolute tolerance (must be positive)
detect_stiff – Whether to detect stiff systems
- Returns:
Dictionary with solution data and metadata, always contains ‘success’ key
- Raises:
TypeError – If arguments have wrong types
ValueError – If arguments are out of valid ranges
Example
>>> solution = simulator.simulate((0, 10), num_points=1000) >>> if solution['success']: ... t = solution['t'] ... y = solution['y']
- async simulate_async(t_span: Tuple[float, float], num_points: int = 1000, method: str | None = None, rtol: float | None = None, atol: float | None = None, detect_stiff: bool = True, executor: Executor | None = None) Dict[str, Any][source]
Run numerical simulation asynchronously.
This method runs the simulation in a thread pool executor to avoid blocking the event loop. Useful for: - Jupyter notebooks (keeps the kernel responsive) - Async web backends (FastAPI, aiohttp) - GUI applications with async event loops
- Parameters:
t_span – Time span (t_start, t_end)
num_points – Number of output points
method – Integration method (‘RK45’, ‘LSODA’, ‘Radau’, etc.)
rtol – Relative tolerance
atol – Absolute tolerance
detect_stiff – Whether to detect stiff systems
executor – Optional custom executor (defaults to ThreadPoolExecutor)
- Returns:
Dictionary with solution data and metadata
Example
>>> import asyncio >>> async def main(): ... result = await simulator.simulate_async((0, 10), num_points=1000) ... print(f"Success: {result['success']}") >>> asyncio.run(main())
Note
For CPU-bound simulations, consider using ProcessPoolExecutor for true parallelism (requires picklable equations).
- async simulate_batch_async(simulations: List[Dict[str, Any]], max_concurrent: int = 4) List[Dict[str, Any]][source]
Run multiple simulations concurrently.
Useful for parameter sweeps, sensitivity analysis, or ensemble simulations where many similar systems need to be simulated.
- Parameters:
simulations – List of simulation parameter dicts, each containing: - t_span: Tuple[float, float] (required) - num_points: int (optional, default 1000) - method: str (optional) - rtol: float (optional) - atol: float (optional)
max_concurrent – Maximum concurrent simulations
- Returns:
List of simulation results in the same order as input
Example
>>> simulations = [ ... {'t_span': (0, 10), 'num_points': 500}, ... {'t_span': (0, 20), 'num_points': 1000}, ... ] >>> results = await simulator.simulate_batch_async(simulations)
- class mechanics_dsl.solver.SymplecticIntegrator[source]
Bases:
ABCBase class for symplectic integrators.
- All symplectic integrators work with Hamiltonian systems of the form:
dq/dt = ∂H/∂p dp/dt = -∂H/∂q
- For separable Hamiltonians H(q,p) = T(p) + V(q):
dq/dt = ∂T/∂p = p/m (for standard kinetic energy) dp/dt = -∂V/∂q = F(q) (generalized force)
- abstract property order: int
Order of accuracy of the integrator.
- abstract property name: str
Human-readable name of the integrator.
- abstract step(t: float, q: ndarray, p: ndarray, h: float, grad_T: Callable[[ndarray], ndarray], grad_V: Callable[[ndarray], ndarray]) Tuple[ndarray, ndarray][source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- integrate(t_span: Tuple[float, float], q0: ndarray, p0: ndarray, h: float, grad_T: Callable[[ndarray], ndarray], grad_V: Callable[[ndarray], ndarray], t_eval: ndarray | None = None, max_steps: int = 100000) Dict[str, ndarray][source]
Integrate the system from t_span[0] to t_span[1].
- Parameters:
t_span – (t_start, t_end)
q0 – Initial positions
p0 – Initial momenta
h – Fixed step size
grad_T – Gradient of kinetic energy
grad_V – Gradient of potential energy
t_eval – Optional times at which to evaluate solution
max_steps – Maximum integration steps
- Returns:
‘t’: Time array
’q’: Position array (shape: n_coords x n_times)
’p’: Momentum array (shape: n_coords x n_times)
’success’: Boolean indicating success
’message’: Status message
- Return type:
Dictionary with keys
- class mechanics_dsl.solver.StormerVerlet[source]
Bases:
SymplecticIntegratorStörmer-Verlet integrator (2nd order, explicit symplectic).
- The velocity Verlet formulation:
p_half = p_n - (h/2) * ∇V(q_n) q_{n+1} = q_n + h * ∇T(p_half) p_{n+1} = p_half - (h/2) * ∇V(q_{n+1})
Properties: - 2nd order accurate - Symplectic - Time-reversible - Explicit (no implicit solves needed for separable H) - Energy oscillates around true value, bounded error
- property order: int
Order of accuracy of the integrator.
- property name: str
Human-readable name of the integrator.
- step(t, q, p, h, grad_T, grad_V)[source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- class mechanics_dsl.solver.Leapfrog[source]
Bases:
SymplecticIntegratorLeapfrog integrator (2nd order, explicit symplectic).
Mathematically equivalent to Störmer-Verlet but with staggered storage pattern. Often preferred for N-body simulations.
- Algorithm:
q_{n+1} = q_n + h * ∇T(p_{n+1/2}) p_{n+3/2} = p_{n+1/2} - h * ∇V(q_{n+1})
- property order: int
Order of accuracy of the integrator.
- property name: str
Human-readable name of the integrator.
- step(t, q, p, h, grad_T, grad_V)[source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- class mechanics_dsl.solver.Yoshida4[source]
Bases:
SymplecticIntegratorYoshida 4th order symplectic integrator.
- Composition method using triple-jump technique:
S_h = S_{c_1 h} ∘ S_{c_2 h} ∘ S_{c_1 h}
where S is the 2nd order Störmer-Verlet step.
- Coefficients:
c_1 = 1/(2 - 2^(1/3)) c_2 = -2^(1/3)/(2 - 2^(1/3))
Properties: - 4th order accurate - Symplectic - 3 stages (force evaluations per step) - Time-reversible
- Reference:
Yoshida, “Construction of higher order symplectic integrators” Physics Letters A, 150 (1990)
- property order: int
Order of accuracy of the integrator.
- property name: str
Human-readable name of the integrator.
- step(t, q, p, h, grad_T, grad_V)[source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- class mechanics_dsl.solver.Ruth3[source]
Bases:
SymplecticIntegratorRuth 3rd order symplectic integrator.
- Minimal-stage 3rd order method using composition:
S_h = A_{c_1 h} ∘ B_{d_1 h} ∘ A_{c_2 h} ∘ B_{d_2 h} ∘ A_{c_3 h} ∘ B_{d_3 h}
where A is the momentum kick and B is the position drift.
- Coefficients (Ruth):
c1 = 7/24, c2 = 3/4, c3 = -1/24 d1 = 2/3, d2 = -2/3, d3 = 1
Properties: - 3rd order accurate - Symplectic - 3 stages
- Reference:
Ruth, “A canonical integration technique” (1983)
- property order: int
Order of accuracy of the integrator.
- property name: str
Human-readable name of the integrator.
- step(t, q, p, h, grad_T, grad_V)[source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- class mechanics_dsl.solver.McLachlan4[source]
Bases:
SymplecticIntegratorMcLachlan 4th order symplectic integrator with optimal coefficients.
This method minimizes the error constant while maintaining 4th order. Uses a 5-stage composition with optimized coefficients.
Properties: - 4th order accurate - Symplectic - 5 stages - Smaller error constant than Yoshida-4
- Reference:
McLachlan, “On the numerical integration of ODEs by symmetric composition methods” (1995)
- property order: int
Order of accuracy of the integrator.
- property name: str
Human-readable name of the integrator.
- step(t, q, p, h, grad_T, grad_V)[source]
Perform one integration step.
- Parameters:
t – Current time
q – Position vector
p – Momentum vector
h – Step size
grad_T – Gradient of kinetic energy w.r.t. momentum (∂T/∂p)
grad_V – Gradient of potential energy w.r.t. position (∂V/∂q)
- Returns:
Tuple of (new_q, new_p) after one step
- mechanics_dsl.solver.get_symplectic_integrator(name: str) SymplecticIntegrator[source]
Get a symplectic integrator by name.
- Parameters:
name – One of ‘verlet’, ‘leapfrog’, ‘yoshida4’, ‘yoshida6’, ‘yoshida8’, ‘ruth3’, ‘mclachlan4’, ‘pefrl’
- Returns:
SymplecticIntegrator instance
- class mechanics_dsl.solver.VariationalIntegrator(config: VariationalConfig | None = None)[source]
Bases:
ABCBase class for variational integrators.
Variational integrators discretize the action integral and derive the discrete Euler-Lagrange equations:
D_2 L_d(q_{k-1}, q_k) + D_1 L_d(q_k, q_{k+1}) = 0
The discrete Lagrangian L_d(q_k, q_{k+1}, h) approximates: ∫_{t_k}^{t_{k+1}} L(q, q̇) dt
- abstract property order: int
Order of accuracy.
- abstract property name: str
Human-readable name.
- abstract discrete_lagrangian(q0: ndarray, q1: ndarray, h: float, lagrangian: Callable[[ndarray, ndarray], float]) float[source]
Compute discrete Lagrangian L_d(q0, q1, h).
- Parameters:
q0 – Configuration at t_k
q1 – Configuration at t_{k+1}
h – Time step
lagrangian – Continuous Lagrangian L(q, q_dot) -> float
- Returns:
Approximation to ∫_{t_k}^{t_{k+1}} L(q, q̇) dt
- discrete_equations(q_prev: ndarray, q_curr: ndarray, q_next: ndarray, h: float, lagrangian: Callable) ndarray[source]
Evaluate discrete Euler-Lagrange equations: D_2 L_d(q_{k-1}, q_k) + D_1 L_d(q_k, q_{k+1}) = 0
- Returns:
Residual of the discrete EL equations
- step(q_prev: ndarray, q_curr: ndarray, h: float, lagrangian: Callable) ndarray[source]
Compute q_{k+1} given q_{k-1} and q_k using Newton iteration.
Solves: D_2 L_d(q_{k-1}, q_k) + D_1 L_d(q_k, q_{k+1}) = 0
- integrate(t_span: Tuple[float, float], q0: ndarray, q_dot0: ndarray, h: float, lagrangian: Callable[[ndarray, ndarray], float], max_steps: int = 100000) Dict[str, ndarray][source]
Integrate using the variational method.
- Parameters:
t_span – (t_start, t_end)
q0 – Initial configuration
q_dot0 – Initial velocity
h – Time step
lagrangian – L(q, q_dot) -> float
max_steps – Maximum steps
- Returns:
Dictionary with ‘t’, ‘q’, ‘q_dot’, ‘success’, ‘message’
- class mechanics_dsl.solver.MidpointVariational(config: VariationalConfig | None = None)[source]
Bases:
VariationalIntegratorMidpoint rule variational integrator.
- Discrete Lagrangian:
L_d(q0, q1, h) = h * L((q0 + q1)/2, (q1 - q0)/h)
This is equivalent to the implicit midpoint rule, which is symplectic and 2nd order accurate.
- property order: int
Order of accuracy.
- property name: str
Human-readable name.
- class mechanics_dsl.solver.TrapezoidalVariational(config: VariationalConfig | None = None)[source]
Bases:
VariationalIntegratorTrapezoidal rule variational integrator.
- Discrete Lagrangian:
L_d(q0, q1, h) = (h/2) * [L(q0, (q1-q0)/h) + L(q1, (q1-q0)/h)]
This is 2nd order accurate and symmetric.
- property order: int
Order of accuracy.
- property name: str
Human-readable name.
- class mechanics_dsl.solver.GalerkinVariational(num_points: int = 2, config: VariationalConfig | None = None)[source]
Bases:
VariationalIntegratorGalerkin variational integrator using polynomial approximation.
Uses Gauss-Legendre quadrature for higher-order accuracy. This method achieves 2s order accuracy with s Gauss points.
Default: 2 Gauss points → 4th order accuracy
- property order: int
Order of accuracy.
- property name: str
Human-readable name.
- mechanics_dsl.solver.get_variational_integrator(name: str) VariationalIntegrator[source]
Get a variational integrator by name.
mechanics_dsl.symbolic module
Symbolic computation engine for MechanicsDSL
- class mechanics_dsl.symbolic.SymbolicEngine(use_weak_refs: bool = False)[source]
Bases:
objectEnhanced symbolic mathematics engine with advanced caching and performance monitoring
- get_symbol(name: str, **assumptions) Symbol[source]
Get or create a SymPy symbol with assumptions (cached)
- clear_cache() int[source]
Clear all caches to free memory.
Useful for long-running applications that process many different mechanical systems. Clears: - LRU expression cache - Symbol map (keeps time_symbol) - Function map
- Returns:
Number of cached items cleared
Example
>>> engine = SymbolicEngine() >>> # ... do lots of computation ... >>> cleared = engine.clear_cache() >>> print(f"Freed {cleared} cached items")
- memory_stats() Dict[str, int][source]
Get memory usage statistics.
- Returns:
Dictionary with counts of cached items by category
- ast_to_sympy(expr: Expression) Expr[source]
Convert AST expression to SymPy with comprehensive support and caching
- Parameters:
expr – AST expression node
- Returns:
SymPy expression
- derive_equations_of_motion(lagrangian: Expr, coordinates: List[str]) List[Expr][source]
Derive Euler-Lagrange equations from Lagrangian
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
- Returns:
List of equations of motion
Note
The Euler-Lagrange equations are: d/dt(∂L/∂q̇ᵢ) - ∂L/∂qᵢ = 0
For coupled systems (e.g., double pendulum), ALL coordinates must be treated as functions of time simultaneously to correctly compute cross-coupling terms like ∂²θ₂/∂t² appearing in the θ₁ equation.
- derive_equations_with_constraints(lagrangian: Expr, coordinates: List[str], constraints: List[Expr]) Tuple[List[Expr], List[str]][source]
Derive equations with holonomic constraints using Lagrange multipliers
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
constraints – List of constraint expressions
- Returns:
Tuple of (augmented equations, extended coordinates including lambdas)
- derive_hamiltonian_equations(hamiltonian: Expr, coordinates: List[str]) Tuple[List[Expr], List[Expr]][source]
Derive Hamilton’s equations from Hamiltonian
Hamilton’s equations: dq/dt = ∂H/∂p dp/dt = -∂H/∂q
- Parameters:
hamiltonian – Hamiltonian expression
coordinates – List of generalized coordinates
- Returns:
Tuple of (q_dot equations, p_dot equations)
- lagrangian_to_hamiltonian(lagrangian: Expr, coordinates: List[str]) Expr[source]
Convert Lagrangian to Hamiltonian via Legendre transform
H = Σ(p_i * q̇_i) - L where p_i = ∂L/∂q̇_i
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
- Returns:
Hamiltonian expression
- solve_for_accelerations(equations: List[Expr], coordinates: List[str]) Dict[str, Expr][source]
Solve equations of motion for accelerations SIMULTANEOUSLY.
For coupled systems like double pendulum, accelerations are interdependent: M * [q1_ddot, q2_ddot, …]^T = F
This function: 1. Substitutes all derivative notations with symbols 2. Extracts the mass matrix M and force vector F 3. Solves the linear system M*a = F simultaneously 4. Returns simplified acceleration expressions
This is CRITICAL for coupled systems where accelerations appear in each other’s equations.
mechanics_dsl.parser module
MechanicsDSL Parser Package
This package provides the parsing infrastructure for converting MechanicsDSL source code into an Abstract Syntax Tree (AST) for compilation.
- Modules:
tokens: Token definitions and tokenization. ast_nodes: AST node dataclass definitions. core: MechanicsParser class implementation.
- Quick Start:
>>> from mechanics_dsl.parser import tokenize, MechanicsParser >>> tokens = tokenize(r"\system{pendulum} \lagrangian{T - V}") >>> parser = MechanicsParser(tokens) >>> ast = parser.parse()
The parser uses a recursive descent approach with operator precedence parsing for expressions. It handles: - System definitions and variables - Lagrangian and Hamiltonian mechanics - Constraints (holonomic and non-holonomic) - Forces and damping - Initial conditions - Coordinate transformations - SPH fluid definitions
- class mechanics_dsl.parser.Token(type: str, value: str, position: int = 0, line: int = 1, column: int = 1)[source]
Bases:
objectToken with position tracking for better error messages.
- type
The token type (e.g., ‘IDENT’, ‘NUMBER’, ‘LAGRANGIAN’).
- Type:
str
- value
The raw string value matched from source.
- Type:
str
- position
Character position in source (0-indexed).
- Type:
int
- line
Line number (1-indexed).
- Type:
int
- column
Column number (1-indexed).
- Type:
int
Example
>>> token = Token('IDENT', 'theta', position=10, line=2, column=5) >>> print(token) IDENT:theta@2:5
- type: str
- value: str
- position: int = 0
- line: int = 1
- column: int = 1
- mechanics_dsl.parser.tokenize(source: str) List[Token][source]
Tokenize DSL source code with position tracking.
Converts a string of MechanicsDSL code into a list of tokens, excluding whitespace and comments. Unrecognized characters are reported as a single error rather than silently dropped.
- Parameters:
source – DSL source code string.
- Returns:
List of Token objects (excluding whitespace and comments).
- Raises:
ValueError – If the source contains characters that do not match any token pattern (e.g.
@,$,&).
Example
>>> tokens = tokenize(r"\lagrangian{T - V}") >>> [t.type for t in tokens] ['LAGRANGIAN', 'LBRACE', 'IDENT', 'MINUS', 'IDENT', 'RBRACE']
- class mechanics_dsl.parser.MechanicsParser(tokens: List[Token])[source]
Bases:
objectRecursive descent parser for MechanicsDSL.
Converts a list of tokens into an Abstract Syntax Tree (AST) that can be compiled into equations of motion.
- tokens
List of Token objects to parse.
- pos
Current position in token stream.
- current_system
Name of current system being parsed.
- errors
List of parsing errors encountered.
- max_errors
Maximum errors before giving up (from config).
Example
>>> tokens = tokenize(r"\lagrangian{T - V}") >>> parser = MechanicsParser(tokens) >>> ast = parser.parse() >>> print(ast[0]) Lagrangian(...)
- peek(offset: int = 0) Token | None[source]
Look ahead at token without consuming it.
- Parameters:
offset – Number of tokens to look ahead (default 0).
- Returns:
Token at position pos+offset, or None if past end.
- match(*expected_types: str) Token | None[source]
Match and consume token if type matches.
- Parameters:
*expected_types – One or more acceptable token types.
- Returns:
Matched token if successful, None otherwise.
- expect(expected_type: str) Token[source]
Expect a specific token type, raise error if not found.
- Parameters:
expected_type – Required token type.
- Returns:
The matched token.
- Raises:
ParserError – If token doesn’t match expected type.
- parse() List[ASTNode][source]
Parse the complete DSL with comprehensive error recovery.
- Returns:
List of ASTNode objects representing the parsed program.
Note
The parser attempts error recovery to parse as much as possible even when errors are encountered.
- parse_boundary() BoundaryDef[source]
Parse boundary{name} region{…}.
- parse_parameter() ParameterDef[source]
Parse parameter{name}{value}{unit}.
- parse_lagrangian() LagrangianDef[source]
Parse lagrangian{expression}.
- parse_hamiltonian() HamiltonianDef[source]
Parse hamiltonian{expression}.
- parse_transform() TransformDef[source]
Parse transform{type}{var = expr}.
- parse_constraint() ConstraintDef[source]
Parse constraint{expression}.
- parse_nonholonomic() NonHolonomicConstraintDef[source]
Parse nonholonomic{expression}.
- parse_force() ForceDef[source]
Parse a non-conservative force.
- Two forms are supported:
force{expr} - applied positionally (legacy) force{coord}{expr} - applied to the named generalized coordinate
- parse_damping() DampingDef[source]
Parse damping{expression}.
- parse_rayleigh()[source]
Parse rayleigh{expression}.
The Rayleigh dissipation function F represents velocity-dependent dissipative forces. The generalized dissipative forces are: Q_i = -∂F/∂q̇_i
For linear damping: F = ½ Σ bᵢⱼ q̇ᵢ q̇ⱼ
Example
rayleigh{frac{1}{2} * b * dot{x}^2}
- parse_initial() InitialCondition[source]
Parse initial{var1=val1, var2=val2, …}.
- parse_animate() AnimateDef[source]
Parse animate{target}.
- parse_expression() Expression[source]
Parse expressions with full operator precedence.
- parse_additive() Expression[source]
Addition and subtraction (lowest precedence).
- parse_multiplicative() Expression[source]
Multiplication, division, and vector operations.
- parse_power() Expression[source]
Exponentiation (right associative).
- parse_unary() Expression[source]
Unary operators (+, -).
- parse_postfix() Expression[source]
Function calls, subscripts, etc.
- parse_primary() Expression[source]
Primary expressions: literals, identifiers, parentheses, vectors, commands.
- parse_command(cmd: str) Expression[source]
Parse LaTeX-style commands.
- expression_to_string(expr: Expression) str[source]
Convert expression back to string for unit parsing.
- exception mechanics_dsl.parser.ParserError(message: str, token: Token | None = None)[source]
Bases:
ExceptionCustom exception for parser errors with position tracking.
Provides detailed error messages including line and column information when available from the token.
- message
Error description.
- token
Optional token where the error occurred.
Example
>>> try: ... parser.expect("RBRACE") ... except ParserError as e: ... print(e) Expected RBRACE but got EOF at line 5, column 10
- class mechanics_dsl.parser.ASTNode[source]
Bases:
objectBase class for all AST nodes.
All AST nodes inherit from this class, providing a common interface for tree traversal and manipulation.
- class mechanics_dsl.parser.Expression[source]
Bases:
ASTNodeBase class for all expressions.
Expressions are AST nodes that evaluate to a value, as opposed to statements which perform actions.
- class mechanics_dsl.parser.NumberExpr(value: float)[source]
Bases:
ExpressionNumeric literal expression.
- value
The numeric value (float).
- Type:
float
Example
>>> expr = NumberExpr(3.14159) >>> print(expr) Num(3.14159)
- value: float
- class mechanics_dsl.parser.IdentExpr(name: str)[source]
Bases:
ExpressionIdentifier expression (variable name).
- name
The identifier string.
- Type:
str
Example
>>> expr = IdentExpr('theta') >>> print(expr) Id(theta)
- name: str
- class mechanics_dsl.parser.GreekLetterExpr(letter: str)[source]
Bases:
ExpressionGreek letter expression (e.g., alpha, omega).
- letter
The Greek letter name (without backslash).
- Type:
str
Example
>>> expr = GreekLetterExpr('omega') >>> print(expr) Greek(omega)
- letter: str
- class mechanics_dsl.parser.DerivativeVarExpr(var: str, order: int = 1)[source]
Bases:
ExpressionDerivative notation expression (dot{x} or ddot{x}).
Represents time derivatives using Newton’s dot notation.
- var
The variable name being differentiated.
- Type:
str
- order
Order of derivative (1 for dot, 2 for ddot).
- Type:
int
Example
>>> expr = DerivativeVarExpr('x', order=2) >>> print(expr) DerivativeVar(x, order=2)
- var: str
- order: int = 1
- class mechanics_dsl.parser.BinaryOpExpr(left: Expression, operator: Literal['+', '-', '*', '/', '^'], right: Expression)[source]
Bases:
ExpressionBinary operation expression.
Represents operations with two operands: +, -, *, /, ^.
- left
Left operand expression.
- right
Right operand expression.
Example
>>> expr = BinaryOpExpr(IdentExpr('x'), '+', NumberExpr(1)) >>> print(expr) BinOp(Id(x) + Num(1))
- left: Expression
- operator: Literal['+', '-', '*', '/', '^']
- right: Expression
- class mechanics_dsl.parser.UnaryOpExpr(operator: Literal['+', '-'], operand: Expression)[source]
Bases:
ExpressionUnary operation expression.
Represents unary + and - operators.
- operator
Operator symbol (+ or -).
- Type:
Literal[‘+’, ‘-’]
- operand
The expression being operated on.
Example
>>> expr = UnaryOpExpr('-', NumberExpr(5)) >>> print(expr) UnaryOp(-Num(5))
- operator: Literal['+', '-']
- operand: Expression
- class mechanics_dsl.parser.VectorExpr(components: List[Expression])[source]
Bases:
ExpressionVector literal expression.
Represents a vector with multiple components.
- components
List of component expressions.
- Type:
Example
>>> expr = VectorExpr([IdentExpr('x'), IdentExpr('y'), IdentExpr('z')]) >>> print(expr) Vector([Id(x), Id(y), Id(z)])
- components: List[Expression]
- class mechanics_dsl.parser.VectorOpExpr(operation: str, left: Expression, right: Expression | None = None)[source]
Bases:
ExpressionVector operation expression.
Represents vector operations like dot product, cross product, gradient, divergence, and curl.
- operation
Operation name (e.g., ‘dot’, ‘cross’, ‘grad’).
- Type:
str
- left
First operand expression.
- right
Optional second operand (for binary operations).
- Type:
Example
>>> expr = VectorOpExpr('cross', IdentExpr('A'), IdentExpr('B')) >>> print(expr) VectorOp(cross, Id(A), Id(B))
- operation: str
- left: Expression
- right: Expression | None = None
- class mechanics_dsl.parser.DerivativeExpr(expr: Expression, var: str, order: int = 1, partial: bool = False)[source]
Bases:
ExpressionDerivative expression.
Represents total or partial derivatives of expressions.
- expr
The expression being differentiated.
- var
The variable of differentiation.
- Type:
str
- order
Order of the derivative (default 1).
- Type:
int
- partial
True for partial derivative, False for total.
- Type:
bool
Example
>>> expr = DerivativeExpr(IdentExpr('f'), 'x', order=2, partial=True) >>> print(expr) PartialDeriv(Id(f), x, order=2)
- expr: Expression
- var: str
- order: int = 1
- partial: bool = False
- class mechanics_dsl.parser.IntegralExpr(expr: Expression, var: str, lower: Expression | None = None, upper: Expression | None = None, line_integral: bool = False)[source]
Bases:
ExpressionIntegral expression.
Represents definite and indefinite integrals, including line integrals.
- expr
The integrand expression.
- var
The variable of integration.
- Type:
str
- lower
Optional lower bound expression.
- Type:
- upper
Optional upper bound expression.
- Type:
- line_integral
True for line integrals (oint).
- Type:
bool
Example
>>> expr = IntegralExpr(IdentExpr('f'), 'x', NumberExpr(0), NumberExpr(1)) >>> print(expr) Integral(Id(f), x, Num(0), Num(1))
- expr: Expression
- var: str
- lower: Expression | None = None
- upper: Expression | None = None
- line_integral: bool = False
- class mechanics_dsl.parser.FunctionCallExpr(name: str, args: List[Expression])[source]
Bases:
ExpressionFunction call expression.
Represents calls to built-in or user-defined functions.
- name
Function name.
- Type:
str
- args
List of argument expressions.
- Type:
Example
>>> expr = FunctionCallExpr('sin', [IdentExpr('theta')]) >>> print(expr) Call(sin, [Id(theta)])
- name: str
- args: List[Expression]
- class mechanics_dsl.parser.FractionExpr(numerator: Expression, denominator: Expression)[source]
Bases:
ExpressionFraction expression (frac{num}{denom}).
Represents fractions in LaTeX-style notation.
- numerator
Numerator expression.
- denominator
Denominator expression.
Example
>>> expr = FractionExpr(NumberExpr(1), NumberExpr(2)) >>> print(expr) Frac(Num(1)/Num(2))
- numerator: Expression
- denominator: Expression
- class mechanics_dsl.parser.SystemDef(name: str)[source]
Bases:
ASTNodeSystem definition statement (system{name}).
Declares a new physics system by name.
- name
The system name.
- Type:
str
Example
>>> stmt = SystemDef('double_pendulum') >>> print(stmt) System(double_pendulum)
- name: str
- class mechanics_dsl.parser.VarDef(name: str, vartype: str, unit: str, vector: bool = False)[source]
Bases:
ASTNodeVariable definition statement (defvar{name}{type}{unit}).
Defines a generalized coordinate or other variable.
- name
Variable name.
- Type:
str
- vartype
Variable type (e.g., ‘Angle’, ‘Length’, ‘Vector’).
- Type:
str
- unit
Unit specification (e.g., ‘rad’, ‘m’).
- Type:
str
- vector
True if this is a vector variable.
- Type:
bool
Example
>>> stmt = VarDef('theta', 'Angle', 'rad') >>> print(stmt) VarDef(theta: Angle[rad])
- name: str
- vartype: str
- unit: str
- vector: bool = False
- class mechanics_dsl.parser.ParameterDef(name: str, value: float, unit: str)[source]
Bases:
ASTNodeParameter definition statement (parameter{name}{value}{unit}).
Defines a constant parameter with a value.
- name
Parameter name.
- Type:
str
- value
Numeric value.
- Type:
float
- unit
Unit specification.
- Type:
str
Example
>>> stmt = ParameterDef('g', 9.81, 'm/s^2') >>> print(stmt) Parameter(g = 9.81 [m/s^2])
- name: str
- value: float
- unit: str
- class mechanics_dsl.parser.DefineDef(name: str, args: List[str], body: Expression)[source]
Bases:
ASTNodeFunction definition statement (define{…}).
Defines a custom function or macro.
- name
Function name.
- Type:
str
- args
List of argument names.
- Type:
List[str]
- body
Body expression.
Example
>>> stmt = DefineDef('KE', ['m', 'v'], BinaryOpExpr(...)) >>> print(stmt) Define(KE(m, v) = ...)
- name: str
- args: List[str]
- body: Expression
- class mechanics_dsl.parser.LagrangianDef(expr: Expression)[source]
Bases:
ASTNodeLagrangian definition statement (lagrangian{expr}).
Defines the system Lagrangian L = T - V.
- expr
The Lagrangian expression.
Example
>>> stmt = LagrangianDef(BinaryOpExpr(T, '-', V)) >>> print(stmt) Lagrangian(...)
- expr: Expression
- class mechanics_dsl.parser.HamiltonianDef(expr: Expression)[source]
Bases:
ASTNodeHamiltonian definition statement (hamiltonian{expr}).
Defines the system Hamiltonian H = T + V.
- expr
The Hamiltonian expression.
- expr: Expression
- class mechanics_dsl.parser.TransformDef(coord_type: str, var: str, expr: Expression)[source]
Bases:
ASTNodeCoordinate transform definition (transform{type}{var = expr}).
Defines a coordinate transformation.
- coord_type
Type of coordinates (e.g., ‘polar’, ‘spherical’).
- Type:
str
- var
Variable being defined.
- Type:
str
- expr
Transformation expression.
- coord_type: str
- var: str
- expr: Expression
- class mechanics_dsl.parser.ConstraintDef(expr: Expression, constraint_type: str = 'holonomic')[source]
Bases:
ASTNodeHolonomic constraint definition (constraint{expr}).
Defines a position-dependent constraint.
- expr
The constraint expression (should equal zero).
- constraint_type
Type of constraint (default ‘holonomic’).
- Type:
str
- expr: Expression
- constraint_type: str = 'holonomic'
- class mechanics_dsl.parser.NonHolonomicConstraintDef(expr: Expression)[source]
Bases:
ASTNodeNon-holonomic constraint definition (nonholonomic{expr}).
Defines a velocity-dependent constraint that cannot be integrated.
- expr
The constraint expression.
- expr: Expression
- class mechanics_dsl.parser.ForceDef(expr: Expression, force_type: str = 'general', coordinate: str | None = None)[source]
Bases:
ASTNodeNon-conservative force definition (force{expr}).
Defines a generalized force (non-conservative).
- expr
The force expression.
- force_type
Type of force (‘friction’, ‘damping’, ‘drag’, ‘general’).
- Type:
str
- coordinate
Optional name of the generalized coordinate this force acts on. When None the force is applied positionally (legacy behavior).
- Type:
str | None
- expr: Expression
- force_type: str = 'general'
- coordinate: str | None = None
- class mechanics_dsl.parser.DampingDef(expr: Expression, damping_coefficient: float | None = None)[source]
Bases:
ASTNodeDamping force definition (damping{expr}).
Defines a velocity-dependent damping force.
- expr
The damping expression.
- damping_coefficient
Optional damping coefficient.
- Type:
float | None
- expr: Expression
- damping_coefficient: float | None = None
- class mechanics_dsl.parser.RayleighDef(expr: Expression)[source]
Bases:
ASTNodeRayleigh dissipation function definition (rayleigh{expr}).
Defines the Rayleigh dissipation function F where the generalized dissipative forces are Q_i = -∂F/∂q̇_i.
For velocity-dependent damping: F = ½Σ bᵢⱼ q̇ᵢ q̇ⱼ
- expr
The dissipation function expression.
Example
rayleigh{frac{1}{2} * b * dot{x}^2}
- expr: Expression
- class mechanics_dsl.parser.InitialCondition(conditions: Dict[str, float])[source]
Bases:
ASTNodeInitial conditions statement (initial{var1=val1, …}).
Specifies initial values for simulation.
- conditions
Dictionary mapping variable names to initial values.
- Type:
Dict[str, float]
- conditions: Dict[str, float]
- class mechanics_dsl.parser.SolveDef(method: str, options: ~typing.Dict[str, ~typing.Any] = <factory>)[source]
Bases:
ASTNodeSolve statement (solve{method}).
Specifies the solution method.
- method
Solution method name.
- Type:
str
- options
Additional solver options.
- Type:
Dict[str, Any]
- method: str
- options: Dict[str, Any]
- class mechanics_dsl.parser.AnimateDef(target: str, options: ~typing.Dict[str, ~typing.Any] = <factory>)[source]
Bases:
ASTNodeAnimate statement (animate{target}).
Specifies animation configuration.
- target
Animation target.
- Type:
str
- options
Animation options.
- Type:
Dict[str, Any]
- target: str
- options: Dict[str, Any]
- class mechanics_dsl.parser.ExportDef(filename: str, format: str = 'json')[source]
Bases:
ASTNodeExport statement (export{filename}).
Exports the system to a file.
- filename
Output filename.
- Type:
str
- format
Export format (default ‘json’).
- Type:
str
- filename: str
- format: str = 'json'
- class mechanics_dsl.parser.ImportDef(filename: str)[source]
Bases:
ASTNodeImport statement (import{filename}).
Imports a system from a file.
- filename
Input filename.
- Type:
str
- filename: str
- class mechanics_dsl.parser.RegionDef(shape: str, constraints: Dict[str, Tuple[float, float]])[source]
Bases:
ASTNodeRegion definition for SPH fluids.
Defines a geometric region with constraints.
- shape
Region shape (‘rectangle’, ‘circle’, ‘line’).
- Type:
str
- constraints
Coordinate constraints as (min, max) tuples.
- Type:
Dict[str, Tuple[float, float]]
- shape: str
- constraints: Dict[str, Tuple[float, float]]
- class mechanics_dsl.parser.FluidDef(name: str, region: RegionDef, mass: float, eos: str)[source]
Bases:
ASTNodeFluid definition for SPH simulation.
Defines a fluid region with properties.
- name
Fluid name.
- Type:
str
- region
Region definition.
- mass
Particle mass.
- Type:
float
- eos
Equation of state (e.g., ‘tait’).
- Type:
str
- name: str
- mass: float
- eos: str
mechanics_dsl.visualization module
MechanicsDSL Visualization Package
Modular visualization tools for animations, plots, and phase space analysis.
The MechanicsVisualizer class is the legacy all-in-one visualizer
preserved for backward compatibility. New code should prefer the focused
Animator, Plotter, and PhaseSpaceVisualizer
classes.
- class mechanics_dsl.visualization.Animator(trail_length: int | None = None, fps: int | None = None)[source]
Bases:
objectAnimation handler for mechanical system simulations.
Supports: - Pendulum animations (single, double, multi-body) - Particle trajectory animations - Fluid particle visualizations
- setup_figure(xlim: Tuple[float, float] = (-2, 2), ylim: Tuple[float, float] = (-2, 2), title: str = 'Animation') Tuple[Figure, Axes][source]
Create and configure figure for animation.
- animate_pendulum(solution: dict, length: float = 1.0, title: str = 'Pendulum') FuncAnimation[source]
Create pendulum animation from simulation solution.
- Parameters:
solution – Simulation result with ‘t’ and ‘y’ arrays
length – Pendulum length for visualization
title – Animation title
- Returns:
matplotlib FuncAnimation object
- animate(solution: dict, parameters: dict | None = None, system_name: str = 'system')[source]
Generic animation dispatcher (backward compatibility with MechanicsVisualizer).
- Parameters:
solution – Simulation result dictionary
parameters – Physical parameters (optional)
system_name – Name of the system
- Returns:
matplotlib FuncAnimation object
- class mechanics_dsl.visualization.MechanicsVisualizer(trail_length: int | None = None, fps: int | None = None)[source]
Bases:
objectEnhanced visualization with circular buffers and configurable options
- save_animation_to_file(anim: FuncAnimation, filename: str, fps: int | None = None, dpi: int = 100) bool[source]
Save animation to file with validation.
- Parameters:
anim – Animation object to save
filename – Output filename (validated)
fps – Frames per second (optional)
dpi – Dots per inch (default: 100)
- Returns:
True if successful, False otherwise
- Raises:
TypeError – If inputs have wrong types
ValueError – If filename is invalid or parameters out of range
- animate_pendulum(solution: dict, parameters: dict, system_name: str = 'pendulum')[source]
Create animated pendulum visualization with validation.
- Parameters:
solution – Solution dictionary (validated)
parameters – System parameters dictionary
system_name – Name of the system
- Returns:
Animation object or None if failed
- Raises:
TypeError – If inputs have wrong types
ValueError – If solution is invalid
- animate_fluid_from_csv(csv_filename: str, title: str = 'Fluid Simulation')[source]
Animate SPH particle data from CSV. Expected CSV Format: t, id, x, y, rho
- animate_oscillator(solution: dict, parameters: dict, system_name: str = 'oscillator')[source]
Animate harmonic oscillator
- animate(solution: dict, parameters: dict, system_name: str = 'system')[source]
Generic animation dispatcher
- plot_energy(solution: dict, parameters: dict, system_name: str = '', lagrangian: Expr | None = None)[source]
Plot energy conservation analysis with proper offset correction
- plot_phase_space(solution: dict, coordinate_index: int = 0)[source]
Plot phase space trajectory with validation.
- Parameters:
solution – Solution dictionary (validated)
coordinate_index – Index of coordinate to plot (default: 0)
- Raises:
TypeError – If inputs have wrong types
ValueError – If solution is invalid or coordinate_index out of range
- class mechanics_dsl.visualization.PhaseSpaceVisualizer[source]
Bases:
objectPhase space and Poincaré section visualization.
Provides tools for analyzing dynamical systems through phase portraits and stroboscopic maps.
- plot_phase_portrait(solution: dict, coordinate_index: int = 0, title: str = 'Phase Portrait') Figure[source]
Plot phase space trajectory (q vs q_dot).
- Parameters:
solution – Simulation result
coordinate_index – Which coordinate to plot
title – Plot title
- Returns:
matplotlib Figure
- plot_phase_portrait_3d(solution: dict, coords: Tuple[int, int, int] = (0, 0, 1), title: str = '3D Phase Space') Figure[source]
Plot 3D phase space trajectory.
- Parameters:
solution – Simulation result
coords – Tuple of (coord1_idx, coord1_type, coord2_idx) where type 0=position, 1=velocity
title – Plot title
- Returns:
matplotlib Figure
- plot_poincare_section(solution: dict, section_var: int = 0, section_value: float = 0.0, plot_vars: Tuple[int, int] = (1, 2), title: str = 'Poincaré Section') Figure[source]
Plot Poincaré section (stroboscopic map).
- Parameters:
solution – Simulation result
section_var – State variable index for section condition
section_value – Value where section is taken
plot_vars – Which variables to plot (indices)
title – Plot title
- Returns:
matplotlib Figure
- class mechanics_dsl.visualization.Plotter[source]
Bases:
objectPlotting utilities for simulation analysis.
Provides methods for: - Time series plots - Trajectory plots - Energy plots - Multi-panel figures
- plot_time_series(solution: dict, variables: List[str] | None = None, title: str = 'Time Series') Figure[source]
Plot state variables vs time.
- Parameters:
solution – Simulation result
variables – List of variables to plot (default: all coordinates)
title – Plot title
- Returns:
matplotlib Figure
- plot_trajectory_2d(solution: dict, x_var: str = 'x', y_var: str = 'y', title: str = 'Trajectory') Figure[source]
Plot 2D trajectory from solution.
- Parameters:
solution – Simulation result
x_var – Variable names for x and y axes
y_var – Variable names for x and y axes
title – Plot title
- Returns:
matplotlib Figure
- plot_energy(solution: dict, kinetic: ndarray, potential: ndarray, title: str = 'Energy Conservation') Figure[source]
Plot energy components over time.
- Parameters:
solution – Simulation result
kinetic – Kinetic energy array
potential – Potential energy array
title – Plot title
- Returns:
matplotlib Figure
mechanics_dsl.utils module
MechanicsDSL Utils Package
Modular utilities for configuration, logging, caching, profiling, and validation.
- mechanics_dsl.utils.setup_logging(level: int = 20, log_file: str | None = None) Logger[source]
Setup logging configuration
- Parameters:
level – Logging level
log_file – Optional file to write logs to
- Returns:
Logger instance
- class mechanics_dsl.utils.Config[source]
Bases:
objectGlobal configuration for MechanicsDSL with validation.
All configuration values are validated on assignment to ensure they are within reasonable bounds and of correct types.
- property enable_profiling: bool
Whether to enable performance profiling.
- property enable_debug_logging: bool
Whether to enable debug-level logging.
- property simplification_timeout: float
Timeout for symbolic simplification operations in seconds.
- property max_parser_errors: int
Maximum parser errors before giving up.
- property default_rtol: float
Default relative tolerance for numerical integration.
- property default_atol: float
Default absolute tolerance for numerical integration.
- property trail_length: int
Maximum length of animation trails.
- property animation_fps: int
Animation frames per second.
- property save_intermediate_results: bool
Whether to save intermediate computation results.
- property cache_symbolic_results: bool
Whether to cache symbolic computation results.
- property enable_performance_monitoring: bool
Whether to enable performance monitoring.
- property enable_memory_monitoring: bool
Whether to enable additional memory monitoring.
- property cache_max_size: int
Maximum cache size.
- property cache_max_memory_mb: float
Maximum cache memory in MB.
- property enable_adaptive_solver: bool
Whether to enable adaptive solver selection.
- property error_recovery_enabled: bool
Whether error recovery is enabled.
- to_dict() Dict[str, Any][source]
Convert configuration to dictionary.
- Returns:
Dictionary containing all configuration values
- from_dict(data: Dict[str, Any]) None[source]
Load configuration from dictionary with validation.
Uses property setters to ensure all values are validated.
- Parameters:
data – Dictionary containing configuration values
- Raises:
TypeError – If data is not a dictionary
ValueError – If any value is invalid
- class mechanics_dsl.utils.LRUCache(maxsize: int = 128, max_memory_mb: float = 100.0)[source]
Bases:
objectAdvanced LRU cache with size limits and memory awareness
- class mechanics_dsl.utils.PerformanceMonitor[source]
Bases:
objectAdvanced performance monitoring with memory and timing tracking
- mechanics_dsl.utils.profile_function(func: Callable) Callable[source]
Decorator to profile function execution
- mechanics_dsl.utils.timeout(seconds: float)[source]
Cross-platform timeout context manager for timing out operations.
Uses signal.SIGALRM on Unix systems and threading.Timer on Windows. Note: Threading-based timeout on Windows cannot interrupt CPU-bound operations.
- Parameters:
seconds – Maximum time allowed (must be positive)
- Raises:
TimeoutError – If operation exceeds time limit
ValueError – If seconds is not positive
- exception mechanics_dsl.utils.TimeoutError[source]
Bases:
ExceptionRaised when an operation times out
- mechanics_dsl.utils.safe_float_conversion(value: Any) float[source]
Safely convert any value to Python float with comprehensive error handling.
- Parameters:
value – Value to convert to float
- Returns:
Converted float value (0.0 on failure)
- mechanics_dsl.utils.validate_array_safe(arr: Any, name: str = 'array', min_size: int = 0, max_size: int | None = None, check_finite: bool = True) bool[source]
Comprehensive array validation with extensive checks.
- Parameters:
arr – Array to validate
name – Name for error messages
min_size – Minimum array size
max_size – Maximum array size (None for no limit)
check_finite – Whether to check for finite values
- Returns:
True if valid, False otherwise
- mechanics_dsl.utils.safe_array_access(arr: ndarray, index: int, default: float = 0.0) float[source]
Safely access array element with bounds checking.
- Parameters:
arr – Array to access
index – Index to access
default – Default value if access fails
- Returns:
Array element or default value
- mechanics_dsl.utils.runtime_type_check(value: Any, expected_type: type, name: str = 'value') bool[source]
Runtime type checking with detailed error messages and validation
- mechanics_dsl.utils.validate_finite(arr: ndarray, name: str = 'array') bool[source]
Validate that array contains only finite values.
- Parameters:
arr – NumPy array to validate
name – Name for error messages
- Returns:
True if all finite, False otherwise
- Raises:
TypeError – If arr is not a numpy array
- mechanics_dsl.utils.validate_positive(value: int | float, name: str = 'value') None[source]
Validate that a value is positive.
- Parameters:
value – Value to validate
name – Name for error messages
- Raises:
TypeError – If value is not numeric
ValueError – If value is not positive
- mechanics_dsl.utils.validate_non_negative(value: int | float, name: str = 'value') None[source]
Validate that a value is non-negative.
- Parameters:
value – Value to validate
name – Name for error messages
- Raises:
TypeError – If value is not numeric
ValueError – If value is negative
- mechanics_dsl.utils.validate_time_span(t_span: Tuple[float, float]) None[source]
Validate time span tuple.
- Parameters:
t_span – Tuple of (t_start, t_end)
- Raises:
TypeError – If t_span is not a tuple or values are not numeric
ValueError – If t_start >= t_end or values are negative
- mechanics_dsl.utils.validate_solution_dict(solution: dict) None[source]
Validate solution dictionary structure and content.
- Parameters:
solution – Solution dictionary from simulation
- Raises:
TypeError – If solution is not a dict
ValueError – If required keys are missing or values are invalid
- mechanics_dsl.utils.validate_file_path(filename: str, must_exist: bool = False, allow_symlinks: bool = False) None[source]
Validate file path with comprehensive security checks.
- Parameters:
filename – File path to validate
must_exist – Whether file must exist
allow_symlinks – Whether to allow symlinks (default: False for security)
- Raises:
TypeError – If filename is not a string
ValueError – If filename is empty, contains unsafe characters, or is invalid
FileNotFoundError – If must_exist=True and file doesn’t exist
- Security checks performed:
Null byte injection prevention
Path traversal (..) prevention
Special character detection
Symlink detection (when allow_symlinks=False)
Excessive path length check
- mechanics_dsl.utils.resource_manager(*resources)[source]
Context manager for multiple resources with validation
- class mechanics_dsl.utils.AdvancedErrorHandler[source]
Bases:
objectAdvanced error handling with retry and recovery mechanisms
- class mechanics_dsl.utils.VariableCategory(value)[source]
Bases:
EnumCategories of variables in the physics system.
- COORDINATE = 1
- VELOCITY = 2
- CONSTANT = 3
- PARAMETER = 4
- EXTERNAL_FIELD = 5
- mechanics_dsl.utils.is_coordinate_type(var_type: str) bool[source]
Check if a variable type represents a dynamic coordinate.
- Parameters:
var_type – The type string from VarDef
- Returns:
True if this type represents a coordinate, False otherwise
- mechanics_dsl.utils.is_constant_type(var_type: str) bool[source]
Check if a variable type represents a constant/parameter.
- Parameters:
var_type – The type string from VarDef
- Returns:
True if this type represents a constant, False otherwise
- mechanics_dsl.utils.is_likely_coordinate(var_name: str, var_type: str) bool[source]
Determine if a variable is likely a dynamic coordinate.
Uses both type information and naming conventions to determine if a variable represents a generalized coordinate.
Priority: 1. Explicit COORDINATE types (Angle, Position, Coordinate) -> IS coordinate 2. Explicit CONSTANT types (Parameter, Constant, Mass) -> NOT coordinate 3. Name-based fallback for ambiguous types (like ‘Length’) -> use common names
- Parameters:
var_name – The variable name
var_type – The variable type string
- Returns:
True if this is likely a coordinate, False otherwise
- mechanics_dsl.utils.classify_variable(var_name: str, var_type: str) VariableCategory[source]
Classify a variable into its category.
- Parameters:
var_name – The variable name
var_type – The variable type string
- Returns:
VariableCategory enum value
- class mechanics_dsl.utils.RateLimiter(requests_per_minute: float = 60.0, burst_limit: float = 10.0, cleanup_interval: float = 300.0)[source]
Bases:
objectThread-safe rate limiter using token bucket algorithm.
Supports per-client rate limiting with configurable limits.
- Parameters:
requests_per_minute – Maximum sustained requests per minute
burst_limit – Maximum burst size (peak requests)
cleanup_interval – Seconds between cleanup of stale buckets
Example
>>> limiter = RateLimiter(requests_per_minute=60, burst_limit=10) >>> if limiter.allow("user_123"): ... # Process request ... pass >>> else: ... # Return 429 Too Many Requests ... pass
- allow(key: str, cost: float = 1.0) bool[source]
Check if a request is allowed under the rate limit.
- Parameters:
key – Identifier for the client (e.g., IP address, user ID)
cost – Cost of this request in tokens (default 1.0)
- Returns:
True if request is allowed, False if rate limited
- allow_or_raise(key: str, cost: float = 1.0) None[source]
Check if request is allowed, raise RateLimitExceeded if not.
- Parameters:
key – Identifier for the client
cost – Cost of this request in tokens
- Raises:
RateLimitExceeded – If rate limit is exceeded
- class mechanics_dsl.utils.SimulationRateLimiter(simulations_per_minute: float = 30.0, burst_limit: float = 5.0, max_points_free: int = 1000, points_per_token: int = 1000)[source]
Bases:
RateLimiterSpecialized rate limiter for physics simulations.
Applies higher costs for expensive operations like long simulations or high-resolution outputs.
- Parameters:
simulations_per_minute – Base simulation rate
max_points_free – Maximum points without extra cost
points_per_token – Points that cost 1 token each
- calculate_cost(num_points: int = 1000, time_span: float = 10.0, method: str = 'RK45') float[source]
Calculate token cost for a simulation.
- Parameters:
num_points – Number of output points
time_span – Simulation time span
method – Integration method
- Returns:
Cost in tokens
- allow_simulation(key: str, num_points: int = 1000, time_span: float = 10.0, method: str = 'RK45') bool[source]
Check if a simulation is allowed.
- Parameters:
key – Client identifier
num_points – Number of output points
time_span – Simulation time span
method – Integration method
- Returns:
True if simulation is allowed
- exception mechanics_dsl.utils.RateLimitExceeded(key: str, retry_after: float)[source]
Bases:
ExceptionRaised when rate limit is exceeded.
- class mechanics_dsl.utils.TokenBucket(capacity: float, refill_rate: float, tokens: float = 0.0, last_refill: float = <factory>)[source]
Bases:
objectToken bucket algorithm implementation for rate limiting.
- capacity: float
- refill_rate: float
- tokens: float = 0.0
- last_refill: float
- exception mechanics_dsl.utils.PathValidationError[source]
Bases:
ValueErrorRaised when a path fails validation.
- mechanics_dsl.utils.is_safe_filename(filename: str) bool[source]
Check if a filename is safe (no path components).
- Parameters:
filename – The filename to validate
- Returns:
True if the filename is safe
- mechanics_dsl.utils.secure_filename(filename: str) str[source]
Sanitize a filename by removing unsafe characters.
Similar to werkzeug.utils.secure_filename.
- Parameters:
filename – The original filename
- Returns:
A safe version of the filename
- mechanics_dsl.utils.validate_path_within_base(user_path: str, base_path: str, must_exist: bool = False) str[source]
Validate that a user-provided path stays within a base directory.
This is the recommended approach for path traversal prevention.
- Parameters:
user_path – The user-provided path (potentially malicious)
base_path – The base directory paths must stay within
must_exist – If True, verify the path exists
- Returns:
The validated absolute path
- Raises:
PathValidationError – If the path escapes the base directory
- mechanics_dsl.utils.safe_open(file_path: str, mode: str = 'r', base_path: str | None = None, allowed_extensions: List[str] | None = None, **kwargs)[source]
Safely open a file with path validation.
- Parameters:
file_path – Path to the file
mode – File open mode
base_path – If provided, validate path is within this directory
allowed_extensions – If provided, restrict to these extensions
**kwargs – Additional arguments for open()
- Returns:
File handle
- Raises:
PathValidationError – If path validation fails
- mechanics_dsl.utils.safe_path_join(base: str, *parts: str) str[source]
Safely join path parts, preventing traversal.
- Parameters:
base – The base directory
*parts – Additional path components
- Returns:
The validated joined path
- Raises:
PathValidationError – If result escapes base
Module contents
MechanicsDSL: A Domain-Specific Language for Classical Mechanics
A comprehensive framework for symbolic and numerical analysis of classical mechanical systems using LaTeX-inspired notation.
- class mechanics_dsl.PhysicsCompiler[source]
Bases:
objectMain compiler class.
Production-ready physics DSL compiler with comprehensive validation, cross-platform support, and security hardening.
Features: - Cross-platform timeout support (Windows/Unix) - Safe AST-based parsing (no eval()) - Comprehensive input validation - Specific exception handling - Extensive type hints - Production-ready error recovery
Example
>>> compiler = PhysicsCompiler() >>> result = compiler.compile_dsl("\system{pendulum}\lagrangian{x^2}") >>> if result['success']: ... solution = compiler.simulate((0, 10)) ... compiler.animate(solution)
- compile_dsl(dsl_source: str, use_hamiltonian: bool = False, use_constraints: bool = True) dict[source]
Complete compilation pipeline with comprehensive validation.
- Parameters:
dsl_source – DSL source code (must be non-empty string)
use_hamiltonian – Force Hamiltonian formulation
use_constraints – Apply constraint handling
- Returns:
Compilation result dictionary with ‘success’ key
- Raises:
TypeError – If dsl_source is not a string
ValueError – If dsl_source is empty or invalid
Example
>>> compiler = PhysicsCompiler() >>> result = compiler.compile_dsl(r"\system{test}\lagrangian{x^2}") >>> assert result['success']
- get_coordinates() List[str][source]
Extract generalized coordinates (exclude constants).
Uses the registry module’s is_likely_coordinate() function to determine which variables are dynamic coordinates vs. constants/parameters.
- Returns:
List of coordinate variable names
- derive_equations() Dict[str, Expr][source]
Derive equations using Lagrangian formulation (Patched for Forces)
- derive_constrained_equations() Dict[str, Expr][source]
Derive equations with constraints using Lagrange multipliers
- derive_hamiltonian_equations() Tuple[List[Expr], List[Expr]][source]
Derive equations using Hamiltonian formulation
- simulate(t_span: Tuple[float, float] = (0, 10), num_points: int = 1000, **kwargs) dict[source]
Run numerical simulation
- export_animation(solution: dict, filename: str, fps: int = 30, dpi: int = 100) str[source]
Export animation to file
- export(target: str, filename: str) str[source]
Generate standalone simulation code for a target language.
- Parameters:
target – Target language identifier (see _GENERATOR_REGISTRY for the list, e.g. ‘cpp’, ‘python’, ‘rust’, ‘julia’, ‘cuda’, …).
filename – Output file path for the generated source.
- Returns:
Path to the generated file.
- Raises:
ValueError – If target is not supported or the compiler has no equations yet.
IOError – If the file cannot be written.
- static import_system(filename: str, allow_pickle: bool = False) PhysicsCompiler | None[source]
Import system state from file.
See
SystemSerializer.import_systemfor the semantics ofallow_pickle; pickle loading is refused by default.
- compile_to_cpp(filename: str = 'simulation.cpp', target: str = 'standard', compile_binary: bool = True) bool[source]
Generate C++ code for multiple targets.
- Parameters:
filename – Output filename
target – ‘standard’, ‘raylib’, ‘arduino’, ‘wasm’, ‘openmp’, ‘python’
compile_binary – Whether to run the compiler (g++, emcc, etc.)
- class mechanics_dsl.MechanicsParser(tokens: List[Token])[source]
Bases:
objectRecursive descent parser for MechanicsDSL.
Converts a list of tokens into an Abstract Syntax Tree (AST) that can be compiled into equations of motion.
- tokens
List of Token objects to parse.
- pos
Current position in token stream.
- current_system
Name of current system being parsed.
- errors
List of parsing errors encountered.
- max_errors
Maximum errors before giving up (from config).
Example
>>> tokens = tokenize(r"\lagrangian{T - V}") >>> parser = MechanicsParser(tokens) >>> ast = parser.parse() >>> print(ast[0]) Lagrangian(...)
- peek(offset: int = 0) Token | None[source]
Look ahead at token without consuming it.
- Parameters:
offset – Number of tokens to look ahead (default 0).
- Returns:
Token at position pos+offset, or None if past end.
- match(*expected_types: str) Token | None[source]
Match and consume token if type matches.
- Parameters:
*expected_types – One or more acceptable token types.
- Returns:
Matched token if successful, None otherwise.
- expect(expected_type: str) Token[source]
Expect a specific token type, raise error if not found.
- Parameters:
expected_type – Required token type.
- Returns:
The matched token.
- Raises:
ParserError – If token doesn’t match expected type.
- parse() List[ASTNode][source]
Parse the complete DSL with comprehensive error recovery.
- Returns:
List of ASTNode objects representing the parsed program.
Note
The parser attempts error recovery to parse as much as possible even when errors are encountered.
- parse_boundary() BoundaryDef[source]
Parse boundary{name} region{…}.
- parse_parameter() ParameterDef[source]
Parse parameter{name}{value}{unit}.
- parse_lagrangian() LagrangianDef[source]
Parse lagrangian{expression}.
- parse_hamiltonian() HamiltonianDef[source]
Parse hamiltonian{expression}.
- parse_transform() TransformDef[source]
Parse transform{type}{var = expr}.
- parse_constraint() ConstraintDef[source]
Parse constraint{expression}.
- parse_nonholonomic() NonHolonomicConstraintDef[source]
Parse nonholonomic{expression}.
- parse_force() ForceDef[source]
Parse a non-conservative force.
- Two forms are supported:
force{expr} - applied positionally (legacy) force{coord}{expr} - applied to the named generalized coordinate
- parse_damping() DampingDef[source]
Parse damping{expression}.
- parse_rayleigh()[source]
Parse rayleigh{expression}.
The Rayleigh dissipation function F represents velocity-dependent dissipative forces. The generalized dissipative forces are: Q_i = -∂F/∂q̇_i
For linear damping: F = ½ Σ bᵢⱼ q̇ᵢ q̇ⱼ
Example
rayleigh{frac{1}{2} * b * dot{x}^2}
- parse_initial() InitialCondition[source]
Parse initial{var1=val1, var2=val2, …}.
- parse_animate() AnimateDef[source]
Parse animate{target}.
- parse_expression() Expression[source]
Parse expressions with full operator precedence.
- parse_additive() Expression[source]
Addition and subtraction (lowest precedence).
- parse_multiplicative() Expression[source]
Multiplication, division, and vector operations.
- parse_power() Expression[source]
Exponentiation (right associative).
- parse_unary() Expression[source]
Unary operators (+, -).
- parse_postfix() Expression[source]
Function calls, subscripts, etc.
- parse_primary() Expression[source]
Primary expressions: literals, identifiers, parentheses, vectors, commands.
- parse_command(cmd: str) Expression[source]
Parse LaTeX-style commands.
- expression_to_string(expr: Expression) str[source]
Convert expression back to string for unit parsing.
- class mechanics_dsl.SymbolicEngine(use_weak_refs: bool = False)[source]
Bases:
objectEnhanced symbolic mathematics engine with advanced caching and performance monitoring
- get_symbol(name: str, **assumptions) Symbol[source]
Get or create a SymPy symbol with assumptions (cached)
- clear_cache() int[source]
Clear all caches to free memory.
Useful for long-running applications that process many different mechanical systems. Clears: - LRU expression cache - Symbol map (keeps time_symbol) - Function map
- Returns:
Number of cached items cleared
Example
>>> engine = SymbolicEngine() >>> # ... do lots of computation ... >>> cleared = engine.clear_cache() >>> print(f"Freed {cleared} cached items")
- memory_stats() Dict[str, int][source]
Get memory usage statistics.
- Returns:
Dictionary with counts of cached items by category
- ast_to_sympy(expr: Expression) Expr[source]
Convert AST expression to SymPy with comprehensive support and caching
- Parameters:
expr – AST expression node
- Returns:
SymPy expression
- derive_equations_of_motion(lagrangian: Expr, coordinates: List[str]) List[Expr][source]
Derive Euler-Lagrange equations from Lagrangian
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
- Returns:
List of equations of motion
Note
The Euler-Lagrange equations are: d/dt(∂L/∂q̇ᵢ) - ∂L/∂qᵢ = 0
For coupled systems (e.g., double pendulum), ALL coordinates must be treated as functions of time simultaneously to correctly compute cross-coupling terms like ∂²θ₂/∂t² appearing in the θ₁ equation.
- derive_equations_with_constraints(lagrangian: Expr, coordinates: List[str], constraints: List[Expr]) Tuple[List[Expr], List[str]][source]
Derive equations with holonomic constraints using Lagrange multipliers
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
constraints – List of constraint expressions
- Returns:
Tuple of (augmented equations, extended coordinates including lambdas)
- derive_hamiltonian_equations(hamiltonian: Expr, coordinates: List[str]) Tuple[List[Expr], List[Expr]][source]
Derive Hamilton’s equations from Hamiltonian
Hamilton’s equations: dq/dt = ∂H/∂p dp/dt = -∂H/∂q
- Parameters:
hamiltonian – Hamiltonian expression
coordinates – List of generalized coordinates
- Returns:
Tuple of (q_dot equations, p_dot equations)
- lagrangian_to_hamiltonian(lagrangian: Expr, coordinates: List[str]) Expr[source]
Convert Lagrangian to Hamiltonian via Legendre transform
H = Σ(p_i * q̇_i) - L where p_i = ∂L/∂q̇_i
- Parameters:
lagrangian – Lagrangian expression
coordinates – List of generalized coordinates
- Returns:
Hamiltonian expression
- solve_for_accelerations(equations: List[Expr], coordinates: List[str]) Dict[str, Expr][source]
Solve equations of motion for accelerations SIMULTANEOUSLY.
For coupled systems like double pendulum, accelerations are interdependent: M * [q1_ddot, q2_ddot, …]^T = F
This function: 1. Substitutes all derivative notations with symbols 2. Extracts the mass matrix M and force vector F 3. Solves the linear system M*a = F simultaneously 4. Returns simplified acceleration expressions
This is CRITICAL for coupled systems where accelerations appear in each other’s equations.
- class mechanics_dsl.NumericalSimulator(symbolic_engine: SymbolicEngine)[source]
Bases:
objectEnhanced numerical simulator with better stability and diagnostics
- compile_equations(accelerations: Dict[str, Expr], coordinates: List[str])[source]
Compile symbolic equations to numerical functions
- compile_hamiltonian_equations(q_dots: List[Expr], p_dots: List[Expr], coordinates: List[str])[source]
Compile Hamiltonian equations
- equations_of_motion(t: float, y: ndarray) ndarray[source]
ODE system for numerical integration with comprehensive bounds checking and validation.
- Parameters:
t – Current time
y – State vector
- Returns:
Derivative vector dydt
- simulate(t_span: Tuple[float, float], num_points: int = 1000, method: str = None, rtol: float = None, atol: float = None, detect_stiff: bool = True) dict[source]
Run numerical simulation with adaptive integration and diagnostics.
- Parameters:
t_span – Time span (t_start, t_end) where t_start < t_end
num_points – Number of output points (must be >= 2)
method – Integration method (‘RK45’, ‘LSODA’, ‘Radau’, etc.)
rtol – Relative tolerance (must be in (0, 1))
atol – Absolute tolerance (must be positive)
detect_stiff – Whether to detect stiff systems
- Returns:
Dictionary with solution data and metadata, always contains ‘success’ key
- Raises:
TypeError – If arguments have wrong types
ValueError – If arguments are out of valid ranges
Example
>>> solution = simulator.simulate((0, 10), num_points=1000) >>> if solution['success']: ... t = solution['t'] ... y = solution['y']
- async simulate_async(t_span: Tuple[float, float], num_points: int = 1000, method: str | None = None, rtol: float | None = None, atol: float | None = None, detect_stiff: bool = True, executor: Executor | None = None) Dict[str, Any][source]
Run numerical simulation asynchronously.
This method runs the simulation in a thread pool executor to avoid blocking the event loop. Useful for: - Jupyter notebooks (keeps the kernel responsive) - Async web backends (FastAPI, aiohttp) - GUI applications with async event loops
- Parameters:
t_span – Time span (t_start, t_end)
num_points – Number of output points
method – Integration method (‘RK45’, ‘LSODA’, ‘Radau’, etc.)
rtol – Relative tolerance
atol – Absolute tolerance
detect_stiff – Whether to detect stiff systems
executor – Optional custom executor (defaults to ThreadPoolExecutor)
- Returns:
Dictionary with solution data and metadata
Example
>>> import asyncio >>> async def main(): ... result = await simulator.simulate_async((0, 10), num_points=1000) ... print(f"Success: {result['success']}") >>> asyncio.run(main())
Note
For CPU-bound simulations, consider using ProcessPoolExecutor for true parallelism (requires picklable equations).
- async simulate_batch_async(simulations: List[Dict[str, Any]], max_concurrent: int = 4) List[Dict[str, Any]][source]
Run multiple simulations concurrently.
Useful for parameter sweeps, sensitivity analysis, or ensemble simulations where many similar systems need to be simulated.
- Parameters:
simulations – List of simulation parameter dicts, each containing: - t_span: Tuple[float, float] (required) - num_points: int (optional, default 1000) - method: str (optional) - rtol: float (optional) - atol: float (optional)
max_concurrent – Maximum concurrent simulations
- Returns:
List of simulation results in the same order as input
Example
>>> simulations = [ ... {'t_span': (0, 10), 'num_points': 500}, ... {'t_span': (0, 20), 'num_points': 1000}, ... ] >>> results = await simulator.simulate_batch_async(simulations)
- class mechanics_dsl.NumbaSimulator(symbolic_engine=None)[source]
Bases:
objectNumba-accelerated numerical simulator for MechanicsDSL.
Provides significant speedups over SciPy’s solve_ivp for simple to moderately complex systems.
Example
>>> from mechanics_dsl.solver_numba import NumbaSimulator >>> sim = NumbaSimulator(symbolic_engine) >>> sim.compile_equations(accelerations, coordinates) >>> solution = sim.simulate_numba(t_span=(0, 10), num_points=1000)
- compile_equations(accelerations: Dict[str, Expr], coordinates: List[str]) None[source]
Compile symbolic equations to Numba-compatible functions.
- Parameters:
accelerations – Dictionary of {coord_ddot: symbolic_expression}
coordinates – List of coordinate names
- simulate_numba(t_span: Tuple[float, float], num_points: int = 1000, method: str = 'rk4', rtol: float = 1e-06, atol: float = 1e-09) Dict[source]
Run simulation using Numba-accelerated integrator.
- Parameters:
t_span – (t_start, t_end) time interval
num_points – Number of output points
method – Integration method (‘euler’, ‘rk4’, ‘rk45’)
rtol – Relative tolerance (for adaptive methods)
atol – Absolute tolerance (for adaptive methods)
- Returns:
Dictionary with ‘t’ and ‘y’ arrays
- mechanics_dsl.tokenize(source: str) List[Token][source]
Tokenize DSL source code with position tracking.
Converts a string of MechanicsDSL code into a list of tokens, excluding whitespace and comments. Unrecognized characters are reported as a single error rather than silently dropped.
- Parameters:
source – DSL source code string.
- Returns:
List of Token objects (excluding whitespace and comments).
- Raises:
ValueError – If the source contains characters that do not match any token pattern (e.g.
@,$,&).
Example
>>> tokens = tokenize(r"\lagrangian{T - V}") >>> [t.type for t in tokens] ['LAGRANGIAN', 'LBRACE', 'IDENT', 'MINUS', 'IDENT', 'RBRACE']
- mechanics_dsl.setup_logging(level: int = 20, log_file: str | None = None) Logger[source]
Setup logging configuration
- Parameters:
level – Logging level
log_file – Optional file to write logs to
- Returns:
Logger instance
- class mechanics_dsl.PotentialEnergyCalculator[source]
Bases:
objectCompute potential energy with proper offset for different systems
- static compute_pe_offset(system_type: str, parameters: Dict[str, float]) float[source]
Compute PE offset to set minimum PE = 0
- Parameters:
system_type – Type of mechanical system
parameters – System parameters
- Returns:
PE offset value
- static compute_kinetic_energy(solution: dict, parameters: Dict[str, float]) ndarray[source]
Compute kinetic energy from solution with validation.
- Parameters:
solution – Solution dictionary (validated)
parameters – System parameters dictionary
- Returns:
Array of kinetic energy values
- Raises:
TypeError – If inputs have wrong types
ValueError – If solution is invalid
- class mechanics_dsl.EnergyAnalyzer[source]
Bases:
objectEnergy analysis for mechanical systems.
Computes kinetic energy, potential energy, and validates conservation.
- compute_kinetic_energy(solution: dict, masses: Dict[str, float], velocities: List[str] | None = None) ndarray[source]
Compute kinetic energy T = 0.5 * m * v^2 for each timestep.
- Parameters:
solution – Simulation result
masses – Dict mapping coordinate names to masses
velocities – List of velocity variable names
- Returns:
Kinetic energy array
- compute_potential_energy(solution: dict, potential_func: Callable) ndarray[source]
Compute potential energy at each timestep.
- Parameters:
solution – Simulation result
potential_func – Function V(state) -> float
- Returns:
Potential energy array
- check_conservation(solution: dict, kinetic: ndarray, potential: ndarray, tolerance: float = 0.001) Dict[source]
Check energy conservation.
- Parameters:
solution – Simulation result
kinetic – Kinetic energy array
potential – Potential energy array
tolerance – Relative tolerance for conservation check
- Returns:
Dict with conservation analysis results
- class mechanics_dsl.StabilityAnalyzer[source]
Bases:
objectStability analysis for dynamical systems.
Provides: - Fixed point finding - Linearization and Jacobian computation - Eigenvalue analysis - Lyapunov exponent estimation
- find_fixed_points(equations: Dict[str, Expr], variables: List[Symbol]) List[Dict][source]
Find fixed points where all derivatives are zero.
- Parameters:
equations – Dict mapping derivative names to expressions
variables – List of state variable symbols
- Returns:
List of fixed point dictionaries
- compute_jacobian(equations: Dict[str, Expr], variables: List[Symbol]) MutableDenseMatrix[source]
Compute the Jacobian matrix of the system.
- Parameters:
equations – Dict mapping output names to expressions
variables – List of input variable symbols
- Returns:
SymPy Matrix (Jacobian)
- analyze_stability(jacobian: MutableDenseMatrix, fixed_point: Dict) Dict[source]
Analyze stability at a fixed point via eigenvalues.
- Parameters:
jacobian – Jacobian matrix
fixed_point – Dict of variable values at fixed point
- Returns:
Stability analysis result
- estimate_lyapunov_exponent(trajectory: ndarray, dt: float, n_renorm: int = 100) float[source]
Estimate largest Lyapunov exponent from trajectory data.
Uses Wolf’s algorithm with periodic renormalization.
- Parameters:
trajectory – State trajectory array (n_vars x n_points)
dt – Time step
n_renorm – Number of renormalization steps
- Returns:
Estimated Lyapunov exponent
- mechanics_dsl.get_preset(name)[source]
Get a built-in preset by name. See list_presets() for available options.
- exception mechanics_dsl.MechanicsDSLError(message: str, suggestion: str | None = None, docs_url: str | None = None)[source]
Bases:
ExceptionBase exception for all MechanicsDSL errors.
- exception mechanics_dsl.ParseError(message: str, line: int | None = None, column: int | None = None, source_snippet: str | None = None)[source]
Bases:
MechanicsDSLErrorRaised when the DSL source code cannot be parsed.
- exception mechanics_dsl.TokenizationError(message: str, position: int | None = None)[source]
Bases:
MechanicsDSLErrorRaised when source code cannot be tokenized.
- exception mechanics_dsl.SemanticError(message: str, suggestion: str | None = None, docs_url: str | None = None)[source]
Bases:
MechanicsDSLErrorRaised when DSL has semantic errors (valid syntax but invalid meaning).
- exception mechanics_dsl.NoLagrangianError(system_name: str = 'system')[source]
Bases:
SemanticErrorRaised when Lagrangian is required but not defined.
- exception mechanics_dsl.NoCoordinatesError[source]
Bases:
SemanticErrorRaised when no generalized coordinates are found.
- exception mechanics_dsl.SimulationError(message: str, suggestion: str | None = None, docs_url: str | None = None)[source]
Bases:
MechanicsDSLErrorBase class for simulation-related errors.
- exception mechanics_dsl.IntegrationError(message: str, t_failed: float | None = None, is_stiff: bool = False)[source]
Bases:
SimulationErrorRaised when numerical integration fails.
- exception mechanics_dsl.InitialConditionError(message: str, missing_vars: List[str] | None = None)[source]
Bases:
SimulationErrorRaised when initial conditions are invalid or inconsistent.
- exception mechanics_dsl.ParameterError(message: str, param_name: str | None = None)[source]
Bases:
MechanicsDSLErrorRaised when there are issues with physical parameters.