📜  求解微分方程的 Runge-Kutta 二阶方法

📅  最后修改于: 2021-09-22 10:48:51             🧑  作者: Mango

给定以下输入:

  1. xy形式定义dy/dx值的常微分方程。
    \LARGE \frac{dy}{dx} = f(x, y)
  2. y 的初始值,即y(0)
    \LARGE y(0)= y_o

任务是在给定点 x 处找到未知函数y 的值,即y(x)
例子:

方法:
Runge-Kutta 方法为给定的 x 找到 y 的近似值。使用 Runge Kutta 二阶方法只能求解一阶常微分方程。
下面是用来从以前的值是计算下一个值y n + 1个公式。
所以:

yn+1 = value of y at (x = n + 1)
yn = value of y at (x = n)
where
  0 ≤ n ≤ (x - x0)/h
  h is step height
  xn+1 = x0 + h

计算 y(n+1) 值的基本公式:
\LARGE K_{1} = h*f(x_{n}, y_{n})
\LARGE K_{2} = h*f((x_{n} + \frac{h}{2}), (y_{n} + \frac{K_{1}*h}{2}))
\LARGE y_{n+1} = y_{n} + K_{2} + (h^{3})
该公式基本上使用当前y n加上两个增量的加权平均值来计算下一个值y n+1

  • K 1是基于区间开头斜率的增量,使用 y。
  • K 2是基于区间中点斜率的增量,使用(y + h*K 1 /2)

该方法是二阶方法,这意味着局部截断误差为 O(h 3 ) 阶,而总累积误差为 O(h 4 ) 阶。
下面是上述方法的实现:

C++
// C++ program to implement Runge
// Kutta method
#include 
using namespace std;
 
// A sample differential equation
// "dy/dx = (x - y)/2"
float dydx(float x, float y)
{
    return (x + y - 2);
}
 
// Finds value of y for a given x
// using step size h
// and initial value y0 at x0.
float rungeKutta(float x0, float y0,
                 float x, float h)
{
    // Count number of iterations
    // using step size or
    // step height h
    int n = (int)((x - x0) / h);
 
    float k1, k2;
 
    // Iterate for number of iterations
    float y = y0;
    for (int i = 1; i <= n; i++) {
        // Apply Runge Kutta Formulas
        // to find next value of y
        k1 = h * dydx(x0, y);
        k2 = h * dydx(x0 + 0.5 * h,
                      y + 0.5 * k1);
 
        // Update next value of y
        y = y + (1.0 / 6.0) * (k1 + 2 * k2);
 
        // Update next value of x
        x0 = x0 + h;
    }
 
    return y;
}
 
// Driver Code
int main()
{
    float x0 = 0, y = 1,
          x = 2, h = 0.2;
 
    cout << fixed << setprecision(6) << "y(x) = " << rungeKutta(x0, y, x, h);
    return 0;
}
 
// This code is contributed by shivani


C
// C program to implement Runge
// Kutta method
 
#include 
 
// A sample differential equation
// "dy/dx = (x - y)/2"
float dydx(float x, float y)
{
    return (x + y - 2);
}
 
// Finds value of y for a given x
// using step size h
// and initial value y0 at x0.
float rungeKutta(float x0, float y0,
                 float x, float h)
{
    // Count number of iterations
    // using step size or
    // step height h
    int n = (int)((x - x0) / h);
 
    float k1, k2;
 
    // Iterate for number of iterations
    float y = y0;
    for (int i = 1; i <= n; i++) {
        // Apply Runge Kutta Formulas
        // to find next value of y
        k1 = h * dydx(x0, y);
        k2 = h * dydx(x0 + 0.5 * h,
                      y + 0.5 * k1);
 
        // Update next value of y
        y = y + (1.0 / 6.0) * (k1 + 2 * k2);
 
        // Update next value of x
        x0 = x0 + h;
    }
 
    return y;
}
 
// Driver Code
int main()
{
    float x0 = 0, y = 1,
          x = 2, h = 0.2;
 
    printf("y(x) = %f",
           rungeKutta(x0, y, x, h));
    return 0;
}


Java
// Java program to implement Runge
// Kutta method
class GFG {
     
    // A sample differential equation
    // "dy/dx = (x - y)/2"
    static double dydx(double x, double y)
    {
        return (x + y - 2);
    }
     
    // Finds value of y for a given x
    // using step size h
    // and initial value y0 at x0.
    static double rungeKutta(double x0, double y0,
                     double x, double h)
    {
        // Count number of iterations
        // using step size or
        // step height h
        int n = (int)((x - x0) / h);
     
        double k1, k2;
     
        // Iterate for number of iterations
        double y = y0;
        for (int i = 1; i <= n; i++) {
            // Apply Runge Kutta Formulas
            // to find next value of y
            k1 = h * dydx(x0, y);
            k2 = h * dydx(x0 + 0.5 * h,
                          y + 0.5 * k1);
     
            // Update next value of y
            y = y + (1.0 / 6.0) * (k1 + 2 * k2);
     
            // Update next value of x
            x0 = x0 + h;
        }
     
        return y;
    }
     
    // Driver Code
    public static void main (String[] args)
    {
        double x0 = 0, y = 1,
              x = 2, h = 0.2;
     
        System.out.println(rungeKutta(x0, y, x, h));
    }
}
 
// This code is contributed by Yash_R


Python3
# Python3 program to implement Runge
# Kutta method
 
# A sample differential equation
# "dy/dx = (x - y)/2"
def dydx(x, y) :
 
    return (x + y - 2);
 
# Finds value of y for a given x
# using step size h
# and initial value y0 at x0.
def rungeKutta(x0, y0, x, h) :
 
    # Count number of iterations
    # using step size or
    # step height h
    n = round((x - x0) / h);
     
        # Iterate for number of iterations
    y = y0;
     
    for i in range(1, n + 1) :
         
                # Apply Runge Kutta Formulas
        # to find next value of y
        k1 = h * dydx(x0, y);
        k2 = h * dydx(x0 + 0.5 * h, y + 0.5 * k1);
 
        # Update next value of y
        y = y + (1.0 / 6.0) * (k1 + 2 * k2);
 
        # Update next value of x
        x0 = x0 + h;
 
    return y;
 
# Driver Code
if __name__ == "__main__" :
 
    x0 = 0; y = 1;
    x = 2; h = 0.2;
 
    print("y(x) =",rungeKutta(x0, y, x, h));
 
# This code is contributed by Yash_R


C#
// C# program to implement Runge
// Kutta method
using System;
 
class GFG {
     
    // A sample differential equation
    // "dy/dx = (x - y)/2"
    static double dydx(double x, double y)
    {
        return (x + y - 2);
    }
     
    // Finds value of y for a given x
    // using step size h
    // and initial value y0 at x0.
    static double rungeKutta(double x0, double y0,
                     double x, double h)
    {
        // Count number of iterations
        // using step size or
        // step height h
        int n = (int)((x - x0) / h);
     
        double k1, k2;
     
        // Iterate for number of iterations
        double y = y0;
        for (int i = 1; i <= n; i++) {
            // Apply Runge Kutta Formulas
            // to find next value of y
            k1 = h * dydx(x0, y);
            k2 = h * dydx(x0 + 0.5 * h,
                          y + 0.5 * k1);
     
            // Update next value of y
            y = y + (1.0 / 6.0) * (k1 + 2 * k2);
     
            // Update next value of x
            x0 = x0 + h;
        }
     
        return y;
    }
     
    // Driver Code
    public static void Main (string[] args)
    {
        double x0 = 0, y = 1,
              x = 2, h = 0.2;
     
        Console.WriteLine(rungeKutta(x0, y, x, h));
    }
}
 
// This code is contributed by Yash_R


Javascript


输出:
y(x) = 0.645590

参考: https : //en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods