如何在 ode 求解器中为每个时间步使用矩阵的一个值
How to use one value of a matrix for each time step inside ode solver
我有一个长度为 N 的向量 x
,我想用它的值来求解微分方程:dy/dt = x - 4*y
。对于每一步,我都希望 ode 求解器函数使用向量的一个值,然后在下一步中使用矩阵的下一个值。
我尝试通过将向量声明为全局变量并在 ode 求解器中像这样使用它来这样做:
global x
tspan = 0:0.01:10;
[t,filter_coef] = ode45(@ode_filter,tspan,0);
求解函数如下:
function dx = ode_filter(t,fil)
global x
dx = x - 4*fil(1);
end
产生以下错误
ODE_FILTER returns a vector of length 1002, but the length of initial conditions vector is 1. The vector returned by
ODE_FILTER and the initial conditions vector must have the same number of elements.
y
是 t
的函数,不是 x
的函数。
从上面的等式中,除非您先定义 x
值,否则 y
将是
t
和 x
.
的函数
也ode45
return只有双值,不是函数y本身
但是它是在不同时间的评估
可以做的是定义一个抛出给定未知数的函数
值 x
到 ode45
。然后就得到了我上面推导的函数
下一步只需设置给定的 x
并计算函数。功能
评估给出结构数据类型,主要字段是 x
和 y
。 x
是你的 t
而 y 仍然是你的 y
global x
tspan = 0:0.01:10;
f = @(x)ode45(@ode_filter, tspan,0);
%% Set x Value First
x = 2;
var = f(x);
t = var.x;
y = var.y;
您的方法可能基于您对显式欧拉方法的理解。如果是这种情况,您最好通过实施(指数)显式 Euler 方法。
求解器 ode45
,因为所有其他 matlab ODE 求解器(没有特定选项?)具有自动适应问题和当前状态的可变步长。此外,在每个步骤中,都会多次计算传递的右侧 ODE 函数。此外,步长调节器取决于右侧函数高阶的平滑度,non-smooth 基因座导致步长急剧减小,并可能从同一当前状态多次重启,进一步与您的假设相矛盾。
因此,即使您成功实现了您的想法,您实际上也是在为您的函数添加随机噪声,导致求解器无法使用,因为违反了基本假设。就算出了结果,也和你想达到的目的几乎没有关系。
实现您想要生成的东西的最快方法是确定 x
值关联的时间,并使用一些插值函数、零阶保持或线性插值来获得在可变时间的正确值。
使用 solution extension 使用平滑的右侧求解每个线段,更改每个线段 [ tx(k), tx(k+1) ]
的常量 x(k)
。定义函数有参数,避免global
变量
的麻烦
function dy = ode_filter(t,y,x)
dy = x - 4*y;
end
然后为第一个段调用积分器进行初始化,然后为所有剩余的段使用它们的常量和段结束调用积分器。
sol = ode45(@(t,y)ode_filter(t,y,x(1)), [ tx(1) tx(2) ], y0)
for k in 2:N
sol = odextend(sol,@(t,y)ode_filter(t,y,x(k)),tx(k+1));
end
(始终考虑使用选项机制来设置自定义的、特定于问题的错误容忍度。)
我有一个长度为 N 的向量 x
,我想用它的值来求解微分方程:dy/dt = x - 4*y
。对于每一步,我都希望 ode 求解器函数使用向量的一个值,然后在下一步中使用矩阵的下一个值。
我尝试通过将向量声明为全局变量并在 ode 求解器中像这样使用它来这样做:
global x
tspan = 0:0.01:10;
[t,filter_coef] = ode45(@ode_filter,tspan,0);
求解函数如下:
function dx = ode_filter(t,fil)
global x
dx = x - 4*fil(1);
end
产生以下错误
ODE_FILTER returns a vector of length 1002, but the length of initial conditions vector is 1. The vector returned by
ODE_FILTER and the initial conditions vector must have the same number of elements.
y
是t
的函数,不是x
的函数。从上面的等式中,除非您先定义
x
值,否则y
将是t
和x
. 的函数
也
ode45
return只有双值,不是函数y本身 但是它是在不同时间的评估可以做的是定义一个抛出给定未知数的函数 值
x
到ode45
。然后就得到了我上面推导的函数下一步只需设置给定的
x
并计算函数。功能 评估给出结构数据类型,主要字段是x
和y
。x
是你的t
而 y 仍然是你的y
global x
tspan = 0:0.01:10;
f = @(x)ode45(@ode_filter, tspan,0);
%% Set x Value First
x = 2;
var = f(x);
t = var.x;
y = var.y;
您的方法可能基于您对显式欧拉方法的理解。如果是这种情况,您最好通过实施(指数)显式 Euler 方法。
求解器 ode45
,因为所有其他 matlab ODE 求解器(没有特定选项?)具有自动适应问题和当前状态的可变步长。此外,在每个步骤中,都会多次计算传递的右侧 ODE 函数。此外,步长调节器取决于右侧函数高阶的平滑度,non-smooth 基因座导致步长急剧减小,并可能从同一当前状态多次重启,进一步与您的假设相矛盾。
因此,即使您成功实现了您的想法,您实际上也是在为您的函数添加随机噪声,导致求解器无法使用,因为违反了基本假设。就算出了结果,也和你想达到的目的几乎没有关系。
实现您想要生成的东西的最快方法是确定 x
值关联的时间,并使用一些插值函数、零阶保持或线性插值来获得在可变时间的正确值。
使用 solution extension 使用平滑的右侧求解每个线段,更改每个线段 [ tx(k), tx(k+1) ]
的常量 x(k)
。定义函数有参数,避免global
变量
function dy = ode_filter(t,y,x)
dy = x - 4*y;
end
然后为第一个段调用积分器进行初始化,然后为所有剩余的段使用它们的常量和段结束调用积分器。
sol = ode45(@(t,y)ode_filter(t,y,x(1)), [ tx(1) tx(2) ], y0)
for k in 2:N
sol = odextend(sol,@(t,y)ode_filter(t,y,x(k)),tx(k+1));
end
(始终考虑使用选项机制来设置自定义的、特定于问题的错误容忍度。)