☰
FDTD模拟双缝干涉的Matlab仿真与PML/PMC边界条件解析
2026/10/3 4:05:34 网站建设 项目流程

最近在整理光学仿真案例时,翻到一套很有意思的Matlab源码:用FDTD方法模拟双缝干涉,并且把PML和PMC两种边界条件放进了同一个项目里。这套源码还附带一份光学综合实验报告,拿到手就能直接跑,适合拿来练手或做课程设计。双缝干涉是波动光学里最经典的现象之一,教材上讲起来很简单,但真要用数值仿真复现出来,涉及的细节其实不少:网格怎么剖分、边界怎么吸收、光源怎么注入、条纹怎么提取,每一步都能踩坑。PML负责吸收外边界反射,PMC用来利用对称性压缩计算域,两者配合可以把一个看似“高大上”的时域仿真变得非常可控。这篇文章就把这套项目从物理原理、参数设计、Matlab实现到报告写作完整走一遍,希望对正在做光学综合实验、FDTD入门或者双缝干涉仿真的同学有帮助。

1. 双缝干涉与FDTD:为什么要把两个概念放在一起

1.1 公式能算,为什么还要做数值仿真

双缝干涉的教材结论非常干净:两束相干光叠加,强度分布是一个cos²项乘上单缝衍射的sinc²包络,主极大位置由缝间距和波长决定。可一旦落到实物上,问题就变了。缝不是无限薄,金属屏也不是理想平面,观察屏可能离缝只有几个波长,边缘绕射、倏逝波、界面反射全都混在一起。解析公式只能帮你估算亮纹角度,真要看电磁场怎么在狭缝附近传播、怎么在后方重新叠加,还是得求解麦克斯韦方程组。

FDTD(时域有限差分)就是干这件事的:把空间切成很多小网格,时间也切成很多小步,反复迭代更新电场和磁场,直到电磁波在计算域里稳定下来。它的优势是直观,可以随时把某一时刻的场图导出来看,波前、衍射、干涉过程一清二楚。对于双缝干涉这种既包含传播又包含边界效应的场景,FDTD比纯解析公式更接近真实问题。这套源码的定位就是“用数值方法复现经典光学现象”,而不是简单画一条理论曲线。

1.2 PML和PMC在项目里的实际分工

FDTD只能在有限区域里计算,直接截断的话,电磁波打到边界会产生虚假反射,结果会完全变样。PML(Perfectly Matched Layer)就是为了解决这个问题:在计算区域外面加一层吸收材料,让进入PML的波被逐渐衰减,几乎不反射回计算域,等效于把边界推到无穷远。实际使用中PML层厚度、电导率渐变曲线都需要仔细调,不然反射照样存在。

PMC(Perfect Magnetic Conductor)则是另一种思路:它不吸收波,而是模拟理想磁导体边界。当仿真模型存在对称性时,可以在对称面上设置PMC,让计算域只保留一半甚至四分之一,从而节省内存和计算时间。这个项目里很有意思的一点,就是把外边界PML和内部对称面的PMC组合使用:PML负责吸收开放边界,PMC负责压缩模型规模,两者各管一件事。如果全模型四周都用PML也能跑通,但加上PMC之后,网格数量直接下降,跑起来明显快很多。

1.3 双缝“干扰”还是“干涉”

先纠正一个用词。标题里写的“双缝干扰”,我理解就是双缝干涉,英文interference本身兼有“干涉、干扰”两层含义,有些软件界面或早期译法会把interference pattern写成“干扰图样”。国内物理教材一般统一用“干涉”,所以下文都用“双缝干涉”。做仿真时候没必要纠结这个词,重点在物理模型和边界条件。

2. 仿真模型搭建:参数选型与边界配置

2.1 几何模型与光源设计

这套源码搭建的是二维FDTD模型,计算平面是x-z平面,狭缝沿y方向无限延伸。双缝屏放在z=0附近,光源从z负半轴一侧入射,透射后在z正半轴形成干涉条纹。几何参数不是随便拍的,要保证条纹清晰、计算量可控。我复盘时用的典型参数如下:

参数符号数值
真空波长λ633 nm
缝宽a800 nm
缝间距d4 μm
金属屏厚度t100 nm
网格步长dx = dz25 nm
计算域Lx × Lz16 μm × 32 μm
PML厚度Npml10 层
光源类型—连续正弦平面波

缝宽取800 nm,略大于波长,单缝衍射包络比较宽,不会把双缝干涉条纹“压死”。缝间距取4 μm,这样在观察屏上能分出至少五六条亮纹。网格步长取25 nm,大约是λ/25,既满足精度,又不会让Matlab数组太大。如果你用的是16GB内存的电脑,这套参数跑起来非常流畅。

光源我建议用连续正弦波,而不是高斯脉冲。脉冲源适合宽频分析,但要看单一波长下的稳态干涉条纹,连续正弦波更直接。入射电场设置为沿y方向偏振,也就是电场方向与狭缝长度方向一致。这样在二维FDTD里只需要更新E_y、H_x、H_z三个分量,计算量最小。

2.2 网格尺寸、时间步长怎么定

FDTD的网格尺寸直接影响数值色散。一般经验是网格步长至少取λ/10,想算得准一点就取λ/20甚至λ/30。这里取λ/25,已经是比较稳妥的选择。网格太粗的话,狭缝边缘会被“台阶化”,缝的有效宽度都不准,干涉条纹的位置自然对不上。网格太细则计算时间成倍增加,需要根据电脑性能权衡。

时间步长要满足CFL稳定性条件。二维情况下有:

[ \Delta t \le \frac{1}{c \sqrt{\frac{1}{\Delta x^2} + \frac{1}{\Delta z^2}}} ]

我习惯取这个上限的0.99倍,留一点余量,避免数值稳定性边缘出现问题。用上面参数算下来,一个时间步大约是0.06 fs量级,跑3000步也就180 fs左右。但要注意,电磁波要从光源位置传播到缝屏,再穿过整个观察区域,必须等到全计算域都建立稳定场之后才能采集数据。我实际跑下来发现,至少需要跑4000到5000步,条纹才会干净。如果只跑一千步,结果里会带着明显的“建立过程”痕迹,看起来就像条纹在抖动。

2.3 PML与PMC的边界组合方式

这套源码里,计算区域四周默认都设置PML。PML的厚度我建议从8层起步,10到16层更稳。PML内部电导率按位置渐变增加,阶数通常取3到4,这样从计算域到PML内部阻抗过渡更平滑,反射率可以压到-60 dB以下。太薄的PML虽然省内存,但会引入可见反射,干涉条纹上会叠一层周期性的“毛刺”。

PMC边界的使用要结合模型对称性。双缝屏和入射波关于中心平面x=0是对称的,TM偏振正入射时,对称面上的切向磁场为零,正好满足PMC边界条件,因此可以只模拟x≥0的一半区域。这样原来两条缝的模型就变成一条缝加一个PMC对称面,计算域直接砍掉一半。算完之后再把结果镜像翻转,就能得到完整干涉图样。源码里同时保留了全模型PML和半模型PML+PMC两套设置,方便对比验证。

3. Matlab源码实现:从Yee网格到条纹输出

3.1 主循环结构

Matlab实现FDTD的核心是Yee网格迭代。代码主体通常由三部分构成:初始化场数组和材料参数、进入时间步循环、循环结束后处理数据。这套源码的主循环结构大致如下:

% 初始化 Ey = zeros(Nx, Nz); Hx = zeros(Nx, Nz); Hz = zeros(Nx, Nz); % 时间步进 for n = 1:Nt % 更新 Hx 和 Hz Hx(2:end-1, 2:end-1) = Hx(2:end-1, 2:end-1) ... - dt / mu0 / dz * (Ey(2:end-1, 3:end) - Ey(2:end-1, 1:end-2)); Hz(2:end-1, 2:end-1) = Hz(2:end-1, 2:end-1) ... + dt / mu0 / dx * (Ey(3:end, 2:end-1) - Ey(1:end-2, 2:end-1)); % 更新 Ey Ey(2:end-1, 2:end-1) = Ey(2:end-1, 2:end-1) ... + dt / eps0 * ( ... (Hz(2:end-1, 2:end-1) - Hz(1:end-2, 2:end-1)) / dx ... - (Hx(2:end-1, 2:end-1) - Hx(2:end-1, 1:end-2)) / dz); % 源注入与边界处理 % ... end

上面只是示意,实际数组维度要对齐Yee网格,但核心逻辑就是这样:先更新磁场,再更新电场。材料参数中,金属屏区域可以用大的电导率近似PEC,也可以直接在电场更新时把对应位置的场强强制置零。两种写法都能出结果,但后者更简单,跑起来也更快。

3.2 PML和PMC的代码落地

PML的代码不是简单地“给边界乘一个小数”,那样会造成阻抗不匹配。工程上常用分裂场PML或CPML。这套源码采用的是经典的PML实现方案:在PML区域内把场分量拆分,并引入辅助变量记录吸收项。电导率沿PML深度方向呈多项式渐变,比如:

sigma_x = sigma_max * (x_in_pml / thickness_pml)^order;

sigma_max和阶数需要调。我的经验是阶数取3,sigma_max取几个S/m量级,反射率就能压得很低。如果你初次写PML,可以直接套用已有模板,重点看两个地方:一是PML区域内的场更新公式是否加了辅助变量,二是PML与内部区域交界处有没有“硬接线”式的突变。

PMC的代码实现比PML简单很多。在对称边界处,只需要把边界上的切向磁场分量强制置零,或者把磁场更新时跨过边界的项做镜像处理。举个例子,如果PMC边界在z=1这一层,那么需要保证这一层边界上的切向H为0,更新代码里区分“内部节点”和“边界节点”即可。这种处理方式比PML直观多了,但前提是物理上确实满足对称条件。

3.3 从场分布到干涉条纹的提取

跑完时间循环后,不能直接看某一时刻的瞬态场,因为瞬态场里既有入射波也有反射波,条纹并不干净。需要等稳态建立后,在一个完整周期内记录电场幅度值。常见做法是记录场强的峰值包络,或者对时间序列取幅度:

field_amplitude = sqrt(mean(Ey_record.^2, 3));

在观察屏位置,也就是距离缝屏几个波长的地方,沿x方向取这一行场强,就得到干涉条纹。如果你只想看相对强度分布,直接用场强平方就行。这里有个小细节:观察屏不要紧贴缝屏,否则近场倏逝波成分会混入结果;也不要太靠计算域边缘,否则PML的微小反射会污染条纹。一般来说,离缝屏5到10个波长最合适。

如果想把近场结果换算成远场角分布,可以对近场记录做空间傅里叶变换。空间频率k_x和角度θ之间满足k_x = k0 sinθ。Matlab里用fft函数就能实现,但要注意先对观察屏数据进行适当的窗函数处理,避免截断效应在角度谱上产生旁瓣。

3.4 报告撰写思路

这套源码附带的光学综合实验报告,写作框架其实很固定。我建议按下面这个顺序组织:

报告章节写什么注意事项
实验目的复现双缝干涉,学习PML与PMC边界条件不要只写“仿真双缝干涉”,要突出FDTD和边界条件
原理部分双缝干涉公式、FDTD迭代格式、PML/PMC作用公式要写清楚,但不需要推导太深
仿真模型参数表、几何示意图、边界设置参数表必须和源码一致,方便复现
结果与分析场图、条纹强度曲线、PML/PMC对比图和曲线要标坐标轴,分析要对应物理现象
结论总结仿真结果和边界条件作用避免泛泛而谈,要写“验证了”“得到了”

报告里最加分的是对比图:比如PML厚度8层和16层的结果对比,或者全模型和半模型PML+PMC的结果对比。把这两张图放进去,老师一眼就能看出你真的理解了边界条件的作用,而不是只会跑代码。

4. 实操中踩过的坑与排查思路

4.1 PML厚度不足导致的“伪条纹”

我第一次跑这套源码时,为了省内存把PML层数从10层降到了6层。结果出来的干涉条纹整体上是对的,但亮纹之间多了一层细密的周期波纹,像是“条纹上面叠了另一组条纹”。后来检查发现,就是PML太薄,波打到边界后反射回计算域,和透射波再次干涉形成了驻波。把PML加到12层,同时把电导率渐变阶数从2改成3,那层伪条纹立刻消失。

所以如果你发现亮度分布上出现均匀的高频波纹,第一个怀疑对象就是PML反射。判断方法很简单:把PML厚度增加到16层,或者把计算域扩大一倍,再看波纹是否变化。如果变了,基本可以确定是边界反射问题。

4.2 稳态建立时间不够

FDTD是迭代求解,源开始注入后,波前需要一段时间才能到达观察区域。如果时间步数太少,你看到的条纹其实只是波前刚经过观察屏时的“瞬态快照”,条纹间距可能对,但边缘会有明显的拖尾或不对称。我常用的判断标准是:在观察屏附近选一个固定点,记录该点场强随时间的变化,当曲线变成稳定的正弦包络时,才代表稳态建立完成。

为了保险起见,我通常把总时间步数设置成“光穿过整个计算域所需时间”的三到四倍。用前面的参数算,光从左侧边界到右侧PML大约要走48μm,需要160 fs左右,跑5000步、大约300 fs,已经足够稳。

4.3 对称边界选错导致结果整体偏移

PML+PMC的省内存方案很诱人,但对称边界不是随便设的。如果入射偏振或者结构对称模式不对,PMC会算出一个对称性错误的解。比如本应该用PEC的地方用了PMC,干涉条纹的强度和位置都会发生变化,甚至主极大变成次极大。排查办法很直接:先用全模型PML跑一遍,再把PMC半模型结果镜像对齐,和全模型逐点比较。如果两幅图重合,边界条件就是对的;如果不重合,就要检查源和结构的对称性。

这里多说一句:源码里针对TM偏振选用PMC是因为该偏振下对称面满足切向磁场为零。如果你换到TE偏振,情况就会反过来,可能需要用PEC。不要背着皮尺照抄,一定要理解边界条件的物理含义。

4.4 数值色散与分辨率不足

网格步长太粗会让电磁波的速度产生误差,表现为条纹位置偏移、窄缝传播角度不对。我试过用λ/10的网格跑同样模型,结果次级明纹位置差了接近5%,肉眼可见。把网格加密到λ/25后,误差就控制到可以忽略的程度。当然,加密网格会带来内存和时间成本。如果电脑跑不动,可以先粗网格调通流程,再加密网格做最终计算,这是比较省事的路径。

还有一个容易被忽略的点:金属屏厚度在二维网格里至少要有两三个网格来表示。如果屏只有一个网格厚,狭缝边缘会出现非常强的场增强,导致结果对参数特别敏感。把屏厚度设为100 nm,网格25 nm,正好四个网格,边缘效应相对稳定。

5. 这次项目调试的小体会

5.1 调试顺序比参数本身更重要

拿到源码后不要急着改缝宽、改波长,我建议先按默认参数跑一遍,确认得到正确的双缝干涉条纹。然后在保持光源和结构不变的情况下,分别做三组对照实验:PML厚度翻倍、去掉PMC改用全模型PML、把PMC替换成PEC。这三组结果能帮你在最短时间内建立起对边界条件的直观感受。之后再回头调整几何参数,你就会很清楚哪些现象是物理本身造成的,哪些是数值设置造成的。

很多时候参数调不出来,不是数值问题,而是模型和源没对。比如入射光不平整、金属屏建模有缝隙、监视器位置太近,这些都会让结果看起来“不对”。所以调试顺序应该是:先简单、后复杂,先验证、再优化。

5.2 这套源码还能怎么扩展

这套项目本身是二维单频仿真,但它的框架可以很容易往多个方向扩展。比如把连续正弦波改成高斯光束,可以研究聚焦后的干涉图样;把双缝屏改成光栅,能直接看各级衍射效率;把PML边界保留、对称边界改成周期性边界,就能往超表面方向走。最近很多人在讨论FDTD偏振转化效率的仿真,其实就是在这个框架里增加不同的偏振光源和各向异性材料模型。

如果你有时间,我建议你再做一个小实验:保持缝宽和屏厚度不变,只改变缝间距,观察条纹间距怎么变化。这个实验很简单,但做完之后你可以更深刻地理解双缝干涉公式里的d和条纹间隔的关系。源码里所有参数都在头部集中定义,改一个变量重新跑一遍就行,非常适合做参数扫描。

我就拿这套源码做过一次缝间距扫描,从2 μm扫到6 μm,得到的主极大角位移和理论值几乎重合。那一刻才真正觉得,FDTD不是黑箱,只要你把参数吃透,它就是一个可以反复实验的虚拟光学平台。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询