コード例 #1
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 VectorNetFunc ODUsearch(VRealFunc f, Vectors begval, double begin = 0, double end = 10, double step = 0.01, Method M = Method.E1, double eps = 0.0001, bool controllingstep = false)
            {
                //$"Вызов функции от вектора {begval}".Show();
                double        thisstep = step;
                VectorNetFunc res      = new VectorNetFunc();

                res.Add(new PointV(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)
                {
                    Vectors u = res.Last().Item2;
                    double  t = res.Last().Item1;

                    Vectors[] k = new Vectors[r];
                    Vectors   tmp = new Vectors(u.Deg), tmpp = new Vectors(u.Deg);
                    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);
                    Vectors val1 = u + step * tmp, val2 = u + step * tmpp;
                    double  R = 0.2 * (val1 - val2).EuqlidNorm;


                    if (controllingstep && stepchange <= MaxStepChange)
                    {
                        Get2Tmp(ref tmp, ref tmpp, step / 2, A, k, f, u, t, r);
                        Vectors uh1 = u + tmp * step / 2;
                        Get2Tmp(ref tmp, ref tmpp, step / 2, A, k, f, uh1, t + step / 2, r);
                        Vectors 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 = ((uh2 - val2) / (1 - 1.0 / Math.Pow(2, p))).EuqlidNorm;
                        }
                        else
                        {
                            RR = ((uh2 - val1) / (1 - 1.0 / Math.Pow(2, p))).EuqlidNorm;
                        }

                        /*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 PointV(begin, val2));
                            }
                            else
                            {
                                res.Add(new PointV(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 PointV(begin, val2));
                            step *= 2;
                            stepchange++;
                        }
                        else
                        {
                            begin += step;
                            res.Add(new PointV(begin, val2));
                        }
                    }
                    else
                    {
                        begin += step;
                        res.Add(new PointV(begin, val1));
                    }

                    if (Math.Abs(end - begin) < step)
                    {
                        step = Math.Abs(end - begin);
                    }
                }

                return(res);
            }
コード例 #2
0
            /// <summary>
            /// Решение задачи о стрельбе
            /// </summary>
            /// <param name="f">Свободная функция в системе ОДУ</param>
            /// <param name="F">Функция из граничных условий</param>
            /// <param name="alp">Вектор альфа начального приближения при поиске корня</param>
            /// <param name="list">Промежуточный список вектор-функций</param>
            /// <param name="vlist">Промежуточный список векторов</param>
            /// <param name="netlist">Промежуточный список вектор-функций (так как делегаты передаются плохо)</param>
            /// <param name="begin">Начало отрезка задания аргумента</param>
            /// <param name="end">Конец отрезка задания аргумента</param>
            /// <param name="stepcount">Число шагов при решении ОДУ</param>
            /// <param name="M">Метод решения ОДУ</param>
            /// <param name="eps">Погрешность</param>
            /// <param name="l">Коэффициент для метода итераций</param>
            /// <param name="controlstep">Нужно ли следить за шагом при решении ОДУ</param>
            /// <returns></returns>
            public static VectorFunc ShootQu(VRealFunc f, TwoVectorToVector F, Vectors alp, out List <VectorFunc> list, out List <Vectors> vlist, out List <VectorNetFunc> netlist, double begin = 0, double end = 10, int stepcount = 50, Method M = Method.RK4, double eps = 1e-5, double l = 0.1, bool controlstep = false)
            {
                list = new List <VectorFunc>(); vlist = new List <Vectors>(); netlist = new List <VectorNetFunc>();
                double    step = (end - begin) / (stepcount - 1);
                VRealFunc u    = (double t, Vectors v) =>
                {
                    var k = ODUsearch(f, v, begin, end, step, M, eps, controlstep);
                    if (t == end)
                    {
                        return(k.Last().Item2);
                    }
                    double arg = begin; int i = 1;
                    while (arg < t)
                    {
                        arg = k[i++].Item1;
                    }
                    return(k[--i].Item2);
                };

                VectorToVector FF = (Vectors v) => F(v, u(end, v));
                Vectors        xn;

                if (FF(alp).EuqlidNorm > eps)
                {
                    Vectors fx0 = FF(alp);//fx0.Show();
                    vlist.Add(fx0);
                    list.Add((double t) => u(t, new Vectors(fx0)));
                    VectorNetFunc tmp = new VectorNetFunc();
                    for (int i = 0; i < stepcount; i++)
                    {
                        double arg = begin + i * step;
                        tmp.Add(new Tuple <double, Vectors>(arg, list.Last()(arg)));
                    }
                    netlist.Add(tmp);
                    VectorToVector ef = (Vectors v) => v - l * FF(v);

                    //double stnorm, stvector, neunorm, neuvector;
                    bool delay = true;
                    while ((ef(fx0) - fx0).EuqlidNorm > eps && delay)
                    {
                        xn = ef(fx0) - fx0;
                        Console.WriteLine($"Norm f(v)-v ={xn.EuqlidNorm}"); //fx0.Show();
                        fx0 = ef(fx0);
                        vlist.Add(fx0);                                     //fx0.Show();
                        list.Add(new VectorFunc((double t) => u(t, fx0)));
                        //$"list({3}) = {list.Last()(3)}".Show();
                        tmp = new VectorNetFunc();
                        for (int i = 0; i < stepcount; i++)
                        {
                            double arg = begin + i * step;
                            tmp.Add(new Tuple <double, Vectors>(arg, list.Last()(arg)));
                        }
                        netlist.Add(tmp);
                        if ((ef(fx0) - fx0 - xn).EuqlidNorm < eps / 1e4)
                        {
                            delay = false;
                        }
                    }
                }
                else
                {
                    vlist.Add(alp);
                    list.Add((double t) => u(t, new Vectors(alp)));

                    VectorNetFunc tmp = new VectorNetFunc();
                    for (int i = 0; i < stepcount; i++)
                    {
                        double arg = begin + i * step;
                        tmp.Add(new Tuple <double, Vectors>(arg, list.Last()(arg)));
                    }
                    netlist.Add(tmp);
                }

                return(list.Last());
            }
コード例 #3
0
 private static void Get2Tmp(ref Vectors tmp, ref Vectors tmpp, double step, Matrix A, Vectors[] k, VRealFunc f, Vectors u, double t, int r)
 {
     tmp  = new Vectors(tmp.Deg);
     tmpp = new Vectors(tmp.Deg);
     for (int i = 0; i < k.Length; i++)
     {
         Vectors tmp2 = new Vectors(tmp.Deg);
         for (int j = 0; j < i; j++)
         {
             tmp2 += A[i, j + 1] * k[j];
         }
         k[i] = f(t + A[i, 0] * step, u + tmp2 * step);
         tmp += A[r, i + 1] * k[i];
         if (A.RowCount != A.ColCount)
         {
             tmpp += A[r + 1, i + 1] * k[i];
         }
     }
 }