如何基于时空序值计算将FTBS改进为蛙跳法(CTCS)求解线性Burgers方程
用蛙跳法求解线性对流方程(无扰动Burgers方程)
首先明确蛙跳法的核心格式:对于无扰动线性Burgers方程(本质为线性对流方程)$\frac{\partial u}{\partial t} + u_0 \frac{\partial u}{\partial x} = 0$,蛙跳格式采用二阶时间差分和二阶空间中心差分,离散形式为:
$$u_i^{n+1} = u_i^{n-1} - \frac{u_0 \Delta t}{\Delta x} \left( u_{i+1}^n - u_{i-1}^n \right)$$
核心改进要点
- 需存储前两个时间步的速度场($u{n-1}$和$un$),不能像FTBS那样仅用单个数组原地更新
- 由于初始只有$t=0$的场,需要先用一阶格式(如原FTBS)计算出$t=\Delta t$的场,作为蛙跳法的启动步
- 周期性边界条件处理:边界点的空间差分需循环取域内对应点
完整实现代码
1. 参数初始化与初始场准备
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # 原参数保留 L = 20 # 计算域长度 dx = 0.1 # 空间步长 N = int(L / dx) # 网格点数 dt = 0.01 # 时间步长 u0 = 1 # 平流速度 T = 10 # 最终时间 num_steps = int(T / dt) # t=0时刻的初始场 u_prev = 0.5 * (1 + np.cos(2 * np.pi * np.arange(N) * dx / L)) # 用FTBS计算t=dt的场,作为蛙跳法的当前时间步(启动蛙跳需要两个初始时间步) u_curr = u_prev.copy() for i in range(N): if i == 0: u_curr[i] = u_prev[i] - (u0*dt/dx) * (u_prev[i] - u_prev[N-1]) else: u_curr[i] = u_prev[i] - (u0*dt/dx) * (u_prev[i] - u_prev[i-1]) # 动画初始化(保留原逻辑) fig, ax = plt.subplots() line, = ax.plot(np.arange(N)*dx, u_prev) ax.set_ylim(0, 1.1) ax.set_xlabel('x') ax.set_ylabel('u') ax.set_title('Leapfrog Method for Linear Advection')
2. 蛙跳法时间推进函数
def advection_leapfrog(n): global u_prev, u_curr u_next = np.zeros_like(u_curr) # 遍历所有网格点,应用蛙跳格式+周期性边界 for i in range(N): # 周期性边界处理:i+1超出右边界则取左端点,i-1超出左边界则取右端点 i_plus = (i + 1) % N i_minus = (i - 1) % N # 蛙跳格式核心计算 u_next[i] = u_prev[i] - (u0 * dt / dx) * (u_curr[i_plus] - u_curr[i_minus]) # 更新时间步缓存:u_prev为上一步,u_curr为当前步 u_prev, u_curr = u_curr, u_next # 更新动画数据 line.set_data(np.arange(N)*dx, u_curr) return line,
3. 启动动画计算
ani = FuncAnimation(fig, advection_leapfrog, frames=num_steps-1, interval=20, blit=True) plt.show()
关键注意事项
- 稳定性验证:蛙跳法的CFL条件为$\frac{u_0 \Delta t}{\Delta x} \leq 1$,你的参数计算得$\frac{1*0.01}{0.1}=0.1 \leq 1$,满足稳定性要求
- 避免数据覆盖:必须用独立数组存储三个时间步的场,防止计算过程中覆盖需要的历史值
- 启动步必要性:蛙跳法需要两个初始时间步,因此必须先用一阶格式生成第一个时间步的场,否则无法启动迭代
内容的提问来源于stack exchange,提问作者louis Du
相关产品推荐
相关产品推荐

