//Формування рядка матриці коефіцієнтів рівнянь поправок public static double[] getCoefMatrixLineKoop(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians) { if (angType == AngleType.Degrees) { deg2rad(ref longitude); } List <double> line = new List <double>((getArraySize(n) - 3) * 2 - (rs.maxDegree - 1)); double[][] legPol = getLegendreP_lm_cos_phi(n, Math.PI / 2d - coLatitude); double u_1 = rs.GM / Math.Pow(rs.a, 3d), u_2 = rs.a / rs.satelliteSphere; for (int l = 2; l <= rs.maxDegree; l++) { double u_3 = u_1 * Math.Pow(u_2, l + 3) * (l + 1) * (l + 2); for (int m = 0; m <= l; m++) { line.Add(u_3 * legPol[l][m] * Math.Cos((double)m * longitude)); if (m != 0) { line.Add(u_3 * legPol[l][m] * Math.Sin((double)m * longitude)); } } } return(line.ToArray()); }
public static string matrixToString(MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dm, ReferenceSystem rs) { StringBuilder sb = new StringBuilder(); int index = 0; for (int i = 0; i < 21; i++) { sb.AppendLine(); } for (int i = 2; i <= rs.maxDegree; i++) { for (int j = 0; j <= i; j++) { if (j != 0) { sb.AppendLine(string.Format("{0}\t{1}\t{2:0.000000000000e+00}\t{3:0.000000000000e+00}", i, j, dm.Values[index], dm.Values[index + 1])); index += 2; } else { sb.AppendLine(string.Format("{0}\t{1}\t{2:0.000000000000e+00}\t{3:0.000000000000e+00}", i, j, dm.Values[index], 0)); index += 1; } } } return sb.ToString(); }
//Обчислення коефіцієнтів збурюючого потенціалу відностно Нормальної Землі "rs" public static GravityModel getDisturbingModel(ReferenceSystem rs, GravityModel model) { GravityModel result = new GravityModel(model, model.model_a, model.model_GM); double[] normalModel = generateNormalModel(rs, 8); for (int i = 0; i < normalModel.Length; i += 2) { result.c_coef[i][0] = result.c_coef[i][0] - normalModel[i]; } return(result); }
//Метод генерує масив з коефіцієнтами моделі нормального потенціалу [1,0,c_20,0,c_40,0,c_80...c_maxDegree0] public static double[] generateNormalModel(ReferenceSystem rs, int maxDegree = 8) { double[] normalModel = new double[maxDegree + 1]; normalModel[0] = 1D; double C_2k = 0, k = 0, tmp = 1d - 2d / 15d * (rs.m_gamma * Math.Sqrt(rs.secondExcentricity_2)) / rs.q0; for (int i = 2; i <= maxDegree; i += 2) { k = i / 2; C_2k = Math.Pow(-1d, k) * 3d * Math.Pow(rs.firstExcentricity_2, k) / ((2d * k + 1d) * (2d * k + 3d)) * (1d - k + 5d * k / 3d * tmp) / Math.Sqrt(2d * i + 1d); normalModel[i - 1] = 0D; normalModel[i] = C_2k; } return(normalModel); }
public static double convertBToThetha(double thetha, ReferenceSystem rs, MathFunc.AngleType angType = MathFunc.AngleType.Radians) { double phi = 0; if (angType == MathFunc.AngleType.Degrees) { phi = deg2rad(90d - thetha); } else { phi = Math.PI / 2d - thetha; }; return(Math.Atan(Math.Tan(phi) * (1d - rs.firstExcentricity_2))); }
/// <summary> /// Конструктор для створення об'єкту ReferenceSystem з параметрами за замовчуванням /// </summary> public ReferenceSystem(ReferenceSystem.Default defaulParams, double satelliteSphere=6500000) { //Система "вільна від припливних чинників" //http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html if (defaulParams == Default.TideFree) { this.GM = 0.3986004415E+15; this.a = 6378136.46; this.f = (double)1 / 298.257686; this.omega = 7292115E-11; this.gridParameters = new Grid(1.6,25); this.maxDegree = 90; this.satelliteSphere = satelliteSphere; mainInit(); } if (defaulParams == Default.ITRF) { this.GM = 3.986004418E14; this.a = 6378136.6; this.f = (double)1 / 298.25642; this.omega = 7292115E-11; this.gridParameters = new Grid(1.6, 25); this.maxDegree = 90; this.satelliteSphere = satelliteSphere; mainInit(); } if (defaulParams == Default.WGS84) { this.GM = 3986004.418E8; this.a = 6378137; this.f = (double)1 / 298.257223563; this.omega = 7292115E-11; this.gridParameters = new Grid(1.6, 25); this.maxDegree = 90; this.satelliteSphere = satelliteSphere; mainInit(); } if (defaulParams == Default.USC2000) { this.GM = 3.986004418E14; this.a = 6378245; this.f = (double)1 / 298.3; this.omega = 7292115E-11; this.gridParameters = new Grid(1.6, 25); this.maxDegree = 90; this.satelliteSphere = satelliteSphere; mainInit(); } }
/// <summary> /// Маштабування моделі для використання з Нормальною Землею "rs" /// </summary> public GravityModel rescaleModel(ReferenceSystem rs) { GravityModel output = new GravityModel(this, rs.a, rs.GM); double rescaleFctor = 1; for (int n = 0; n < this.c_coef.Length; n++) { rescaleFctor = (this.model_GM / rs.GM) * Math.Pow(this.model_a / rs.a, n); for (int m = 0; m < this.c_coef[n].Length; m++) { output.c_coef[n][m] = this.c_coef[n][m] * rescaleFctor; output.s_coef[n][m] = this.s_coef[n][m] * rescaleFctor; } } return(output); }
public static void checkMap(double[][] SGG_data, List<int>[] map, List<double[]> greed, ReferenceSystem el) { Parallel.For(0, map.Length, (i) => { if (map[i].Count > 0) { foreach (int p in map[i]) { double d_phi = greed[i][0] - SGG_data[p][1]; double d_lam = greed[i][1] - SGG_data[p][2]; if (d_phi > MathFunc.deg2rad(el.gridParameters.cellSize) || d_lam > MathFunc.deg2rad(el.gridParameters.cellSize)) { System.Windows.Forms.MessageBox.Show(string.Format("F**k!\r\np{0},l{1}__{2}", MathFunc.rad2deg(d_phi), MathFunc.rad2deg(d_lam),i)); } } }; }); }
/// <summary> /// Визначає, до якої клітинки сітки відноситься кожен результат. Кожен елемент List() відповідає елементу Greed, і є масивом номерів точок з pointsData /// </summary> /// <param name="rs">Референсна система</param> /// <param name="pointsData">Масив точок типу: {radius,coLatitude,Longitude,Gradient}</param> /// <param name="greed">Масив з клітинками сітки типу: {{colat,long},{colat,long},{colat,long}...}</param> /// <param name="rowCount">Кількість рядків сітки</param> /// <param name="colsCount">Кількість стовпчиків сітки</param> /// <returns>Повертає масив з номерами точок з масиву pointsData</returns> public static List <int>[] getMappingOfPoints(ReferenceSystem rs, double[][] pointsData, double[][] greed, int rowCount, int colsCount, double avgRadius) { List <int>[] map = new List <int> [greed.Length]; for (int i = 0; i < map.Length; i++) { map[i] = new List <int>(); } double cellSize = MathFunc.deg2rad(rs.gridParameters.cellSize); double zero = greed[0][0] - cellSize / 2D; double l_zero = greed[0][1] - cellSize / 2d; Parallel.For(0, pointsData.Length, (i) => { double fi, lambda, r; lock (pointsData) { fi = pointsData[i][1]; lambda = pointsData[i][2]; r = pointsData[i][0]; } if (fi >= greed[0][0] && fi <= greed[greed.Length - 1][0] && lambda >= greed[0][1] && lambda <= greed[greed.Length - 1][1] && Math.Abs(r - avgRadius) < 10000d) { fi = fi - (zero); lambda = lambda - l_zero; int n = (int)Math.Floor(fi / cellSize); int m = (int)Math.Floor(lambda / cellSize); int index = (colsCount * n) + m; lock (map) { var x1 = cellSize / 2D - Math.Abs(greed[index][0] - zero - fi); var x2 = cellSize / 2D - Math.Abs(greed[index][1] - l_zero - lambda); if (x1 < 0 || x2 < 0) { System.Windows.Forms.MessageBox.Show("getMappingOfPoints: неправильна визначена клітинка точки " + i.ToString()); } else { map[index].Add(i); } } } ; }); return(map); }
/// <summary> /// Генерує об'єкт GravityModel з коефіцієнтами Нормальної Землі "rs" /// </summary> public static GravityModel getNormalModel(ReferenceSystem rs, int maxDegree = 8) { double[] m = generateNormalModel(rs, maxDegree); GravityModel gm = new GravityModel(maxDegree); gm.model_a = rs.a; gm.model_GM = rs.GM; for (int i = 0; i < m.Length; i++) { gm.c_coef[i] = new double[i + 1]; gm.s_coef[i] = new double[i + 1]; gm.c_coef[i][0] = m[i]; i++; if (i < gm.c_coef.Length) { gm.c_coef[i] = new double[i + 1]; gm.s_coef[i] = new double[i + 1]; } } return(gm); }
/// <summary> /// Обчислює масив з коефіцієнтами рядка в матриці /// </summary> /// <param name="rs">Еліпсоїд</param> /// <param name="n">Порядок розвинення</param> /// <param name="r">Радіус сфери, до якої віднесені виміри</param> /// <param name="coLatitude">Полярний кут tetha = 90deg-phi</param> /// <param name="longitude">Довгота</param> /// <param name="angType">Одиниці, в яких задано попередні кути</param> /// <returns></returns> public static double[] getCoefMatrixLine(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians) { if (angType == AngleType.Degrees) { deg2rad(ref longitude); } double[] line = new double[(getArraySize(n) - 3) * 2 - (rs.maxDegree - 1)]; double u_1 = rs.GM / (Math.Pow(rs.a, 3d)); double[] legPol = null; getLegendre(n, coLatitude, out legPol, angType); double tmp_n = 0; double tmp_m = 0; int lineIndex = 0; for (int i = 0; i <= legPol.Length; i++) { if (i < 4) { continue; } tmp_n = t_nm[i - 1][0]; tmp_m = t_nm[i - 1][1]; double b = legPol[getArraySize(t_nm[i - 1][0] - 1) + t_nm[i - 1][0] - t_nm[i - 1][1]]; double a = (tmp_n + 1D) * (tmp_n + 2D) * Math.Pow(rs.a / rs.satelliteSphere, (double)tmp_n + 3d) * u_1; double a1 = a * Math.Cos(tmp_m * longitude); line[lineIndex] = a1 * b; if (tmp_m > 0) { double a2 = a * Math.Sin(tmp_m * longitude); line[lineIndex + 1] = a2 * b; lineIndex += 2; } else { lineIndex++; } } return(line); }
/// <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); }
/// <summary> /// Обчислення градієнту V_zz для сітки "grid" /// </summary> public double[] getGradientForGrid(ReferenceSystem rs, List <double[]> grid) { GravityModel gm; if (this.model_a != rs.a || this.model_GM != rs.GM) { gm = this.rescaleModel(rs); } else { gm = this; }; double[] Gradients = new double[grid.Count]; int progress = 0; Parallel.For(0, grid.Count, (i) => { lock (Gradients){ Gradients[i] = getGradient(rs, gm, grid[i][0], grid[i][1]); progress++; } }); return(Gradients); }
public static void writeModeVectorlToTxtFile(MathNet.Numerics.LinearAlgebra.Double.DenseVector dm, ReferenceSystem rs, string file) { System.IO.File.WriteAllText(file, matrixToString((MathNet.Numerics.LinearAlgebra.Double.DenseMatrix)dm.ToColumnMatrix(), rs), System.Text.Encoding.Default); }
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 }); }
/// <summary> /// Генерує об'єкт GravityModel з коефіцієнтами Нормальної Землі "rs" /// </summary> public static GravityModel getNormalModel(ReferenceSystem rs, int maxDegree = 8) { double[] m = generateNormalModel(rs, maxDegree); GravityModel gm = new GravityModel(maxDegree); gm.model_a = rs.a; gm.model_GM = rs.GM; for (int i = 0; i < m.Length; i ++) { gm.c_coef[i]=new double[i+1]; gm.s_coef[i] = new double[i + 1]; gm.c_coef[i][0] = m[i]; i++; if (i < gm.c_coef.Length) { gm.c_coef[i] = new double[i + 1]; gm.s_coef[i] = new double[i + 1]; }} return gm; }
private void обчисленняЗаВихідноюМоделлюToolStripMenuItem_Click(object sender, EventArgs e) { tabControl1.SelectedTab = tabControl1.TabPages[1]; this.Refresh(); var task = Task.Factory.StartNew(() => { addText("Обчислення розпочато...\r\n"); string file = SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel; GravityModel gm = new GravityModel(SphericalHarmonicAnalyze.Properties.Settings.Default.modelMaxOrder); gm.loadFromFile(SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel, new setProgressDel(addVal)); ReferenceSystem elipsoid = new ReferenceSystem(ReferenceSystem.Default.WGS84); elipsoid.gridParameters.cellSize = SphericalHarmonicAnalyze.Properties.Settings.Default.GridCellSize; elipsoid.gridParameters.coLatitudeBounds = SphericalHarmonicAnalyze.Properties.Settings.Default.minCoLatitude; elipsoid.maxDegree = SphericalHarmonicAnalyze.Properties.Settings.Default.modelMaxOrder; int greedColumnsCount, greedRowsCount; List<double[]> greed = MathFunc.generateGrid(elipsoid.gridParameters.cellSize, out greedColumnsCount, out greedRowsCount, elipsoid.gridParameters.coLatitudeBounds); double[] h = GravityModel.getGeoidHeight(elipsoid, gm, greed); double[] dg = GravityModel.getAnomaly(elipsoid, gm, greed); IOFunc.writeGeoidHeightsAndAnomalysToTxt(greed, h, dg, elipsoid, file + "B_L_N_dg.txt"); addText("Готово...\r\nРезультати записано в файл: " + file + "B_L_N_dg.txt"); }); }
/// <summary> /// Обчислює масив з коефіцієнтами рядка в матриці /// </summary> /// <param name="rs">Еліпсоїд</param> /// <param name="n">Порядок розвинення</param> /// <param name="r">Радіус сфери, до якої віднесені виміри</param> /// <param name="coLatitude">Полярний кут tetha = 90deg-phi</param> /// <param name="longitude">Довгота</param> /// <param name="angType">Одиниці, в яких задано попередні кути</param> /// <returns></returns> public static double[] getCoefMatrixLine(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians) { if (angType == AngleType.Degrees) { deg2rad(ref longitude); } double[] line = new double[(getArraySize(n) - 3) * 2-(rs.maxDegree-1)]; double u_1 = rs.GM / (Math.Pow(rs.a, 3d)); double[] legPol = null; getLegendre(n, coLatitude, out legPol, angType); double tmp_n = 0; double tmp_m = 0; int lineIndex = 0; for (int i = 0; i <= legPol.Length; i++) { if (i < 4) { continue; } tmp_n = t_nm[i-1][0]; tmp_m = t_nm[i-1][1]; double b = legPol[getArraySize(t_nm[i - 1][0] - 1) + t_nm[i - 1][0] - t_nm[i - 1][1]]; double a = (tmp_n + 1D) * (tmp_n + 2D) * Math.Pow(rs.a / rs.satelliteSphere, (double)tmp_n + 3d)*u_1; double a1 = a * Math.Cos(tmp_m * longitude); line[lineIndex] = a1 * b; if (tmp_m > 0) { double a2 = a * Math.Sin(tmp_m * longitude); line[lineIndex + 1] = a2 * b; lineIndex += 2; } else { lineIndex++; } } return line; }
//Формування рядка матриці коефіцієнтів рівнянь поправок public static double[] getCoefMatrixLineKoop(ReferenceSystem rs, int n, int[][] t_nm, double r, double coLatitude, double longitude, MathFunc.AngleType angType = AngleType.Radians) { if (angType == AngleType.Degrees) { deg2rad(ref longitude); } List<double> line = new List<double>((getArraySize(n) - 3) * 2 - (rs.maxDegree - 1)); double[][] legPol = getLegendreP_lm_cos_phi(n, Math.PI / 2d - coLatitude); double u_1 = rs.GM / Math.Pow(rs.a, 3d), u_2 = rs.a / rs.satelliteSphere; for (int l = 2; l <= rs.maxDegree; l++) { double u_3 = u_1 * Math.Pow(u_2, l + 3)*(l+1)*(l+2); for (int m = 0; m <= l; m++) { line.Add(u_3 * legPol[l][m] * Math.Cos((double)m * longitude)); if (m != 0) { line.Add(u_3 * legPol[l][m] * Math.Sin((double)m * longitude)); } } } return line.ToArray(); }
public static double getGeocentrDistanceToPointOnElips(ReferenceSystem rs, double B) { return (rs.a * Math.Sqrt((1d - rs.firstExcentricity_2) / (1d - Math.Pow(Math.Sqrt(rs.firstExcentricity_2) * Math.Sin(B), 2d)))); }
public static string matrixToString(MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dm, ReferenceSystem rs) { StringBuilder sb = new StringBuilder(); int index = 0; for (int i = 0; i < 21; i++) { sb.AppendLine(); } for (int i = 2; i <= rs.maxDegree; i++) { for (int j = 0; j <= i; j++) { if (j != 0) { sb.AppendLine(string.Format("{0}\t{1}\t{2:0.000000000000e+00}\t{3:0.000000000000e+00}", i, j, dm.Values[index], dm.Values[index + 1])); index += 2; } else { sb.AppendLine(string.Format("{0}\t{1}\t{2:0.000000000000e+00}\t{3:0.000000000000e+00}", i, j, dm.Values[index], 0)); index += 1; } } } return(sb.ToString()); }
/// <summary> /// Визначає, до якої клітинки сітки відноситься кожен результат. Кожен елемент List() відповідає елементу Greed, і є масивом номерів точок з pointsData /// </summary> /// <param name="rs">Референсна система</param> /// <param name="pointsData">Масив точок типу: {radius,coLatitude,Longitude,Gradient}</param> /// <param name="greed">Масив з клітинками сітки типу: {{colat,long},{colat,long},{colat,long}...}</param> /// <param name="rowCount">Кількість рядків сітки</param> /// <param name="colsCount">Кількість стовпчиків сітки</param> /// <returns>Повертає масив з номерами точок з масиву pointsData</returns> public static List<int>[] getMappingOfPoints(ReferenceSystem rs, double[][] pointsData, double[][] greed, int rowCount, int colsCount, double avgRadius) { List<int>[] map = new List<int>[greed.Length]; for (int i = 0; i < map.Length; i++) { map[i] = new List<int>(); } double cellSize = MathFunc.deg2rad(rs.gridParameters.cellSize); double zero = greed[0][0] - cellSize / 2D; double l_zero = greed[0][1] - cellSize / 2d; Parallel.For(0, pointsData.Length, (i) => { double fi,lambda,r; lock (pointsData) { fi = pointsData[i][1]; lambda = pointsData[i][2]; r = pointsData[i][0]; } if (fi >= greed[0][0] && fi <= greed[greed.Length-1][0] && lambda >= greed[0][1] && lambda<=greed[greed.Length-1][1] && Math.Abs(r-avgRadius)<10000d) { fi = fi - (zero); lambda = lambda - l_zero; int n = (int)Math.Floor(fi / cellSize); int m = (int)Math.Floor(lambda / cellSize); int index = (colsCount * n) + m; lock (map) { var x1 =cellSize/2D-Math.Abs(greed[index][0]-zero - fi); var x2 = cellSize / 2D - Math.Abs(greed[index][1]-l_zero - lambda); if (x1 < 0 || x2 < 0) { System.Windows.Forms.MessageBox.Show("getMappingOfPoints: неправильна визначена клітинка точки "+ i.ToString()); } else { map[index].Add(i); } } }; }); return map; }
public static double convertThethaToB(double thetha, ReferenceSystem rs, MathFunc.AngleType angType = MathFunc.AngleType.Radians) { double phi = 0; if (angType == MathFunc.AngleType.Degrees) { phi = deg2rad(90d - thetha); } else { phi = Math.PI / 2d - thetha; }; return (Math.Atan(Math.Tan(phi) / (1d - rs.firstExcentricity_2))); }
/// <summary> /// Обчислення градієнту V_zz для сітки "grid" /// </summary> public double[] getGradientForGrid(ReferenceSystem rs, List<double[]> grid) { GravityModel gm; if (this.model_a != rs.a || this.model_GM != rs.GM) { gm = this.rescaleModel(rs); } else { gm = this; }; double[] Gradients = new double[grid.Count]; int progress = 0; Parallel.For(0, grid.Count, (i) => { lock (Gradients){ Gradients[i] = getGradient(rs,gm, grid[i][0], grid[i][1]); progress++; } }); return Gradients; }
//Запис висот геоїда і аномалій для сітки в текстовий файл public static void writeGeoidHeightsAndAnomalysToTxt(List <double[]> greed, double[] heights, double[] anomalies, ReferenceSystem rs, string file) { System.IO.TextWriter w = new System.IO.StreamWriter(file, false); for (int i = 0; i < greed.Count; i++) { w.WriteLine(string.Format("{0} {1} {2,10:0.0000} {3,10:0.0000}", MathFunc.rad2deg(MathFunc.convertThethaToB(greed[i][0], rs)), MathFunc.rad2deg(greed[i][1]), heights[i], anomalies[i])); } w.Close(); }
//Обчислення висот геоїда для сітки (в метрах) формула обчислення нормальної сили ваги "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; }
public static double getGeocentrDistanceToPointOnElips(ReferenceSystem rs, double B) { return(rs.a * Math.Sqrt((1d - rs.firstExcentricity_2) / (1d - Math.Pow(Math.Sqrt(rs.firstExcentricity_2) * Math.Sin(B), 2d)))); }
private void button8_Click(object sender, EventArgs e) { ts2 = new CancellationTokenSource(); ct2 = ts2.Token; ct_p = ts_p.Token; tabControl1.SelectedTab = tabControl1.TabPages[1]; this.Refresh(); ReferenceSystem.Default def = (ReferenceSystem.Default)listBox1.SelectedItem; відмінитиПоточнуОпераціюToolStripMenuItem.Enabled = true; var task = Task.Factory.StartNew(() => { addText("Обчислення розпочато...\r\n"); string file = SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel; GravityModel gm = new GravityModel(SphericalHarmonicAnalyze.Properties.Settings.Default.modelMaxOrder); gm.loadFromFile(SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel, new setProgressDel(addVal)); ReferenceSystem elipsoid = new ReferenceSystem(def); elipsoid.gridParameters.cellSize = SphericalHarmonicAnalyze.Properties.Settings.Default.GridCellSize; elipsoid.gridParameters.coLatitudeBounds = SphericalHarmonicAnalyze.Properties.Settings.Default.minCoLatitude; elipsoid.maxDegree = SphericalHarmonicAnalyze.Properties.Settings.Default.modelMaxOrder; int greedColumnsCount, greedRowsCount; List<double[]> greed = MathFunc.generateGrid(elipsoid.gridParameters.cellSize, out greedColumnsCount, out greedRowsCount, SphericalHarmonicAnalyze.Properties.Settings.Default.minCoLatitude, SphericalHarmonicAnalyze.Properties.Settings.Default.maxCoLatitude, SphericalHarmonicAnalyze.Properties.Settings.Default.longW, SphericalHarmonicAnalyze.Properties.Settings.Default.longE); addText("Колонок: {0}\r\n",greed.Count); double[][] h_dg = GravityModel.getGeoidHeightAndAnomalys(elipsoid, gm, greed, d: new setProgressDel(addVal),ct: ct2,ct2:ct_p); if (ct2.IsCancellationRequested) { addText("Перервано...\r\n"); addVal(0,1,""); Thread.CurrentThread.Abort(); }; addText("dg обчислено\r\n"); IOFunc.writeGeoidHeightsAndAnomalysToTxt(greed, h_dg[0], h_dg[1], elipsoid, file + "B_L_N_dg.txt"); addText("Готово...\r\nРезультати записано в файл: " + file + "NEW____________B_L_N_dg.txt\r\n"); },ct2); var t3 = Task.Factory.StartNew(() => { label1: if (task.IsCompleted) { if (checkBox1.Checked) { System.Diagnostics.Process.Start("rundll32.exe", "powrprof.dll,SetSuspendState 0,1,0"); }; } else { task.Wait(); goto label1; } }); }
/// <summary> /// Маштабування моделі для використання з Нормальною Землею "rs" /// </summary> public GravityModel rescaleModel(ReferenceSystem rs) { GravityModel output = new GravityModel(this, rs.a, rs.GM); double rescaleFctor = 1; for (int n = 0; n < this.c_coef.Length; n++) { rescaleFctor = (this.model_GM / rs.GM) * Math.Pow(this.model_a / rs.a, n); for (int m = 0; m < this.c_coef[n].Length; m++) { output.c_coef[n][m] = this.c_coef[n][m] * rescaleFctor; output.s_coef[n][m] = this.s_coef[n][m] * rescaleFctor; } } return output; }
private void button4_Click(object sender, EventArgs e) { Action fileProc = () => { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); MathNet.Numerics.Control.LinearAlgebraProvider = new MathNet.Numerics.Algorithms.LinearAlgebra.Mkl.MklLinearAlgebraProvider(); MathNet.Numerics.Control.NumberOfParallelWorkerThreads = Environment.ProcessorCount; addText("Обробка файлу вимірювань...\r\n"); double[][] SGG_data = null; if (System.IO.File.Exists("sgg_data.bin")) { SGG_data = IOFunc.binLoad_SGG_data("sgg_data.bin"); } else { SGG_data = Data.IOFunc.read_SGG_data(SphericalHarmonicAnalyze.Properties.Settings.Default.SGG_measures, new setProgressDel(addVal)); IOFunc.binwrite_SGG_data("sgg_data.bin", SGG_data); } addText("Дані вимірювань оброблено: {0} шт.\r\n", SGG_data.Length); Thread.Sleep(500); ReferenceSystem elipsoid = new ReferenceSystem(ReferenceSystem.Default.TideFree); elipsoid.gridParameters.cellSize = SphericalHarmonicAnalyze.Properties.Settings.Default.GridCellSize; elipsoid.gridParameters.coLatitudeBounds = SphericalHarmonicAnalyze.Properties.Settings.Default.minCoLatitude; elipsoid.maxDegree = SphericalHarmonicAnalyze.Properties.Settings.Default.modelMaxOrder; int greedColumnsCount, greedRowsCount; List<double[]> greed = MathFunc.generateGrid(elipsoid.gridParameters.cellSize, out greedColumnsCount, out greedRowsCount, elipsoid.gridParameters.coLatitudeBounds,180 - elipsoid.gridParameters.coLatitudeBounds); addText("Сітку згенеровано: {0} комірок \r\n", greed.Count); double avgR = MathFunc.getAvgRadius(SGG_data); List<int>[] map = MathFunc.getMappingOfPoints(elipsoid, SGG_data, greed.ToArray(), greedRowsCount, greedColumnsCount, avgR); sw.Stop(); addText("Точки віднесено до комірок сітки за: {0}.\r\n", sw.Elapsed.ToString()); addText("Кількість клітинок сітки всього: {0}\r\n", greed.Count); int res1 = 0; foreach (var item in map) { res1 += item.Count; } addText("Використано вимірів: {0}\r\nСер радіус: {1}\r\n", res1, avgR); test.checkMap(SGG_data, map, greed, elipsoid); List<int>[] newMap = null; MathFunc.checkGreed(ref greed, map, out newMap); addText("Кількість клітинок сітки, в яких присутні дані вимірювань: {0}\r\n", greed.Count); map = newMap; newMap = null; IOFunc.writeGreedToCsvFileWithMeasureCount(greed, map, "greed_new_map.txt"); double[] avgRadius; sw.Restart(); double[] regularisedValues = MathFunc.regularization(SGG_data, greed.ToArray(), map, out avgRadius); sw.Stop(); addText("Регуляризація (на основі сферичної відстані) виконана за: {0}.\r\n", sw.Elapsed.ToString()); IOFunc.writeGreedToCsvFileWithMeasureS(greed,regularisedValues, "greed_regular_grad.txt"); avgRadius[0] = Math.Round(avgRadius[0]); elipsoid.satelliteSphere = avgRadius[0]; addText("Середній радіус: {0,10:0.000}.\r\nМінімальний радіус: {1,10:0.0000}\r\nМаксимальний радіус:{2,10:0.0000}\r\n", avgRadius[0], avgRadius[1], avgRadius[2]); SGG_data = null; map = null; int[][] t_nm = MathFunc.get_nm(elipsoid.maxDegree); sw.Restart(); MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dm = new MathNet.Numerics.LinearAlgebra.Double.DenseMatrix(greed.Count, (MathFunc.getArraySize(elipsoid.maxDegree) - 3) * 2 - (elipsoid.maxDegree-1)); sw.Stop(); addText("Пам'ять для матриці коефіцієнтів виділено за: {0}.\r\n", sw.Elapsed.ToString()); sw.Restart(); int progress = 0; //Обчислення елементів матриці var p= Parallel.For(0, dm.RowCount, (i) => { double[] line = MathFunc.getCoefMatrixLineKoop(elipsoid, elipsoid.maxDegree, t_nm, elipsoid.satelliteSphere, greed[i][0], greed[i][1]); lock (dm) { dm.SetRow(i,line); } progress++; if (progress / 100D == Math.Round(progress / 100D)) {addVal(progress, dm.RowCount, "Визначено");} }); if (!p.IsCompleted) { throw new Exception("Parallel.For"); }; IOFunc.writeMatrixToMatLabFile(dm, @"matlab\A.mat","A"); sw.Stop(); richTextBox1.Invoke(new setProgressDel(addVal), new object[] { 0, dm.RowCount, "" }); addText("Матриця {0} на {1} ({2}MB) згенерована за: {3,10}\r\n", dm.RowCount, dm.ColumnCount, dm.ColumnCount * dm.RowCount * 8 / 1000000,sw.Elapsed.ToString()/* + "\r\nЗапис у файл...\r\n"*/); if(true){ GravityModel gm08 = new GravityModel(elipsoid.maxDegree); gm08.loadFromFile("GO_CONS_EGM_GCF_2.gfc", new setProgressDel(addVal)); MathNet.Numerics.LinearAlgebra.Double.DenseVector dmL = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(gm08.getGradientForGrid(elipsoid,greed));//regularisedValues); MathNet.Numerics.LinearAlgebra.Double.DenseVector dmL2; GravityModel gm = new GravityModel(elipsoid.maxDegree); if (radioButton1.Checked) { sw.Restart(); gm.loadFromFile(SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel, new setProgressDel(addVal)); sw.Stop(); addText("Вихідна модель завантажена за: {0}.\r\n", sw.Elapsed.ToString()); sw.Restart(); dmL2 = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(gm.getGradientForGrid(elipsoid,greed)); sw.Stop(); addText("Градієнти за вихідною моделлю обчислені для сітки за: {0}.\r\n", sw.Elapsed.ToString()); } else { sw.Restart(); gm = GravityModel.getNormalModel(elipsoid, elipsoid.maxDegree); dmL2 = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(gm.getGradientForGrid(elipsoid, greed)); sw.Stop(); addText("Нормальні градієнти обчислені для сітки за: {0}.\r\n", sw.Elapsed.ToString()); } dmL = dmL - dmL2; dmL2 = null; IOFunc.writeMatrixToMatLabFile(dmL.ToColumnMatrix(), @"matlab\L.mat", "L"); sw.Restart(); MathNet.Numerics.LinearAlgebra.Double.DenseVector dmLNormal = null; dmLNormal = (MathNet.Numerics.LinearAlgebra.Double.DenseVector)dm.TransposeThisAndMultiply(dmL); dmL = null; IOFunc.writeMatrixToMatLabFile(dmLNormal.ToColumnMatrix(), @"matlab\LNorm.mat", "LNorm"); sw.Stop(); addText("Стовпчик вільних членів обчислений за: {0}.\r\n", sw.Elapsed.ToString()); MathNet.Numerics.LinearAlgebra.Double.DenseMatrix dmANorm = null; sw.Restart(); dmANorm = (MathNet.Numerics.LinearAlgebra.Double.DenseMatrix)dm.TransposeThisAndMultiply(dm); dm = null; sw.Stop(); addText("Нормальна матриця коефіціэнтів обчислена за: {0}.\r\n", sw.Elapsed.ToString()); IOFunc.writeMatrixToMatLabFile(dmANorm, @"matlab\ANorm.mat", "ANorm"); //dmLNormal = (MathNet.Numerics.LinearAlgebra.Double.DenseVector)dmLNormal.Multiply(5e-8); var x = dmANorm.Inverse(); var res = (MathNet.Numerics.LinearAlgebra.Double.DenseVector)x.Multiply(dmLNormal); IOFunc.writeModeVectorlToTxtFile(res, elipsoid, @"matlab\_out.AL"); addText(@"Результат за методом A\L знайдено..."); x = null; GravityModel gm_R = new GravityModel(gm); gm_R.addDeltaCoef(res.ToArray()); res = null; double[] h = GravityModel.getGeoidHeight(elipsoid, gm_R, greed); double[] dg = GravityModel.getAnomaly(elipsoid, gm_R, greed); IOFunc.writeGeoidHeightsAndAnomalysToTxt(greed, h, dg, elipsoid, @"output\result_AL.txt"); IOFunc.writeGravityModelToTxtFile(gm_R, @"output\model_AL.gcf"); sw.Restart(); addText(dmANorm.Rank().ToString() + "\r\n"); dmANorm = null; dmLNormal = null; sw.Stop(); addText("Невідомі знайдено за: {0}.\r\n", sw.Elapsed.ToString()); } }; if (System.IO.File.Exists(SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel)) { tabControl1.SelectedTab = tabControl1.TabPages[1]; this.UseWaitCursor = true; ts = new CancellationTokenSource(); ct = ts.Token; tsk = Task.Factory.StartNew(fileProc,ct); var setCur = Task.Factory.StartNew(() => { tsk.Wait(); this.UseWaitCursor = false; addText("Обчислення завершені!"); }); richTextBox1.SaveFile(@"output\zvit.rtf"); } }
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 }; }
private void toolStripButton2_Click(object sender, EventArgs e) { ReferenceSystem elipsoid = new ReferenceSystem(ReferenceSystem.Default.WGS84); elipsoid.gridParameters.cellSize = 30d; elipsoid.gridParameters.coLatitudeBounds = 15D; elipsoid.maxDegree = 100; double[] gmN = GravityModel.generateNormalModel(elipsoid, 10); GravityModel gm = new GravityModel(100); gm.loadFromFile(SphericalHarmonicAnalyze.Properties.Settings.Default.inGravityModel, new setProgressDel(addVal)); int greedColumnsCount, greedRowsCount; GravityModel gm2 = new GravityModel(gm); List<double[]> greed = MathFunc.generateGrid(elipsoid.gridParameters.cellSize, out greedColumnsCount, out greedRowsCount, elipsoid.gridParameters.coLatitudeBounds); double[] h = GravityModel.getGeoidHeight(elipsoid,gm2,greed); double[] dg = GravityModel.getAnomaly(elipsoid, gm, greed); IOFunc.writeGeoidHeightsAndAnomalysToTxt(greed, h, dg, elipsoid, "result.txt"); }
//Обчислення коефіцієнтів збурюючого потенціалу відностно Нормальної Землі "rs" public static GravityModel getDisturbingModel(ReferenceSystem rs, GravityModel model) { GravityModel result = new GravityModel(model, model.model_a, model.model_GM); double[] normalModel = generateNormalModel(rs,8); for (int i = 0; i < normalModel.Length; i+=2) {result.c_coef[i][0] = result.c_coef[i][0] - normalModel[i];} return result; }
//Запис висот геоїда і аномалій для сітки в текстовий файл public static void writeGeoidHeightsAndAnomalysToTxt(List<double[]> greed, double[] heights, double[] anomalies,ReferenceSystem rs, string file) { System.IO.TextWriter w = new System.IO.StreamWriter(file, false); for (int i = 0; i < greed.Count; i++) { w.WriteLine(string.Format("{0} {1} {2,10:0.0000} {3,10:0.0000}",MathFunc.rad2deg(MathFunc.convertThethaToB(greed[i][0], rs)),MathFunc.rad2deg(greed[i][1]), heights[i], anomalies[i])); } w.Close(); }
//Обчислення аномалій сили ваги для сітки (в мГал) 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); }
//Метод генерує масив з коефіцієнтами моделі нормального потенціалу [1,0,c_20,0,c_40,0,c_80...c_maxDegree0] public static double[] generateNormalModel(ReferenceSystem rs, int maxDegree = 8) { double[] normalModel = new double[maxDegree + 1]; normalModel[0] = 1D; double C_2k = 0, k = 0, tmp = 1d - 2d / 15d * (rs.m_gamma * Math.Sqrt(rs.secondExcentricity_2)) / rs.q0; for (int i = 2; i <= maxDegree; i += 2) { k = i / 2; C_2k = Math.Pow(-1d, k) * 3d * Math.Pow(rs.firstExcentricity_2, k) / ((2d * k + 1d) * (2d * k + 3d)) * (1d - k + 5d * k / 3d * tmp) / Math.Sqrt(2d * i + 1d); normalModel[i - 1] = 0D; normalModel[i] = C_2k; } return normalModel; }
/// <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; }