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.
pip install molenspin
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")
# 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
# 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 │
# └──────────────────────┴────────────┴──────────────┘
# 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.
# 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")
ms.BeltDrive between shafts for chain/belt transmissions