将额外的可变参数传递给 ode15s 函数 (MATLAB)
Pass extra variable parameters to ode15s function (MATLAB)
我正在尝试在 MATLAB 中求解常微分方程组。
我有一个简单的等式:
dy = -k/M *x - c/M *y+ F/M。
这是在我的 ode 函数 test2.m 中定义的,取决于值 X 和 t。我想用自定义函数 squaresignal.m 生成的信号触发 'F'。这里的输出是变量 u,范围从 0 到 1,因为它是一个平滑的重函数。 - 想想方波。 squaresignal.m 中的输入是 t 和 f。
u=squaresignal(t,f)
这些值将在我的函数 test2 中使用,以启用或禁用值为 u==1(启用)的变量 'F'。禁用所有其他值。
我的 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 循环似乎并没有什么神奇之处。当 u==1 时,我仍然只得到 F=0,而不是 F=F。而且我知道,有时 u 等于 1,因为 squaresignal.m 的输出对我来说是可见的。
所以真正的问题是这个。我如何正确地将我的变量 u 传递到我的函数 test2.m,并在那里使用它来触发 F?是否有可能 squaresignal.m 应该在 odefunction test2.m 内?
这是我将变量 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
触发行为,您应该将积分分成不同的部分,其中微分方程在一个部分中不会发生变化。然后,您可以使用当前状态和时间作为 ode15s 的下一个 运行 的 x0
和 t0
来恢复集成。当然这只适用于你的外部信号源 u
是一些简单的东西,比如阶跃函数或方波。在方波的情况下,您只会对波不跳跃的时间跨度进行积分。然后恰好在跳跃的时候,你开始用改变的微分方程进行另一个积分。
我正在尝试在 MATLAB 中求解常微分方程组。
我有一个简单的等式: dy = -k/M *x - c/M *y+ F/M。
这是在我的 ode 函数 test2.m 中定义的,取决于值 X 和 t。我想用自定义函数 squaresignal.m 生成的信号触发 'F'。这里的输出是变量 u,范围从 0 到 1,因为它是一个平滑的重函数。 - 想想方波。 squaresignal.m 中的输入是 t 和 f。
u=squaresignal(t,f)
这些值将在我的函数 test2 中使用,以启用或禁用值为 u==1(启用)的变量 'F'。禁用所有其他值。
我的 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 循环似乎并没有什么神奇之处。当 u==1 时,我仍然只得到 F=0,而不是 F=F。而且我知道,有时 u 等于 1,因为 squaresignal.m 的输出对我来说是可见的。
所以真正的问题是这个。我如何正确地将我的变量 u 传递到我的函数 test2.m,并在那里使用它来触发 F?是否有可能 squaresignal.m 应该在 odefunction test2.m 内?
这是我将变量 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
触发行为,您应该将积分分成不同的部分,其中微分方程在一个部分中不会发生变化。然后,您可以使用当前状态和时间作为 ode15s 的下一个 运行 的 x0
和 t0
来恢复集成。当然这只适用于你的外部信号源 u
是一些简单的东西,比如阶跃函数或方波。在方波的情况下,您只会对波不跳跃的时间跨度进行积分。然后恰好在跳跃的时候,你开始用改变的微分方程进行另一个积分。