Skip to content

Latest commit

 

History

History
129 lines (117 loc) · 34.2 KB

testing.md

File metadata and controls

129 lines (117 loc) · 34.2 KB

Testing and validation

The complete list of tests, with the analytic result, published value or other code each one is checked against, is the generated validation matrix. This page is the overview by subject.

Continuous integration (.github/workflows/ci.yml) runs on Linux: it builds net10.0 and net48, compiles the CLI for every platform, and runs the C# tests on both runtimes, the Python tests with pyNLO, the strict docs build and python build/example_check.py, which reruns every example and tutorial and checks the numbers they quote. OpticStudio cannot run there: the Zemax binding stays a manual check.

Running

dotnet run --project tests/UltrafastEngine.Tests -f net10.0             # all (slow tests included only when filtered or with --slow)
dotnet run --project tests/UltrafastEngine.Tests -f net10.0 -- Soliton  # name filter
dotnet run --project tests/UltrafastEngine.Tests -f net10.0 -- --slow --verbose
mono tests/UltrafastEngine.Tests/bin/Debug/net48/UltrafastEngine.Tests.exe   # .NET Framework build (macOS/Linux)
python -m pytest python/tests                                            # Python bindings + pyNLO cross-checks
ULTRAFAST_SLOW=1 python -m pytest python/tests                           # + slow Python tests (high-gain DFG vs pyNLO)
UltrafastEngine.Zemax.exe selftest                                       # binding on fake systems

The C# runner is a console app with its own [Test] attribute (no NuGet packages, runs on .NET 10 and .NET Framework 4.8/Mono). In Visual Studio set it as start-up project and press Ctrl+F5.

What is checked

area test criterion
numerics JSON round trip, expression engine, NPZ, FFT round trip / Parseval / delay sign, dispersion extraction exact / 1e-12
materials Ciddor air at 633 nm, N-BK7 and fused silica n_d, fused-silica GDD/TOD at 800 nm, argon refractivity 2e-5 ... 3 %
surfaces Fresnel R+T = 1, normal-incidence R, Brewster r_p = 0, total internal reflection, quarter-wave AR, Bragg-mirror reflectance (analytic) and its group-delay sign 1e-9 ... 1e-12
linear optics Treacy grating pair GDD, sampled stretcher (FWHM, arrival time, GDD, chirp fit, auto window), chirped-mirror GDD per bounce, Beer-Lambert 1e-4 ... 2 %
nonlinear SPM broadening of a Gaussian vs analytic (Agrawal 4.1.15) and B-integral; fundamental soliton over a period; adaptive vs fixed stepper; self-steepening and Raman directions; envelope vs carrier-resolved; callback/expression == built-in Kerr; Bessel sidebands of lab-time modulation 1e-9 ... 4 %
polarisation waveplates, polariser leakage, Brewster window s/p, periscope basis transport 1e-3 ... 1e-12
vector Kerr and Raman (NER) circular / elliptical B-integral (2/3, 1 − sin²2χ/3 of linear); circular at 1.5× energy has the linear spectrum; ellipse rotation B sin(2χ)/3 (electronic) and B sin(2χ)[(1 − fR)/3 + fR b/2] with the anisotropic silica Raman; circular/linear phase (1 − fR)2/3 + fR(1 − b/2); linear light unchanged by the split; Lin-Agrawal anisotropic share 0.5 ... 2 %
system loss budget closes; aperture clip formula; override priority and provenance; material override beats traced data; system file round trip and validation exact
instruments AC deconvolution (Gaussian, sech^2), IAC 8:1, spectrometer FWHM, ideal compressor, polarimeter, energy meter, d-scan optimum, FROG marginal 1 ... 5 %
Zemax sampling Treacy pair through the sampler == Treacy + slab (and the phase-path model has the wrong sign); argon MPC: passes, mirrors, coating rules, GBPS/GBPW waist, per-pass B; tilted slab AOI, AR rule, Fresnel; record/replay; beam profile reconstruction 0.5 % / exact
χ(2) crystals SHG vs Armstrong tanh² (0.02-85 % conversion); OPA vs cosh² gain and Manley-Rowe; sinc² angle detuning; cascaded-χ(2) phase; QPM averaged vs domains; calculator vs handbook angles (BBO, LBO, KDP, KTP, NC magic angle, PPLN periods); radial vs 1-D overlap; aux beam from saved results; conversion / delayScan / phaseMatchingCurve instruments; C# user element 2e-4 ... 2 % / 0.15°
spatial Hankel quadrature, Gaussian w(z) radial and cartesian, M² = 1, lens focus, thin Kerr lens, energy of a carried profile after spectral broadening, beamProfile instrument 1e-12 ... 2 %
measured input spectra repeated wavelength no longer NaN; 29 out-of-order rows sorted and reported; non-finite rows dropped; a 0.66 % floor shortens the transform limit and background (auto / number) restores it; auto background from the darker edge of a cut-off spectrum; threshold; CSV in descending order; bad background is an error 0.2 ... 2 %
comparisons, satellite window recording wider than the simulated instrument compared on the overlap only; coarser recording matched by blurring; 20 ghosted plates keep a modest window; satellite room sums coincident delays coherently and honours grid.satelliteLevel exact / 1 %
sampling, measured data, fit near/far-field pinhole and slit transmissions vs Gaussian analytics, off-axis pinhole, far-field fibre colour shift on a 1-D beam; CSV/NPZ loading and units; zero residual when data = simulation (curve, d-scan trace, values); normalisations and background; missing files become warnings; pseudo-inverse null space; fit paths (lists, overrides); fit recovers energy and chirp from a spectrum and autocorrelation; unidentifiable parameter flagged; Python comparison, fit and figures 2 % / 1 % / exact
grids exact resampling round trip between derived grids; carrier change SHG → glass; chirped input fits the auto window 1e-9
components Gaussian beam tracking (lens, off-axis mirrors), Zernike / Strehl, plate and end-face ghosts (delay, level, Kerr pre-pulse), ND OD(λ), thick and compound waveplates, TFP Tp / Ts, Faraday rotation and dispersion, GDD ripple, pedestals 10⁻⁴ ... 2 %
gases, ionisation rotational impulse response and revivals, molecular gas data, electronic + rotational n2, PPT / ADK / Keldysh rates and limits, Dawson and elliptic functions, electron density, plasma blue shift, filament clamping (UPPE vs envelope); the Drude filter exp(i (ω/c) Δn(ω) L) of a prepared plasma in the envelope, carrier-resolved and radial models (1e-8, 15 rad), its narrow-band limit, the drift energy U_p of electrons born in the field (2 %), envelope vs carrier-resolved with ionisation (2 %, 1 %) 10⁻⁹ ... 5 %
fibres fundamental soliton over 5 L_D, D(λ) = Taylor, loss / gain / gain goal, tapered γ(z) B-integral, Raman kernels (unit integral, causality, Hollenbeck peak 13.2 THz), dispersive-wave phase matching, quantum-noise energy, coherence of a soliton and of a long-pulse supercontinuum 10⁻³ ... 3 %
instruments (device) spectrometer normalisation modes, settings echo, FROG acceptance (product) and resolution (convolution), AC resolution and acceptance, detector calibration / noise / bits reproducibility, filter in front, polarimeter extinction, every enum value accepted 10⁻¹² ... 5 %
speed, studies, retrieval mixed-radix / Bluestein FFT vs DFT, SIMD = scalar, scans with and without the prefix cache, optimisation, elasticities, Sobol indices; PCGPA, ePIE and d-scan retrieval of chirped pulses 10⁻¹² ... 5 %
transforms, fitting transform phase == dispersion element; filter, energy and loss budget; replica level and grid room; Jones rotation / quarter wave; minimum phase is causal; not-a-knot spline exact for parabolas; every operator inverts; wavefront on a radial profile and 1-D note; ASE pedestal level; schema accepts fit objects; sameAs: two passes of a GDD transform == one element of twice the GDD, each pass sees its own pulse and books its own loss, copies follow a fitted source and save compactly, unknown source / cycle / shared key are errors 10⁻¹² ... 2 %
ASE and stress birefringence (AseStressTests) uniform-inversion ASE = n_sp h ν Δν (G − 1) at both ends, one and two polarisations; non-uniform inversion vs RK4; spontaneous source into 4π = N2 ⟨hν⟩ / τ_rad (Füchtbauer-Ladenburg); slice step vs the saturated-amplifier law; cw photon balance with ASE; depletion vanishes with the solid angle; element reports and the pulse budget closes; stress map unitary, beam average = lumped D, four lobes with alternating sign; pattern in a gain element and its carried y profile 10⁻¹³ ... 5 %
backward propagation linear chain (glass, transform, dispersion) recovers a 60 fs input; nonlinear plate (B > 2) un-broadens to the input bandwidth and peak power; active elements refused / identity / linearised 1 %
fits marked transform parameters from a spectrum (layers, influence, SHA-256 provenance, fitted system on a new input); GDD and TOD from a d-scan; prior-only parameter (σ = prior, influence 100 % priors); instrument resolution as a parameter; CMA-ES from a far start; MCMC 95 % intervals contain the truth; smooth spline phase from a FROG 0.01 ... 5 %
resolution and sampling axis explicit pixels with pixel bins; axis resolution == spectrometer resolution; coarse AC delay steps; dB curves follow their linear curves; input-spectrum deconvolution recovers 2 nm from a 2.83 nm recording; Gaussian tails restore a truncated spectrum; measured-resolution mismatch reported (coarser simulated instrument) or matched (coarser recording) 1 ... 6 %
CPU FFT and compute (ComputeTests) radix-4 Stockham = radix-2 = DFT for every power of two to 2^17; FFTW / Accelerate pass the self-check or say why; compute.fft selects the provider with equal results; allocation-free envelope operator = general operator (scalar, Raman, vector Raman; same steps); auto without a device = CPU 10⁻¹³ ... 10⁻¹¹
GPU (GpuTests, Python test_compute.py) device FFT (contiguous and strided) = managed FFT; 1-D scalar / vector Kerr + Raman + steepening, adaptive and fixed steppers, radial and cartesian spatial and UPPE coupling on the device = CPU (field, B-integral, step count); small / unsupported problems stay on the CPU with a note; 6 concurrent runs on one device = CPU and release their slots; devices self-test passes. Needs an OpenCL or CUDA device: PoCL provides one on any CPU (GPU); skipped otherwise 10⁻⁹ (observed ~10⁻¹⁵)
delayed light (DelayedLightTests) ledger vs brute force: a plate ghost, a mirror echo and a ledger run reproduce one large grid (delay 1e-3, relative peak power 1e-3, total energy 1e-5); the energy budget closes with the tail booked as delayed light (tail); light that leaves the main window returns; the cross-correlator probe sees the ghost, its gate comes from the main field; ghosts follow a table coating's R(lambda)^2; mirror echo delay = 2 n_g d / c (6.35 / 9.5 / 12.7 mm), echo intensity (T r_b)^2 / R, echo = t^2 r_b exp(i psi) exactly (real and imaginary part), leakage follows T(lambda), AR back face, wedge; window warnings name the satellite (delay, level, energy, wrapped position), extendForSatellites, strict, pedestal replicas; coating ripple pedestal sigma^2 within the max delay, amplitude ripple energy 1 - sqrt(2/pi) sigma + sigma^2/2, seed reproducibility; delayed scatter fraction, delay support, mean delay, lambda^-n weight, plate default delay; detector saturation clips the peak and stitching restores the contrast, the floor of an attenuated segment rises as 1/attenuation 1e-3 .. 1e-5 (ledger vs brute), 1 % .. 25 % (random ripple / scatter statistics)
HITRAN plugin (HitranTests, Python test_delayed_light.py) Faddeeva: w(0) = 1, erfcx(1), erfcx(0.1), Re/Im w(1) = e^-1 and 2/sqrt(pi) Dawson(1), continuity at the asymptotic switch; .par and CSV round trips; Doppler width = kinetic formula (0.0141 cm-1); Lorentz line: peak n_d S / (pi gamma_L), dispersion extremum n_d S / (8 pi^2 nu gamma_L) with the right signs; Kramers-Kronig of a Voigt line by a numerical Hilbert transform; temperature and density scaling; environment.air off by default and plain Ciddor reproduces the built-in Air; a gap's own air; energy lost = sum S (1 - exp(-alpha L)); three water lines in a 10 m gap: tail grid (N = 1024 + 262 144) vs one 2 ns window (N = 524 288); Python: builders, the downloader with a fake HITRAN API, a hitran run and a ghost run through the hosted engine 1 % .. 1e-9
small-scale self-focusing (SmallScaleTests) seeded ripple on a flat-top beam in a Kerr plate against Bespalov-Talanov cosh(g z) integrated over the pulse (q = Delta and 3 Delta); diffraction-only ripple = Talbot `2 eps cos(q L)
crossing beams (CrystalChainTests) non-collinear SHG cut against n_e(2ω, θ) = n_o(ω) cos(α/2); sinc² detuning; erf law of overlap; autocorrelation with geometric smearing on a Cartesian grid; 1-D against 2-D energy; output tilts against tangential momentum; arms against the stated angle 0.01°; 1 ... 2 %; 1e-3
delayed light through solvers (HitranTests, DelayedLightTests) lines in nonlinear, radial and vector gaps against the linear gap; a plate's ghost at 2 n_g d / c with intensity R² in every solver; the tail through a spatial element's material 2 %; 1 %, 20 %
non-collinear OPA / DFG (NoncollinearOpaTests) recorded tilts conserve transverse momentum (1e-6); parametric gain G = 1 + (Γ/g)² sinh²(gL) with mismatch against the plane-wave closed form (Cerullo & De Silvestri, RSI 74, 1 (2003)); cut from arm tilts = stated angle; DFG Manley-Rowe; Sequential = Branched 1e-6 ... 2 %
paper replications (docs/papers/, build/paper_check.py, CI job) Escoto 2022 Eq. 2 (C ≈ 0.59 B + 1) and the compressor FWHM (SystemTests); Gordon 1986 SSFS rate = perturbation integral on a coarse grid, T0⁻⁴ (FiberTests); Boyd-Kleinman h_m = 1.068 at ξ = 2.84; Bespalov-Talanov g_max = k0 n2 I 0.5 % ... 5 %
pump-probe (python/tests/test_pump_probe.py, example 41) probe centroid shift under the cross-phase of a delayed pump (opposite circular polarisations, Branched) = −(4/3) k0 n2 L ⟨dI_pump/dt⟩_probe, exact for a pure phase; packetsAtEnd = 1; the pump blocked in the probe channel 2.5 % of the peak shift
regression cases (OpenBugRegressionTests) tilted plate GDD = refracted-colour k_z(ω)·d (tracked and untracked, 1e-5); fed beams at a Sequential splitter keep their carrier and are booked when outside the grid; a spectrum outside the band is an error; probe arrays per packet; leakMirror GDD about the beam's own carrier; reported GDD at the requested carrier (1000 fs² with 2000 fs³ TOD reports 1000 fs²); critical power constant 1e-8 ... 1e-3
measured pedestal (ComponentTests.Pedestal_Measured_FollowsTheRecordedTrace) the pulse's intensity follows the recorded trace on average (csv in dB and arrays; excluded rows and beyond-trace zero) 25 % (random field)
logo generator (python/tests/test_logo.py, assets/logo/make_logo.py) deterministic output; flat coefficient cells below 96 px and Zernike maps above; Zernike modes 2-10 rms-normalised over the disc (Noll 1976); text to the right of the mark, lighter text on the dark-page variant; SVGs are valid XML and the text fits the canvas; the long logo has five tiles then one line of text inside the canvas; the docs copies and favicon are written; the ICO holds seven sizes as PNG exact; 2·10⁻³ (normalisation)
ao devices (AoDeviceTests, 26; 1 slow) deformable mirror tilt, 2 cos(aoi), neighbour coupling, stroke, hex layout; SLM blaze efficiency vs levels [sin(π/N)/(π/N)]², binary-grating orders, liquid-crystal dispersion, nearest grey level, 1920 x 1080; AOPDF delay, GDD (Diels and Rudolph), window, replica; spectral shaper side pulses [sin(πf)/(πf)]² exp(-2(π w0/p)²) (Weiner 2000), grating dispersion at Littrow, grid-planner room and wrap warning for shapers 0.6 % ... 1e-9
ao algorithms and plugin (python/tests/test_ao_algorithms.py, test_ao_plugin.py) GS error monotone (Fienup 1982), WGS uniformity, Bolduc and double-phase encoding, Shack-Hartmann spot shift f dW/dx, Southwell reconstruction; Strehl against Maréchal exp(-σ²), correction and loop (1 - g)^k, modal search, GS hologram through the slm element (correlation 0.9995), tiled array N, piston ` Σe^{iφ}
fitting across conditions (FittingConditionsTests, 15) shared parameters from two conditions (1e-3); held-out predicted within the noise, and flagged when the model cannot predict it; per-condition resolutions; nonlinear-phase slope from five energies (1e-3); every dependence kind against its formula (1e-12); a smooth surface; network constraints hold exactly for 50 random weight sets 1e-12 ... 3 %
twin plugin (python/tests/test_twin.py, 9; PluginTests) the fit recovers the hidden centre, width and slope of the synthetic lab; held-out energies inside and outside the training range predicted (chi² per point about 1); a saturating lab is flagged fits-training-only; stored dependences reproduce the fitted values (1e-9); the planner ranks the placements and a zero-energy shot cannot see the slope; paired what-if; the drift tracker follows a 0.5 nm shift; benchmark 3 of 3; goal files; ultrafast twin registered and a missing interpreter exits with 2 1e-9 ... 3σ
branched-system plot (python/tests/test_plot_graph.py) layers and lanes of a Mach-Zehnder graph; the system figure draws every element exact
components (Components/: ComponentSheet, LinearComponentTests, InstrumentCrystalComponentTests) component sheet at 515 nm / 1030 nm / 2 µm and 1 ps / 10 fs: energy and loss budget, reported GDD vs analytic (Sellmeier × Ciddor, Treacy), bandwidth, Sequential = Branched (1e-12); leakMirror GDD per port; fed beam of another colour keeps its carrier; sech² AC ratio 1.5427, TOCC √(3/2), SHG-FROG marginal; Python scripts with plots (10 families, 1694 checks, 24 KNOWN engine disagreements): Component tests 1e-12 ... 1e-3
pulse calculator (PulseCalculatorTests; Python test_setup_and_calc.py) TBP of Gaussian 2 ln2/π = 0.4413, sech² 0.3148, rectangular 0.8859 (Diels and Rudolph); Δν = cΔλ/λ²; chirped-Gaussian GDD from τ = τ₀√(1+(4 ln2 GDD/τ₀²)²); a sampled Gaussian gives ratio 1 and rms product 1/(4π); source-build front door (build/setup.py --dry-run, plugin dependencies) and install.py --preset against a synthetic release 1e-5 ... 1 %
crystal chains (CrystalChainTests) SHG then SFG: Manley-Rowe photon balance, main and fed beams swapped, 31.3° THG cut of BBO at 1064 nm (Dmitriev), cross-correlation FWHM of Gaussians; efficiency as L² then L past τ / GVM; SH bandwidth 0.886 / (GVM L); tilted arm warns, non-collinear sfg refused 1e-3; 0.3°; 1 ... 3 %
diffraction by apertures (DiffractionTests) plane wave through a round iris: on-axis 4 F sin²(πN/2) (Born & Wolf 8.8) at N = 3, 2, 1; Gaussian and flat-top through an iris vs the Fresnel integral over the whole profile and transmission 1 − exp(−2a²/w²); square flat-top through a square aperture vs the separable Fresnel integral (512²); far zone: first Airy ring 0.61 λz/a, first sinc² zero λz/2a; area-averaged hard edges on coarse and fine grids, warning under 10 samples; absorbing boundary (wrapped light removed, loss budget closes); linear profile-only path = full-field path; square shapes need a cartesian grid; test_double_slit_matches_the_fresnel_integral: a Gaussian on two slits vs a direct sum of the Fresnel kernel 1 ... 2 % of the peak (observed 0.02 ... 0.7 %); 10⁻⁴ (paths)
modulator (ModulatorTests) tilt moves the focus by f θ; a quadratic phase focuses like a thin lens; N-level blaze efficiency [sin(π/N)/(π/N)]² (also the exact sampled staircase); fill-factor transmission and replica orders; gaps and edge cells are area averages; rotation; wrapped ramp = grating (x₁ ∝ λ) and unwrapped ramp = prism; fixedPhase; index rule (constant Δn = opd; = fixedPhase × α; blaze efficiency at depth α); cross-talk kernel convolution; inline / file / callback maps identical and N loop trials = N file runs (1e-12); cw = narrow pulse; one stored frequency at the carrier; sampling-error law 1/K², warning, and bound on the true error; zero-order leak; quantisation wrap; wavefront-sensor slope maps (tilt, defocus) 1e-12 ... 2 %; a cw line on the requested carrier equals the one-stored-frequency pulse (1e-9), snapped lattice only when snapCarrier is written
coherent tiles (TileSourceTests) N in-phase tiles give N × the single-beam peak; grating lobes at λ f / pitch; piston errors give |Σ e^{iφ}|² / N²; delay mismatch (1 + e^{−ln2 (τ/T)²}) / 2; hex / ring / explicit layouts; tilted tile focuses at F θ; tophat slit far field; unequal amplitudes; delay sign exact ... 3 %; four tiles with pistons against a Branched balanced tree recombined at one point (1e-6 against the formula, 1.5 % tile source)
large spatial runs (SpatialStreamingTests) streaming over stored frequencies (frequencyBlock) = all at once (1e-12); keepProfiles: "used" drops unread profiles with identical results, also in a prefix-cached study; one stored frequency is the centroid (or the nearest lit bin); cylindrical lens focuses one axis (λ f/π w) and leaves the other to diffract; slow: a 1920 × 1080 cw panel within 4 × the spike's time, its Gaussian power on the panel, and at least one profile less held with used 1e-12 ... 2 %
beam sources and masks (BeamSourceTests) Airy function and polynomials vs tables; Hermite-Gauss and Laguerre-Gauss radii, dark vortex axis, LG node; Durnin Bessel core over 6 Rayleigh ranges; Siviloglou & Christodoulides Airy trajectory; measured near field; zone plate 4 N² / 16 N² on the axis; axicon core; Young's fringes; vortex plate; file mask 1e-12 ... 5 %; one-row measured scenes and mask files on grids with ny = 1, 4, 128
cw, nonlinear boundary, retrieval (FieldToolsTests) cw through an iris: Fresnel intensity; Kerr phase of a cw beam; absorbing layer in the stepper vs the linear path; Gerchberg-Saxton on a known phase; phase map round trip; PNG near field with background, centre, threshold 1e-3 ... 3 %
cavities and coherence (CavityAndCoherenceTests) Kogelnik & Li eigenmode; two-mirror formulas; Fox-Li vs ABCD; plane-mirror loss N^(−3/2) (Fox & Li); Gaussian-Schell M² law; Koechner depolarisation and bifocal lens; amplifier lens per pass 1e-3 ... 25 %
branched systems (BranchingTests) carrier phase of glass; Mach-Zehnder fringes, spectral fringes pinning the sign; separate packets; Airy function; ring pulse train; steady-state loop; every graph check, port form and alert; virtual beams; branch-fed crystal against aux; modelled autocorrelator √2 τ 1e-9 ... 1 %
physics review (PhysicsReviewTests) dispersed beam in glass; reversed return pass in a linear cavity; Gaussian stress depolarisation; Fox-Li that must not claim a mode; mode truncation; profile tilt of a prism; curvature sign 1e-6 ... 2 %
splitter family and space (BranchedElementsTests) Gouy phase; Michelson fringes; Malus; leak, dichroic; Gaussian overlap in tilt and offset; tilt fringes λ/θ of carried profiles; harmonic phase; crystal ports; tail through a splitter; f-2f following the CEP 1e-9 ... 3 %
modelled instruments (ModelledInstrumentsTests) IAC 8:1; FTS (Wiener-Khinchin) against the input; FROG marginal √2 τ; study node cache and array outputs 0.2 ... 2 %
review regressions (ReviewRegressionTests) M² of tilted, decentred, Hermite-Gauss and Laguerre-Gauss beams (2m + 1, 2p + |l| + 1) on each axis; centroid radius; packets at end; packets at crystal ports; passive steadyState; all-pass ring
beam tracking (BeamTrackingTests) thermal lens on the tracked beam: small beam = Innocenzi πKw_p²/(P_h dn/dT); the thermal lens as a graded-index duct (ABCD cos gL, sin gL / n0 g, thin-lens and hyperbolic limits 1e-12; N thin slices converge as 1/N²; a thick rod against the exact duct 1e-9); a measured effective focal length; N regenerative round trips = N multipass passes (1e-12); tracked radius vs the radial spatial gain model (7 %, aberrated lens). Spatio-temporal couplings (Kostenbauder): grating angular dispersion and Hebling pulse-front tilt; grating + gap + grating = gratingPair (Treacy GDD, spatial chirp); pulse-front tilt from spatial chirp and GDD vs the Gaussian result (Akturk 2005); prism vs Snell at both faces; 4f zero-dispersion stretcher GDD = 0; physics.spatioTemporal modes 0.1 ... 7 %
material catalogue (CatalogueSnapshotTests, CatalogueTests) every built-in index, n2, Raman kernel, rotational line and ionisation datum pinned to 1e-15 (the move of the tables into catalogue files was a pure refactor); catalogue files lint (source and status on every quantity, an uncertainty on every unverified one, units in the key names); verified dispersion sets record their comparison with the database page; published indices (Malitson fused silica n_d = 1.45846, Schott N-BK7 n_d = 1.5168, Dodge MgF2); a user catalogue replaces a quantity with a notice and can add a material; a run lists exactly the approximate / unverified values it used and not the ones the user overrode; gain media and crystals report theirs (thermal data only with a thermal lens, a given deff or doping replaces the catalogue's); Ciddor standard air equals the database formula (1e-12); physics.strictMaterials / ULTRAFAST_STRICT_MATERIALS refuse unverified values and accept overrides and user-verified ones 1e-15 ... 1e-4
delayed light, follow-ups (DelayedLightTests) smooth elements skip the exact long-grid step with the same result (energy 1e-9, power 1e-6) and are counted; first-order cross-phase of the tail vs the full nonlinear difference field (B = 0.11: 7.5 %); analytic surface scatter: in-mode share = numerical integral of the roughness spectrum, lost power TIS (1 - g), lambda^-2, returned power g TIS, plate has 2 surfaces; detector spectral response = table, photon counting = x lambda, presets (run spec name, file, overrides, unknown name) 1e-12 .. 15 %
HITRAN, partition sums and real lines (HitranTests) partition table interpolation and range check; strength follows the table (T^-3 vs T^-1.5); <NAME>.partition.csv found next to the lines; opt-in real H2O, CO2, O2 lines at 250 / 296 / 350 K vs HAPI (ULTRAFAST_HITRAN_VALIDATE_DIR, plugins/hitran/tools/make_hapi_reference.py) 1 % integrated, 4 % worst point
release assets and installer (test_release.py) component resolution (dotted names, dependencies, excludes, all without media, platform choice, conflicts); install.py against a local release: select, add, upgrade, uninstall leaves nothing, a changed file is kept, a file it did not install is not overwritten, hash mismatch installs nothing, unsafe paths and ZOS-API archives refused; the ZOS-API gate finds a planted file in an archive and in a wheel inside one; manifest merge; the git sparse checkout and uninstall in a temporary repository; the packager writes and installs real source assets exact
release packaging build/package.py: platform aliases, plugin selection, ZOS-API assemblies never copied, the wheel writer (metadata, extras, entry point, RECORD hashes), dry run (Python test_packaging.py) exact
cross-code N ~ 2.4 higher-order soliton with TOD and self-steepening vs pyNLO: bulk medium and fiber element, no Raman, Blow-Wood Raman, Lin-Agrawal Raman (pyNLO's weights), flat gain < 0.3 % (gain 0.5 %)
cross-code spatial engine vs LightPipes (test_lightpipes.py, skipped without it): fluence maps through free space, lenses, cylinder, curved mirror, tilt, decentre, HG, eight Zernike terms, vortex handedness, axicon, apertures, double slit, Talbot, glass; branched Mach-Zehnder vs BeamMix with tilt and phase; tracked Gaussian vs wave optics 0.1 % smooth beams; 3 to 10 % hard edges, limited by LightPipes' 0/1 masks at N = 256
cross-code Raman soliton self-frequency shift, T0 = 50 fs, N = 1, 3 to 6 m (test_raman_shift.py, slow): engine vs pyNLO rate (1 %), vs the exact-gain rate of a fixed-width soliton -γ f_R ∫ (h_R * P) P' dt / E (3 %), Gordon's first-moment rate 20-30 % low; the exact rate reduces to Gordon's for a narrow response (1 %) 0.3 % ... 3 %
cross-code branched arms vs pyNLO (test_pynlo_branched.py): a fibre after a splitter, before one, and in both arms of a Mach-Zehnder 0.5 %
cross-code DFG 1064 + 1550 → 3.39 µm in MgO:PPLN vs pyNLO three-wave mixing (energies, idler spectrum) 0.1-0.7 % small signal, 0.5 % at gain 50

pyNLO

python/tests/test_pynlo.py runs the same fibre in pyNLO and UltrafastEngine (identical grid, dispersion, gamma, self-steepening, Raman model, gain) and compares temporal profiles, spectra, energy and peak power -- once as a bulk medium with a constant beam, and once through the fiber element. Agreement is better than 0.3 % (L1 distance of the profiles) with and without Raman. Two details matter at that level: the engine normalises the sampled Raman kernel on the time grid (as pyNLO does), and pyNLO's "full" (Lin-Agrawal) model carries a unit-dependent normalisation of its oscillator part, which the test reproduces with explicit weights (Fibres). pyNLO is optional: set PYNLO_SRC to a checkout's src (fetch the pinned commit with python python/tools/get_pynlo.py); the test applies small shims for current NumPy/SciPy.

python/tests/test_pynlo_dfg.py compares the crystal element with pyNLO's dfg_problem (Boyd's coupled-amplitude equations, domain-resolved poling, plane-wave coupling at the pump waist). The engine is set up identically: MgO:LiNbO3 at 24.5 °C (same Gayer Sellmeier), deffPmPerV 14.9, pyNLO's period (designed with ΔkL = 3.2), qpm.model: "domains" with phaseDeg: 90, overlap: {"model": "planeWave", "radiusM": 100e-6}, chi3: false. pyNLO's three-wave code needs a few more shims (the Python-2 exceptions module, a NumPy stand-in for two pyfftw calls), applied by conftest.import_pynlo(); the high-gain case is slow (ULTRAFAST_SLOW=1). | grid, carrier and solver accuracy (GridSolverTests, BeamSourceTests) | pulse centred on the requested carrier; pure SPM phase = γPL on every grid at 515 nm, 1030 nm and 2 µm; grating angular dispersion = grating equation (1e-6); round aperture on an elliptical beam = 2-D quadrature; strongly phase-mismatched SHG follows sin² at the default stepper; delayed-response memory in the planned window; element-level selfSteepening; D(λ) table β2 (2e-4); zero-frequency warning; binaryPhase edge loss | 1e-6 ... 3 % | | instrument fixes (InstrumentFixesTests) | energy-meter band edges vs the Gaussian CDF (0.5 %); interferometric autocorrelator peak : background = 8 for five pulses; cross-correlator trace / floor / report consistent with resolutionS; gate-arm plate ghosts at R^(2k) | 0.2 ... 3 % | | FROG kinds and retrieval (FrogKindsTests, MultiTraceRetrievalTests, python/tests/test_retrieve_kinds.py) | PG and SD trace centroid slopes 2b/3 and 4b/3 (Kane & Trebino 1993, App. C); XFROG slope and sum frequency; PCGPA and ePIE retrieval of ±300 fs² pulses with the sign; kind inference; double FROG retrieves the right time direction in six of six starts (Kida et al. 2014) | 2 ... 6 % | | materials and crystals (MaterialsCrystalsTests, NerTests) | KDP d_eff ∝ sin 2φ for every φ at fixed θ; CS2 index (Kedenburg, handbook) and GDD (0.3 %); orientational CS2 response and circular/linear phase; anisotropicFraction b ∈ {0, 0.25, 1, 1.5} against the Hellwarth tensor; cubic Kerr: XPW ∝ sin²(4β) in a [001] cut, SPM index 1 − (σ/2) sin²2β; BaF2 index | 0.3 ... 4 % | | multi-pass cell mode and single-shot correlator (CellModeTests, SingleShotCorrelatorTests, python/tests/test_cells.py) | empty cell vs Kogelnik-Li (1e-9); Herriott closure Nθ = 2πk; thin Kerr lens shift (0.3 %); second-moment Kerr lens vs the radial model (rms radius 0.3 %); single-shot window and resolution vs Ma et al. 2018 eqs. 1-2 (1e-9); a pre-pulse at the right position; area conservation; spatial SFG of crossed beams | 1e-9 ... 3 % | | Python package structure (test_structure.py) | every public name of 2.2.0 still imports (committed list, 13 modules); ultrafast.diagram warns and is the new module; import ultrafast loads neither matplotlib nor Pillow and raises no warning; CapWords names are the builder functions; every public builder is grouped or on the build-only list | exact | | Zernike, plots and animation (test_zernike.py) | Noll table; orthonormality over the unit disc by polar quadrature; fit recovers coefficients (off-centre pupil, NaN points); rms and Maréchal Strehl; the Python fit of the engine's wavefrontSensor map equals the sensor's coefficients; a complex field's phase is the wavefront; GIF frames, size, loop and a held last frame; size budget check | 1e-12 ... 1e-6 | | Computing examples (test_computing.py) | the numpy twin of a 4f system (inversion through the origin); a lens at f = N dx² / λ is the DFT matrix (correlation > 0.9999); the shift theorem moves the image by 3 pixels (0.05 px); each example's own checks (matched filter peaks at the pixel of each T, convolution theorem, circulant matrix, scaling) | 2e-2 ... 5e-2 | | Examples wheel (test_examples_package.py) | build/package.py --examples-wheel metadata and contents (no results, figures scripts or ZOS-API files); ultrafast-examples list / copy bring dependencies and shared files; run executes the README commands in a copy | exact |

Adding tests

Every physics feature comes with a test against an analytic result, a conservation law, or another code. Prefer small grids (N <= 4096) and mark anything over ~10 s as [Test(Slow = true)].