2015-09-05 111 views
1

我试图模拟随着时间的推移无限板上的热量分布。为此,我写了一个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中是否有内置的聚合函数,可以让我为矩阵的所有元素执行此操作?我还没有找到方法的原因是每个点的结果都取决于其他矩阵点的值,这使得我使用嵌套循环来做到这一点。任何想法如何使其更快的升值。

回答

2

在我看来,要计算你的热量场的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

+0

是的,这是肯定不够快。真棒回答,谢谢! –

相关问题