Single precision#
solprop computes in IEEE binary64 (double precision) by default. A run can instead hold
its propagated field and its nonlinear evaluation in binary32 (single precision) with
precision="single" (SEP 33).
Single precision halves the memory of every field-sized buffer and is what graphics
processors without fast binary64 arithmetic compute in; whether a given problem keeps
its accuracy in binary32 is a property of the problem, so this page records which do.
Note
Single precision runs on the mlx backend, on the GPU of an Apple-silicon Mac
(choosing a backend), for capillary and fibre runs
and radial and Cartesian free space. numpy_ref runs every route below as the
reference implementation, which defines the arithmetic and measures it but is not fast.
numba_cpu and native compute in binary64 only.
Asking for it#
from solprop.driver import prop_capillary
output = prop_capillary(
125e-6,
0.1,
"He",
0.8,
lambda0=800e-9,
fwhm=10e-15,
energy=100e-6,
wavelength_limits=(200e-9, 3e-6),
trange=200e-15,
precision="single",
backend="numpy_ref",
)
precision is a keyword of prop_gnlse, prop_capillary and prop_waveguide, and a
field of SimulationSettings for the free-space
interfaces. Under single precision:
The tolerance floor. The default
rtolis1e-6(SINGLE_RTOL_FLOOR), and an explicit adaptivertolbelow it is refused: a local error target below binary32’s rounding per step buys steps without accuracy. A fixed schedule reads no tolerance.The step’s exponent. Binary32 represents
exp(x)only up to \(x \approx 88.7\) (binary64 to 709.8). The interaction picture multiplies by the linear propagator and its inverse, so a replayed step (or an adaptive run’s floordz_min) over which a strong collar or loss reaches that exponent is refused at translation, with the shortest step that fits, and one within a tenth of it is warned of. A 1 mm capillary’s default collar on 0.25 mm steps is one such case.The integrator. The default is
RungeKutta()(DOPRI5) and the low-storage march is admitted; the Adams integrator,Multistep(), is refused until its single-precision accuracy is established.The backend.
backend="auto"resolves to"mlx"when MLX and a Metal GPU are present, and is refused otherwise; it never resolves to a binary64 backend, nor to the reference implementation, which is named explicitly,backend="numpy_ref".Outputs are unchanged: saved fields, statistics and processing are binary64, and files are the same size. The precision is part of the run’s configuration, so a run is never resumed in the other precision.
What it covers#
|
|
|
|---|---|---|
capillaries, solid-core and GNLSE fibres, mode-averaged and multimode, field and envelope grids |
yes |
yes |
Kerr, the envelope grid’s third-harmonic term, scalar and tensor Raman, gas Raman mixtures, the silica bundle |
yes |
yes |
field-grid plasma |
yes |
yes |
envelope-grid plasma |
yes |
yes, each sample’s ellipse and cycle moments in one GPU kernel |
radial and Cartesian free space, including a line, with their transverse collars |
yes |
yes |
gradients, tapers, loss, both temporal absorber schemes, the polarisation taper |
yes |
yes, where the operator is device-ready (not a z table) |
Runge–Kutta, the low-storage march, fixed-schedule batches |
yes |
yes |
the Adams integrator |
refused, pending its accuracy record |
refused |
noise models |
refused (a known limitation, below) |
refused |
the general modal route, the hybrid planar kind, coupled flows, TDSE responses, the dispersive electronic response, the far-field statistics |
refused |
refused |
How the arithmetic is kept accurate#
Binary32 carries about seven significant digits and represents magnitudes between about \(10^{-38}\) and \(3\times10^{38}\). solprop keeps both from limiting a run:
Range. Every table a run multiplies by is narrowed with its own power-of-two exponent, and the field is held at an exact power-of-two scale chosen from the launch. A nitrogen Raman kernel whose spectrum is near \(10^{-50}\) — zero in binary32 as it stands — keeps every bin; a Cartesian energy sum that would reach \(10^{44}\) is scaled before squaring.
The linear propagator \(e^{\Delta\Phi}\) is formed to binary64 accuracy and rounded once per step. Its rounding still adds coherently from step to step, about \(c\,M\,u\) after \(M\) steps with \(u = 2^{-24}\); the record below states \(c\).
Populations. The ionised fraction and the neutral survival are formed in forms that keep relative accuracy at tiny and saturated exposures, and running integrals over time are summed in a balanced order rather than one long sequential sum.
The controller, landing and every scalar stay in binary64.
The survival record#
Each case below was run in single precision at rtol = 1e-6 and 1e-5 and compared, at
the end of its window, with a binary64 run on the same grid at rtol = 1e-10, against
accuracy envelopes fixed before any comparison: the field to \(10^{-3}\), the spectral
energy in each of 32 bands above −40 dB to 1 %, the total energy to \(10^{-4}\), the peak
power or intensity, the final ionised fraction and the beam width to \(10^{-3}\), all
relative. The table gives the largest of those relative errors at rtol = 1e-6, the
field’s error, and binary64’s own field error at the same tolerance for comparison.
case |
single: field error |
largest other metric |
binary64 at |
verdict |
|---|---|---|---|---|
self-phase modulation, 10π, no dispersion (GNLSE) |
7.9e-6 |
9.6e-5 (bands) |
1.9e-6 |
survives |
fundamental soliton, ten periods (GNLSE) |
2.7e-5 |
6.5e-6 (peak) |
1.1e-6 |
survives |
dispersive-wave emission, He capillary gradient, two modes, 1.5 m |
2.6e-6 |
4.9e-5 (bands) |
1.3e-6 |
survives |
comb-to-continuum, H₂ capillary at 40 bar, 0.1 m, noise-free |
2.6e-3 |
3.4e-4 (peak) |
3.0e-7 |
survives over 0.05 m |
plasma blue shift, Ar capillary, field grid, 0.4 m |
1.8e-4 |
2.1e-4 (bands) |
1.6e-4 |
survives |
plasma blue shift, Ar capillary, envelope grid, 0.4 m |
1.3e-5 |
2.1e-5 (ionised) |
1.3e-5 |
survives |
molecular Raman, N₂ capillary at 2 bar, 0.3 m |
1.1e-6 |
2.7e-5 (bands) |
1.6e-7 |
survives |
radial Kerr beam, 0.3 m |
8.5e-6 |
1.3e-4 (bands) |
8.6e-6 |
survives |
radial filament in argon with plasma, 3 cm |
2.3e-6 |
1.2e-5 (peak) |
2.2e-6 |
survives |
Cartesian Gaussian diffraction, 64 × 64 |
2.4e-7 |
2.4e-7 (bands) |
0 |
survives |
Cartesian Kerr beam, 64 × 64 |
2.7e-6 |
2.0e-5 (bands) |
4.2e-6 |
survives |
At rtol = 1e-5 every case but the comb-to-continuum stays inside its envelopes too.
The table is the reference implementation’s. On mlx, whose envelope-grid plasma is
its own discretisation of the cycle moments, the envelope-grid blue shift over its full
0.4 m has field error 4.8e-5 (largest other 5.3e-5, the ionised fraction) and the
field-grid one 2.2e-4 (2.8e-4, bands): both survive.
The comb-to-continuum limit. Noise-free stimulated Raman scattering grows from whatever seed the Stokes band holds; rounding seeds it at the level of the unit roundoff times the field. In binary64, adding a seed of \(2^{-24}\) of the launch’s peak spectral amplitude moves the result at 0.1 m by 5 %: the sensitivity is the physics, and binary32’s own rounding is such a seed. Over 0.05 m the run is inside every envelope.
The tolerance floor stays at
1e-6: tightening from1e-5to1e-6still buys accuracy (by 92 % in the self-phase-modulation case’s field).The propagator’s step limit. With no nonlinear source the rounding of \(e^{\Delta\Phi}\) accumulates as \(c\,M\,u\) after \(M\) steps, with \(c \approx 0.5\) measured on a capillary operator over \(10^2\)–\(10^4\) steps (0.1–0.3 on a GNLSE one). The field envelope of \(10^{-3}\) is reached after about \(3\times10^4\) steps; a run that needs more takes binary64.
Known limitations#
Noise. A one-photon-per-mode seed is of order \(10^{-5}\) of a microjoule pulse’s peak spectral amplitude and smaller at higher energies, while binary32’s accumulated rounding can reach \(10^{-5}\) after \(10^4\) steps. Noise-seeded runs are refused under single precision until that boundary is qualified.
Amplifying dynamics. Rounding at the level of \(10^{-7}\) per step is amplified like any perturbation by soliton fission, modulation instability or noise-free stimulated Raman scattering; such runs reach their accuracy over a shorter length, as the record states.
Performance. On the reference implementation a single-precision run costs about as much as a double-precision one. On
mlxthe gain overnativegrows with the problem, and is largest for the envelope-grid plasma, whose cycle moments the GPU evaluates one sample per thread. On an otherwise idle MacBook Pro M5 Max (18 CPU cores, 40-core GPU), in the same process, the median time of a fixed step onnative(binary64) over that onmlx(binary32) was:case
native/mlxGNLSE with Raman, one line, 2¹⁴ / 2¹⁶ / 2¹⁸ samples
1.7 / 3.4 / 5.3
Ar capillary, field-grid plasma, 1 / 4 modes (300 fs) and 8 modes (1 ps)
0.51 / 0.69 / 1.12
the same with the envelope-grid plasma
8.1 / 8.1 / 3.5
radial Kerr beam, 64 / 256 nodes
1.05 / 2.9
Cartesian Kerr beam, 64 × 64 / 128 × 128
1.9 / 1.9
radial argon filament, field grid, 64 / 128 / 256 nodes
1.8 / 2.5 / 3.2
Small field-plasma capillaries are slower on the GPU, bound by its per-operation latency. These are same-process comparisons on one machine, not the standard benchmark suite.
The worked example runs a
capillary with the envelope-grid plasma and a radial filament in both precisions and
compares them. The precision setting, its binary32 contract, the survival study and the
mlx backend were proposed and carried out by
SEP 33.