# Importing libraries:
from pylab import arange, zeros, plot, savefig, clf, grid, legend, array
from pylab import pi, exp, sin, cos
# Explicit Euler (RK1) method
def RK1(F, y0, t_array, n):
y_array = zeros(n+1)
y_array[0] = y0
for i in range(n):
y_array[i+1] = y_array[i] + dt*F(y_array[i], t_array[i])
return y_array
# RK2 method
def RK2(F, y0, t_array, n):
b1 = 1./4
b2 = 3./4
c2 = 2./3
a21 = 2./3
y_array = zeros(n+1)
y_array[0] = y0
for i in range(n):
k1 = F(y_array[i], t_array[i])
k2 = F(y_array[i] + a21*dt*k1, t_array[i] + c2*dt)
y_array[i+1] = y_array[i] + dt*(b1*k1 + b2*k2)
return y_array
# RK4 method
def RK4(F, y0, t_array, n):
b1 = 1./6
b2 = 1./3
b3 = 1./3
b4 = 1./6
c2 = 1./2
c3 = 1./2
c4 = 1.
a21 = 1./2
a31 = 0.
a32 = 1./2
a41 = 0.
a42 = 0.
a43 = 1.
y_array = zeros(n+1)
y_array[0] = y0
for i in range(n):
k1 = F(y_array[i], t_array[i])
k2 = F(y_array[i] + dt*(a21*k1), t_array[i] + c2*dt)
k3 = F(y_array[i] + dt*(a31*k1 + a32*k2), t_array[i] + c3*dt)
k4 = F(y_array[i] + dt*(a41*k1 + a42*k2 + a43*k3), t_array[i] + c4*dt)
y_array[i+1] = y_array[i] + dt*(b1*k1 + b2*k2 + b3*k3 + b4*k4)
return y_array
# Plotting exact solution
def plot_exact(E, t_min, t_max, n_exact):
dt_exact = (t_max - t_min)/n_exact
t_array_exact = arange(t_min, t_max + dt_exact/2., dt_exact)
E_array = array([E(t) for t in t_array_exact])
label = "Exact solution E(t)"
plot(t_array_exact, E_array, "g-", label=label)
# Main program:
# Problem definition:
t_min = 0.
t_max = pi
K = 3
# Right-hand side
def F(y,t):
return K*cos(K*t)
#return -y
# Initial condition
y0 = 0.
# Is exact solution available?
exact_known = True
# Exact solution:
def E(t):
#return 3*exp(-t)
return sin(K*t)
# Division
n = 30
# Time step
dt = (t_max - t_min)/n
# Array of discrete time points
t_array = arange(t_min, t_max + dt/2., dt)
clf()
# Explicit Euler (RK1) method
Y_RK1_array = RK1(F, y0, t_array, n)
label = "RK1"
plot(t_array, Y_RK1_array, "b-", label=label)
# Second-order Runge-Kutta (RK2) method
Y_RK2_array = RK2(F, y0, t_array, n)
label = "RK2"
plot(t_array, Y_RK2_array, "y-", label=label)
# Fourth-order Runge-Kutta (RK4) method
Y_RK4_array = RK4(F, y0, t_array, n)
label = "RK4"
plot(t_array, Y_RK4_array, "r-", label=label)
# Plot exact solution if known
if exact_known == True: plot_exact(E, t_min, t_max, 500)
legend()
grid(True)
savefig("a.png")