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]); }
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 }); }
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); }
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 })); } }