你好,这里是arcadia13。

在这第 15 篇 MATLAB 文章中,我将解释其中一种数值计算方法,即 Runge-Kutta 方法(经典的 Runge-Kutta 方法)。

这是欧拉法的改进,与真解的误差小于欧拉法得到的近似解。

在这里,我们解释了广泛使用的“四阶龙格-库塔法”。

实际上,在 ode45() 命令中使用了 Runge-Kutta 方法。

换句话说,实现 Runge-Kutta 方法可以被认为是自己实现 ode45() 命令。

1.龙格-库塔算法

Runge-Kutta 算法与第 14 部分中解释的 Euler 方法几乎相同。所以,让我们先回顾一下欧拉的方法。

有关欧拉方法的详细信息,请参阅第 14 部分。

欧拉算法

  1. 确定微分方程$y_0=y(x_0)$的初始值和积分范围$a(=x_0) leq x leq b$。这为欧拉方法提供了起点 $(x,y)=(x_0, y_0)$。

  2. 将积分范围除以 $n$,再除以步长 $h$。即 $x_{k+1}=x_k + h
    (k=0,1,...,n−1), x_0=a, x_n=b$。

  3. 假设$y_k=y(x_k)$,将$(x_k,y_k)$代入近似$y_{k+1}pprox y_k + hf(x_k,y_k)$得到$y_{k+1}$求

  4. 重复第 3 步,直到从 $y_1$ 获得 $y_n$。

Euler 方法和 Runge-Kutta 方法的区别在于近似公式。

将近似公式 $y_{k+1}pprox y_k + hf(x_k,y_k)$ 的 $f(x_k,y_k)$ 部分更改如下。

龙格-库塔法中的近似公式

egin{eqnarray}
y_{k+1} &pprox& y_k + hcfrac{k_1 + 2k_2 + 2k_3 + k_4}{6}\
k_1 &=& f(x_k, y_k)\
k_2 &=& f(x_k + rac{h}{2}, y_k + rac{h}{2}k_1)\
k_3 &=& f(x_k + rac{h}{2}, y_k + rac{h}{2}k_2)\
k_4 &=& f(x_k + h, y_k + k_3)\
end{eqnarray}

是不是处于不想看到的状态……

但是仔细看。我做的很简单,我只是通过将各种值代入$f(x,y)$来进行计算。

它与欧拉方法的作用相同,因为它被替换和计算。

实际上,欧拉法也是通过将$(x_k, y_k)$ 代入$f(x,y)$ 来计算的。我只是稍微调整了一下。

该算法的其余部分与欧拉方法完全相同。大多数 Runge-Kutta 方法都是在实现 Euler 方法时实现的。

2 Runge-Kutta 方法的实现

我们现在转向 Runge-Kutta 方法的实现。

由于我要实现 Runge-Kutta 方法(?),让我们通过结合我最喜欢的物理来解决运动方程。

主题是高中物理力学熟悉的“斜投影”。

为简单起见,我们考虑二维平面上的运动并忽略空气阻力。

让我们尝试绘制放置在平面原点的质点的轨迹,方法是在 45 度仰角的方向上发射它。

我将初始速度设置为 $10 ext{m/s}$。

样品1.m
% 質点の斜方投射

clear; clc;
%% 物理パラメータと運動方程式の初期条件
% 手順1,2はここで行う

x0 = 0; y0 = 0; % 原点
g = 9.8; % 重力加速度
theta = (45/180)*pi; % 45度の方向へ投げる
v0 = 10; % 初速度 m/s

% 運動方程式の初期条件
Y0 = [y0; v0*sin(theta)];

% シミュレーション時間
h = 10^(-4); %刻み幅
t = 0:h:5;

%% 運動方程式を解いてボールの軌跡を描画

x = x0 + v0*cos(theta)*t;
y = ClassicalRungeKutta(@MotionEquation, t, Y0); % 近似解
yTrue = y0 + v0*sin(theta)*t - (g*t.^2)/2; % 真の解

plot(x, y(1,:), 'LineWidth', 1.3); 
hold on
plot(x, yTrue, 'g--','LineWidth', 1.3)
title('斜方投射')
legend('質点の軌跡')
xlabel('x[m]')
ylabel('y[m]')
set(gca,'FontSize',13)
ylim([0 5])
grid on


%% 斜方投射(鉛直上向き)の運動方程式
function Ydot = MotionEquation(t, Y)
 g = 9.8;
 nrow = length(Y);
 Ydot = zeros(nrow, 1);

 Ydot(1,1) = Y(2);
 Ydot(2,1) = -g;
end


%% ルンゲ・クッタ法
function Yout = ClassicalRungeKutta(func, t, Y0)
  % func:微分方程式の関数ハンドル
  % t:積分範囲(hで分割済み)
  % Y0:初期値
  nrow = length(Y0);
  ncol = length(t);

  Y = zeros(nrow, ncol);
  Y(:,1) = Y0; % 初期値の代入

  h = t(2) - t(1); % 刻み幅

  % 手順3,4
  for k = 1:ncol-1
      k1 = feval(func, t(k), Y(:,k));
      k2 = feval(func, t(k) + h/2, Y(:,k) + h*k1/2);
      k3 = feval(func, t(k) + h/2, Y(:,k) + h*k2/2);
      k4 = feval(func, t(k) +h, Y(:,k) + h*k3);
      Y(:, k+1) = Y(:, k) + h*(k1 + 2*k2 + 2*k3 + k4)/6;
  end
  Yout = Y;
end

for语句的内容也可以这样写(我用@WolfMoon的代码作为参考)。

k1 = func(t(k), Y(:,k));
k2 = func(t(k) + h/2, Y(:,k) + h*k1/2);
k3 = func(t(k) + h/2, Y(:,k) + h*k2/2);
k4 = func(t(k) +h, Y(:,k) + h*k3);
Y(:, k+1) = Y(:, k) + h*(k1 + 2*k2 + 2*k3 + k4)/6;
MATLABでルンゲ・クッタ法を実装してみよう。

忽略空气阻力的斜投影有一个著名的公式(真解),可以在高中物理教科书中找到。

正好,所以比较了大概的解和官方的轨迹。

题目虽然简单,但也恰到好处。惊人。

本文主要部分到此结束。

* 鼓励深入探索龙格-库塔方法的奖励

说完Runge-Kutta法算法是这样的,我在MATLAB中实现了。

在这里,作为奖励,我将编写一个指南,指导那些有兴趣深入挖掘龙格-库塔方法的人。

用图表直观理解

无论是 Euler 方法还是 Runge-Kutta 方法,您是否曾因直觉而不确定自己在做什么?

如果您是这样的人,请访问以下网站。

这里,用图来说明近似公式的含义。视觉上吸引人的图表仍然是直观理解的最佳选择。

盯着公式看,当你真的不明白的时候,你可以通过用图表来轻松理解它。

龙格-库塔近似的推导

Runge-Kutta 方法最大的奥秘在于近似公式。那是从哪里来的?

答案是泰勒展开式。通过考虑多变量函数的泰勒展开,我们可以推导出这个近似值。

另外,虽然我一开始就写了四阶龙格-库塔法,但四阶的原因在于这个泰勒展开式,据说它是四阶龙格-库塔法,因为它甚至考虑了四阶导数项。这是。

以下是 HP 的摘要,可能会有所帮助。

概括

这一次,我们实现了 Runge-Kutta 方法,它是 Euler 方法的改进版本。

Runge-Kutta 方法非常有名,即使你自己不去实现它,知道它是知识也不会有损失。

在最后

手动求解常微分方程的方法之一是将解视为泰勒级数。

事实上,众所周知,任何单变量函数都可以用泰勒级数来表示。由于解是一个函数,我们通过认为应该将其表示为泰勒级数来求解常微分方程。

从某种意义上说,Taylor展开式可能不可避免地涉及到Runge-Kutta方法等数值计算算法。

如果您也可以阅读下一篇文章,我将非常高兴。

*如果您对本文的改进或更正有任何建议,或者您想了解类似的内容,请告诉我们。

参考网站

[1] Rai Burari,使用数值计算求解常微分方程-龙格-库塔法解释-,2020/01/19出版,2020/03/06更新,2022/10/7查看

[2] MONOist,Let's solve Differential equations using Euler and Runge-Kutta methods,2015/1/28出版,2022/10/4查看


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308628558.html

相关文章: