如何对Scilab中的所有矩阵元素执行操作?
我试图模拟随着时间的推移无限板上的热量分布。为此,我写了一个Scilab脚本。现在,它的关键点,是所有平板点温度的计算,它对于每次例如做我想观察:如何对Scilab中的所有矩阵元素执行操作?
for j=2:S-1
for i=2:S-1
heat(i, j) = tcoeff*10000*(plate(i-1,j) + plate(i+1,j) - 4*plate(i,j) + plate(i, j-1) + plate(i, j+1)) + plate(i,j);
end;
end
的问题是,如果我想做一个100×100点的板,这意味着,在这里(这仅适用于内部,没有边界条件),我将不得不环路98x98 = 9604倍,动辄给定i,j
点计算的热量。如果我想观察一下,例如100秒,步长为1秒,我必须重复100次,共计960,400次迭代。这需要相当长的时间,我想避免它。高达50x50的平板,全都在合理的4-5秒的时间内完成。
现在的问题是 - 是否有必要做这一切使用for
循环? Scilab中是否有内置的聚合函数,可以让我为矩阵的所有元素执行此操作?我还没有找到方法的原因是每个点的结果都取决于其他矩阵点的值,这使得我使用嵌套循环来做到这一点。任何想法如何使其更快的升值。
在我看来,要计算你的热量场的2D相互关联和一定的扩散模式。这种模式可以被认为是一个“滤波器”内核,这是一种用线性滤波器矩阵修改图像的常用方法。你的“过滤器”是:
F=[0,1,0;1,-4,1;0,1,0];
如果您安装了图像处理工具箱(IPD),你将有一个MaskFilter
功能做到这一点2D相互关联。
S=500;
plate=rand(S,S);
tcoeff=1;
//your solution with nested for loops
t0=getdate();
for j=2:S-1
for i=2:S-1
heat(i, j) = tcoeff*10000*(plate(i-1,j)+plate(i+1,j)-..
4*plate(i,j)+plate(i,j-1)+plate(i, j+1))+plate(i,j);
end
end
t1=getdate();
T0=etime(t1,t0);
mprintf("\nNested for loops: %f s (100 %%)",T0);
//optimised nested for loop
F=[0,1,0;1,-4,1;0,1,0]; //"filter" matrix
F=tcoeff*10000*F;
heat2=zeros(plate);
t0=getdate();
for j=2:S-1
for i=2:S-1
heat2(i,j)=sum(F.*plate(i-1:i+1,j-1:j+1));
end
end
heat2=heat2+plate;
t1=getdate();
T2=etime(t1,t0);
mprintf("\nNested for loops optimised: %f s (%.2f %%)",T2,T2/T0*100);
//MaskFilter from IPD toolbox
t0=getdate();
heat3=MaskFilter(plate,F);
heat3=heat3+plate;
t1=getdate();
T3=etime(t1,t0);
mprintf("\nWith MaskFilter: %f s (%.2f %%)",T3,T3/T0*100);
disp(heat3(1:10,1:10)-heat(1:10,1:10),"Difference of the results (heat3-heat):");
请注意,MaskFilter
垫的图像(原始矩阵)应用滤镜之前,据我所知,它使用越过边境的“镜像”阵列。你应该检查这种行为是否适合你。
速度增加大约×320(执行时间是你的原代码0.32%)。这足够快吗?
在理论上它可能有两个2D傅立叶变换完成(与Scilab的内置mfft
也许),但它可能不会比这更快。在这里看到:http://mailinglists.scilab.org/Image-processing-filter-td2618144.html#a2618168
是的,这是肯定不够快。真棒回答,谢谢! –