private void calculate(double lower, double upper) { if (rb_Math.Checked == true) { DrawCurve math1 = new DrawCurve(); MathematicaLink math2 = new MathematicaLink(); this.Cursor = Cursors.WaitCursor; HookUp(math1); int choice = lb_curvature.SelectedIndex; rangeV = range[choice]; txt_range.Text = rangeV.ToString(); math1.SolveAcurate(math2, kappa[choice], rangeV.ToString()); this.Cursor = Cursors.Arrow; } else if (rb_Euler.Checked == true) { DrawCurve rk4 = new DrawCurve(); this.Cursor = Cursors.WaitCursor; HookUp(rk4); int choice = lb_curvature.SelectedIndex + 1; rk4.SolveFast(rk4, choice, lower, upper); this.Cursor = Cursors.Arrow; } }
//Hookup public void HookUp(DrawCurve data) { currentData = data; chr_2Dcurve.DataSource = currentData.Bsdata; chr_2Dcurve.Series[0].XValueMember = "X"; chr_2Dcurve.Series[0].YValueMembers = "Y"; currentData.Bsdata.ListChanged += new ListChangedEventHandler(Bsdata_ListChanged); }
public void SolveFast(DrawCurve instance, int choice, double lower, double upper) { List <Vector>[] out1; List <Vector> out2 = new List <Vector>(); solution.Clear(); bsdata.DataSource = null; List <Vector>[] test = this.RK4(new double[] { 0, 1, 0 }, lower, upper, 10000, choice); List <Vector>[] test2 = this.RK4(new double[] { 0, 0, 0.1 }, lower, upper, 10000, choice); //List<Vector>[] test = this.RKF(new double[] { 0, 1, 0 }, lower, upper, 10000, choice); //List<Vector>[] test2 = this.RKF(new double[] { 0, 0, 0.1 }, lower, upper, 10000, choice); for (int i = 0; i < test[0].Count; i++) { out2.Add(new Vector(test[0][i].Y, test2[0][i].Y, 0)); solution.Add(new Vector(Math.Round(test[0][i].Y, 5), Math.Round(test2[0][i].Y, 5), 0)); } out1 = new List <Vector>[] { out2 }; OutputToFile(out1, "testOut", new double[] { 0, 6 }, 10); bsdata.DataSource = solution; }
/// <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 }); }
/// <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 }); }