我试图用有限差分法求解非线性扩散方程。它基本上是两个嵌套的for
循环,内部循环在网格上,外部循环推进方程式,有点像这样:
for i=1:(Nt-1)
for j=2:(Nx-1)
%%% simple diffusion equation
c(2,i+1) = c(1,i) + D*dt/dx/dx*(cL(1,j-1)2*cL(1,j)+cL(1,j+1));
end
%re-impose BCs
c(2,1)=1;
c(2,Nx)=1;
%save into solution matrix
if mod(i,floor(Nt/sol_no))==0
sol_c(sol_i+1,:) = c(2,:);
t_axis(sol_i+1,1) = i*dt;
sol_i=sol_i+1;
end
%flip rows 1 and 2
c = flipud(c);
end
为了节省内存,c只是一个2×Nx的矩阵,我每次都会在每次增量时翻转,比如每100个实例保存到一个解决方案矩阵中。
请注意,为了清楚起见,我在这里使用了简单的扩散方程。问题在于,实际上我必须使用非常精细的网格(理想情况下大约200,000个点),以便考虑一些快速变化的系数,这些系数是空间的函数。这与稳定性标准相结合,严格限制了时间步长和总时间。
现在,我想优化我的代码,我认为一种方法是在内循环中使用parfor
而不是for
。 c(2,:)行中的每个元素仅依赖于行c(1,:)中的元素,所以这应该有效,对吧?但是当我尝试运行它时,它会永远运行并且不能产生任何东西。我没有在代码片段中显示它,但是当循环开始时所有变量都已经初始化,因此我不确定导致问题的是什么。我阅读了parfor
文档,但我没有找到任何有用的内容。我怀疑它必须与切片有关,但我不确定如何解决它。此外,也许我错过了一些其他更有效的方法来解决这个问题,所以任何建议都值得赞赏。
编辑:我正在将我的代码的主旨添加到裸露的骨头上。 parfor
的执行速度比for
慢得多。
tic
gridpoints = 400000;
time_iter = 200;
c1 = ones(1,gridpoints);
c2 = ones(1,gridpoints);
x = linspace(0,1,gridpoints);
k = 1.0000001;
for j=1:time_iter
parfor i=2:gridpoints-1
c2(i) = c1(i-1) + k*c1(i) - c1(i+1);
end
c1=c2;
end
toc
答案 0 :(得分:1)
你可以完全消除内环,并使用Matlab的矢量化(使用你的第二个例子),这要快得多:
c2(2:end-1) = c1(1:end-2) + k * c1(2:end-1) - c1(3:end);
话虽这么说,你甚至可以完全消除c2:
c(2:end-1) = c(1:end-2) + k * c(2:end-1) - c(3:end);
并且可能想要在我们处理时添加边界条件:
c = [1; c(1:end-2) + k * c(2:end-1) - c(3:end); 1];
您还可以在外部循环外创建一个向量(idx = [2:gridpoints-1];)并相应地替换索引以阐明代码。
此外,如果您遇到稳定性问题,隐式方案可能更可取。