MATH_467_hw1

168 days ago by solin

The goal of HW1 was to calculate and compare convergence rates of explicit Runge-Kutta methods RK1, RK2 and RK4.

# Importing libraries: from pylab import arange, zeros, plot, savefig, clf, grid, legend, array, xscale, yscale, title, xlabel, ylabel, axis, fabs from pylab import pi, exp, sin, cos, loglog # Explicit Euler (RK1) method def RK1(F, y0, t_array, n, dt): 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, dt): 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, dt): 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) # Error calculation: Finds maximum of |E(t) - y_approx(t)| # over all discrete time steps def calc_error(E, t_array, y_array, n): max = 0. for i in range(n): if fabs(E(t_array[i]) - y_array[i]) > max: max = fabs(E(t_array[i]) - y_array[i]) return max # Go through div_list, always calculate and plot the three # solutions, and store the maximum errors for all three # methods def browse_list(t_min, t_max, E, F, y0, n_array): RK1_error = [] RK2_error = [] RK4_error = [] for n in n_array: print "Subdivision = ", n # Time step dt = (t_max - t_min)/n # Array of discrete time points t_array = arange(t_min, t_max + dt/2., dt) clf() name = "Convergence for division n = " + str(n) title(name) # Explicit Euler (RK1) method Y_RK1_array = RK1(F, y0, t_array, n, dt) RK1_error.append(calc_error(E, t_array, Y_RK1_array, n)) plot(t_array, Y_RK1_array, "b-", label = "RK1") # Second-order Runge-Kutta (RK2) method Y_RK2_array = RK2(F, y0, t_array, n, dt) RK2_error.append(calc_error(E, t_array, Y_RK2_array, n)) plot(t_array, Y_RK2_array, "y-", label = "RK2") # Fourth-order Runge-Kutta (RK4) method Y_RK4_array = RK4(F, y0, t_array, n, dt) RK4_error.append(calc_error(E, t_array, Y_RK4_array, n)) plot(t_array, Y_RK4_array, "r-", label = "RK4") # Plot exact solution if known if exact_known == True: plot_exact(E, t_min, t_max, 500) legend() grid(True) name = "a" + str(1000000+n) + ".png" savefig(name) # Print errors print "RK1_error:" print RK1_error print "RK2_error:" print RK2_error print "RK4_error:" print RK4_error # Plot convergence clf() #axis('equal') title("Convergence") xlabel("Number of time steps (log scale)") ylabel("Error (log scale)") loglog(n_array, RK1_error, "g-o", label="RK1") loglog(n_array, RK2_error, "b-o", label="RK2") loglog(n_array, RK4_error, "y-o", label="RK4") legend() grid(True) savefig("graph.png") 
       
# Main program # Problem definition: t_min = 0. t_max = 5. K = 1 # Right-hand side def F(y,t): #K = 1 #return K*cos(K*t) return -y # Initial condition y0 = 3. # Is exact solution available? exact_known = True # Exact solution: def E(t): return 3*exp(-t) #return sin(K*t) # Array of divisions n_array = [10, 20, 50, 100, 200, 500, 1000, 2000, 5000] # Subdivision for error calculation browse_list(t_min, t_max, E, F, y0, n_array) 
       
Subdivision =  10
Subdivision =  20
Subdivision =  50
Subdivision =  100
Subdivision =  200
Subdivision =  500
Subdivision =  1000
Subdivision =  2000
Subdivision =  5000
RK1_error:
[0.353638323514327, 0.154419573514327, 0.057603003214326876,
0.028180556288700087, 0.013941003850685751, 0.0055412996946380133,
0.0027648583358252932, 0.0013809867322736036,
0.00055204920143525626]
RK2_error:
[0.068236676485672998, 0.013948766024247217, 0.0019846309863285061,
0.00047754150124390549, 0.00011714563625364605,
1.8532634249446289e-05, 4.6157815039027383e-06,
1.1517815534656251e-06, 1.8407774615702976e-07]
RK4_error:
[0.00087420903775647929, 4.4274705918834201e-05,
9.9972316847107834e-07, 5.9928292106548042e-08,
3.6682255011299958e-09, 9.2738927648383651e-11,
5.7713833712114138e-12, 3.5860203695392556e-13,
9.3258734068513149e-15]