手把手用Python模拟单缝衍射:从公式到可视化光强分布图
用Python模拟单缝衍射:从公式到可视化光强分布图
当一束光穿过比波长略宽的狭缝时,会在屏幕上形成明暗相间的条纹——这就是著名的单缝衍射现象。作为波动光学的基础实验之一,单缝衍射不仅揭示了光的波动本质,其数学描述和模拟实现更是理解现代光学系统的关键。本文将带你用Python从零构建单缝衍射模型,通过代码实现理论公式的可视化,直观展示缝宽、波长等参数如何影响衍射图样。
1. 理论基础与模型搭建
单缝夫琅禾费衍射的光强分布由经典公式决定:
$$ I = I_0 \left( \frac{\sin u}{u} \right)^2 $$
其中 $u = \frac{\pi a \sin \theta}{\lambda}$,$a$为缝宽,$\lambda$为波长,$\theta$为衍射角。中央明纹强度$I_0$与入射光强成正比。
关键参数关系表:
| 参数 | 物理意义 | 典型值范围 | 影响规律 |
|---|---|---|---|
| a | 单缝宽度 | 0.01-1mm | 与条纹宽度成反比 |
| λ | 光波长 | 400-700nm | 波长越长衍射越明显 |
| f | 透镜焦距 | 0.5-2m | 决定屏幕上的实际尺度 |
建立计算模型需要三个核心步骤:
- 定义参数空间:设置合理的物理参数和计算范围
- 离散化处理:将连续角度θ转换为数值计算可处理的离散点
- 归一化处理:将光强统一缩放到[0,1]区间便于可视化
import numpy as np import matplotlib.pyplot as plt # 基础参数设置 wavelength = 632.8e-9 # 氦氖激光波长(单位:m) a = 0.1e-3 # 单缝宽度(单位:m) f = 1.0 # 透镜焦距(单位:m)2. 光强分布计算实现
采用NumPy进行向量化计算可显著提升效率。衍射角的处理需要注意:
- 实际实验中θ通常很小(<5°),故采用小角度近似$\sinθ ≈ \tanθ = x/f$
- 计算范围应覆盖多个明暗条纹周期
def calculate_intensity(a, wavelength, f, screen_width=0.02): """计算单缝衍射光强分布""" x = np.linspace(-screen_width/2, screen_width/2, 2000) # 屏幕坐标 theta = np.arctan(x/f) # 衍射角计算 u = np.pi * a * np.sin(theta) / wavelength intensity = (np.sin(u)/u)**2 # 光强公式 intensity[np.isnan(intensity)] = 1 # 处理u=0处的奇异点 return x, intensity常见问题处理技巧:
- 当u接近0时会出现0/0不定式,需特殊处理
- 使用
np.sinc函数可能产生精度问题,建议显式计算 - 屏幕采样点数需足够多(建议>1000)以避免aliasing效应
3. 结果可视化与参数分析
Matplotlib提供了灵活的绘图工具,我们可以创建专业级可视化:
def plot_diffraction(x, intensity, params): """绘制衍射光强分布图""" plt.figure(figsize=(12, 6)) # 光强曲线绘制 plt.subplot(1, 2, 1) plt.plot(x*1000, intensity, 'b-', linewidth=1.5) plt.xlabel('屏幕位置 (mm)') plt.ylabel('相对光强') plt.title('单缝衍射光强分布曲线') # 二维灰度图模拟 plt.subplot(1, 2, 2) pattern = np.outer(intensity, np.ones(100)) # 扩展为二维 plt.imshow(pattern.T, cmap='gray', extent=[x[0]*1000, x[-1]*1000, 0, 1], aspect='auto') plt.xlabel('屏幕位置 (mm)') plt.title('衍射条纹灰度模拟') plt.tight_layout() plt.show()执行计算与绘图:
x, intensity = calculate_intensity(a, wavelength, f) plot_diffraction(x, intensity, {'a': a, 'λ': wavelength})4. 参数影响与交互探索
通过改变关键参数观察衍射图样变化,可以验证光学原理:
缝宽a的影响:
widths = [0.05e-3, 0.1e-3, 0.2e-3] # 不同缝宽 plt.figure(figsize=(10, 6)) for a in widths: x, intensity = calculate_intensity(a, wavelength, f) plt.plot(x*1000, intensity, label=f'a={a*1e3:.2f}mm') plt.legend() plt.title('不同缝宽下的衍射图样对比')波长λ的影响:
wavelengths = [400e-9, 550e-9, 700e-9] # 可见光范围 plt.figure(figsize=(10, 6)) for λ in wavelengths: x, intensity = calculate_intensity(a, λ, f) plt.plot(x*1000, intensity, label=f'λ={λ*1e9:.0f}nm') plt.legend() plt.title('不同波长下的衍射图样对比')衍射反比律验证: 中央明纹宽度$\Delta x = 2fλ/a$,可通过测量不同参数组合下的实际条纹宽度验证这一基本规律。
5. 高级扩展与实验对比
将理论模拟与实际实验数据对比是验证模型准确性的好方法。我们可以:
- 添加噪声模拟:
noisy_intensity = intensity + 0.02*np.random.randn(len(intensity)) noisy_intensity = np.clip(noisy_intensity, 0, 1) # 保持物理合理性- 考虑非理想因素:
- 光源尺寸效应
- 透镜像差影响
- 缝边缘衍射效应
- 创建交互工具: 使用IPython widgets构建参数调节界面:
from ipywidgets import interact @interact(a=(0.01, 0.5, 0.01), λ=(400, 700, 10)) def interactive_diffraction(a=0.1, λ=632.8): a *= 1e-3 # 转换为米 λ *= 1e-9 x, intensity = calculate_intensity(a, λ, f) plot_diffraction(x, intensity, {'a': a, 'λ': λ})在实际教学中,这种可视化模拟可以帮助学生直观理解:
- 为什么几何光学在a>>λ时成立
- 如何通过衍射图样反推缝宽
- 光学仪器分辨率限制的来源
