1. 光子晶体扭转结构仿真全攻略
上周实验室新到了一批光子晶体样品,老板让我先用COMSOL做个理论验证。这玩意儿看着简单——不就是两个周期性结构叠一起转个角度嘛,结果一上手才发现坑多得能摔死人。折腾了三天终于把能带和透射谱都跑出来了,今天就把这个"魔角光子晶体"的完整仿真流程拆开揉碎讲明白。
先说说这结构的特别之处。就像魔角石墨烯两层堆叠会出现超导态一样,两个光子晶体晶格相互扭转时,会在特定角度产生新的光学特性。我这次仿真的是三角形空气孔阵列,晶格常数500nm,空气孔半径150nm,当扭转角接近7.5°时,在1550nm通信波段会出现特殊的双共振峰,这个现象在光学滤波器和传感器领域很有应用前景。
2. 建模关键步骤详解
2.1 晶格生成技巧
手动在COMSOL里画旋转晶格纯属找虐,我直接用MATLAB脚本生成坐标点。核心思路是先创建基准晶格,再用旋转矩阵处理:
matlab复制% 基础晶格参数
theta = 7.5; % 扭转角度(度)
a = 500e-9; % 晶格常数(m)
r = 0.3*a; % 空气孔半径
% 生成六方密排晶格
[x_base,y_base] = meshgrid(-3*a:a:3*a, -3*a*sqrt(3)/2:a*sqrt(3)/2:3*a*sqrt(3)/2);
x_offset = x_base + a/2*mod(y_base/(a*sqrt(3)/2),2); % 奇数行偏移
coords = [x_offset(:), y_base(:)];
% 旋转变换
R = [cosd(theta) -sind(theta); sind(theta) cosd(theta)];
rot_coords = (R * coords')';
这里有几个关键点:
- 网格范围取3×3个原胞足够捕捉Moire特征,再大计算量呈指数增长
- 奇数行需要水平偏移a/2才能形成六方密排结构
- 旋转后的坐标要转置两次才能保持维度一致
生成的数据保存为txt文件,在COMSOL的几何界面选择"导入->点坐标",然后批量创建圆柱体空气孔。记得把单位统一设为纳米级,否则容易报几何错误。
2.2 材料与物理场设置
基底材料我选的是硅(Si),折射率设为3.48,空气孔区域折射率设为1。物理场选择"电磁波,频域",边界条件要特别注意:
- 上下表面设为散射边界条件(Scattering Boundary Condition)
- 四个侧面设为周期性条件(Floquet周期边界)
- 空气孔壁设为完美磁导体(PMC),简化计算
重要提示:扭转结构的周期性边界需要手动调整波矢分量,后面能带计算部分会详细说明
网格划分采用用户控制:
- 基底区域:最大单元尺寸λ/5
- 空气孔边缘:局部细化到λ/15
- 使用曲率适应网格提升精度
3. 能带计算实战
3.1 布里渊区扫描设置
扭转结构的原胞变大,传统能带计算方法会漏掉简并点。我的解决方案是用参数化扫描替代:
- 在"研究"中新建参数化扫描
- 定义波矢kx和ky为扫描参数
- 设置扫描路径为六边形不可约布里渊区边界
对应的COMSOL Java API设置:
java复制model.physics("pw").prop("Periodic").set("kappax", "k0x");
model.physics("pw").prop("Periodic").set("kappay", "k0y");
model.study("std1").feature("param").set("pname", new String[]{"k0x", "k0y"});
扫描路径建议按Γ→M→K→Γ顺序设置,每个边取15-20个采样点。计算频率范围覆盖0.5-2×10^15Hz(对应波长1500-600nm)。
3.2 数据处理技巧
COMSOL自带的能带绘图工具比较基础,我通过LiveLink调用MATLAB做后处理:
matlab复制data = mphgetquad(model, 'ewfd.E', 'dataset', 'dset1');
[Kx,Ky] = meshgrid(linspace(0,2*pi/a,100), linspace(0,2*pi/a,100));
F = scatteredInterpolant(data.kx, data.ky, data.E);
E_interp = F(Kx,Ky);
contourf(Kx,Ky,E_interp,40,'EdgeColor','none');
colormap(jet); colorbar;
xlabel('k_x (rad/m)'); ylabel('k_y (rad/m)');
这样处理后的能带图可以清晰显示带隙位置和等频线分布。特别要注意的是,扭转7.5°时会在Γ点附近出现平带(flat band),这是产生特殊光学响应的关键。
4. 透射谱仿真要点
4.1 端口设置
- 在结构上下表面添加端口边界
- 端口类型选"数值",模式数设为3(包含高阶衍射)
- 扫描波长范围设置为中心波长±20%
端口尺寸要大于Moire超原胞尺寸,否则会漏掉边缘衍射。我的经验是取3倍原胞长度比较安全。
4.2 散射场处理
高阶衍射会导致反射干扰,需要自定义散射场表达式:
java复制double k0 = 2*M_PI*freq/3e8;
ex = ex - 1j*(k0*(x^2+y^2)^0.5)*scattering_field;
这个表达式相当于在标准散射边界条件上增加了相位修正项,能有效抑制虚假反射。实测表明,当网格加密到λ/10时,共振峰位置误差可以控制在0.5nm以内。
5. 常见问题排查
5.1 计算不收敛
现象:求解器报错"达到最大迭代次数"
解决方法:
- 检查周期性边界条件是否正确定义了波矢分量
- 尝试使用直接求解器(MUMPS)替代迭代求解器
- 降低初始频率步长,采用自适应扫描
5.2 共振峰偏移
现象:仿真结果与文献数据存在系统性偏移
排查步骤:
- 确认材料折射率参数是否正确
- 检查网格是否在共振波长附近足够细密
- 验证端口是否包含了足够多的高阶模式
5.3 内存不足
现象:计算中途崩溃
优化方案:
- 使用对称性简化模型(如旋转对称)
- 改用频域模态法替代全波仿真
- 分段计算后拼接结果
6. 性能优化技巧
-
并行计算设置:在首选项→求解器中将最大核心数设为物理核心数-1,留一个核心给系统
-
内存管理:64GB内存的机器建议设置30GB为COMSOL专用,在配置文件添加:
code复制-Xmx30g -XX:MaxPermSize=4g -
缓存利用:相同参数扫描时勾选"存储解决方案",下次计算直接调用缓存
-
网格策略:先粗算定位共振区域,再局部加密网格精算
这个仿真在i9-13900K+64GB内存的机器上跑了约5小时。如果急着要结果,可以尝试以下加速方案:
- 使用二维模型替代三维(精度损失约15%)
- 采用等效介质理论简化空气孔结构
- 开启GPU加速(需安装CUDA工具包)
最后分享一个血泪教训:一定要设置自动保存间隔!我第一天没保存跑了三小时的结果,一个蓝屏直接回到解放前...现在都是设置每30分钟自动保存一次。