import numpy as np
import matplotlib.pyplot as plt
def euler_shm():
h = 0.01
t = np.arange(0, 100*np.pi, h)
# init values for y(x) and y'(x)
yx = [1]
ypx = [0]
cum_error = 0
for ts in t:
# compute new y(x) and new y'(x)
yx_new = yx[-1] + (h * ypx[-1])
ypx_new = ypx[-1] - (h * yx[-1])
yx.append(yx_new)
ypx.append(ypx_new)
cum_error += np.abs(np.cos(ts) - yx[-1])
plt.plot(t, np.cos(t))
plt.plot(t, yx[:-1])
print "Cumulative Error", cum_error
plt.show()
if __name__ == "__main__":
euler_shm()
# yx -> y0
# ypx -> y1; Neil's notation easier to follow
def rk_shm():
h = 0.01
t = np.arange(0, 100*np.pi, h)
# init values
y0 = [1]
y1 = [0]
k1 = [0,0]
k2 = [0,0]
k3 = [0,0]
k4 = [0,0]
cum_error = 0
for ts in t:
k1[0] = h * y1[-1]
k1[1] = -h * y0[-1]
k2[0] = h * (y1[-1] + k1[1]/2.0)
k2[1] = -h * (y0[-1] + k1[0]/2.0)
k3[0] = h * (y1[-1] + k2[1]/2.0)
k3[1] =-h * (y0[-1] + k2[0]/2.0)
k4[0] = h * (y1[-1] + k3[1]/2.0)
k4[1] =-h * (y0[-1] + k3[0]/2.0)
y0.append(y0[-1] + (k1[0] / 6.0) + (k2[0] / 3.0) + (k2[0] / 3.0) + (k4[0] / 6.0) )
y1.append(y1[-1] + (k1[1] / 6.0) + (k2[1] / 3.0) + (k2[1] / 3.0) + (k4[1] / 6.0) )
cum_error += np.abs(np.cos(ts) - y0[-1])
plt.plot(t, np.cos(t))
plt.plot(t, y0[:-1])
print "Cumulative Error", cum_error
plt.show()
if __name__ == "__main__":
rk_shm()
# Incorrect - the y value diverging from cos solution?
def make_step(si, sf, s):
k1 = [0,0]
k2 = [0,0]
k3 = [0,0]
k4 = [0,0]
k1[0] = s * si[1]
k1[1] = -s * si[0]
k2[0] = s * (si[1] + k1[1]/2.0)
k2[1] = -s * (si[0] + k1[0]/2.0)
k3[0] = s * (si[1] + k2[1]/2.0)
k3[1] =-s * (si[0] + k2[0]/2.0)
k4[0] = s * (si[1] + k3[1])
k4[1] =-s * (si[0] + k3[0])
sf[0] = (si[0] + (k1[0] / 6.0) + (k2[0] / 3.0) + (k2[0] / 3.0) + (k4[0] / 6.0) )
sf[1] = (si[1] + (k1[0] / 6.0) + (k2[0] / 3.0) + (k2[0] / 3.0) + (k4[0] / 6.0) )
return (si, sf)
def rk_adaptive():
allowed_error = 0.1
scale_down = 1.3
scale_up = 1.2
h = 0.1
t = 2 * np.pi
# init values
y0 = [1,0]
y1 = [0,0]
y2 = [0,0]
y3 = [0,0]
y4 = [0,0]
error = 0
out = []
time = []
i = 0
while i < t:
# print i
y0, y1 = make_step(y0, y1, h/2.0)
y1, y2 = make_step(y1, y2, h/2.0)
y0, y3 = make_step(y0, y3, h)
error = np.abs(y3[0] - y2[0])
# print error
if error > allowed_error:
h = h / scale_down
else:
y0[0] = y2[0]
y0[1] = y2[1]
print y0[0]
out.append(y0[0])
time.append(i)
i+=h
if error < allowed_error * 0.20:
h = h * scale_up
plt.plot(time, np.cos(time))
print len(time)
print len(out)
plt.plot(time, out)
print "Error", error
plt.show()
if __name__ == "__main__":
rk_adaptive()
def rk_shm_pendulum():
h = 0.01
t = np.arange(0, 100*np.pi, h)
l = 2
g = 9.81
# init values
# y0 = [1]
# y1 = [0]
# initial values should be a function of l, g, and z?
k1 = [0,0]
k2 = [0,0]
k3 = [0,0]
k4 = [0,0]
cum_error = 0
for ts in t:
k1[0] = h * y1[-1]
k1[1] = -h * y0[-1]
k2[0] = h * (y1[-1] + k1[1]/2.0)
k2[1] = -h * (y0[-1] + k1[0]/2.0)
k3[0] = h * (y1[-1] + k2[1]/2.0)
k3[1] =-h * (y0[-1] + k2[0]/2.0)
k4[0] = h * (y1[-1] + k3[1]/2.0)
k4[1] =-h * (y0[-1] + k3[0]/2.0)
y0.append(y0[-1] + (k1[0] / 6.0) + (k2[0] / 3.0) + (k2[0] / 3.0) + (k4[0] / 6.0) )
y1.append(y1[-1] + (k1[1] / 6.0) + (k2[1] / 3.0) + (k2[1] / 3.0) + (k4[1] / 6.0) )
cum_error += np.abs(np.cos(ts) - y0[-1])
plt.plot(t, np.cos(t))
plt.plot(t, y0[:-1])
print "Cumulative Error", cum_error
plt.show()
if __name__ == "__main__":
rk_shm()