注意这个代码不是我自己写的,是取自《Electromagnetic and Photonic Simulation for the Beginner Finite-Difference Frequency-Domain in MATLAB》这书的第七章,这本书的PDF在谷歌上很容易下载,并且作者在书中贴出了全书的代码链接。(ps:作者 Raymond C. Rumpf真的太无私了 很了不起的分享精神)
但是这个代码我自己改了一下可以适用于对角各向异性,也就是相对介电常数和相对磁导率可以是对角矩阵,且对角元可以都不等;同时我和comsol计算结果对比了一下,无论是TE还是TM模式的实、虚部都和仿真软件符合得非常好。
仿真对比的comsol文件和.dat数据已上传在蓝奏云,读者可根据合理要求从我这里获得。
close all;
clc;
clear all; CRe= dlmread ( 'ComsolRe.dat' ) ;
CIm= dlmread ( 'ComsolIm.dat' ) ;
a = 1 ;
erhole = diag ( [ 3 - 15 * 1j , 5 + 1j , 9 + 8 * 1j ] ) ;
urhole = diag ( [ 1 - 1j , 4 + 5 * 1j , 7 - 5 * 1j ] ) ; erfill = diag ( [ 2 - 1j , 3 - 1j , 4 - 1j ] ) ;
urfill = diag ( [ 11 - 2 * 1j , 10 - 2 * 1j , 9 - 2 * 1j ] ) ; len= 3 * a/ 5 ;
xp= [ len/ 2 ; len/ 2 ; - len/ 2 ; - len/ 2 ] ;
yp= [ len/ 2 ; - len/ 2 ; - len/ 2 ; len/ 2 ] ;
Nx = 100 ;
Ny = 100 ;
NBANDS = 12 ;
num_point= 10 ; kxky0= kxky ( num_point, a) ;
NBETA= length ( kxky0) ;
BZpar= 0 : 1 / num_point: 3 ;
dx = a/ Nx;
dy = a/ Ny;
Nx2 = 2 * Nx; dx2 = dx/ 2 ;
Ny2 = 2 * Ny; dy2 = dy/ 2 ;
xa2 = [ 1 - 0.5 : Nx2- 0.5 ] * dx2; xa2 = xa2 - mean ( xa2) ;
ya2 = [ 1 - 0.5 : Ny2- 0.5 ] * dy2; ya2 = ya2 - mean ( ya2) ;
[ Y2, X2] = meshgrid ( ya2, xa2) ;
sf= @ ( xx, yy) shape_f ( xx, yy, xp, yp) ;
[ uu, vv] = size ( X2) ;
ER2= zeros ( uu, vv) ;
for aa= 1 : uufor bb= 1 : vvER2 ( aa, bb) = sf ( X2 ( aa, bb) , Y2 ( aa, bb) ) ; end
end
ER2xx = erfill ( 1 , 1 ) * ( 1 - ER2) + erhole ( 1 , 1 ) * ER2;
ER2yy = erfill ( 2 , 2 ) * ( 1 - ER2) + erhole ( 2 , 2 ) * ER2;
ER2zz = erfill ( 3 , 3 ) * ( 1 - ER2) + erhole ( 3 , 3 ) * ER2; UR2xx = urfill ( 1 , 1 ) * ( 1 - ER2) + urhole ( 1 , 1 ) * ER2;
UR2yy = urfill ( 2 , 2 ) * ( 1 - ER2) + urhole ( 2 , 2 ) * ER2;
UR2zz = urfill ( 3 , 3 ) * ( 1 - ER2) + urhole ( 3 , 3 ) * ER2;
ERxx = ER2xx ( 2 : 2 : Nx2, 1 : 2 : Ny2) ;
ERyy = ER2yy ( 1 : 2 : Nx2, 2 : 2 : Ny2) ;
ERzz = ER2zz ( 1 : 2 : Nx2, 1 : 2 : Ny2) ;
URxx = UR2xx ( 1 : 2 : Nx2, 2 : 2 : Ny2) ;
URyy = UR2yy ( 2 : 2 : Nx2, 1 : 2 : Ny2) ;
URzz = UR2zz ( 2 : 2 : Nx2, 2 : 2 : Ny2) ;
figure
title ( 'Unit Cell' )
subplot ( 2 , 3 , 1 )
imagesc ( xa2, ya2, imag ( ER2xx.' ) ) ;
axis equal tight;
colorbar;
title ( 'er_{xx}' ) ; subplot ( 2 , 3 , 2 )
imagesc ( xa2, ya2, imag ( ER2yy.' ) ) ;
axis equal tight;
colorbar;
title ( 'er_{yy}' ) ; subplot ( 2 , 3 , 3 )
imagesc ( xa2, ya2, imag ( ER2zz.' ) ) ;
axis equal tight;
colorbar;
title ( 'er_{zz}' ) ; subplot ( 2 , 3 , 4 )
imagesc ( xa2, ya2, imag ( UR2xx.' ) ) ;
axis equal tight;
colorbar;
title ( 'ur_{xx}' ) ; subplot ( 2 , 3 , 5 )
imagesc ( xa2, ya2, imag ( UR2yy.' ) ) ;
axis equal tight;
colorbar;
title ( 'ur_{yy}' ) ; subplot ( 2 , 3 , 6 )
imagesc ( xa2, ya2, imag ( UR2zz.' ) ) ;
axis equal tight;
colorbar;
title ( 'ur_{zz}' ) ;
KL = { 'M' 'X' '\Gamma' 'M' } ;
ERxx = diag ( sparse ( ERxx ( : ) ) ) ;
ERyy = diag ( sparse ( ERyy ( : ) ) ) ;
ERzz = diag ( sparse ( ERzz ( : ) ) ) ;
URxx = diag ( sparse ( URxx ( : ) ) ) ;
URyy = diag ( sparse ( URyy ( : ) ) ) ;
URzz = diag ( sparse ( URzz ( : ) ) ) ;
WNTE = zeros ( NBANDS, NBETA) ;
WNTM = zeros ( NBANDS, NBETA) ;
HermiTE= zeros ( 1 , NBETA) ;
HermiTM= zeros ( 1 , NBETA) ; %
%
for nbeta = 1 : length ( kxky0) Mark= nbeta/ NBETAbeta = kxky0 ( : , nbeta) ; NS = [ Nx Ny] ; RES = [ dx dy] ; BC = [ 1 1 ] ; [ DEX, DEY, DHX, DHY] = yeeder2d ( NS, RES, BC, beta) ; A = - DHX/ URyy* DEX - DHY/ URxx* DEY; B = ERzz; HermiTM ( 1 , nbeta) = ishermitian ( inv ( B) * A) ; D = eigs ( A, B, NBANDS, 0 ) ; D = sort ( D) ; WNTM ( : , nbeta) = D ( 1 : NBANDS) ; A = - DEX/ ERyy* DHX - DEY/ ERxx* DHY; B = URzz; HermiTE ( 1 , nbeta) = ishermitian ( inv ( B) * A) ; D = eigs ( A, B, NBANDS, 0 ) ; D = sort ( D) ; WNTE ( : , nbeta) = D ( 1 : NBANDS) ; end
ReWNTE = a/ ( 2 * pi ) * real ( sqrt ( WNTE) ) ;
ReWNTM = a/ ( 2 * pi ) * real ( sqrt ( WNTM) ) ;
ImWNTE = a/ ( 2 * pi ) * imag ( sqrt ( WNTE) ) ;
ImWNTM = a/ ( 2 * pi ) * imag ( sqrt ( WNTM) ) ;
figure
hold on
plot ( HermiTE, 'b.' )
plot ( HermiTM, 'ro' )
hold off
legend ( 'TE' , 'TM' )
title ( 'ishermitian' )
figure
subplot ( 1 , 2 , 1 )
hold on
plot ( BZpar, ReWNTM, '.g' ) ;
scatter ( CRe ( : , 1 ) , CRe ( : , 2 ) , 'bo' )
hold off
xlim ( [ min ( BZpar) max ( BZpar) ] ) ;
set ( gca, 'XTick' , [ 0 1 2 3 ] , 'XTickLabel' , KL) ;
xlabel ( 'Bloch Wave Vector $\vec{\beta}$' , ... 'Interpreter' , 'LaTex' ) ;
ylabel ( 'Frequency $\omega_{\textrm{n}} = a/\lambda_0$' , ... 'Interpreter' , 'LaTex' ) ; subplot ( 1 , 2 , 2 )
hold on
plot ( BZpar, ImWNTM, '.k' ) ;
scatter ( CIm ( : , 1 ) , CIm ( : , 2 ) , 'bo' )
hold off
title ( 'TM' ) figure
subplot ( 1 , 2 , 1 )
hold on;
plot ( BZpar, ReWNTE, '.r' ) ;
hold off;
xlim ( [ min ( BZpar) max ( BZpar) ] ) ;
set ( gca, 'XTick' , [ 0 1 2 3 ] , 'XTickLabel' , KL) ;
xlabel ( 'Bloch Wave Vector $\vec{\beta}$' , ... 'Interpreter' , 'LaTex' ) ;
ylabel ( 'Frequency $\omega_{\textrm{n}} = a/\lambda_0$' , ... 'Interpreter' , 'LaTex' ) ; subplot ( 1 , 2 , 2 )
hold on
plot ( BZpar, ImWNTE, '.k' ) ;
hold off;
title ( 'TE' ) function [ op] = kxky ( num_point, a)
x0= 0 : 1 / num_point: 3 ;
op= zeros ( 2 , length ( x0) ) ;
for jj= 1 : length ( x0) x= x0 ( jj) ; if x>= 0 && x< 1 op ( : , jj) = [ pi / a; ( 1 - x) * ( pi / a) ] ; elseif x>= 1 && x< 2 op ( : , jj) = [ ( 2 - x) * ( pi / a) ; 0 ] ; elseif x>= 2 && x <= 3 op ( : , jj) = [ ( x- 2 ) * ( pi / a) ; ( x- 2 ) * ( pi / a) ] ; end end end function [ out] = shape_f ( xx, yy, xp, yp)
out= double ( inpolygon ( xx, yy, xp, yp) ) ; end function [ DEX, DEY, DHX, DHY] = yeeder2d ( NS, RES, BC, kinc)
%
%
%
%
Nx = NS ( 1 ) ; dx = RES ( 1 ) ;
Ny = NS ( 2 ) ; dy = RES ( 2 ) ;
if ~ exist ( 'kinc' ) kinc = [ 0 0 ] ;
end
M = Nx* Ny;
Z = sparse ( M, M) ;
if Nx== 1 DEX = - 1i * kinc ( 1 ) * speye ( M, M) ;
else d0 = - ones ( M, 1 ) ; d1 = ones ( M, 1 ) ; d1 ( Nx+ 1 : Nx: M) = 0 ; DEX = spdiags ( [ d0 d1] / dx, [ 0 1 ] , Z) ; if BC ( 1 ) == 1 d1 = zeros ( M, 1 ) ; d1 ( 1 : Nx: M) = exp ( - 1i * kinc ( 1 ) * Nx* dx) / dx; DEX = spdiags ( d1, 1 - Nx, DEX) ; end end
if Ny== 1 DEY = - 1i * kinc ( 2 ) * speye ( M, M) ;
else d0 = - ones ( M, 1 ) ; d1 = ones ( M, 1 ) ; DEY = spdiags ( [ d0 d1] / dy, [ 0 Nx] , Z) ; if BC ( 2 ) == 1 d1 = ( exp ( - 1i * kinc ( 2 ) * Ny* dy) / dy) * ones ( M, 1 ) ; DEY = spdiags ( d1, Nx- M, DEY) ; end end
DHX = - DEX' ;
DHY = - DEY' ;
end
不得不说Rumpf教授的FDFD代码是我目前见过的算得和comsol软件吻合得最好的代码!