예제 #1
0
        public static Vector GetRs(double x0, double xN, double[] Y0, MethodRK rk, int k, int p)
        {
            /*
             * Получение точных полных погрешностей R на шагах h = 1 / (2^i) при i = 0..k
             */

            var R = new Vector(k);

            double h = 1 / Math.Pow(2, 0);             // начальная велечина шага

            //Значение Y на конце отрезка на предыдущей велечине шага
            var resPred = Result_ConstH(x0, xN, Y0, rk, h).Last().SecondElement;

            for (int i = 1; i < k; i++)
            {
                //Текущая велечина шага
                h = 1 / Math.Pow(2, i);
                //Значение Y на конце отрезка на текущей велечине шага
                var resTemp = Result_ConstH(x0, xN, Y0, rk, h).Last().SecondElement;

                //Погрешность для пред.шага
                var R1 = ((1 / (1 - Math.Pow(2, -p))) * (resTemp - resPred)).Norm();
                //Погрешность для тек.шага
                var R2 = ((1 / (Math.Pow(2, p) - 1)) * (resTemp - resPred)).Norm();

                R.data[i - 1] = Math.Max(R.data[i - 1], R1);
                R.data[i]     = R2;

                resPred.Copy(resTemp);
            }
            return(R);
        }
예제 #2
0
        public static double H_Opt(double x0, double xN, double[] Y0, MethodRK rk, int p, double tol)
        {
            var k = 10;

            var h1       = 1.0 / Math.Pow(2, k);
            var resultH1 = OduCalculation.Result_ConstH(x0, xN, Y0, rk, h1);

            var h2       = 1.0 / Math.Pow(2, k + 1);
            var resultH2 = OduCalculation.Result_ConstH(x0, xN, Y0, rk, h2);

            var R2 = ((1 / (Math.Pow(2, p) - 1)) * (resultH2.Last().SecondElement - resultH1.Last().SecondElement)).Norm();

            return(h2 * Math.Pow(tol / R2, 1.0 / p));
        }
예제 #3
0
        public static Pair <int, int>[] CountCallF_onRtol(double x0, double xN, double[] Y0, MethodRK rk, int p, int s)
        {
            var h_begin = 1 / Math.Pow(2, 6);

            var rtol = 1e-4;

            var tempDegree = 4;

            var result = new Pair <int, int> [5];

            for (int i = 0; i < 5; i++)
            {
                var accH = new List <Pair <double, Pair <double, List <double> > > >();
                Result_VariableH(x0, xN, Y0, rk, p, h_begin, ref accH, rtol);

                var countAddCallRK = accH.Sum(infoH => infoH.SecondElement.SecondElement.Count());

                result[i] = new Pair <int, int>
                {
                    FirstElement  = tempDegree,
                    SecondElement = s * (accH.Count() + countAddCallRK)
                };

                tempDegree++;
                rtol /= 10;
            }
            return(result);
        }
예제 #4
0
        public static Pair <double, Vector>[] Result_VariableH(double x0, double xN, double[] Y0, MethodRK rk, int p, double h0,
                                                               ref List <Pair <double, Pair <double, List <double> > > > accH,
                                                               double rtol = 1e-6, double atol = 1e-12)
        {
            accH = new List <Pair <double, Pair <double, List <double> > > >();

            var result = new List <Pair <double, Vector> >();

            var    tempVectorY = new Vector(Y0);
            double tempX       = x0;

            //Текущий обычный шаг
            double h1 = h0;
            //Текущий половинный шаг
            double h2;

            //Текущий результат при обычном шаге
            var resultY_H1 = new Vector(Y0.Length);
            //Текущий результат при половинном шаге
            var resultY_H2_1 = new Vector(Y0.Length);
            //Текущий результат при двойном половинном шаге
            var resultY_H2_2 = new Vector(Y0.Length);

            var infoH       = new Pair <double, Pair <double, List <double> > >();
            var AcceptH     = double.NaN;
            var notAcceptHs = new List <double>();
            var isAcceptH   = true;

            do
            {
                if (isAcceptH)
                {
                    infoH = new Pair <double, Pair <double, List <double> > >
                    {
                        FirstElement  = tempX,
                        SecondElement = new Pair <double, List <double> >()
                    };
                    AcceptH     = double.NaN;
                    notAcceptHs = new List <double>();
                    isAcceptH   = false;
                }

                h2 = h1 / 2;

                //Рез на x и h1 (s1)
                resultY_H1.Copy(tempVectorY + h1 * rk(tempX, tempVectorY.data, h1));

                //Рез на x и h2 (s1/2)
                resultY_H2_1.Copy(tempVectorY + h2 * rk(tempX, tempVectorY.data, h2));
                //Рез на (x + h2) и h2 (s2)
                resultY_H2_2.Copy(resultY_H2_1 + h2 * rk(tempX + h2, resultY_H2_1.data, h2));

                //Погрешность по Рунге
                var R1 = ((1.0 / (1 - Math.Pow(2, -p))) * (resultY_H2_2 - resultY_H1)).Norm();

                //Вычисляем tol = rtol*s1 + atol
                var tol = rtol * resultY_H1.Norm() + atol;

                //Проверяем все случаи
                //1. tol * 2^p < R
                if (R1 > tol * Math.Pow(2, p))
                {
                    //Потворяем с этими значениями (нет занесения результата)
                    tempVectorY = new Vector(resultY_H2_1.data);                     //берём s1/2

                    notAcceptHs.Add(h1);
                    isAcceptH = false;

                    h1 /= 2;                     // уменьшаем шаг
                }
                //2.  tol < R <= tol * 2^p
                if (tol < R1 && R1 <= tol * Math.Pow(2, p))
                {
                    result.Add(new Pair <double, Vector>
                    {
                        FirstElement  = tempX,
                        SecondElement = tempVectorY
                    });

                    tempX      += h1;                            //сдвигаемся
                    tempVectorY = new Vector(resultY_H2_2.data); //берём s2

                    AcceptH   = h1;
                    isAcceptH = true;

                    h1 /= 2;                    // уменьшаем шаг
                }
                //3.  tol * (1 / 2^(p+1)) <= R <= tol
                if (tol * (1 / Math.Pow(2, p + 1)) <= R1 && R1 <= tol)
                {
                    result.Add(new Pair <double, Vector>
                    {
                        FirstElement  = tempX,
                        SecondElement = tempVectorY
                    });

                    tempX      += h1;                          //сдвигаемся
                    tempVectorY = new Vector(resultY_H1.data); //берём s1

                    AcceptH   = h1;
                    isAcceptH = true;
                }
                //4.  R < tol * (1 / 2^(p+1))
                if (R1 < tol * (1 / Math.Pow(2, p + 1)))
                {
                    result.Add(new Pair <double, Vector>
                    {
                        FirstElement  = tempX,
                        SecondElement = tempVectorY
                    });

                    tempX      += h1;                          //сдвигаемся
                    tempVectorY = new Vector(resultY_H1.data); //берём s1

                    AcceptH   = h1;
                    isAcceptH = true;

                    h1 *= 2;                    // увеличиваем шаг
                }

                if (isAcceptH)
                {
                    infoH.SecondElement = new Pair <double, List <double> >
                    {
                        FirstElement  = AcceptH,
                        SecondElement = notAcceptHs
                    };
                    accH.Add(infoH);
                }
            } while (tempX < xN);

            return(result.ToArray());
        }
예제 #5
0
        public static Pair <double, Vector>[] Result_ConstH(double x0, double xN, double[] Y0, MethodRK rk, double h)
        {
            //Кол-во шагов
            int n = (int)((xN - x0) / h);

            var result = new Pair <double, Vector> [n];

            var    tempVectorY = new Vector(Y0);
            double tempX;

            for (int i = 0; i < n; i++)
            {
                tempX = x0 + h * i;

                result[i].FirstElement  = tempX;
                result[i].SecondElement = new Vector(tempVectorY.data);

                //Получаем следующие значение в текущем x
                tempVectorY += h * rk(tempX, tempVectorY.data, h);
            }
            return(result);
        }