public void OdeSine() { // The sine and cosine functions satisfy // y'' = - y // This is perhaps the simplest conservative differential equation. // (i.e. right hand side depends only on y, not y') Func <double, double, double> f = (double x, double y) => - y; int count = 0; OdeSettings settings = new OdeSettings() { Listener = (OdeResult r) => { Assert.IsTrue(TestUtilities.IsNearlyEqual( MoreMath.Sqr(r.Y) + MoreMath.Sqr(r.YPrime), 1.0, r.Settings )); Assert.IsTrue(TestUtilities.IsNearlyEqual( r.Y, MoreMath.Sin(r.X), r.Settings )); count++; } }; OdeResult result = FunctionMath.IntegrateConservativeOde(f, 0.0, 0.0, 1.0, 5.0, settings); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Y, MoreMath.Sin(5.0))); Assert.IsTrue(count > 0); }
public static void IntegrateOde() { Func <double, double, double> rhs = (x, y) => - x * y; OdeResult sln = FunctionMath.IntegrateOde(rhs, 0.0, 1.0, 2.0); Console.WriteLine($"Numeric solution y({sln.X}) = {sln.Y}."); Console.WriteLine($"Required {sln.EvaluationCount} evaluations."); Console.WriteLine($"Analytic solution y({sln.X}) = {Math.Exp(-MoreMath.Sqr(sln.X) / 2.0)}"); // Lotka-Volterra equations double A = 0.1; double B = 0.02; double C = 0.4; double D = 0.02; Func <double, IReadOnlyList <double>, IReadOnlyList <double> > lkRhs = (t, y) => { return(new double[] { A *y[0] - B * y[0] * y[1], D *y[0] * y[1] - C * y[1] }); }; MultiOdeSettings lkSettings = new MultiOdeSettings() { Listener = r => { Console.WriteLine($"t={r.X} rabbits={r.Y[0]}, foxes={r.Y[1]}"); } }; MultiFunctionMath.IntegrateOde(lkRhs, 0.0, new double[] { 20.0, 10.0 }, 50.0, lkSettings); Func <double, IReadOnlyList <double>, IReadOnlyList <double> > rhs1 = (x, u) => { return(new double[] { u[1], -u[0] }); }; MultiOdeSettings settings1 = new MultiOdeSettings() { EvaluationBudget = 100000 }; MultiOdeResult result1 = MultiFunctionMath.IntegrateOde( rhs1, 0.0, new double[] { 0.0, 1.0 }, 500.0, settings1 ); double s1 = MoreMath.Sqr(result1.Y[0]) + MoreMath.Sqr(result1.Y[1]); Console.WriteLine($"y({result1.X}) = {result1.Y[0]}, (y)^2 + (y')^2 = {s1}"); Console.WriteLine($"Required {result1.EvaluationCount} evaluations."); Func <double, double, double> rhs2 = (x, y) => - y; OdeSettings settings2 = new OdeSettings() { EvaluationBudget = 100000 }; OdeResult result2 = FunctionMath.IntegrateConservativeOde( rhs2, 0.0, 0.0, 1.0, 500.0, settings2 ); double s2 = MoreMath.Sqr(result2.Y) + MoreMath.Sqr(result2.YPrime); Console.WriteLine($"y({result2.X}) = {result2.Y}, (y)^2 + (y')^2 = {s2}"); Console.WriteLine($"Required {result2.EvaluationCount} evaluations"); Console.WriteLine(MoreMath.Sin(500.0)); }
public void OdeNonlinear() { // y = \frac{y_0}{1 - y_0 (x - x_0)} Func <double, double, double> f = (double x, double y) => MoreMath.Sqr(y); int count = 0; OdeSettings settings = new OdeSettings() { RelativePrecision = 1.0E-8, EvaluationBudget = 1024, Listener = (OdeResult) => count++ }; OdeResult result = FunctionMath.IntegrateOde(f, 0.0, 1.0, 0.99, settings); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Y, 1.0 / (1.0 - 1.0 * (0.99 - 0.0)), result.Settings)); Assert.IsTrue(count > 0); Console.WriteLine(result.EvaluationCount); }