示例#1
0
        public void OdeLRC()
        {
            double L = 1.0;
            double R = 1.0;
            double C = 1.0;

            Func <double, IList <double>, IList <double> > rhs = (double x, IList <double> y) => {
                double q = y[0]; double qp = y[1];
                return(new double[] {
                    qp,
                    (0.0 - q / C - R * qp) / L
                });
            };

            double q0  = 1.0;
            double qp0 = 0.0;

            double t0 = 2.0 * L / R;
            double w0 = Math.Sqrt(1.0 / (L * C) - 1.0 / (t0 * t0));

            double t  = 1.0;
            double sc = (q0 * Math.Cos(w0 * t) + (qp0 + q0 / t0) / w0 * Math.Sin(w0 * t)) * Math.Exp(-t / t0);

            Console.WriteLine(sc);

            IList <double> s = MultiFunctionMath.SolveOde(rhs, 0.0, new double[] { q0, qp0 }, t).Y;

            Console.WriteLine(s[0]);
        }
示例#2
0
        public void OdeLorenz()
        {
            double sigma = 10.0;
            double beta  = 8.0 / 3.0;
            double rho   = 28.0;

            Func <double, IList <double>, IList <double> > rhs = (double t, IList <double> u) => new ColumnVector(
                sigma * (u[1] - u[0]),
                u[0] * (rho - u[2]) - u[1],
                u[0] * u[1] - beta * u[2]
                );

            ColumnVector u0 = new ColumnVector(1.0, 1.0, 1.0);

            MultiFunctionMath.SolveOde(rhs, 0.0, u0, 10.0, new EvaluationSettings()
            {
                RelativePrecision = 1.0E-8, EvaluationBudget = 100000
            });
        }
示例#3
0
        public void OdeEuler()
        {
            // Euler's equations for rigid body motion (without external forces) are
            //   I_1 \dot{\omega}_1  = (I_2 - I_3) \omega_2 \omega_3
            //   I_2 \dot{\omega}_2  = (I_3 - I_1) \omega_3 \omega_1
            //   I_3 \dot{\omega}_3  = (I_1 - I_2) \omega_1 \omega_2
            // where \omega's are rotations about the principal axes and I's are the moments
            // of inertia about those axes. The rotational kinetic energy
            //   I_1 \omega_1^2 + I_2 \omega_2^2 + I_3 \omega_3^2 = 2E
            // and angular momentum
            //   I_1^2 \omega_1^2 + I_2^2 \omega_2^2 + I_3^2 \omega_3^2 = M^2
            // are conserved quantities.

            ColumnVector I = new ColumnVector(1.0, 2.0, 3.0);

            Func <double, IList <double>, IList <double> > rhs = (double t, IList <double> w) => {
                return(new ColumnVector((I[1] - I[2]) * w[1] * w[2] / I[0], (I[2] - I[0]) * w[2] * w[0] / I[1], (I[0] - I[1]) * w[0] * w[1] / I[2]));
            };

            ColumnVector w0 = new ColumnVector(1.0, 1.0, 1.0);

            double             eps      = 1.0E-12;
            EvaluationSettings settings = new EvaluationSettings()
            {
                RelativePrecision = eps,
                AbsolutePrecision = eps * eps,
                EvaluationBudget  = 10000
            };

            settings.UpdateHandler = (EvaluationResult r) => {
                OdeResult <IList <double> > q = (OdeResult <IList <double> >)r;
                Console.WriteLine("{0} {1}", q.EvaluationCount, q.X);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(EulerKineticEnergy(I, q.Y), EulerKineticEnergy(I, w0), settings));
                Assert.IsTrue(TestUtilities.IsNearlyEqual(EulerAngularMomentum(I, q.Y), EulerAngularMomentum(I, w0), settings));
            };

            MultiFunctionMath.SolveOde(rhs, 0.0, w0, 10.0, settings);
        }
示例#4
0
        public void OdeOrbit2()
        {
            Func <double, IList <double>, IList <double> > rhs = (double t, IList <double> r) => {
                double d  = MoreMath.Hypot(r[0], r[2]);
                double d3 = MoreMath.Pow(d, 3);
                return(new ColumnVector(r[1], -r[0] / d3, r[3], -r[2] / d3));
            };

            //double e = 0.5;
            foreach (double e in TestUtilities.GenerateUniformRealValues(0.0, 1.0, 8))
            {
                Console.WriteLine(e);

                ColumnVector r0 = new ColumnVector(1.0 - e, 0.0, 0.0, Math.Sqrt((1.0 + e) / (1.0 - e)));

                ColumnVector r1 = new ColumnVector(MultiFunctionMath.SolveOde(rhs, 0.0, r0, 2.0 * Math.PI).Y);

                Assert.IsTrue(TestUtilities.IsNearlyEqual(r0, r1, new EvaluationSettings()
                {
                    RelativePrecision = 1.0E-9
                }));
            }
        }