/// <summary> /// Returns the value of a differential equation calculated by the Adams-Bashfort method. /// </summary> /// <param name="function">The delegate of a continuous function depending on two variables</param> /// <param name="x">Array of values argument</param> /// <param name="y0">Value</param> /// <param name="order">Order</param> /// <returns>Array of function values</returns> public Complex32[] Compute(IComplexMesh function, Complex32[] x, Complex32 y0, int order = 2) { int n = x.Length - 1; // if order more than 1 // Adams-Bashfort method if (order > 1 && order < n) { // params int i, j, k = order + 1; Complex32[] y = new Complex32[n]; Complex32[] r = new Complex32[k]; float[] c = Differential.GetCoefficients(order); Complex32 h, t, sum; // compute first points by order for (i = 0; i < k; i++) { r[i] = x[i]; } // classic differential r = this.Compute(function, r, y0); for (i = 0; i < order; i++) { y[i] = r[i]; } // Adams-Bashforth method // for order for (i = order; i < n; i++) { sum = y[i - 1]; for (j = 0; j < order; j++) { t = x[i - j]; h = t - x[i - j - 1]; sum += h * c[j] * function(t, y[i - j - 1]); } y[i] = sum; } return(y); } // classic differential return(this.Compute(function, x, y0)); }
/// <summary> /// /// </summary> /// <param name="f"></param> /// <param name="x"></param> /// <param name="y0"></param> /// <returns></returns> private static Complex32[] euler(IComplexMesh f, Complex32[] x, Complex32 y0) { int n = x.Length - 1; Complex32 xnew, ynew = y0, h; Complex32[] result = new Complex32[n]; for (int i = 0; i < n; i++) { h = x[i + 1] - x[i]; xnew = x[i]; ynew = ynew + f(xnew, ynew) * h; result[i] = ynew; } return(result); }
/// <summary> /// Returns the value of a differential equation. /// </summary> /// <param name="function">The delegate of a continuous function depending on two variables</param> /// <param name="x">Array of values argument</param> /// <param name="y0">Value</param> /// <returns>Array of function values</returns> public Complex32[] Compute(IComplexMesh function, Complex32[] x, Complex32 y0) { // chose method of differentiation switch (method) { case Method.Euler: return(Differential.euler(function, x, y0)); case Method.Fehlberg: return(Differential.fehlberg(function, x, y0)); case Method.RungeKutta4: return(Differential.rungeKutta4(function, x, y0)); default: return(Differential.rungeKutta2(function, x, y0)); } }
/// <summary> /// /// </summary> /// <param name="f"></param> /// <param name="x"></param> /// <param name="y0"></param> /// <returns></returns> private static Complex32[] rungeKutta2(IComplexMesh f, Complex32[] x, Complex32 y0) { int n = x.Length - 1; Complex32 xnew, ynew = y0, h, k1, k2; Complex32[] result = new Complex32[n]; for (int i = 0; i < n; i++) { h = x[i + 1] - x[i]; xnew = x[i]; k1 = h * f(xnew, ynew); k2 = h * f(xnew + 0.5 * h, ynew + 0.5 * k1); ynew = ynew + k2; xnew = xnew + h; result[i] = ynew; } return(result); }
/// <summary> /// /// </summary> /// <param name="f"></param> /// <param name="x"></param> /// <param name="y0"></param> /// <returns></returns> private static Complex32[] rungeKutta4(IComplexMesh f, Complex32[] x, Complex32 y0) { int n = x.Length - 1; Complex32 xnew, ynew = y0, h, k1, k2, k3, k4; Complex32[] result = new Complex32[n]; for (int i = 0; i < n; i++) { h = x[i + 1] - x[i]; xnew = x[i]; k1 = h * f(xnew, ynew); k2 = h * f(xnew + 0.5 * h, ynew + 0.5 * k1); k3 = h * f(xnew + 0.5 * h, ynew + 0.5 * k2); k4 = h * f(xnew + h, ynew + k3); ynew = ynew + (k1 + 2 * k2 + 2 * k3 + k4) / 6; xnew = xnew + h; result[i] = ynew; } return(result); }
/// <summary> /// /// </summary> /// <param name="f"></param> /// <param name="x"></param> /// <param name="y0"></param> /// <returns></returns> private static Complex32[] fehlberg(IComplexMesh f, Complex32[] x, Complex32 y0) { int n = x.Length - 1; Complex32 xnew, ynew = y0, h, k1, k2, k3, k4, k5, k6; Complex32[] result = new Complex32[n]; for (int i = 0; i < n; i++) { h = x[i + 1] - x[i]; xnew = x[i]; k1 = h * f(xnew, ynew); k2 = h * f(xnew + 0.25 * h, ynew + 0.25 * k1); k3 = h * f(xnew + 3 * h / 8, ynew + 3 * k1 / 32 + 9 * k2 / 32); k4 = h * f(xnew + 12 * h / 13, ynew + 1932 * k1 / 2197 - 7200 * k2 / 2197 + 7296 * k3 / 2197); k5 = h * f(xnew + h, ynew + 439 * k1 / 216 - 8 * k2 + 3680 * k3 / 513 - 845 * k4 / 4104); k6 = h * f(xnew + 0.5 * h, ynew - 8 * k1 / 27 + 2 * k2 - 3544 * k3 / 2565 + 1859 * k4 / 4104 - 11 * k5 / 40); ynew = ynew + 25 * k1 / 216 + 1408 * k3 / 2565 + 2197 * k4 / 4104 - 0.2 * k5; xnew = xnew + h; result[i] = ynew; } return(result); }