Solving ODEs: Euler and Runge–Kutta Methods
Ordinary differential equations (ODEs) describe how a quantity changes in response to another, often time. Many scientific and engineering problems take the form of an initial value problem (IVP), where you know the state at an initial point and want to predict future states. Mathematically, an IVP is written as:
dy/dt=f(t,y), y(t0)=y0Here, f(t,y) defines the rate of change, y0 is the initial value at time t0, and you seek y(t) for t>t0. While some ODEs have exact solutions, most real-world problems do not, making numerical solvers essential. These algorithms approximate the solution at discrete time points, allowing you to analyze systems that would otherwise be intractable.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950import numpy as np import matplotlib.pyplot as plt # Define the ODE: dy/dt = -2y, with y(0) = 1 def f(t, y): return -2 * y # Euler's method def euler(f, y0, t): y = np.zeros(len(t)) y[0] = y0 for i in range(1, len(t)): y[i] = y[i-1] + (t[i] - t[i-1]) * f(t[i-1], y[i-1]) return y # Classical Runge–Kutta (RK4) method def rk4(f, y0, t): y = np.zeros(len(t)) y[0] = y0 for i in range(1, len(t)): h = t[i] - t[i-1] ti = t[i-1] yi = y[i-1] k1 = f(ti, yi) k2 = f(ti + h/2, yi + h*k1/2) k3 = f(ti + h/2, yi + h*k2/2) k4 = f(ti + h, yi + h*k3) y[i] = yi + (h/6)*(k1 + 2*k2 + 2*k3 + k4) return y # Time grid t = np.linspace(0, 2, 21) y0 = 1 # Numerical solutions y_euler = euler(f, y0, t) y_rk4 = rk4(f, y0, t) # Exact solution for comparison y_exact = np.exp(-2 * t) # Plot results plt.plot(t, y_exact, 'k-', label='Exact') plt.plot(t, y_euler, 'bo--', label="Euler's method") plt.plot(t, y_rk4, 'gs-', label='RK4 method') plt.xlabel('t') plt.ylabel('y(t)') plt.legend() plt.title("Numerical Solutions of dy/dt = -2y") plt.show()
When you use numerical methods to solve ODEs, two types of errors are important: local truncation error and global error. Local truncation error is the error made in a single step of the method, assuming perfect knowledge up to that point. Global error is the accumulated error over all steps, reflecting the total deviation from the true solution.
Euler's method is simple but has relatively large local and global errors, especially for larger step sizes. Its error per step is proportional to the square of the step size, and the global error grows linearly with the step size. In contrast, the classical fourth-order Runge–Kutta (RK4) method is much more accurate: its local error per step is proportional to the fifth power of the step size, and the global error grows with the fourth power. This means RK4 can achieve high accuracy with fewer steps than Euler's method, making it a preferred choice for many scientific computing problems.
Thanks for your feedback!
Ask AI
Ask AI
Ask anything or try one of the suggested questions to begin our chat
Awesome!
Completion rate improved to 7.69
Solving ODEs: Euler and Runge–Kutta Methods
Swipe to show menu
Ordinary differential equations (ODEs) describe how a quantity changes in response to another, often time. Many scientific and engineering problems take the form of an initial value problem (IVP), where you know the state at an initial point and want to predict future states. Mathematically, an IVP is written as:
dy/dt=f(t,y), y(t0)=y0Here, f(t,y) defines the rate of change, y0 is the initial value at time t0, and you seek y(t) for t>t0. While some ODEs have exact solutions, most real-world problems do not, making numerical solvers essential. These algorithms approximate the solution at discrete time points, allowing you to analyze systems that would otherwise be intractable.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950import numpy as np import matplotlib.pyplot as plt # Define the ODE: dy/dt = -2y, with y(0) = 1 def f(t, y): return -2 * y # Euler's method def euler(f, y0, t): y = np.zeros(len(t)) y[0] = y0 for i in range(1, len(t)): y[i] = y[i-1] + (t[i] - t[i-1]) * f(t[i-1], y[i-1]) return y # Classical Runge–Kutta (RK4) method def rk4(f, y0, t): y = np.zeros(len(t)) y[0] = y0 for i in range(1, len(t)): h = t[i] - t[i-1] ti = t[i-1] yi = y[i-1] k1 = f(ti, yi) k2 = f(ti + h/2, yi + h*k1/2) k3 = f(ti + h/2, yi + h*k2/2) k4 = f(ti + h, yi + h*k3) y[i] = yi + (h/6)*(k1 + 2*k2 + 2*k3 + k4) return y # Time grid t = np.linspace(0, 2, 21) y0 = 1 # Numerical solutions y_euler = euler(f, y0, t) y_rk4 = rk4(f, y0, t) # Exact solution for comparison y_exact = np.exp(-2 * t) # Plot results plt.plot(t, y_exact, 'k-', label='Exact') plt.plot(t, y_euler, 'bo--', label="Euler's method") plt.plot(t, y_rk4, 'gs-', label='RK4 method') plt.xlabel('t') plt.ylabel('y(t)') plt.legend() plt.title("Numerical Solutions of dy/dt = -2y") plt.show()
When you use numerical methods to solve ODEs, two types of errors are important: local truncation error and global error. Local truncation error is the error made in a single step of the method, assuming perfect knowledge up to that point. Global error is the accumulated error over all steps, reflecting the total deviation from the true solution.
Euler's method is simple but has relatively large local and global errors, especially for larger step sizes. Its error per step is proportional to the square of the step size, and the global error grows linearly with the step size. In contrast, the classical fourth-order Runge–Kutta (RK4) method is much more accurate: its local error per step is proportional to the fifth power of the step size, and the global error grows with the fourth power. This means RK4 can achieve high accuracy with fewer steps than Euler's method, making it a preferred choice for many scientific computing problems.
Thanks for your feedback!