
好久没写散射仿真的实操分享了。这两天帮一个做纳米光学方向的研究生调 COMSOL 模型他的问题很有代表性算出来的散射截面永远是那种左右对称的钟形峰怎么看都不像文献里那种“陡谷尖峰”的不对称曲线。我问他入射极化、颗粒尺寸、背景条件都动过没有他说都试了就是出不来。问题其实不在参数在于他还没有理解法诺共振到底是怎么在散射体里形成的。这篇就借“Comsol 散射体法诺共振”这个话题把物理机制、建模参数、PML 设置、散射截面计算、法诺线型拟合一整条链路完整讲一遍。无论你之前用的是总场公式还是散射场公式也无论你是做介质纳米颗粒、等离激元结构还是超表面单元这篇文章都能帮你把“非对称峰”稳稳地仿真出来。1. 法诺共振的物理图景为什么散射光谱里会长出非对称峰1.1 洛伦兹对称峰与法诺非对称峰的本质区别大多数人最开始接触共振学的都是洛伦兹线型。一个带阻尼的谐振子在共振频率附近响应谱长这样σ_L(ω) σ_max · Γ² / [(ω − ω0)² Γ²]这个公式给出的峰左右完全对称。频率往左扫和往右扫功率下降速度一样峰值位置就是物质的共振频率峰宽由阻尼决定。很多散射仿真里看到的就是这种曲线——一个鼓包干干净净。法诺共振是另一种东西。它的经典表达式是σ_F(ω) σ0 · (q ε)² / (1 ε²) 其中 ε (ω − ω0) / (Γ/2)这里多了一个参数 q叫法诺参数。当 q 很大时这个式子会退化回洛伦兹但当 q 比较小尤其是 q 接近 0 时谱线会变成明显的“峰—谷”结构一侧是峰一侧是谷中间还有一个接近零的极值点。整条曲线不对称看起来像洛伦兹峰被什么东西“压扁”了一边。为什么会出现这种形状最通俗的理解是有两条路径同时通往同一个观测通道一条是宽谱的连续路径另一条是窄带的离散路径。扫频率时窄路径的相位会快速翻转两条路径发生干涉增强时形成峰、相消时形成谷。我可以拿两列水波打比方一列是稳定的背景波浪频率变了也只是换了个强度另一列只在某个窄频段里剧烈起振。在某个频率点上两列波相位相同振幅叠加变高相邻频率点相位相反振幅相消变低。于是谱线上出现了比洛伦兹更陡峭的“峰压着谷”。法诺共振的另一个特征是谷的宽度往往很窄谱线斜率极大。这个特点在传感上特别值钱因为共振位置只要偏移一点点谱线的强度变化就是巨大。这也是为什么大家宁可折腾仿真也想把 Fano 峰调出来。1.2 散射体中的“宽通道”和“窄通道”回到散射这个问题。一个颗粒暴露在平面波里散射出去的电磁场可以拆成两部分叠加。第一部分是宽通道入射波直接被散射体的几何边界弯曲、反射、绕射出去。对于尺寸和波长可比的结构这部分贡献随波长缓慢变化相当于一个宽带背景。对于亚波长介质颗粒通常是低阶米氏模式比如电偶极或磁偶极模式的宽共振。第二部分是窄通道散射体内部或者表面存在某个高 Q 值局域模式。典型有介质颗粒的高阶米氏模电四极、磁四极、漏泄模Whispering Gallery Mode或者等离激元结构里的暗模式。这些模式只有在特定的频率附近才会被有效激发而且一旦共振场增强非常剧烈谱线上表现为一个窄带。法诺共振的条件就是让这两个通道对应的辐射模式在某个频率附近重叠。宽通道提供一个缓变的背景相位窄通道提供快速翻转的共振相位二者在远场干涉后散射截面就呈现出非对称线型。这里必须提醒一点并不是任意散射体都能自然出现法诺共振。有时候只有宽共振谱就是洛伦兹峰有时候窄共振太弱被背景淹没也看不到非对称结构。需要满足“宽窄重叠”和“两者都能辐射到同一远场通道”这两个条件。这也是很多人在 COMSOL 里怎么扫参都扫不出 Fano 的根本原因。1.3 法诺共振在工程上的价值理解了机制再说它有什么用。法诺共振最经典的应用是折射率传感。由于峰谷之间的斜率极大待测介质折射率微小变化会导致光谱强度剧烈变化灵敏度远高于普通洛伦兹共振。这是表面等离激元传感器里一直强调“Fano profile”的原因。其次是滤波和光学开关。超表面单元若利用法诺共振可以在很窄的波长范围内实现透过率的通断切换本质上是光信号的调制。对于全介质超表面来说这种窄带特性还能避免金属吸收带来的损耗。还有慢光。法诺共振附近存在强烈的相位色散群速度可以降到很低适合做延迟线、光存储器件。从计算角度这些应用落地前都绕不开一步把散射体的法诺共振谱稳定地仿真出来。这就是接下来要讲的建模和实操内容。2. 动手前的参数决策介质柱尺寸、入射极化和扫频策略2.1 为什么首选高折射率介质颗粒而不是金属不少初学者想做法诺共振第一反应是金银纳米颗粒。金属确实能做等离激元共振也能做暗模式诱导透明但问题在于金属在可见光和近红外波段的损耗非常大尤其是金在 700 nm 以下有很强的带间吸收。等离激元共振本身 Q 值通常只有 10 左右谱线宽窄通道不够“窄”法诺谷的深度和陡峭程度都有限仿真里还特别依赖 Drude 模型的参数准确性。所以我建议第一次做直接用高折射率介质材料最典型的是硅n ≈ 3.5 左右、二氧化钛或者砷化镓。介质材料的优势是损耗低、模式Q 值高、几何形状简单不需要处理复杂的色散模型。而且只需一个折射率参数模型轻量网格内存压力小。这里说的“高折射率”是关键。折射率对比度越高颗粒内部才能把电磁场束缚得更厉害模式Q值越高窄共振越窄法诺谷越明显。空气里放一个 n 3.5 的硅柱是比较理想的入门选择。2.2 2D介质柱与3D介质盘怎么选COMSOL 建模前要做的第一个决策是维度。2D 模型的最典型散射体是一个无限长介质圆柱用 TM 极化平面波电场沿圆柱轴向也就是 z 方向照射。这样模型里只有一个非零电场分量 Ez加上两个面内磁场分量 Hx、Hy计算量非常小普通笔记本几分钟就能扫完一大段频带。缺点是它对应的是无限长圆柱和真实的纳米盘、纳米球有差别。3D 模型可以建模介质球、介质纳米盘更接近实验但自由度按数量级上涨。光频段下波长几百纳米细化网格后三维模型很容易跑到几百万自由度扫频几十个点就是半天以上。我的做法是先在 2D 介质柱模型上把物理机制和计算流程跑通确认能复现法诺峰再根据需求迁移到 3D。2D 模型最大的价值就在这里——它把变量的维度降下来让你把所有注意力集中在“物理条件是否成立”上面而不是被网格和内存消耗拖死。2.3 扫频范围、折射率和尺寸初值怎么定参数初值不要乱猜用归一化尺寸来估算。定义无量纲尺寸 x 2πa / λ其中 a 是圆柱半径λ 是真空中波长。对于折射率 m ≈ 3.5 的介质圆柱第一阶磁偶极或电偶极共振大致出现在 x ≈ 0.7 到 1.8 之间高阶模出现在更大的 x 范围但也在 2 到 4 附近。假设半径 a 200 nm想让 x 落在 0.7 到 1.8 区间对应的波长大约是λ 2πa / x ≈ 1257 nmx0.7 到 489 nmx1.8所以扫频范围取 500 nm 到 1200 nm 是合理起点。如果想让高阶模和低阶模重叠出现法诺可以把半径再调大一点或者把波长范围放宽一些。扫频步长也要分层。粗扫用 5 nm 甚至 10 nm 的步长先把峰谷的大致位置找出来然后局部加密到 0.5 到 1 nm确保把窄共振的线型细节和谷底深度都吃下来。直接用大范围细扫会消耗大量计算时间很多时候还不一定逮得住那个窄峰。3. 建模实操从几何到PML再到网格分配的关键设置3.1 几何散射体、包裹空气域和PML层COMSOL 里电磁散射问题的几何一般由三部分组成散射体本身、包围散射体的计算域、最外层的完美匹配层 PML。以 2D 介质柱为例几何可以这样建圆1硅柱半径 r圆心在原点。圆2空气域半径 R 要明显大于散射体通常取 R ≥ 3λ0/2保证散射体周围有足够的空间来过渡到远场。圆环PML 层由圆2外边界到圆3外边界之间的环形区域组成。要注意的是COMSOL 的 PML 是一个单独的域必须在几何里明确画出来。建完几何后在“定义”节点下添加“完美匹配层”并选中那个环形域。对于圆形几何PML 的类型建议选择柱坐标缩放这样平面波斜着入射时的吸收效果也比较好。PML 厚度至少取半个波长稳妥一点取一个波长。很多人为了省计算域把 PML 做得很薄结果边界反射在频域谱上出现一堆毛刺还以为是物理上有什么新峰——这个坑后面再展开。3.2 物理场设置散射场公式与背景平面波这是整个建模里最关键的一步一定要理解清楚。添加物理场时选择“电磁波频域”ewfd研究类型选择“频域”。然后在主物理场节点下把求解量从“总场”切换到“散射场”。为什么要用散射场公式这里面有个大坑。如果选总场公式COMSOL 会把总场作为因变量求解所有边界条件都施加在总场上近场后处理里你想单独提取散射场分量还得手动做减法麻烦且容易出错。而散射场公式下因变量本身就是散射场背景场作为解析表达式单独给出这样后处理提取散射功率就非常自然。背景场这样设置在“背景场”子节点中选择“平面波”方向沿 x 轴正方向极化方向沿 z 轴即电场只有 Ez 分量。电场幅值设为 1 V/m 即可。这就是标准的 TM 入射。物理场设置完成后还要检查外边界。因为已经把最外层域设成了 PML外边界上不需要再额外施加散射边界条件。在 COMSOL 里PML 的默认外边界处理已经足够不会产生明显反射。如果不想用 PML那就在空气域最外边界上添加“散射边界条件”节点但散射边界条件对斜入射仍有反射精度不如 PML。3.3 网格分配哪里加密、哪里可以粗网格策略直接影响法诺谷的数值准确性。散射体内部网格尺寸要按介质内波长来定建议小于 λ_s/6其中 λ_s λ0/n。如果硅的折射率 n 3.5那就是 λ0/21 左右。比如扫到 800 nm 波长硅内的网格大约需要 40 nm 甚至更细。空气域这里用 λ0/8 即可不需要刻意加密。PML 域切向方向可以粗一点但法向方向也就是厚度方向至少要 3 到 4 层网格这样吸收渐变才平滑。PML 的网格类型建议用映射网格或扫掠网格自由三角形也能用但吸收层的分辨率要够。网格尺寸这个“λ/n/6”的经验值很多人会忽略。用统一 λ0/8 去剖分整个模型介质内部波长只有真空的 1/3.5等于直接把共振模式的空间分辨率砍掉了三倍多算出来的共振频率和线宽都会偏移。尤其在法诺峰这么窄的线型上网格不足会让谷的位置和深度失真。3.4 求解设置用参数扫描替代大列表频率扫描模型建好后还有最后一个细节如何做频率扫描。建议不要直接在“频域”研究步骤里填一大串频率列表。几千个频率点一次性求解对内存的占用和结果的存储量都很大。更稳妥的做法是这样在“全局定义”里先定义一个参数 λ0初值设为 900 nm。在“频域”研究步骤中把频率设成 c_const/λ0这是由波长换算出来的频率。再添加一个“参数扫描”研究节点对 λ0 做扫描列表填 range(700e-9, 5e-9, 1200e-9) 或者手动分段填写。这个方案的实际效果是COMSOL 在参数扫描中逐个求解单频点每个频率的相对内存占用更可控结果组织也更清晰。粗扫用 5 nm 步长找到可疑的峰谷区域后再局部加一个 0.5 nm 步长的扫描。4. 把仿真场变成散射截面积分算子与后处理的正确姿势4.1 用积分算子计算散射功率模型求完解怎么把仿真场变成一条散射截面曲线这一步很多人卡住。正确的做法是利用散射场公式下的场变量直接对散射场的坡印廷通量做闭合面积分。先在“定义”节点下添加一个“积分”算子选中一个完全包围散射体的闭合边界。这个边界要放在 PML 内侧、紧贴散射体或者稍远一点都行但不能穿过 PML。然后在“派生值 → 全局计算”里调用积分算子并计算表达式int_sc(ewfd.nPoav)注意由于物理场采用的是散射场公式COMSOL 的场变量 ewfd.Ez、ewfd.Hx、ewfd.Hy 代表的都是散射场不是总场。因此 ewfd.nPoav 本身就是散射场的平均坡印廷矢量的法向分量对闭合边界积分的结果就是单位长度的散射功率。这是散射场公式带来的最大便利。如果误用了总场公式在这里积分得到的是净能量通量对无耗介质结果接近零根本得不到散射截面。这一点是新手最容易犯的错误。4.2 从散射功率到散射截面拿到散射功率之后还要除以入射波的功率密度。平面波的入射功率密度是I0 0.5 · c0 · ε0 · |E0|²在 COMSOL 里可以直接用内置常数 c_const 和 eps0_const 计算E0 是背景电场幅值 1 V/m所以 I0 0.5c_consteps0_const。最后散射截面 σ W_sca / I0。具体操作上可以在全局计算里写一个组合表达式int_sc(ewfd.nPoav) / (0.5c_consteps0_const)得到的结果单位是米。这是 2D 无限长柱的单位长度散射截面不是面积。要转成散射效率 Q_sca还要除以柱的直径或者按米氏理论归一化。这些对比验证可以交给后面的拟合阶段处理。4.3 用远场域做定性验证除了定量计算散射截面建议再添加一个“远场域”节点做验证。在物理场树中右键“电磁波频域”添加“远场域”然后选择一个包围散射体的闭合边界。注意远场域边界也要在 PML 内侧。求解后可以在一维绘图组或者极坐标绘图组中画出散射角方向的远场强度分布。这一步不是必须的但很有用。法诺共振的物理本质是远场干涉所以看不同角度的远场辐射图可以直观确认“峰谷”是来自辐射方向的干涉而不是数值假象。有时散射截面上的法诺谷不明显但远场方向图上会出现零点或双瓣结构的剧烈变化可以作为补充证据。4.4 数据导出的正确姿势后处理数据导出同样有个小技巧。先在“派生值 → 全局计算”中求出每个波长对应的散射截面生成一个表格。然后右键表格 → “文件 → 导出”选择 CSV 格式。导出前注意要看清楚“数据”选项卡里选中的是全部解还是当前解。如果用参数扫描做了很多个波长默认可能只导出当前显示的解那导出的 CSV 就少了一半数据。正确做法是在表格上方的“数据”下拉列表中选择“所有解”或对应扫描标签确保每一行的波长和散射截面都完整对应。5. 扫参、拟合和法诺参数提取让非对称线型开口说话5.1 先扫半径找“宽窄重叠”窗口散射体法诺共振能不能出现往往就在尺寸这个参数上。所以第一步不是拟合而是扫参数找峰谷重叠。以硅介质柱为例可以固定扫描波长范围 700 nm 到 1200 nm将半径 r 设为参数扫描变量分别取 150、175、200、225、250 nm。每一组都算一条散射截面曲线然后把它们叠加画在同一张图里对比。预期现象是这样的当半径较小时散射截面只有宽的低阶共振峰谱线基本对称随着半径增大某些高阶模的频率逐渐靠近低阶模的峰边光谱上开始出现一个窄的谷和相邻的陡峰半径再继续增大两条模式错开法诺特征消失。这个过程中的“峰谷对”就是法诺共振信号。找到它之后再在谷和峰的附近把扫频步长加密把曲线细节算清楚。如果你扫完一圈一个法诺特征都没有优先检查三件事入射极化是不是 TM 且电场沿柱轴方向材料折射率是不是足够高低于 2.5 会很难出窄共振扫频范围是否覆盖到了高阶模的频段。绝大多数“扫不出来”都是这三个条件之一没满足。5.2 法诺公式与 Python 拟合有了曲线下一步是定量提取共振位置、线宽和非对称参数 q。这一步用 Python 的 scipy 完成。先把 COMSOL 导出的两列数据波长 λ、散射截面 σ读进来然后用下面这个模型做拟合import numpy as np from scipy.optimize import curve_fit def fano_profile(w, sigma0, q, w0, gamma, sbg): eps (w - w0) / (gamma/2) return sigma0 * (q eps)**2 / (1 eps**2) sbg # 数据从COMSOL导出第0列是波长第1列是散射截面 data np.loadtxt(sigma_vs_lambda.csv, delimiter,, skiprows1) wl data[:, 0] sigma data[:, 1] # 初值估计w0取谷的位置gamma取峰谷间距的2倍左右 p0 [max(sigma) - min(sigma), -1.5, 850, 30, min(sigma)] popt, pcov curve_fit(fano_profile, wl, sigma, p0p0) sigma0_fit, q_fit, w0_fit, gamma_fit, sbg_fit popt print(fq {q_fit:.3f}, w0 {w0_fit:.3f} nm, Gamma {gamma_fit:.3f} nm)这里有几个初值设置的经验q 的初值设成负数还是正数取决于峰在谷的哪一侧。峰在波长减小的方向q 取负峰在波长增大的方向q 取正。不放心就在 -2 到 2 之间多试几个初值。gamma 的初值取峰谷特征宽度的 2 倍左右太离谱的初值会让 curve_fit 掉进局部极小。sbg 是背景项这里用常数近似。如果背景本身是倾斜的宽峰可以改成 sbg a0 a1*(w - w0)多拟合两个系数。拟合完成后务必把拟合曲线和原始数据画在同一张图上比较。如果残差呈现出波浪形说明这个频段里有两条窄共振重叠一个法诺公式不够用需要叠加两个共振项。5.3 从拟合结果反推模型可靠性拟合参数不是拿来发论文就完事了它们逆向反映了仿真质量。第一个要看的是线宽 gamma。如果 gamma 小于扫频步长的一半说明步长太粗这条窄谷可能根本没有被完整采到拟合出来的 gamma 完全不可信。遇到这种情况回到 COMSOL 里把该频段的扫描步长加密到 gamma/5 以下重新计算。第二个要看的是 q 的绝对值。如果 |q| 非常大比如上百其实说明曲线已经接近洛伦兹法诺特征很弱这个“Fano”别急着下结论先检查是不是窄模根本没激发谱线只是宽背景叠加了一个小窄峰。如果 q 接近 0是典型的反共振谷峰的成分弱也要留意数值噪声的影响。第三个是残差里是否有周期性抖动。抖动往往不是物理效应而是 PML 反射或者网格离散误差。这时候要回到第 6 章讲的可靠性检查而不是继续调拟合参数。6. 网格、内存和收敛性几个踩过坑的细节6.1 网格误差对线宽的影响法诺共振的窄谷数值上是最脆弱的特征。如果网格太粗窄共振的 Q 值会被“数值阻尼”压低表现出来的 gamma 偏大谷变浅变宽。更糟的是网格误差会让峰谷位置偏移几十纳米这在你做传感灵敏度标定时是致命的。我习惯的做法是固定其他条件不变把散射体的最大网格尺寸从 λs/8 细化到 λs/12重新算一遍比较峰谷位置和 gamma 的变化。如果变化小于 5%说明网格已经收敛如果移动明显继续加密。另外扫频步长和网格要一起检查。网格保证空间离散精度步长保证频率分辨率。法诺谷很窄时步长太大相当于把谷“跳过去”了即使网格再细也白搭。6.2 PML 厚度与域大小带来的伪振荡PML 反射是法诺仿真里最容易出假峰的来源。如果 PML 太薄或者网格太马虎边界反射回到散射体附近会和真实散射场发生干涉。这种干涉在频响曲线上表现为等间隔的、幅度不高的正弦波纹频率间距和计算域半径有关。假峰和真法诺谷怎么区分有一个简单方法把计算域半径增大 50%同时把 PML 厚度从 0.5 倍波长增加到 1 倍波长重新计算。如果峰谷位置不变说明是真物理如果振荡纹路跟着变了就是边界反射。这个方法比任何后处理都直观。顺带说一句如果你的模型是 3D 球形散射体PML 类型一定要选球坐标缩放并且确保 PML 域网格是各向异性的切向疏、法向密。这样吸收效率最高。6.3 内存与时间优化光频段仿真最烦人的就是内存。波长 700 nm 到 1200 nm散射体内部网格要到几十纳米量级3D 模型自由度动辄几十万到几百万。几个实用优化手段能用 2D 就不用 3D。把物理机制确认清楚再迁移到 3D能节省大量反复调试的时间。利用对称性。如果模型关于 x 轴或者 y 轴对称可以加理想磁导体或理想电导体边界只算四分之一或一半模型。法诺共振本身是非对称结构但介质柱圆对称在特定极化下仍可以作为切入点考虑。用参数扫描分段跑。先粗扫定位再细扫加密。不要一次性提交几百个点的细扫。内存估算参考2D 单场分量模型几十万自由度大概占用几个 GB 内存3D 多个场分量百万自由度可能要 16 GB 以上。自己机器内存不够时优先缩小模型而不是减少网格质量。最后分享一个我自己的经验。每次跑新的法诺模型我都会在拿到第一版数据后先把最窄的谷单独放大看一遍确认谷底点数至少有三个以上再继续后续的参数扫描。如果谷底只有一个点那这条曲线的可信度要打一个大大的问号。宁可多花半小时加密网格也不要在不确定的数据上折腾半天拟合。法诺共振这个东西物理上理解不难真正难的是把仿真设置的每个细节都做对。从散射场公式、PML 类型、网格收敛到扫频步长每一步都影响最终能不能看到那个经典的“峰压着谷”。希望这篇能把你在 COMSOL 里调散射体法诺共振的弯路省掉一些。