【问题标题】:Matlab: ode45 and 4-th order Runge-Kutta method yield different valuesMatlab:ode45 和 4 阶 Runge-Kutta 方法产生不同的值
【发布时间】:2018-08-28 18:10:50
【问题描述】:

我正在尝试在 Matlab 中模拟仓本振荡。我尝试使用 ode45 来解决系统问题。我还看到其他人使用 Runge-kutta 方法。我知道 ode45 使用 Runge-kutta 方法,但是,我从每个方法中获得的值可疑地不同。

kuramoto= @(x,K,N,Omega)Omega+(K/N)*sum(sin(x*ones(1,N)-(ones(N,1)*x')))'
%Kuramoto is a model of N coupled ocilators (such as multiple radiowaves)
%The solution to the model is the phase of each ocilator
%[Kuramoto Equation][1]

theta(:,1) = 2*pi*randn(N,1);
t0 = theta(:,1);
[t,y] = ode45(@(t,y)kuramoto(theta(:,1),K,N,omega),tspan,t0);

%Runge-Kutta method
for j=1:iter
k1=kuramoto(theta(:,j),K,N,omega);
k2=kuramoto(theta(:,j)+0.5*h*k1,K,N,omega);
k3=kuramoto(theta(:,j)+0.5*h*k2,K,N,omega);           
k4=kuramoto(theta(:,j)+h*k3,K,N,omega);
theta(:, j+1)=theta(:,j)+(h/6)*(k1+2*k2+2*k3+k4);
end

这两种方法都输出一个包含 N 行(其中每行代表不同的振荡器)和 M 列(其中 M 代表给定时间的解)的矩阵。我让 ode45 以 0.1 的间隔提供从 0 到 0.5 的解。为了比较这些方法,我将从 Runge-Kutta 获得的矩阵与使用 ode45 获得的矩阵相减。理想情况下,两者应该具有相同的值,结果应该是一个 zeor 矩阵,但我得到的值如下:

0   -0.0003   -0.0012   -0.0027   -0.0048   -0.0076
0    0.0003    0.0012    0.0027    0.0048    0.0076
%here I have only two oscillators from t = [0.0,0.5] 

两个矩阵之间存在微小差异(以较大的时间间隔增长)。但不同寻常的是,每次计算的总值(即每一列)都是相同的。无论振荡器的数量如何,这都是一致的。

我不确定这是数学问题还是编程问题(可能两者都有),并且我认为我错误地调用了 ode45,但我不确定并且几天来一直无法找出问题所在.任何帮助将不胜感激。

【问题讨论】:

标签: matlab math ode45


【解决方案1】:

您应该使用 ode45 输出。如果您选择的步长太大,您实现的 Runge Kutta 最终将变得不稳定。 ode45 的全部意义在于它在内部运行 Runge Kutta 4 和 Runge Kutta 5 方案。如果一个积分步骤的结果不同,则 ode45 将减少时间步骤,直到结果具有可比性。像你正在做的那样使用原始方法显然不会那样做。

从技术上讲,像 ode45 这样的东西被称为“嵌入式龙格库塔”方法。这是一种这样的方法:https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta%E2%80%93Fehlberg_method 它们是高效的,因为不同阶的 Runge Kutta 方法重用了许多相同的函数评估。

说了这么多,你应该会发现,如果你足够减少你的时间步,结果几乎是一样的。它们不同的唯一原因是 ode45 在检测到解决方案可能不准确时会在内部优化时间步长。

【讨论】:

  • 这能解释为什么差值总和为 0 吗?
  • 从问题中我不清楚您要在那里提出什么观点。您正在显示两行输出。这些值是连续的吗?
  • 另外,如果您怀疑有错误,我要做的第一件事是使用这两种方法绘制响应图。它们有本质不同吗?
  • 抱歉,我对您的型号一无所知。当您说 2 个不同的振荡器时,您是什么意思?你的意思是你用不同的模型运行了两次 ode45?
  • Runge Kutta 方法返回什么值?
【解决方案2】:

你真的用过这条线吗

[t,y] = ode45(@(t,y)kuramoto(theta(:,1),K,N,omega),tspan,t0);

在您的运行代码中?那么这里的结果肯定是错误的。使用

[t,y] = ode45(@(t,u)kuramoto(u,K,N,omega),tspan,t0);

获得至少与 RK4 集成相关的结果。也就是说,在计算其值时使用匿名函数声明的局部变量/参数。 (使用 u 而不是 ytheta 以不重用也在更全局范围内使用的变量名称。如果需要自记录变量名称,可以使用 thetalocal 代替。)


PS:差异之和为零是由于导数向量之和为零,因此状态向量上的和是一个常数,而不管应用这些方法时所犯的错误如何。因此,如果您从自身中减去相同的常数,您最终会再次为零。如果状态向量只有 2 个元素,那么差分向量的元素必须是相反的。

【讨论】:

  • 澄清一下 u 是否等于 theta(:,1)?
  • 不,为什么会这样? theta(:,1) 是初始值,你传递的函数必须是 ODE 系统函数,这取决于参数中传递的状态。
  • 抱歉,您能否再澄清一点。特别是“在计算其值时使用匿名函数的声明的局部变量/参数”。你是说你应该是象征性的吗?
  • 不,不是象征性的。阅读什么匿名函数。 lambda 表达式是。在您的版本中,您将常量与 ode45 集成,而 RK4 集成正确地集成了 ODE。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 2015-03-19
  • 1970-01-01
相关资源
最近更新 更多