前の回答は一般的には正しいですが、ODE のコンテキストでベクトル化すると、より具体的な意味になります。つまり、関数f(t,y)
は、列ベクトルに対してf(t,[y1 y2 ...])
が返される場合にベクトル化されます。ドキュメント[1]によると、「これにより、ソルバーはヤコビ行列のすべての列を計算するために必要な関数評価の数を減らすことができます。」[f(t,y1) f(t,y2) ...]
y1,y2
以下の関数はfun3
、fun4
ODE の意味で適切にベクトル化されます。
function re=rabdab()
x=linspace(0,20000,20000)';
opts=odeset('Vectorized','on');
tic;
[T,Y] = ode45(@fun,[x],[0 1 1]);
[T,Y] = ode45(@fun,[x],[0 1 1]);
[T,Y] = ode45(@fun,[x],[0 1 1]);
toc;
tic;
[A,B] = ode45(@fun2,[x],[0 1 1]);
[A,B] = ode45(@fun2,[x],[0 1 1]);
[A,B] = ode45(@fun2,[x],[0 1 1]);
toc;
tic;
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
toc;
tic;
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
toc;
function dy = fun(t,y)
dy = zeros(3,1); % a column vector
dy = [y(2) * y(3);...
-y(1) * y(3);...
-0.51 * y(1) * y(2);];
function dy = fun2(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
function dy = fun3(t,y)
dy = zeros(size(y)); % a matrix with arbitrarily many columns, rather than a column vector
dy = [y(2,:) .* y(3,:);...
-y(1,:) .* y(3,:);...
-0.51 .* y(1,:) .* y(2,:);];
function dy = fun4(t,y)
dy = [y(2,:) .* y(3,:);... % same as fun3()
-y(1,:) .* y(3,:);...
-0.51 .* y(1,:) .* y(2,:);];
(余談ですが、不必要なメモリ割り当てを省略して、よりもわずかに速く実行zeros
できます。)fun4
fun3
- Q: 最初の引数に関するベクトル化についてはどうですか?
- A: ODE ソルバーの場合、ODE 関数は 2 番目の引数に関してのみベクトル化されます。ただし、境界値問題ソルバー
bvp4c
は、1 番目と 2 番目の引数に関してベクトル化を必要とします。[1]
公式ドキュメント [1] には、ODE 固有のベクトル化に関する詳細が記載されています (セクション「ヤコビ プロパティの説明」を参照)。
[1] https://www.mathworks.com/help/releases/R2015b/matlab/ref/odeset.html