我已经找到了几个问题/答案,用于矢量化和加速用于在单个循环中乘以矩阵和向量的例程,但我试图做一些更通用的事情,即将任意数量的矩阵相乘,以及然后执行该操作任意次数。
我正在编写一个计算从任意数量的层到光学频率的薄膜反射的一般程序。对于每个光学频率W
,每个层具有折射率N
和相关的2x2传递矩阵L
和2x2接口矩阵I
,其取决于折射率和层的厚度。如果n
是层数,m
是频率数,那么我可以将索引矢量化为nxm矩阵,但是为了计算每个频率的反射,我必须做嵌套循环。由于我最终使用它作为拟合程序的一部分,所以我能做的任何事情都可以加快它的速度。
这应该提供一个最小的工作示例:
W = 1260:0.1:1400; %frequency in cm^-1
N = rand(4,numel(W))+1i*rand(4,numel(W)); %dummy complex index of refraction
D = [0 0.1 0.2 0]/1e4; %thicknesses in cm
[n,m] = size(N);
r = zeros(size(W));
for x = 1:m %loop over frequencies
C = eye(2); % first medium is air
for y = 2:n %loop over layers
na = N(y-1,x);
nb = N(y,x);
%I = InterfaceMatrix(na,nb); % calculate the 2x2 interface matrix
I = [1 na*nb;na*nb 1]; % dummy matrix
%L = TransferMatrix(nb) % calculate the 2x2 transfer matrix
L = [exp(-1i*nb*W(x)*D(y)) 0; 0 exp(+1i*nb*W(x)*D(y))]; % dummy matrix
C = C*I*L;
end
a = C(1,1);
c = C(2,1);
r(x) = c/a; % reflectivity, the answer I want.
end
对于具有2562个频率的三层(空气/填料/基板)问题,两次不同的极化运行两次需要0.952秒,而对于三层系统,使用显式公式(矢量化)解决完全相同的问题需要0.0265秒。问题是超过3层,显式公式很快变得棘手,我必须为每个层数设置不同的子程序,而上述是完全一般的。
是否希望对此代码进行矢量化或以其他方式加快速度?
(编辑补充说我已经从代码中留下了一些东西来缩短它,所以请不要尝试使用它来实际上计算反射率)
编辑:为了澄清,I
和L
对于每个层和每个频率都不同,因此它们在每个循环中都会发生变化。简单地使用指数是行不通的。对于一个现实世界的例子,在空气中采用最简单的肥皂泡。有三层(空气/肥皂/空气)和两个界面。对于给定频率,完整传输矩阵C
为:
C = L_air * I_air2soap * L_soap * I_soap2air * L_air;
和I_air2soap ~= I_soap2air
。因此,我从L_air = eye(2)
开始然后沿着连续的层向下,计算I_(y-1,y)和L_y,将它们与前一个循环的结果相乘,然后继续直到我到达底部堆。然后我抓住第一个和第三个值,取比率,那就是那个频率的反射率。然后我继续下一个频率再做一遍。
我怀疑答案将以某种方式涉及每层的块对角矩阵,如下所述。
答案 0 :(得分:2)
不在matlab旁边,所以这只是一个启动器,
您可以将na*nb
写为Nab=N(1:end-1,:).*N(2:end,:);
,而不是双循环
指数nb*W(x)*D(y)
中的术语可写为e=N(2:end,:)*W'*D;
I*L
的结果是具有以下形式的2x2块矩阵:
M = [1, Nab; Nab, 1]*[e-, 0;0, e+] = [e- , Nab*e+ ; Nab*e- , e+]
e-
为exp(-1i * e),e+
为exp(1i * e)'
请参阅kron
了解如何获取块矩阵表单,对传播进行矢量化C=C*I*L
只需M^n
答案 1 :(得分:2)
@Lama通过建议块矩阵让我走上正确的道路,但最终的答案最终变得更加复杂,所以我把它放在这里为后代。由于传输和接口矩阵对于每一层都是不同的,因此我将循环留在层上,但构造一个大的稀疏块矩阵,其中每个块代表一个频率。
W = 1260:0.1:1400; %frequency in cm^-1
N = rand(4,numel(W))+1i*rand(4,numel(W)); %dummy complex index of refraction
D = [0 0.1 0.2 0]/1e4; %thicknesses in cm
[n,m] = size(N);
r = zeros(size(W));
C = speye(2*m); % first medium is air
even = 2:2:2*m;
odd = 1:2:2*m-1;
for y = 2:n %loop over layers
na = N(y-1,:);
nb = N(y,:);
% get the reflection and transmission coefficients from subroutines as a vector
% of length m, one value for each frequency
%t = Tab(na, nb);
%r = Rab(na, nb);
t = rand(size(W)); % dummy vector for MWE
r = rand(size(W)); % dummy vector for MWE
% create diagonal and off-diagonal elements. each block is [1 r;r 1]/t
Id(even) = 1./t;
Id(odd) = Id(even);
Io(even) = 0;
Io(odd) = r./t;
It = [Io;Id/2].';
I = spdiags(It,[-1 0],2*m,2*m);
I = I + I.';
b = 1i.*(2*pi*D(n).*nb).*W;
B(even) = -b;
B(odd) = b;
L = spdiags(exp(B).',0,2*m,2*m);
C = C*I*L;
end
a = spdiags(C,0);
a = a(odd).';
c = spdiags(C,-1);
c = c(odd).';
r = c./a; % reflectivity, the answer I want.
使用上面提到的3层系统,它不如显式公式快,但它很接近,并且在进行一些分析后可能会更快一些。完整版本的原始代码时钟为0.97秒,公式为0.012秒,稀疏对角线版本为0.065秒。