Exemple #1
0
        /// <summary>
        /// Обчислення градієнту V_zz для заданих координат по моделі "in_model"
        /// </summary>
        public static double getGradient(ReferenceSystem rs, GravityModel in_model, double coLat, double longit, MathFunc.AngleType angType = MathFunc.AngleType.Radians)
        {
            GravityModel gm;

            if (in_model.model_a != rs.a || in_model.model_GM != rs.GM)
            {
                gm = in_model.rescaleModel(rs);
            }
            else
            {
                gm = new GravityModel(in_model);
            };
            if (angType == MathFunc.AngleType.Degrees)
            {
                MathFunc.deg2rad(ref longit);
            }
            double grad = 0;
            double tmp = 0, sum_tmp = 0, sum_tmp_2 = 0;

            double[] legendrePolynoms = null;
            MathFunc.getLegendre(rs.maxDegree, coLat, out legendrePolynoms, angType);
            for (int i = 0; i <= rs.maxDegree; i++)
            {
                int n = MathFunc.getArraySize(i - 1) - 1;
                sum_tmp_2 = 0;
                sum_tmp   = (i + 1) * (i + 2) * Math.Pow(rs.a / rs.satelliteSphere, i + 3);
                for (int m = 0; m < gm.c_coef[i].Length; m++)
                {
                    double a1 = legendrePolynoms[n + m + 1], a2 = gm.c_coef[i][m] * Math.Cos(m * longit), a3 = gm.s_coef[i][m] * Math.Sin(m * longit);
                    double x = a1 * (a2 + a3);
                    sum_tmp_2 += x;
                }
                tmp += sum_tmp * sum_tmp_2;
            }
            grad = rs.GM / Math.Pow(rs.a, 3D) * tmp;
            return(grad);
        }
Exemple #2
0
        public static double[][] getGeoidHeightAndAnomalys(ReferenceSystem rs, GravityModel model, List <double[]> grid, System.Threading.CancellationToken ct, System.Threading.CancellationToken ct2, NormalGammaFormula gamma_0_formula = NormalGammaFormula.Somigliana, MainForm.setProgressDel d = null)
        {
            GravityModel gm;

            if (model.model_a != rs.a || model.model_GM != rs.GM)
            {
                gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM);
            }
            else
            {
                gm = new GravityModel(model, model.model_a, model.model_GM);
            };
            gm = getDisturbingModel(rs, gm);
            double[]        heights = new double[grid.Count];
            double[]        anomaly = new double[grid.Count];
            int[][]         t_nm = MathFunc.get_nm(gm.maxDegree);
            double[]        legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int             position = 0;
            int             count = grid.Count, position_p = (rs.maxDegree < 150)?(int)Math.Round(0.01d * count):5;
            ParallelOptions po = new ParallelOptions();

            po.MaxDegreeOfParallelism = Environment.ProcessorCount;
            po.CancellationToken      = ct;
            try
            {
                Parallel.For(0, grid.Count, po, (pointIndex) =>
                {
                    Label1: if (ct2.IsCancellationRequested)
                    {
                        System.Threading.Thread.Sleep(1000);
                    }
                    else
                    {
                        goto label2;
                    }
                    goto Label1;
                    label2:    double gamma_0 = 0, B = 0, r = 0;
                    double[] legendrePolys    = null;
                    double[] point            = grid[pointIndex];
                    lock (locker2)
                    {
                        if (point_old != double.MinValue)
                        {
                            if (point[0] == point_old)
                            {
                                legendrePolys = new double[legendrePolys_old.Length];
                                legendrePolys_old.CopyTo(legendrePolys, 0);
                            }
                            MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                            legendrePolys_old = new double[legendrePolys.Length];
                            legendrePolys.CopyTo(legendrePolys_old, 0);
                            point_old = point[0];
                        }
                        else
                        {
                            MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                            legendrePolys_old = new double[legendrePolys.Length];
                            legendrePolys.CopyTo(legendrePolys_old, 0);
                            point_old = point[0];
                        }
                    }
                    B = MathFunc.convertThethaToB(point[0], rs);
                    r = MathFunc.getGeocentrDistanceToPointOnElips(rs, B);
                    if (gamma_0_formula == NormalGammaFormula.Somigliana)
                    {
                        gamma_0 = rs.gamma_a * (1d + rs.k * Math.Pow(Math.Sin(B), 2d)) / Math.Sqrt(1d - rs.firstExcentricity_2 * Math.Pow(Math.Sin(B), 2d));
                    }
                    else
                    {
                        gamma_0 = 9.78030d * (1d + 0.005302 * Math.Pow(Math.Sin(B), 2d) - 0.000007 * Math.Pow(Math.Sin(2d * B), 2d));
                    }
                    double a1, a2_x = rs.a / r, a2_t, a3, cosMlambda, sinMlambda, a1_a, a2_a = 0, a2 = 0, a2_x_m = a2_x;
                    a1     = rs.GM / (r * gamma_0);
                    a1_a   = rs.GM / (r * r);
                    int az = 0;
                    for (int n = 0; n < rs.maxDegree; n++)
                    {
                        int x = (n == 0) ? 0 : -1;
                        a3    = 0;
                        az   += (n - 1) + 1;
                        for (int m = 0; m <= n; m++)
                        {
                            cosMlambda = Math.Cos(m * point[1]);
                            sinMlambda = Math.Sin(m * point[1]);
                            a3        += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[az + (n - m)];
                        }
                        if (n > 1)
                        {
                            a2_x *= a2_x_m; a2_t = a2_x;
                        }
                        else
                        {
                            a2_t = Math.Pow(a2_x, n);
                        };
                        a2   += a2_t * a3;
                        a2_a += a2_t * (n - 1) * a3;
                    }

                    double tmp_h = a1 * a2, tmp_a = a1_a * a2_a * 1e5;
                    lock (heights)
                    { heights[pointIndex] = tmp_h; }
                    lock (anomaly)
                    { anomaly[pointIndex] = tmp_a; }
                    if (d != null)
                    {
                        position++;
                        if (position > position_p)
                        {
                            lock (locker) { position_p += position_p; }; d.Invoke(position, count, "Обчислено висоти для точок: ");
                        }
                        ;
                        if (position >= count)
                        {
                            d.Invoke(0, 1, "");
                        }
                        ;
                    }
                });
            }
            catch (OperationCanceledException)
            {
                return(new double[2][]);
            }
            return(new double[][] { heights, anomaly });
        }
Exemple #3
0
        //Обчислення аномалій сили ваги для сітки (в мГал)
        public static double[] getAnomaly(ReferenceSystem rs, GravityModel model, List <double[]> grid, MainForm.setProgressDel d = null)
        {
            GravityModel gm;

            if (model.model_a != rs.a || model.model_GM != rs.GM)
            {
                gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM);
            }
            else
            {
                gm = new GravityModel(model, model.model_a, model.model_GM);
            };
            gm = getDisturbingModel(rs, gm);
            double[] heights = new double[grid.Count];
            int[][]  t_nm = MathFunc.get_nm(gm.maxDegree);
            double[] legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int      position = 0;
            int      count = grid.Count, position_p = (int)Math.Round(0.01d * count);

            Parallel.For(0, grid.Count, (pointIndex) =>
            {
                double B = 0, r = 0;
                double[] legendrePolys = null;
                double[] point         = grid[pointIndex];
                lock (locker2)
                {
                    if (point_old != double.MinValue)
                    {
                        if (point[0] == point_old)
                        {
                            legendrePolys = new double[legendrePolys_old.Length];
                            legendrePolys_old.CopyTo(legendrePolys, 0);
                        }
                        MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                    else
                    {
                        MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                }
                B             = MathFunc.convertThethaToB(point[0], rs);
                r             = MathFunc.getGeocentrDistanceToPointOnElips(rs, B);
                double a1, a2 = 0, a3, cosMlambda, sinMlambda;
                a1            = rs.GM / (r * r);
                for (int n = 0; n < gm.maxDegree; n++)
                {
                    a3 = 0;
                    for (int m = 0; m <= n; m++)
                    {
                        cosMlambda = Math.Cos(m * point[1]);
                        sinMlambda = Math.Sin(m * point[1]);
                        lock (gm)
                        { a3 += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[MathFunc.getArraySize(n - 1) + (n - m)]; }
                    }
                    a2 += Math.Pow(rs.a / r, n) * (n - 1) * a3;
                }
                lock (heights)
                { heights[pointIndex] = a1 * a2; }
                if (d != null)
                {
                    position++;
                    if (position > position_p)
                    {
                        lock (locker) { position_p += position_p; }; d.Invoke(position, count, "Обчислено висоти для точок: ");
                    }
                    ;
                    if (position >= count)
                    {
                        d.Invoke(0, 1, "");
                    }
                    ;
                }
            });
            return(heights);
        }
 /// <summary>
 /// Обчислення градієнту V_zz для заданих координат по моделі "in_model"
 /// </summary>
 public static double getGradient(ReferenceSystem rs,GravityModel in_model, double coLat, double longit, MathFunc.AngleType angType = MathFunc.AngleType.Radians)
 {
     GravityModel gm;
     if (in_model.model_a != rs.a || in_model.model_GM != rs.GM) { gm = in_model.rescaleModel(rs); } else { gm = new GravityModel(in_model); };
     if (angType == MathFunc.AngleType.Degrees) { MathFunc.deg2rad(ref longit); }
     double grad = 0;
     double tmp = 0, sum_tmp = 0, sum_tmp_2 = 0;
     double[] legendrePolynoms = null;
     MathFunc.getLegendre(rs.maxDegree, coLat, out legendrePolynoms, angType);
     for (int i = 0; i <= rs.maxDegree; i++)
     {
         int n = MathFunc.getArraySize(i - 1) - 1;
         sum_tmp_2 = 0;
         sum_tmp = (i + 1) * (i + 2) * Math.Pow(rs.a / rs.satelliteSphere, i + 3);
         for (int m = 0; m < gm.c_coef[i].Length; m++)
         {
             double a1 = legendrePolynoms[n + m + 1], a2 = gm.c_coef[i][m] * Math.Cos(m * longit), a3 = gm.s_coef[i][m] * Math.Sin(m * longit);
             double x = a1 * (a2 + a3);
             sum_tmp_2 += x;
         }
         tmp += sum_tmp * sum_tmp_2;
     }
     grad = rs.GM / Math.Pow(rs.a, 3D) * tmp;
     return grad;
 }
        public static double[][] getGeoidHeightAndAnomalys(ReferenceSystem rs, GravityModel model, List<double[]> grid, System.Threading.CancellationToken ct,System.Threading.CancellationToken ct2, NormalGammaFormula gamma_0_formula = NormalGammaFormula.Somigliana, MainForm.setProgressDel d = null)
        {
            GravityModel gm;
            if (model.model_a != rs.a || model.model_GM != rs.GM) { gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM); } else { gm = new GravityModel(model, model.model_a, model.model_GM); };
            gm = getDisturbingModel(rs, gm);
            double[] heights = new double[grid.Count];
            double[] anomaly = new double[grid.Count];
            int[][] t_nm = MathFunc.get_nm(gm.maxDegree);
            double[] legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int position = 0;
            int count = grid.Count, position_p = (rs.maxDegree<150)?(int)Math.Round(0.01d * count):5;
            ParallelOptions po = new ParallelOptions();
            po.MaxDegreeOfParallelism = Environment.ProcessorCount;
            po.CancellationToken = ct;
            try
                {
            Parallel.For(0, grid.Count,po, (pointIndex) =>
            {
            Label1: if (ct2.IsCancellationRequested) { System.Threading.Thread.Sleep(1000); } else { goto label2; }
            goto Label1;
                label2:    double gamma_0 = 0, B = 0, r = 0;
                double[] legendrePolys = null;
                double[] point = grid[pointIndex];
                lock (locker2)
                {
                    if (point_old != double.MinValue)
                    {
                        if (point[0] == point_old)
                        {
                            legendrePolys = new double[legendrePolys_old.Length];
                            legendrePolys_old.CopyTo(legendrePolys, 0);
                        }
                        MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                    else
                    {
                        MathFunc.getLegendre(rs.maxDegree, point[0], out legendrePolys);
                        legendrePolys_old = new double[legendrePolys.Length];
                        legendrePolys.CopyTo(legendrePolys_old, 0);
                        point_old = point[0];
                    }
                }
                B = MathFunc.convertThethaToB(point[0], rs);
                r = MathFunc.getGeocentrDistanceToPointOnElips(rs, B);
                if (gamma_0_formula == NormalGammaFormula.Somigliana)
                { gamma_0 = rs.gamma_a * (1d + rs.k * Math.Pow(Math.Sin(B), 2d)) / Math.Sqrt(1d - rs.firstExcentricity_2 * Math.Pow(Math.Sin(B), 2d)); }
                else { gamma_0 = 9.78030d * (1d + 0.005302 * Math.Pow(Math.Sin(B), 2d) - 0.000007 * Math.Pow(Math.Sin(2d * B), 2d)); }
                double a1, a2_x = rs.a / r, a2_t, a3, cosMlambda, sinMlambda, a1_a, a2_a = 0, a2 = 0, a2_x_m = a2_x;
                a1 = rs.GM / (r * gamma_0);
                a1_a = rs.GM / (r * r);
                int az = 0;
                for (int n = 0; n < rs.maxDegree; n++)
                {
                    int x = (n == 0) ? 0 : -1;
                    a3 = 0;
                    az += (n - 1) + 1;
                    for (int m = 0; m <= n; m++)
                    {
                        cosMlambda = Math.Cos(m * point[1]);
                        sinMlambda = Math.Sin(m * point[1]);
                        a3 += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[az + (n - m)];
                    }
                    if (n > 1) { a2_x *= a2_x_m; a2_t = a2_x; } else { a2_t = Math.Pow(a2_x, n); };
                    a2 += a2_t * a3;
                    a2_a += a2_t * (n - 1) * a3;
                }

                double tmp_h = a1 * a2, tmp_a = a1_a * a2_a*1e5;
                lock (heights)
                { heights[pointIndex] =tmp_h; }
                lock (anomaly)
                { anomaly[pointIndex] = tmp_a; }
                if (d != null)
                {
                    position++;
                    if  (position > position_p) { lock (locker) { position_p += position_p; }; d.Invoke(position, count, "Обчислено висоти для точок: "); };
                    if (position >= count) { d.Invoke(0, 1, ""); };
                }
            });
                }
            catch (OperationCanceledException)
            {
                return new double[2][];
            }
            return new double[][] { heights, anomaly };
        }
        //Обчислення висот геоїда для сітки (в метрах) формула обчислення нормальної сили ваги "gamma_0_formula" (за замовчуванням ф-ла Сомільяни)
        public static double[] getGeoidHeight(ReferenceSystem rs, GravityModel model, List<double[]> grid, NormalGammaFormula gamma_0_formula = NormalGammaFormula.Somigliana, MainForm.setProgressDel d = null)
        {
            GravityModel gm;
            if (model.model_a != rs.a || model.model_GM != rs.GM) { gm = new GravityModel(model.rescaleModel(rs), rs.a, rs.GM); } else { gm = new GravityModel(model, model.model_a, model.model_GM); };
            gm = getDisturbingModel(rs, gm);
            double[] heights = new double[grid.Count];
            int[][] t_nm = MathFunc.get_nm(gm.maxDegree);
            double[] legendrePolys_old = null; double point_old = double.MinValue; object locker = new object(), locker2 = new object();
            int position = 0;
            int count =grid.Count,position_p=(int)Math.Round(0.01d*count);

               Parallel.For(0, grid.Count, (pointIndex) => {
                double gamma_0 = 0, B = 0, r = 0;
                double[] legendrePolys = null;
                double[] point = grid[pointIndex];
                lock (locker2)
                        {
                            if (point_old != double.MinValue)
                            {
                                if (point[0] == point_old)
                                {
                                legendrePolys = new double[legendrePolys_old.Length];
                                legendrePolys_old.CopyTo(legendrePolys, 0);
                                }
                                MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                                legendrePolys_old = new double[legendrePolys.Length];
                                legendrePolys.CopyTo(legendrePolys_old, 0);
                                point_old = point[0];
                            }
                            else {
                                MathFunc.getLegendre(gm.maxDegree, point[0], out legendrePolys);
                                legendrePolys_old = new double[legendrePolys.Length];
                                legendrePolys.CopyTo(legendrePolys_old,0);
                                point_old = point[0];
                            }
                        }
                B = MathFunc.convertThethaToB(point[0], rs);
                r=MathFunc.getGeocentrDistanceToPointOnElips(rs,B);
                if (gamma_0_formula == NormalGammaFormula.Somigliana)
                {gamma_0 = rs.gamma_a * (1d + rs.k * Math.Pow(Math.Sin(B), 2d)) / Math.Sqrt(1d - rs.firstExcentricity_2 * Math.Pow(Math.Sin(B), 2d));}
                else { gamma_0 = 9.78030d * (1d + 0.005302 * Math.Pow(Math.Sin(B), 2d) - 0.000007 * Math.Pow(Math.Sin(2d * B), 2d)); }
                double a1, a2=0, a3,cosMlambda,sinMlambda;
                a1 = rs.GM / (r * gamma_0);
                for (int n = 0; n < gm.maxDegree; n++) {
                    a3 = 0;
                    for (int m = 0; m <= n; m++){
                        cosMlambda = Math.Cos(m * point[1]);
                        sinMlambda = Math.Sin(m * point[1]);
                        lock (gm)
                        {a3 += (gm.c_coef[n][m] * cosMlambda + gm.s_coef[n][m] * sinMlambda) * legendrePolys[MathFunc.getArraySize(n - 1) + (n - m)];}
                    }
                    a2 += Math.Pow(rs.a / r, n)*a3;
                }
                lock (heights)
                {heights[pointIndex] = a1 * a2;}
                if (d!=null)
                {
                    position++;
                    if (true || position > position_p) { lock (locker) { position_p += position_p;}; d.Invoke(position,count,"Обчислено висоти для точок: ");};
                    if (position >= count) { d.Invoke(0, 1, ""); };
                }
                });
            return heights;
        }