Ordinate 2D Marketplace Community Open the studio

Marketplace › From Ordinate 2D

A pulse along a chain of springs

Script by Ordinate 2D ✓ · Oscillations and waves

Strike one end of a chain of 30 masses: the pulse travels at a√(k/m).

Use in Ordinate 2DOpens in the Script tab: it runs when you press Run. Free, no account needed.
"""A pulse along a chain of masses and springs: the wave speed is v = a√(k/m).

Thirty masses a = 0.2 m apart are joined by springs (k = 200 N/m, m = 0.1 kg) on a frictionless floor. The first mass is
struck once; a compression pulse runs down the chain. The script times it at the 10th and the 25th mass and writes
the speed it measured next to a√(k/m).

Runs in the studio (Script tab → Run) and locally:  python3 wave_chain.py
"""
import math
import studio as s

N, A, K, M = 30, 0.2, 200.0, 0.1

s.clear()
s.gravity = (0, -9.81)
s.ground(0, width=12, friction=0)
chain = []
for i in range(N):
    chain.append(s.box(-2.9 + i * A, 0.07, 0.08, 0.14, mass=M, friction=0, restitution=0, name=f"Mass {i + 1}",
                       color="#e5484d" if i == 0 else "#4f8ff7"))
for i in range(N - 1):
    s.spring(chain[i], chain[i + 1], K, 0.0, rest=A - 0.08, at_a=(chain[i].x + 0.04, 0.07), at_b=(chain[i + 1].x - 0.04, 0.07))
chain[0].velocity = (1.0, 0)                       # the strike
arrival = {}


@s.on_step
def timing(t, dt):
    for k in (9, 24):
        if k not in arrival and abs(chain[k].x - (-2.9 + k * A)) > 0.004:
            arrival[k] = t
    if round(t / dt) % 6 == 0:                                   # 40 rows a second
        s.record(t=t, x10=chain[9].x + 2.9 - 9 * A, x25=chain[24].x + 2.9 - 24 * A)
    if len(arrival) == 2:
        s.stop()


@s.on_end
def report():
    if len(arrival) == 2:
        speed = (24 - 9) * A / (arrival[24] - arrival[9])
        print(f"measured wave speed {speed:.2f} m/s, a·√(k/m) = {A * math.sqrt(K / M):.2f} m/s")


s.run(3)

table springs waves