Loading [MathJax]/extensions/MathMenu.js

Friday, 5 December 2014

Basic physics and Python: simple harmonic motion

Here is simple harmonic motion simulation with a spring and a bouncing ball.
Springs are a classic example of harmonic motion, on Wikipedia you can get a grasp of the basics. Among other assumption, in my simulation I’ve assumed an ideal spring and that there is no friction (and therefore the motion will not stop by itself) however, if you like, you can implement friction easily.



Here is the spring simulation
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
fig = plt.figure(figsize=(7,7))
ax1 = fig.add_subplot(1,1,1)
ax2 = fig.add_subplot(2,1,1)
ax3 = fig.add_subplot(3,1,1)
fig.subplots_adjust(hspace=.45)
# Spring data
k = 100
m = 20
w = np.sqrt(k/m)
phi = 2
A = 2
period = 2*np.pi/w
frequency = 1/period
print("Period:",period,"seconds",sep=" ")
print("Frequency:",frequency,"Hz",sep=" ")
print("k: ",k,"N/m",sep=" ")
def fun(t):
global w,phi,A
return A*np.sin(w*t+phi)
def vel(t):
global w,phi,A
return A*w*np.cos(w*t+phi)
def acceleration(t):
global w,phi,A
return -A*w**2*np.sin(w*t+phi)
def position(x):
x1 = x-1
x2 = x+1
y1 = 1
y2 = -1
p1 = [x1,y2]
p2 = [x2,y2]
p3 = [x2,y1]
p4 = [x1,y1]
return [p1,p2,p3,p4]
counter = 0
xt = [0]
yt = [0]
vy = [0]
acy = [0]
def animate(i):
global counter, xt,yt,A,vy,acy
ax3.clear()
plt.subplot(311)
# configure X axes
plt.xlim(-3.5,3.5)
# configure Y axes
plt.ylim(-2,2)
# labels
plt.xlabel("x")
plt.ylabel("y")
plt.title("Motion of an ideal spring")
p1 = [position(fun(counter))[0][0],position(fun(counter))[0][1]]
p2 = [position(fun(counter))[1][0],position(fun(counter))[1][1]]
p3 = [position(fun(counter))[2][0],position(fun(counter))[2][1]]
p4 = [position(fun(counter))[3][0],position(fun(counter))[3][1]]
x = [p1[0],p2[0],p3[0],p4[0],p1[0]]
y = [p1[1],p2[1],p3[1],p4[1],p1[1]]
linex = [-4,p1[0]]
liney = [0,0]
plt.plot(x,y,lw=5,color="blue")
plt.plot(linex,liney,color="red",ls=":",lw=5)
plt.subplot(312)
xt.append(counter)
vy.append(vel(counter))
plt.title("Velocity")
plt.xlim(0,15)
plt.ylim(-A*w-0.5,A*w+0.5)
plt.plot(xt,vy,lw=1,color="green")
plt.plot([0,15],[0,0],lw=0.5,color="black")
plt.subplot(313)
acy.append(acceleration(counter))
plt.title("Acceleration")
plt.xlim(0,15)
plt.ylim(-A*w**2-0.5,A*w**2+0.5)
plt.plot(xt,acy,lw=1,color="green")
plt.plot([0,15],[0,0],lw=0.5,color="black")
counter += 0.1
ani = animation.FuncAnimation(fig,animate,interval=2)
plt.show()

Below is the bouncing ball:


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def fun(x):
return 2*np.sin(2*x+2)
counter = 1
def animate(i):
global x,y,counter
counter += 0.2
ax1.clear()
plt.xlim(0,50)
plt.ylim(-3,3)
plt.plot([x for x in range(50)],[-2.15 for x in range(50)],lw=2,color="black")
plt.plot(counter,fun(counter),marker="o",ms=20)
ani = animation.FuncAnimation(fig,animate,interval=1)
plt.show()

A simpler example of simple harmonic motion with a spring (video):


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def fun(t):
return 2*np.sin(4/3*t+2)
x = [0]
y = [fun(x[0])]
def position(x):
x1 = x-1
x2 = x+1
y1 = 1
y2 = -1
p1 = [x1,y2]
p2 = [x2,y2]
p3 = [x2,y1]
p4 = [x1,y1]
return [p1,p2,p3,p4]
counter = 0
def animate(i):
global x,y,counter
ax1.clear()
# configure X axes
plt.xlim(-5,5)
plt.xticks([-4,-3,-2,-1,0,1,2,3,4])
# configure Y axes
plt.ylim(-5,5)
# labels
plt.xlabel("x")
plt.ylabel("y")
plt.title("Simple harmonic motion")
# plt.gca().add_line(line)
p1 = [position(fun(counter))[0][0],position(fun(counter))[0][1]]
p2 = [position(fun(counter))[1][0],position(fun(counter))[1][1]]
p3 = [position(fun(counter))[2][0],position(fun(counter))[2][1]]
p4 = [position(fun(counter))[3][0],position(fun(counter))[3][1]]
x = [p1[0],p2[0],p3[0],p4[0],p1[0]]
y = [p1[1],p2[1],p3[1],p4[1],p1[1]]
linex = [-4,p1[0]]
liney = [0,0]
plt.plot(x,y,lw=5,color="blue")
plt.plot(linex,liney,color="red",ls=":",lw=5)
counter += 0.2
ani = animation.FuncAnimation(fig,animate,interval=1)
plt.show()

Hope this was interesting.

8 comments:

  1. Thanks. I'd like to write an animation program that simulates the forces of gravitational attraction between two bodies. First have to learn how to use animate.

    ReplyDelete
  2. p1 = [position(fun(counter))[0][0],position(fun(counter))[0][1]] can i know what does this line do ? im new to python , i search for plt.gca and i still dun get it

    ReplyDelete
    Replies
    1. That's some horribly inefficient and convoluted code on my behalf I'm afraid! :D that line simply returns p1 from the position function, you could replace it with p1 = position(fun(counter))[0]. p1 is one of the four points you need to draw a rectangle.

      plt.gca does nothing, it's a comment.

      Delete
    2. please if possible explain the meaning of
      p1 = [position(fun(counter))[0][0],position(fun(counter))[0][1]]
      p2 = [position(fun(counter))[1][0],position(fun(counter))[1][1]]
      p3 = [position(fun(counter))[2][0],position(fun(counter))[2][1]]
      p4 = [position(fun(counter))[3][0],position(fun(counter))[3][1]]

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. hey i'm having a problem programing a spring with potential and gravitational energy using the formula (1/2)Kx^2 + (1/6)Yx^3, i know we have to derive that to get force but i can't seem to add it up to create a cubic or more cubic graph. please help!!!!

    ReplyDelete
  5. Thanks for the lovely simulation codes, man.

    ReplyDelete