from typing import Callable
from benchmarks.comparative.implementations.gmat.base import (
build_task_result,
gmat_clear,
m_to_km_state,
time_iterations,
)
_JD_TO_UTCMJD_OFFSET = 2430000.0
_EGM96_COF = "EGM96.cof"
def _set_spacecraft(sc, state_m: list[float], jd: float) -> None:
state_km = m_to_km_state(state_m)
sc.SetField("StateType", "Cartesian")
sc.SetField("DateFormat", "UTCModJulian")
sc.SetField("Epoch", str(jd - _JD_TO_UTCMJD_OFFSET))
for name, val in zip(["X", "Y", "Z", "VX", "VY", "VZ"], state_km):
sc.SetField(name, val)
sc.SetField("DryMass", 100.0)
sc.SetField("Cd", 2.2)
sc.SetField("DragArea", 1.0)
sc.SetField("Cr", 1.5)
sc.SetField("SRPArea", 1.0)
def _extract_accel_m_s2(deriv) -> list[float]:
return [deriv.GetElement(i) * 1000.0 for i in range(3, 6)]
def _build_point_mass_fm():
import gmatpy as gmat
sc = gmat.Construct("Spacecraft", "Sat")
fm = gmat.Construct("ForceModel", "FM")
pmf = gmat.Construct("PointMassForce", "EarthPM")
pmf.SetField("BodyName", "Earth")
fm.AddForce(pmf)
fm.SetSolarSystem(gmat.GetSolarSystem())
fm.Initialize()
return sc, fm
def _build_spherical_harmonics_fm(degree: int, order: int):
import gmatpy as gmat
sc = gmat.Construct("Spacecraft", "Sat")
fm = gmat.Construct("ForceModel", "FM")
grav = gmat.Construct("GravityField", "EarthGravity")
grav.SetField("BodyName", "Earth")
grav.SetField("PotentialFile", _EGM96_COF)
grav.SetField("Degree", degree)
grav.SetField("Order", order)
fm.AddForce(grav)
fm.SetSolarSystem(gmat.GetSolarSystem())
fm.Initialize()
return sc, fm
def _build_third_body_fm(body_name: str):
import gmatpy as gmat
sc = gmat.Construct("Spacecraft", "Sat")
fm = gmat.Construct("ForceModel", "FM")
tb = gmat.Construct("PointMassForce", f"{body_name}TB")
tb.SetField("BodyName", body_name)
fm.AddForce(tb)
fm.SetSolarSystem(gmat.GetSolarSystem())
fm.Initialize()
return sc, fm
def _make_run(params: dict, build_fn: Callable):
cases = params.get("cases")
if cases is None:
state_m = params["state_eci"]
jd = params["jd"]
n_samples = params.get("n_samples", 1)
def run_perf():
gmat_clear()
sc, fm = build_fn()
_set_spacecraft(sc, state_m, jd)
last_deriv = None
for _ in range(n_samples):
last_deriv = fm.GetDerivativesForSpacecraft(sc)
return [_extract_accel_m_s2(last_deriv)]
return run_perf
def run_sweep():
gmat_clear()
sc, fm = build_fn()
out = []
for case in cases:
_set_spacecraft(sc, case["state_eci"], case["jd"])
deriv = fm.GetDerivativesForSpacecraft(sc)
out.append(_extract_accel_m_s2(deriv))
return out
return run_sweep
def accel_point_mass_gravity(params: dict, iterations: int):
times, result = time_iterations(
_make_run(params, _build_point_mass_fm),
iterations,
)
return build_task_result(
"force_model.accel_point_mass_gravity", iterations, times, result
)
def accel_spherical_harmonics_20(params: dict, iterations: int):
times, result = time_iterations(
_make_run(params, lambda: _build_spherical_harmonics_fm(20, 20)),
iterations,
)
return build_task_result(
"force_model.accel_spherical_harmonics_20", iterations, times, result
)
def accel_spherical_harmonics_80(params: dict, iterations: int):
times, result = time_iterations(
_make_run(params, lambda: _build_spherical_harmonics_fm(80, 80)),
iterations,
)
return build_task_result(
"force_model.accel_spherical_harmonics_80", iterations, times, result
)
def accel_third_body_sun(params: dict, iterations: int):
times, result = time_iterations(
_make_run(params, lambda: _build_third_body_fm("Sun")),
iterations,
)
return build_task_result(
"force_model.accel_third_body_sun", iterations, times, result
)
def accel_third_body_moon(params: dict, iterations: int):
times, result = time_iterations(
_make_run(params, lambda: _build_third_body_fm("Luna")),
iterations,
)
return build_task_result(
"force_model.accel_third_body_moon", iterations, times, result
)