예제 #1
0
            /// <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);
            }
예제 #2
0
            /// <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);
            }