1. What the engine computes
Given a transmit/receive pair, date/time, and space-weather indices, the engine produces the frequency window that will support the link (MUF50, FOT, LUF), an expected time availability (reliability), and field-strength / SNR predictions per candidate frequency. The computation follows ITU-R P.533-14 as its top-level algorithm, with ionospheric inputs from CCIR P.1239-3 and noise from P.372-16.
- Frequency window: MUF decile envelope (10 / 50 / 90 %), FOT = 0.85 · MUF50, absorption-and-SNR-limited LUF.
- Ionospheric layers: foF2, foF1, foE, foEs, M(3000)F2, hmF2 at path midpoint and per-hop reflection points.
- Per-hop integration: absorption accumulated along great-circle reflection points, not averaged.
- Mode selection: P.533 §3.4 tiered elevation rule — 1F2 / 2F2 / 3F2, 1E / 2E, 1Es / 2Es, 1F1.
- Reliability: joint probability of SNR margin × MUF-day variability × Es opening × (1 − Es blanketing).
- Antennas: NEC-style image method for Yagi / LPDA / Rhombic over real ground, with height and frequency.
- Path routing: short-path (great-circle) and long-path (antipodal) both supported.
2. ITU-R recommendations implemented
| Recommendation | Scope | Where |
|---|---|---|
| P.533-14 | HF propagation prediction (master algorithm) | HFPropagationEngine.ts |
| P.1239-3 | Reference ionospheric characteristics — CCIR foF2 & M(3000)F2 Fourier maps (76/49 coeffs) | ionosphericModel.ts, ccirEvaluation.ts |
| P.1239 Annex 2 (Bradley-Dudeney) | hmF2 from M(3000)F2 + foF2 / foE ratio | ionosphericModel.ts::calculateHmF2 |
| P.533 §5.2 | Non-deviative absorption (D & lower-E region) | absorptionModel.ts::calculateNonDeviativeAbsorption |
| P.533 §5.3 | Deviative absorption at F-region reflection (1 dB per hop, literal) | absorptionModel.ts::calculateDeviativeAbsorption |
| P.531-13 | SID / X-ray flare absorption (Davies 1990 calibration) | absorptionModel.ts::calculateSIDAbsorption |
| P.534-4 | Auroral absorption, K-index driven | absorptionModel.ts::calculateAuroralAbsorption |
| P.372-16 | Radio noise: galactic / atmospheric / man-made, quadrant-resolved | noiseModel.ts, data/ionosphericCoefficients.ts |
| P.842-5 | Reliability & time-availability (Gaussian CDF on SNR + MUF margins) | statisticalReliability.ts |
| P.525 | Free-space basic transmission loss | fieldStrength.ts |
| IGRF-14 (epoch 2025) | MODIP grid for ionospheric mapping | modipCalc.ts |
3. Documented deviations from ITU-R literal
Every deviation is annotated in source with a ═══ ITU-R COMPLIANCE AUDIT ═══
block so the rationale is visible at the point it's applied. The list below is the complete
set — there are no silent adjustments.
3.1 Equatorial Ionisation Anomaly (EIA) damping
CCIR P.1239 coefficients don't resolve the ±15-20° EIA crests of enhanced plasma density that dominate tropical daytime HF propagation. For paths whose midpoint falls within the crest region between 10:00 and 18:00 local time, the engine damps predicted foF2 by up to 8 % to bring MUF closer to observation. This is not part of ITU-R P.1239 and is flagged as empirical.
3.2 Tropical REL ceiling
VOACAP's own reference observations at low latitudes record more TID and spread-F fading than our model captures. For paths whose midpoint latitude is |φ| < 20°, reliability is capped between 75 % and 95 % (graded on latitude). Outside the tropics this clamp has no effect.
3.3 Grayline reduction
For paths whose great-circle crosses the solar terminator, LUF is reduced by 8 / 5 / 4 / 2 dB in a piecewise function of the crossing angle. This matches operator observation but is not directly an ITU-R formula.
3.4 Multi-mode Rayleigh fading σ
P.842 prescribes a single-path Rayleigh variance. When the engine identifies multiple co-present propagation modes (e.g. 1F2 + 2F2 + 1Es), σ is scaled to 4.5 / 6.5 / 8 dB for 2 / 3 / 4+ active modes to reflect the measured multipath penalty. Single-mode paths use the P.842 literal.
3.5 Sporadic-E probability multiplier
foEs and its occurrence probability (seasonal + diurnal + latitude Gaussian) aren't prescribed in P.533. The engine uses a literature-calibrated model that is multiplied into the joint reliability. This extends P.533 rather than contradicting it.
3.6 LUF ≥ 25 MHz semantic
VOACAP emits LUF ≥ 25 MHz as a "no frequency meets the required reliability" sentinel. Our LUF is defined differently — the lowest frequency where absorption plus noise still permits a 10 dB SNR margin — so the two are not directly comparable above ~25 MHz. The benchmark in §4 drops LUF comparisons above that threshold rather than pretending they're comparable.
3.7 Above-MUF experimental extrapolation
The engine reports a tentative availability curve above MUF50 using a scattering-loss estimator. This is marked experimental in the UI with a hatched band — ITU-R P.533 stops at MUF50.
4. Accuracy envelope vs VOACAPL
The engine is benchmarked on 30 reference paths that span the full operating envelope — tropical, mid-lat, trans-polar, trans-equatorial, dawn/dusk grayline, solar min/max. Each path's reference numbers come from VOACAPL, the canonical Fortran implementation.
| Quantity | Mean abs error | Median | P90 | Max |
|---|---|---|---|---|
| MUF50 | 2.1 MHz | 1.6 MHz | 4.8 MHz | 6.4 MHz |
| FOT | 1.8 MHz | 1.4 MHz | 4.1 MHz | 5.4 MHz |
| Reliability (peak-across-freqs) | 17 pts | 15 pts | 32 pts | 58 pts |
Tolerances in the test suite (tests/hf/integration/voacap-paths.test.ts) are
set to the P95 envelope. A path that exceeds tolerance is not silently passed — it's
flagged as a known outlier with a root cause (see §5).
4.1 Ionospheric layer accuracy vs PyIRI / IRI-2020
The ionospheric layer model is separately benchmarked against 384 reference vectors from PyIRI (IRI-2020). This isolates the CCIR layer model from downstream propagation physics.
| Quantity | Mean abs error | P95 | Max | Within tolerance |
|---|---|---|---|---|
| foF2 | 0.13 MHz | 0.91 MHz | 2.24 MHz | 99.0 % |
| foE | 0.23 MHz | 0.58 MHz | 0.94 MHz | 97.4 % |
| foF1 | 1.40 MHz | 3.92 MHz | 4.43 MHz | 100.0 % |
| M(3000)F2 | 0.001 | 0.00 | 0.01 | 100.0 % |
| MODIP | 0.07° | 0.29° | 0.40° | 100.0 % |
foF1 tolerance is wider because our foF1 < foE ⇒ 0 truncation
differs from IRI's behaviour of reporting a raw value; the downstream
impact on mode selection is marginal (F1 contributes only to mid-lat daytime sub-MUF
absorption).
5. Known outliers
Five of the 30 benchmark paths sit at or beyond the P95 envelope. All have a documented physical cause:
- Hanoi → Manila (MUF +4.0 MHz): tropical daytime over the EIA crest region. The §3.1 EIA damping pulls this from the previous +11.5 MHz bug, but it remains at the upper end of the envelope — we under-resolve the crest structure without a full EIA model.
- Moscow → Vladivostok (REL +58 pts, MUF +0.5 MHz): Asian mid-lat summer morning. Root cause is not an Asian-sector foF2 calibration issue (MUF agrees) — it is a systematic difference in reliability definition. VOACAP bakes a conservative man-made noise margin into its REL output; our engine treats noise environment as a user input (rural / residential / industrial) and applies it separately. For a given site where the user knows the noise floor, our engine's REL is more actionable. For comparing against VOACAP's default output the gap is real. Four other paths show the same pattern (Boulder → Berlin +36, Iceland → Cape Town +36, Cape Town → Rio +26, Anchorage → Houston +25).
- London → Sydney solar MIN (MUF −5.2 MHz, REL −31 pts): at R12 near zero our foF2 decile scaling runs thinner than VOACAP's, over-predicting MUF drop.
- Singapore → Nairobi, Hawaii → Auckland (MUF ±5-6 MHz): long trans-equatorial and trans-Pacific paths that integrate multiple EIA regions — compounded version of the Hanoi → Manila story.
- Boulder → Berlin / Iceland → Cape Town / Cape Town → Rio / Anchorage → Houston (REL +25-36 pts): same man-made noise-margin difference described for Moscow → Vladivostok. Not per-path errors — a methodology choice.
6. When to trust this tool (and when not to)
An honest three-tier answer for an RF engineer evaluating whether to use this in a workflow:
| Use case | Suitable? | Why |
|---|---|---|
| Pre-planning & band selection (which bands to try, at what hours, which season) | Yes — confidently | MUF median error 1.6 MHz is well inside amateur / commercial band widths; the frequency window recommendation is reliable. |
| Engineering design with documented uncertainty (antenna sizing, power budget, link availability targets) | Yes — with the envelope shown | Use MUF90 / MUF10 as design bounds, not MUF50 as a point estimate. Reliability ±17 pts means quote "80 % ± 17" not "80 %". |
| Safety-critical or regulatory submissions (aviation HF, emergency services, spectrum licensing) | No — use VOACAPL directly | For anything a regulator or auditor reviews, use the ITU reference tool. This engine is a faster, map-driven frontend — it does not replace VOACAPL for formal submissions. |
7. Regenerating the benchmark
The numbers on this page come from the test suite, not hand-edited values. Two scripts refresh the reference vectors and a bundled npm script runs end-to-end:
# regenerate PyIRI layer vectors (requires python3 + PyIRI)
npm run test:hf:regen-pyiri
# regenerate VOACAPL path vectors (requires local voacapl build)
npm run test:hf:regen-voacap
# full pipeline: regen + run benchmark + emit docs/hf/benchmark-report.md
npm run hf:benchmark
The emitted docs/hf/benchmark-report.md is the per-path table of engine vs
VOACAP deltas that backs the summary statistics in §4. It is regenerable and should be
checked in alongside engine changes.
Questions or corrections? Contact us — if you find an outlier with a physical explanation we haven't documented, we'll credit the fix.