solprop.driver.scaffold#
A fixed-step interaction-picture integrator for the mode-averaged GNLSE.
Not the solver, and not how a simulation is run: that is
solprop.driver.interface.prop_gnlse() and
solprop.driver.simulation.Simulation. This is a second, independent integrator
of the same physics, which is why it stays now that the driver has landed: it
composes the nonlinear term from the physics layer and steps it with the classical
interaction-picture RK4, sharing nothing with the reference backend’s passes but the
response itself, so agreement between the two checks the stage combination and the
propagator factors rather than the physics they share
(tests/backends/test_numpy_ref_soliton.py). It is plain NumPy, fixed step, envelope
grid, mode-averaged, Kerr only, and allocates freely.
The scheme is the classical fourth-order Runge-Kutta method in the interaction picture
[1]: the linear flow exp(D h) is applied exactly, which the diagonal operator
allows (docs/guide/numerics/linear-operator.md), and only the nonlinear term is
integrated
numerically.
References#
J. Hult, “A fourth-order Runge-Kutta in the interaction picture method for simulating supercontinuum generation in optical fibers”, J. Lightwave Technol. 25, 3770 (2007). doi:10.1109/JLT.2007.909373
Functions
|
Return the scaffold's nonlinear term of the mode-averaged GNLSE. |
|
Propagate a mode-averaged envelope spectrum with fixed-step IP-RK4. |
- solprop.driver.scaffold.gnlse_source(problem, grid)[source]#
Return the scaffold’s nonlinear term of the mode-averaged GNLSE.
The term
propagate_fixed_rk4()integrates, composed from the physics layer alone (docs/dev/architecture.mdsection 2): the spectrum is oversampled onto the fine grid, transformed, scaled to volts per metre, handed to the Kerr response, and the polarisation is transformed back, cropped and multiplied bysolprop.nonlinear.normalisation.mode_average_prefactor(). Exposed so that one evaluation can be compared with a backend’s (SEP 24 section 7.1).- Parameters:
- problemsolprop.nonlinear.gnlse.GnlseProblem
The fibre and the nonlinearity.
- gridsolprop.grid.TimeGrid
An envelope grid.
- Returns:
- collections.abc.Callable
N[state]: a stored spectrum of shape(n_omega,)in the square root of watts to the nonlinear term, same shape, in the square root of watts per metre.
- Raises:
- GridError
If the grid is not an envelope grid.
Examples
>>> import numpy as np >>> from solprop.driver.scaffold import gnlse_source >>> from solprop.grid import EnvelopeGrid >>> from solprop.nonlinear.gnlse import problem_from >>> grid = EnvelopeGrid.from_limits(1.0, 835e-9, (500e-9, 2e-6), 4e-12) >>> problem = problem_from([0.0, 0.0, -1.2e-26], omega_ref=grid.omega0, ... gamma=0.11, shock=False) >>> source = gnlse_source(problem, grid) >>> bool(np.all(source(np.zeros(grid.n_omega, dtype=complex)) == 0.0)) True
- solprop.driver.scaffold.propagate_fixed_rk4(problem, grid, spectrum, z_end, n_steps, *, n_save=1)[source]#
Propagate a mode-averaged envelope spectrum with fixed-step IP-RK4.
The state is the stored spectrum in the internal FFT convention, in the square root of watts, as
solprop.pulsesbuilds it. Each step applies the exact linear factorexp(D h / 2)around the four nonlinear evaluations of the classical Runge-Kutta scheme. The nonlinear term isgnlse_source()’s. The linear operator is evaluated once, atz = 0, which is exact for a dispersion-specified mode because it does not vary along the fibre.The state is masked to the grid’s active band once at the start. Outside the band both the operator and the prefactor are zero, so nothing there ever changes.
A fibre that varies along z is refused: the operator and the area are evaluated once here, and a varying effective area belongs to the tabulated route of
solprop.driver.interface.prop_gnlse().- Parameters:
- problemsolprop.nonlinear.gnlse.GnlseProblem
The fibre and the nonlinearity, from
solprop.nonlinear.gnlse.problem_from().- gridsolprop.grid.TimeGrid
An envelope grid. A field grid is refused: this scaffold has no field path.
- spectrumnumpy.ndarray
Initial stored spectrum, shape
(n_omega,), complex, in the square root of watts and the internal convention.- z_endfloat
Propagation length, m, positive.
- n_stepsint
Number of equal steps, at least 1 and a multiple of
n_save.- n_saveint, optional
Number of planes to save after
z = 0, at least 1. Default 1: the end only.
- Returns:
- tuple
(z, spectra): the saved positions, shape(n_save + 1,), m, starting at zero; and the stored spectra there, shape(n_save + 1, n_omega).
- Raises:
- GridError
If the grid is not an envelope grid, or the spectrum does not match it.
- StepperError
If the fibre varies along z,
z_endis not positive and finite,n_stepsorn_saveis below 1, orn_stepsis not a multiple ofn_save.
Examples
A fundamental soliton is stationary up to the phase
-i xi / 2of the internal convention,xibeing the distance in dispersion lengths:>>> import numpy as np >>> from solprop.driver.scaffold import propagate_fixed_rk4 >>> from solprop.grid import EnvelopeGrid >>> from solprop.nonlinear.gnlse import problem_from >>> from solprop.pulses import SechPulse >>> beta2, gamma, tau0 = -11.83e-27, 0.11, 100e-15 >>> grid = EnvelopeGrid.from_limits(1.0, 835e-9, (500e-9, 2e-6), 4e-12) >>> problem = problem_from( ... [0.0, 0.0, beta2], omega_ref=grid.omega0, gamma=gamma, shock=False ... ) >>> peak = abs(beta2) / (gamma * tau0**2) >>> start = SechPulse(wavelength=835e-9, width=tau0, peak_power=peak).build(grid) >>> z, spectra = propagate_fixed_rk4( ... problem, grid, start[0, 0], tau0**2 / abs(beta2), 200 ... ) >>> error = np.linalg.norm(spectra[-1] - np.exp(-0.5j) * spectra[0]) >>> bool(error / np.linalg.norm(spectra[0]) < 1e-9) True