Turbulence
In short
- What it models: random gusts from the Dryden model: a gust pattern with a published spectrum (how gust strength spreads over wavelength), sized by height and the wind at 20 ft, and repeatable from a seed.
- Sources: MIL-F-8785C, the US military flying-qualities specification (1980), noting where MIL-HDBK-1797 (1997) differs; xoshiro256++ (Blackman and Vigna, 2021) and Marsaglia and Bray’s polar method (1964) for random numbers.
- How well it is validated: analytic and unit tests only: over 2²⁰ samples, each component’s spectrum is within 4 standard errors of theory in every octave band (±1–3% in the wide bands). Not compared with another simulator or a real flight.
- What it leaves out: Dryden is an aircraft model, unvalidated for rockets. Its frozen gust pattern needs airspeed well above the gusts, which fails on the rail and near apogee. No flight uses it, and none is planned (issue #39). Above 2000 ft the caller supplies the intensity.
Code and sources
Code: hpr_atmos::dryden, using the seeded generator in hpr_core::random.
Sources:
- [8785C] MIL-F-8785C, Military Specification: Flying Qualities of Piloted Airplanes
(5 November 1980), §3.7 and the definitions in §6.2.7, pinned as
mil-f-8785c. - [1797] MIL-HDBK-1797 (1997), Appendix A §4.9, for its differences only. It is not pinned: no stable public copy was found.
- [BV] D. Blackman and S. Vigna, “Scrambled linear pseudorandom number generators”, ACM TOMS 47(4) (2021): xoshiro256++ with SplitMix64 seeding.
- [MB] G. Marsaglia and T. A. Bray, “A convenient method for generating normal variables”, SIAM Review 6(3) (1964): the polar method.
Dryden spectra
Turbulence is a frozen random field that the vehicle moves through, so its spectra are functions
of spatial frequency Ω (rad/m, [8785C] §6.2.7). They are one-sided, with
∫₀^∞ Φ dΩ = σ² ([8785C] §3.7.1.2):
Φ_u(Ω) = σ_u² (2L_u/π) / (1 + (L_u Ω)²)
Φ_v(Ω) = σ_v² (L_v/π) (1 + 3(L_v Ω)²) / (1 + (L_v Ω)²)² (Φ_w likewise)
R_u(ξ) = σ_u² e^(−|ξ|/L_u)
R_v(ξ) = σ_v² e^(−|ξ|/L_v) (1 − |ξ|/(2L_v))
Φ = (2/π) ∫₀^∞ R(ξ) cos(Ωξ) dξ, so each spectrum and autocorrelation is a Fourier pair. A test
checks this numerically.
The factor-of-two trap. [1797] writes the transverse spectra with 2L_v and 12(L_vΩ)² over
(1 + 4(L_vΩ)²)², and halves the lengths (L_u = 2L_v). The spectra are identical, but mixing
one document’s lengths with the other’s formula puts the transverse scales off by two. This code
uses [8785C]’s form and lengths throughout.
Parameters
-
Low altitude ([8785C] §3.7.3.4, Figs. 10–11). With
hthe height above terrain in ft andu₂₀the mean wind at 20 ft:L_u = L_v = h / (0.177 + 0.000823 h)^1.2, L_w = h (ft) σ_w = 0.1 u₂₀, σ_u = σ_v = σ_w / (0.177 + 0.000823 h)^0.4- The formulas hold from 10 to 1000 ft. Below 10 ft this code uses the 10 ft values. From 1000
to 2000 ft the figures give
L = 1000 ftand equal intensities. - The model covers only up to about 2000 ft (§3.8.1), so above that the constructor returns an error instead of quietly holding values.
- Fig. 9 marks
u₂₀= 15, 30 and 45 kt for light, moderate and severe turbulence. - For aircraft at low altitude,
ulies along the horizontal relative mean wind andwis vertical ([8785C] p. 60).
- The formulas hold from 10 to 1000 ft. Below 10 ft this code uses the 10 ft values. From 1000
to 2000 ft the figures give
-
Medium/high altitude ([8785C] §3.7.2, above about 2000 ft): isotropic, with
L = 1750 ft.- The intensity against altitude and exceedance probability is only a graph (Fig. 7), so the caller supplies it.
- Neither military document says how to blend 1000–2000 ft. MATLAB’s documentation interpolates linearly, but that is its own choice.
-
Axes of the gust field:
uis the longitudinal component andv,wthe transverse ones.- The longitudinal spectrum belongs to the component along the path through the frozen
field. For a climbing rocket that is nearly vertical. The flight engine (M1.6)
doesn’t use turbulence, and no milestone plans it yet
(issue #39); whoever adds it must align
uwith the path. - Getting that wrong changes the statistics: a horizontal gust given the longitudinal spectrum has twice the transverse power at low frequency and 2/3 of it at high frequency.
- The axes’ signs don’t matter.
- The longitudinal spectrum belongs to the component along the path through the frozen
field. For a climbing rocket that is nearly vertical. The flight engine (M1.6)
doesn’t use turbulence, and no milestone plans it yet
(issue #39); whoever adds it must align
Generator
Exact discretization, so step length never changes the statistics.
u: a first-order Gauss–Markov state. Over a stepΔs, withρ = e^(−Δs/L):x ← ρx + √(1 − ρ²) n.vandw: two normalized states, driven asdx₁/ds = (−x₁ + η)/Landdx₂/ds = (x₁ − x₂)/L, with outputy = (σ/√2)(√3 x₁ + (1 − √3) x₂).-
The stationary covariance is
P = [[1, ½], [½, ½]]for everyL. -
The output’s autocorrelation is exactly
R_v. Algebra:c Φ(r) P cᵀ = 2e^(−r)(1 − r/2)withc = (√3, 1 − √3). -
Over
r = Δs/L, the transition isΦ(r) = e^(−r) [[1, 0], [r, 1]], plus Gaussian noise of covarianceQ = P − ΦPΦᵀ:Q = [[P(1,2r), ½P(2,2r)], [½P(2,2r), ½P(3,2r)]], P(n,x) = γ(n,x)/Γ(n) -
Written with the regularized incomplete gamma function,
Qkeeps full relative precision for tiny steps, where the closed form½ − e^(−2r)(r² + r + ½)cancels to nothing. The noise is drawn throughQ’s Cholesky factor.
-
- State is normalized, so intensities and lengths may change from one step to the next (with altitude, say) without breaking stationarity.
- Determinism: draws come in a fixed order (
u, two forv, two forw) from a seeded xoshiro256++, so the same seed and steps give bit-identical gusts on one platform.- The integer stream is identical everywhere.
- Normals and gusts go through the math library’s
lnandexp, which may differ in the last bit between platforms.
- Checkpointing: the generator serializes, so a run can be checkpointed and resumed.
GustField precomputes a realization at a fixed spacing and interpolates it linearly. That makes
the gust a pure function of the path coordinate, which an adaptive integrator can evaluate
repeatedly and on rejected steps.
- Spacing: linear interpolation smooths wavelengths near the spacing, so keep the spacing at or below a tenth of the smallest scale length.
- Size limit: a field holds at most 10⁷ samples.
Limits for rockets
- Scaled for aircraft. Dryden’s lengths and intensities describe aircraft flying roughly level. A rocket climbs through the low-altitude model’s height dependence in seconds. The frozen-field assumption holds when airspeed is well above the gust velocities. That is false on the rail and near apogee, where the gust field barely moves past the vehicle.
- Path coordinate: whoever adds turbulence to a flight decides what to key the field on: distance flown through the air, or altitude, and how to fade gusts in on the rail. This module does neither.
Tests that pin this
dryden::tests::dryden_spectrum_matches_theory(the done when of M1.2, the atmosphere and wind milestone):- Setup: 2²⁰ samples at 1 m, with
σ = (1.5, 1.2, 0.9)m/s andL = (40, 40, 20)m. - Estimate: 256 Hann-windowed segments of 4096 samples, averaged (Bartlett’s method).
- In every octave band from bin 1 to Nyquist, each component’s mean ratio to theory is within 4 standard errors.
- The variance of a band’s mean ratio is
[1 + 2ρ₁²(n−1)/n + 2ρ₂²(n−2)/n]/(nK)fornbins andKsegments, with the Hann window’s neighbouring-bin correlationsρ₁ = 2/3andρ₂ = 1/6. The bracket tends to 1.94. - The one- and two-bin bands at the bottom are loose (±25%, ±21%); the wide bands (±1–3%) pin the spectrum.
- Theory is the continuous spectrum sampled at 1 m, in closed form. Below a tenth of Nyquist it is checked against [8785C]’s formula to 1%.
- The variance of the record is within 5% of
σ².
- Setup: 2²⁰ samples at 1 m, with
- Exactness:
transition_preserves_the_stationary_covariance:ΦPΦᵀ + Q = Pto 4ε for steps from 10⁻¹² to 10³ scale lengths.two_steps_compose_into_one:Q(a+b) = Φ(b)Q(a)Φ(b)ᵀ + Q(b)to 1e-12 relative, down tor = 1e-9.transverse_output_has_the_dryden_autocorrelation.regularized_gamma_matches_independent_references.
- Stepping loop:
quarter_meter_steps_give_the_one_meter_correlation, to 2e-3.- The sampling error is about 4e-4, so this catches a scale length 10% off.
- It can’t tell an exact step from an Euler step (8e-5 apart), which is why the exactness tests above exist.
- Spectra:
spectra_integrate_to_the_variancespectra_are_the_cosine_transforms_of_the_autocorrelations
- Parameters:
low_altitude_parameters_follow_the_specification, at 100 ft moderate:L_u = 505.169 ftandσ_u/σ_w = 1.715849. It also checks the 10 ft floor, the 1000–2000 ft hold, and the refusal above 2000 ft. - Determinism: the same seed gives bit-identical fields, and a serialized generator resumes the stream.
hpr_core::random::tests:- Bit-identical to
rand_xoshiroover 10⁴ draws for 5 seeds. - The normal sampler’s moments and CDF at ±2σ, within 5 standard errors.
- Bit-identical to