环形谐振器(Ring resonator)这个案例,几乎是每个用Lumerical FDTD做集成光子学仿真的人绕不开的一关。我自己当年啃官方教程时,第一二部分还算顺畅,模型搭起来了、光场也看到了,但到了第二和第三部分——也就是透射谱分析和参数优化的部分——整个人就有点懵。官网给的步骤能跑通,但每一步在算什么、为什么这么设、结果怎么读,官方文档讲得并不细。这篇我按自己的理解把这两部分拆开揉碎讲清楚,适合已经跑通基础案例、开始认真琢磨透射谱和Q值的读者。
先说清楚,不同版本教程对“第二部分/第三部分”的划分可能略有差异,但落到FDTD仿真的实际流程上,无非是两件核心事:把环形谐振器的透射谱算准,然后通过扫描参数把性能调到设计目标。这篇文章就围绕这两件事展开,把Lumerical里的模型设置、脚本调用、数据后处理、扫参思路和踩坑记录一次讲透。
1. 案例定位:环形谐振器第二三部分到底在算什么
1.1 官方案例的进度定位:第二三部分在学什么
Lumerical官方的环形谐振器案例,一般沿着“结构搭建 → 基本透射谱 → 参数扫描优化”的路径推进。第一部分通常是把硅波导、环形波导、衬底、包层这些几何结构建起来,然后跑一次仿真看一眼场分布,确认光确实耦合进了环,这部分偏“能跑就行”。到了第二、第三部分,重点就不再是“看光进去没有”,而是“光的传输特性到底怎么样”——也就是要把透射谱这条曲线算出来,并且能从曲线里读出谐振波长、品质因子Q、消光比ER、自由光谱范围FSR这些工程参数。
我给读者的建议是,不要急着照抄教程里的每一步操作,先把自己代入设计师的角色:现在要设计一个工作波段在1550nm附近的环形谐振器滤波器,我需要知道这个环在哪个波长谐振、谐振深度够不够、带宽是否符合要求——这些问题的答案全部藏在透射谱里。第二三部分就是教你怎么把这些答案挖出来。
1.2 从结果反推物理:透射谱、Q值、消光比和FSR
先把这几个常用指标的定义理一遍,因为后面所有操作都围绕它们展开。
透射谱是直波导输出端的功率随波长的变化曲线。环形谐振器的核心特征就是谐振波长处出现一个下陷(notch),非谐振波长的光基本无损通过。这个下陷的波长位置由谐振条件决定,下陷的深度由耦合状态决定,下陷的宽度由环内损耗和耦合强度共同决定。
Q值是品质因子,通俗地讲是“光在环里能存多久”的度量,Q值越高,谐振峰越尖锐,波长选择性越好。用透射谱计算Q值的标准方法是:Q = λ₀ / Δλ,其中λ₀是谐振波长,Δλ是谱线半高全宽(FWHM)。消光比ER则代表谐振深度,单位是dB,公式为ER = 10·log₁₀(T_max / T_min),T_max是非谐振透过率,T_min是谐振点透过率,实际器件中我们总希望ER尽可能大。
FSR是自由光谱范围,指相邻两个谐振峰之间的波长间隔。对于微环谐振器,FSR≈λ²/(2πR·ng),其中R是环半径,ng是波导群折射率。这个公式后面扫半径参数时会经常用到,先记在小本子上。
这部分我特别想强调的是,仿真不是跑出几张彩色图就完了,而是要从图中“提参数”。第二三部分的核心能力训练,就是把一张透射率曲线变成一行可以写进设计报告的数字。
2. 仿真建模细节:决定Ring Resonator仿真成败的四个关键设置
2.1 几何参数与材料参数:模型质量的地基
环形谐振器仿真结果准不准,一半取决于几何和材料。FDTD是直接求解麦克斯韦方程的数值方法,材料折射率给错了,后面一切分析都失去意义。
官方案例通常基于SOI(Silicon-on-Insulator)平台,常见参数是:硅波导厚度220nm或250nm,波导宽度450nm到500nm,环半径在3μm到10μm之间,直波导与环之间的耦合间距gap从100nm到500nm不等。我建议你在建模型时把波导宽度、环半径、gap这些参数全部用变量定义,而不是写死数字。这是因为第三部分的参数扫描必须靠变量驱动,写死数字后面只能在GUI里一个一个改,效率极低。
材料这块Lumerical自带硅和二氧化硅的折射率数据,但要注意频带范围。如果你仿真波长范围不是常见通信波段,要确认材料折射率数据覆盖了这个范围,否则仿真出来的色散曲线是错的。另外,如果涉及空气包层,折射率设成1就好,不需要建空气实体,边界条件会默认包层是背景折射率。
我踩过的一个坑是忘记设置背景折射率。在Lumerical FDTD里,背景折射率默认是1(空气),如果你的结构是埋在二氧化硅里的,需要把背景折射率改成1.44左右(SiO₂的折射率),不然模式场分布和有效折射率都会偏不少。
2.2 网格设置与仿真区域:精度和时间的平衡
FDTD方法的核心就是空间网格,网格尺寸决定了能解析的最小结构特征和仿真时间。网格太粗,谐振波长会偏移;网格太细,内存和计算时间成倍增加。这里的核心矛盾是:环形谐振器的波导界面非常薄(220nm),但谐振腔结构又很大(半径几微米),全区域用细网格完全不现实。
Lumerical的解决方案是mesh override region(网格覆盖区域)。官方案例的常规操作是,在波导横截面区域单独加一个覆盖网格,把网格精度强制设为5nm或10nm,而结构外围区域保持较粗的默认网格。这样既保证了波导模式计算的精度,又不至于把整个仿真区域的网格全部加密。
网格精度的选择有一个判断标准:做一次网格收敛性检查。具体方法是把关键区域的网格从10nm改成5nm,观察谐振波长移动多少。如果移动量小于你的设计容差(比如0.1nm),那10nm就够用了;如果移动了十几个纳米,说明网格严重不足。仿真是不能追求“一次性完美”的,它是个迭代逼近的过程。
关于仿真区域,FDTD边界一般用PML吸收边界,结构距离PML至少要留半个波长的距离,否则边界会截断倏逝场,导致透射谱出现不正常的波纹。环形谐振器的泄漏场主要集中在水平和垂直方向,所以仿真区域在竖直和水平方向要留足够余量。
2.3 激励源与监视器:数据从哪里来
透射谱仿真中,激励源一般用模式源(Mode Source),设置在直波导的输入端,方向指向波导传播方向。模式源需要指定模场阶数、偏振方向和传播方向。对于标准矩形波导,TE基模一般是默认选项,但还是要确认你的模式源对准的是哪个模式,因为模式没选对,耦合进环的效率也会完全不同。
监视器方面,要做透射谱分析,至少需要两个关键监视器:一个放在直波导输出端,用于记录透射功率;另一个如果放在环内,可以记录环内功率,帮助判断耦合状态。功率监视器记录的是通过某个平面的总功率,要选对输出数据的类型——频率响应Profile还是功率P。建议直接使用脚本提取,因为GUI里手动导数据实在太烦了。
监视器的位置不能贴着波导拐角或者弯曲部分太近,要放在模式稳定的直波导段,否则会引入高阶模的影响。我一般在波导输入端和输出端各留1μm以上的直段,在直段中间放监视器。
2.4 用Lumerical脚本批量控制仿真:从GUI到自动化的关键一步
标题热词里“Lumerical怎么调用脚本”是很多人搜的,确实,案例做到第三部分开始参数扫描时,毫无疑问要写脚本。Lumerical FDTD自带基于Lumerical Script的脚本语言,语法上类似MATLAB,可以直接在脚本编辑器里写循环、调用run、提取结果。用脚本控制仿真的好处不只是批量跑,更重要的是可复现——你的参数、设置、数据处理流程都写进脚本里,以后改个半径重新跑一遍,几分钟就搞定。
一个最简的扫参脚本结构大概是这样的:
gap_list = [100e-9, 150e-9, 200e-9, 250e-9, 300e-9]; for (i = 1:length(gap_list)) { setnamed("ring", "gap", gap_list(i)); run; T = getresult("output_monitor", "T"); # 把T数据保存到文件,或者直接在脚本里做计算 t = T.T; lambda = T.lambda; filename = "gap_" + num2str(gap_list(i)*1e9) + "nm.mat"; matlabsave(filename, t, lambda); }这段脚本做的事情是遍历不同gap值,每次修改环的gap参数后重新运行仿真,再把输出监视器的透射谱保存下来。注意setnamed用的是结构名称而不是变量名,所以建模型时给结构起个靠谱的名字非常重要,否则脚本里到处是“structure group:UNNAMED”,想优化都没法下手。
脚本里还有一个好处是可以自动计算Q值和ER。等跑完所有gap,可以再写一段后处理脚本把mat文件全部读回来,提取谐振谷和半高宽,这样一张“gap vs Q值、gap vs ER”的设计曲线就出来了。
3. 透射谱分析实操:从数据到S参数、Q值、消光比
3.1 从监视器导出数据的标准流程
仿真跑完,数据在监视器对象里。Lumerical中可以用getresult命令把数据提取到脚本环境里,也可以直接右键监视器选择Export Data。不过GUI导出一次只能导一个监视器,手动操作繁琐且容易遗漏,我一般直接在脚本编辑器里统一处理。
标准流程是先用list命令查看监视器有哪些数据组,然后getresult取数据,最后保存或绘图。代码示例:
# 查看输出监视器拥有的所有数据组 monitor = "output_monitor"; list(monitor); # 提取透射率数据组 T_data = getresult(monitor, "T"); lambda = T_data.lambda; T = T_data.T; # 直接画图 plot(lambda*1e9, T, "Wavelength (nm)", "Transmission");这里T是一个矩阵,如果仿真中用了不同偏振分解,T可能不止一行。一般只关注基模的透射率,所以取T的第一个元素或者按模式索引挑选。另外要注意lambda的单位是米,画图时通常转成纳米。
3.2 用数值结果计算Q值、消光比和FSR的脚本模板
拿到透射谱之后,后处理的核心工作是找谐振谷、算深度、算半高宽。这里给一段我常用的处理脚本逻辑,可以直接抄进Lumerical脚本编辑器或者把数据导到Python里处理。Lumerical脚本里找极值可以用local min判断,但最简单的还是在Python里利用scipy的find_peaks。下面先给Lumerical脚本的版本:
# 找到谐振波长的近似位置:先找透射率的最小值 minT = 1e9; minIdx = 1; for (i = 1:length(T)) { if (T(i) < minT) { minT = T(i); minIdx = i; } } lambda_res = lambda(minIdx); T_min = minT; # 找半高全宽:以基线的50%为阈值,找左右交点 T_baseline = mean(T(length(T)*0.2:length(T)*0.8)); T_half = (T_baseline + T_min)/2; # 在谐振谷左侧找穿过T_half的索引,右侧也同样处理 # ... 插值求交点,这是数值细节注意这里半高宽是基于功率透射率还是线性幅度,要分清楚。FDTD监视器输出的T一般是功率,所以半高宽计算时直接用功率阈值是合理的。Q值计算公式中的“半高全宽”严格来说是谐振峰在功率谱上的3dB带宽,对应T值为峰值的一半(在线性功率坐标下),所以上面的阈值算法是对的。
如果你习惯把数据拿到Python里处理,则可以用scipy.signal.find_peaks快速定位;但要注意透射谱的谷不是峰,需要把T取反再找峰。文件导入用scipy.io.loadmat读取matlabsave保存的.mat文件即可。
ER的计算直接取T_baseline与T_min的比值,换算成dB:
ER_dB = 10 * np.log10(T_baseline / T_min)FSR的计算更简单,找到两个相邻谐振谷的波长,相减即可。
3.3 谐振条件与模式展开的对照
跑完透射谱以后,一定要把仿真得到的谐振波长和解析公式对照一下,这是验证模型可靠性的关键一步。环形谐振器的谐振条件是:光沿环传播一圈的相位变化是2π的整数倍,即β·2πR = 2πm。用有效折射率neff表达就是2πR·neff/λ = m,化简得到谐振波长λ_res = neff·2πR/m。
注意这里有个初学者容易掉坑的地方:公式里的neff是相折射率(phase index),但仿真里我们经常接触的是群折射率ng。实际微环的谐振波长随着波长变化,neff本身也会变(色散),所以更严格的计算应该用群折射率来推算FSR。FSR的公式Δλ = λ²/(2πR·ng)就是这个原因。
举个例子,假设R=5μm,ng≈4.2,λ₀=1.55μm,那么FSR≈1.55²/(2π×5e-6×4.2)米≈18.2nm。如果你的仿真结果里两个谐振谷间隔明显偏离这个值,多半是波导色散设置或者模式有效折射率出了问题。这种“仿真数据 vs 理论估算”的交叉验证,比单纯看仿真软件是否报错更重要。
4. 参数扫描与设计优化:从单点仿真到设计空间探索
4.1 耦合间距gap扫描的设计思维
第三部分的核心内容是参数扫描,其中最重要的参数就是直波导与环之间的耦合间距gap。gap决定了耦合强度,而耦合强度直接决定器件的Q值和消光比。
小gap时,耦合强,光很容易从直波导进环再回到直波导,环内储能相对降低,所以Q值偏低,透射谷变宽;当gap很小到一定程度,可能出现过耦合状态,此时透射谷深度反而变浅。gap很大时,耦合弱,环内损耗占比上升,Q值变高,但透射谷也会越来越浅,因为大部分光根本没耦合进环。所以在某一个中间gap值,存在一个“临界耦合”点,此时透射谷深度最深,也就是ER最大。
第三部分常要求做一组gap扫描,比如从100nm到300nm,步长20-50nm。每次改gap都要重新跑仿真,这时候就体现出脚本批量运行的价值了。跑完把所有透射谱叠画在一起,你会看到非常直观的变化:gap越大,谷越窄但也越浅;gap越小,谷越深但越宽。设计者需要根据实际需求选择:如果要高Q值窄带宽,接受较低的ER;如果要高消光比,gap就取临界耦合附近。
4.2 半径R扫描与谐振波长调谐
另一个常见扫描参数是环半径R。半径改变带来的第一个直接后果是谐振波长移动,根据公式λ_res = neff·2πR/m,半径变大,谐振波长红移;半径变小,蓝移。第二个后果是FSR变化,R越大,FSR越小,也就是说在同样的工作波段范围内,谐振峰排布更密。
做半径扫描时还要注意一个坑:当半径变化以后,弯波导的弯曲损耗会发生变化。半径太小时弯曲损耗急剧增大,透射谷会越来越浅甚至看不到明显的谐振峰;半径太大时又丢失了微环小尺寸的优势。所以半径并不是越大越好,要结合工艺条件和器件尺寸约束来看。
扫R和扫gap不一样的地方在于,R每次变化后,模式源的有效折射率也会变化。如果模式源设置的是“用当前波导结构自动计算模式”,那没问题;如果模式源固定了一个特定有效折射率,就要重新校正了。
4.3 从单点仿真到批量扫参的落地方法
当你打算系统扫两个参数时,比如gap和R同时扫,就进入了“参数扫描矩阵”的领域。在Lumerical里可以用Optimization and Sweeps窗口里的Sweep工具,也可以用脚本直接写双重循环。两种方法各有优劣,Sweep工具界面友好、可以设置并行任务,但灵活性一般;脚本更灵活,可以一边扫一边做后处理,我倾向于用脚本。
扫双参数时,建议先把所有组合列出来,按从快到慢的顺序跑。先跑粗网格快速预筛,缩小最佳参数范围,再在附近用细网格精确扫描。这就像做实验先粗调再微调,盲目全精度扫描非常浪费时间。
如果内存充裕,可以同时开多个仿真任务并行,Lumerical支持并行运算。但要注意每个任务都会占用固定内存,开多了反而可能因为内存不足导致仿真发慢甚至失败。我一般根据本机内存大小,控制在同时跑2到4个仿真。
4.4 优化结果的二次验证:网格收敛性不可跳过
参数扫描找到一组看着不错的参数以后,千万不要直接拿去用。我强烈建议再做一遍网格收敛性检查:针对最优参数,把关键区域网格加密一倍,重新仿真,对比谐振波长和Q值变化多少。
为什么这一步很重要?因为扫描过程中如果网格设置保持不变,不同参数之间的相对趋势是可信的,但绝对数值可能系统性偏移。如果最终设计用于工程流片,这个偏移会造成实际器件谐振波长偏离设计值。网格收敛试验是验证仿真可靠性的最低成本方法。
我也遇到过另一种情况:粗网格下gap扫描显示某个gap点ER最大,但加密网格后最佳gap点偏移了10nm左右。这就是网格误差对耦合系数的影响。虽然趋势对了,但最佳工作点需要重新确认。
5. 常见问题与排查技巧实录
5.1 曲线显示红线和发散问题怎么排查
很多人在跑FDTD时都会遇到监视器输出的曲线不是正常的透射谱,而是一条红得扎眼的异常曲线,甚至直接显示NaN或者Inf。这通常不是模型“坏了”,而是数值仿真不稳定。
最典型的原因是网格太粗或者材料参数非常规,导致FDTD时间步进中积累的数值误差越来越大,最终场幅度爆炸。Lumerical默认会自动设置时间步长以满足Courant稳定性条件,一般不会因为dt本身出问题。出现发散时,重点检查两处:一是材料折射率是否设成了复数,而且虚部符号正确(增益还是损耗写反会导致能量不守恒);二是PML边界是否离结构太近,反射信号不断被放大。
另一种“红线”情况是,你盯着功率监视器的时域信号看,发现它迟迟不衰减到零。这其实不是发散,而是因为高Q环形谐振器在仿真时间内还没把能量耗散完,跑出的透射谱有截断误差。解决办法是延长仿真时间(simulation time),例如从默认的1000fs加到2000fs以上,直到时域信号衰减到峰值的一小部分。判断标准很简单:时域信号归零,频域结果就准;不归零,频谱就会抖动。
5.2 透射谱不平滑、PML反射、监视器放置问题
透射谱上出现不自然的波纹,大概率是PML反射或监视器位置不合理。PML虽然能吸收大部分入射光,但总会有少量反射,尤其大角度入射时。环形谐振器的倏逝场在水平方向可能在PML边界有一定入射角,如果PML层数太少,反射波纹就会叠加到透射谱上。
处理办法:增加PML层数(从默认的8层调到16层),或者把仿真区域整体扩大。代价是计算时间变长,但对最终结果的可靠性帮助很大。监视器放置也不容忽视:监视器如果太靠近波导弯角、PML或光源,会记录到不必要的干扰模式。经验值是与弯角保持一个直波导段距离,至少2~3μm。
5.3 脚本和界面操作常见问题
关于“Lumerical打开后各个窗口界面比例不协调”,这个问题确实让人抓狂。有时候脚本编辑器或者Object Tree窗口拖乱了,恢复的办法是在View菜单里选择Reset Layout或者Default View,窗口会回到默认布局。如果还不行,关掉软件删除用户配置文件再打开,通常能解决。
调用脚本时新手常犯的一个错误是getresult的监视器名称写错。脚本报错说找不到对象时,首先用list列出当前所有对象名,看看你的监视器是不是叫“output_monitor”,还是软件自动加了一串后缀。用GUI创建的监视器名称可能带空格,在脚本里引用时要用引号括起来。
另外要注意,脚本里的run命令是同步运行还是异步运行。默认情况下run执行完毕才会返回,但如果你在Sweep里并行跑多个任务,要注意变量隔离,不同任务不要共用同一个文件名,避免写文件互相覆盖导致数据丢失。
5.4 常见问题速查表
| 现象 | 常见原因 | 解决思路 |
|---|---|---|
| 时域监视器红线不再衰减 | 高Q腔没跑够时间 | 延长simulation time,检查时域能量衰减 |
| 透射谱出现NaN/Inf | 网格问题或材料折射率异常 | 细化关键区域网格,检查材料模型 |
| 透射谱有规律波纹 | PML反射或监视器离结构太近 | 增加PML层数,扩大仿真区域,移动监视器 |
| 谐振波长与理论偏差大 | 网格精度不足或材料色散不准 | 做网格收敛检查,确认材料折射率数据 |
| 扫描脚本报错找不到对象 | 对象名写错或带空格 | 用list列出对象名后核对引用 |
| 软件窗口布局乱套 | 界面配置损坏 | 用Reset Layout恢复默认布局 |
| 仿真时间过长 | 仿真区域过大或网格过细 | 缩小非关键区域,使用symmetry边界 |
排查思路的核心是“分离变量”:先确认单个参数变化时的响应是否平滑,如果某个参数微调导致结果剧烈跳变,说明数值稳定性出问题了;如果结果平滑,再去看物理合理性。这种排查方式能帮你快速定位问题出在模型还是设置。
我自己跑环形谐振器案例最大的体会是:FDTD仿真工作量的八成不在“跑通”,而在“跑准”。第二第三部分教的不只是几个按钮的操作顺序,更是一种工程思维——拿到透射谱以后,知道怎么判断它准不准,怎么从中提取设计参数,怎么通过扫描找到最优解。把这一套流程走通,后面无论做微环调制器、微环传感器还是其他微纳光子器件,基本思路都是相通的。
最后分享一个我当时折腾很久才想明白的小技巧:当你对某一组参数做精细设计时,先跑一个短时间、粗网格的快速扫描确定大致趋势,再对最有希望的区域做高精度仿真。不要一上来就全精度扫描,那样一天只能跑几个点。仿真工程师的时间,一半花在合理规划计算资源上。