
1. 环形谐振器仿真选型为什么我最终锁定了Lumerical FDTD刚接触硅光子方向的同学十有八九第一个要上手仿真的器件就是环形谐振器。这玩意儿结构看着简单——一根直波导旁边再绕一圈环但真要拿Lumerical跑出漂亮的反谐振谷涉及的坑一点都不少。我最早读研那会儿导师随手甩给我一个lumerical-环形谐振器的题目我以为是套模板算算透射谱结果光是把光谱跑收敛就折腾了两周。先别急着打开软件。在动手之前必须把环形谐振器到底在仿真什么这件事想清楚。环形谐振器本质是一个波长选择器件光从直波导Bus传过来一部分通过倏逝波耦合进环形波导在环里绕圈当绕圈一周的相位恰好是2π的整数倍时满足谐振条件能量就在环里累积并从另一侧输出或损耗掉。表现在透射谱上就是直通端出现一个个周期性的凹陷。1.1 先把环形谐振器的几个核心参数对齐仿真之前我习惯先把下面几个参数写在纸上避免后面被一堆曲线带偏。自由光谱范围FSR相邻两个谐振峰之间的波长间隔。计算公式是 FSR ≈ λ² / (ng × L)。其中L是环的周长ng是群折射率。比如一个半径5μm的硅波导环周长约31.4μm取ng4.2在1550nm波长附近FSR算下来大约是18nm。这个值决定了器件的工作带宽也决定了你仿真时波长扫描范围至少要覆盖一个FSR以上。品质因子Q值Q λ0 / Δλ其中Δλ是谐振谷的3dB带宽。Q值直接反映谐振器储存光能的能力。无源硅环的Q值从几千到几万都很常见但要注意仿真里的Q值可能混入很多数值假象这一点我后面专门用一整章讲。消光比ER透射谱中通带最大值和谐振谷最小值的比值。临界耦合时直通端的透射功率可以掉到接近0消光比非常漂亮。耦合状态环和直波导之间如果耦合太弱叫欠耦合太强叫过耦合恰好让环内损耗等于耦合进环的功率时叫临界耦合。透射谷的深度和形状能直接反映处于哪种状态。这四个参数决定了你在Lumerical里要扫哪些几何量、设多宽的波长范围以及最后怎么评估仿真结果。1.2 方法选型为什么不用varFDTD或EMELumerical套件里能算环形谐振器的工具不止一个FDTD、varFDTD、MODE本征模求解器、EME都有各自适合的场景。很多人上来就点开FDTD其实不一定是最高效的选择。varFDTD适用于平面方向变化平缓、纵向结构固定的波导器件优点是快。但环形谐振器的弯曲波导存在强弯曲效应模式在弯曲处的场分布会发生偏移varFDTD在曲率半径较小的场景下精度会打折扣。如果你的环半径只有3~5μm我不建议用varFDTD做最终设计验证。MODE/Eigenmode求解器适合算波导截面模式、有效折射率用来快速估算波导宽度和高度对neff、ng的影响。环形谐振器设计前期可以用它来定波导截面参数但没法直接给出整个器件的透射谱。EME擅长处理沿传播方向分段均匀的结构比如绝热锥形波导、多模干涉器对环形这种闭合回路并不友好。FDTD直接把Maxwell方程在空间和时间上离散求解能完整处理弯曲波导的辐射损耗、模式转换、背向反射对环形谐振器这种强反馈结构是最稳妥的选择。代价是计算量大尤其是三维模型。所以我的结论很明确设计前期用MODE快速定波导截面器件级验证和参数扫描用三维FDTD。后面的内容全部围绕三维FDTD展开因为环形谐振器的透射谱、Q值、耦合状态这些核心指标只有它算得准。2. 开工前的环境驯服界面比例失调与固定检查项Lumerical的FDTD软件界面如果第一次打开很多人第一反应是这布局怎么这么乱。尤其是搜lumerical打开后各个窗口界面比例不协调的人大概率遇到过Object Tree区域窄得看不清名字或者Script Prompt窗口占了半个屏幕的情况。2.1 窗口比例不协调的两种典型场景及解法我见过最多的界面问题有两种。第一种是高分屏DPI缩放导致整体错乱。Windows系统如果开了125%或150%缩放Lumerical的各个子窗口可能挤在一起或者字特别大、工具按钮被截断看起来就是比例不协调。这种情况去改软件兼容性设置——右键Lumerical启动图标选属性在兼容性里勾选替代高DPI缩放行为由应用程序自己控制缩放通常能解决。如果还不行把显示器的缩放调回100%再重启软件也是最粗暴有效的办法。第二种是误拖拽后布局被改乱。Lumerical的Object Tree、Layout Editor、Script Prompt这些窗口之间都有可拖拽的分隔条手一滑就把某个面板拖成细条。解决办法也很直接——把鼠标放到分隔条上拖回到合适位置。如果乱到救不回来直接在菜单栏找View里的Layout重置选项或者关闭软件后删除用户配置文件路径一般是%APPDATA%\Lumerical让软件重新生成默认布局。注意删配置之前先把脚本和仿真文件存好。2.2 建模前必须固定的材料、单位和物理设置界面理顺以后先别急着画环。FDTD建模的坑一小半在网格一大半在设错材料或单位。我每次新建项目后固定做四件事单位在Model菜单里把长度单位设成nm或μm。硅光子器件动辄几微米用默认的m会导致数字后面跟一大串0手输参数时很容易多敲或少敲一位。我个人习惯用μm因为波导宽度500、厚度220这种数字在Lumerical里直接对应几何尺寸的数值。材料库硅波导材料要选中实际可用的光学模型。SOI平台最常用的是SiSilicon和SiO2Silicon Dioxide材料库里自带Palik折射率数据覆盖通信波段。注意材料库里还有一个Si (Silicon) - Palik和单纯的Si之分选带Palik数据的那种折射率有色散仿真结果才可信。背景材料Background Material设成SiO2表示埋氧层和上包层。别问为什么会有人把背景设成空气那是我第一次仿真出来的谐振波长偏了十几纳米的教训。FDTD仿真区域Lumerical默认的仿真区域往往过大或过小。对于环形谐振器仿真区要包裹住环和直波导但也不能大到让PML边界离结构太远。我一般让PML边界离波导外壁至少1μm这样既不引入边界反射又不浪费计算资源。光源和监视器的习惯命名先建好光源、监视器并命名成T_bus、source_in这样一眼能看懂的名字。后续用脚本批量处理时良好的命名习惯能省下大量排除命名错误的时间。这些检查看起来琐碎但步骤错一点后面整个光谱都可能不对。尤其是材料模型我用一句话总结先用默认Palik数据别玩花活。3. 环形谐振器建模从几何到光源监视器的完整链路环形谐振器的三维FDTD模型说复杂也复杂说简单也简单。把几何画对、光源放对、监视器摆对、网格设好四步走完就能跑出个大概。3.1 环的几何怎么画最稳建模方法上Lumerical里有现成的环结构也可以在Layout里画两个同心圆然后做布尔减运算得到环。我更推荐用现成的圆环对象因为参数化方便——半径、波导宽度、高度直接改数字后面扫描半径时不需要重建几何。关键几何参数我列一下以220nm SOI平台为例参数典型值说明波导高度220 nmSOI顶层硅厚度工艺固定波导宽度500 nm单模TE波导兼顾弯曲损耗环半径5~10 μm中心到波导中心的距离耦合间隙100~300 nm直波导与环的间距影响耦合系数刻蚀深度全刻蚀220nm全刻蚀或部分刻蚀看工艺画完环再画一根直波导矩形结构即可长度为仿真区宽度的两倍以上确保模式光源能稳定起激励。直波导的纵轴线要与环的边缘相切并且之间留下耦合间隙。这里有一个很容易忽视的地方耦合间隙的定义。有些教程里gap指的是直波导边缘到环边缘的距离有些则定义成两个结构中线之间的距离。Lumerical里直接用对象的x/y坐标和尺寸来控制更直观。我习惯在直波导和环之间建一个参数化变量gap然后把直波导的y坐标写成和gap相关的表达式这样后面扫描间隙时不需要手动移动波导。3.2 模式光源、透射监视器和FDTD边界配置几何模型搭好后下一步是设置光源和监视器。**模式光源Mode Source**是环形谐振器仿真最常用的光源。它会在直波导截面处激发指定模式的场分布。设置时要注意三点位置放在直波导上离环的耦合区足够远一般至少隔3~5μm确保入射的是稳定的波导模式方向选择正向forward模式选择用fundamental TE基础TE模这是大多数硅波导环形谐振器的工作模式。你可以在Mode标签页里查看计算的模式场分布确认它确实被约束在波导里。透射监视器放在直波导的另一端用来记录透射功率。监视器的平面要垂直于波导传播方向并且尽量贴紧仿真区边界避免把散射光也算了进去。如果想同时看环内的能量积累可以再加一个场分布监视器Profile Monitor放在环的正上方观察谐振时环内的驻波分布。FDTD边界条件默认是PML完美匹配层吸收反射波。对于环形谐振器PML是可靠的只要仿真区够大、PML层数足够默认就够不会产生明显的边界反射。如果器件关于x轴或y轴对称并且光源也是对称模式可以把其中一个方向的边界设为Symmetry对称/反对称计算量直接减半。这一点很多人到仿真跑不动了才想到后面我会细说。3.3 网格覆盖弯曲波导的数值损耗陷阱网格设置是整个环形谐振器仿真里最影响结果质量的一步。FDTD是空间离散算法网格越粗结构边界越锯齿化。对直波导来说粗网格最多让有效折射率偏一点但对弯曲波导锯齿边界会带来额外的数值散射损耗直接导致谐振器的Q值变得很不真实。我的做法是在环和耦合区域套一个网格覆盖区Mesh Override Region把步长细化到20nm以内。以1550nm波长、硅折射率约3.45为例基模在硅中的波长约为450nm20nm的网格大约对应λ/8到λ/10的采样密度对于弯曲结构是性价比比较高的选择。注意网格覆盖区不要覆盖整个仿真区只覆盖环、直波导的耦合段以及两者之间的间隙即可。网格越细时间步长越小计算时间按非线性增长全仿真区细化会让人等到怀疑人生。收敛性验证是网格设置的最后一环。同一个设计分别用50nm、30nm、20nm网格跑一遍对比透射谱和谐振波长。如果三次结果中谐振波长偏移小于1nm、Q值变化在合理范围内说明网格已经收敛如果还在剧烈变化那就是数值效应掩盖了物理结果需要继续细化或用更高阶网格。这一步虽然耗时但能避免你在错误的仿真结果上浪费更多时间。4. 用脚本把环形谐振器扫参跑起来Lumerical调用脚本的实战姿势手动建模跑单次仿真可以但环形谐振器的设计几乎必然涉及参数扫描——扫耦合间隙、扫半径、扫波导宽度。这时候就要靠脚本了。4.1 Lumerical脚本的三种调法Lumerical支持多种脚本调用方式我按使用频率排个序脚本编辑器直接运行在布局界面下方有Script Prompt可以直接敲命令也可以打开完整的脚本编辑器写好一整个.lsf脚本文件后用File菜单里的Run Script运行。这是最基础、最稳的方式。调试时可以一段段执行看到变量值。外部Python API调用Lumerical提供了lumapiPython模块。在Python环境里import lumapi然后创建一个FDTD实例建几何、设光源、跑仿真都可以做。更实用的是把整个.lsf脚本当成字符串传进去fdtd.evalscript(...路径/xxx.lsf)。这样你可以在自己熟悉的Python环境里写后处理逻辑Lumerical只负责算。我现在的流程基本是Python脚本生成lsf参数组合 → 调用FDTD批量跑 → 再读结果回Python绘图。命令行调用用命令行直接运行Lumerical的脚本文件适合服务器批量提交任务。每个版本的命令略有差异核心思路是在命令行指定仿真文件和脚本路径让FDTD在后台运行。这个方法配合服务器排队系统可以一次性把几十组参数跑完。对于新手我建议先掌握第一种把脚本语言的基本命令练熟再过渡到Python API。因为Lumerical脚本的错误提示比较直观能帮你快速理解对象层级关系。4.2 一个可复用的耦合间隙扫描脚本下面这个脚本是我早期跑环形谐振器的骨架用来扫描耦合间隙。伪代码里省略了一些和具体版本相关的细节但整体思路完全可以直接套到你自己的模型上。# 进入布局模式 switchtolayout; # 清理当前对象 selectall; delete; # 定义设计参数 w 0.5; # 波导宽度单位um h 0.22; # 波导厚度 radius 5; # 环半径 gap_start 0.10; gap_end 0.30; gap_num 5; # 添加衬底可选用SiO2背景更省资源 addrect; set(name, buried_oxide); set(x span, 20); set(y span, 20); set(z min, -2); set(z max, 0); set(material, SiO2 (Silicon Dioxide) - Palik); ... # 添加硅波导层 addrect; set(name, si_layer); set(x span, 20); set(y span, 20); set(z min, 0); set(z max, h); set(material, Si (Silicon) - Palik); # 添加环 addring; set(name, ring); set(x, 0); set(y, 0); set(z min, 0); set(z max, h); set(inner radius, radius - w/2); set(outer radius, radius w/2); set(material, Si (Silicon) - Palik); # 循环扫描耦合间隙 for (i 1:gap_num) { gap gap_start (gap_end - gap_start)*(i-1)/(gap_num-1); # 直波导位置随gap变化 addrect; set(name, bus_waveguide); set(x span, 20); set(y span, w); set(z min, 0); set(z max, h); set(y, radius w/2 gap); set(material, Si (Silicon) - Palik); # 模式光源 addmode; set(name, source_in); set(direction, forward); set(mode selection, fundamental TE); set(x, -8); set(y, radius w/2 gap); set(z, h/2); # 透射监视器 addpower; set(name, T_bus); set(monitor type, 2D Z normal); set(x, 8); set(y, radius w/2 gap); set(z, h/2); # 设置FDTD边界和仿真区 addfdtd; set(x span, 20); set(y span, 16); set(z min, -2); set(z max, 2); set(boundary conditions, {PML, PML, PML, PML, PML, PML}); # 添加网格覆盖 addmesh; set(name, mesh_ring); set(x min, -radius - 2); set(x max, radius 2); set(y min, -2); set(y max, radius 2); set(z min, -0.1); set(z max, 0.3); set(dx, 0.02); set(dy, 0.02); set(dz, 0.02); # 运行仿真 run; # 保存透射率数据 T getresult(T_bus, T); t T.T; wl T.lambda*1e9; # 转换为nm # 把结果按gap命名保存为mat或csv matlabsave(sprintf(g%dnm.mat, gap*1e3), t, wl); # 关闭当前项目防止对象累积 switchtolayout; selectall; delete; }这段脚本的核心思路很朴素用for循环把gap从100nm扫到300nm每个gap跑一次FDTD保存透射谱。几个细节值得说说每次循环后清空对象。忘了清空的结果就是第二次循环把新波导叠在旧波导上透射谱乱七八糟。用变量控制几何位置。直波导的y坐标始终用radius w/2 gap表达这样改gap时不用手动移动波导也不会出现耦合间隙算错的老问题。matlabsave存中间结果。Lumerical的.mat文件在Python里也能用scipy.io.loadmat读出来后面处理特别方便。4.3 扫参策略先粗扫后细扫参数扫描最忌讳一上来就全参数细扫。耦合间隙从100nm到300nm如果每一步只扫5个点可能完全错过临界耦合的间隙位置。我的习惯是先大步长粗扫找到透射谷最深、消光比最大的区间再在这个区间里用小步长细扫。同样波长扫描范围也要根据FSR来定——如果环半径5μm、FSR约18nm扫描范围至少25nm步长0.1nm起步。步长太粗会把谐振谷的深度拉浅后面的Q值提取根本没法用。5. 结果提取从透射谱到Q值、FSR与消光比仿真跑完一堆透射率数据在手接下来是把这些数据变成器件指标。很多人在这一步犯迷糊因为Lumerical默认给的是归一化透射率单位、坐标轴都要自己处理。5.1 把透射谱数据取出来如果用了前面的脚本结果已经存成了mat文件。读取数据后画透射谱——横轴是波长nm纵轴是透射率对数坐标dB。环形谐振器最典型的特征是等间隔的谐振谷。如果你看到谷底不在预期位置、谷深不对称先别急着调设计去检查采集数据的监视器位置和网格设置。以我上面脚本的例子透射谱在1550nm附近会有一个约几十dB的谐振谷。谐振波长的位置由环的光学周长决定相邻谷间距对应FSR。如果FSR和理论值差距超过5%大概率是群折射率设置或波导截面尺寸出了偏差。5.2 Q值提取3dB带宽法与洛伦兹拟合提取Q值有两个层次的做法。第一层直接用3dB带宽。在谐振谷的曲线上找到谷底最低点对应的波长λ0然后找到比谷底深3dB的两个点即功率降到谷底的一半这两个点之间的波长差就是ΔλQ λ0 / Δλ。这个方法简单直接但受离散波长步长影响比较大。如果扫描步长是0.1nm而谐振谷的3dB带宽本来就只有0.5nm你可能会得到非常粗糙的Q值。第二层洛伦兹拟合。谐振峰在频率域上通常符合洛伦兹线型。选取谐振谷附近的几十个数据点用洛伦兹函数做最小二乘拟合拟合出的半高全宽才更接近真实值。即使波长扫描步长不密拟合也能给出比直接读点更好的结果。这一步用Python scipy的curve_fit就能做非常快。我个人的经验是凡是准备写进论文的Q值都做一遍洛伦兹拟合直接读点只用来粗判数量级。5.3 用FSR和消光比反推器件状态从透射谱里能读出的远不止Q值。观察相邻两个谐振谷的间距FSR结合环周长可以反推群折射率ng λ² / (FSR × L)。这个反推值如果和MODE求解器算出的群折射率对不上说明环的有效周长被低估或高估了常见原因是耦合区场在直波导和环之间不是理想相切等效周长有偏移。观察谷底的深度还能判断耦合状态。临界耦合时谷底最深接近0透射过耦合时谷底变浅但谷形变宽欠耦合时谷底也浅但谷形更窄。扫描耦合间隙时如果你看到透射谷从深变浅又变深恭喜你你刚刚在参数空间里把临界耦合点附近扫出来了。这时候再去细扫把消光比最高的间隙锁定为设计值。6. 我在环形谐振器FDTD仿真里踩过的坑及排查链路下面这部分是我最想分享的。环形谐振器的FDTD仿真不是跑通就算完很多时候结果看起来合理实则全是数值假象。我用自己的踩坑经历反推一套完整的排查链路。6.1 谐振谷又浅又歪先从激励和监视器查起有一次我跑出来的透射谱谐振谷只有5dB深而且谷形明显不对称。第一反应是耦合间隙太大于是把gap从200nm一路扫到80nm谷还是浅。折腾了半天最后发现是模式光源的模式选择出了问题。我当时用的模式光源选了fundamental TE但模式计算是在一个很短的波导截面里做的计算收敛得不够好激励出的模式含有少量的高阶模分量。这些杂散模式在弯曲波导里不会被很好地约束辐射到包层里导致直通端功率被干扰。解决方法是把光源位置放在一段较长的均匀直波导上让模式充分稳定同时检查Mode标签页里模式的场分布确认没有明显的高阶模尾巴。这个问题的排查链路可以总结成透射谷浅时不是无脑加长仿真区或减小间隙而是先看光源模式纯度再看监视器是否把散射光也算进去了。6.2 Q值虚高或虚低网格收敛性才是关键另一段更难忘的经历是用50nm网格跑出一个Q值3万的结果高兴地拿给师兄看。师兄在环上套了一层20nm的细网格重跑一遍Q值直接掉到8000。后来又换了10nm网格Q值稳定在7500左右。原因就是弯曲波导的阶梯离散化。粗网格让弯曲边界产生人工散射损耗损耗小的时候Q值看似虚高但其实这个高Q并不是设计本身的高Q而是数值上漏算了损耗换细网格以后真实损耗暴露出来Q值就回到正常水平。另一面如果网格太粗导致模式被强烈散射Q值又会虚低。所以Q值是最依赖网格收敛性的指标没有之一。我的建议是每次改结构参数之前先对关键网格尺寸做一次收敛性验证确认在当前网格下Q值变化在可接受范围内。这个验证一旦做完后面扫参时的不确定性会小很多。6.3 谐振波长偏了半纳米材料模型与加工误差的思维谐振波长的位置由环的光学周长决定。仿真值和设计目标差个零点几纳米在硅光子领域几乎可以接受但如果偏了5nm以上就要认真排查了。第一次遇到这个偏差时我怀疑是自己的波导宽度输错了检查半天没发现问题。后来把材料从默认的Si (Silicon)改成Si (Silicon) - Palik谐振波长瞬间回正。原因是默认材料模型可能是常数折射率不包含随波长变化的色散而硅在1550nm附近的色散足以让谐振波长明显偏移。排除这个问题后还要注意工艺思维实际加工中波导侧壁不会是理想垂直会存在约几度的倾角光刻显影也会影响实际线宽。仿真时如果把波导宽度设定为500nm工艺实际可能得到495nm或505nm谐振波长自然跟着漂。所以做设计时一般会给波导宽度留一个相对宽松的窗口而不是死磕单一值。6.4 运算时间爆炸对称边界和仿真区缩小环形谐振器的三维FDTD非常吃内存和时间。一个半径5μm的环默认网格下可能要跑几十分钟细网格后可能直接小时级起步。我早期经常在等仿真结果时刷网页后来学会用对称边界效率翻倍。如果结构在某个平面两边完全对称并且光源也是对称模式就可以把该方向的边界设为Symmetry。以环形谐振器为例如果直波导和环关于x轴对称而激励的是TE基模那么关于x轴的边界可以用一个对称面PEC-like替代计算量减少一半如果是二维对称则可能是四分之一。另一个减负思路是缩小仿真区。PML边界不是越远越安全离结构太远纯粹是在浪费网格。我一般是先跑一次粗网格看电磁场分布确认场强在PML边界处已经衰减到足够低再据此收紧仿真区。6.5 最后分享一个小技巧用场监视器判断耦合状态排查了一圈之后如果你还是不确定环形谐振器当前处于什么耦合状态最直观的办法是加一个场分布监视器看谐振波长处环内的场强分布。临界耦合时直通波导里的光几乎全被耦合进环环内的电场强度非常高形成清晰的驻波图案而直通端几乎无场欠耦合时直通波导里的场还很强环内场相对弱过耦合时环内场很强但直通端也有明显的透射场。这个技巧在调试光谱谷形异常时非常管用一眼就能分辨出问题是出在耦合还是出在损耗。我自己的习惯是每做一个新环形谐振器设计第一步先不看透射谱先看谐振波长处的场分布图。它比任何参数曲线都直观能帮你快速确认几何和光源有没有设对。跑熟了以后这个习惯能省下大量无头苍蝇式的排查时间。