Quickstart

Five minutes. By the end you'll have a simulated two-stage gear train, a printed output table, and an exported SVG animation you can open in any browser.

Step 1 — install

pip install molenspin

Step 2 — create an assembly

Create a file called first_gearbox.py:

import molenspin as ms

# An Assembly holds everything — shafts, gears, constraints
asm = ms.Assembly(name="two-stage-gearbox")

Step 3 — add shafts and gears

# Input shaft at 3000 RPM
shaft_in = asm.add_shaft(omega_rpm=3000, name="input")

# Stage 1: 20-tooth pinion meshes with 80-tooth wheel → 4:1
pinion_1 = asm.add_gear(teeth=20, driven_by=shaft_in, name="p1")
wheel_1  = asm.add_gear(teeth=80, meshes_with=pinion_1, name="w1")

# Stage 2: 16-tooth pinion on the same shaft as wheel_1, meshes with 48-tooth wheel → 3:1
pinion_2 = asm.add_gear(teeth=16, driven_by=wheel_1.shaft, name="p2")
wheel_2  = asm.add_gear(teeth=48, meshes_with=pinion_2, name="w2")

# Total reduction = 4 × 3 = 12:1 → output should be 250 RPM

Step 4 — simulate

# Integrate over 1 second, 2 kHz sample rate
result = asm.simulate(duration=1.0, dt=5e-4)

# Print a summary
result.print_summary()
# ┌──────────────────────┬────────────┬──────────────┐
# │ shaft                │  omega RPM │  n_revs      │
# ├──────────────────────┼────────────┼──────────────┤
# │ input                │  3000.0    │  50.00       │
# │ w1 / p2 (shared)     │   750.0    │  12.50       │
# │ w2 (output)          │   250.0    │   4.17       │
# └──────────────────────┴────────────┴──────────────┘

Step 5 — export

# SVG animation at 30 fps, first 0.5 s only
result.export_svg("gearbox.svg", fps=30, duration=0.5)
print("Wrote gearbox.svg")

Open gearbox.svg in Firefox or Chrome to see the gear teeth rotate. The geometry is computed analytically — involute tooth profiles with the module derived from a default pitch diameter of 100 mm per 20 teeth. You can override this with module=2.5 on any gear.

Terminal showing gearbox simulation summary output

Step 6 — read the angular positions

# result.shafts is a dict keyed by shaft name
s_out = result.shafts["w2"]

# Angular position history (radians) at each timestep
theta = s_out.theta_history   # shape (2000,) — 1s / 5e-4 s per step

# Velocity (should be constant for this steady-state run)
import numpy as np
print(f"omega mean: {np.mean(s_out.omega_history):.4f} rad/s")
print(f"omega std:  {np.std(s_out.omega_history):.2e} rad/s")

Next steps