利用 FFT 模拟菲涅尔衍射积分
一束光线穿过一个孔径为 S ′ S' S′ 的平面,在距离平面为 L L L 的时候,其波函数可以由菲涅尔积分定义:
Ψ ( r , t ) = C ∫ S ′ e i k ∣ r − r ′ ∣ ∣ r − r ′ ∣ cos ( θ ) d 2 r ′ , w i t h C = k Ψ 0 e − i t w 2 π i \Psi(\mathbf{r}, t) = C \int_{S'} \frac{e^{ik|r-r'|}}{|r-r'|} \cos(\theta)d^2r', \quad with \quad C = \frac{k \Psi_{0} e^{-itw}}{2 \pi i} Ψ(r,t)=C∫S′∣r−r′∣eik∣r−r′∣cos(θ)d2r′,withC=2πikΨ0e−itw
基于菲涅尔近似,在角度接近 0 度的时候,上式可以简化为:
∣ r − r ′ ∣ ≈ z + ( x − x ′ ) 2 + ( y − y ′ ) 2 2 z |r - r'| \approx z + \frac{(x - x')^2 + (y - y')^2}{2z} ∣r−r′∣≈z+2z(x−x′)2+(y−y′)2
并且可以假设:
∣ r − r ′ ∣ ≈ L |r - r'| \approx L ∣r−r′∣≈L
菲涅尔积分可以变成:
Ψ ( r , t ) = R ∫ − ∞ ∞ ∫ − ∞ ∞ f ( x ′ , y ′ ) e i k 2 z ( x ′ 2 + y ′ 2 ) e − i k x z x ′ − i k y z y ′ d x ′ d y ′ \Psi(\mathbf{r}, t) = R \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x', y') e^{\frac{ik}{2z}(x'^2 + y'^2)} e^{-\frac{ikx}{z}x'-\frac{iky}{z}y'} dx'dy' Ψ(r,t)=R∫−∞∞∫−∞∞f(x′,y′)e2zik(x′2+y′2)e−zikxx′−zikyy′dx′dy′
w i t h R = k Ψ 0 e i ( k z − t w ) 2 π i z e i k x 2 + y 2 2 z with \quad R = \frac{k \Psi_{0} e^{i(kz - tw)}}{2 \pi i z} e^{ik \frac{x^2 + y^2}{2z}} withR=2πizkΨ0ei(kz−tw)eik2zx2+y2
f ( x ′ , y ′ ) = { 1 if ( x ′ , y ′ ) ∈ S ′ 0 if ( x ′ , y ′ ) ∉ S ′ f(x', y') = \begin{cases} 1 & \text{ if } (x', y')\in S' \\ 0 & \text{ if } (x', y')\notin S' \end{cases} f(x′,y′)={10 if (x′,y′)∈S′ if (x′,y′)∈/S′
上式可以转换成傅里叶变换的形式:
Ψ ( r , t ) = R ⋅ F [ f ( x ′ , y ′ ) e i k 2 z ( x ′ 2 + y ′ 2 ) ] \Psi(\mathbf{r}, t) = R \cdot \mathcal{F}[f(x', y') e^{\frac{ik}{2z}(x'^2 + y'^2)}] Ψ(r,t)=R⋅F[f(x′,y′)e2zik(x′2+y′2)]
F [ f ( x ′ , y ′ ) e i k 2 z ( x ′ 2 + y ′ 2 ) ] = ∫ − ∞ ∞ ∫ − ∞ ∞ f ( x ′ , y ′ ) e i k 2 z ( x ′ 2 + y ′ 2 ) e − i k x z x ′ − i k y z y ′ d x ′ d y ′ \mathcal{F}[f(x', y') e^{\frac{ik}{2z}(x'^2 + y'^2)}] = \int_{-\infty}^{\infty} \int_{-\infty}^{\infty} f(x', y') e^{\frac{ik}{2z}(x'^2 + y'^2)} e^{-\frac{ikx}{z}x'-\frac{iky}{z}y'} dx'dy' F[f(x′,y′)e2zik(x′2+y′2)]=∫−∞∞∫−∞∞f(x′,y′)e2zik(x′2+y′2)e−zikxx′−zikyy′dx′dy′
为了便于计算,我们可以将连续域内的 ( x ′ , y ′ ) (x', y') (x′,y′) 进行离散化,比如,可以将 ( x ′ , y ′ ) ∈ [ − L x , L x ] × [ − L y , L y ] (x', y') \in [-L_x, L_x] \times [-L_y, L_y] (x′,y′)∈[−Lx,Lx]×[−Ly,Ly] 划分成等间距的 N x , N y N_x, N_y Nx,Ny 份:
x n x ′ = { − L x + n x 2 L x N x , 0 ≤ n x ≤ N x − 1 } x'_{n_x} = \left \{ -L_x + n_x \frac{2L_x}{N_x}, \quad 0 \leq n_x \leq N_x -1 \right \} xnx′={−Lx+nxNx2Lx,0≤nx≤Nx−1}
y n y ′ = { − L y + n y 2 L y N y , 0 ≤ n y ≤ N y − 1 } y'_{n_y} = \left \{ -L_y + n_y \frac{2L_y}{N_y}, \quad 0 \leq n_y \leq N_y -1 \right \} yny′={−Ly+nyNy2Ly,0≤ny≤Ny−1}
接下来,就可以定义离散傅里叶变换:
G ( u x , u y ) = ∑ n x = 0 N x − 1 ∑ n y = 0 N y − 1 g ( x n x ′ , y n y ′ ) e − i 2 π u x n x N x − i 2 π u y n y N y G(u_x, u_y) = \sum_{n_x = 0}^{N_x -1} \sum_{n_y =0}^{N_y -1} g(x'_{n_x}, y'_{n_y})e^{-i2\pi u_x \frac{n_x}{N_x} - i 2 \pi u_y \frac{n_y}{N_y} } G(ux,uy)=nx=0∑Nx−1ny=0∑Ny−1g(xnx′,yny′)e−i2πuxNxnx−i2πuyNyny
在距离为 L 的平面上,
x u x = ( u x − N x / 2 ) L λ 2 L x x_{u_x} = \frac{(u_x - N_x / 2)L \lambda}{2 L_x} xux=2Lx(ux−Nx/2)Lλ
y u x = ( u y − N y / 2 ) L λ 2 L y y_{u_x} = \frac{ (u_y - N_y / 2)L \lambda}{ 2 L_y} yux=2Ly(uy−Ny/2)Lλ
### 代码转载自:
## https://rafael-fuente.github.io/solving-the-diffraction-integral-with-the-fast-fourier-transform-fft-and-python.html
import numpy as np
import matplotlib.pyplot as plt
class Sheet():
def __init__(self,extentX, extentY, Nx, Ny):
self.x = np.linspace(extentX[0],extentX[1],Nx)
self.y = np.linspace(extentY[0],extentY[1],Ny)
self.xx,self.yy = np.meshgrid(self.x, self.y)
self.Nx = int(Nx)
self.Ny = int(Ny)
self.f = np.zeros((int(self.Ny), int(self.Nx)))
def rectangular_slit(self,x0, y0, lx, ly):
"""
Creates a slit centered at the point (x0, y0) with width lx and height ly
"""
self.f += np.select( [((self.xx > (x0 - lx/2) ) & (self.xx < (x0 + lx/2) )) & ((self.yy > (y0 - ly/2) ) & (self.yy < (y0 + ly/2) )), True], [1, 0])
Lx = 1.4
Ly = 0.4
Nx= 2500
Ny= 1500
sheet = Sheet(extentX = [-Lx, Lx] , extentY = [-Ly, Ly], Nx= Nx, Ny= Ny)
#slit separation
mm = 1e-3
D = 500 * mm
sheet.rectangular_slit(x0 = -D/2, y0 = 0, lx = 22 * mm , ly = 88 * mm)
sheet.rectangular_slit(x0 = +D/2, y0 = 0, lx = 22 * mm , ly = 88 * mm)
# distance from slit to the screen (mm)
z = 5000
# wavelength (mm)
λ = 18.5*1e-7
k = 2*np.pi/λ
fft_c = np.fft.fft2(sheet.f * np.exp(1j * k/(2*z) *(sheet.xx**2 + sheet.yy**2)))
c = np.fft.fftshift(fft_c)
fig = plt.figure(figsize=(6, 6))
ax1 = fig.add_subplot(2,1,1)
ax2 = fig.add_subplot(2,1,2,sharex=ax1, yticklabels=[])
abs_c = np.absolute(c)
#screen size mm
Lx_screen = Nx*z*λ/(4*Lx)
Ly_screen = Ny*z*λ/(4*Ly)
x_max = (np.pi/Lx * (Nx//2 - 1))*z*λ/(2*np.pi)
y_max = (np.pi/Ly * (Ny//2 - 1))*z*λ/(2*np.pi)
ax1.imshow(abs_c, extent = [-Lx_screen, Lx_screen, -Ly_screen,Ly_screen], cmap ='gray', interpolation = "bilinear", aspect = 'auto')
ax2.plot(np.linspace(-Lx_screen,Lx_screen, len(abs_c[0])), abs_c[len(abs_c)//2]**2)
ax1.set_ylabel("y (mm)")
ax2.set_xlabel("x (mm)")
ax2.set_ylabel("Probability Density $|\psi|^{2}$")
ax1.set_xlim([-2,2])
ax2.set_xlim([-2,2])
ax1.set_ylim([-1,1])
plt.setp(ax1.get_xticklabels(), visible=False)
plt.show()
参考文献:
https://rafael-fuente.github.io/solving-the-diffraction-integral-with-the-fast-fourier-transform-fft-and-python.html