MATLAB で ode45 を使用して一連の ODE を実行していますが、後で使用するために変数の 1 つ (導関数ではない) を保存する必要があります。関数 'assignin' を使用して、ベース ワークスペースに一時変数を割り当て、各ステップで更新しています。これは機能しているように見えますが、配列のサイズが ode45 から取得した解ベクトルのサイズと一致しません。たとえば、次のネストされた関数があります。
function [Z,Y] = droplet_momentum(theta,K,G,P,zspan,Y0)
options = odeset('RelTol',1e-7,'AbsTol',1e-7);
[Z,Y] = ode45(@momentum,zspan,Y0,options);
function DY = momentum(z,y)
DY = zeros(4,1);
%Entrained Total Velocity
Ve = sin(theta)*(y(4));
%Total Relative Velocity
Urs = sqrt((y(1) - y(4))^2 + (y(2) - Ve*cos(theta))^2 + (y(3))^2);
%Coefficients
PSI = K*Urs/y(1);
PHI = P*Urs/y(1);
%Liquid Axial Velocity
DY(1) = PSI*sign(y(1) - y(4))*(1 + (1/6)*(abs(y(1) - y(4))*G)^(2/3));
%Liquid Radial Velocity
DY(2) = PSI*sign(y(2) - Ve*cos(theta))*(1 + (1/6)*(abs(y(2) - ...
Ve*cos(theta))*G)^(2/3));
%Liquid Tangential Velocity
DY(3) = PSI*sign(y(3))*(1 + (1/6)*(abs(y(3))*G)^(2/3));
%Gaseous Axial Velocity
DY(4) = (1/z/y(4))*((PHI/z)*sign(y(1) - y(4))*(1 + ...
(1/6)*(abs(y(1) - y(4))*G)^(2/3)) + Ve*Ve - y(4)*y(4));
assignin('base','Ve_step',Ve);
evalin('base','Ve_out(end+1) = Ve_step');
end
end
上記のコードでは、theta (ラジアン)、K (負の値)、P、および G は定数であり、この例では、任意の値を使用できます。Zspan は ODE ソルバーの積分時間ステップであり、Y0 は初期条件ベクトル (4x1) です。繰り返しますが、この例のために、これらは任意の妥当な値を取ることができます。メインファイルでは、関数は次のように呼び出されます。
Ve_out = 0;
[Z,Y] = droplet_momentum(theta,K,G,P,zspan,Y0);
Ve_out = Ve_out(2:end);
この方法は MATLAB から問題なく動作しますが、問題は Ve_out のサイズが Z または Y のサイズと同じではないことです。この理由は、MATLAB がそのアルゴリズムに対して ODE 関数を複数回呼び出すためです。したがって、解決策は次のとおりです。 Ve_out よりわずかに小さくなります。am304 が示唆したように、ODE 関数に DY = モメンタム(Z,Y) などの Z および Y ベクトルを与えることで DY を単純に計算できますが、これを「assignin」(または同様の方法) で機能させる必要があります。この問題のバージョンでは、DY と Ve の間に暗黙の依存関係があり、反復ごとに DY を計算するには計算コストがかかりすぎます (この問題を何度も反復して実行します)。