The Spherical Harmonic Model

This documentation was generated with the assistance of AI. Please report any inaccuracies.

Classes: WorldMagneticModel, WMMLoader, WMMEarthMagneticFluxDensityEstimator (see the Class Reference table at the end of this page for Javadoc and source links).

Coefficient files

The WMM represents the Earth’s main magnetic field (and its slow year-on-year drift) as a degree-and-order-12 spherical harmonic expansion of the geomagnetic potential. Its 168+134 Gauss coefficients are re-fit every 5 years by NCEI/NGA/BGS from satellite, aircraft, and observatory measurements, and published as a plain-text .cof coefficient file — see NOAA coefficient downloads and the file-format description ([wmm-site]). This library bundles a wmm.cof resource and loads it through WMMLoader; a newer release can be substituted by loading a different file, resource, or URL.

Each WMM release is only valid for WorldMagneticModel.LIFESPAN (5.0) years from its epoch — WMMEarthMagneticFluxDensityEstimator itself uses model.epoch + LIFESPAN / 2.0 as the default date whenever no explicit year is supplied, but it does not check, warn, or refuse to compute past that window: it will happily (and silently) extrapolate secular variation arbitrarily far past epoch + 5 years, with growing error. The bundled wmm.cof is WMM-2025 (epoch 2025.0, nominally valid through 2030.0). To use this library beyond a bundled model’s 5-year window, download the current coefficient file from NOAA/NCEI’s WMM coefficients page and load it via WMMLoader.loadFromFile(…​) / WMMLoader.loadFromResource(…​) / WMMLoader.loadFromUrl(…​) (see below) instead of the no-arg WMMEarthMagneticFluxDensityEstimator() constructor, which always loads the bundled default.

Each data line in the file has the form:

n  m  gnm  hnm  dgnm  dhnm

and are the spherical harmonic degree and order; , are the main-field Gauss coefficients (nT) at the model epoch; , are their secular-variation rates (nT/year). WorldMagneticModel stores these (Schmidt semi-normalized, see below) together with the epoch year.

WMMLoader: Schmidt semi-normalization

Raw Gauss coefficients are published in Schmidt quasi-normalized form. WMMLoader converts them, once, into the fully normalized form used internally, via the recursive Schmidt normalization factor:


and rescales (and equivalently for , , ). It also precomputes the recursion coefficients

used by WMMEarthMagneticFluxDensityEstimator to generate the associated Legendre functions.

// load a specific coefficient file (e.g. a newer WMM release than the bundled one)
WorldMagneticModel model = WMMLoader.loadFromFile("/path/to/WMM.COF");

// or from an arbitrary resource/URL:
// WMMLoader.loadFromResource("/com/irurueta/navigation/inertial/wmm/wmm.cof");
// WMMLoader.loadFromUrl("https://example.org/WMM.COF");

WMMEarthMagneticFluxDensityEstimator: evaluating the model

Given a geodetic position and a decimal year, the estimator:

flowchart TD A["geodetic latitude/longitude/height,\ndecimal year"] --> B["Convert geodetic to\ngeocentric spherical coordinates"] B --> C["Time-adjust Gauss coefficients:\ng + (year - epoch) * gdot"] C --> D["Recursively evaluate Schmidt\nsemi-normalized Legendre functions"] D --> E["Accumulate spherical-harmonic sum\n(radial, colatitude, longitude components)"] E --> F["Rotate geocentric components\nto geodetic North/East/Down"] F --> G["Declination, dip, intensity,\nNEDMagneticFluxDensity"]

1. Geodetic-to-geocentric conversion. Because the WGS84 ellipsoid is not a sphere, geodetic latitude must first be converted to a geocentric colatitude and radius before the spherical-harmonic sum applies.

2. Time adjustment. Coefficients are linearly extrapolated from the model epoch:


This is only a good approximation within the model’s 5-year validity window (see World Magnetic Model (WMM)) — extrapolating far past years accumulates error.

3. Legendre recursion. The Schmidt semi-normalized associated Legendre functions and their colatitude derivatives are generated by the stable recursion (using from WMMLoader):


4. Spherical-harmonic sum. The field components in geocentric spherical coordinates (radial , colatitude , longitude ) accumulate one term per pair, using raised to the -th power ( = 6371.2 km, the WMM reference radius):

(with the term handled by a separate polar-region recursion at the geographic poles, where ). See the NOAA WMM technical report ([wmm-site]) for the full derivation.

5. Rotate to geodetic North/East/Down. The geocentric components are rotated back into the geodetic frame using the geocentric/geodetic latitude difference angle computed during step 1:



6. Derived quantities. Horizontal intensity, total intensity, declination, and dip follow directly:




WMMEarthMagneticFluxDensityEstimator exposes each of these individually (getDeclination, getDip, getIntensity, getHorizontalIntensity, getNorthIntensity, getEastIntensity, getVerticalIntensity) as well as the full NEDMagneticFluxDensity vector via estimate(…​).

// no-arg constructor loads the coefficient file bundled with this library
WMMEarthMagneticFluxDensityEstimator estimator = new WMMEarthMagneticFluxDensityEstimator();

NEDPosition position = new NEDPosition(Math.toRadians(41.3851), Math.toRadians(2.1734), 0.0);
double year = 2026.5; // decimal year

double declination = estimator.getDeclination(position, year); // radians
double dip = estimator.getDip(position.getLatitude(), position.getLongitude(), position.getHeight(), year);

NEDMagneticFluxDensity b = new NEDMagneticFluxDensity();
estimator.estimate(position.getLatitude(), position.getLongitude(), position.getHeight(), year, b);

Class Reference

Javadoc and source links for the classes used in the examples above:

Class Javadoc Source

WorldMagneticModel

Javadoc

Source

WMMLoader

Javadoc

Source

WMMEarthMagneticFluxDensityEstimator

Javadoc

Source

NEDMagneticFluxDensity

Javadoc

Source

Where to go next