最近收拾硬盘翻出来一堆COMSOL模型文件仔细一数居然有40多个mph。这些都是我当初对照一本光子晶体专著一点点复现的覆盖一维多层膜、二维周期柱阵列再到三维反蛋白石和复杂波导结构。当时做这个项目没指望能出什么论文就是觉得书里那些能带图太漂亮了光看公式实在不过瘾想亲眼看着它们从求解器里跑出来。结果这一跑就入了坑。如果你也是刚接触光子晶体或者在用COMSOL 5.6做微纳光子学的仿真这个项目应该能帮你少走不少弯路。这套文件几乎就是一个现成的案例库打开、看设置、改参数、重新算一连串动作都很直接。1. 项目缘起把一本厚书“跑起来”是个什么概念1.1 为什么要复现而不是只看公式光子晶体这门课最大的门槛不是量子力学而是“看不见”。介质折射率周期排列之后光会怎么走、哪些频率会被挡住光靠脑子里推导二维平面的布洛赫波很难建立直觉。书里的公式当然严谨但公式是抽象的尤其到了三维、到了TM/TE模式分裂、到了带隙边缘的场分布光看文字根本想象不出形状。我的习惯很笨对着书上的图把参数猜出来然后在COMSOL里重新搭一遍。所谓复现不是简单照着mph文件跑一遍而是要把书中的一段话转成一个可计算的模型。比如书上说“正方晶格圆柱半径0.2a折射率3.4”那你在软件里就得问自己a是多少工作频率范围怎么设k点路径是从Γ到X还是从M回Γ这些问题不亲手解决看十遍书都白搭。还有一个现实原因很多学校没有昂贵的实验平台但一台普通电脑就能算能带。COMSOL 5.6对硬件要求不算苛刻16GB内存跑二维案例绰绰有余。所以复现成了性价比极高的学习手段既是理论课作业又是一份能反复调用的数字资产。1.2 40多个mph文件的构成这套项目里的mph文件不是乱堆的而是按维度分层的。一维案例大概有十几个主要处理多层膜结构的反射率和一维光子带隙二维案例是数量最多的部分包括三角晶格、正方晶格、蜂窝晶格里的不同TE/TM模能带三维案例最少但每一个都足够有分量涉及反蛋白石结构、三维波导耦合、以及完整的布里渊区路径扫描。每一个文件的命名我都尽量保留书中的章节号和结构关键词比如“ch3_2D_square_TE_band.mph”这种格式。这样做的好处是当成千上万个文件堆在一起你想回头找“那个二维蜂窝晶格的TM模案例”靠名字就能筛出来。这些文件的共同特点是几何都比较简单难点全在物理设置上。圆柱、球形、矩形这些基础几何画起来很快但周期边界的配对、特征值搜索范围的设定、网格与频率的匹配才是决定结果能否收敛到正确能带的关键。1.3 一、二、三维案例的难度曲线一维案例是热身。几何就是一堆长方形叠起来边界条件简化到极致网格用映射就行几秒钟就能算出好几条带隙。缺点是实际感弱因为真实空间里总有两个横向方向没有被周期化处理但用来理解“带隙是什么”已经是满分答案。二维案例是主战场。以正方晶格为例一个边长a的正方形晶胞中心放一根圆柱加上Floquet周期边界扫一条不可约布里渊区路径能带图就能出来。这里的难点是TE和TM模式的区分以及对周期边界条件中相位关系的理解。我在这层花了最多时间因为很多微妙的结果差异都源于边界条件设错了。三维案例是硬骨头。网格稍微粗一点特征值偏移会大得惊人网格稍微密一点内存又报警。三维反蛋白石或蛋白石结构的计算需要提前规划自由度总数通常我只取第一布里渊区的几条高对称线来算不会做全空间扫描。三维案例不适合入门但它是检验你前两维知识有没有学透的试金石。2. 能带计算的底层逻辑与COMSOL中的对应关系2.1 光子晶体能带到底在解什么方程不管是一维、二维还是三维能带计算的核心都是求解电磁场的本征值问题。介质中无源、无损耗、线性材料的前提下电磁波满足矢量波动方程∇×(∇×E) - k0²·εr·E 0这里的k0是真空波矢εr是相对介电常数。问题的关键是介电常数在空间上周期分布所以方程的解不再是简单的平面波而是布洛赫波的形式E(r) u(r)·e^{j·k·r}。其中u(r)和晶格同周期k是波矢跑了不起眼的“相位”作用实际上决定了整个能带结构。把它和吉他弦类比就很好懂吉他弦的振动频率取决于弦长、张力和单位长度质量是一组离散的本征频率。光子晶体也是类似材料周期分布相当于给电磁波设了“驻波条件”只有特定的频率和特定的波矢组合才能存在。能带图说白了就是给一个k算出所有允许的频率连起来就成了带。在COMSOL里这一步通常用“电磁波、频域”接口下的“特征值”研究来完成。特征值不是时间t而是本征频率f。你给出一堆k值软件会针对每个k输出若干个本征频率这些点连成线就是能带。2.2 Floquet周期边界条件周期性假设的直接体现要在一个有限大小的几何里模拟无限周期结构必须靠周期边界条件。COMSOL中叫Floquet周期边界条件本质上就是布洛赫定理的边界形式。它要求一对边界上的场满足E_dest E_source · e^{j·k·(r_dest - r_source)}其中r_dest和r_source是目标边界和源边界上的位置向量k就是你要扫描的波矢。这个相位乘子是整个能带计算的灵魂。很多人算出来的能带是错位的跳来跳去基本都是因为这个相位关系设置反了或者源边界和目标边界选反了。在模型里设置Floquet边界时软件会让你输入“波矢”的各个分量通常是用全局参数定义例如k_x kx_scan、k_y ky_scan。这些参数可以在辅助扫描中被循环赋值从而完成整条布里渊区路径的扫描。注意一维、二维、三维需要配对的边界对数不同。一维只需一对二维需要两对当然如果你只建一半再加对称条件可以只设一对三维要三对。每对边界在设置时都要确认“源边界”和“目标边界”的高亮方向有一个方向反了计算结果就会完全不可信。2.3 特征值搜索模式与“色散关系”的关系能带图本质就是色散关系即频率与波矢的关系。COMSOL的特征值求解器通常允许你设定“搜索基准点”和“搜索特征值数量”。这一点特别关键如果搜索范围太小高频模式会丢失能带图就会少几条带搜索范围太大又会把很多非物理的伪特征值也捞进来。我的经验是先算一个k0的参考点观察前几个特征值大概落在什么频率区间再根据需求把搜索范围缩窄到感兴趣区域。例如想算可见光波段把搜索范围设在0到6×10^14 Hz之间目标数量设为8到12条带往往就有不错的分辨率。之后扫描k时依赖“参数化扫描”配合“重新使用上一步的解作为初值”能明显提高扫带效率。色散关系这个名字听起来复杂实际上你只需要记住一件事横轴是k纵轴是归一化频率a/λ。这里的a是晶格常数λ是真空波长。归一化后的能带图与具体尺寸无关只和结构占空比、折射率对比度有关这也是不同论文之间能相互对比的原因。2.4 关于“弱形式求解色散光子晶体能带”的方案标准ewfd接口能处理大多数光子晶体问题但碰到材料介电常数随频率变化即色散材料时标准特征值公式会变得别扭因为εr(ω)使问题不再是标准的线性特征值问题。这时需要借助弱形式方程。COMSOL的弱形式解法通俗讲就是把你手中的偏微分方程先变形成积分形式再告诉软件每个项应该在哪个域里做数值积分。对于色散光子晶体常见的做法是把波动方程改写成关于u(r)的广义特征值方程并把色散D(electric displacement field)作为额外的状态变量引入。这样一来频率不再藏在材料属性里而作为特征值显式出现。具体操作时可以添加“偏微分方程”接口里的“弱形式偏微分方程”定义未知场u然后在弱表达式里写test(u) · (∇×∇×u) - (ω/c)^2 · εr(ω) · u · test(u) 0其中εr(ω)用插值函数或者解析表达式定义。这种写法初看很劝退但实际测试下来它对计算频带和带隙边缘的精度很有帮助尤其是研究石墨烯类、等离激元类色散材料时几乎绕不开。我在复现一书中的几个金属-介质混合结构时用的就是这个思路。标准接口算一半会报错换弱形式后一次跑通。3. 实操从mph文件到自建模型的一条龙流程3.1 5.6版本打开旧文件时先做三件事这套mph文件虽然都是用COMSOL 5.6保存的但在别人电脑上打开时依然会出现各种意想不到的问题。我建议每次打开一个新文件先做三件事别急着点“计算”。第一检查“全局定义”里的参数列表。确认晶格常数a、圆柱半径r、介电常数eps_r、以及波矢参数kx、ky这些关键量是真实存在的。旧文件中参数名可能和我习惯不同直接修改成你自己的命名规则。第二把“研究”节点里的“特征值搜索范围”读一遍。不同版本默认设置会有差异5.6在特征值求解器中默认搜索频率是0到无穷目标特征值数可能只有6个。这会导致高波段根本没参与扫描结果里看不到高频率的带。第三重新构建网格再求解。mph文件里保存的网格是从原电脑生成的一旦几何被修改或者单位设置不同旧网格可能失效或退化。稳妥做法是删除现有网格按原始设置重新划分再跑一次特征值求解。这样至少能排除最简单的坑。3.2 一维案例多层膜能带与反射率一维光子晶体是一维堆叠的多层膜结构例如高折射率n13.4和低折射率n21.46交替排列。复现这类案例我通常用一维模型就够。几何就是一段长度为a的周期单元两端设置Floquet周期边界材料赋值给各个层。扫描波矢时参数k对应传播方向的相位累积。特征值算出来的频率直接归一化为a/λ。你会发现低频允许通过、高频附近出现带隙带隙中心位置与关系式n1·d1 n2·d2 λ0/4基本吻合这个是检验模型对不对的黄金标准。更进阶的一维案例还要算反射谱。这时候要把模型扩展为“多层膜两侧空气层”外层用完美匹配层收住入射端口用端口边界条件激发。反射率R随波长的变化会明确显示带隙位置。这个案例计算量小、逻辑清晰适合作为整套项目的第一课。3.3 二维案例Floquet边界扫描不可约布里渊区二维正方晶格是最常见的练手场景。几何设置上晶胞边长a中心圆柱半径r圆柱介电常数设为ε_high背景介质设为ε_low。圆形居中之后对着四条边界分别设置Floquet周期边界条件左右一对上下另一对。然后设置波矢扫描路径。正方晶格的不可约布里渊区路径一般是Γ→X→M→Γ对应高对称点的坐标为Γ (0, 0)X (π/a, 0)M (π/a, π/a)在COMSOL里我习惯定义一个扫描参数s取值范围0到1每段路径的比例长度按实际距离分配。例如Γ→X占1段X→M占1段M→Γ的长度会略长√2倍这会导致能带图横轴刻度不均匀。为了好看需要给扫描参数设置不同的映射关系或者在导出后用Origin/Python重新排横轴。求解完成后在“派生值”里提取“全局最小值”而不是“点值”因为特征值结果通常在数据集里做的是一维极值处理。保留前8条能带画出来就是典型的能带图。细心的话可以看到带隙出现在哪条高对称线上场分布在带边位置的空间形态也能看得很清楚。3.4 三维案例网格规模控制和求解参数调整三维光子晶体案例最典型的是反蛋白石结构或者三维立方晶格球形孔洞。几何用三维晶胞边长为a内部放一个球体代表孔洞或高折射率材料。三对Floquet周期边界条件设置方式和二维完全类似只是多了一组z方向配对。网格是最大拦路虎。三维里如果还用三角形网格疏疏朗朗地剖特征值误差会大得离谱。我一般给球体表面设“较细化”网格背景区域用“较粗化”整体自由度控制在50万以内。对于8GB内存的机器超过这个量会开始卡顿16GB内存则相对安全最多可以跑到80万。求解器方面特征值研究建议把“线性扰动求解器”关掉直接用默认的全耦合特征值求解器。如果内存不足可以把“目标特征值数”从8降到4或者缩小“特征值搜索范围”。三维案例求的不是全貌而是关键带隙趋势能用局部信息验证书中的结论就够了。3.5 能带图的整理与数据导出mph文件里面的结果图是可以直接截图的但论文或作业里需要再加工所以我习惯把数据导出来重绘。在COMSOL中右键“派生值”选择“全局计算”在表达式栏输入实部特征频率freq选中所有特征值模块然后勾选“表”最后把表格导出成csv文件。导出文件里会有两列核心数据扫描参数s和对应的归一化频率f·a/c0。用Python或Origin把散点画出来后你会发现不同段路径之间的“段边界”如果没处理横轴会出现跳跃。解决办法是手动给每段路径分配一个累计长度参数比如x坐标再画散点图。这样整理出来的能带图干净清晰和书上的图对比也方便。顺带说一句COMSOL模型树中的“结果”节点里我通常预先存好几个分组绘图电场模、磁场模、能量密度以及能带图模板。这样每次算完新案例只需要双击运行“绘图组”图片就自动刷新省去了重复设置的麻烦。4. 踩坑实录复现过程里最常见的五个问题4.1 特征值算出来是虚数或者负实部这是新手最容易遇到也最容易吓退人的问题。特征值求解器输出的是一个复数实部是频率虚部代表损耗或增益。正常情况下无损耗材料的特征值虚部应该非常小接近零。如果你看到实部为负、虚部很大不用慌。先检查所有材料的介电常数是不是有虚部。有时候设置εr时误填了复数哪怕虚部只有0.01也会让本征频率偏移并出现明显虚部。把材料改回纯实数之后特征值就干净多了。还有一种情况是当模型中有开放边界例如空气截断面造成的泄漏模式特征值也会变虚。能带计算里我们要求严格周期结构这时必须确认四个或六个边界都已经配对成Floquet边界没有哪个边条悄悄设成了默认的“完美电导体”或“连续型边界”。4.2 能带结果和书对不上先查单位复现最痛苦的瞬间是图算出来了但纵轴数值跟书里差了十万八千里。十有八九问题出在归一化单位。书上的纵轴通常是无量纲频率a/λ或者ωa/(2πc)这两种写法等价。而COMSOL特征值求解器返回的频率是赫兹还需要乘上晶格常数a再除以光速c。我来举个具体例子假设晶格常数a500nm算出一个特征频率f300THz那么归一化频率是 f·a/c 300e12 × 500e-9 / 3e8 0.5。你拿这个0.5去和书中能带图对比才发现完全对得上。很多人直接把300THz画上去当然和书不一样。还有反过来的坑如果书中设定a1μm而你的几何画的是a0.5μm所有能带频率会翻倍。所以开始建模前先从书中判断a取了多少再确定COMSOL几何中的单位。这个判断不花时间但能省下一整天的排查。4.3 边界相位设反导致能带折叠错误Floquet边界条件的相位表达式里正负号决定了波沿哪个方向传播。如果符号设反计算结果会等于把k映射成了负k而能带结构通常关于k是对称的所以有些情况看不出区别。但在非对称结构或某些高对称点上符号错误会让“带折叠”方向完全错误。排查方法很直接算一个k0频率点应该能观察到所有模式的场分布具有晶格相同的对称性。如果空间场分布出现明显错位检查source边和destination边是否选择了同一组边界的两端。COMSOL的边界方向由箭头指示需要确保source边箭头方向和destination边箭头方向一致否则相位乘子会多出180度莫名其妙的偏差。4.4 网格粗细与特征值搜索范围的权衡网格加密之后特征频率通常会降一点并趋于收敛。但真实问题是网格粗的时候特征值频率偏高带宽范围和带隙边缘都是虚胖的。复现书中精确带隙边缘时网格必须密到能分辨场在晶格内快速变化的细节。我的经验是先跑一个粗细的网格看趋势例如最大单元尺寸设为a/8能带大体轮廓先出来。然后只对带隙边界点加密到a/16看频率变化不超过1%才敢说结果可信。二维圆柱结构可以用三角形网格但圆柱边界的曲率会影响局部网格质量建议在曲率较大的地方设置边界层网格。特征值搜索范围的权衡也没有统一解。搜索范围太宽求解时间会指数增加太窄会漏掉带。建议先从已知的理论带隙位置出发把搜索范围向上扩展20%。多试几次后你会摸到每个结构大致需要几条带才能覆盖感兴趣频率区间。4.5 弱形式建模的细节与排查使用弱形式方程时最常出的错是万花筒一样的变量名不匹配。COMSOL中自定义弱形式需要显式声明测试函数变量例如test(u)。如果表达式里写的是u而不是test(u)软件会报“未知变量”或“变量未使用”即使能求解矩阵也是空的。另外弱形式中定义的本征值通常是一个全局参数例如lambda或者omega。你需要在“特征值”设置里指定“本征值变量”为lambda而且在表达式中要出现“lambda·u·test(u)”这样的质量项。如果没有质量项特征值求解器会认为你解的是一个静态问题输出一堆奇怪的0特征值。排查时最好的工具是“求解器日志”它会打印出每个归一化参数对应的自由度数和最终装配方程的数量。如果自由度数量少得离谱多半是弱形式方程没有正确作用到域上回去检查“启用方程”的选择框以及“域选择”是否正确。5. 这份案例库怎么用效率最高5.1 推荐的学习顺序和实验节奏建议不要一次性把所有mph文件全打开那样会看吐。合理节奏是一周一个维度第一周一维第二到三周二维第四周三维。每个文件不求跑完所有能带只取书中一个关键图进行复现然后对照检查。一维案例花12分钟就能完成一个完整实验。二维案例从建模到出图大约四十分钟刚好是一个下午能专心做完两个案例的节奏。三维案例建议选重点比如反蛋白石结构算一次第一布里渊区路径其他相似三维结构就只改参数不深挖。这样既节省时间又保证了整体覆盖面。5.2 把mph文件改造成自己的研究模型复现的终点不是把书里的图重新画一遍而是让这些mph文件变成自己下一步研究的起点。替换几何是最容易的把圆柱改成方柱、六边形改变r/a比值就能研究不同结构对带隙宽度的影响。只要参数化做得好这个改造过程极快。另一条路是引入缺陷。在一个二维周期结构中去掉中心某个圆柱再扩大计算区域为3×3或5×5超胞你会看到带隙中出现一条很平的缺陷态能级。这其实就是光子晶体波导和微腔的原型。mph文件里调整“晶格阵列”相关的几何复制次数就能实现整个过程不需要重学新物理。如果你对拓扑光子学感兴趣还可以在现有能带模型中加入晶格变形参数观测能带简并打开和边缘态的出现。来自mph文件的基础边界条件、扫描路径和特征值设置都能原样保留只需要修改k路径的定义和几何周期。5.3 我的几点收尾体会做完这40多个文件我最深的体会是算能带这件事本身不复杂真正难的是结果的可信度。COMSOL里每个设置都有它存在的理由Floquet相位不是装饰品特征值搜索范围不是随便填的数字网格加密不是为了打磨漂亮图。只有每一步都清楚自己为什么这么做复现才真正起到作用。如果非要说一个小技巧就是反复使用“对照实验”的方法故意改错一个参数比如把边界相位符号取反看看能带会发生什么变化。看一眼错误结果再改成正确设置比直接得到正确答案更能加深理解。这套mph文件现在不仅是我自己的学习笔记也是一份可以分享给后来者的数字资源希望它能帮更多人在光子晶体的路上少掉一点头发。