標籤:

第5節.均勻各向同性介質中單色標量光場的傳播

這節課,我們來看看怎麼模擬光在均勻各向同性介質中的傳播過程。會了這節課,你就可以模擬一些特殊光束的傳播特性,例如:艾里光,徑向艾里光,渦旋光等。這節的光就是跟題目說的一樣:單色標量光場。

1.傅里葉變換正基

我這裡定義的

正頻率時域諧波對應的時域表示 => exp(iomega t)

正頻率空域諧波對應的時域表示 => exp(-i(k_xx+k_yy+k_zz))

正頻率時空域諧波對應的時域表示 => exp(i(omega t-k_xx-k_yy-k_zz))

2.單色標量光場的表示

標量:不考慮偏振態,假設各處偏振都是一樣的。

單色:光學頻率為單一值。

標量光場可以用 E(t,x,y,z) 表示,如果是一個處處都是時域單色諧波,那麼我們對時域做傅里葉變換,就可以得到頻率域的兩個尖峰非零值。我們取正頻率處的非零值 E_omega(x,y,z) 來描述該處的光場。也就是說,我們光場做了個時域傅里葉變換,然後那個超級窄帶濾波器濾了出來。

而我們要求解的問題就是,已知 E_omega(x,y,0) ,求 E_omega(x,y,z)

3. 光的傳播

均勻線性介質中有 E_omega(k_x,k_y,z)=E_omega(k_x,k_y,0)exp(-ik_z(k_x,k_y,omega)z)

在各項同性介質中有 k_z(k_x,k_y,omega) = left{ (frac{n(omega)omega}{c})^{2}-k_x^{2}-k_y^{2} 
ight}^{1/2}

基本的原理弄完了,下面開始寫代碼。

function var = space(varargin)
% 創建變數空間
% para = space(dimension1,window1,sample1,dimension2,window2,sample2,...)
% 輸入
% dimension - 維度 (字元串),可取x 、 y、t
% window - 範圍
% sample - 採樣個數
%
% 輸出
% var - 變數空間
% 如果不定義某維度,則定義該維度window = 0,sample =1

[var.x_,var.fx_]=domain(0,0);
[var.y_,var.fy_]=domain(0,0);
[var.t_,var.ft_]=domain(0,0);

for index_var =1:3:length(varargin)
key = varargin{index_var};
try
window = varargin{index_var+1};
sample = varargin{index_var+2};
catch
error([unenougth parm for: ,key])
end

switch key
case x
[var.x_,var.fx_]=domain(window,sample);
case y
[var.y_,var.fy_]=domain(window,sample);
case t
[var.t_,var.ft_]=domain(window,sample);
otherwise
error([undefine key : ,key])
end
end
[var.x,var.y,var.t] = meshgrid(var.x_,var.y_,var.t_);
[var.fx,var.fy,var.ft] = meshgrid(var.fx_,var.fy_,var.ft_);

第一個代碼是用來創建變數空間,就是利用第1節.Matlab中的fft的函數重建多維空間,這個最多創建三維空間xyt, 但是這節只需要使用xy.

下面代碼是模擬高斯光束經過透鏡的聚焦過程。

clc
clear
units
%%
lambda = 1560*nm;
var = space(x,10*mm,256,y,10*mm,256);
var.ft = var.ft+c./lambda;

%%

kz = 2*pi*sqrt((var.ft/c).^2-(var.fx).^2-(var.fy).^2);
w0 = 1.5*mm;
E = exp(-(var.x/w0).^2).*exp(-(var.y/w0).^2);
subplot(1,3,1)
imagesc(fftshift(var.x_)/mm,fftshift(var.y_)/mm,fftshift(abs(E).^2));
colormap gray
axis xy
title(輸入)

Focus_length = 25*cm;
Fai_len = 2*pi*var.ft./c.*(var.x.^2+var.y.^2)/2/(Focus_length);

STEP = 1:500;
dz = 2*Focus_length./length(STEP);

GPU_ON = 1;
%% 初始化光場
if(GPU_ON)
Ez = gpuArray(E.*exp(i*Fai_len));
P = gpuArray( exp(-i*kz.*dz));
section = gpuArray(zeros(length(var.y_),length(STEP)));
else
Ez = (E.*exp(i*Fai_len));
P = ( exp(-i*kz.*dz));
section = (zeros(length(var.y_),length(STEP)));
end
%% 模擬主程序
tic
for index = STEP
Ez = fft2(P.*ifft2(Ez));
section(:,index) = Ez(:,1);
end
toc
%%
subplot(1,3,2)
imagesc(fftshift(var.x_)/mm,fftshift(var.y_)/mm,fftshift(abs(Ez).^2));
colormap gray
axis xy
title(輸出)
subplot(1,3,3)
imagesc(STEP*dz/mm,fftshift(var.y_)/mm,(abs(fftshift(section,1))));
colormap gray
axis xy
title(截面)

然後我們把透鏡相位去掉,然後把入射光束的寬度調小一點。可以看到衍射。

你們可以初始化出不同的初始光場,例如經過兩個狹縫。

最後,如果有大神看到這篇文章,我有個問題想請教一下:

在我的電腦上,如果使用gpuArray來做迭代,在STEP比較小的是可以加速的。但是隨著迭代次數的提高,似乎耗時越來越長。我不太能理解。有沒有大神能解答一下!使用的顯卡是Quadro K600。下圖是把每次迭代的時間記錄下來的圖。可以看到118次處,使用gpuArray的曲線有個拐點。

我想問~這個是什麼原因導致的,有辦法避免嗎?

下面代碼為測試代碼(因為前面的代碼需要額外的外部m文件,把步驟實現了),複製到matlab中應該可以直接運行。

clc
clear
%%
matrix_size = 256;

Fai_len = rand(matrix_size);
E = rand(matrix_size);
kz = rand(matrix_size);

dz = 1;
STEP = 1:500;
TOC1 = zeros(size(STEP));
TOC2 = zeros(size(STEP));
%% 沒有GPU加速

Ez = E.*exp(i*Fai_len);
P = exp(-i*kz.*dz);
section = zeros(matrix_size,length(STEP));

tic
for index = STEP
Ez = fft2(P.*ifft2(Ez));
section(:,index) = Ez(:,1);
TOC1(index) = toc;
end

%% 有GPU加速

Ez = gpuArray(E.*exp(i*Fai_len));
P = gpuArray(P);
section = gpuArray(section);

tic
for index = STEP
Ez = fft2(P.*ifft2(Ez));
section(:,index) = Ez(:,1);
TOC2(index) = toc;
end

%%

plot(TOC1);
hold on
plot(TOC2);
hold off

matrix_size =256; Quadro K600

matrix_size = 512; 電腦940MX


推薦閱讀:

TAG:MATLAB |