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 }); }
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); }
//Обчислення висот геоїда для сітки (в метрах) формула обчислення нормальної сили ваги "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; }