/// <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 float[] Compute(IFloatMesh function, float[] x, float 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; float[] y = new float[n]; float[] r = new float[k]; float[] c = Differential.GetCoefficients(order); float 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 float[] euler(IFloatMesh f, float[] x, float y0) { int n = x.Length - 1; float xnew, ynew = y0, h; float[] result = new float[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 float[] Compute(IFloatMesh function, float[] x, float 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 float[] rungeKutta2(IFloatMesh f, float[] x, float y0) { int n = x.Length - 1; float xnew, ynew = y0, h, k1, k2; float[] result = new float[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.5f * h, ynew + 0.5f * 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 float[] rungeKutta4(IFloatMesh f, float[] x, float y0) { int n = x.Length - 1; float xnew, ynew = y0, h, k1, k2, k3, k4; float[] result = new float[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.5f * h, ynew + 0.5f * k1); k3 = h * f(xnew + 0.5f * h, ynew + 0.5f * 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 float[] fehlberg(IFloatMesh f, float[] x, float y0) { int n = x.Length - 1; float xnew, ynew = y0, h, k1, k2, k3, k4, k5, k6; float[] result = new float[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.25f * h, ynew + 0.25f * 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.5f * 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.2f * k5; xnew = xnew + h; result[i] = ynew; } return(result); }
/// <summary> /// Initializes the color photo filter. /// </summary> /// <param name="blendf">Blend function</param> /// <param name="color">Color</param> /// <param name="strength">Strenght [0, 1]</param> public PhotoFilter(IFloatMesh blendf, Color color, float strength = 0.5f) { BlendFunction = blendf; Color = color; Strength = strength; }