/// <summary> /// Решение задачи Штурма-Лиувилля /// </summary> /// <param name="g">Функция внутри второй производной</param> /// <param name="h">Функция при первой производной</param> /// <param name="s">Функция при искомой функции</param> /// <param name="f">Свободная функция</param> /// <param name="a">Начало отрезка</param> /// <param name="b">Конец отрезка</param> /// <param name="N">Число шагов</param> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <param name="D"></param> /// <param name="A1"></param> /// <param name="B1"></param> /// <param name="C1"></param> /// <param name="D1"></param> /// <returns></returns> public static NetFunc SchLiuQu(Func <double, double> g, Func <double, double> h, Func <double, double> s, Func <double, double> f, out double nevaska, double a = 0, double b = 10, int N = 50, double A = 1, double B = 1, double D = 1, double A1 = 1, double B1 = 1, double D1 = 1, bool firstkind = true) { double[] hn = new double[N + 1], fn = new double[N + 1], sn = new double[N + 1], tn = new double[N + 1], an = new double[N + 1], bn = new double[N + 1], cn = new double[N + 1], dn = new double[N + 1]; double t = (b - a) / N; for (int i = 0; i < N + 1; i++) { double arg = a + i * t; tn[i] = arg; hn[i] = h(arg); fn[i] = f(arg); sn[i] = s(arg); an[i] = (g(arg - t / 2) / t - hn[i] / 2) / t; cn[i] = (g(arg + t / 2) / t + hn[i] / 2) / t; bn[i] = an[i] + cn[i] - sn[i]; //поставил sn вместо hn //bn[i] = (g(arg + t / 2) - g(arg - t / 2)) / t / t - sn[i]; dn[i] = fn[i]; } double k1 = 0, k2 = 0; if (firstkind) { bn[0] = A / t - B; cn[0] = A / t; dn[0] = D; an[N] = -A1 / t; bn[N] = -A1 / t - B1; dn[N] = D1; } else { bn[0] = 3 * A / 2 / t - B; cn[0] = 2 * A / t; k1 = -A / 2 / t; bn[N] = -3 * A1 / 2 / t - B1; an[N] = -2 * A1 / t; k2 = A1 / 2 / t; } dn[0] = D; dn[N] = D1; SLAU S = new SLAU(N + 1); S.A[0, 0] = -bn[0]; S.A[0, 1] = cn[0]; S.A[0, 2] = k1; S.A[N, N - 1] = an[N]; S.A[N, N - 2] = k2; S.A[N, N] = -bn[N]; S.b[0] = dn[0]; S.b[N] = dn[N]; for (int i = 1; i < N; i++) { S.A[i, 0 + i - 1] = an[i]; S.A[i, 1 + i - 1] = -bn[i]; S.A[i, 2 + i - 1] = cn[i]; S.b[i] = dn[i]; } S.Show(); "".Show(); double c1 = S.A[0, 2] / S.A[1, 2], c2 = S.A[N, N - 2] / S.A[N - 1, N - 2]; for (int i = 0; i < 3; i++) { S.A[0, i] -= S.A[1, i] * c1; S.A[N, N - i] -= S.A[N - 1, N - i] * c2; } S.b[0] -= S.b[1] * c1; S.b[N] -= S.b[N - 1] * c2; //S.Show(); "".Show(); S.ProRace(); S.Show(); nevaska = S.Nevaska; NetFunc res = new NetFunc(); for (int i = 0; i < N + 1; i++) { res.Add(new Point(tn[i], S.x[i])); } return(res); }
/// <summary> /// Решение приведённого ОДУ первого порядка /// </summary> /// <param name="f">Свободная функция переменных u и x, где u - искомая функция</param> /// <param name="begin">Начальный аргумент по задаче Коши</param> /// <param name="end">Конечный аргумент</param> /// <param name="step">Шаг интегрирования</param> /// <param name="M">Метод поиска решения</param> /// <param name="begval">Значение функции при начальном аргументе</param> /// <param name="eps">Допустимый уровень расчётных погрешностей</param> /// <returns></returns> public static NetFunc ODUsearch(DRealFunc f, double begin = 0, double end = 10, double step = 0.01, Method M = Method.E1, double begval = 1, double eps = 0.0001, bool controllingstep = false) { double thisstep = step; NetFunc res = new NetFunc(); res.Add(new Point(begin, begval)); step *= Math.Sign(end - begin); Matrix A; switch (M) { case Method.E1: A = E1; break; case Method.E2: A = E2; break; case Method.H: A = H; break; case Method.RK3: A = RK3; break; case Method.RK4: A = Rk4; break; case Method.P38: A = P38; break; case Method.F: A = F; break; default: A = C; break; } int r = A.RowCount - 1; if (A.RowCount != A.ColCount) { r--; } while (begin < /*=*/ end) { double u = res.LastVal(); double t = res.LastArg(); double[] k = new double[r]; double tmp = 0, tmpp = 0; int stepchange = 0; //double[] h2 = new double[2]; //Get2Tmp(ref tmp, ref tmpp, step/2, A, k, f, u, t, r); //double uh1 = u + tmp * step/2; //Get2Tmp(ref tmp, ref tmpp, step / 2, A, k, f, uh1, t+step/2, r); //double uh2 = uh1 + tmp * step/2; Get2Tmp(ref tmp, ref tmpp, step, A, k, f, u, t, r); double val1 = u + step * tmp, val2 = u + step * tmpp; double R = 0.2 * Math.Abs(val1 - val2); if (controllingstep && stepchange <= MaxStepChange) { Get2Tmp(ref tmp, ref tmpp, step / 2, A, k, f, u, t, r); double uh1 = u + tmp * step / 2; Get2Tmp(ref tmp, ref tmpp, step / 2, A, k, f, uh1, t + step / 2, r); double uh2 = uh1 + tmp * step / 2; int p; switch (M) { case Method.E1: p = 1; break; case Method.E2: p = 2; break; case Method.H: p = 3; break; case Method.RK3: p = 3; break; case Method.RK4: p = 4; break; case Method.P38: p = 4; break; case Method.F: p = 3; break; default: p = 4; break; } double RR; if (A.RowCount != A.ColCount) { RR = Math.Abs((uh2 - val2) / (1 - 1.0 / Math.Pow(2, p))); } else { RR = Math.Abs((uh2 - val1) / (1 - 1.0 / Math.Pow(2, p))); } /*if (RR < eps / 64) { step *= 2; stepchange++; } * else */ if (RR > eps) { step /= 2; stepchange++; } else { begin += step; step = thisstep;//возврат к исходному шагу if (A.RowCount != A.ColCount) { res.Add(new Point(begin, val2)); } else { res.Add(new Point(begin, val1)); } } } else if (A.RowCount != A.ColCount && stepchange <= MaxStepChange) { if (R > eps) { step /= 2; stepchange++; } else if (R <= eps / 64) { begin += step; res.Add(new Point(begin, val2)); step *= 2; stepchange++; } else { begin += step; res.Add(new Point(begin, val2)); } } else { begin += step; res.Add(new Point(begin, val1)); } if (Math.Abs(end - begin) < step) { step = Math.Abs(end - begin); } } return(res); }