[Numerical calculation methods (Huang Mingyou)] Numerical integration method for initial value problems of ordinary differential equations: Euler method (Backward Euler) [Theory to program]

  Numerical integration method for initial value problems of ordinary differential equations is a problem that uses numerical methods to solve ordinary differential equations (Ordinary Differential Equations, ODEs) under given initial conditions.

1. Numerical integration method

1. General steps

  1. Determine the differential equation:

    • Definite differential equation set y ′ ( x ) = f ( x , y ( x ) ) y'(x) = f(x, y(x) )and(x)=f(x,y(x))
  2. Determine the initial conditions:

    • The initial value problem contains an initial condition y ( a ) = y 0 y(a) = y_0 y(a)=and0, inside a a a is the starting point of the domain, y 0 y_0 and0is the initial value.
  3. Choose a numerical method:

    • Choose an appropriate numerical method to approximate the solution (accuracy, stability and computational efficiency need to be considered). Common numerical methods include Euler method, improved Euler method, Runge-Kutta method, etc.
  4. Discretization domain:

    • General range [ a , b ] [a, b] [a,b] Divide it into several small steps, that is, choose the appropriate step size h h h. Generally, a smaller step size improves the accuracy of the numerical solution, but also increases the computational cost.
  5. Numerical iteration:

    • Iterative calculation using the selected numerical method: According to the selected method, the function value at the next point is calculated and the solution is updated.
  6. Determine stopping conditions:

    • Determine whether an approximate solution that meets the specified accuracy is reached: some error estimation method can be used, such as controlling local truncation error or global error.
  7. Output result:

    • Finally, an approximate solution that satisfies the initial value problem in a given domain is obtained.

2. Numerical methods

  1. Euler Method:

    • Basic idea: According to the definition of differential equations, use discrete steps to approximate the derivative, and then approximate the function value of the next point.
    • 公式: y n + 1 = y n + h f ( t n , y n ) y_{n+1} = y_n + h f(t_n, y_n) andn+1=andn+hf(tn,andn)
      inside, y n y_n andnThis is the first n n Function value of n step, h h h是步长, f ( t n , y n ) f(t_n, y_n) f(tn,andn) is the point ( t n , y n ) (t_n, y_n) (tn,andnThe derivative at ).
  2. Improved Euler Method (Improved Euler Method or Trapezoidal Rule):

    • Basic idea: Use two approximations to improve accuracy, first using Euler's method to calculate the intermediate point, and then using the derivative estimate of that point to calculate the next point.
    • 公式: y n + 1 = y n + h 2 [ f ( t n , y n ) + f ( t n + 1 , y n + h f ( t n , y n ) ) ] y_{n+1} = y_n + \frac{h}{2} [f(t_n, y_n) + f(t_{n+1}, y_n + hf(t_n, y_n))] andn+1=andn+2h[f(tn,andn)+f(tn+1,andn+hf(tn,andn))]
  3. Runge-Kutta method:

    • Basic idea: improve accuracy through multiple stages of calculation. The most common of these is the fourth-order Runge-Kutta method.
    • 公式:
      k 1 = h f ( t n , y n ) k_1 = hf(t_n, y_n) k1=hf(tn,andn) k 2 = h f ( t n + h 2 , y n + k 1 2 ) k_2 = hf(t_n + \frac{h}{2}, y_n + \frac{k_1}{2}) k2=hf(tn+2h,andn+2k1) k 3 = h f ( t n + h 2 , y n + k 2 2 ) k_3 = hf(t_n + \frac{h}{2}, y_n + \frac{k_2}{2}) k3=hf(tn+2h,andn+2k2) k 4 = h f ( t n + h , y n + k 3 ) k_4 = hf(t_n + h, y_n + k_3) k4=hf(tn+h,andn+k3) y n + 1 = y n + 1 6 ( k 1 + 2 k 2 + 2 k 3 + k 4 ) y_{n+1} = y_n + \frac{ 1}{6}(k_1 + 2k_2 + 2k_3 + k_4) andn+1=andn+61(k1+2k2+2k3+k4)

  In these methods, the step size h h h is a key parameter, which determines the degree of discretization. Choosing an appropriate step size is very important for the accuracy and stability of numerical solutions.

2. Euler Method

1. Forward Euler method (Forward Euler method)

[Computational methods and scientific modeling] Numerical integration method for initial value problems of ordinary differential equations: Euler method (forward Euler and its python implementation)

  • The forward difference quotient approximates the microquotient:
    • current point X n X_n Xn, by forward difference quotient y ( X n + 1 ) − y ( X n ) h \frac{y(X_{n+1}) - y( X_n)}{h} hy(Xn+1)y(Xn) Approximate alternative differential equation y ′ ( x ) = f ( x , y ( x ) ) y'(x) = f(x, y(x)) and(x)=f(x,y(x)) 中的导数项,得到 y ′ ( X n ) ≈ y ( X n + 1 ) − y ( X n ) h = f ( X n , y ( X n ) ) y'(X_n) \approx \frac{y(X_{n+1}) - y(X_n)}{h} = f(X_n, y(X_n)) and(Xn)hy(Xn+1)y(Xn)=f(Xn,y(Xn))
    • This approximation transforms the differential equation into a recurrence relation by equating the difference quotient with the derivative.
  • Recursion formula:
    • Change the above approximate formula into an equation to get the recursion formula y n + 1 = y n + h f ( X n , y n ) y_{n+1} = y_n + hf (X_n, y_n) andn+1=andn+hf(Xn,andn)
    • This formula is the core of Euler's method, through which the value of the approximate solution can be calculated step by step.

2. Backward Euler method (Backward Euler method)

a. Basic theory

  The core idea of ​​the backward Euler method is from the differential equation y ′ ( X n + 1 ) = f ( x n + 1 , y ( X n + 1 ) ) y& #39;(X_{n+1}) = f(x_{n+1}, y(X_{n+1})) and(Xn+1)=f(xn+1,y(Xn+1)) Difference quotient for output and usage y ( X n + 1 ) − y ( X n ) h \frac{y (X_{n+1}) - y(X_n)}{h} hy(Xn+1)y(Xn) Approximate derivative y ′ ( X n + 1 ) y'(X_{n+1}) and(Xn+1), and then use this approximation to get the recursion formula. Specifically, the recursion formula is:

y n + 1 = y n + h f ( X n + 1 , y n + 1 ) , n = 0 , 1 , …   y_{n+1} = y_n + hf(X_{n+1}, y_{n+1}), \quad n = 0, 1, \ldots \ andn+1=andn+hf(Xn+1,andn+1),n=0,1, 

这り, y n + 1 y_{n+1} andn+1 is there X n + 1 X_{n+1} Xn+1Approximate solution at , h h h This is long.

  Comparing the forward Euler method and the backward Euler method, you can notice the key differences between the two:

  1. Explicit vs. Implicit:

    • The forward Euler method gives an explicit recursion formula, which can bedirectly calculated y n + 1 y_{n+1} andn+1
    • The backward Euler method gives an implicit recursion formula where y n + 1 y_{n+1} andn+1 appears on the right side of the equation and needs to be obtained by solving the nonlinear equation.
  2. Solution:

    • The solution to the forward Euler method can be calculated by simple iterations.
    • The solution of the backward Euler method requires solving the nonlinear equation iteratively. Usually, iterative methods, such as Newton's iteration method, can be used to gradually approximate the solution of the equation.
  3. Specific iteration process:

    • Initial value: Use the forward Euler formula to give an initial value, for example y n + 1 ( 0 ) = y n + h f ( x n + 1 , y n ) y_{n+ 1}^{(0)} = y_n + hf(x_{n+1}, y_n) andn+1(0)=andn+hf(xn+1,andn), inside y n + 1 ( 0 ) y_{n+1}^{(0)} andn+1(0)is the initial value of the iteration.

    • Iterative formula: Use iterative formula y n + 1 ( k + 1 ) = y n + h f ( x n + 1 , y n + 1 ( k ) ) , k = 0 , 1 , … y_{n+1}^{(k+1)} = y_n + hf(x_{n+1}, y_{n+1}^{(k)}), \quad k = 0, 1, \ldots andn+1(k+1)=andn+hf(xn+1,andn+1(k)),k=0,1,计算 y n + 1 y_{n+1} andn+1approximation value.

    • Repeat the iteration until the convergence condition is met, and obtain y n + 1 y_{n+1} andn+1approximate solution.

  The backward Euler method may be more stable when dealing with certain problems (such as stiffness problems), but due to the implicit equations involved The computational cost may be high.

b. Algorithm implementation

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve


def forward_euler(f, y0, a, b, h):
    """
    使用向前欧拉法求解一阶常微分方程初值问题

    Parameters:
    - f: 函数,表示微分方程的右侧项,形式为 f(x, y)
    - y0: 初始条件,表示在 x=a 处的函数值
    - a: 区间起点
    - b: 区间终点
    - h: 步长

    Returns:
    - x_values: 区间 [a, b] 上的离散节点
    - y_values: 对应节点上的函数值的近似解
    """

    num_steps = int((b - a) / h) + 1  # 计算步数
    x_values = np.linspace(a, b, num_steps)  # 生成离散节点
    y_values = np.zeros(num_steps)  # 初始化结果数组

    y_values[0] = y0  # 设置初始条件

    # 使用向前欧拉法进行逐步迭代
    for i in range(1, num_steps):
        x = x_values[i - 1]
        y = y_values[i - 1]
        y_values[i] = y + h * f(x, y)

    return x_values, y_values


def backward_euler(f, y0, a, b, h):
    """
    使用向后欧拉法求解一阶常微分方程初值问题

    Parameters:
    - f: 函数,表示微分方程的右侧项,形式为 f(x, y)
    - y0: 初始条件,表示在 x=a 处的函数值
    - a: 区间起点
    - b: 区间终点
    - h: 步长

    Returns:
    - x_values: 区间 [a, b] 上的离散节点
    - y_values: 对应节点上的函数值的近似解
    """

    num_steps = int((b - a) / h) + 1  # 计算步数
    x_values = np.linspace(a, b, num_steps)  # 生成离散节点
    y_values = np.zeros(num_steps)  # 初始化结果数组

    y_values[0] = y0  # 设置初始条件

    # 使用向后欧拉法进行逐步迭代
    for i in range(1, num_steps):
        x = x_values[i]
        # 定义非线性方程
        equation = lambda y_next: y_next - y_values[i - 1] - h * f(x, y_next)
        # 利用 fsolve 求解非线性方程,得到 y_values[i]
        y_values[i] = fsolve(equation, y_values[i - 1])[0]

    return x_values, y_values


# 示例:求解 y' = y -2x/y,初始条件 y(0) = 1 在区间 [0, 1] 上的近似解
def example_function(x, y):
    return y - 2 * x / y


a, b = 0, 1  # 区间 [a, b]
y0 = 1  # 初始条件 y(0) = 1
h = 0.05  # 步长
x_values0, y_values0 = forward_euler(example_function, y0, a, b, h)

x_values, y_values = backward_euler(example_function, y0, a, b, h)

# 绘制结果
plt.plot(x_values0, y_values0, label='Forward Euler')
plt.plot(x_values, np.sqrt(1 + 2 * x_values), label='Exact Solution')
plt.plot(x_values, y_values, label='Backward Euler')
plt.title('h = {}'.format(h))
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

  • h = 0.1
    Insert image description here

  • h = 0.05
    Insert image description here

  • h = 0.02
    Insert image description here

Guess you like

Origin blog.csdn.net/m0_63834988/article/details/134672457