Skip to main content

thunder4D

Transverse-resolved Herriott-cell UPPE solver for Nonlinear Dynamics close to Experimental Reality, 4D: a 4D (x, y, z, t) UPPE solver for multipass cells. Python package: thunder4d.

Full documentation: https://victorkolt.github.io/thunder4D/.

thunder4D simulates nonlinear pulse propagation in a gas-filled Herriott-type multipass cell (MPC) with full spatial and temporal resolution: the field is A(x, y, t) and it is propagated along z. It is built to study spatial and spatio-spectral effects that 1D or radially symmetric codes cannot capture:

  • spatial effects in non-Gaussian inputs (clipped, aberrated, high-order beams),
  • spatio-spectral homogeneity, radial chirp,
  • time-dependent nonlinear mode mismatch,
  • influence of space-time couplings (spatial chirp, pulse-front tilt, …) on the output.

The code is pure Python. NumPy (≥ 2.0) is required. SciPy is optional but strongly recommended, because scipy.fft is about 8× faster than numpy.fft for the 2D transforms. Matplotlib is only needed for the examples. An NVIDIA GPU is optional: with CuPy installed (pip install cupy-cuda12x), suggest_grid(..., device="auto") (the default) runs the propagation on the GPU, and device="cpu" / "gpu" force one or the other. thunder4d.gpu_available() tells you whether CuPy works; thunder4d.to_host(array) converts a device array to NumPy. Everything returned by thunder4d.diagnostics is a NumPy array on either device.

Quick start

import thunder4d as m
from thunder4d import diagnostics as dg

# medium and cell
gas  = m.Material("Ar", pressure_bar=1.0)
cell = m.MPC.herriott(R=0.5, N=20, k=3, branch="planar", medium=gas)  # 20 passes, 54 deg Gouy/pass, re-entrant

# grid sized from the cell
grid = m.suggest_grid(cell, lambda0=1030e-9, lambda_min=900e-9, lambda_max=1200e-9, pulse_fwhm=200e-15, box_factor=12)
print(grid.describe())

# 1) spectrum (+ phase)
E = m.gaussian_spectrum(grid, fwhm_fs=200)
E = m.add_spectral_phase(grid, E, gdd_fs2=0)

# 2) nonlinear mode matching, computed from a probe pulse of the right energy
probe = m.Pulse.at_focus(grid, E, m.Beam(m.gaussian(1e-3)), 1.2e-3)
mm = cell.match(probe)

# 3) the actual input beam
pulse = m.Pulse.at_focus(grid, E, m.Beam(m.gaussian(mm["w0"])), 1.2e-3)

# 4) run
sim = m.MPCSimulation(pulse, cell, phi_max=0.02, mode_reference=mm["w0"], profile_wavelengths=[1010e-9, 1030e-9, 1050e-9], profile_bandwidth=2e-9)
sim.run()
sim.save("run.npz")

# 5) analyse the output
x, lam, S = dg.spectrogram_x_lambda(grid, sim.Aw)
c = dg.compress(grid, sim.Aw)
print(c["fwhm_fs"], c["gdd_fs2"])

Physical model

The field is a complex envelope A(x, y, t) with carrier exp[i(k₀z − ω₀t)], normalised so that |A|² is the intensity in W/m². It is propagated with the unidirectional pulse propagation equation (UPPE), written in the frame moving at the group velocity at λ₀:

∂A(kx, ky, Ω)/∂z = i [ kz(kx, ky, ω) − k₀ − k₁Ω ] A  +  i γ(Ω) FT_t[ |A|² A ]

kz   = sqrt( k(ω)² − kx² − ky² )        (non-paraxial, full gas dispersion)
k(ω) = n(ω) ω / c,   ω = ω₀ + Ω,   k₁ = dk/dω at ω₀
γ(Ω) = n₂ ω/c · n(ω₀)/n(ω)               (self-steepening included)
  • Linear operator: it is exact. It includes diffraction without the paraxial approximation, gas dispersion to all orders, and evanescent components, which decay.
  • Kerr term: it is the instantaneous electronic response. Its frequency dependence gives self-steepening. With self_steepening=False it becomes γ = n₂ω₀/c.
  • Edge taper: the nonlinear source is tapered to zero at the edges of the spectral window to avoid aliasing.

Numerical scheme

  • Home domain: the solver keeps the field in the mixed domain (x, y, Ω).
    • The linear step needs only 2D spatial FFTs, because Ω is already a coordinate.
    • The Kerr term does not depend on (kx, ky), so it needs only 1D temporal FFTs.
  • Splitting: symmetric Strang splitting (linear half-step, nonlinear step, linear half-step). Consecutive linear half-steps are merged.
  • Nonlinear step: fourth-order Runge–Kutta.
  • Adaptive step size: h = φ_max / (k₀ n₂ I_peak), where φ_max is the peak nonlinear phase allowed per step. It is limited to dz_max (default d/8, a quarter of a half-pass) and quantised to dz_max · 2^(−n/4). The quantisation lets the linear propagators exp(iDh) be reused from a small cache.

Performance and memory

  • Cost per step: 2 spatial 2D FFTs, 8 temporal 1D FFTs (RK4) and a few array operations. With SciPy on one core, a 150 × 150 × 135 grid takes about 0.1–0.4 s per step. A 20-pass run at B ≈ 16 rad needs about 900 steps.
  • Steps per pass: they scale with the B-integral per pass divided by phi_max.
  • Memory: about 8–10 field arrays: the field, RK4 buffers, the linear operator D, up to cache_size cached propagators and the cached mirror transfer. One complex64 array is Nx·Ny·Nt·8 bytes, so 256 × 256 × 256 is 134 MB.
  • Speed-ups:
    • SciPy backend with all cores (fft_backend="scipy", workers=-1, the default with "auto").
    • record_every > 1, or near_field=False (near-field diagnostics, i.e. of the collimated beam, use per-colour matrix transforms).
    • Fewer profile_wavelengths.
    • A smaller cache_size if memory is tight.
  • Long runs: use run(max_seconds=…) with checkpoint / resume.

Limitations

Not included

  • Ionisation and plasma: fine for MPCs operated well below ionisation thresholds.
  • Raman response: relevant for N₂, air and other molecular gases.
  • Off-axis geometry: the real cell is folded, so the beam hits the mirrors at small angles. The resulting astigmatism and the actual spot pattern are not modelled; the unfolded on-axis picture is used.
  • Non-uniform media: gas plates, windows or pressure gradients are not built in. The nonlinear mode matching formula also assumes a uniformly filled cell with constant power during a pass.
  • Vectorial effects: the field is scalar, with a single polarisation.

Metadata

Release files for thunder4d 0.9.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for thunder4d 0.9.2
File Size Uploaded Provenance Actions
thunder4d-0.9.2.tar.gz 33.1 kB With provenance Details for thunder4d-0.9.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for thunder4d 0.9.2
File Interpreter ABI Platform Actions
thunder4d-0.9.2-py3-none-any.whl Python 3 none any Details for thunder4d-0.9.2-py3-none-any.whl

Total release size: 66.6 kB

Release files / thunder4d-0.9.2.tar.gz

Download URL thunder4d-0.9.2.tar.gz
Size 33.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3f7aaefc8d0828045c7b45f9c176689f07f4de3bc5ed679141732fefc5208fb0
BLAKE2b-256 checksum
How to use checksums
8e6aaeb842b432b7c196e3b353526d764c334d5bc79059b48fa5521a955c2ccd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Release files / thunder4d-0.9.2-py3-none-any.whl

Download URL thunder4d-0.9.2-py3-none-any.whl
Size 33.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c0b0a66825c5b25badba2a0bc7f8d2934f2676e408d0a398e68e76c63bd55b9
BLAKE2b-256 checksum
How to use checksums
5fdcf2137d7b25625856a2636989967cef602c103995a066510b333051161e9f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

Security for thunder4d 0.9.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for thunder4d-0.9.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page