Source code for astroforge.force_models._models

# Copyright (c) 2024 Massachusetts Institute of Technology
# SPDX-License-Identifier: MIT

"""
Models
"""

from numba import njit
from numpy.typing import NDArray
import numpy as np

from ._forces import F_J2, F_geo_MEMED, F_third
from ..constants import ss_GM, GM, GM_moon, GM_sun
from ..coordinates import shadow
from ..common import R_moon, R_moon_MEMED, R_sun, R_sun_MEMED

__all__ = [
    "F_mp",
    "F_mp_srp",
    "kepler",
]


[docs] @njit def F_mp( t: float, y: NDArray[np.float64], ) -> NDArray[np.float64]: """A built-in medium-fidelity force model for propagating a satellite. This model includes: * Two body + J2 perturbation Earth gravity * Third body gravitational perturbation from the Sun * Third body gravitational perturbation from the Moon Parameters ---------- t : float Time at which the force model is to be evaluated, expressed as a Modified Julian Date (MJD) in the UT1 time system. y : NDArray[np.float64] State vector; should have shape (6, ) with the first three parameters corresponding the 3D position, and the last three parameters corresponding to the 3D velocity of the satellite. Units are km and km/s. Returns ------- ydot : NDArray[np.float64] Derivate of the state vector. """ x = y[:3] v = y[3:] mjd = t / 86400.0 rm = R_moon(mjd) rs = R_sun(mjd) acc = F_J2(x) + F_third(x, rm, GM_moon) + F_third(x, rs, GM_sun) ydot = np.empty(6) ydot[:3] = v ydot[3:] = acc return ydot
[docs] @njit def F_mp_srp( time: float, xxdot: NDArray[np.float64], ) -> NDArray[np.float64]: """A built-in, medium-fidelity force model for propagating an orbital state. This model includes: * 8 x 8 spherical harmonic Earth gravity model * Third body gravitational perturbation from the Sun * Third body gravitational perturbation from the Moon * Solar radiation pressure (SRP) model This model uses a 9-element state vector. The first six are the typical position and velocity vectors. The final three elements are time-constant coefficients of the SRP model: :math:`\\alpha_i`. The SRP model is: .. math:: a_{SRP} = \\alpha_1 n_1 + \\alpha_2 n_2 + \\alpha_3 n_3 where * :math:`n_1` is in the direction away from the Sun * :math:`n_2` is along the direction of the satellite's velocity vector * :math:`n_3` is along the direction of the satellite's position vector. Parameters ---------- time : float Time at which the force model is to be evaluated, expressed as a Modified Julian Date (MJD) in the UT1 time system. xxdot : NDArray[np.float64] State vector; should have shape (9, ). The total state vector is: .. math:: X = \\begin{bmatrix} x \\\\ v \\\\ \\alpha \\end{bmatrix} Returns ------- ydot : NDArray[np.float64] Derivative of the state vector """ mjd = time / 86400.0 x = xxdot[:3] v = xxdot[3:6] alpha = xxdot[6:] Rm = R_moon_MEMED(mjd) Rs = R_sun_MEMED(mjd) n1 = -Rs n1 = n1 / np.sqrt(n1 @ n1) n3 = x / np.sqrt(x @ x) n2 = v / np.sqrt(v @ v) a = shadow(-n1, x) * (alpha[0] * n1 + alpha[1] * n2 + alpha[2] * n3) acc = F_geo_MEMED(mjd, x) + F_third(x, Rm, GM_moon) + F_third(x, Rs, GM_sun) + a jerk = np.zeros(3) ydot = np.empty(9) ydot[:3] = v ydot[3:6] = acc ydot[6:] = jerk return ydot
[docs] @njit def kepler(t: float, y: NDArray[np.float64]) -> NDArray[np.float64]: """A built-in force model that computes only the two-body acceleration term. The two body equations of motions are: .. math:: \\ddot{r} = - \\frac{GM}{||r||^3} r Parameters ---------- t : float Time, unused. Time must be the first input to this function in order to satisfy the ODE solver API. y : NDArray[np.float64] State vector; should have shape (6, ) with the first three parameters corresponding the 3D position, and the last three parameters corresponding to the 3D velocity of the satellite. Units are km and km/s. Returns ------- ydot : NDArray[np.float64] Derivative of the state vector. """ x = y[:3] v = y[3:] r3 = np.sqrt(np.sum(x**2, axis=0)) ** 3 acc = -GM * x / r3 ydot = np.empty(6) ydot[:3] = v ydot[3:] = acc return ydot