相场模拟——枝晶生长(COMSOL模拟雪花形成)
一、介绍
1.1 物理含义
雪花是人们最常见的枝晶。枝晶生长是一种生长的不稳定现象,常起因于过冷的液体,或晶体的生长速度受限于溶质原子向固体表面的扩散速度。造成以上条件的原因,可以是液相中负的温度梯度,也可以是负的浓度梯度。在这种模式下,晶体倾向于在其棱角处优先生长,从而形成突触状结构。
这篇博文会介绍用相场模拟的方法,模拟雪花生长的过程。
1.2 相场模拟介绍
在相场法中,使用连续变量描述微观结构特征。这些变量有两种形式:代表物理性质的守恒变量,如原子浓度或材料密度;描述材料微观结构(包括晶粒和不同相)的非守恒序参数(order parameters)。这些连续变量的演化用自由能的函数表达,可以定义为一个PDE偏微分方程系统。该相场模型还可以与其他物理相耦合,例如力学或热传导。这些模型方程可以用多种方法求解,包括有限差分法、谱方法和有限元法。
相场PDE是各种变量的演化方程,是自由能泛函F的函数。
对于守恒变量(conserved variables),其满足Cahn-Hilliard方程:
其中ci是保守变量,Mi是相应的迁移率。
对于非保守量,其满足 Allen-Cahn方程:
ηj是序参量,Lj是序参数的迁移率。
自由能函数包括局部自由能,梯度自由能,以及系统的其它额外自由能(比如电势能,弹性势能等等)。可以用如下公式计算:
f_loc: local free energy density; f_gr: gradient energy density; Ed: additional sources of energy in the system, such as deformation or electrostatic energy.
二、枝晶生长模型
模型包含两个变量: 相场θ(r, t),温度场T(r, t)
θ = 0 表示液态;θ = 1 表示固态;
PDE:
其它方程:
三、COMSOL建模
1. 建立一个2D,两个变量的General Form PDE模型(自变量为theta, T),瞬态求解。
2. Global Definition-> Parameters
K 1.8 1.8
TAU 0.0003 3E-4
EPS 0.01 0.01
DELTA 0.02 0.02
ANGLE0 1.57 1.57
ANISO 6 6
ALPHA 0.9 0.9
GAMMA 10.0 10
TEQ 1.0 1
4. Model -> Definition -> Variables
epsilon EPS*(1+DELTA*cos(ANISO*(angle-ANGLE0)))
epsilonp -EPS*ANISO*DELTA*sin(ANISO*(angle-ANGLE0))
epsilon2 epsilon*epsilon
m ALPHA/pi*atan(GAMMA*(TEQ-T)) rad
angle if(abs(thetax)>eps,atan2(thetay,thetax)+pi*(atan2(thetay,thetax)<0),pi/2*((thetay>0)+3*(thetay<0))) rad
5. Geometry
建立一个关于原点对称的9×9矩形
6. PDE设置
初始值
7. Mesh
建立Mapped型网格,Maximum element size为0.1(可适当加密,0.06~0.08左右效果比较好)
8. Study求解时间为range(0,0.1,0.3)
导出的部分matlab代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | function out = model % % crystalGrowth.m % % Model exported on Jul 16 2023, 16:41 by COMSOL 6.0.0.318. import com.comsol.model.* import com.comsol.model.util.* model = ModelUtil. create ( 'Model' ); model.component. create ( 'comp1' , true); model.component( 'comp1' ).geom. create ( 'geom1' , 2); model.component( 'comp1' ). mesh . create ( 'mesh1' ); model.component( 'comp1' ).physics. create ( 'g' , 'GeneralFormPDE' , { 'theta' 'T' }); model.study. create ( 'std1' ); model.study( 'std1' ). create ( 'time' , 'Transient' ); model.study( 'std1' ).feature( 'time' ).setSolveFor( '/physics/g' , true); model.param. set ( 'K' , '1.8' ); model.param. set ( 'TAU' , '0.0003' ); model.param. set ( 'EPS' , '0.01' ); model.param. set ( 'DELTA' , '0.02' ); model.param. set ( 'ANGLE0' , '1.57' ); model.param. set ( 'ANISO' , '6' ); model.param. set ( 'ALPHA' , '0.9' ); model.param. set ( 'GAMMA' , '10.0' ); model.param. set ( 'TEQ' , '1.0' ); model.func. create ( 'step1' , 'Step' ); model.func( 'step1' ). set ( 'location' , 0.09); model.func( 'step1' ). set ( 'from' , 1); model.func( 'step1' ). set ( 'to' , 0); model.func( 'step1' ). set ( 'smooth' , 0.05); model.variable. create ( 'var1' ); model.variable. remove ( 'var1' ); model.component( 'comp1' ).variable. create ( 'var1' ); model.component( 'comp1' ).geom( 'geom1' ). run ; model.component( 'comp1' ).variable( 'var1' ). set ( 'epsilon' , 'EPS*(1+DELTA*cos(ANISO*(angle-ANGLE0)))' ); model.component( 'comp1' ).variable( 'var1' ). set ( 'epsilonp' , '-EPS*ANISO*DELTA*sin(ANISO*(angle-ANGLE0))' ); model.component( 'comp1' ).variable( 'var1' ). set ( 'epsilon2' , 'epsilon*epsilon' ); model.component( 'comp1' ).variable( 'var1' ). set ( 'm' , 'ALPHA/pi*atan(GAMMA*(TEQ-T))' ); model.component( 'comp1' ).variable( 'var1' ). set ( 'angle' , 'if(abs(thetax)>eps,atan2(thetay,thetax)+pi*(atan2(thetay,thetax)<0),pi/2*((thetay>0)+3*(thetay<0)))' ); model.component( 'comp1' ).geom( 'geom1' ). create ( 'r1' , 'Rectangle' ); model.component( 'comp1' ).geom( 'geom1' ).feature( 'r1' ). set ( 'size' , [9 9]); model.component( 'comp1' ).geom( 'geom1' ).runPre( 'fin' ); model.component( 'comp1' ).geom( 'geom1' ). run ; model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'Ga' , { '-thetax*epsilon2+epsilon*epsilonp*thetay' '-thetay' }, 0); model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'Ga' , { '-thetax*epsilon2+epsilon*epsilonp*thetay' '-thetay*epsilon2-epsilon*epsilonp*thetax' }, 0); model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'f' , 'd(epsilon2,x)*thetax+d(epsilon2,y)*thetay+theta*(1-theta)*(theta-0.5+m)' , 0); model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'f' , 0, 1); model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'da' , 'TAU' , 0); model.component( 'comp1' ).physics( 'g' ).feature( 'gfeq1' ).setIndex( 'da' , '-K' , 1); model.component( 'comp1' ).physics( 'g' ).feature( 'init1' ). set ( 'theta' , 'step1(x^2+y^2)' ); model.component( 'comp1' ). mesh ( 'mesh1' ). create ( 'size1' , 'Size' ); model.component( 'comp1' ). mesh ( 'mesh1' ).feature. remove ( 'size1' ); model.component( 'comp1' ). mesh ( 'mesh1' ). create ( 'map1' , 'Map' ); model.component( 'comp1' ). mesh ( 'mesh1' ).feature( 'size' ). set ( 'hmax' , 0.1); model.component( 'comp1' ). mesh ( 'mesh1' ).feature( 'size' ). set ( 'hmin' , '6.75e-4' ); model.component( 'comp1' ). mesh ( 'mesh1' ).feature( 'size' ). set ( 'hgrad' , 1.2); model.component( 'comp1' ). mesh ( 'mesh1' ).feature( 'size' ). set ( 'hcurve' , 0.25); model.component( 'comp1' ). mesh ( 'mesh1' ). run ; model.sol. create ( 'sol1' ); model.sol( 'sol1' ).study( 'std1' ); model.study( 'std1' ).feature( 'time' ). set ( 'notlistsolnum' , 1); model.study( 'std1' ).feature( 'time' ). set ( 'notsolnum' , 'auto' ); model.study( 'std1' ).feature( 'time' ). set ( 'listsolnum' , 1); model.study( 'std1' ).feature( 'time' ). set ( 'solnum' , 'auto' ); model.sol( 'sol1' ). create ( 'st1' , 'StudyStep' ); model.sol( 'sol1' ).feature( 'st1' ). set ( 'study' , 'std1' ); model.sol( 'sol1' ).feature( 'st1' ). set ( 'studystep' , 'time' ); model.sol( 'sol1' ). create ( 'v1' , 'Variables' ); model.sol( 'sol1' ).feature( 'v1' ). set ( 'control' , 'time' ); model.sol( 'sol1' ). create ( 't1' , 'Time' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'tlist' , 'range(0,0.1,1)' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'plot' , 'off' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'plotgroup' , 'Default' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'plotfreq' , 'tout' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'probesel' , 'all' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'probes' , {}); model.sol( 'sol1' ).feature( 't1' ). set ( 'probefreq' , 'tsteps' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'atolglobalvaluemethod' , 'factor' ); model.sol( 'sol1' ).feature( 't1' ). set ( 'endtimeinterpolation' , true); model.sol( 'sol1' ).feature( 't1' ). set ( 'control' , 'time' ); model.sol( 'sol1' ).feature( 't1' ). create ( 'fc1' , 'FullyCoupled' ); model.sol( 'sol1' ).feature( 't1' ).feature( 'fc1' ). set ( 'linsolver' , 'dDef' ); model.sol( 'sol1' ).feature( 't1' ).feature. remove ( 'fcDef' ); model.sol( 'sol1' ).attach( 'std1' ); model.result. create ( 'pg1' , 'PlotGroup2D' ); model.result( 'pg1' ). set ( 'data' , 'dset1' ); model.result( 'pg1' ). create ( 'surf1' , 'Surface' ); model.result( 'pg1' ).feature( 'surf1' ). set ( 'expr' , 'theta' ); model.sol( 'sol1' ).runAll; |
四、结果
参考:
https://mooseframework.inl.gov/modules/phase_field/Phase_Field_Equations.html
https://mooseframework.inl.gov/modules/phase_field/Derivation_explanations.html
https://blog.sina.com.cn/s/blog_4a0a8b5d01011spl.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具