Skip to content

Drag: replace the SMAD mean-activity density table with NRLMSISE-00 driven by F10.7 and Ap #224

Closed

Description

@patrickmckeen

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 pymsis package 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:

  1. A density_model selector on Orbital_State and Orbit, like the magnetic_model selector 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 an interpolate-like interface.
  2. An NRLMSISEDensity class 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, evaluates pymsis at the orbital state's position and time, and caches the daily indices so the per-step cost is one model evaluation.
  3. pymsis as an optional dependency (an extra in pyproject.toml), with a clear error naming it when the model is selected and the package is missing.
  4. 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

  1. nscheuer commented on Oct 25, 2026

    @nscheuer
    Owner

    PRs #238 and #241 add NRMLSISE

  2. patrickmckeen commented on Oct 27, 2026

    @patrickmckeen
    CollaboratorAuthor

    Done in #239 (NRLMSISE-00 via pymsis).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions