Comsol计算蜂窝晶格光子晶体能带拓扑陈数。 包含mph与matlab脚本。

蜂窝晶格的六边形对称性总能搞出有意思的拓扑特性。最近在实验室搭了个简易光路验证拓扑边界态,老板突然甩过来一句"你这陈数到底准不准",得,老老实实用COMSOL重新算一遍更踏实。

打开COMSOL新建二维模型,先画蜂窝晶格的基本单元。这里有个坑要注意:真正的原胞其实是包含两个介质柱的菱形结构。直接上LiveLink脚本生成蜂窝结构比手动画图靠谱:

a = 1e-6; % 晶格常数
r = 0.3*a; % 介质柱半径
geom = model.geom.create('geom',2);
cyl1 = geom.create('cyl1','Cylinder').set('r',r);
cyl1.set('pos',[0 0]);
cyl2 = geom.create('cyl2','Cylinder').set('r',r);
cyl2.set('pos',[a/2 a/2*sqrt(3)]);

参数化扫频是关键操作。在能带计算时记得勾选"存储所有频率",不然后续处理Berry曲率时哭都没地方哭。边界条件建议用Floquet周期边界,kx和ky方向都要设置相位延迟参数,这对处理动量空间拓扑至关重要。

算完能带别急着关软件,把本征模式导出为.mat文件。这时候Matlab脚本要上场了,咱自己写的贝里曲率计算工具包比官方后处理强多了。核心算法主要分三步走:

  1. 在布里渊区生成离散k点网格
  2. 计算每个小网格的贝里通量
  3. 全空间积分得到陈数
% 读取COMSOL数据
load('eigenmodes.mat','E','H'); 
% 生成k空间网格
[kx,ky] = meshgrid(linspace(-pi/a,pi/a,50));
berry_flux = zeros(size(kx)-1);

for i = 1:size(kx,1)-1
    for j = 1:size(kx,2)-1
        % 计算每个小方格的贝里曲率
        U1 = get_parallel_transport(kx(i,j), ky(i,j), kx(i+1,j), ky(i+1,j));
        U2 = get_parallel_transport(kx(i+1,j), ky(i+1,j), kx(i+1,j+1), ky(i+1,j+1));
        U3 = get_parallel_transport(kx(i+1,j+1), ky(i+1,j+1), kx(i,j+1), ky(i,j+1));
        U4 = get_parallel_transport(kx(i,j+1), ky(i,j+1), kx(i,j), ky(i,j));
        
        berry_flux(i,j) = angle(U1*U2*U3*U4);
    end
end

chern_number = sum(berry_flux(:))/(2*pi))

这里的getparalleltransport函数处理布洛赫波函数的平行输运,需要用到COMSOL导出的本征模式数据。有个骚操作是把电场分布做傅里叶变换,取出特定k点的相位信息,比直接调用场量更稳定。

计算结果要是出现陈数接近整数但有个0.1左右的偏差,别慌。检查k点网格密度是否足够,特别是狄拉克点附近的采样。上次算石墨烯体系时发现,当网格从50x50提升到100x100时,陈数从0.89跳变到1.02,这其实是数值误差在作妖。

最后验证拓扑特性的正确姿势是:同时计算Z2不变量和边缘态频带。当两者结果冲突时,大概率是原胞边界条件没设对——老司机都知道,蜂窝结构的手性边缘处理能坑掉80%的新手。

整套流程跑通大概需要吃掉32G内存,建议挂着服务器慢慢算。要是中途报错提示"内存不足",试试把COMSOL的求解器改成MUMPS,亲测能省下1/3的内存开销。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐