Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runge-Kutta algorithm C++

Below is my 4th order Runge-Kutta algorithm to solve a first order ODE. I am checking it against the wikipedia example found here to solve:

\frac{dx}{dt} = tan(x) + 1

Unfortunately it is out by a little bit. I have toyed around for a long while, but I can't find the error. The answer should be t = 1.1 and x = 1.33786352224364362. The below code gives t = 1.1 and x = 1.42223.

/*

This code is a 1D classical Runge-Kutta method. Compare to the Wikipedia page.

*/

#include <math.h> 
#include <iostream>
#include <iomanip>

double x,t,K,K1,K2,K3,K4;

const double sixth = 1.0 / 6.0;

static double dx_dt(double t, double x){
    return tan(x) + 1;
}

int main(int argc, const char * argv[]) {

/*======================================================================*/
/*===================== Runge-Kutta Method for ODE =====================*/
/*======================================================================*/

double t_initial = 1.0;// initial time
double x_initial = 1.0;// initial x position

double t_final = 1.1;// value of t wish to know x 
double dt = 0.025;// time interval for updates
double halfdt = 0.5*dt;

/*======================================================================*/

while(t_initial < t_final){

    /*============================ Runge-Kutta increments =================================*/ 

    double K1 = dt*dx_dt( t_initial, x_initial );
    double K2 = dt*dx_dt( t_initial + halfdt, x_initial + halfdt*K1 );
    double K3 = dt*dx_dt( t_initial + halfdt, x_initial + halfdt*K2 );
    double K4 = dt*dx_dt( t_initial + dt, x_initial + dt*K3 );

    x_initial += sixth*(K1 + 2*(K2 + K3) + K4);

    /*============================ prints =================================*/

    std::cout << t_initial << std::setw(16) << x_initial << "\n";

    /*============================ re-setting update conditions =================================*/

    t_initial += dt;

    /*======================================================================*/
}

std::cout<<"----------------------------------------------\n";
std::cout << "t =  "<< t_initial << ",  x =  "<< x_initial << std::endl; 


}/* main */
like image 286
PeterSM Avatar asked Mar 17 '17 11:03

PeterSM


People also ask

What is the Runge-Kutta formula?

Runge-Kutta Fourth Order Method Formula The formula for the fourth-order Runge-Kutta method is given by: y1 = y0 + (⅙) (k1 + 2k2 + 2k3 + k4) Here, k1 = hf(x0, y0) k2 = hf[x0 + (½)h, y0 + (½)k1]

What is Runge-Kutta method with example?

Example 3.3. y=e−2x4(x4+4). The results obtained by the Runge-Kutta method are clearly better than those obtained by the improved Euler method in fact; the results obtained by the Runge-Kutta method with h=0.1 are better than those obtained by the improved Euler method with h=0.05.

What is the Runge-Kutta 4th order formula?

The most commonly used method is Runge-Kutta fourth order method. x(1) = 1, using the Runge-Kutta second order and fourth order with step size of h = 1. yi+1 = yi + h 2 (k1 + k2), where k1 = f(xi,ti), k2 = f(xi + h, ti + hk1).

Which is better RK2 or RK4?

The most popular RK method is RK4 since it offers a good balance between order of accuracy and cost of computation. RK4 is the highest order explicit Runge-Kutta method that requires the same number of steps as the order of accuracy (i.e. RK1=1 stage, RK2=2 stages, RK3=3 stages, RK4=4 stages, RK5=6 stages, ...).


1 Answers

The problem is that the tableau used for your code is different than the one for the code you cited in wikipedia. The one you're using is this:

0   |
1/2 |   1/2
1/2 |   0       1/2
1   |   0       0       1   
-------------------------------------
    |   1/6     1/3     1/3     1/6

And the one used in wikipedia is

0   |
2/3 |   2/3     
---------------------
    |   1/4     3/4

Different tableaus will yield different results depending on the step-size, which is the way used to make sure that the step-size is good enough for a certain accuracy. However, when dt -> 0, then all tableaus are the same.

Besides all this, your code is wrong anyway even for RK4. The second part of the function should have halves, not 0.5*dt:

double K1 = dt*dx_dt( t_initial, x_initial );
double K2 = dt*dx_dt( t_initial + halfdt, x_initial + 0.5*K1 );
double K3 = dt*dx_dt( t_initial + halfdt, x_initial + 0.5*K2 );
double K4 = dt*dx_dt( t_initial + dt, x_initial + K3 );
like image 162
The Quantum Physicist Avatar answered Sep 24 '22 00:09

The Quantum Physicist