将额外的变量参数传递给ode15s函数(MATLAB)

时间:2015-06-08 14:49:56

标签: matlab for-loop ode

我试图在MATLAB中解决常微分方程组。

我有一个简单的等式: dy = -k / M * x - c / M * y + F / M.

这是在我的ode函数test2.m中定义的,取决于值X和t。我想要触发F' F'带有信号,由我的自定义函数squaresignal.m生成。这里的输出是变量u,从0到1,因为它是一个平滑的重载函数。 - 想方波。 squareignal.m中的输入是t和f。

u=squaresignal(t,f)

这些值将在我的函数test2中使用,以启用或禁用变量' F'值为u == 1(启用)。禁用所有其他值。

我的ode函数test2.m读取:

function dX = test2(t ,X, u)
x = X (1) ;
y = X (2) ;

M = 10;
k = 50;
c = 10;
F = 300;

if u == 1
    F = F;
else
    F = 0,
end

dx = y ;
dy = -k/M *x - c/M *y+ F/M ;

dX = [ dx dy ]';
end

我的脚本写着:

clc
clear all

tstart = 0;
tend = 10;
tsteps = 0.01;

tspan = [0 10];
t = [tstart:tsteps:tend];
f = 2;

u = squaresignal(t,f)

for ii = 1:length(u)
    options=odeset('maxstep',tsteps,'outputfcn',@odeplot);
    [t,X]=ode15s(@(t,X)test2(t,X,u(ii)),[tstart tend],[0 0],u);
end


figure (1);
plot(t,X(:,1))

figure (2);
plot(t,X(:,2));

然而,for-loop似乎没有做到这一点。当u == 1时,我仍然只得到F = 0而不是F = F.而且我知道,在某些时候你是等于一个,因为squareignal.m的输出对我来说是可见的。

所以真正的问题是这个。我如何正确地将我的变量u传递给我的函数test2.m,并在那里使用它来触发F? squareignal.m是否应该在odefunction test2.m中?

1 个答案:

答案 0 :(得分:2)

以下是我将变量coeff传递给微分方程的示例:

function [T,Q] = main()
  t_span = [0 10];
  q0 = [0.1; 0.2];        % initial state
  ode_options = odeset(); % currently no options... You could add some here
  coeff = 0.3;            % The parameter we wish to pass to the differential eq.

  [T,Q] = ode15s(@(t,q)diffeq(t,q,coeff),t_span,q0, ode_options);
end

function dq = diffeq(t,q,coeff)
  % Preallocate vector dq
  dq = zeros(length(q),1);

  % Update dq:
  dq(1) = q(2);
  dq(2) = -coeff*sin(q(1));
end

编辑: 这可能是问题吗?

tstart = 0;
tend = 10;
tsteps = 0.01;

tspan = [0 10];
t = [tstart:tsteps:tend];
f = 2;

u = squaresignal(t,f)

在这里创建一个时间向量t,它与ODE求解器返回的时间向量无关!这意味着我们首先得到t[2]=0.01,但是一旦运行了ODE求解器,t[2]就可以了。所以,是的,如果你想根据时间加载外部信号源,那么你需要从微分方程中调用 squaresignal.m 并传递求解器的当前时间t!您的代码应该如下所示(请注意,我现在将f作为另一个参数传递给diffeq):

function dX = test2(t ,X, f)
x = X (1) ;
y = X (2) ;

M = 10;
k = 50;
c = 10;
F = 300;

u = squaresignal(t,f)
if u == 1
    F = F;
else
    F = 0,
end

dx = y ;
dy = -k/M *x - c/M *y+ F/M ;

dX = [ dx dy ]';
end

但请注意,matlab的ODE解算器根本不喜欢你在这里做的事情。你正在大幅度地(即不顺利地)改变系统的动态。你应该做的是使用以下之一:

a)events如果您想触发某些行为(例如终止),具体取决于集成变量x

b)如果要根据时间t触发行为,则应将积分划分为不同的部分,其中微分方程在一个段内不变。然后,您可以使用当前状态和时间x0t0恢复集成,以便下次运行ode15s。当然这只适用于你的外部信号源u是一种简单的步骤函数或方波。在方波的情况下,您只会整合一个时间跨度,在此期间波不会跳跃。然后恰好在跳跃时你开始另一个与改变的微分方程的积分。