Ordinate 2D Marketplace Community Open the studio

Marketplace › From Ordinate 2D

Elastic collisions for every mass ratio

Script by Ordinate 2D ✓ · Dynamics

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))

table collisions events momentum