#!/usr/bin/env python #fixed step euler and runge-kutta for harmonic oscillator from __future__ import division from numpy import * from matplotlib import pyplot as plt import pyximport pyximport.install(setup_args={"include_dirs":get_include()}) from integration import * def f(z): #we are simplifying a second order equation in y to a first order equation in z #we know that ddy = -y, so let z = (y,dy) #then dz = (dy,ddy) = (dy, -y) = (z[1],-z[0]) return array([z[1],-z[0]]) def fixed_error(ti,tf,z0): from time import time dt = tf-ti t0 = time() max_steps = 1e4 z = empty((max_steps,2)) #allocate t = empty(max_steps) #allocate n_steps = adaptive_runge_kutta_4_cython(f,dt,t,z,z0,h0=.01,error_threshold=1e-9,max_steps=max_steps) t = t[:n_steps+1] z = z[:n_steps+1] print "adaptive Runge Kutta took: %.3f s"%(time()-t0) plt.figure() plt.plot(t+ti,z[...,0],color='g',label='runge kutta 4',marker='.') plt.xlim([ti,tf]) plt.ylim([-2,2]) plt.xlabel('t') plt.ylabel('y') plt.title('Adaptive Runge Kutta for $\ddot{y}+y=0$') plt.legend(loc='lower left') plt.figure() plt.plot(t[1:]+ti, t[1:]-t[:-1], color='g',label='runge kutta 4') plt.xlim([ti,tf]) plt.ylim([0,1]) plt.xlabel('t') plt.ylabel('step size') plt.title('Adaptive Runge Kutta step size for $\ddot{y}+y=0$') plt.legend(loc='lower left') def plot_over_desired_error(ti,tf,z0,errors): from time import time avg_steps = [] dt = tf-ti max_steps = 1e4 for err in errors: t0 = time() z = empty((max_steps,2)) #allocate t = empty(max_steps) #allocate n_steps = adaptive_runge_kutta_4_cython(f,dt,t,z,z0,h0=.01,error_threshold=err,max_steps=max_steps) t = t[:n_steps+1] z = z[:n_steps+1] print "adaptive Runge Kutta took: %.3f s"%(time()-t0) avg_steps.append( average(t[1:]-t[:-1]) ) print avg_steps plt.figure() ax = plt.gca() ax.set_xscale('log') ax.set_yscale('log') plt.plot(errors,avg_steps,color='b',marker='.') plt.xlim([0,errors[-1]]) plt.xlabel('desired error') plt.ylabel('average step size') plt.grid(True) plt.title('Average step size of adaptive Runge Kutta for $\ddot{y}+y=0$') if __name__ == '__main__': ti = 0. tf = 100*pi z0 = array([1,0]) #z = (y,dy) fixed_error(ti,tf,z0) #errors = logspace(-11, -3, num=10) #plot_over_desired_error(ti,tf,z0,errors) plt.show()