/// <summary> /// Evaluate the components of the gravity anomaly vector using the spherical approximation. /// </summary> /// <param name="lat">the geographic latitude (degrees).</param> /// <param name="lon">the geographic longitude (degrees).</param> /// <param name="h">the height above the ellipsoid (meters).</param> /// <returns> /// <list type="bullet"> /// <item><i>Dg01</i>, the gravity anomaly (m s^−2).</item> /// <item><i>xi</i>, the northerly component of the deflection of the vertical (degrees).</item> /// <item><i>eta</i>, the easterly component of the deflection of the vertical (degrees).</item> /// </list> /// </returns> /// <remarks> /// The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used so that the results of /// the NGA codes are reproduced accurately. approximations used here. /// Details are given in /// <a href="https://geographiclib.sourceforge.io/html/gravity.html#gravitygeoid">Details of the geoid height and anomaly calculations</a>. /// </remarks> public (double Dg01, double xi, double eta) SphericalAnomaly(double lat, double lon, double h) { Span <double> M = stackalloc double[Geocentric.dim2_]; var(X, Y, Z) = _earth.Earth.IntForward(lat, lon, h, M); double T = InternalT(X, Y, Z, out var deltax, out var deltay, out var deltaz, true, false), clam = M[3], slam = -M[0], P = Hypot(X, Y), R = Hypot(P, Z), // psi is geocentric latitude cpsi = R != 0 ? P / R : M[7], spsi = R != 0 ? Z / R : M[8]; // Rotate cartesian into spherical coordinates Span <double> MC = stackalloc double[Geocentric.dim2_]; Geocentric.Rotation(spsi, cpsi, slam, clam, MC); Geocentric.Unrotate(MC, deltax, deltay, deltaz, out deltax, out deltay, out deltaz); // H+M, Eq 2-151c var Dg01 = -deltaz - 2 * T / R; var(_, gammaX, gammaY, gammaZ) = _earth.U(X, Y, Z); var gamma = Hypot(Hypot(gammaX, gammaY), gammaZ); var xi = -(deltay / gamma) / Degree; var eta = -(deltax / gamma) / Degree; return(Dg01, xi, eta); }
/// <summary> /// Evaluate the gravity at an arbitrary point above (or below) the ellipsoid. /// </summary> /// <param name="lat">the geographic latitude (degrees).</param> /// <param name="lon">the geographic longitude (degrees).</param> /// <param name="h">the height above the ellipsoid (meters).</param> /// <returns> /// <list type="bullet"> /// <item><i>W</i>, the sum of the gravitational and centrifugal potentials (m^2 s^−2).</item> /// <item><i>gx</i>, the easterly component of the acceleration (m s^−2).</item> /// <item><i>gy</i>, the northerly component of the acceleration (m s^−2).</item> /// <item><i>gz</i>, the upward component of the acceleration (m s^−2); this is usually negative.</item> /// </list> /// </returns> /// <remarks> /// The function includes the effects of the earth's rotation. /// </remarks> public (double W, double gx, double gy, double gz) Gravity(double lat, double lon, double h) { Span <double> M = stackalloc double[Geocentric.dim2_]; var(X, Y, Z) = _earth.Earth.IntForward(lat, lon, h, M); var(Wres, gx, gy, gz) = W(X, Y, Z); Geocentric.Unrotate(M, gx, gy, gz, out gx, out gy, out gz); return(Wres, gx, gy, gz); }
/// <summary> /// Evaluate the gravity disturbance vector at an arbitrary point above (or below) the ellipsoid. /// </summary> /// <param name="lat">the geographic latitude (degrees).</param> /// <param name="lon">the geographic longitude (degrees).</param> /// <param name="h">the height above the ellipsoid (meters).</param> /// <returns> /// <list type="bullet"> /// <item><i>T</i>, the corresponding disturbing potential (m2 s−2).</item> /// <item><i>deltax</i>, the easterly component of the disturbance vector (m s^−2).</item> /// <item><i>deltay</i>, the northerly component of the disturbance vector (m s^−2).</item> /// <item><i>deltaz</i>, the upward component of the disturbance vector (m s^−2).</item> /// </list> /// </returns> public (double T, double deltax, double deltay, double deltaz) Disturbance(double lat, double lon, double h) { Span <double> M = stackalloc double[Geocentric.dim2_]; var(X, Y, Z) = _earth.Earth.IntForward(lat, lon, h, M); var Tres = InternalT(X, Y, Z, out var deltax, out var deltay, out var deltaz, true, true); Geocentric.Unrotate(M, deltax, deltay, deltaz, out deltax, out deltay, out deltaz); return(Tres, deltax, deltay, deltaz); }
/// <summary> /// Evaluate the gravity. /// </summary> /// <param name="lon">the geographic longitude (degrees).</param> /// <returns> /// <list type="bullet"> /// <item><i>W</i>, the sum of the gravitational and centrifugal potentials (m^2 s^−2).</item> /// <item><i>gx</i>, the easterly component of the acceleration (m s^−2).</item> /// <item><i>gy</i>, the northerly component of the acceleration (m s^−2).</item> /// <item><i>gz</i>, the upward component of the acceleration (m s^−2); this is usually negative.</item> /// </list> /// </returns> /// <remarks>The function includes the effects of the earth's rotation.</remarks> public (double W, double gx, double gy, double gz) Gravity(double lon) { Span <double> M = stackalloc double[Geocentric.dim2_]; SinCosd(lon, out var slam, out var clam); var(Wres, gx, gy, gz) = W(slam, clam); Geocentric.Rotation(_sphi, _cphi, slam, clam, M); Geocentric.Unrotate(M, gx, gy, gz, out gx, out gy, out gz); return(Wres, gx, gy, gz); }
/// <summary> /// Evaluate the gravity disturbance vector. /// </summary> /// <param name="lon">the geographic longitude (degrees).</param> /// <returns> /// <list type="bullet"> /// <item><i>T</i>, the corresponding disturbing potential (m2 s−2).</item> /// <item><i>deltax</i>, the easterly component of the disturbance vector (m s^−2).</item> /// <item><i>deltay</i>, the northerly component of the disturbance vector (m s^−2).</item> /// <item><i>deltaz</i>, the upward component of the disturbance vector (m s^−2).</item> /// </list> /// </returns> public (double T, double deltax, double deltay, double deltaz) Disturbance(double lon) { Span <double> M = stackalloc double[Geocentric.dim2_]; SinCosd(lon, out var slam, out var clam); var Tres = InternalT(slam, clam, out var deltax, out var deltay, out var deltaz, true, true); Geocentric.Rotation(_sphi, _cphi, slam, clam, M); Geocentric.Unrotate(M, deltax, deltay, deltaz, out deltax, out deltay, out deltaz); return(Tres, deltax, deltay, deltaz); }
private (double Bx, double By, double Bz) Field(double t, double lat, double lon, double h, bool diffp, out double Bxt, out double Byt, out double Bzt) { Bxt = Byt = Bzt = default; Span <double> M = stackalloc double[Geocentric.dim2_]; var(X, Y, Z) = _earth.IntForward(lat, lon, h, M); // Components in geocentric basis // initial values to suppress warning var(BX, BY, BZ) = FieldGeocentric(t, X, Y, Z, out var BXt, out var BYt, out var BZt); if (diffp) { Geocentric.Unrotate(M, BXt, BYt, BZt, out Bxt, out Byt, out Bzt); } Geocentric.Unrotate(M, BX, BY, BZ, out var Bx, out var By, out var Bz); return(Bx, By, Bz); }
private (double Bx, double By, double Bz) Field(double lon, bool diffp, out double Bxt, out double Byt, out double Bzt) { Bxt = Byt = Bzt = default; SinCosd(lon, out var slam, out var clam); Span <double> M = stackalloc double[Geocentric.dim2_]; Geocentric.Rotation(_sphi, _cphi, slam, clam, M); var(BX, BY, BZ) = FieldGeocentric(slam, clam, out var BXt, out var BYt, out var BZt); if (diffp) { Geocentric.Unrotate(M, BXt, BYt, BZt, out Bxt, out Byt, out Bzt); } Geocentric.Unrotate(M, BX, BY, BZ, out var Bx, out var By, out var Bz); return(Bx, By, Bz); }
/// <summary> /// Evaluate the components of the gravity anomaly vector using the spherical approximation. /// </summary> /// <param name="lon">the geographic longitude (degrees).</param> w /// <returns> /// <list type="bullet"> /// <item><i>Dg01</i>, the gravity anomaly (m s^−2).</item> /// <item><i>xi</i>, the northerly component of the deflection of the vertical (degrees).</item> /// <item><i>eta</i>, the easterly component of the deflection of the vertical (degrees).</item> /// </list> /// </returns> /// <remarks> /// The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used so that the results of the NGA codes are /// reproduced accurately. approximations used here. /// Details are given in /// <a href="https://geographiclib.sourceforge.io/html/gravity.html#gravitygeoid">Details of the geoid height and anomaly calculations</a>. /// </remarks> public (double Dg01, double xi, double eta) SphericalAnomaly(double lon) { if (_caps.HasFlag(GravityFlags.SphericalAnomaly)) { return(double.NaN, double.NaN, double.NaN); } SinCosd(lon, out var slam, out var clam); double deltax, deltay, deltaz, T = InternalT(slam, clam, out deltax, out deltay, out deltaz, true, false); // Rotate cartesian into spherical coordinates Span <double> MC = stackalloc double[Geocentric.dim2_]; Geocentric.Rotation(_spsi, _cpsi, slam, clam, MC); Geocentric.Unrotate(MC, deltax, deltay, deltaz, out deltax, out deltay, out deltaz); // H+M, Eq 2-151c var Dg01 = -deltaz - 2 * T * _invR; var xi = -(deltay / _gamma) / Degree; var eta = -(deltax / _gamma) / Degree; return(Dg01, xi, eta); }