Marketplace › From Ordinate 2D
Elastic collisions for every mass ratio
A moving ball hits balls of 0.25 to 8 times its mass; the speeds after against the formulas.
Use in Ordinate 2DOpens in the Script tab: it runs when you press Run. Free, no account needed.
"""Head-on elastic collisions for every mass ratio: v₁′ = (m₁ − m₂)/(m₁ + m₂)·v₁, v₂′ = 2m₁/(m₁ + m₂)·v₁.
A 1 kg ball at 4 m/s hits a ball at rest whose mass goes through 0.25, 0.5, 1, 2, 4, 8 kg. The script writes the speeds after
each collision with the formula's values; the momentum and the kinetic energy afterwards stay what they were.
Runs in the studio (Script tab → Run) and locally: python3 elastic_collisions.py
"""
import studio as s
M1, V1 = 1.0, 4.0
RATIOS = [0.25, 0.5, 1, 2, 4, 8]
TRIAL = 2.0 # seconds per collision
s.clear()
s.gravity = (0, 0)
a = s.circle(-1.5, 1, 0.2, mass=M1, name="Ball 1", color="#e5484d", restitution=1, friction=0)
b = s.circle(0, 1, 0.2, mass=1, name="Ball 2", color="#4f8ff7", restitution=1, friction=0)
s.box(0, -0.2, 14, 0.2, static=True, name="Floor", collide=False, color="#c5cad1")
state = {"k": -1, "hit": False}
def setup(k):
a.position, a.velocity = (-1.5, 1), (V1, 0)
b.position, b.velocity = (0, 1), (0, 0)
b.mass = M1 * RATIOS[k]
@s.on_collision
def hit(x, y):
state["hit"] = True
@s.on_step
def trial(t, dt):
k = int(t // TRIAL)
if k != state["k"]:
if state["k"] >= 0 and state["hit"]:
r = RATIOS[state["k"]]
m2 = M1 * r
v1, v2 = a.vx, b.vx
s.record(mass_ratio=r, v1_after=v1, v1_theory=(M1 - m2) / (M1 + m2) * V1, v2_after=v2, v2_theory=2 * M1 / (M1 + m2) * V1,
momentum=M1 * v1 + m2 * v2, energy=0.5 * M1 * v1 ** 2 + 0.5 * m2 * v2 ** 2)
print(f"m₂/m₁ = {r:>4}: v₁′ = {v1:+.3f}, v₂′ = {v2:+.3f} m/s")
state["k"], state["hit"] = k, False
if k >= len(RATIOS):
s.stop()
return
setup(k)
s.run(TRIAL * (len(RATIOS) + 1))