我有一个僵化的耦合ODE系统,我正在为MATLAB的ode15s
解算器提供支持。它工作得很好,但现在我正在努力优化集成的速度。我在N
个不同的空间位置上建模了5个不同的变量,给出了5N耦合方程。目前,N=20
和积分时间约为25秒,但我希望更大的N
值。
我使用分析器看到绝大部分时间用于评估myODEfun
。我尽了最大努力来优化代码,但这并没有改变这样一个事实,即函数中有相当多的事情,并且它被评估〜50,000次。我读到使用'Vectorized'
的{{1}}属性可以减少所需的评估次数。
但我不太清楚我需要更改我的ODEfunction
到底是什么让它符合Matlab想要ODEfun
'vectorized'
的样子。< / p>
From the documentation我看到你可以改变示例Van der Pol系统的正常形式:
ODEfun
到矢量化形式:
function dydt = vdp1000(t,y)
dydt = [y(2); 1000*(1-y(1)^2)*y(2)-y(1)];
我并不确切地知道这个function dydt = vdp1000(t,y)
dydt = [y(2,:); 1000*(1-y(1,:).^2).*y(2,:)-y(1,:)];
的新矩阵应该代表什么,以及第二维的大小是如何定义的。我几乎可以只添加“y
”而不考虑它,但我遇到了问题,因为我已经在我的代码中进行了一些向量操作。
以下是我当前功能的简化示例,尚未,:
。它模拟2个变量,制作vectorized
方程。请不要试图理解这里生成的ODE:它们不会。我在谈论正在发生的行动。
2*N
显然,在实际功能中,function dydt = exampleODEfun(t,y,N)
dydt = zeros(2*N,1);
dTdt = zeros(N,1);
dXdt = zeros(N,1);
T = y(1:N);
X = y(N+1:2*N);
a = [T(2:N).^2 T(2:N) ones(N-1,1)];
b = [3 5 -2];
dTdt(1:N) = 0;
dXdt(1) = 0;
dXdt(2:N) = a*b';
dydt(1:N) = dTdt;
dydt(N+1:2*N) = dXdt;
end
和T
都会发生更多事情。如您所见,X
是一个边界条件,需要自己计算。
盲目地传递odeset dXdt(1)
并且仅向所有索引添加“'Vectorized','on'
”不起作用。例如,我需要将,:
和dTdt
初始化为什么尺寸?我该怎么做dXdt
?我需要做些什么才能使(ones(N-1,1)
)仍然有意义?
我正在使用Matlab R2006a。
答案 0 :(得分:2)
来自help odeset
:
矢量化 - 矢量化ODE函数[on | {off}]
Set this property 'on' if the ODE function F is coded so that F(t,[y1 y2 ...]) returns [F(t,y1) F(t,y2) ...].
对于van der Pol的例子:
没有矢量化:
function dydt = vdp1000(t,y) %// 'y' is passed as [y1
%// y2]
dydt = [y(2); %// 'dydt' is computed as [y1´
1000*(1-y(1)^2)*y(2)-y(1)] %// y2´]
%// where the ´ indicates d/dt
带有矢量化的:
function dydt = vdp1000(t,y) %// 'y' is passed as [y11 y21 y31 ...
%// y12 y22 y32 ...]
dydt = [y(2,:); %// 'dydt' is computed as
1000*(1-y(1,:).^2).*y(2,:)-y(1,:)]; %// [y11´ y21´ y31´ ...
%// y12´ y22´ y32´ ...]
其中y1
,y2
,y3
等同时引用不同的向量y
t
ode15s
将y
用来计算下一步。
对于您的示例,您必须考虑到您传递的function dydt = exampleODEfun(t,y,N)
%// Adjust sizes to meet size of y
dydt = zeros(2*N, size(y,2));
dTdt = zeros(N, size(y,2));
dXdt = zeros(N, size(y,2));
%// Adjust indices to extract proper vales of ALL vectors
T = y(1:N,:);
X = y(N+1:2*N,:);
%// This sort of section is usually where all the "thought" goes into:
%// you can't use a*b' anymore, so I sum over the third dimension of the
% 3D array I built from your original vector
b = [3 5 -2];
ab = sum(cat(3, b(1)*T(2:N,:).^2, b(2)*T(2:N,:), b(3)*ones(N-1, size(y,2))), 3);
%// and finish it off
dTdt(1:N,:) = 0;
dXdt(1,:) = 0;
dXdt(2:N,:) = ab;
dydt(1:N,:) = dTdt;
dydt(N+1:2*N,:) = dXdt;
end
不再是矢量,而是一个矩阵,其中每列代表您需要计算衍生物的不同矢量:
{{1}}