2015-09-05 89 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

是的,這是肯定不夠快。真棒回答,謝謝! –

相關問題