如何实现meshgrid矩阵所有点动画?为何扩散模型代码仅显示中心点
点源扩散模型动画仅显示中心点的问题解决
问题
代码尝试制作点源扩散的高斯分布动画,但运行后仅能看到中心点的变化,无法展示整个Z矩阵的扩散效果,预期是全域扩散的高斯云动画。
原因分析
pcolormesh数组更新错误:cax.set_array()需要传入扁平化的1D数组,直接传入2D的Z会导致数据不匹配,网格无法正确更新。- 颜色范围未动态调整:初始仅设置
vmin=0但未动态更新vmax,随着扩散进行整体浓度降低,固定的颜色范围会让边缘低浓度区域无法显示,视觉上仅呈现中心点。 - 初始时间步的高斯函数方差极小:前几帧
frame_num*dt数值太小,导致高斯分布的方差趋近于0,只有中心点附近有非零值,视觉上仅显示中心点。
修复方案
- 将
Z扁平化后传入set_array,即cax.set_array(Z.ravel()) - 动态调整颜色范围,确保每帧的浓度变化都能被正确显示
- 给时间参数添加极小值,避免初期方差过小的问题
修复后的完整代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # Parameters Dx = 0.00002 # x方向扩散系数 (cm²/s) Dy = 0.00001 # y方向扩散系数 (cm²/s) M = 1000 # 初始质量 (g) L = 40 # 容器半长 (cm) dt = 0.01 # 时间步长 (s) T = 20.0 # 总模拟时间 (s) num_frames = int(T / dt) epsilon = 1e-6 # 避免时间为0的极小值 x = np.arange(-L, L + 0.25, 0.25) y = np.arange(-L, L + 0.25, 0.25) X, Y = np.meshgrid(x, y) def gaussian_circle(X, Y, frame_num): t = frame_num * dt + epsilon # 添加epsilon避免t=0 c = M * np.exp(-((X ** 2)/(4 * Dx * t) + (Y ** 2)/(4 * Dy * t))) / \ ((4 * np.pi * Dx * t) ** 0.5 * (4 * np.pi * Dy * t) ** 0.5) / 10**6 return c # 初始化绘图 Z = gaussian_circle(X, Y, 1) fig, ax = plt.subplots() cax = ax.pcolormesh(X, Y, Z, vmin=0) cbar = fig.colorbar(cax) cbar.set_label('浓度 (ppm)') ax.set_xlabel('x (cm)') ax.set_ylabel('y (cm)') def animate(frame): next_frame = frame + 1 Z = gaussian_circle(X, Y, next_frame) # 传入扁平化数组更新网格 cax.set_array(Z.ravel()) # 动态调整颜色上限,确保扩散效果可见 cax.set_clim(vmin=0, vmax=np.max(Z)) ax.set_title(f'扩散模拟 t = {next_frame * dt:.2f} s') return cax, # 创建动画 animation = FuncAnimation(fig, animate, frames=num_frames, interval=10) plt.show()
内容的提问来源于stack exchange,提问作者Payman
相关产品推荐
相关产品推荐

