krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Packages/MoonriseKit/Sources/SkyEngine/Geomagnetic.swift

59d401dca1a327705632d1e2e20f00f807dee828
moonrise/Packages/MoonriseKit/Sources/SkyEngine/Geomagnetic.swift history · blame · raw

46 lines · 1968 bytes

7 symbols in this file
 1import Foundation
 2
 3/// Geomagnetic latitude from a centred-dipole model of Earth's field.
 4public enum Geomagnetic {
 5    /// North geomagnetic pole, IGRF-14 for 2025 (approximately 80.8° N, 72.8° W).
 6    public static let poleLatitude = 80.8
 7    public static let poleLongitude = -72.8
 8
 9    /// Geomagnetic latitude in degrees for a geographic position.
10    public static func latitude(_ observer: Observer) -> Double {
11        let r = Double.pi / 180
12        let s = sin(observer.latitude * r) * sin(poleLatitude * r)
13            + cos(observer.latitude * r) * cos(poleLatitude * r) * cos((observer.longitude - poleLongitude) * r)
14        return asin(max(-1, min(1, s))) / r
15    }
16
17    /// The backend's 5° band, named by its equatorward edge: 50 covers 50–55° N, -55 covers 50–55° S.
18    /// Must match `bandFor` in server/src/aurora.ts.
19    public static func band(_ observer: Observer) -> Int {
20        let m = latitude(observer)
21        let b = Int((abs(m) / 5).rounded(.down)) * 5
22        return m < 0 ? -(b + 5) : b
23    }
24
25    /// Geomagnetic latitude of the auroral oval's equatorward edge for a Kp value.
26    /// Must match `ovalEdge` in server/src/aurora.ts.
27    public static func ovalEdge(kp: Double) -> Double {
28        66.5 - 2.04 * kp
29    }
30
31    /// Lowest geomagnetic latitude (absolute) where aurora may be seen low on the poleward horizon.
32    /// Must match `visibleFrom` in server/src/aurora.ts.
33    public static func visibleFrom(kp: Double) -> Double {
34        ovalEdge(kp: kp) - 6
35    }
36
37    /// Kp at which aurora may be seen on the horizon from here; 0 under or poleward of the quiet oval.
38    public static func kpNeeded(_ observer: Observer) -> Double {
39        kpNeeded(geomagneticLatitude: latitude(observer))
40    }
41
42    /// `kpNeeded(_:)` for a geomagnetic latitude in degrees.
43    public static func kpNeeded(geomagneticLatitude: Double) -> Double {
44        max(0, (visibleFrom(kp: 0) - abs(geomagneticLatitude)) / 2.04)
45    }
46}