Exemple #1
0
        /// <summary>
        /// A method for computing a solution to a third order IVP ODE using RK4
        /// </summary>
        /// <param name="f1">The first function to be solved</param>
        /// <param name="f2">The second function to be solved</param>
        /// <param name="f3">The third function to be solved</param>
        /// <param name="y0">The initial values for the system</param>
        /// <param name="a">The lower bound to the range</param>
        /// <param name="b">The upper bound to the range</param>
        /// <param name="NumSteps">The number of steps to take in the range</param>
        /// <returns>A list of points calculated by the function</returns>
        public List <Vector>[] RK4(double[] y0, double a, double b, int NumSteps, int choice)
        {
            List <Vector> odesol1 = new List <Vector>();

            double h  = (Math.Max(a, b) - Math.Min(a, b)) / (NumSteps - 1.0);
            double xt = a;

            double[] yNew  = y0, yOld = new double[yNew.Length];
            int      i     = 0;
            double   deriv = 0;


            Function udash  = x => x[2];
            Function u2dash = x => x[3];
            Function u3dash = x => x[0];
            Function kappa1 = x => (1.0 / 3.0) + Math.Sin(x[0]);
            Function kappa2 = x => (1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0);
            Function kappa3 = x => (1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0);
            Function kappa4 = x => (1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0);
            Function kappa5 = x => (1.0 / 10.0) + Math.Sin(x[0]);
            Function kappa6 = x => 1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3);
            Function kappa7 = x => 1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4);

            while (i < NumSteps)
            {
                switch (choice)
                {
                case (1):
                    deriv  = DrawCurve.RichardsonWithError(kappa1, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 3.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 3.0) + Math.Sin(x[0])) * ((1.0 / 3.0) + Math.Sin(x[0])) * x[2]);
                    break;

                case (2):
                    deriv  = DrawCurve.RichardsonWithError(kappa2, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0))) * x[3] - (((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0)) * ((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0)) * x[2]);;
                    break;

                case (3):
                    deriv  = DrawCurve.RichardsonWithError(kappa3, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0))) * x[3] - (((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0)) * ((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0)) * x[2]);
                    break;

                case (4):
                    deriv  = DrawCurve.RichardsonWithError(kappa4, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0))) * x[3] - (((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0)) * ((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0)) * x[2]);
                    break;

                case (5):
                    deriv  = DrawCurve.RichardsonWithError(kappa5, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 10.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 10.0) + Math.Sin(x[0])) * ((1.0 / 10.0) + Math.Sin(x[0])) * x[2]);
                    break;

                case (6):
                    deriv  = DrawCurve.RichardsonWithError(kappa6, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3))) * x[3] - ((1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3)) * (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3)) * x[2]);
                    break;

                case (7):
                    deriv  = DrawCurve.RichardsonWithError(kappa7, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4))) * x[3] - ((1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4)) * (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4)) * x[2]);
                    break;

                default:
                    deriv  = DrawCurve.RichardsonWithError(kappa1, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 3.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 3.0) + Math.Sin(x[0])) * ((1.0 / 3.0) + Math.Sin(x[0])) * x[2]);
                    break;
                }
                odesol1.Add(new Vector(xt, yNew[0], 0));
                for (int j = 0; j < yNew.Length; j++)
                {
                    yOld[j] = yNew[j];
                }
                yNew = RK4Step(udash, u2dash, u3dash, xt, h, yOld);
                xt   = xt + h;
                i++;
            }
            return(new List <Vector>[] { odesol1 });
        }
Exemple #2
0
        /// <summary>
        /// A method for computing a solution to a third order IVP ODE using RKF
        /// </summary>
        /// <param name="f1">The first function to be solved</param>
        /// <param name="f2">The second function to be solved</param>
        /// <param name="f3">The third function to be solved</param>
        /// <param name="y0">The initial values for the system</param>
        /// <param name="a">The lower bound to the range</param>
        /// <param name="b">The upper bound to the range</param>
        /// <param name="NumSteps">The number of steps to take in the range</param>
        /// <returns>A list of points calculated by the function</returns>
        public List <Vector>[] RKF(double[] y0, double a, double b, int NumSteps, int choice)
        {
            List <Vector> odesol1 = new List <Vector>();
            double        h = (Math.Max(a, b) - Math.Min(a, b)) / (NumSteps - 1.0);
            double        xt = a, x0 = 0;

            double[]        yNew       = y0, yOld = new double[yNew.Length];
            int             i          = 0;
            double          deriv      = 0;
            List <double[]> resultStep = new List <double[]>();
            //double tolerance = 1E-9;
            double err = 0, tol = 1E-4, /*maxErr = 0, delta = 0,*/ s = 0;

            double hmin = 1E-9;
            double hmax = 5;

            Function udash  = x => x[2];
            Function u2dash = x => x[3];
            Function u3dash = x => x[0];
            Function kappa1 = x => (1.0 / 3.0) + Math.Sin(x[0]);
            Function kappa2 = x => (1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0);
            Function kappa3 = x => (1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0);
            Function kappa4 = x => (1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0);
            Function kappa5 = x => (1.0 / 10.0) + Math.Sin(x[0]);
            Function kappa6 = x => 1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3);
            Function kappa7 = x => 1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4);

            while (i < NumSteps)
            {
                /*if (i >= NumSteps)
                 * {
                 *  break;
                 * }*/

                switch (choice)
                {
                case (1):
                    deriv  = DrawCurve.RichardsonWithError(kappa1, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 3.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 3.0) + Math.Sin(x[0])) * ((1.0 / 3.0) + Math.Sin(x[0])) * x[2]);
                    break;

                case (2):
                    deriv  = DrawCurve.RichardsonWithError(kappa2, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0))) * x[3] - (((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0)) * ((1.0 / 5.0) + 2 * Math.Sin(x[0]) + 3 * Math.Cos(x[0] / 3.0)) * x[2]);;
                    break;

                case (3):
                    deriv  = DrawCurve.RichardsonWithError(kappa3, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0))) * x[3] - (((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0)) * ((1.0 / 5.0) + Math.Sin(x[0] / 2.0) - Math.Cos(x[0] / 3.0)) * x[2]);
                    break;

                case (4):
                    deriv  = DrawCurve.RichardsonWithError(kappa4, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0))) * x[3] - (((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0)) * ((1.0 / 5.0) + Math.Sin(x[0] / 3.0) + 2 * Math.Cos(x[0] / 2.0)) * x[2]);
                    break;

                case (5):
                    deriv  = DrawCurve.RichardsonWithError(kappa5, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 10.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 10.0) + Math.Sin(x[0])) * ((1.0 / 10.0) + Math.Sin(x[0])) * x[2]);
                    break;

                case (6):
                    deriv  = DrawCurve.RichardsonWithError(kappa6, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3))) * x[3] - ((1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3)) * (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (3)) * x[2]);
                    break;

                case (7):
                    deriv  = DrawCurve.RichardsonWithError(kappa7, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4))) * x[3] - ((1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4)) * (1 + (3.0 / (5 + 4 * Math.Cos(x[0]))) * (4)) * x[2]);
                    break;

                default:
                    deriv  = DrawCurve.RichardsonWithError(kappa5, xt, 1E-6, 10000, 1E-9);
                    u3dash = x => (deriv / ((1.0 / 10.0) + Math.Sin(x[0]))) * x[3] - (((1.0 / 10.0) + Math.Sin(x[0])) * ((1.0 / 10.0) + Math.Sin(x[0])) * x[2]);
                    break;
                }
                odesol1.Add(new Vector(xt, yNew[0], 0));
                for (int j = 0; j < yNew.Length; j++)
                {
                    yOld[j] = yNew[j];
                }
                resultStep = RKFStep(udash, u2dash, u3dash, xt, h, yOld);

                /*for (int j = 0; j < 3; j++)
                 * {
                 *  err = Math.Max(err, resultStep[2][j]);
                 * }*/
                err = resultStep[2][0];
                s   = Math.Pow(0.5 * tol / err, 0.25);

                if (err < tol)
                {
                    yNew = resultStep[0];
                    xt   = x0 + h;
                    x0   = xt;
                }
                if (s < 0.1)
                {
                    s = 0.1;
                }
                else if (s > 4.0)
                {
                    s = 4.0;
                }
                h *= s;
                if (h > b - x0)
                {
                    h = b - x0;
                }
                if (h > hmax)
                {
                    h = hmax;
                }
                else if (h < hmin)
                {
                    h = hmin;
                }
                i++;
                err = 0;
            }
            deriv = 0;
            return(new List <Vector>[] { odesol1 });
        }