public Vector <double>[] bvpsolver_zzz(Func <double, Vector <double>, Vector <double> > system, double ya, double yb, double xa, double xb, int N) { Vector <double>[] res; Vector <double> y0; double s_guess = (yb - ya) / (xb - xa), s_guess_pre = 0; double fais = yb, fais_pre = 0, dfaids = 0; do { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, s_guess }); // observer_pr ob_pr = this->write_targetFunc_end; res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais_pre = fais; fais = res[N - 1][0] - yb; dfaids = (fais - fais_pre) / (s_guess - s_guess_pre); s_guess_pre = s_guess; s_guess = s_guess - fais / dfaids; //count++; } while (fais > 0.001 * yb + 1e-6 || fais < -0.001 * yb - 1e-6); return(res); }
static void Main(string[] args) { int N = 1000000; Vector <double> y0 = Vector <double> .Build.Dense(new[] { -7.0 / 4.0, 55.0 / 8.0 }); Func <double, Vector <double>, Vector <double> > der = DerivativeMaker(); Vector <double>[] res = RungeKutta.FourthOrder(y0, 0, 10, N, der); double[] x = new double[N]; double[] y = new double[N]; for (int i = 0; i < N; i++) { double[] temp = res[i].ToArray(); x[i] = temp[0]; y[i] = temp[1]; } //Test Console.WriteLine(y[N / 10]); // gives 164,537981852489 Console.WriteLine(Math.Exp(-1) + 3 * Math.Exp(4) - 5.0 / 2 + 23.0 / 8); //gives 164,537329540604, which is y(1) Console.ReadKey(); }
static Vector <double>[] function_RungeKutta(double P, double R, double p, double c, double a, double k, double t_first, double t_end, int N) { Vector <double> variables = Vector <double> .Build.Dense(new[] { P, R }); Func <double, Vector <double>, Vector <double> > der = DerivativeMaker(p, c, a, k); Vector <double>[] res = RungeKutta.FourthOrder(variables, t_first, t_end, N, der); return(res); }
public double[,] SolveRK4(Vector <double> x0, double start, double end, int n, Func <double, Vector <double>, Vector <double> > func) { var answer = new double[n, 2]; var res = RungeKutta.FourthOrder(x0, start, end, n, func); for (var i = 0; i < n; i++) { var temp = res[i].ToArray(); answer[i, 0] = temp[0]; answer[i, 1] = temp[1]; } return(answer); }
public List <double[]> SolveODE(double[] y0, double startTime, double endTime, int n, Func <double, double[], double[]> func) { var y0Vector = Vector <double> .Build.DenseOfArray(y0); var result = RungeKutta.FourthOrder(y0Vector, startTime, endTime, n, (t, y) => { var res = func(t, y.AsArray()); return(Vector <double> .Build.DenseOfArray(res)); }); var resultList = new List <double[]>(); for (var i = 0; i < n; i++) { var vector = result[i]; resultList.Add(vector.AsArray()); } return(resultList); }
public void RK4Test() { Func <double, double, double> ode = (t, y) => t + 2 * y * t; Func <double, double> sol = (t) => 0.5 * (Math.Exp(t * t) - 1); double ratio = double.NaN; double error = 0; double oldError = 0; for (int k = 0; k < 4; k++) { double y0 = 0; double[] y_t = RungeKutta.FourthOrder(y0, 0, 2, Convert.ToInt32(Math.Pow(2, k + 6)), ode); error = Math.Abs(sol(2) - y_t.Last()); if (oldError != 0) { ratio = Math.Log(oldError / error, 2); } oldError = error; Console.WriteLine(string.Format("{0}, {1}", error, ratio)); } Assert.AreEqual(4, ratio, 0.01);// Check error convergence order }
static void Main(string[] args) { int N = 10000; Vector <double> y0 = Vector <double> .Build.Dense(new[] { -7.0 / 4.0, 55.0 / 8.0 }); //Func<double, Vector<double>, Vector<double>> der = DerivativeMaker(); Vector <double>[] res = RungeKutta.FourthOrder(y0, 0, 10, N, DerivativeMaker_zzz2); double[] t = Vector <double> .Build.Dense(N, i => i * 10.0 / N).ToArray(); double[] x = new double[N]; double[] y = new double[N]; for (int i = 0; i < N; i++) { double[] temp = res[i].ToArray(); x[i] = temp[0]; y[i] = temp[1]; //Console.WriteLine(t[i]); } var plt = new ScottPlot.Plot(800, 600); plt.PlotScatter(t, x, label: "x", markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); plt.PlotScatter(t, y, label: "y", markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); plt.Grid(false); plt.Legend(fontSize: 10); //plt.PlotSignal(new[,] { x, y }); plt.SaveFig("quickstart.png"); //Test Console.WriteLine(y[N / 10]); // gives 164,537981852489 Console.WriteLine(Math.Exp(-1) + 3 * Math.Exp(4) - 5.0 / 2 + 23.0 / 8); //gives 164,537329540604, which is y(1) Console.ReadKey(); }
private void button_calc_Click_3(object sender, EventArgs e) { DataTable dt = (DataTable)dataGridView1.DataSource; bendStiffener.max_k = (double)dt.Rows[0][1]; bendStiffener.D1 = (double)dt.Rows[1][1]; bendStiffener.d1 = (double)dt.Rows[2][1]; bendStiffener.d2 = (double)dt.Rows[3][1]; bendStiffener.L1 = (double)dt.Rows[4][1]; bendStiffener.L2 = (double)dt.Rows[5][1]; bendStiffener.L3 = (double)dt.Rows[6][1]; bendStiffener.EIp = (double)dt.Rows[7][1]; bendStiffener.Es = (double)dt.Rows[8][1]; bendStiffener.F = (double)dt.Rows[9][1]; bendStiffener.q = (double)dt.Rows[10][1]; int N = 10000; //Vector<double>[] res = bendStiffener.bvpsolver_zzz(bendStiffener.Ode_to_solve, 0.0, bendStiffener.q, 0.0, 5.0, N); double[] x = Vector <double> .Build.Dense(N, i => i * 5.0 / N).ToArray(); double[] y = new double[N]; double[] dydx = new double[N]; //initialisation of plot formsPlot1.Reset(); var plt = new ScottPlot.Plot(800, 600); //plt.PlotScatter(x, y, label: "y", markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); //plt.PlotSignal(new[,] { x, y }); //plt.SaveFig("quickstart.png"); double[] lineX = new double[] { 0, 5 }; double[] lineY = new double[] { bendStiffener.max_k, bendStiffener.max_k }; //formsPlot1.plt.PlotScatter(lineX, lineY, label: "Pass", lineWidth: 5, markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); //double[] max_pnt = new double[] { x[Array.IndexOf(dydx, dydx.Max())], dydx.Max() }; //formsPlot1.plt.PlotPoint(max_pnt[0], max_pnt[1], color: Color.Magenta, markerSize: 15); //initialisation of plot //-------- double ya = 0; double yb = bendStiffener.q; double xa = 0; double xb = 5; Func <double, Vector <double>, Vector <double> > system = bendStiffener.Ode_to_solve; Vector <double>[] res; Vector <double> y0; //double s_guess = (yb - ya) / (xb - xa), s_guess_pre = 0; double fais = yb, fais_pre = 0, dfaids = 0, dfai, ds; //bool changeDirectionFlag = false; int countTimes = 1000; double[] faisLst = new double[countTimes]; double[] sLst = new double[countTimes]; sLst = Vector <double> .Build.Dense(N, i => - 0.05 + i * 0.3 / countTimes).ToArray(); for (int count = 0; count < countTimes; count++) { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, sLst[count] }); // observer_pr ob_pr = this->write_targetFunc_end; res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais_pre = fais; fais = res[N - 1][0] - yb; ////dfaids = (fais - fais_pre) / (s_guess - s_guess_pre); //dfai = fais - fais_pre; //ds = s_guess - s_guess_pre; //s_guess_pre = s_guess; ////s_guess = s_guess - fais / dfaids; //s_guess = s_guess - fais * ds / dfai; ////s_guess = s_guess - fais / (fais - fais_pre) * (s_guess - s_guess_pre); faisLst[count] = fais; //sLst[count] = s_guess; formsPlot1.plt.PlotPoint(sLst[count], fais, color: Color.Magenta, markerSize: 15); //--------- double[][] dydx2 = new double[countTimes][]; for (int i = 0; i < N; i++) { double[] temp = res[i].ToArray(); y[i] = temp[0]; dydx[i] = temp[1]; //Console.WriteLine(t[i]); } dydx2[count] = (double[])dydx.Clone(); //formsPlot1.plt.PlotScatter(x, dydx2[count], label: "dydx" + count.ToString(), lineWidth: 5, markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); } //formsPlot1.plt.PlotScatter(x, dydx, label: "dydx", lineWidth: 5, markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); formsPlot1.plt.PlotScatter(sLst, faisLst, label: "fais-s", lineWidth: 5, markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); //plt.PlotScatter(x, dydx, label: "dydx", markerShape: (MarkerShape)Enum.Parse(typeof(MarkerShape), "none")); formsPlot1.plt.Grid(true); formsPlot1.plt.Legend(fontSize: 20, location: legendLocation.lowerLeft); formsPlot1.Render(); }
public Vector <double>[] bvpsolver_zzz(Func <double, Vector <double>, Vector <double> > system, double ya, double yb, double xa, double xb, int N) { //先求解方程得到初始斜率的估计值,再进行打靶法迭代。--zzz Vector <double>[] res; Vector <double> y0; double s_guess, s_guess_pre; double fais, fais_pre; double dfai, ds; int count = 0; //计算20组s_guess和fais,然后样条插值得到连续函数,再通过解方程,得到使fais=0的初始s_guess int M = 50; double[] sLst = Vector <double> .Build.Dense(M, i => yb / M *i).ToArray(); double[] faisLst = new double[M]; count = 0; while (count < M) { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, sLst[count] }); // observer_pr ob_pr = this->write_targetFunc_end; res = RungeKutta.FourthOrder(y0, xa, xb, N, system); faisLst[count] = res[N - 1][0] - yb; count++; } //样条插值得到连续函数 var cubicSpl = CubicSpline.InterpolateNatural(sLst, faisLst); /*如果初始值离解太远,牛顿法会不收敛。故采用Mathnet包中的RobustNewtonRaphson * double s_cur = 0, s_next; * count = 0; * while (count < 1000) * { * fais = cubicSpl.Interpolate(s_cur); * dfaids = cubicSpl.Differentiate(s_cur); * if (fais < 1e-5 && fais > -1e-5) * { * break; * } * * s_next = s_cur - fais / dfaids; * s_cur = s_next; * count += 1; * }*/ //解方程fais=0,得到初始斜率s_guess。该法先尝试牛顿法,如失败会采用二分法(bisection)。 s_guess = RobustNewtonRaphson.FindRoot(cubicSpl.Interpolate, cubicSpl.Differentiate, 0, yb, 1e-5); //利用解得的s_guess,构造s_guess_pre,目的是求导数dfai/ds。 if (s_guess == 0) { s_guess_pre = 1e-2; } else { s_guess_pre = s_guess * 0.99; } //求s_guess_pre对应的fais_pre,目的是求导数dfai/ds。 y0 = Vector <double> .Build.DenseOfArray(new[] { ya, s_guess_pre }); res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais_pre = res[N - 1][0] - yb; count = 0; while (count < 50) { y0 = Vector <double> .Build.DenseOfArray(new[] { ya, s_guess }); res = RungeKutta.FourthOrder(y0, xa, xb, N, system); fais = res[N - 1][0] - yb; dfai = fais - fais_pre; ds = s_guess - s_guess_pre; if (fais < 1e-5 && fais > -1e-5) { break; } fais_pre = fais; s_guess_pre = s_guess; s_guess = s_guess - fais * ds / dfai; count++; } return(res); }
/// <summary> /// Método Runge Kutta de Quarta ordem para equações diferenciais /// </summary> /// <param name="y0">Valor Inicial</param> /// <param name="start">Tempo Inicial</param> /// <param name="end">Tempo Final</param> /// <param name="dydx">Equação diferencial a ser calculada</param> /// <returns></returns> public double RungeKutta4(double y0, double start, double end, Func <double, double, double> dydx) { return(RungeKutta.FourthOrder(y0, start, end, 10, dydx)[9]); }
public Vector <double>[] Integrate(IReadOnlyList <double> Control) { _params = Control; return(RungeKutta.FourthOrder(_x0, 0, _tMax, _sizeOfRes, OdeFunction)); }