Repository navigation
Drag: replace the SMAD mean-activity density table with NRLMSISE-00 driven by F10.7 and Ap #224
Description
What the package does today
Atmospheric density, which drives the drag disturbance torque and orbit decay, comes from DensityModel in ADCS/orbits/density_model.py: a table of density against altitude taken from SMAD (Space Mission Analysis and Design), interpolated in altitude. The table is a single profile for mean solar activity, so density depends on altitude and nothing else. Orbital_State evaluates it once per orbital state (self.rho) and the drag disturbance reads that value.
Real thermospheric density is not a function of altitude alone. Between solar minimum and solar maximum it changes by a factor of about 10 at 400 km and about 50 at 800 km, and it also varies with local time, latitude, season and geomagnetic activity. A simulation of a given mission in a given year therefore has the wrong drag by up to an order of magnitude, in either direction, which matters for anything that depends on the drag torque (momentum build-up, de-tumble times, estimator tuning for drag parameters) and for orbit lifetime.
#100 goes one step in this direction: it scales the SMAD profile by a "solar level" between quiet and active Sun, with a helper that maps the F10.7 solar flux to that level. That is a cheap, altitude-dependent scaling, not a physical model.
What would be better
Use an empirical thermosphere model driven by the actual space-weather indices for the simulation epoch:
- NRLMSISE-00 (the NASA/NRL mass spectrometer and incoherent scatter model, 2000 edition) is the standard choice. Its inputs are the date, altitude, latitude, longitude, local solar time, the daily F10.7 solar radio flux, its 81-day average, and the geomagnetic index Ap. It returns total mass density. The
pymsispackage wraps the reference Fortran code (and the newer MSIS 2.0/2.1) with a NumPy interface. - The indices are published daily by CelesTrak as a space-weather file (
SW-All.csv), with historical values and forecasts, so a run at a given J2000 epoch can look up the right F10.7 and Ap automatically.
A reasonable shape for the change:
- A
density_modelselector onOrbital_StateandOrbit, like themagnetic_modelselector in v1 IGRF choice [needs review] #221:"smad"(the current table, default, so nothing changes for existing users and tests),"nrlmsise00", and a user-supplied object with aninterpolate-like interface. - An
NRLMSISEDensityclass that takes either fixed indices (F10.7, F10.7 average, Ap) for a what-if study or a space-weather file for epoch-dependent indices, evaluatespymsisat the orbital state's position and time, and caches the daily indices so the per-step cost is one model evaluation. pymsisas an optional dependency (an extra inpyproject.toml), with a clear error naming it when the model is selected and the package is missing.- Tests: the model reproduces published NRLMSISE-00 values at a few reference points; density rises monotonically with F10.7 and with Ap at fixed altitude; the SMAD default is bit-for-bit unchanged; and a drag torque computed with each model differs by the expected factor at solar maximum.
The SMAD table should stay as the default for speed and reproducibility; this is about giving the drag model a physically grounded option.
Why this is a good first issue
The work is self-contained (one new class, one selector, an optional dependency and tests), the reference model is well documented, and the existing DensityModel and the magnetic_model selector in #221 show exactly where things plug in. Related planning: #144.
Activity
nscheuer commentedon Oct 25, 2026
PRs #238 and #241 add NRMLSISE
patrickmckeen commentedon Oct 27, 2026
Done in #239 (NRLMSISE-00 via pymsis).