Marketplace › From Ordinate 2D
A pulse along a chain of springs
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)