Jupyter中波传播时间演化动画无法正常显示的问题
有限差分法波传播动画在Jupyter Notebook中无法正常显示
问题描述
我尝试通过有限差分法(Finite Difference Method)可视化波随时间的传播过程,但在最新版Jupyter Notebook中运行代码后无任何显示。仅使用%matplotlib inline时能看到初始图像,但无法更新动画。
运行代码
%matplotlib widget import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from matplotlib import gridspec from mpl_toolkits.axes_grid1 import make_axes_locatable import warnings warnings.filterwarnings("ignore") def run_2d_wave_animation(): # ----- 模拟参数 ----- nx = 200 # 为了动画流畅先减小尺寸,后续可增大 nz = nx dx = dz = 1 c0 = 580 isx = isz = 100 irx = irz = 150 nt = 502 dt = 0.0010 f0 = 25 t0 = 2. / f0 op = 3 # ----- 稳定性检查 ----- eps = c0 * dt / dx if eps > 1: print('CFL条件不满足。') else: print('CFL条件符合要求。') # ----- 网格与源项 ----- x = dx * np.arange(nx) z = dz * np.arange(nz) time = dt * np.arange(nt) c = c0 * np.ones((nz, nx)) p = np.zeros((nz, nx)) pnew = np.zeros((nz, nx)) pold = np.zeros((nz, nx)) d2px = np.zeros((nz, nx)) d2pz = np.zeros((nz, nx)) seis = np.zeros(nt) src = -8 * (time - t0) * f0 * (np.exp(-1.0 * (4 * f0)**2 * (time - t0)**2)) # ----- 解析格林函数 ----- G = np.zeros(nt) r = np.sqrt((x[isx] - x[irx])**2 + (z[isz] - z[irz])**2) for it in range(nt): if (time[it] - r / c0) >= 0: G[it] = (1 / (2 * np.pi * c0**2)) * (1 / np.sqrt((time[it]**2) - (r**2 / c0**2))) Gc = np.convolve(G, src * dt)[:nt] # ----- 绘图设置 ----- fig = plt.figure(figsize=(10, 6)) gs = gridspec.GridSpec(1, 2, width_ratios=[1, 1], wspace=0.3) # --- 左面板:波场 --- ax1 = plt.subplot(gs[0]) lim = np.max(np.abs(Gc)) im = ax1.imshow(p, vmin=-lim, vmax=lim, cmap='RdBu', interpolation='nearest') divider = make_axes_locatable(ax1) cax = divider.append_axes("right", size="5%", pad=0.05) fig.colorbar(im, cax=cax) ax1.plot(isx, isz, 'r*', markersize=10) ax1.plot(irx, irz, 'k^', markersize=8) ax1.set_title("波场 t = 0") ax1.set_xlim(0, nx) ax1.set_ylim(0, nz) # --- 右面板:地震记录 --- ax2 = plt.subplot(gs[1]) line_fd, = ax2.plot(time, seis, 'b-', label='数值解(FD)') line_analytic, = ax2.plot(time, Gc, 'r--', label='解析解') marker, = ax2.plot([0], [0], 'ko', markersize=6) ax2.set_xlim(time[0], time[-1]) ax2.set_ylim(min(Gc.min(), -1e-6), max(Gc.max(), 1e-6)) ax2.set_title('地震记录') ax2.set_xlabel('时间 (s)') ax2.set_ylabel('振幅') ax2.legend(loc='upper right') # ----- 动画更新函数 ----- def update(it): nonlocal p, pold, pnew, seis if op == 3: d2px[1:-1, :] = (p[2:, :] - 2 * p[1:-1, :] + p[0:-2, :]) / dx**2 d2pz[:, 1:-1] = (p[:, 2:] - 2 * p[:, 1:-1] + p[:, 0:-2, :]) / dz**2 else: raise NotImplementedError("本示例仅支持3点有限差分格式") pnew = 2 * p - pold + (c**2) * dt**2 * (d2px + d2pz) pnew[isz, isx] += src[it] / (dx * dz) * dt**2 # 软边界条件(可选) pnew[0, :] = pnew[1, :] pnew[-1, :] = pnew[-2, :] pnew[:, 0] = pnew[:, 1] pnew[:, -1] = pnew[:, -2] pold, p = p, pnew seis[it] = p[irz, irx] im.set_data(p) # 对imshow使用set_data更新数据 ax1.set_title(f"波场 t = {it*dt:.3f}s") line_fd.set_ydata(seis) marker.set_data(time[it], seis[it]) fig.canvas.draw_idle() # 强制widget后端重绘 return im, line_fd, marker ani = FuncAnimation(fig, update, frames=nt, interval=10, blit=False, repeat=False) plt.show() return ani ani = run_2d_wave_animation()
解决方法
针对Jupyter Notebook中%matplotlib widget动画不显示的问题,可以尝试以下方案:
- 安装依赖库:运行
pip install ipympl,这是matplotlib widget后端的必需依赖,新版Jupyter需手动安装。 - 启用widget扩展:运行
jupyter nbextension enable --py widgetsnbextension,确保扩展正常加载。 - 调整动画参数:将
FuncAnimation的interval参数调至30左右,避免刷新过快导致渲染异常;保持blit=False,因为widget后端对blitting支持有限。 - 保存本地动画:如果widget后端仍无法显示,可将动画保存为MP4或GIF,使用
ani.save('wave_propagation.mp4', writer='ffmpeg')(需提前安装ffmpeg),通过本地播放器查看。
内容的提问来源于stack exchange,提问作者Gaurav Maurya
相关产品推荐
相关产品推荐

