我试图在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中?
答案 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
触发行为,则应将积分划分为不同的部分,其中微分方程在一个段内不变。然后,您可以使用当前状态和时间x0
和t0
恢复集成,以便下次运行ode15s。当然这只适用于你的外部信号源u
是一种简单的步骤函数或方波。在方波的情况下,您只会整合一个时间跨度,在此期间波不会跳跃。然后恰好在跳跃时你开始另一个与改变的微分方程的积分。