我在MATLAB中使用ode45运行一组ODE,我需要保存其中一个变量(不是衍生物)供以后使用。我正在使用函数'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函数一个Z和Y向量来计算DY,例如DY =动量(Z,Y),但是,我需要使用'assignin'(或类似的方法)来处理它,因为另一个这个问题的版本在DY和Ve之间存在隐含的依赖关系,并且在每次迭代时计算DY的计算成本太高(我将在许多次迭代中运行此问题)。
答案 0 :(得分:3)
好的,让我们先来看一个SSCCE的快速示例:
function [Z,Y] = khan
options = odeset('RelTol',1e-7,'AbsTol',1e-7);
[Z,Y] = ode45(@momentum,[0 12],[0 0],options);
end
function Dy = momentum(z,y)
Dy = [0 0]';
Dy(1) = 3*y(1) + 2* y(2) - 2;
Dy(2) = y(1) - y(2);
Ve = Dy(1)+ y(2);
assignin('base','Ve_step',Ve);
evalin('base','Ve_out(end+1) = Ve_step;');
assignin('base','T_step',z);
evalin('base','T_out(end+1) = T_step;');
end
通过运行[Z,Y] = khan
作为命令行,我得到了一个完整的功能代码,可以演示您的问题,而不会产生任何麻烦。我对此的耐心已经筋疲力尽:生活和学习。
这似乎有效,但是,数组的大小不匹配 从ode45获得的溶液向量的大小
请注意,我在代码中添加了两行,用于提取时间变量。在命令提示符下,只需运行以下命令即可了解正在发生的事情:
Ve_out = [];
T_out = [];
[Z,Y] = khan;
size (Z)
size (T_out)
size (Ve_out)
plot (diff(T_out))
ans =
109 1
ans =
1 163
ans =
1 163
基本上ode45是一种迭代算法,这意味着它会定期校正(这就是你经常看到diff(T)= 0的原因)。你不能强迫算法做你想做的事情,你必须忍受它。
所以你的选择是
1. Use a fixed step algorithm
2.在ode45算法完成其脏工作后,进行函数调用以再现所需的函数。 (am304的解决方案)
3.使用时间函数收集数据,然后使用算法解析所有内容以删除额外数据。
答案 1 :(得分:1)
[Z,Y] = droplet_momentum2(theta,K,G,P,zspan,Y0);
DY = momentum(Z,Y);
Ve = sin(theta)*(0.5*z*DY(4) + y(4));
即。一旦ODE得到解决,就计算导数DY
作为Z
和Y
(刚刚由ODE解决)和最后Ve
的函数。