Brahe computes Earth's geomagnetic field using spherical harmonic models. You provide a geodetic position and an epoch, and get back a three-component magnetic field vector in your choice of output frame. Two models are available: IGRF-14 for broad historical coverage and WMMHR-2025 for high spatial resolution near the current epoch.
The simplest call takes an epoch, a geodetic position (longitude, latitude, altitude), and an angle format. The result is a three-element vector [B_east, B_north, B_zenith] in nanoTesla:
IGRF-14 magnetic field at (lon=0, lat=60, alt=400 km)
B_east: -76.4 nT
B_north: 13099.9 nT
B_zenith: -41136.7 nT
Horizontal intensity: 13100.1 nT
Total intensity: 43172.2 nT
Inclination: 72.34 deg
Declination: -0.33 deg
IGRF-14 magnetic field at (lon=0, lat=60, alt=400 km)
B_east: -76.4 nT
B_north: 13099.9 nT
B_zenith: -41136.7 nT
Horizontal intensity: 13100.1 nT
Total intensity: 43172.2 nT
Inclination: 72.34 deg
Declination: -0.33 deg
\(B_\text{north}\) -- northward component (positive north, tangent to the reference surface)
\(B_\text{zenith}\) -- vertical component (positive upward, perpendicular to the reference surface)
From these you can derive the standard magnetic elements: horizontal intensity \(H = \sqrt{B_e^2 + B_n^2}\), total intensity \(F = |B|\), inclination \(I = \arctan(-B_z / H)\) (positive when the field dips below horizontal), and declination \(D = \arctan(B_e / B_n)\) (the compass deviation from true north).
Each model offers three output frame variants. All take the same geodetic input -- only the frame of the returned field vector changes.
The geodetic ENZ functions (igrf_geodetic_enz, wmmhr_geodetic_enz) return the field relative to the WGS84 ellipsoid surface. "Zenith" points along the ellipsoid normal. This is the standard frame for geomagnetic applications and matches the convention used by NOAA's magnetic field calculators.
The geocentric ENZ functions (igrf_geocentric_enz, wmmhr_geocentric_enz) return the field relative to a geocentric sphere. "Zenith" points radially outward from Earth's center. At the equator the two frames coincide; at high latitudes they differ by up to ~0.2 degrees due to Earth's oblateness.
The ECEF functions (igrf_ecef, wmmhr_ecef) return the field in the Earth-Centered Earth-Fixed frame. This is useful when you need the field expressed in the same frame as satellite position vectors, for example when computing magnetic torques on a spacecraft.
IGRF-14 (International Geomagnetic Reference Field) covers 1900 to 2030. It models spherical harmonic degrees 1 through 13, capturing Earth's core field at ~3000 km spatial resolution. Coefficients are provided every 5 years and interpolated linearly for dates in between. Use IGRF when you need magnetic field values over long time spans or at historical epochs.
WMMHR-2025 (World Magnetic Model High Resolution) covers approximately 2025 to 2030. It extends to spherical harmonic degree 133, adding crustal magnetic anomalies at ~300 km resolution on top of the core field. Use WMMHR when you need the most accurate current field values, particularly at or near Earth's surface where crustal contributions matter.
WMMHR-2025 at (lon=120, lat=0, alt=0) -- Full resolution (nmax=133)
B_east: -100.3 nT
B_north: 39643.1 nT
B_zenith: 10580.7 nT
Total intensity: 41030.9 nT
Inclination: -14.94 deg
Declination: -0.14 deg
Truncated resolution (nmax=13):
B_east: -115.3 nT
B_north: 39677.8 nT
B_zenith: 10579.4 nT
Difference from full resolution: 37.9 nT
WMMHR-2025 at (lon=120, lat=0, alt=0) -- Full resolution (nmax=133)
B_east: -100.3 nT
B_north: 39643.1 nT
B_zenith: 10580.7 nT
Total intensity: 41030.9 nT
Inclination: -14.94 deg
Declination: -0.14 deg
Truncated resolution (nmax=13):
B_east: -115.3 nT
B_north: 39677.8 nT
B_zenith: 10579.4 nT
Difference from full resolution: 37.9 nT
The nmax parameter on WMMHR functions controls the maximum spherical harmonic degree. Setting nmax=13 gives results comparable to standard WMM/IGRF resolution. The default (None / None) uses the full 133 degrees.
Satellite positions are often available in ECEF or ECI coordinates rather than geodetic. The typical workflow is: convert the ECEF position to geodetic using position_ecef_to_geodetic, then call the magnetic field function with the geodetic result.
importbraheasbhimportnumpyasnpbh.initialize_eop()# Define a LEO orbit and compute the ECEF stateepc=bh.Epoch(2025,3,15,12,0,0.0,time_system=bh.UTC)oe=np.array([bh.R_EARTH+500e3,0.01,51.6,45.0,30.0,60.0])# ISS-like orbitstate_eci=bh.state_koe_to_eci(oe,bh.AngleFormat.DEGREES)state_ecef=bh.state_eci_to_ecef(epc,state_eci)# Convert ECEF position to geodetic coordinatesx_ecef=state_ecef[0:3]x_geod=bh.position_ecef_to_geodetic(x_ecef,bh.AngleFormat.DEGREES)print(f"Epoch: {epc}")print(f"Geodetic position: lon={x_geod[0]:.2f} deg, lat={x_geod[1]:.2f} deg, alt={x_geod[2]/1e3:.1f} km")# Compute the magnetic field at the satellite location using IGRFb_enz=bh.igrf_geodetic_enz(epc,x_geod,bh.AngleFormat.DEGREES)b_total=np.linalg.norm(b_enz)print("\nIGRF field at satellite:")print(f" B_east: {b_enz[0]:10.1f} nT")print(f" B_north: {b_enz[1]:10.1f} nT")print(f" B_zenith: {b_enz[2]:10.1f} nT")print(f" |B|: {b_total:10.1f} nT")# Get the field in ECEF frame (useful for torque calculations in the body frame)b_ecef=bh.igrf_ecef(epc,x_geod,bh.AngleFormat.DEGREES)print("\nIGRF field in ECEF frame:")print(f" B_x: {b_ecef[0]:10.1f} nT")print(f" B_y: {b_ecef[1]:10.1f} nT")print(f" B_z: {b_ecef[2]:10.1f} nT")
usebraheasbh;usenalgebraasna;fnmain(){bh::initialize_eop().unwrap();// Define a LEO orbit and compute the ECEF stateletepc=bh::Epoch::from_datetime(2025,3,15,12,0,0.0,0.0,bh::TimeSystem::UTC);letoe=na::SVector::<f64,6>::new(bh::R_EARTH+500e3,0.01,51.6_f64,45.0_f64,30.0_f64,60.0_f64,);letstate_eci=bh::state_koe_to_eci(oe,bh::AngleFormat::Degrees);letstate_ecef=bh::state_eci_to_ecef(epc,state_eci);// Convert ECEF position to geodetic coordinatesletx_ecef=na::Vector3::new(state_ecef[0],state_ecef[1],state_ecef[2]);letx_geod=bh::position_ecef_to_geodetic(x_ecef,bh::AngleFormat::Degrees);println!("Epoch: {}",epc);println!("Geodetic position: lon={:.2} deg, lat={:.2} deg, alt={:.1} km",x_geod[0],x_geod[1],x_geod[2]/1e3);// Compute the magnetic field at the satellite location using IGRFletb_enz=bh::igrf_geodetic_enz(&epc,x_geod,bh::AngleFormat::Degrees).unwrap();letb_total=b_enz.norm();println!("\nIGRF field at satellite:");println!(" B_east: {:10.1} nT",b_enz[0]);println!(" B_north: {:10.1} nT",b_enz[1]);println!(" B_zenith: {:10.1} nT",b_enz[2]);println!(" |B|: {:10.1} nT",b_total);// Get the field in ECEF frame (useful for torque calculations in the body frame)letb_ecef=bh::igrf_ecef(&epc,x_geod,bh::AngleFormat::Degrees).unwrap();println!("\nIGRF field in ECEF frame:");println!(" B_x: {:10.1} nT",b_ecef[0]);println!(" B_y: {:10.1} nT",b_ecef[1]);println!(" B_z: {:10.1} nT",b_ecef[2]);}
Epoch: 2025-03-15 12:00:00.000 UTC
Geodetic position: lon=143.71 deg, lat=51.66 deg, alt=479.2 km
IGRF field at satellite:
B_east: -2904.0 nT
B_north: 17484.4 nT
B_zenith: -39565.4 nT
|B|: 43353.9 nT
IGRF field in ECEF frame:
B_x: 32554.2 nT
B_y: -20302.7 nT
B_z: -20188.7 nT
Epoch: 2025-03-15 12:00:00.000 UTC
Geodetic position: lon=143.71 deg, lat=51.66 deg, alt=479.2 km
IGRF field at satellite:
B_east: -2904.0 nT
B_north: 17484.4 nT
B_zenith: -39565.4 nT
|B|: 43353.9 nT
IGRF field in ECEF frame:
B_x: 32554.2 nT
B_y: -20302.7 nT
B_z: -20188.7 nT
Info
The input altitude is always in meters (SI), consistent with all other Brahe functions. The models work internally in kilometers but handle the conversion automatically.