
简介面向生态数学与数值模拟研究者的MATLAB源码项目用于二维捕食与被捕食模型的数值模拟可生成经典的图灵斑状图。资源适合新手及有一定开发经验的人员既能帮助理解反应扩散系统中空间模式的形成机理也可作为非线性动力学教学演示的参考实现。压缩包内共1个m文件文件体量仅1KB核心算法紧凑便于快速阅读与修改运行。目前已有625人学习下载经过作者测试校正下载后可直接运行若遇到环境配置等问题可联系作者获得指导。通过研读源码读者可掌握捕食与被捕食模型的空间离散化、数值迭代与可视化实现思路进而扩展到其他图灵斑图案例。整体上是一份小巧实用、上手门槛低的MATLAB模拟示例。1. 二维捕食-被捕食模型的图灵斑状图不是“随机图”而是扩散把稳态逼出来的把捕食者和被捕食者放在同一个二维平面上并且让它们各自做随机扩散种群分布并不会一直停留在均匀状态在某些扩散系数比、种群增长率和捕食强度组合下空间中的小扰动会被特定波段的频率放大最终形成斑点、条纹或迷宫状图案。这就是图灵在 1952 年提出的“扩散致失稳”没有扩散时均匀稳态是稳定的引入扩散后反而变得不稳定。这句话听起来反直觉却是反应扩散系统最值得模拟的地方。MATLAB 里要复现一张图灵斑状图真正的工作量不在pcolor或imagesc而在三件事把捕食-被捕食模型写成反应扩散方程组找一组满足图灵不稳定条件的参数用足够稳定的二维数值格式把方程积分到饱和。本文用的模型带捕食者密度制约和被捕食者 Allee 效应扩散系数比取 10:1能够稳定长出有特征波长的斑图。下面从方程条件一路推到可直接运行的 MATLAB 代码再讲调参和验证。2. 模型方程与图灵失稳的数学条件2.1 捕食-被捕食反应扩散方程的构造常见捕食-被捕食模型直接用 Lotka-Volterra 项但要产生图灵斑图均匀稳态必须先在没有扩散时稳定。经典线性功能反应的 Jacobian 在稳态处往往出现零元素很难同时满足稳定和失稳条件。这里采用更接近生态实际的一种形式设u(x,y,t)为被捕食者密度v(x,y,t)为捕食者密度∂u/∂t D1·∇²u u(1-u)(u-α) - β·u·v ∂v/∂t D2·∇²v v(γ·u - δ - μ·v)u(1-u)(u-α)是被捕食者的自身增长率带 Allee 效应当u很小时增长为负在uα附近存在一个临界密度低于这个密度种群会衰退β·u·v是捕食压力。捕食者项v(γ·u - δ - μ·v)含义更直接γ·u是捕食收益δ是基础死亡率μ·v是捕食者内部密度制约。加入μ·v可以把均匀稳态的 Jacobian 中g_v项变成负数这是经典的线性 Lotka-Volterra 做不到的。选这个模型还有一个好处所有参数都有明确的生态学解释调参时可以对着现象调整。比如想看到更多的小斑点就降低捕食者扩散系数想抑制高波数噪声就提高μ。D1是被捕食者扩散系数D2是捕食者扩散系数二维拉普拉斯算子∇²是空间扩散项。2.2 线性稳定性分析与图灵条件推导假设存在均匀稳态(u0, v0)满足所有空间导数为零即f(u0,v0)0g(u0,v0)0。在它上面加一个微小扰动并且把扰动展开成平面波exp(i·k·x λ·t)。线性化后的 Jacobian 为A(k) [ f_u - D1·k² , f_v ] [ g_u , g_v - D2·k² ]其中f_u, f_v, g_u, g_v都是稳态处偏导数k² kx² ky²是空间波数的模平方。无扩散时k0稳态稳定需要两个条件迹为负行列式为正tr f_u g_v 0 det f_u·g_v - f_v·g_u 0这是图灵斑图的第一层门槛没有扩散时必须稳定。加上扩散后特征值是否变正取决于矩阵A(k)的行列式。对二维系统最终可以得到一个波数范围条件φ(k²) D1·D2·k⁴ - (D2·f_u D1·g_v)·k² det 0φ(k²)是关于k²的开口向上的二次函数。如果它有一段小于零说明存在某些波数会被放大。二次函数的最小值出现在k0² (D2·f_u D1·g_v) / (2·D1·D2)所以图灵不稳定必须满足D2·f_u D1·g_v 2·sqrt(D1·D2·det)这解释了为什么捕食者扩散系数通常要远大于被捕食者要让D2·f_u这个正项压倒D1·g_v的负贡献。u相当于激活子v相当于抑制子图灵斑图的经典图像就是“激活子不太动抑制子跑得快”。2.3 一组能直接出图的参数与理论波长取一组满足上述条件的参数参数值含义α0.1Allee 阈值β1.4捕食强度γ1.0捕食转化率δ0.1捕食者死亡率μ2.0捕食者密度制约D11.0被捕食者扩散系数D210.0捕食者扩散系数(u0, v0)(0.3, 0.1)均匀稳态密度把参数代入稳态方程可验证f(u0,v0)0, g(u0,v0)0。再代入偏导数公式f_u 0.15, f_v -0.42 g_u 0.10, g_v -0.20无扩散时tr -0.05 0det 0.012 0均匀稳态稳定。扩散项D2·f_u D1·g_v 1.5 - 0.2 1.3而2·sqrt(D1·D2·det) ≈ 0.693条件满足。对应主导波数k0 sqrt(1.3 / 20) ≈ 0.255 λ0 2π / k0 ≈ 24.6如果计算域边长取 100理论上会容纳约 4 个波长网格取 128×128每个波长有接近 31 个网格点分辨率足够。这就是后面 MATLAB 代码的基础。3. MATLAB 谱方法实现从随机扰动长成图灵斑状图3.1 为什么选 FFT 谱方法而不是一阶有限差分二维拉普拉斯算子在傅里叶空间里是对角矩阵。对周期性边界条件∇²的每个 Fourier 模式只乘一个-k²因此可以把偏微分方程的空间积分变成一个逐波数的乘子更新。相比传统显式有限差分FFT 谱方法的优势有两点第一没有差分格式的数值色散网格分辨率要求更低128×128 就可以看到光滑斑图第二扩散部分用exp(-D·k²·Δt)处理是精确的不受显式稳定性约束时间步长只要照顾反应项即可。常见的显式有限差分解法在D210, dx≈0.78时稳定条件要求Δt dx²/(2·D2) ≈ 0.03。虽然也能用但边界和网格各向异性经常让斑图边缘出现方块状伪影。FFT 谱方法不需要组装矩阵代码也短。代价是必须接受周期性边界条件不过图灵斑图研究本来就大量使用周期域。3.2 主程序二维图灵斑状图 MATLAB 完整代码下面的代码保存成turing_2d_predator_prey.m在 MATLAB 的当前目录直接运行即可。% turing_2d_predator_prey.m % 二维捕食-被捕食模型FFT 谱方法周期边界 clear; clc; close all; % 模型参数 alpha 0.1; beta 1.4; gamma 1.0; delta 0.1; mu 2.0; D1 1.0; D2 10.0; % 均匀稳态 u0 0.3; v0 0.1; % 空间网格边长100128x128 L 100; N 128; x linspace(0, L, N1); x(end) []; [X, Y] meshgrid(x, x); % 二维波数注意负频率排列顺序 fx (2*pi/L) * [0:N/2-1, -N/2:-1]; [Kx, Ky] meshgrid(fx, fx); K2 Kx.^2 Ky.^2; % 时间步长与总时长 dt 0.01; Tmax 400; steps ceil(Tmax / dt); % 初始条件稳态加小幅随机扰动 rng(7); U u0 0.02 * randn(N, N); V v0 0.02 * randn(N, N); for n 1:steps % 反应项全部矩阵运算 fU U.*(1-U).*(U-alpha) - beta*U.*V; gV V.*(gamma*U - delta - mu*V); % Lie 分裂反应步显式推进 dt扩散步精确乘子 Uhat fft2(U dt*fU) .* exp(-D1*K2*dt); Vhat fft2(V dt*gV) .* exp(-D2*K2*dt); U real(ifft2(Uhat)); V real(ifft2(Vhat)); % 密度保持非负防止非线性振荡 U max(U, 0); V max(V, 0); % 每500步画一次 if mod(n, 500) 0 subplot(1,2,1); pcolor(X, Y, U); shading interp; axis image; title(sprintf(Prey t%.0f, n*dt)); colorbar; subplot(1,2,2); pcolor(X, Y, V); shading interp; axis image; title(Predator); colorbar; drawnow; end end这段代码有几个值得强调的细节。fU和gV是反应项在物理空间的矩阵值不是标量U.*(1-U).*(U-alpha)会对每个网格点同时完成三次乘法。fft2(U dt*fU)先把反应项推进dt再乘exp(-D1*K2*dt)完成扩散。这个拆分称为 Lie 分裂是一阶时间精度但对反应扩散方程非常稳健。max(U,0)可以避免个别网格点因为随机扰动产生负密度后继续被非线性项放大。3.3 代码里两个需要改的关键参数dt的选择直接决定是否发散。反应项中最大特征值大约0.2dt0.01已经足够小。如果运行后发现出现 NaN优先把dt降到0.005同时把Tmax提高到500其他不用改。N的选择影响波长分辨率和速度。上面的理论波长约24.6在L100的域里有 4 个波长128×128 网格完全够用。如果想看更细的斑图边界可以把N改成 256但运行时间会变成约 4 倍。对初学者128×128 速度更快也更容易理解斑图背后的尺度关系。4. 调出清晰图灵斑状图的参数设置与 MATLAB 常见坑4.1 扩散系数比D2/D1 是图灵斑图的总开关图灵失稳最关键的一步是D2·f_u D1·g_v必须大于扩散加权后的几何均值。在本文参数下D2/D1 10是一个比较安全的值。如果缩小到 3:1D2·f_u D1·g_v 0.45 - 0.2 0.25小于0.693系统不会出现斑图如果放大到 20:1失稳波段变宽高波数模式也可能被激活最后容易看到细碎噪声和斑点混合的图案。扩散比 D2/D1表现建议2~4基本不出斑图检查是否满足图灵条件8~12稳定的斑点或条纹本文推荐范围15~30高频噪声增多斑图细碎适当增大 μ 或减小噪声D2/D1调好后尽量不要再动D1的绝对值因为它也会改变时间尺度。反应扩散系统的斑图波长由D1·D2的乘积和线性项共同决定所以只调比值会带来意想不到的尺度变化。4.2 初始扰动幅度和随机种子初始扰动要小但也不能太小。0.02 * randn(N,N)是比较常见的做法。扰动太小比如0.001系统需要更长时间才能越过线性放大阶段扰动太大比如0.1会让部分网格点直接变成负密度max(U,0)截断后可能引入额外的高频成分图案会被破坏。随机种子rng(7)决定具体的斑图布局。换一个种子斑点位置会变但主导波长应该大致不变。如果换了三个种子后得到的图案形状差别巨大比如一次全是点、一次全是条纹说明参数区处在“点-条纹共存”的临界区这是正常现象。如果想做稳定的点状斑图可以把μ从2.0提高到2.5条纹会更难存活。4.3 边界条件、网格数与时间步长的关系FFT 谱方法默认周期性边界条件所以斑图在边界处会首尾相接。如果模拟时发现边界上出现明显的“接缝”或不连续多半是因为x linspace(0,L,N1)时没有去掉最后一个点导致首尾重复。上面的代码里x(end)[]已经处理不要删掉。如果换成真实生态区域可能需要 no-flux 边界。常见做法是在离散余弦变换域里实现或者用pdepe处理一维问题。二维 no-flux 图灵斑图也可以做但代码复杂不少。我的建议是先跑通周期边界再根据应用场景决定是否换边界条件。网格数N推荐至少每波长 20 个点。本文L100, N128每波长约 31 个点如果把边长安 200建议N256。4.4 失败现象排查表现象可能原因处理办法一直均匀不出斑图参数不满足图灵条件计算D2·f_u D1·g_v是否大于2·sqrt(D1·D2·det)图案呈棋盘状彩色噪声dt太大或N太小把dt改成0.005N加到 256出现负密度或 NaN初值噪声过大降低randn幅度减小dt斑图出现后很快消失Tmax不足以饱和把Tmax提高到 600 或 800边界有亮线周期网格首尾重复检查linspace是否已去除最后一点表格里最有用的一行是第一条。很多人在 MATLAB 里把反应扩散方程写好但不出图问题不在代码而在参数。先用一小段脚本把稳态和几个偏导数值算出来再判断是否进入图灵失稳区间能省掉大量调试时间。5. 用功率谱验证是图灵斑图还是数值噪声5.1 从 U 的 FFT 读主导波长仿真结束后不能只看颜色花不花还要确认图案确实有一个特征波长。提取U的傅里叶功率谱找到能量最大的波数就能和理论值对比。接在上一段代码后面运行% 去掉均匀背景保留空间扰动 Uc U - mean(U(:)); F fft2(Uc); P abs(F).^2; P(1,1) 0; % 去掉零频 kMag sqrt(K2); [pmax, idx] max(P(:)); k_star kMag(idx); lambda_star 2*pi / k_star; fprintf(主导波数 k*%.3f主导波长 λ%.2f\n, ... k_star, lambda_star);P(1,1)0这一步很关键因为零频对应均匀背景功率几乎总是最大不减掉会掩盖真正的模式。k_star应该落在理论值0.255附近对应波长大约24.6。实际离散网格上结果可能是21~28之间这受波形非正弦影响属于正常。5.2 观察功率谱是否只有一个窄峰图灵斑图区别于随机纹理的另一个特征是波数峰窄。可以在仿真结束时画一维径向平均功率谱把kMag按区间分桶然后求每个桶的均值功率。如果只有一个明显峰说明是真正的图灵失稳。如果功率谱非常平坦说明现在看到的是数值噪声或初值里残留的随机场。用pcolor(X,Y,fftshift(P))可以看到二维功率谱中的亮环。出现圆环而不是单个点是因为波数的大小决定增益方向是各向同性的。亮环半径对应k_star环越细斑图越规则。5.3 更换随机种子确认形态稳定性改用rng(0)、rng(1)再跑一次观察最终的斑点位置和数量。真正的图灵不稳定性对随机种子不敏感每次的斑点具体位置会变但斑点的尺度、密度、形态类型基本一致。如果换一次种子图案就完全变成另一种类型说明当前参数处于不稳定边界。此时可以做一次简单的线性参数扫描保持其他参数不变把D2从 8 扫到 12记录每次的主导波长和斑块密度就能确定这个模型在这组参数下的“相图”。这一套验证做完就能确定眼前的斑状图来自扩散驱动失稳而不是幻觉。下次换参数时先用理论公式估计k0再对照功率谱峰值就不会被随机噪声骗过。本文还有配套的精品资源点击获取