Skip to content

Generalized nonlinear Schrödinger equation

Full GNLSE solver: dispersion, Kerr, Raman, self-steepening, TPA, adaptive steps. Docstrings are the source of truth, rendered with mkdocstrings (numpydoc style).

photonics_helper.gnlse

Generalized nonlinear Schrödinger equation (GNLSE) solver.

Split-step Fourier solver for pulse propagation through nonlinear media, supporting Kerr, Raman, self-steepening, and two-photon absorption effects.

BetasUnit module-attribute

BetasUnit = Literal['ps^k/m', 's^k/m', 'SI']

FigureLike module-attribute

FigureLike: TypeAlias = MplFigure | PlotlyFigure

HBAR_J_S module-attribute

HBAR_J_S = 1.0545718e-34

FiberProfile dataclass

FiberProfile(n2: float, alpha: float, A_eff: Area, length: Length, confinement_factor: float = 1.0, sigma_tpa: float = 0.0, carrier_lifetime: Time | None = None, raman_response: object | None = None, beta_tpa: float = 0.0, sigma_fca: float = 0.0, group_velocity: float | None = None)

Optical fiber/waveguide parameters for GNLSE propagation.

Attributes: n2: Nonlinear refractive index n₂ (m²/W). alpha: Fiber loss coefficient α (1/m). A_eff: Effective mode area (m²). confinement_factor: Waveguide confinement factor Γ (1.0 for fibers, <1.0 for waveguides). sigma_tpa: Two-photon absorption cross-section (m²·W⁻¹). Default 0. carrier_lifetime: Carrier recombination lifetime (s). Default None. length: Fiber length (m). raman_response: Raman response function. Default None. beta_tpa: Two-photon absorption coefficient β_TPA (m/W) for the time-resolved free-carrier model. Default 0. sigma_fca: Free-carrier absorption cross-section σ_FCA (m²) for the time-resolved free-carrier model. Default 0. group_velocity: Envelope group velocity v (m/s) converting the carrier lifetime to a propagation length. Default None → C_MS.

n2 instance-attribute

n2: float

alpha instance-attribute

alpha: float

A_eff instance-attribute

A_eff: Area

length instance-attribute

length: Length

confinement_factor class-attribute instance-attribute

confinement_factor: float = 1.0

sigma_tpa class-attribute instance-attribute

sigma_tpa: float = 0.0

carrier_lifetime class-attribute instance-attribute

carrier_lifetime: Time | None = None

raman_response class-attribute instance-attribute

raman_response: object | None = None

beta_tpa class-attribute instance-attribute

beta_tpa: float = 0.0

sigma_fca class-attribute instance-attribute

sigma_fca: float = 0.0

group_velocity class-attribute instance-attribute

group_velocity: float | None = None

from_gamma classmethod

from_gamma(gamma: float, n2: float, omega0: float, alpha: float = 0.0, length: Length = Length(1.0, 'm'), confinement_factor: float = 1.0, sigma_tpa: float = 0.0, carrier_lifetime: Time | None = None, raman_response: object | None = None, beta_tpa: float = 0.0, sigma_fca: float = 0.0, group_velocity: float | None = None) -> FiberProfile

Create a FiberProfile from a target nonlinear coefficient γ.

Convenience constructor that mirrors laserfun's API where γ is specified directly (e.g. gamma_W_m) rather than deriving it from n₂ and A_eff.

Parameters:

Name Type Description Default
gamma float — target nonlinear coefficient γ in 1/(W·m).
required
n2 float — nonlinear refractive index n₂ in m²/W.
required
omega0 float — carrier angular frequency in rad/s.
required
alpha float — fiber loss coefficient α in 1/m. Default 0.
0.0
length Length — fiber length. Default 1 m.
Length(1.0, 'm')
confinement_factor float — waveguide confinement factor Γ. Default 1.0.
1.0
sigma_tpa float — two-photon absorption cross-section. Default 0.
0.0
carrier_lifetime Time — carrier recombination lifetime. Default None.
None
raman_response object — Raman response function. Default None.
None
beta_tpa float — two-photon absorption coefficient β_TPA in m/W.

Used by the time-resolved free-carrier model (SplitStepEngine(include_free_carriers=True)). Default 0.

0.0
sigma_fca float — free-carrier absorption cross-section σ_FCA in m².

Used by the time-resolved free-carrier model. Default 0.

0.0
group_velocity float | None — envelope group velocity v in m/s used

to convert the retarded-time carrier lifetime into a propagation length. Default None → the vacuum-light-speed constant.

None

Returns:

Type Description
FiberProfile — configured with the computed A_eff.
Notes

Computes A_eff = n₂·ω₀·Γ / (c·γ) from the relation γ = n₂·ω₀·Γ / (c·A_eff).

SplitStepEngine

SplitStepEngine(pulse: Wave, fiber: FiberProfile, betas: NDArray, include_raman: bool = False, include_self_steepening: bool = False, include_tpa: bool = False, include_free_carriers: bool = False, conserving_shock: bool = False, tau_shock: float | None = None, step_size: Length | None = None, dispersion_profile: ZDependentDispersion | Callable[[NDArray, float], NDArray] | None = None, a_eff_fn: Callable[[float], float] | None = None, alpha_fn: Callable[[float], float] | None = None, gamma_fn: Callable[[float], float] | None = None, min_shrink_factor: float = 0.1, betas_unit: BetasUnit = 'ps^k/m')

Split-step Fourier engine for GNLSE propagation.

Alternates linear (dispersion) and nonlinear (Kerr/Raman/steepening/TPA) steps in Fourier space with adaptive step sizing.

Parameters:

Name Type Description Default
pulse Wave

Input pulse.

required
fiber FiberProfile

Fiber parameters.

required
betas array_like

Dispersion coefficients [beta2, beta3, ...] in ps^k/m (with Ω in rad/ps), as returned by Dispersion.get_betas(). Pass betas_unit="s^k/m" (or "SI") to supply SI coefficients instead; they are converted to ps^k/m internally.

required
betas_unit ('ps^k/m', 's^k/m', 'SI')

Unit of betas. Default "ps^k/m" (native internal form).

"ps^k/m"
include_raman bool

Include Raman. Default False.

False
include_self_steepening bool

Include self-steepening (shock term). Default False.

When enabled, the shock operator (1 + (i/ω₀)∂t) of Blow & Wood (1989) and Dudley–Genty–Coen RMP 78, 1135 (2006), Eq. (3), is integrated with an interaction-picture scheme (τ_shock settable, default 1/ω₀): the exactly-integrable Kerr/Raman phase exp(iγP_NL Δz) is factored out and only the shock correction iγτ_shock ∂_t(A·P_NL) is advanced with frequency-domain RK4 (the RK4IP idea of Hult 2007 / Hochbruck & Ostermann 2010). The shock factor is never clamped (see :meth:_validate_shock_grid). Enable explicitly for cross-library comparisons; laserfun defaults to shock on (but its shock term has the opposite linear-in-Ω asymmetry).

Sign audit (2026): the multiplier 1 + Ω·τ_shock is the correct physical factor ω/ω₀ under this codebase's FFT convention. The grid FFT uses the numpy e^{−iΩt} kernel while the linear dispersion step, all spectral plots, and the DW/MI utilities map bin W to optical frequency ω₀ + W; that fixes the carrier convention to e^{+iω₀t} and makes W > 0 the blue side. The convention set was verified numerically to be self-consistent: (i) Raman-only soliton propagation red-shifts under the same mapping (Gordon SSFS), (ii) a fundamental soliton with shock and β₂ only develops a blue-shifted centroid and positive spectral skew with 1 + Ω·τ and the mirror-image red shift with 1 − Ω·τ, and (iii) energy is conserved. laserfun's opposite raw-bin asymmetry follows from its own (unshifted-FFT) convention, not from different physics.

False
include_tpa bool

Include TPA (legacy spatially-averaged carrier model). Default False.

False
include_free_carriers bool

Include the opt-in time-resolved TPA / free-carrier model: the carrier population N(t) is resolved over the retarded-time grid instead of spatially averaged, driven by β_TPA |A|⁴/(2ħω₀) generation and N/(τ_c v) recombination, with the field attenuated by the TPA term −(β_TPA/2)|A|²A and free-carrier absorption −(σ_FCA/2)N·A (Soref & Bennett 1987; Cowan et al. 2003; Yin & Agrawal 2007). Requires fiber.beta_tpa / fiber.sigma_fca; free-carrier refraction (μ), diffusion and drift are out of scope. Default False.

False
tau_shock float | None

Shock (self-steepening) timescale in seconds (SI). None (default) uses 1/ω₀ at the pulse carrier frequency, matching Agrawal and the uncorrected Dudley Eq. (3) value (0.443 fs at 835 nm). Pass an explicit value for the effective-area-corrected timescale (Dudley–Genty–Coen RMP 78, 1135 (2006), Sec. V.B: tau_shock = 0.56e-15 for the Fig. 3 PCF config). Must be > 0.

None
conserving_shock bool

Enable the photon-conserving (pcGNLSE) shock operator. Default False. The modification substitutes |γ| for γ on the delayed (Raman) arm only; the instantaneous SPM/SS arm keeps the signed γ. Note: for any fiber with γ > 0 (every ordinary dielectric), abs(gamma) == gamma and the two paths are identical — the flag is a no-op. It only has an effect when γ < 0 (the sign bench used in reproductions/huang_202x_pcgnlse_attractors/). Requires include_raman=True and a Raman response.

False
step_size Length | None

Fixed step size (m). If None, adaptive stepping is used.

None
min_shrink_factor float

Floor for the gradient-based step shrink factor in z-dependent mode. Must be in (0, 1]. Default 0.1.

0.1

pulse instance-attribute

pulse = pulse

fiber instance-attribute

fiber = fiber

betas instance-attribute

betas = _normalize_betas(betas, betas_unit)

include_raman instance-attribute

include_raman = include_raman

include_self_steepening instance-attribute

include_self_steepening = include_self_steepening

include_tpa instance-attribute

include_tpa = include_tpa

include_free_carriers instance-attribute

include_free_carriers = include_free_carriers

conserving_shock instance-attribute

conserving_shock = bool(conserving_shock)

step_size instance-attribute

step_size = step_size

gamma_fn instance-attribute

gamma_fn = gamma_fn

grid instance-attribute

grid: TemporalGrid = pulse.grid

omega0 instance-attribute

omega0 = pulse.central_frequency

A instance-attribute

A = np.array(pulse.envelope_field, dtype=complex)

evolution instance-attribute

evolution: list[Wave] = []

tau_shock property

tau_shock: float

Shock timescale in seconds (SI): explicit override or 1/ω₀.

z_array property

z_array: NDArray

Array of propagation distances (m) for each evolution entry.

spectra_vs_z property

spectra_vs_z: tuple[NDArray, NDArray]

Tuple of (frequency array, spectra at each step).

energy_vs_z property

energy_vs_z: NDArray

Pulse energy Σ|A|²·dt at each saved step (same length as z_array).

propagate

propagate(num_steps: int, *, nsaves: int | None = None, show_progress: bool = False, raman_noise: bool = False, noise_seed: int | None = None) -> None

Run split-step simulation for num_steps steps.

Parameters:

Name Type Description Default
num_steps int

Target number of split-steps along the fiber (actual integration steps may be higher if adaptive stepping shrinks dz below length/num_steps).

required
nsaves int

Number of evenly spaced snapshots to retain along z (including z=0 and z=L). If None, every integration step is stored (can use many GB for long runs). Use ~200 for contour plots, as in laserfun's NLSE(..., nsaves=200).

None
show_progress bool

If True, show a tqdm progress bar over propagation distance. Requires tqdm (pip install tqdm).

False
raman_noise bool

If True, inject spontaneous-Raman noise (Dudley Eq. 5 Γ_R) once per step. Default False (bit-identical to legacy runs). Requires include_raman=True with a Raman response on the fiber.

False
noise_seed int

Seed for the per-step noise generator; same seed gives bit-identical output. None draws nondeterministically.

None

GNLSESolver

GNLSESolver(pulse: Wave, fiber: FiberProfile, betas: NDArray, include_raman: bool = True, include_self_steepening: bool = False, include_tpa: bool = False, include_free_carriers: bool = False, check_phase_matching: bool = False, step_size: Length | None = None, betas_unit: BetasUnit = 'ps^k/m', tau_shock: float | None = None, conserving_shock: bool = False)

High-level GNLSE solver using split-step Fourier method.

Parameters:

Name Type Description Default
pulse Wave

Input pulse envelope.

required
fiber FiberProfile

Fiber parameters.

required
betas array_like

Dispersion coefficients [beta2, beta3, ...] in ps^k/m (with Ω in rad/ps), as returned by Dispersion.get_betas(). Pass betas_unit="s^k/m" (or "SI") to supply SI coefficients instead; they are converted to ps^k/m internally.

required
betas_unit ('ps^k/m', 's^k/m', 'SI')

Unit of betas. Default "ps^k/m".

"ps^k/m"
include_raman bool

Include Raman scattering. Default True.

True
include_self_steepening bool

Include self-steepening (shock term). Default False.

Models intensity-dependent group velocity with the shock operator (1 + (i/ω₀)∂t) (see :class:SplitStepEngine; τ_shock settable, default 1/ω₀). False by default; laserfun's NLSE uses shock=True by default — set True when comparing against laserfun or reproducing Dudley-style supercontinuum demos.

False
include_tpa bool

Include two-photon absorption (legacy spatially-averaged model). Default False.

False
include_free_carriers bool

Include the opt-in time-resolved TPA/free-carrier model (see :class:SplitStepEngine). Requires fiber.beta_tpa / fiber.sigma_fca. Default False.

False
check_phase_matching bool

Run the phase-matching preflight and emit warnings before propagating.

False
step_size Length | None

Fixed split-step size (m). If None (default), the engine uses its adaptive step heuristic. Supply an explicit value for deterministic, reproducible step counts, or when the adaptive heuristic is inappropriate (e.g. CW/finite-background fields where the pulse-width based dispersion limit is not meaningful).

None

pulse instance-attribute

pulse = pulse

fiber instance-attribute

fiber = fiber

betas instance-attribute

betas = _normalize_betas(betas, betas_unit)

betas_unit instance-attribute

betas_unit = _validate_betas_unit(betas_unit)

include_raman instance-attribute

include_raman = include_raman

include_self_steepening instance-attribute

include_self_steepening = include_self_steepening

include_tpa instance-attribute

include_tpa = include_tpa

include_free_carriers instance-attribute

include_free_carriers = include_free_carriers

check_phase_matching instance-attribute

check_phase_matching = check_phase_matching

step_size instance-attribute

step_size = step_size

conserving_shock instance-attribute

conserving_shock = bool(conserving_shock)

tau_shock instance-attribute

tau_shock = float(tau_shock) if tau_shock is not None else None

evolution property

evolution: list[Wave]

List of Wave objects at each propagation step.

z_array property

z_array: NDArray

Array of propagation distances (m) for each evolution entry.

omega0 property

omega0: float

Carrier angular frequency (rad/s).

spectra_vs_z property

spectra_vs_z: tuple[NDArray, NDArray]

Tuple of (frequency array, spectra at each step).

energy_vs_z property

energy_vs_z: NDArray

Pulse energy Σ|A|²·dt at each saved step (same length as z_array).

preflight_report property

preflight_report: SimulationReadinessReport | None

Lazy preflight report from phase-matching assessment.

Builds and caches the report on first access when check_phase_matching=True. Returns None when disabled.

propagate

propagate(num_steps: int = 100, *, nsaves: int | None = None, show_progress: bool = False, raman_noise: bool = False, noise_seed: int | None = None) -> None

Run split-step simulation for num_steps steps.

estimate_num_steps classmethod

estimate_num_steps(pulse: Wave, fiber: FiberProfile, betas: NDArray, *, include_self_steepening: bool = False, include_raman: bool = False, safety_factor: float = 2.0) -> int

Estimate split-step count from dispersion and nonlinear length scales.

Uses the same limits as :meth:SplitStepEngine._adaptive_step_size, divided by safety_factor (larger → more steps). Useful for supercontinuum / soliton regimes where coarse stepping gives wrong physics.

interpolated_spectrum_db

interpolated_spectrum_db(wl_min: float, wl_max: float, n_wl: int, *, step_index: int = -1) -> tuple[NDArray, NDArray]

Return spectrum (dB) on a uniform wavelength grid (nm).

Uses absolute angular frequency omega0 + grid.w before converting to wavelength, matching :func:plot_spectrum_vs_distance.

Parameters:

Name Type Description Default
wl_min float

Wavelength range in nm.

required
wl_max float

Wavelength range in nm.

required
n_wl int

Number of wavelength samples.

required
step_index int

Evolution index (default -1 = final step).

-1

Returns:

Type Description
wavelength_nm, spectrum_db : 1-D arrays

TaperedGNLSESolver

TaperedGNLSESolver(pulse: Wave, fiber: FiberProfile, dispersion_profile: ZDependentDispersion | Callable[[NDArray, float], NDArray], a_eff_fn: Callable[[float], float] | None = None, alpha_fn: Callable[[float], float] | None = None, gamma_fn: Callable[[float], float] | None = None, include_raman: bool = True, include_self_steepening: bool = False, include_tpa: bool = False, include_free_carriers: bool = False, check_phase_matching: bool = False, min_shrink_factor: float = 0.1, step_size: Length | None = None, betas_unit: BetasUnit = 'ps^k/m', tau_shock: float | None = None)

High-level GNLSE solver for z-dependent (tapered/dispersion-managed) waveguides.

Wraps a SplitStepEngine configured with z-dependent dispersion, nonlinearity, and loss. Exposes the same API as GNLSESolver.

Parameters:

Name Type Description Default
pulse Wave

Input pulse envelope.

required
fiber FiberProfile

Fiber parameters (n2, alpha, etc.).

required
dispersion_profile ZDependentDispersion or callable

β(ω, z) profile. Either a ZDependentDispersion table or a callable beta(omega: NDArray, z: float) -> NDArray.

required
a_eff_fn callable

A_eff(z) in m². Falls back to fiber.A_eff if None.

None
alpha_fn callable

α(z) in 1/m. Falls back to fiber.alpha if None.

None
include_raman bool

Include Raman scattering. Default True.

True
include_self_steepening bool

Include self-steepening (shock term). Default False (laserfun NLSE defaults to shock=True).

False
include_tpa bool

Include two-photon absorption (legacy spatially-averaged model). Default False.

False
include_free_carriers bool

Include the opt-in time-resolved TPA/free-carrier model (see :class:SplitStepEngine). Requires fiber.beta_tpa / fiber.sigma_fca. Default False.

False
min_shrink_factor float

Floor for the gradient-based step shrink factor in z-dependent mode. Must be in (0, 1]. Default 0.1. Raise it (e.g. 0.3) to trade a small amount of accuracy for speed on tapers with mild dispersion gradients.

0.1
betas_unit ('ps^k/m', 's^k/m', 'SI')

Unit contract for dispersion coefficients. The tapered solver takes its dispersion from dispersion_profile (β(ω, z), SI), so this flag is validated for consistency with the other solvers but does not rescale a coefficient array. Default "ps^k/m".

"ps^k/m"

pulse instance-attribute

pulse = pulse

fiber instance-attribute

fiber = fiber

betas_unit instance-attribute

betas_unit = _validate_betas_unit(betas_unit)

step_size instance-attribute

step_size = step_size

dispersion_profile instance-attribute

dispersion_profile = dispersion_profile

a_eff_fn instance-attribute

a_eff_fn = a_eff_fn

alpha_fn instance-attribute

alpha_fn = alpha_fn

gamma_fn instance-attribute

gamma_fn = gamma_fn

include_raman instance-attribute

include_raman = include_raman

include_self_steepening instance-attribute

include_self_steepening = include_self_steepening

include_tpa instance-attribute

include_tpa = include_tpa

include_free_carriers instance-attribute

include_free_carriers = include_free_carriers

check_phase_matching instance-attribute

check_phase_matching = check_phase_matching

min_shrink_factor instance-attribute

min_shrink_factor = min_shrink_factor

tau_shock instance-attribute

tau_shock = float(tau_shock) if tau_shock is not None else None

evolution property

evolution: list[Wave]

List of Wave objects at each propagation step.

z_array property

z_array: NDArray

Array of propagation distances (m) for each evolution entry.

omega0 property

omega0: float

Carrier angular frequency (rad/s).

spectra_vs_z property

spectra_vs_z: tuple[NDArray, NDArray]

Tuple of (frequency array, spectra at each step).

energy_vs_z property

energy_vs_z: NDArray

Pulse energy Σ|A|²·dt at each saved step (same length as z_array).

preflight_report property

preflight_report: SimulationReadinessReport | None

Lazy preflight report from phase-matching assessment.

Builds and caches the report on first access when check_phase_matching=True. Returns None when disabled.

propagate

propagate(num_steps: int = 100, strict: bool = False, *, nsaves: int | None = None, show_progress: bool = False, raman_noise: bool = False, noise_seed: int | None = None) -> None

Run split-step simulation for num_steps steps.

Parameters:

Name Type Description Default
num_steps int — number of split-step steps.
100
strict bool — if True, raise ValueError on excessive β clipping (>5%).
False
nsaves int, optional — evenly spaced snapshots along z (see SplitStepEngine).
None
show_progress bool — if True, show ``tqdm`` progress bars (requires tqdm).
False

kerr_step

kerr_step(A: NDArray, fiber: FiberProfile, grid: TemporalGrid, dz: float, omega0: float) -> NDArray

Apply instantaneous Kerr effect: A ← A · exp(i·γ·|A|²·Δz).

Parameters:

Name Type Description Default
A complex array — pulse envelope.
required
fiber FiberProfile — fiber parameters.
required
grid TemporalGrid — time grid.
required
dz float — step size (m).
required
omega0 float — carrier frequency (rad/s).
required

Returns:

Name Type Description
A updated complex array.

raman_step

raman_step(A: NDArray, fiber: FiberProfile, grid: TemporalGrid, dz: float, include_raman: bool, omega0: float = 0.0) -> NDArray

Apply Raman convolution: P_NL = (1-fR)|A|² + fR·(h_R ⊗ |A|²).

Uses FFT-based circular convolution on the centered grid.t axis with the same grid.fft / grid.ifft convention as the split-step engine.

Parameters:

Name Type Description Default
A complex array — pulse envelope.
required
fiber FiberProfile — fiber parameters.
required
grid TemporalGrid — time grid.
required
dz float — step size (m).
required
include_raman bool — whether to include Raman.
required
omega0 float — carrier angular frequency (rad/s).
0.0

Returns:

Name Type Description
A updated complex array (with Raman nonlinear polarization added).

Raises:

Type Description
ValueError : if include_raman is True but fiber.raman_response is None.

free_carrier_step

free_carrier_step(A: NDArray, fiber: FiberProfile, grid: TemporalGrid, dz: float, N: NDArray | None, omega0: float) -> tuple[NDArray, NDArray | None]

Time-resolved TPA / free-carrier absorption step (opt-in).

Models the per-sample carrier population over the retarded-time grid (Soref & Bennett 1987; Cowan, Rieger & Young, Appl. Phys. Lett. 82, 1745 (2003); Yin & Agrawal, Opt. Lett. 32, 2951 (2007)):

∂A/∂z|_TPA = −(β_TPA/2) |A|² A — the standard TPA attenuation; in intensity form d|A|²/dz = −β_TPA |A|⁴, solved exactly per sample for a constant intensity within the step: |A|²(z+dz) = |A|² / (1 + β_TPA |A|² dz).

∂N/∂z = β_TPA |A|⁴/(2ħω₀) − N/(τ_c v) — carrier generation by TPA and recombination (v the envelope group velocity converts the retarded-time lifetime into a propagation length); integrated exactly per sample: N = N e^{−dz/L} + S·L·(1 − e^{−dz/L}) with L = τ_c v.

∂A/∂z|_FCA = −(σ_FCA/2) N A — free-carrier absorption, applied with the mid-step carrier density.

Out of scope (documented, not implemented): free-carrier refraction (the μ index term), carrier diffusion and drift.

Parameters:

Name Type Description Default
A complex array — pulse envelope.
required
fiber FiberProfile — carries ``beta_tpa``, ``sigma_fca``,

carrier_lifetime and group_velocity.

required
grid TemporalGrid — time grid (defines the sample axis of ``N``).
required
dz float — step size (m).
required
N NDArray | None — per-sample carrier density state from the previous

steps, on the same grid. None (start of propagation init).

required
omega0 float — carrier angular frequency (rad/s).
required

Returns:

Type Description
(A, N) — updated field and carrier states.

tpa_step

tpa_step(A: NDArray, fiber: FiberProfile, grid: TemporalGrid, dz: float, include_tpa: bool, U: float = 0.0, omega0: float = 0.0) -> tuple[NDArray, float]

Apply two-photon absorption with carrier dynamics.

dA/dz = -σ·U·A dU/dz = σ·|A|²/(2ħω) - U/τ_c

Parameters:

Name Type Description Default
A complex array — pulse envelope.
required
fiber FiberProfile — fiber parameters.
required
grid TemporalGrid — time grid.
required
dz float — step size (m).
required
include_tpa bool — whether to include TPA.
required
U float — current carrier density (W⁻¹·m⁻³). Default 0.
0.0
omega0 float — carrier angular frequency (rad/s). Required when include_tpa=True.
0.0

Returns:

Name Type Description
A updated complex array.
U_new updated carrier density.

Raises:

Type Description
ValueError : if include_tpa=True and omega0 <= 0.

spectral_evolution_on_wavelength_grid

spectral_evolution_on_wavelength_grid(solver: GNLSESolver, wl_min: float, wl_max: float, n_wl: int) -> tuple[NDArray, NDArray, NDArray]

Interpolate stored spectra onto a uniform wavelength grid (nm).

Uses absolute angular frequency omega0 + grid.w before converting to wavelength. Returns spectra in dB normalized to the global peak.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with propagated results.

required
wl_min float

Wavelength range (nm).

required
wl_max float

Wavelength range (nm).

required
n_wl int

Number of wavelength samples.

required

Returns:

Type Description
(z_m, wavelength_nm, spectra_dB)

z_m has shape (n_z,), wavelength_nm (n_wl,), spectra_dB (n_z, n_wl).

spectral_evolution_on_frequency_grid

spectral_evolution_on_frequency_grid(solver: GNLSESolver, f_min_THz: float, f_max_THz: float, n_f: int) -> tuple[NDArray, NDArray, NDArray]

Interpolate stored spectra onto a uniform absolute-frequency grid (THz).

Returns:

Type Description
(z_m, f_THz, spectra_dB)

spectra_dB has shape (n_z, n_f), normalized to global peak = 0 dB.

temporal_evolution_intensity

temporal_evolution_intensity(solver: GNLSESolver) -> tuple[NDArray, NDArray, NDArray]

Build |A(t)|² at each stored propagation step.

Returns:

Type Description
(z_m, t_ps, intensity)

intensity has shape (n_z, N_time).

plot_waterfall

plot_waterfall(solver: GNLSESolver, ax=None, dB: bool = True, offset_scale: float = 1.0) -> plt.Figure

Pulse envelope waterfall plot (envelope vs propagation distance).

Each saved trace i is drawn as y_norm + i * offset_scale where y_norm is the trace normalized to unit range (0..1 linear, or -1..0 for dB scaled by 90 dB). Y-tick labels show the propagation distance of each trace, so offsets are documented and interpretable.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with propagated results.

required
ax matplotlib Axes

Axis to plot on. Creates new figure if None.

None
dB bool

Plot in dB scale. Default True.

True
offset_scale float

Vertical spacing between consecutive traces in normalized units. Must be > 0. Default 1.0.

1.0

Returns:

Name Type Description
fig matplotlib Figure

plot_spectrum_vs_distance

plot_spectrum_vs_distance(solver: GNLSESolver, ax=None, dB: bool = True) -> plt.Figure

Spectrum vs propagation distance contour (legacy wrapper).

See :func:plot_spectral_evolution for wavelength range and dynamic-range control. Uses millimetres on the distance axis and the hot colormap for backward compatibility.

plot_spectral_evolution

plot_spectral_evolution(solver: GNLSESolver, ax=None, *, wl_min: float | None = None, wl_max: float | None = None, f_min_THz: float | None = None, f_max_THz: float | None = None, n_points: int = 400, dynamic_range_db: float = 40.0, dB: bool = True, cmap: str = 'viridis', z_scale: str = 'm', use_imshow: bool = True) -> plt.Figure

Spectral evolution contour: wavelength or frequency vs propagation distance.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with propagated results.

required
ax matplotlib Axes

Axis to plot on. Creates new figure if None.

None
wl_min float

Wavelength limits (nm) when plotting vs wavelength.

None
wl_max float

Wavelength limits (nm) when plotting vs wavelength.

None
f_min_THz float

Absolute frequency limits (THz) when plotting vs frequency. If both frequency limits are set they take precedence over wavelength.

None
f_max_THz float

Absolute frequency limits (THz) when plotting vs frequency. If both frequency limits are set they take precedence over wavelength.

None
n_points int

Number of samples along the spectral axis.

400
dynamic_range_db float

Color scale spans [global_max - dynamic_range_db, global_max] in dB.

40.0
dB bool

Plot log-scale intensity (recommended). If False, plots linear power.

True
cmap str

Matplotlib colormap name.

'viridis'
z_scale str

"m" for metres on the distance axis, "mm" for millimetres.

'm'
use_imshow bool

If True, use imshow with origin='lower' (laserfun style).

True

Returns:

Name Type Description
fig matplotlib Figure

plot_temporal_evolution

plot_temporal_evolution(solver: GNLSESolver, ax=None, *, t_min: float | None = None, t_max: float | None = None, dynamic_range_db: float = 40.0, cmap: str = 'viridis', z_scale: str = 'm', use_imshow: bool = True, time_reversal: bool = False) -> plt.Figure

Temporal evolution contour: time vs propagation distance.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with propagated results.

required
ax matplotlib Axes

Axis to plot on. Creates new figure if None.

None
t_min float

Time window in ps (in the plotted convention). Default: full grid.

None
t_max float

Time window in ps (in the plotted convention). Default: full grid.

None
dynamic_range_db float

Color scale spans [global_max - dynamic_range_db, global_max] in dB.

40.0
cmap str

Matplotlib colormap name.

'viridis'
z_scale str

"m" or "mm" for the distance axis.

'm'
time_reversal bool

Kept for back-compatibility with pre-#0 notebooks; default False. Post-ISSUES.md #0 the internal time grid ALREADY uses the standard literature (Agrawal) comoving direction -- Raman-shifted solitons appear at positive delay without any flip (chirp and spectra are unaffected). Set True only to reproduce the historical (pre-#0) mirrored axis.

False

Returns:

Name Type Description
fig matplotlib Figure

plot_scg_dashboard

plot_scg_dashboard(*, z_axis: NDArray, wl_nm: NDArray, spec_db: NDArray, t_ps: NDArray, int_db: NDArray, out_wl_nm: NDArray, out_spec_db: NDArray, out_t_ps: NDArray, out_int_db: NDArray, spec_labels: NDArray, t_labels: NDArray, title: str = '', z_label: str = 'Distance (m)', wl_bounds: tuple[float, float] | None = None, t_bounds: tuple[float, float] | None = None, dynamic_range_db: float = 40.0, colorscale: str = 'Jet', annotate_features: bool = True, height: int = 850) -> FigureLike

Interactive four-panel Plotly SCG dashboard with feature hover labels.

Layout: output line profiles (a) intensity (dB) vs wavelength and (b) intensity (dB) vs time on top, with the taller (c) spectral and (d) temporal evolution heatmaps below. Hovering a heatmap cell reports wavelength/time, distance, power and the local feature class.

This is the low-level array consumer used by :func:plot_spectral_temporal_summary with plotly=True and by the Dudley Fig. 3 reproduction (which stores an Evolution rather than a solver). Requires the optional plotly dependency.

Parameters:

Name Type Description Default
z_axis NDArray

Propagation-distance values for the heatmap y axis.

required
wl_nm NDArray

Uniform wavelength grid (nm) for the spectral heatmap columns.

required
spec_db (NDArray, shape(n_z, n_wl))

Spectral density in dB (peak 0, clipped to the dynamic range).

required
t_ps NDArray

Time grid (ps, plotted convention) for the temporal heatmap columns.

required
int_db (NDArray, shape(n_z, n_time))

Temporal intensity in dB (peak 0, clipped to the dynamic range).

required
out_wl_nm NDArray

Output spectrum line for panel (a).

required
out_spec_db NDArray

Output spectrum line for panel (a).

required
out_t_ps NDArray

Output intensity line for panel (b).

required
out_int_db NDArray

Output intensity line for panel (b).

required
spec_labels NDArray

Per-wavelength feature labels, shape (n_wl,) or (n_z, n_wl).

required
t_labels NDArray

Per-time feature labels, shape (n_time,) or (n_z, n_time).

required
title str

Figure title.

''
z_label str

Label for the heatmap distance axis.

'Distance (m)'
wl_bounds (float, float)

Axis ranges; default to the extent of the supplied grids.

None
t_bounds (float, float)

Axis ranges; default to the extent of the supplied grids.

None
dynamic_range_db float

Colour-axis floor (dB).

40.0
colorscale str

Plotly colorscale name (e.g. "Jet", "Viridis").

'Jet'
annotate_features bool

Mark the strongest cell of each feature class.

True
height int

Figure height in pixels.

850

Returns:

Type Description
Figure

plot_spectral_temporal_summary

plot_spectral_temporal_summary(solver: GNLSESolver, *, wl_bounds: tuple[float, float] | None = None, wl_min: float | None = None, wl_max: float | None = None, t_bounds: tuple[float, float] | None = None, t_min: float | None = None, t_max: float | None = None, dynamic_range_db: float = 40.0, cmap: str = 'jet', z_scale: str = 'm', time_reversal: bool = False, height_ratios: tuple[float, float] = (1.0, 1.7), figsize: tuple[float, float] = (11.0, 9.0), n_points: int = 500, plotly: bool = False) -> FigureLike

Four-panel GNLSE summary with line profiles on top and dense plots below.

Layout

(a) output intensity (dB) vs wavelength — line (b) output intensity (dB) vs time — line (c) spectral evolution — density plot (taller) (d) temporal evolution — density plot (taller)

The two contour panels occupy a larger fraction of the figure (height_ratios) because their dynamic range carries the SC dynamics; the line profiles give a quantitative, easily read complement.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with stored fields (call :meth:propagate first).

required
wl_bounds (float, float)

Wavelength window in nm. Defaults to the carrier ± 50 %.

None
wl_min float

Individual overrides used only when wl_bounds is None.

None
wl_max float

Individual overrides used only when wl_bounds is None.

None
t_bounds (float, float)

Time window in ps (plotted convention). Defaults to the full grid.

None
t_min float

Individual overrides used only when t_bounds is None.

None
t_max float

Individual overrides used only when t_bounds is None.

None
dynamic_range_db float

Colour/floor range below the peak for the density plots and the line profiles.

40.0
cmap str

Matplotlib colormap for the density plots.

'jet'
z_scale ('m', 'cm', 'mm')

Propagation-distance unit on the density-plot y axes.

"m"
time_reversal bool

Use the standard literature (Agrawal/Dudley) comoving time (default).

False
height_ratios (float, float)

Relative heights of the line row and the (taller) contour row.

(1.0, 1.7)
figsize (float, float)

Figure size in inches.

(11.0, 9.0)
n_points int

Spectral samples used by the Plotly path.

500
plotly bool

If True, return an interactive plotly.graph_objects.Figure whose heatmap hover labels each cell as DW / SPM / Raman soliton (see :func:plot_scg_dashboard). write_html it for a standalone page, or use :func:save_summary_html.

False

Returns:

Name Type Description
fig matplotlib Figure or plotly Figure

The assembled figure (not closed), so the caller can adjust it.

save_summary_html

save_summary_html(solver: GNLSESolver, path, **kwargs) -> Path

Render the interactive summary and write a standalone HTML file.

Builds :func:plot_spectral_temporal_summary with plotly=True and writes a self-contained .html document (Plotly.js loaded from the CDN). This is the automated path that turns a propagated solver into the interactive Fig. 3-style dashboard described in the reproduction docs.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with stored fields.

required
path str or Path

Output HTML path; parent directories are created.

required
**kwargs

Forwarded to :func:plot_spectral_temporal_summary (for example wl_bounds, t_bounds, dynamic_range_db).

{}

Returns:

Type Description
Path

The written path.

gnlse_spectrogram

gnlse_spectrogram(solver: GNLSESolver, *, gate: NDArray | None = None, n_delays: int = 161, delay_span_ps: float | None = None, snapshot: int = -1, wl_bounds: tuple[float, float] | None = None, n_wavelength: int = 500, time_reversal: bool = False) -> tuple[NDArray, NDArray, NDArray]

Cross-correlation spectrogram of a propagated field (GNLSE Eq. 4).

Computes

Σ(Ω, τ) = |∫ E(t) g(t − τ) e^{−iΩt} dt|²

with the complex envelope E(t) taken from the last stored field (or snapshot) and a real gate g (by default the input pulse envelope, as in Dudley et al., Rev. Mod. Phys. 78, 1135 (2006), Fig. 10). This is the cross-correlation FROG trace, not a conventional STFT: the gate is the actual pulse rather than a fixed window, and the trace preserves the relative phase information of the pulse.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with stored fields (call :meth:propagate first).

required
gate NDArray

Real gate sampled on solver.pulse.grid.t. Defaults to the input pulse envelope real(E_in(t)).

None
n_delays int

Number of delay samples.

161
delay_span_ps float

Half-range of the delay axis in ps. Defaults to 40 % of the full temporal window.

None
snapshot int

Index into solver.evolution of the field to analyse (default last).

-1
wl_bounds (float, float)

Wavelength window (wl_min, wl_max) in nm. Defaults to the carrier wavelength ± 50 %, i.e. (0.5·λ0, 1.5·λ0); pass an explicit tuple to zoom or widen.

None
n_wavelength int

Number of samples on the uniform wavelength grid.

500
time_reversal bool

Kept for back-compatibility with pre-#0 notebooks; default False. Post-ISSUES.md #0 the internal time grid already uses the standard literature (Agrawal) comoving time T (Raman red-shift -> positive delay); spectra and the Raman red-shift are unaffected either way. Set True only to reproduce the historical (pre-#0) mirrored axis.

False

Returns:

Name Type Description
delay_ps (NDArray, shape(n_delays))
wavelength_nm (NDArray, shape(n_wavelength))
spectrogram (NDArray, shape(n_delays, n_wavelength))

Power spectrogram (arb. units; normalise with its maximum).

plot_spectrogram

plot_spectrogram(solver: GNLSESolver, ax=None, *, gate: NDArray | None = None, n_delays: int = 161, delay_span_ps: float | None = None, snapshot: int = -1, wl_bounds: tuple[float, float] | None = None, dynamic_range_db: float = 40.0, cmap: str = 'jet', with_projections: bool = False, t_min: float | None = None, t_max: float | None = None, time_reversal: bool = False, plotly: bool = False, annotate_features: bool = True) -> FigureLike

Plot the supercontinuum spectrogram (Dudley et al. Fig. 10 style).

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with stored fields.

required
ax matplotlib Axes

Axis for the spectrogram when with_projections=False and plotly=False.

None
wl_bounds (float, float)

Wavelength window (wl_min, wl_max) in nm. Defaults to the carrier ± 50 %.

None
with_projections bool

If True, build a matplotlib figure with the spectrogram plus its temporal (bottom) and spectral (right) projections (ignores ax).

False
t_min float

Delay limits in ps (defaults to the full delay span).

None
t_max float

Delay limits in ps (defaults to the full delay span).

None
time_reversal bool

Use the standard literature (Agrawal) comoving time (default True).

False
plotly bool

If True, return an interactive plotly.graph_objects.Figure instead of a matplotlib figure. The hover text labels each (delay, λ) cell as a dispersive wave, SPM/pump, or Raman soliton, and (with annotate_features=True) the strongest cell of each class is marked.

False
annotate_features bool

Add feature labels in the Plotly path. Ignored for matplotlib.

True

Returns:

Name Type Description
fig matplotlib Figure or plotly Figure

The figure, so the caller can adjust axes/labels afterwards.

plot_intensity_metrics

plot_intensity_metrics(solver: GNLSESolver, ax=None) -> plt.Figure

Peak power and pulse width vs propagation distance.

Parameters:

Name Type Description Default
solver GNLSESolver

Solver with propagated results.

required
ax matplotlib Axes

Axis to plot on. Creates new figure with two subplots if None.

None

Returns:

Name Type Description
fig matplotlib Figure