/// <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[] 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); }