Second order Runge Kutta Heun

by Trent Guidry 7. October 2009 07:11
In this article I develop a second order Runge Kutta Heun class.
The update formula for the Runge Kutta Heun algorithm is shown below.
Runge Kutta Heun
This algorithm is implemented in the second order Runge Kutta Heun class, which is given at the bottom of this post.
As an example of using this class, I will use the following equations.
x1’ = x1 – 2x2
x2’ = 2x1 + x2
Where x1(0) = 0, x2(0) = 4
These equations have an analytical solution given below.
x1 = -4etsin(2t)
x2 = 4etcos(2t)
To solve these equations using the second order Runge Kutta Heun class, with a step size of 0.1 from 0.0 to 3.3, the code below is used.
            Parameter T = new Parameter(0.0);
            Parameter X1 = new Parameter(0.0);
            Parameter X2 = new Parameter(4.0);
            Parameter[] parameters = new Parameter[] { X1, X2 };
            Func<double>[] functions = new Func<double>[]
            {
                () => X1 - 2.0 * X2,
                () => 2.0 * X1 + X2
            };
 
            RungeKuttaBase ode = new RungeKutta2Heun();
            double[][] dRes = ode.Integrate(parameters, T, functions, 3.3, 0.1);
A graph of these results is given below.
Runge Kutta 2 Heun
As can be seen, the second order Runge Kutta Heun class gives much more accurate results than the Euler class with a step size of 0.1.
The code for the second order Runge Kutta Heun class is given below.  The code for the Runge Kutta Base class was posted previously.
public class RungeKutta2Heun : RungeKuttaBase
    {
        public RungeKutta2Heun()
            : base()
        {
        }
 
        public override double[][] Integrate(Parameter[] rungeKuttaParameters, Parameter x, Func<double>[] rungeKuttaFunctions, double xEnd, double step)
        {
            Debug.Assert(rungeKuttaParameters.Length == rungeKuttaFunctions.Length);
            double xStart = x;
            double stepSize = (xEnd - xStart) / step;
            int integerStepSize = (int)stepSize;
            if (stepSize > (double)integerStepSize) { integerStepSize++; }
            integerStepSize++;
            Collection<double[]> returnCollection = new Collection<double[]>();
            double[] row = new double[rungeKuttaParameters.Length + 1];
            row[0] = x;
            for (int i = 0; i < rungeKuttaParameters.Length; i++)
            {
                row[i + 1] = rungeKuttaParameters[i];
            }
            returnCollection.Add(row);
 
            double currentX = xStart;
            double[,] ks = new double[2, rungeKuttaParameters.Length];
            double x0 = xStart;
            double[] y0 = new double[rungeKuttaParameters.Length];
            double currentStep = step;
            while (currentX < xEnd)
            {
                if (currentX + currentStep > xEnd) { currentStep = xEnd - currentX; }
                x0 = currentX;
                for (int i = 0; i < rungeKuttaParameters.Length; i++)
                {
                    y0[i] = rungeKuttaParameters[i];
                }
 
                //k0s
                x.Value = x0;
                for (int i = 0; i < rungeKuttaParameters.Length; i++)
                {
                    ks[0, i] = rungeKuttaFunctions[i]();
                }
 
                //k1s
                x.Value = x0 + currentStep;
                for (int i = 0; i < rungeKuttaParameters.Length; i++)
                {
                    rungeKuttaParameters[i].Value = y0[i] + ks[0, i] * currentStep;
                }
                for (int i = 0; i < rungeKuttaParameters.Length; i++)
                {
                    ks[1, i] = rungeKuttaFunctions[i]();
                }
 
                //Final
                currentX += currentStep;
                row = new double[rungeKuttaParameters.Length + 1];
                row[0] = currentX;
                for (int i = 0; i < rungeKuttaParameters.Length; i++)
                {
                    rungeKuttaParameters[i].Value = y0[i] + (ks[0, i] / 2.0 + ks[1, i] / 2.0) * currentStep;
                    row[i + 1] = rungeKuttaParameters[i];
                }
                returnCollection.Add(row);
            }
            return returnCollection.ToArray();
        }
    }
 

Add comment




  Country flag
biuquote
  • Comment
  • Preview
Loading