ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

光学衍射模拟:衍射积分与傅立叶变换方法对比及MATLAB实现

光学衍射模拟:衍射积分与傅立叶变换方法对比及MATLAB实现

简介:这份资源面向学习大学物理光学、需要动手验证衍射理论的学生与教师,提供一套用 MATLAB 编程模拟光学衍射的完整文档。内容围绕两条技术路线展开:一是衍射积分方法,通过计算接收屏上的光强分布,模拟单缝衍射、杨氏双缝干涉与黑白光栅衍射;二是傅立叶变换方法,借助屏函数功率谱模拟简单孔径、黑白光栅及正弦光栅的夫琅和费衍射,并附有可直接运行的示例代码与光强分布图。资源包共 1 个 doc 文档,约 247KB,以文字讲解配合程序清单的形式组织,便于对照理解公式与实现。目前已有 793 人学习。读者可从中获得从物理公式到 MATLAB 代码的完整映射,掌握用数值计算与图像显示复现衍射条纹的方法,并借助傅立叶变换思路拓展到圆孔、矩孔、三角孔等孔径的衍射模拟,适合作为课程实验的参考与自学材料。

1. 光学衍射模拟:为什么两套数学工具能画出同一张图

把一束激光打向单缝,屏幕上出现的不是一条亮线,而是一串明暗相间的条纹。这个现象在物理课上被反复演示,但真正让人困惑的地方在于:同一张衍射图样,既可以用「把缝拆成无数个点光源、逐个叠加复振幅」的衍射积分算出来,也可以直接对孔径函数做一次二维傅立叶变换得到。两条路径的数学起点完全不同,结果却严丝合缝地对上。这份 MATLAB 资源正是围绕这个「殊途同归」展开的:它用衍射积分模拟单缝、杨氏双缝和黑白光栅,又用傅立叶变换方法模拟圆孔、矩孔、三角孔、黑白光栅和正弦光栅的夫琅和费衍射。搞懂这两套方法为什么等价、各自在什么条件下成立,比单纯跑通一段代码有价值得多——因为前者是底层机制,后者只是调用习惯。

2. 衍射积分:把孔径拆成点光源再叠加

2.1 单缝为什么被离散成 np 个相干光源

衍射积分方法的核心思路非常朴素:孔径上每一点都可以看作一个次级子波源,接收屏上某点的复振幅,就是所有这些子波源传到该点后的相干叠加。资源里的单缝程序把缝宽a切成np=51个采样点,每个点对应一个子波源,然后对每个屏幕采样点累加所有子波的余弦和正弦分量:

lam=500e-9; a=1e-3; D=1; % 波长、缝宽、屏距 ym=3*lam*D/a; ny=51; % 屏幕范围取到第三级暗纹附近 ys=linspace(-ym,ym,ny); % 屏幕采样点 np=51; yp=linspace(0,a,np); % 缝内子波源采样点 for i=1:ny sinphi=ys(i)/D; % 小角近似下的衍射角正弦 alpha=2*pi*yp*sinphi/lam; % 每个子波源的相位 sumcos=sum(cos(alpha)); sumsin=sum(sin(alpha)); B(i,:)=(sumcos^2+sumsin^2)/np^2; % 归一化光强 end

这里有几个参数值得停下来看。ym=3*lam*D/a不是随手取的,它对应单缝衍射第一级暗纹位置lam*D/a的三倍,保证画出来的图能覆盖到第三级暗纹,条纹结构完整。np=51是离散化精度:子波源越多,累加结果越接近连续积分,但 51 个点对于单缝这种一维问题已经足够,因为被积函数是光滑的三角函数,采样密度远高于奈奎斯特要求。B(i,:)=(sumcos^2+sumsin^2)/np^2里的除以np^2是归一化,让最大光强落在 1 附近,方便后续映射到 0–255 的灰度。

提示:sinphi=ys(i)/D用了小角近似sinφ≈tanφ≈y/D。屏距D=1米、屏幕范围只有毫米级时这个近似误差可以忽略,但如果把D缩小到厘米级,就该老老实实用ys(i)/sqrt(ys(i)^2+D^2)。

2.2 杨氏双缝:相位差才是干涉的全部

双缝程序换了一个角度:不再离散缝内点,而是直接算两条缝到屏幕点的光程差,再用I=4I0cos²(Φ/2)得到光强。这个公式本身就是两束等幅相干光叠加的解析结果,代码只是把Φ=2π(r2-r1)/λ代进去:

a=2e-3; D=1; % 缝间距、屏距 ym=5*lam*D/a; n=101; ys=linspace(-ym,ym,n); for i=1:n r1=sqrt((ys(i)-a/2).^2+D^2); % 到上缝距离 r2=sqrt((ys(i)+a/2).^2+D^2); % 到下缝距离 phi=2*pi*(r2-r1)./lam; % 相位差 B(i,:)=sum(4*cos(phi/2).^2); % 双缝干涉光强 end

注意这里r1、r2用的是精确的欧氏距离,没有做小角近似,因为双缝的缝间距a=2e-3和屏距D=1之比虽然小,但干涉条纹对相位差极其敏感,近似带来的误差会直接体现在条纹位置上。ym=5*lam*D/a取到第五级条纹,n=101的采样密度保证每条条纹有足够多的点来描出余弦包络。这段代码里sum(4*cos(phi/2).^2)的sum其实作用在标量上,是原程序的一个冗余写法,不影响结果,但读的时候别被它误导成在做什么累加。

2.3 光栅衍射:两个因子的乘积从哪来

黑白光栅的公式I=I0(sinα/α)²(sin(Nβ)/sinβ)²是单缝衍射因子和多缝干涉因子的乘积。α=(πa/λ)sinφ里的a是单缝缝宽,负责调制包络;β=(πd/λ)sinφ里的d是光栅常数,负责产生尖锐的主极大。资源里取N=2、a=2e-4、d=5*a,也就是缝宽是光栅常数的五分之一,这个比例直接决定了缺级出现在第几级——第 5、10、15 级主极大正好落在单缝衍射的暗纹上,被调制掉。

N=2; a=2e-4; D=5; d=5*a; ym=2*lam*D/a; n=1001; ys=linspace(-ym,ym,n); for i=1:n sinphi=ys(i)/D; alpha=pi*a*sinphi/lam; beta=pi*d*sinphi/lam; B(i,:)=(sin(alpha)./alpha).^2.*(sin(N*beta)./sin(beta)).^2; B1=B/max(B); end

n=1001比前两个程序密得多,因为光栅主极大非常窄,采样点少了会直接漏掉峰值,画出来的条纹忽宽忽窄,这是数值模拟里典型的欠采样翻车现场。sin(beta)在beta接近整数倍 π 时分母趋零,但分子sin(N*beta)同时趋零,极限是N,MATLAB 的浮点运算在这个邻域内通常能给出接近正确的结果,但如果n取得太粗、采样点正好落在奇点上,会出现NaN或异常尖峰,这是后面避坑章节要展开的一个点。

3. 傅立叶变换方法:夫琅和费衍射就是孔径的功率谱

3.1 为什么 fft2 之后还要 fftshift

傅立叶光学里有一个结论:夫琅和费衍射的复振幅分布正比于孔径函数的傅立叶变换,光强就是它的模平方。资源里的做法是读入一张孔径图像,做二维离散傅立叶变换,取模,再移位显示:

a=imread('aperture.bmp'); % 孔径图像,二维矩阵 afft=fft2(a); % 二维离散傅立叶变换 aabs=abs(afft); % 取模得到振幅谱 aabss=fftshift(aabs); % 直流分量移到中心 imshow(aabss,[]); % 显示频谱 colormap(gray); colorbar

fft2输出的矩阵,零频分量在四个角上,这是因为离散傅立叶变换的求和从索引 1 开始,正负频率分别排在矩阵两端。fftshift交换第一、三象限和第二、四象限,把零频挪到中心,视觉上才和实际衍射图样一致——人眼习惯中心最亮、向外衰减的分布。这一步不是数学上必需的,纯粹是为了可视化对齐直觉,但不做这一步,初学者很容易把角上的亮点误认为某种异常。

3.2 孔径形状如何决定衍射图样

资源里用同一套流程跑了圆孔、矩孔、三角孔、单缝、黑白光栅和正弦光栅。圆孔的频谱是艾里斑,中心亮斑加一圈圈暗环;矩孔的频谱是两个 sinc 函数的乘积,呈现十字形亮纹;三角孔则出现三重对称的星状结构。这些差异全部来自孔径矩阵本身的形状,fft2只是忠实地把空间域的边界条件翻译成频率域的分布。换句话说,你不需要为每种孔径推导新的衍射公式,只要把孔径画成黑白图像,傅立叶变换就自动给出对应的夫琅和费衍射图样。这正是傅立叶方法相对于衍射积分的最大优势:孔径任意复杂,流程不变。

3.3 正弦光栅只有三个斑说明了什么

资源里先用余弦函数生成一张正弦光栅图像,再做傅立叶变换,结果只有三个衍射斑。这个结果不是巧合:正弦光栅的透过率函数只含一个空间频率分量,它的频谱自然只有零频和正负一级三个峰。对比黑白光栅——方波透过率包含无穷多奇次谐波,频谱上就是一系列等间距的主极大。这个对比把「傅立叶变换把空间周期性翻译成频率离散峰」这件事变得非常直观,也是理解光栅衍射缺级、谐波结构的入口。

4. 避坑与排查:数值模拟里那些不像 bug 的 bug

4.1 条纹忽宽忽窄、峰值对不上

现象:光栅衍射程序跑出来,主极大位置和理论值差了一截,或者条纹宽度不均匀。原因通常是屏幕采样点数n不够,窄主极大被欠采样,峰值落在两个采样点之间被削平。解决:把n从 1001 继续加大,或者先用解析公式算出主极大位置,再在附近局部加密采样,确认峰值位置收敛。

4.2 出现 NaN 或异常尖峰

现象:光栅公式里sin(N*beta)./sin(beta)在某些点算出NaN或极大值。原因是beta恰好等于整数倍 π 时分子分母同时为零,浮点运算在奇点邻域内不稳定。解决:在循环里判断abs(sin(beta))是否小于阈值,小于时用极限值N替代,或者直接对beta加一个极小偏移避开精确奇点。

4.3 频谱图四个角亮、中心暗

现象:做完fft2直接imshow,发现亮点在四个角。原因是没有做fftshift,零频分量还在矩阵角落。解决:显示前加一步fftshift,或者接受这个布局但心里清楚角上才是低频。这个坑几乎每个第一次用fft2做光学模拟的人都踩过。

4.4 衍射图样和理论对不上、整体偏移

现象:圆孔衍射的艾里斑不在画面中心。原因可能是读入的孔径图像本身不在矩阵中心,或者图像有非零背景(比如灰度不是纯黑白),引入了额外的低频分量。解决:确认孔径矩阵的中心对称性,必要时用padarray把孔径补零到更大矩阵的中心,背景统一归一化到 0 和 1。

4.5 小角近似在近距离下失效

现象:把屏距D改小之后,衍射积分算出的条纹位置和实验对不上。原因是sinφ≈y/D的近似在y与D可比时误差显著。解决:改用精确的sinφ=y/sqrt(y^2+D^2),或者干脆把屏距保持在远场条件D>>a^2/λ之下,让夫琅和费近似本身成立。

5. 两种方法的取舍:什么时候该用积分,什么时候该用 FFT

衍射积分和傅立叶变换方法并不是互相替代的关系,它们各自对应不同的物理条件和计算代价。衍射积分从子波叠加出发,物理图像清晰,适合菲涅耳区——也就是屏距不够远、夫琅和费近似不成立的情形,因为你可以把传播因子完整地写进每个子波的相位里,不需要假设远场。代价是计算量随孔径采样点和屏幕采样点的乘积增长,二维问题很容易爆内存。傅立叶变换方法则天然对应夫琅和费远场,一次fft2就把整个衍射场算完,复杂度是O(N²logN),孔径多复杂都不增加流程步骤,但它要求远场条件,近场用它会得到错误的图样。

维度衍射积分傅立叶变换
适用区域菲涅耳区、近场夫琅和费区、远场
孔径灵活性需逐点建模任意图像直接输入
计算代价采样点乘积FFT 复杂度
物理直觉子波叠加,直观频谱映射,抽象

我一般会这么理解:衍射积分是「从物理过程出发」,傅立叶变换是「从数学结构出发」。前者帮你建立对相位、光程差、干涉的肌肉记忆,后者帮你快速探索各种孔径的衍射花样。资源里两种方法都给了完整代码,价值不在于哪段代码更短,而在于你可以拿同一个孔径分别跑两条路径,在远场条件下对比结果是否一致——这个交叉验证本身就是最好的理解检验。从那以后我每次做数值模拟,都会先用解析解或另一种方法对一遍结果,确认不是采样或近似在骗我。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进