Example #1
0
        public void Solve()
        {
            // Example taken from https://tutorial.math.lamar.edu/classes/de/BoundaryValueProblem.aspx
            // y'' + 4y = 0, 0 <= t <= pi/4, y(0) = -2, y(pi/4) = 10
            DoubleRange t     = new DoubleRange(0, Math.PI / 4, increment: 0.1);
            double      y0    = -2;
            double      ypi_4 = 10;

            //DoubleFunction3 yPP = new DoubleFunction3((t,y,yP) => (-4 * y));
            // y`` = 0*y` -4*y + 0
            var de = new SecondOrderDE <double>(new DoubleFunction((x) => 0), new DoubleFunction((x) => - 4), new DoubleFunction((x) => 0));

            var solver = new LinearShootingBvpSolver();

            var(approxy, _) = solver.SolveBoundary(de, t, y0, ypi_4); //discard approximation to y`
            var exact = new DoubleFunction((t) => - 2 * Math.Cos(2 * t) + 10 * Math.Sin(2 * t));

            SaveCsv("LinearShootingBVP", approxy, exact, t);
        }
        /// <summary>
        /// Solve the boundary value problem where y`` = f(t, y, y`), a <= t <= b, y(a) = y0, y(b) = y1
        /// </summary>
        /// <param name="de">function of three arguments (t,y,y`)</param>
        /// <param name="tRange">range (a,b) of values for t</param>
        /// <param name="y0">value of y at a</param>
        /// <param name="y1">value of y at b</param>
        /// <returns>approximation for the function y and y`</returns>
        public (IFunction <double> y, IFunction <double> dy) SolveBoundary(SecondOrderDE <double> de, Range <double> tRange, double y0, double y1)
        {
            // INPUTS: endpoints a and b for t, boundary conditions y0 and y1, number of subintervals N
            var a = tRange.Start; var b = tRange.End;
            var p = de.Px;
            var q = de.Qx;
            var r = de.Rx;

            // Step 1
            var h  = (b - a) / N;
            var u1 = new double[N + 1];
            var u2 = new double[N + 1];
            var v1 = new double[N + 1];
            var v2 = new double[N + 1];

            u1[0] = y0;
            u2[0] = 0d;
            v1[0] = 0d;
            v2[0] = 1d;

            var xs = new double[N + 1];
            var w1 = new double[N + 1];
            var w2 = new double[N + 1];

            // Step 2
            for (var i = 0; i <= N - 1; i++)
            {
                // Step 3
                var x = a + i * h;

                // Step 4
                // Solve for approximation to 'y'
                var k11 = h * u2[i];
                var k12 = h * (p[x] * u2[i] + q[x] * u1[i] + r[x]);
                var k21 = h * (u2[i] + 0.5 * k12);
                var k22 = h * (p[x + h / 2] * (u2[i] + 0.5 * k12) + q[x + h / 2] * (u1[i] + 0.5 * k11) + r[x + h / 2]);
                var k31 = h * (u2[i] + 0.5 * k22);
                var k32 = h * (p[x + h / 2] * (u2[i] + 0.5 * k22) + q[x + h / 2] * (u1[i] + 0.5 * k21) + r[x + h / 2]);
                var k41 = h * (u2[i] + k32);
                var k42 = h * (p[x + h] * (u2[i] + k32) + q[x + h] * (u1[i] + k31) + r[x + h]);

                u1[i + 1] = u1[i] + (1f / 6f) * (k11 + 2 * k21 + 2 * k31 + k41);
                u2[i + 1] = u2[i] + (1f / 6f) * (k12 + 2 * k22 + 2 * k32 + k42);

                // Solve for approximation to 'y`'
                var kp11 = h * v2[i];
                var kp12 = h * (p[x] * v2[i] + q[x] * v1[i] + r[x]);
                var kp21 = h * (v2[i] + 0.5 * kp12);
                var kp22 = h * (p[x + h / 2] * (v2[i] + 0.5 * kp12) + q[x + h / 2] * (v1[i] + 0.5 * kp11) + r[x + h / 2]);
                var kp31 = h * (v2[i] + 0.5 * kp22);
                var kp32 = h * (p[x + h / 2] * (v2[i] + 0.5 * kp22) + q[x + h / 2] * (v1[i] + 0.5 * kp21) + r[x + h / 2]);
                var kp41 = h * (v2[i] + kp32);
                var kp42 = h * (p[x + h] * (v2[i] + kp32) + q[x + h] * (v1[i] + kp31) + r[x + h]);

                v1[i + 1] = v1[i] + (1f / 6f) * (kp11 + 2 * kp21 + 2 * kp31 + kp41);
                v2[i + 1] = v2[i] + (1f / 6f) * (kp12 + 2 * kp22 + 2 * kp32 + kp42);
            }

            // Step 5
            w1[0] = y0;
            w2[0] = (y1 - u1[N]) / v1[N];
            xs[0] = a;

            // Step 6
            for (var i = 1; i <= N; i++)
            {
                w1[i] = u1[i] + w2[0] * v1[i];
                w2[i] = u2[i] + w2[0] * v2[i];
                xs[i] = a + i * h;
            }

            // Step 7
            return(new DoubleInterpolatedFunction(xs, w1), new DoubleInterpolatedFunction(xs, w2));
        }