5#include <janus/janus.hpp>
22 std::vector<std::vector<double>>
C;
23 std::vector<std::vector<double>>
S;
32 C.resize(
static_cast<size_t>(
n_max + 1));
33 S.resize(
static_cast<size_t>(
n_max + 1));
34 for (
int n = 0; n <=
n_max; ++n) {
35 C[
static_cast<size_t>(n)].resize(
static_cast<size_t>(n + 1), 0.0);
36 S[
static_cast<size_t>(n)].resize(
static_cast<size_t>(n + 1), 0.0);
69template <
typename Scalar> Scalar
legendre_Pnm(
int n,
int m,
const Scalar &x) {
76 Scalar pmm = Scalar(1.0);
78 Scalar somx2 = janus::sqrt((1.0 - x) * (1.0 + x));
80 for (
int i = 1; i <= m; ++i) {
81 pmm = -pmm * fact * somx2;
90 Scalar pmm1 = x * (2.0 * m + 1.0) * pmm;
96 Scalar pnm = Scalar(0.0);
97 for (
int nn = m + 2; nn <= n; ++nn) {
98 pnm = ((2.0 * nn - 1.0) * x * pmm1 - (nn + m - 1.0) * pmm) / (nn - m);
119template <
typename Scalar>
125 const Scalar r = sph.
radius;
126 const Scalar lon = sph.
lon;
127 const Scalar lat_gc = sph.
lat_gc;
129 const Scalar sin_lat = janus::sin(lat_gc);
130 const Scalar cos_lat = janus::cos(lat_gc);
132 const double mu = coeffs.mu;
133 const double R_eq = coeffs.R_eq;
134 const int n_max = coeffs.n_max;
137 Scalar dU_dr = Scalar(0.0);
138 Scalar dU_dlat = Scalar(0.0);
139 Scalar dU_dlon = Scalar(0.0);
143 for (
int n = 0; n <= n_max; ++n) {
144 const Scalar Re_r_n = janus::pow(R_eq / r,
static_cast<double>(n));
146 for (
int m = 0; m <= n; ++m) {
148 coeffs.C[
static_cast<size_t>(n)][
static_cast<size_t>(m)];
150 coeffs.S[
static_cast<size_t>(n)][
static_cast<size_t>(m)];
153 if (C_nm == 0.0 && S_nm == 0.0)
156 const Scalar cos_m_lon = janus::cos(
static_cast<double>(m) * lon);
157 const Scalar sin_m_lon = janus::sin(
static_cast<double>(m) * lon);
163 (n > 0) ?
legendre_Pnm(n - 1, m, sin_lat) : Scalar(0.0);
164 const Scalar tan_lat = janus::tan(lat_gc);
165 const Scalar dP_dlat =
static_cast<double>(n) * tan_lat * P_nm -
166 static_cast<double>(n + m) / cos_lat * P_nm1;
168 const Scalar trig_term = C_nm * cos_m_lon + S_nm * sin_m_lon;
169 const Scalar dtrig_dlon =
170 static_cast<double>(m) * (-C_nm * sin_m_lon + S_nm * cos_m_lon);
173 dU_dr +=
static_cast<double>(n + 1) * Re_r_n / r * trig_term * P_nm;
174 dU_dlat += Re_r_n * trig_term * dP_dlat;
175 dU_dlon += Re_r_n * dtrig_dlon * P_nm;
180 const Scalar scale = mu / r;
181 dU_dr = dU_dr * scale;
182 dU_dlat = dU_dlat * scale;
183 dU_dlon = dU_dlon * scale;
187 const Scalar sin_lon = janus::sin(lon);
188 const Scalar cos_lon = janus::cos(lon);
191 const Scalar g_r = -dU_dr;
192 const Scalar g_lat = -dU_dlat / r;
193 const Scalar g_lon = -dU_dlon / (r * cos_lat);
198 cos_lat * cos_lon * g_r - sin_lat * cos_lon * g_lat - sin_lon * g_lon;
200 cos_lat * sin_lon * g_r - sin_lat * sin_lon * g_lat + cos_lon * g_lon;
201 g_ecef(2) = sin_lat * g_r + cos_lat * g_lat;
216template <
typename Scalar>
220 const Scalar r = sph.
radius;
221 const Scalar lon = sph.
lon;
222 const Scalar lat_gc = sph.
lat_gc;
224 const Scalar sin_lat = janus::sin(lat_gc);
226 const double mu = coeffs.mu;
227 const double R_eq = coeffs.R_eq;
228 const int n_max = coeffs.n_max;
232 for (
int n = 2; n <= n_max; ++n) {
233 const Scalar Re_r_n = janus::pow(R_eq / r,
static_cast<double>(n));
235 for (
int m = 0; m <= n; ++m) {
237 coeffs.C[
static_cast<size_t>(n)][
static_cast<size_t>(m)];
239 coeffs.S[
static_cast<size_t>(n)][
static_cast<size_t>(m)];
241 if (C_nm == 0.0 && S_nm == 0.0)
244 const Scalar cos_m_lon = janus::cos(
static_cast<double>(m) * lon);
245 const Scalar sin_m_lon = janus::sin(
static_cast<double>(m) * lon);
249 mu / r * Re_r_n * (C_nm * cos_m_lon + S_nm * sin_m_lon) * P_nm;
constexpr double R_eq
Equatorial radius [m] (WGS84).
Definition Constants.hpp:16
constexpr double J4
J4 zonal harmonic coefficient.
Definition Constants.hpp:34
constexpr double J3
J3 zonal harmonic coefficient.
Definition Constants.hpp:31
constexpr double J2
J2 zonal harmonic coefficient.
Definition Constants.hpp:28
constexpr double mu
Gravitational parameter (GM) [m^3/s^2].
Definition Constants.hpp:13
Definition SphericalHarmonics.hpp:12
Scalar potential(const Vec3< Scalar > &r_ecef, const GravityCoefficients &coeffs=default_coefficients())
Spherical harmonic gravitational potential.
Definition SphericalHarmonics.hpp:217
const GravityCoefficients & default_coefficients()
Default Earth model with zonal harmonics only.
Definition SphericalHarmonics.hpp:52
Vec3< Scalar > acceleration(const Vec3< Scalar > &r_ecef, const GravityCoefficients &coeffs=default_coefficients())
Spherical harmonic gravitational acceleration.
Definition SphericalHarmonics.hpp:121
Scalar legendre_Pnm(int n, int m, const Scalar &x)
Compute associated Legendre polynomial P_nm(x).
Definition SphericalHarmonics.hpp:69
Spherical< Scalar > ecef_to_spherical(const Vec3< Scalar > &r)
Definition Geodetic.hpp:190
Definition Geodetic.hpp:49
Scalar lon
Longitude [rad], positive East, range [-π, π].
Definition Geodetic.hpp:50
Scalar radius
Distance from Earth center [m].
Definition Geodetic.hpp:52
Scalar lat_gc
Geocentric latitude [rad], range [-π/2, π/2].
Definition Geodetic.hpp:51
Gravity model coefficients container.
Definition SphericalHarmonics.hpp:20
GravityCoefficients(int n_max_val=20, double mu_val=constants::earth::mu, double R_eq_val=constants::earth::R_eq)
Initialize with given maximum degree.
Definition SphericalHarmonics.hpp:28
double mu
Gravitational parameter [m³/s²].
Definition SphericalHarmonics.hpp:24
std::vector< std::vector< double > > S
Sine coefficients S[n][m].
Definition SphericalHarmonics.hpp:23
std::vector< std::vector< double > > C
Cosine coefficients C[n][m].
Definition SphericalHarmonics.hpp:22
double R_eq
Reference radius [m].
Definition SphericalHarmonics.hpp:25
int n_max
Maximum degree.
Definition SphericalHarmonics.hpp:21