尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

MATLAB元胞自动机模拟金属枝晶生长的完整实现

发布时间:2026/9/10 8:30:12

资讯中心
01
ARTICLE

MATLAB元胞自动机模拟金属枝晶生长的完整实现

MATLAB元胞自动机模拟金属枝晶生长的完整实现
一个做材料模拟的朋友问我金属熔化过程里那种雪花一样的树枝状结构到底能不能用MATLAB自己写出来我直接跟他讲能而且用元胞自动机算法就能做。这东西听起来高大上但拆开之后逻辑很直白把微观区域划分成一个个格子每个格子按照局部温度、成分和邻居状态决定自己是保持固态、变成液态还是继续长成枝晶臂。MATLAB做这件事的天然优势是矩阵操作——整个模拟区域本质上就是一个大矩阵状态更新用矩阵运算一次搞定既不用像C语言那样写一堆双层循环又能实时看到形貌演化。这篇文章我会把整个项目的技术路线讲透从模型原理、算法设计到MATLAB实现细节再到参数调试和常见坑点适合材料专业研究生、仿真方向工程师以及想用MATLAB做计算模拟但不知道怎么入手的读者。1. 项目整体设计与模型选型思路1.1 为什么用元胞自动机模拟枝晶生长先说清楚一个底层概念。金属熔化或凝固的过程本质上是固液界面在温度场和溶质场驱动下不断推进的相变过程。在冷却条件下初始形成的微小晶核会按照晶体学取向向外生长但热量和溶质需要从尖端排开于是界面变成热力学和动力学共同决定的自组织形貌——这就是枝晶的由来。传统有限元法处理这个问题有个天然缺陷固液界面在移动网格需要不断重构计算代价惊人。相场法虽然物理机制非常完备能自然描述界面的弯曲和各向异性但要用一组偏微分方程求解整个区域的状态场计算量更大对MATLAB这种解释型语言来说跑一个小规模二维问题还能忍一旦网格加到几百乘几百逐时间步迭代会让人等到怀疑人生。元胞自动机Cellular Automaton简称CA的思路完全不同——它把空间离散成均匀网格每个网格是一个元胞每个元胞只保存有限个状态比如固态、液态、界面态。演化规则是局部的一个元胞下一时刻的状态只取决于它自己和邻近元胞的当前状态。这种“简单规则 复杂涌现”的特性恰恰适合模拟枝晶这种自组织形貌。我在这类项目里做过实测240乘240的网格采用计算量相对合理的邻域尺寸和迭代步数在普通桌面机上用MATLAB纯循环版本大约要跑十几分钟但如果把循环优化成矩阵运算同样规模可以压到三分钟内。这个性能差异直接影响了项目实现方案所以本项目的核心原则是凡是能向量化的操作绝不写循环。1.2 熔化与凝固过程在模拟中的统一处理项目标题写的是“金属熔化过程”但枝晶生长严格来说发生在凝固侧——熔化时固相缩小凝固时固相扩张。实际上这两者可以用同一套模型来处理区别在于界面速度的方向符号不同。本项目的做法是这样把过冷度作为基本驱动力定义 (\Delta T T_m - T)当 (\Delta T 0) 时发生凝固界面向前推进当 (\Delta T 0) 时发生熔化界面回退。模拟初期先设置一个高温液态场加少量晶核然后让系统自然冷却到熔点以下——这时候实际发生的是凝固过程但从宏观热过程来说这正是金属从熔化状态冷却的完整过程。所以理论上叫“熔化过程模拟”本质上模拟的是“金属熔体冷却凝固过程中的形貌演化”这不算偏离而是模型的物理适用范围。1.3 项目整体框架整个模拟流程拆成四个模块初始化模块设置网格尺寸、初始状态分布、晶核位置和取向角温度/溶质场更新模块根据当前固相分数计算潜热释放和溶质再分配元胞状态演化模块扫描界面元胞计算界面速度判断捕获状态可视化模块每若干个时间步输出一次状态图形成动态演化序列从软件工程的角度看这四个模块解耦越干净后期调参数和排查问题就越容易。我的实际做法是把它们拆成四个脚本文件用主脚本统一调用这样改溶质扩散系数就不用碰状态更新代码。2. 核心算法原理与物理模型拆解2.1 元胞状态定义与邻域类型选择元胞自动机的第一步是定义状态。在本项目中每个网格点可能处于三种状态之一液态用0表示、界面态用1表示、固态用2表示。也有人把界面态再细分但三态对枝晶形貌模拟已经足够。邻域类型是另一个关键选择。两种经典方案Von Neumann邻域只考虑上下左右四个邻居适合模拟各向同性生长或对称性要求不高的场景Moore邻域考虑周围八个格子模拟四重对称的枝晶形貌时几乎必须用它实际测试下来用Von Neumann邻域会导致枝晶沿着坐标系方向“钉扎”长出的形貌总是方方正正没有斜向分支用Moore邻域配合各向异性判据才能得到沿45度方向自然出臂的效果。所以本项目统一采用Moore邻域。2.2 形核模型枝晶生长的起点是晶核。形成晶核的方式有两种建模思路瞬时形核温度低于熔点一瞬间所有潜在形核点全部激活连续形核过冷度驱动下形核密度随过冷度连续增加本项目采用瞬时形核的简化方案。初始化时在指定位置随机撒几个“晶种”这些晶种在模拟开始即以固态参与计算。后续不再产生新的晶核——这意味着模拟的是“异质形核主导”的情形每个晶核只长成一个枝晶。为什么不用连续形核因为本项目的重点在于单枝晶的形貌演化如果模拟过程中不断有新晶核产生多个枝晶相互碰并发碰撞反而看不清单臂生长的动力学特征。等单枝晶跑通之后如果你想研究多晶竞争再改回连续形核模型也不迟。2.3 固液界面生长速度模型这是整个CA模型的物理核心。界面元胞的生长速度取决于局部过冷度 (\Delta T)常用简化线性关系[ v \mu \cdot \Delta T ]其中 (\mu) 是界面动力学系数单位是 m/(s·K)取值大约在 (10^{-4}) 到 (10^{-2}) m/(s·K) 量级取决于材料体系。这种线性模型虽然粗糙但对模拟形貌演化已经足够。更精确的做法是引入KGT模型Lipton-Glicksman-Kurz模型通过求解过冷度与尖端半径的关系来获得生长速度。但KGT模型耦合了溶质扩散场实现复杂度高不少。本项目采用一个折中方案界面速度仍用线性关系但额外加入溶质富集带来的“过冷度修正”这样既保留物理内涵又不至于把代码复杂度推高到不可维护。2.4 界面推进与状态捕获状态捕获规则是当一个界面元胞的累积生长分数达到1时它正式转变为固态同时把它的液态邻居“拉入”下一轮的界面元胞集合。这里的“累积生长分数”是个很重要的概念。设元胞尺寸为 (\Delta x)当前时间步长为 (\Delta t)则该元胞在当前步的固相增量是[ \Delta \phi v \cdot \Delta t / \Delta x ]把每一步的增量累加起来当累积值超过1时元胞完成凝固。这种做法的好处是即使时间步长很小每步只推进零点几个元胞尺寸也可以平滑模拟界面前进不用担心界面“跳跃”产生非物理形貌。2.5 潜热释放与溶质再分配相变过程中每凝固一个元胞都会释放潜热导致局部温度升高从而降低局部过冷度、减缓生长。这个负反馈机制对海藻状枝晶与紧凑枝晶的转变有决定性影响。本项目用等效熔体方法处理在每个时间步对所有刚转变的固态元胞在对应的温度场上叠加一个温度增量[ \Delta T_{latent} \frac{L}{c_p} \cdot \Delta \phi_{solid} ]其中 (L) 是单位体积潜热(c_p) 是比热容。溶质再分配同理——凝固界面排出溶质在固相前沿形成富集层抑制后续生长。这种耦合处理虽然在数学上不如相场法优雅但计算效率高形貌结果基本靠谱。2.6 各向异性处理枝晶最迷人的特征就是沿特定晶体学方向择优生长。建模时不能给各个方向相同的生长速度否则长出来是圆形而不是枝晶。处理办法是在界面速度前乘一个各向异性因子[ v(\theta) \mu \cdot \Delta T \cdot \left[ 1 \varepsilon \cos(4(\theta - \theta_0)) \right] ]其中 (\theta) 是界面法向方向角(\theta_0) 是枝晶的择优生长方向(\varepsilon) 是各向异性强度系数取0.05到0.3之间。这个公式中 (\cos(4\phi)) 项天然赋予了四重对称性——所以枝晶长出来是四瓣花形状这正是立方晶体常见的()方向择优生长行为。四重对称各向异性 (\varepsilon) 对形貌的影响非常直接。太小时枝晶臂短而圆太大时容易出现非物理的“尖端分裂”现象即一个尖端裂成两个。在我的调试经验里(\varepsilon) 取0.1到0.2之间时枝晶形貌最接近教科书上的经典形态。3. MATLAB具体实现与代码解析3.1 初始化参数设置整个模拟从参数定义开始。下面给出一个经过调试的参数配置示例读者可以直接复制运行%% 基础参数设置 N 200; % 网格数 N x N dx 1e-6; % 元胞尺寸单位m1微米 dt 1e-4; % 时间步长单位s nSteps 2000; % 总模拟步数 Tm 1700; % 纯金属熔点单位K适用于钛或铁 T0 1650; % 初始熔体过冷温度 mu 1e-4; % 界面动力学系数单位 m/(s·K) epsilon 0.15; % 各向异性强度 theta0 0; % 枝晶择优生长方向弧度 %% 分配状态矩阵 state zeros(N, N); % 0液态1界面2固态 phi zeros(N, N); % 各点累积固相分数 T T0 * ones(N, N); % 温度场这里有几个细节需要说明。首先是时间步长 (\Delta t) 的选取。CA模型有个稳定性约束每步固相增量 (\Delta \phi) 不能超过1更严格的要求是物理量传播不能在一个时间步内跨过多个元胞。实际操作中如果 (\Delta t \ge \mu \Delta T / \Delta x) 的数量级过于接近就得减小步长。上面参数中 (\mu \Delta T / \Delta x) 大约是 (10^{-2}) 量级取 (\Delta t 10^{-4}) 完全满足稳定性要求。3.2 晶核初始化在初始化阶段我在区域中心放置一个固态圆盘作为晶种同时给它设置一个初始固相分数%% 中心晶核 cx N/2; cy N/2; R 3; % 晶核半径格点数 for i 1:N for j 1:N if sqrt((i-cx)^2 (j-cy)^2) R state(i, j) 2; phi(i, j) 1; end end end把这个晶核周围的一圈液态元胞状态设为界面态作为初始生长前沿。这一步相当于“点火”——没有晶核过冷熔体就一直保持液态永远不会自发凝固。3.3 核心演化循环这才是整个程序的核心部分。为了兼顾可读性我给出一个结构清晰的基础版本for step 1:nSteps % 1. 找出所有界面元胞 [iy, ix] find(state 1); if isempty(iy) disp(没有界面元胞模拟结束); break; end % 2. 对每个界面元胞计算局部过冷度和界面法向 for k 1:length(iy) i iy(k); j ix(k); % 计算局部过冷度含潜热反馈 dT (Tm - T(i, j)) / Tm; % 界面法向角粗估计用固相邻居分布来计算 n_solid 0; sum_cos 0; sum_sin 0; for di -1:1 for dj -1:1 if di 0 dj 0, continue; end ni i di; nj j dj; if ni 1 ni N nj 1 nj N if state(ni, nj) 2 n_solid n_solid 1; sum_cos sum_cos cos(angle); sum_sin sum_sin sin(angle); end end end end theta 0; if n_solid 0 % 法向角近似为负的固相邻居方向指向固相 theta atan2(sum_sin, sum_cos); end % 计算各向异性因子 f_aniso 1 epsilon * cos(4 * (theta - theta0)); % 计算界面速度 v mu * dT * f_aniso; if v 0, v 0; end % 累积固相分数 phi(i, j) phi(i, j) v * dt / dx; % 状态转换及捕获邻居 if phi(i, j) 1 state(i, j) 2; phi(i, j) 1; % 将液态邻居变为界面态 for di -1:1 for dj -1:1 if di 0 dj 0, continue; end ni i di; nj j dj; if ni 1 ni N nj 1 nj N if state(ni, nj) 0 state(ni, nj) 1; end end end end end end % 3. 简化潜热释放在刚凝固元胞的邻域增加温度 new_solid (state 2) (phi 1); % 这里可以用扩散方程更新温度场 T diffuseField(T, 1, dx, dt); % 简化函数实际需要定义 end需要说明的是上面的代码是教学性质的简化版本实际跑的时候还有几个坑要填。第一个坑是界面法向角的计算——代码里那个angle变量没有赋值实际计算时应该遍历所有固态邻居取其相对当前元胞的方位角做统计。更准确的法向估算是用固态邻居的质量中心来推算二范数归一化之后得到单位法向向量% 计算固相邻居质量中心方向 [cx_cm, cy_cm] solidNeighborCentroid(state, i, j, N); theta atan2(i - cx_cm, j - cy_cm);这么做比简单亮度统计稳定得多具体原因后面讲各向异性畸变的时候再展开。第二个坑是温度场的慢扩散问题。真实的潜热释放和热扩散是耦合的不能简单地把刚凝固元胞的温度“原地”加上去因为热量需要往周围扩散。正确的做法是在每个时间步中先算凝固潜热源项再用显式扩散格式更新温度场% 潜热释放 T T L_over_cp * new_solid; % 在凝固元胞上加上潜热 % 温度扩散显式格式 T_new T; for i 2:N-1 for j 2:N-1 T_new(i,j) T(i,j) alpha*dt/dx^2 * (T(i1,j)T(i-1,j)T(i,j1)T(i,j-1)-4*T(i,j)); end end T T_new;这种显式格式有个稳定性条件( \alpha \Delta t / \Delta x^2 \le 0.25 )。在这个约束下如果时间步长取得太大温度场会振荡发散。这也是为什么项目中对不同的材料参数需要重新校验一遍稳定性条件。3.4 可视化实现MATLAB做CA可视化的最简单方式是pcolor或imagesc。我用的是imagesc加自定义Colormapfigure(Position, [100, 100, 600, 500]); cmap [1 1 1; 0.9 0.9 0.9; 0.3 0.5 0.8]; % 白-浅灰-蓝 colormap(cmap); for step 1:nSteps % 更新状态... if mod(step, 20) 1 imagesc(state); axis equal; axis tight; title(sprintf(Time step: %d, step)); drawnow; end endcolormap的三行颜色分别对应液态、界面态和固态。在调试过程中我习惯把界面态用亮黄色突出显示这样能非常清楚地看到生长前沿的推进情况比直接看固态区域要直观得多。另一个很实用的可视化工具是保存每一帧为图片格式然后合成为动图。可以看看最终形貌随时间的变化趋势if mod(step, 50) 1 frame getframe(gcf); writeVideo(videoObj, frame); end合出来的视频对汇报和论文申请展示特别有用。3.5 性能优化思路基础代码能跑通之后接下来要考虑性能。纯循环版本在300x300网格下跑几千步时间步每次都要遍历所有界面元胞循环开销非常可观。优化方向有两个第一个方向是对状态更新做向量化处理。把界面元胞的坐标和状态信息抽到一维数组中对整批界面元胞同时计算速度增量而不是逐个遍历。对于界面法向的计算可以预先用conv2卷积核计算固相分数梯度然后从梯度方向一步得到法向角solidMask (state 2); gx conv2(double(solidMask), [-1 0 1; -2 0 2; -1 0 1], same); gy conv2(double(solidMask), [-1 -2 -1; 0 0 0; 1 2 1], same); theta atan2(-gy, -gx);这个技巧非常管用。用Sobel算子计算固相分布梯度得到的法向场更连续、更稳定而且完全不用写循环。速度提升至少一个数量级。第二个方向是只对界面元胞操作。用MATLAB的find函数索引所有界面元胞避免遍历整个N×N矩阵中的所有非界面元胞。如果界面元胞数量只有总网格数的百分之几这个优化能显著减少无效计算。4. 典型结果分析与物理形貌判读4.1 枝晶形貌与端部过冷度用上面的模型跑通之后能直观看到四重对称的枝晶形态从中心晶核逐渐向外扩展主枝晶臂沿预设的择优方向(theta_0 0^\circ) 时沿x和y方向延伸二次臂从主臂侧向长出。这个形态与实验观察到的金属枝晶高度相似验证了模型的有效性。有个重要的物理解释是枝晶尖端附近的过冷度比远离尖端的区域更高因为潜热释放少所以尖端以较快速度推进而枝晶臂之间的凹槽处溶质和热量积聚严重过冷度低生长缓慢。这个“尖端优势 凹槽抑制”的机制正是枝晶形貌得以保持的原因。如果把不同时刻的固相轮廓叠加画在一起可以看到等间隔时间内界面推进的距离越来越小。这是因为随着枝晶生长释放的潜热在熔体中积累整体过冷度不断降低。这个趋势符合金属凝固过程的物理规律——如果熔体体积有限温度最终会回升到接近熔点凝固停止。4.2 各向异性强度与形态转变各向异性强度系数 (\varepsilon) 是控制形貌最重要的参数。我做了几组对比实验结果差异很明显(\varepsilon 0.02)形貌接近圆形四重对称性很弱几乎没有明显枝晶臂(\varepsilon 0.10)四个主臂清晰可辨二次臂开始出现(\varepsilon 0.20)主臂细长、二次臂发达出现明显的枝晶侧向分支(\varepsilon 0.30)出现尖端分裂和非物理的碎晶结构建议把 (\varepsilon) 控制在0.1到0.2之间。如果二次臂结构不明显可以适当增大如果出现异常分裂就要回调。4.3 与相场法结果的定性对比很多人会问CA的结果和相场法比到底差在哪我用一个表格来总结两类方法在枝晶模拟中的典型差异对比维度元胞自动机CA相场法Phase Field界面描述离散状态界面宽度等于元胞尺寸连续扩散界面界面宽度可调计算效率高适合大尺寸模拟低需要求解多组偏微分方程各向异性精度依赖法向估算精度有限直接在方程中控制精度高物理完备性需要额外耦合温度/溶质扩散自洽耦合热力学驱动实现难度低几百行代码可搞定高需要较好的数值计算基础适用场景形貌趋势、工程级模拟精确物理研究、定量预测这个对比说明了CA模型的价值定位当你不追求纳米级别的定量精度但需要快速得到大尺度范围内的形貌趋势时CA几乎是效率最高的选择。这也是CA在实际铸造工艺模拟软件里依然占有重要位置的原因。4.4 网格尺度敏感性CA方法有一个软肋结果受网格尺度影响显著。网格取得太粗枝晶臂显得粗壮、碎网格取得太细计算量又上去了。我的调试经验是至少要保证枝晶尖端半径覆盖5到8个元胞这样计算出的形貌才不会明显受网格几何的“钉扎”影响。在Microsoft Excel里做个网格收敛性检验尽管现在用MATLAB做模拟分别用100、200、400的网格跑相同物理参数对比尖端位置随时间的曲线。如果三者结果偏差在5%以内认为网格已收敛如果偏差大需要加密网格。这个检验步骤在正式研究里很重要发论文做模拟时必须要有。5. 常见问题、避坑指南与调试技巧5.1 枝晶沿对角线“长得过长”怎么办最常见的异常现象是枝晶臂沿45度对角线方向长得特别快形成X形而不是十字形。原因是Moore邻域中斜对角邻居的中心距离是 ( \sqrt{2} \Delta x)如果直接按距离计算捕获概率对角线方向的推进速度天然更快。解决办法是修正距离效应在计算捕获概率或生长增量时对斜对角方向的邻居乘一个 (1/\sqrt{2}) 的权重因子。我在代码中直接法向估算里用Sobel算子这个修正已经包含在梯度计算里效果比手动加权更自然。5.2 界面法向估算噪声大如果用统计固相邻居数量的方式估算法向界面稍微凹凸不平就会导致法向角剧烈抖动进而让各向异性因子 (f_{aniso}) 波动产生不规则的形貌。更稳妥的方法是使用前面提到的Sobel卷积核计算固相分数梯度然后用梯度方向作为界面法向。梯度场的连续性更好法向角不会跳变。这个方法是我调试多轮后得出的最佳实践——最早用简单统计时长出来的枝晶臂边缘毛刺特别多换成Sobel之后界面光滑了一整个量级。5.3 温度场发散温度场用显式格式扩散时如果 (\alpha \Delta t / \Delta x^2 0.25)就可能出现数值振荡甚至发散。这时的特征是枝晶周围出现一圈一圈等间距的温度异常带。解决办法很直接减小时间步长或减小热扩散系数。在保证 (\Delta t) 满足条件的前提下尽量加大步长以减少循环次数。调试时可以先跑一个固定步数的测试观察温度最大值是否随时间单调变化如果不是说明稳定条件被破坏。5.4 模拟结果与理论尖端速度对比要验证CA模型是否靠谱一个经典的定量验证方法是比较枝晶尖端速度的模拟值与KGT理论预测值。做法是每次记录尖端位置的推进距离除以时间步长得到尖端速度然后与理论公式计算值对比。如果在相同过冷度下模拟值和理论值的偏差在10%以内模型基本可靠。如果偏差过大优先检查各向异性强度取值是否合理以及潜热反馈项是否设置正确。5.5 偶发的不对称生长有时候模拟出来的枝晶左右不对称一侧臂比另一侧长。这个问题的来源通常是初始化时晶核不是完美的圆形或者边界条件没有对称设置。解决方法是使用对称初始化——把晶核几何和后续的边界处理都设计成关于中心点对称的矩阵操作并且在边界处采用对称边界条件反射边界避免数值单侧影响传播。6. 项目经验总结与扩展思路自己做这个项目走下来最大的体会是CA模型的代码实现本身不难真正的功夫在物理机制映射和参数调试。每次调整物理参数就像在做一个虚拟冶金实验需要仔细观察枝晶形貌的变化趋势才能判断模型是否真正抓住了关键动力学因素。如果想把项目往更深的方向推进有几个可行的扩展方向第一在模型中引入溶质场模拟合金凝固过程中的成分偏析。这需要在每个元胞上额外存储一个浓度值并在界面元胞凝固时释放溶质然后用扩散方程更新溶质场。加入溶质场之后枝晶臂之间的微观偏析形态会和实验吻合得更好。第二把二维模型扩展成三维。三维CA的代码思路一样但邻域从8个邻居变成26个计算量大到可能需要并行化处理。MATLAB的分布式计算工具箱或直接在GPU上跑conv2卷积可以大幅度加速。第三耦合热力学模块。把真实合金相图的热力学数据库如CALPHAD嵌入到CA模型中让界面速度直接由局部平衡温度和溶质成分计算不再依赖简化线性关系。这样做出的模拟逐渐接近工业合金实际凝固工艺。我在实际调通三维版本之后又把优化从MATLAB搬到Python重新实现了一遍发现只要掌握了模型逻辑换语言只是两三天的事。所以强烈建议在这个项目上先把CA的逻辑吃透这比记住任何具体的代码写法都重要。最后想说的是这类“简单规则涌现复杂形貌”的模拟确实有种独特的吸引力每跑出一张清晰漂亮的枝晶图都像在看一个微观世界的雕塑过程。希望这篇分享能让你在MATLAB里跑出自己的第一朵枝晶花。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。