solprop.driver.simulation#

The simulation object: physics objects in, a written, resumable run out.

A Simulation holds what a run is made of – the grid, the modes, the responses, the input, the noise and the numerical settings – translates it once into a solprop.translate.problem.KernelProblem, and can then be run as often as one likes, into memory or into a file. It owns three things the loop of solprop.driver.run does not: the translation and its cache, the solprop.output.schema.RunMetadata that says what produced a file, and the resume decision.

Resume. Given a path, a run checks the file that is already there with solprop.output.hdf5.check_cache(): the digest covers the grid, the modes, the whole serialised configuration, the noise and the stepper settings, so a file written for different physics is refused by name rather than continued from someone else’s state. If it passes, the last plane comes back through solprop.output.hdf5.resume(), the backend is loaded at that plane’s position, and the run carries on into the same file with HDF5Output(path, append=True).

Layer D of docs/dev/architecture.md section 3: this module imports the physics, the translation, the backends and the output layer, and nothing imports it. The manual page is docs/guide/setup/running.md.

Module Attributes

LOOSE_ADAMS_RTOL

The rtol from which an adaptive Adams run is warned on.

DEFAULT_RTOL

Relative tolerance a GNLSE run asks for unless told otherwise.

DEFAULT_ATOL

Absolute tolerance, in the square root of watts, of the same default.

DEFAULT_N_SAVE

Planes a GNLSE run stores, counting the one at z = 0.

CAPILLARY_RTOL

Relative tolerance a capillary run asks for unless told otherwise.

WAVEGUIDE_RTOL

Relative tolerance a modal waveguide run asks for unless told otherwise.

SPATIAL_RTOL

Relative tolerance of the controller a radial or planar run takes by default.

SPATIAL_ATOL

Absolute tolerance of the same default controller: none, as the suite runs it.

FREE_RTOL

Relative tolerance of the controller a Cartesian or line run takes by default.

FREE_ATOL

Absolute tolerance of the same default controller.

WAVEGUIDE_ATOL

Absolute tolerance of a modal waveguide run, in sqrt(W).

PLASMA_STATISTICS

Backend statistics that read the plasma the run compiled; refused without one.

BACKEND_STATISTICS

The statistics only a backend can compute, recorded by a capillary run by default.

ORTHONORMALITY_TOLERANCE

How far a given mode set may stray from orthonormality before it is refused.

NoiseModel

Which shot-noise model a run carries; None carries none.

NoiseSetting

What a constructor's noise keyword takes (SEP 37).

SINGLE_PRECISION_NOISE

Why a default resolves to no noise under precision="single" (SEP 37).

PLANAR_NOISE

Why a planar run carries no noise (SEP 37).

FREE_NOISE

Why a default resolves to no noise on the free-space interface (SEP 37).

TDSE_NOISE

Why a default resolves to no noise beside the TDSE response (SEP 37).

INTERIOR_LAUNCH_NOISE

Why a default noise is dropped at an interior launch (SEP 37).

LOW_STORAGE_BACKENDS

The backends that execute LowStorageRungeKutta.

Functions

check_derived_problem(constructed, derived)

Refuse a derived problem that is not the constructed one but for its input.

default_field_range(peak_field)

Return the field amplitudes an ionisation table covers, from the input's peak.

default_radial_order(n_modes)

Return the radial order of the fixed rule a capillary run uses by default.

metadata_for(problem, grid, *[, modes, ...])

Build the record that says what produced a run, and whether it may be resumed.

Classes

Simulation(grid, modes, responses, initial, ...)

A run that can be translated once and executed many times.

SimulationRunner(simulation, *[, memory_budget])

One translated problem and one backend, run for many inputs (SEP 22 section 5.2).

SimulationSettings([controller, dz_min, ...])

How a run is stepped, what it records and which backend executes it.

solprop.driver.simulation.BACKEND_STATISTICS = ('peak_intensity', 'quadrature_error', 'electron_density', 'peak_ionisation_rate')#

The statistics only a backend can compute, recorded by a capillary run by default.

Each needs something the kernel contract does not carry to a later pass: the quadrature nodes the plasma was evaluated at, the mode set the axis needs, or the embedded coarse-rule projection, which is gone once the step is accepted. The two plasma entries are recorded only by a run that has a plasma response; the backend refuses them otherwise, and a default that always asked for them would make plasma=False fail.

solprop.driver.simulation.CAPILLARY_RTOL = 1e-06#

Relative tolerance a capillary run asks for unless told otherwise.

The default of Simulation.from_capillary() and prop_capillary() with their default Multistep(). SEP 37’s convergence protocol on the benchmark suite’s rdw case passes it, and a noisy comb-to-continuum check needs it with this integrator (1e-5 fails the coherence budget there). It is a starting point, not a guarantee: a production run should calibrate it (docs/dev/stepper.md section 3).

solprop.driver.simulation.DEFAULT_ATOL = 1e-14#

Absolute tolerance, in the square root of watts, of the same default.

solprop.driver.simulation.DEFAULT_N_SAVE = 201#

Planes a GNLSE run stores, counting the one at z = 0.

solprop.driver.simulation.DEFAULT_RTOL = 1e-07#

Relative tolerance a GNLSE run asks for unless told otherwise.

Set by SEP 37’s convergence protocol on the supercontinuum of Dudley, Genty and Coen (the benchmark suite’s gnlse_raman_shock): the loosest of three levels a decade apart at which the ensemble-mean spectrum stays within 0.5 dB above -40 dB of its peak and the coherence within 0.02, over paired seeds, with the default RungeKutta(). A noiseless soliton-recurrence study asks for its own, tighter value.

solprop.driver.simulation.FREE_ATOL = 0.0#

Absolute tolerance of the same default controller.

solprop.driver.simulation.FREE_NOISE = 'a Cartesian or line run carries no noise by default: it is slow, and rarely about noise sensitivity'#

Why a default resolves to no noise on the free-space interface (SEP 37).

solprop.driver.simulation.FREE_RTOL = 0.0001#

Relative tolerance of the controller a Cartesian or line run takes by default.

With the default RungeKutta() (SEP 37): the Adams history’s memory rules the multistep method out for a large transverse state. On a self-focusing Kerr beam the spectrum stays within 0.002 dB of a tight reference even at 1e-3; 1e-4 cuts the field error by 2.5 times for a sixth more steps. Applies only where the caller’s SimulationSettings gives no controller.

solprop.driver.simulation.INTERIOR_LAUNCH_NOISE = 'an interior launch takes its spectrum as given, which may already carry a draw'#

Why a default noise is dropped at an interior launch (SEP 37).

solprop.driver.simulation.LOOSE_ADAMS_RTOL = 0.05#

The rtol from which an adaptive Adams run is warned on.

An error of five per cent or more allowed per step compounds through the method’s history, and its predictor-corrector estimate is unreliable there (docs/guide/numerics/choosing-a-stepper.md).

solprop.driver.simulation.LOW_STORAGE_BACKENDS = ('native', 'numba_cpu', 'numpy_ref')#

The backends that execute LowStorageRungeKutta.

numpy_ref from SEP 24’s phase 1, numba_cpu from phase 2 and solprop-native from phase 3, on every route the translation admits the march on; backend="auto" resolves as for every other integrator (solprop.backends.registry.resolve_name(): the native backend when it is installed, otherwise numba_cpu).

solprop.driver.simulation.NoiseModel#

Which shot-noise model a run carries; None carries none.

The two models are described in docs/guide/media/noise.md.

alias of Literal[‘input’, ‘modified’]

solprop.driver.simulation.NoiseSetting = typing.Literal['default', 'input', 'modified'] | None#

What a constructor’s noise keyword takes (SEP 37).

A model, None for a noiseless run, or "default", the keyword’s default, which resolves to "input" wherever the run can carry noise and to none where it cannot, recording which in the run’s NoiseResolution.

solprop.driver.simulation.ORTHONORMALITY_TOLERANCE = 1e-06#

How far a given mode set may stray from orthonormality before it is refused.

The transform is one synthesis matrix and its dual, which represent an orthonormal basis and nothing else, so a set that is not one is propagating a different problem from the one it describes. The bound is loose because the overlaps are integrated adaptively by scipy.integrate.dblquad(), whose own accuracy on a set of Bessel profiles is around 1e-9.

solprop.driver.simulation.PLANAR_NOISE = 'the hybrid planar grid carries no noise: no photon measure is declared'#

Why a planar run carries no noise (SEP 37).

solprop.driver.simulation.PLASMA_STATISTICS = ('electron_density', 'peak_ionisation_rate')#

Backend statistics that read the plasma the run compiled; refused without one.

solprop.driver.simulation.SINGLE_PRECISION_NOISE = 'single precision carries no noise: binary32 rounding swamps a one-photon seed'#

Why a default resolves to no noise under precision="single" (SEP 37).

solprop.driver.simulation.SPATIAL_ATOL = 0.0#

Absolute tolerance of the same default controller: none, as the suite runs it.

solprop.driver.simulation.SPATIAL_RTOL = 1e-05#

Relative tolerance of the controller a radial or planar run takes by default.

Set by SEP 37’s convergence protocol on the benchmark suite’s radial_filament_256 and planar cases. It applies only where the caller’s SimulationSettings gives no controller.

class solprop.driver.simulation.Simulation(grid, modes, responses, initial, *, settings, initial_z=0.0, noise=None, noise_resolution=None, profiles=None, configuration=None, spatial_grid=None, medium=None, frame=None, general=None, guide=None, wall=None, taper_coupling=True, materials=None)[source]#

Bases: Displayed

A run that can be translated once and executed many times.

Construct it from the physics objects and a SimulationSettings, or through from_gnlse() for a GNLSE fibre. translate() assembles the kernel problem and caches it, so a second run() – into another handler, or resuming a file – reuses it. settings may be replaced until that first translation; after it only its backend may change.

Parameters:
gridsolprop.grid.TimeGrid

The field or envelope grid.

modessolprop.modes.protocol.Mode or sequence of Mode

The mode, or the ordered set of a multimode problem.

responsescollections.abc.Sequence

The declared nonlinear responses, as solprop.translate.responses.compile_responses() takes them.

initialsolprop.pulses.Pulse or solprop.pulses.SpatialPulse or numpy.ndarray

The input: a solprop.pulses.Pulse – anything with a build(grid) method – or an already-built spectrum of shape (n_modes, n_pol, n_omega) in the square root of watts and the internal convention. A pulse is the better choice: it is a small specification, while a built array is recorded in the metadata as itself.

settingsSimulationSettings

How to step it, what to record and which backend to use.

initial_zfloat, optional

Absolute position of an array input, m, default zero. Every requested save plane must follow it. An interior launch keeps the original profiles and propagation frame; it requires a modal array input, no noise and no fixed step schedule.

noisesolprop.noise.NoiseRealisation or None, optional

A shot-noise realisation to carry along the run (docs/guide/media/noise.md).

noise_resolutionsolprop.output.schema.NoiseResolution or None, optional

How the noise model was chosen, as the constructors record it (SEP 37); None records the realisation as asked for explicitly.

profilescollections.abc.Mapping, optional

The z-profiles keyed by statistic name, for the density, pressure and core_radius statistics. Passed to the backend, which computes them.

configurationcollections.abc.Mapping, optional

Extra provenance to record beside what the simulation can see for itself, such as the coefficients a mapping came from.

spatial_gridRadialGrid, FreeGrid, PlanarGrid or None, optional

Transverse grid for spatial propagation; use an empty mode sequence (a solprop.modes.slab.PlanarGrid carries its own slab modes).

mediumsolprop.spatial.SpatialMedium or None, optional

Bulk material, required with a spatial grid.

framesolprop.linear.Frame or None, optional

Propagation frame. None uses the grid and responses’ normal default.

generalsolprop.translate.general.GeneralModalRoute or None, optional

The seam leaves of one general modal guide. Built by from_waveguide() from a provider=; with it the run takes the general modal route, whose responses are the guide’s material regions’ and whose declared responses must therefore be empty.

guidesolprop.modes.guide.ModalGuide or None, optional

The general modal guide general was built from, kept so that the run’s material manifest finds what its regions hold (their laws and delayed responses); it enters no translation. Set by from_waveguide().

wallsolprop.modes.capillary.CoherentWall or None, optional

The declaration of a coherent wall block. Built by from_capillary() from a wall=; with it the mode set must be the contiguous HE_11 to HE_1N block – or, with impedance="te_tm", one azimuthal order – on a constant or a varying guide, the cumulative operator carries the mode-independent carrier alone and the modal part of the flow becomes linear.coupled_flow, which all three backends execute (a method="cf4" wall numpy_ref alone).

taper_couplingbool, optional

Carry the taper coupling of a multimode capillary whose radius varies along z: the connection <psi_m|d_z psi_n> between the HE_1m channels, lossless or not, in a coupled flow beside each channel’s own propagation constant. True, the default; False is the explicit opt-out to the adiabatic route, on which each channel follows its local mode and no power is exchanged. No effect on a set the coupling does not apply to (solprop.modes.capillary.taper_coupling_block()); False beside a wall is refused, because the wall carries its connection.

materialssolprop.physdata.selection.MaterialSelection or None, optional

The material selection the run was built with, recorded in its material manifest (output schema 8) with every optmat-backed object the run carries. The objects themselves are taken as they are: the from_* constructors resolve the built-in materials under the selection. None records none.

Raises:
DriverError

If initial is neither an array nor something with a build method.

Examples

>>> from solprop.driver import Simulation, SimulationSettings
>>> from solprop.grid import EnvelopeGrid
>>> from solprop.nonlinear.gnlse import problem_from
>>> from solprop.pulses import SechPulse
>>> from solprop.stepper import PIController
>>> grid = EnvelopeGrid.from_limits(0.01, 835e-9, (500e-9, 2e-6), 1e-12)
>>> gnlse = problem_from([0.0, 0.0, -1.183e-26], omega_ref=grid.omega0, gamma=0.11,
...                      shock=False)
>>> simulation = Simulation(
...     grid, gnlse.mode, [gnlse.kerr],
...     SechPulse(wavelength=835e-9, width=100e-15, peak_power=9.8),
...     settings=SimulationSettings(
...         controller=PIController(rtol=1e-6, atol=1e-16),
...         save_planes=[0.01], dz_max=0.01, dz_init=1e-3,
...         density=1.0, shock=False, prefactor_index=1.0,
...     ),
... )
>>> handler = simulation.run()
>>> handler.n_saved, simulation.translate().shape
(2, (1, 1, 1, 1024))
classmethod from_capillary(radius, length, gas, pressure=None, *, pressure_floor=None, vacuum_end=None, lambda0, wavelength_limits=None, trange=None, grid=None, envelope=False, fwhm=None, width=None, pulseshape='gauss', energy=None, peak_power=None, phases=(), pulses=None, modes=1, mode_average=False, lattice=None, wall=None, taper_coupling=True, model='full', loss=True, cladding=None, susceptibility=None, temperature=None, kerr=True, thg=None, plasma=None, preionisation=None, plasma_integration=None, raman=None, n_r=None, n_theta=None, radial_rule='gauss_kronrod', ionisation_field_range=None, absorber=None, absorber_scheme=None, noise='default', seed=None, rtol=None, atol=1e-10, dz_max=None, dz_init=None, schedule=None, integrator=None, interpolate_planes=False, step_planes=None, save_planes=None, n_save=None, stats=None, node_budget=67108864, backend='auto', precision='double', polarisation=None, materials=None, tdse=None, tdse_execution=None)[source]#

Build a simulation of a pulse in a gas-filled hollow waveguide.

The constructor solprop.driver.interface.prop_capillary() calls. The mode set is the first modes HE_1m modes of the capillary unless a set is given; the transverse integral is a fixed quadrature rule (docs/guide/waveguides/mode-sets.md); the gas density along z is the pressure path through the equation of state, and the same path sets the modes’ core index, so a gradient fill disperses and broadens consistently.

See docs/guide/setup/running.md for the discussion and a worked example.

Parameters:
radiusfloat or solprop.profiles.ZProfile

Core radius, m, constant or along z.

lengthfloat

Capillary length, m.

gasGas, str, Mapping or Mixture

Built-in gas, mole fractions keyed by species name, or ordered populations carrying their own density paths. A mapping uses total pressure.

pressurefloat, sequence, ZProfile or None, optional

None uses one bar for a gas or fractions. Omit pressure beside a Mixture; every explicit pressure is refused because it already carries its paths. Fill pressure in bar: a number for a constant fill, a pair (p_in, p_out) for the steady-flow gradient of solprop.profiles.PressureGradient.two_point(), or (z, p) with the positions and the pressures there for solprop.profiles.PressureGradient.from_stages().

pressure_floorfloat or None, optional

Lowest pressure the fill is allowed to reach, bar; None takes solprop.profiles.DEFAULT_PRESSURE_FLOOR_FRACTION of the highest stage pressure. With vacuum_end="floor", pass 0.0 for a true vacuum end, which warns, because dp/dz diverges there.

vacuum_end{‘choked’, ‘floor’} or None, optional

How a pressure gradient’s outer end below its choked pressure is treated. None (the default) means "choked" for a circular hollow guide: the fill follows the bore (Pennetta et al. 2019, eq. 6) and an end exhausting into vacuum takes the choked pressure of the flow (solprop.gasflow.steady_fill()), with a warning if the flow is not laminar. "floor" concerns the ends only: it keeps the declared end pressures, raised only to pressure_floor, for a comparison with a model that imposes them, while a taper’s fill still follows the bore (on a uniform bore, bitwise the uniform law). Refused beside a constant pressure, a pressure profile or a Mixture, which have no end to choke, and on the general route. Every mode declaring core_radius – every MarcatiliMode subclass, a TabulatedMode built from arrays included – is taken as a circular bore of that radius; a rectangular guide keeps the uniform law.

lambda0float

Reference wavelength, m, and the pulse’s centre wavelength.

wavelength_limitstuple of float or None, optional

Shortest and longest wavelength of the frequency window, m. Required unless grid is given.

trangefloat or None, optional

Requested width of the time window, s. Required unless grid is given.

gridsolprop.grid.TimeGrid or None, optional

A grid of one’s own, instead of the three keywords above; the only way to reach dt, ffac or the transform size.

envelopebool, optional

Propagate an envelope. Plasma is off by default; explicit plasma=True selects cycle averaging of instantaneous rates. Plasma forbids THG.

fwhmfloat or None, optional

Pulse duration at half maximum, s.

widthfloat or None, optional

Natural width of a sech pulse, s; give this or fwhm.

pulseshape{‘gauss’, ‘sech’}, optional

Transform-limited shape of the input.

energyfloat or None, optional

Pulse energy, J. Give this or peak_power.

peak_powerfloat or None, optional

Peak power, W, realised after the spectral phases.

phasessequence of float, optional

Taylor spectral phases about lambda0, optics convention: CEP in rad, group delay in s, GDD in s^2, and so on.

pulsessequence of solprop.pulses.Pulse or None, optional

Several pulses launched together, for two-colour and multi-colour inputs: each a solprop.pulses object with its own wavelength, duration, energy or peak power, phase and delay; the input is the sum of their fields (PulseSum). Replaces the single-pulse keywords fwhm, width, pulseshape, energy, peak_power and phases, which must then be left unset; lambda0 still sets the grid’s reference wavelength.

modesint or sequence of Mode, optional

How many HE_1m modes to propagate, or the mode set itself. A set is checked for orthonormality. Supplied sets may include TabulatedHollowMode or TabulatedMode with their own tables. A supplied set carries its own geometry: radius must agree with every mode’s core radius along the run, and a model, loss or cladding declared away from its default must be every mode’s own, or the call is refused by name rather than the argument ignored.

mode_averagebool, optional

Propagate the one mode mode-averaged, as a uniform disc of its effective area, instead of resolving it on the radial rule (docs/guide/waveguides/mode-averaging.md). The plasma then sees the area-mean field, below the on-axis one (HE_11’s axis intensity is 1.768 times P/A_eff), and peak_intensity stays on the axis. False, the default, resolves the mode. Refused beside more than one mode and beside n_r, n_theta or a radial_rule.

latticeTubeLattice or None, optional

Tube geometry for an integer mode count, selecting Vincetti modes. Refused with supplied modes, which carry their own geometry, and with model="reduced". None selects ordinary capillary modes.

wallsolprop.modes.CoherentWall or None, optional

Declare the scalar coherent wall block: the outgoing Robin boundary condition condensed onto the retained basis, which couples every HE_1m channel to every other with a definite phase instead of giving each its own Marcatili attenuation. It needs the contiguous set HE_11 to HE_1N – or, with impedance="te_tm", one azimuthal order – on a constant or a varying guide, a scalar run and no noise model, and all three backends execute it (a method="cf4" wall numpy_ref alone); every other mode set or geometry is refused by name. None, the default, carries no wall: the modes keep their own Marcatili loss, and a multimode taper its taper coupling (below).

taper_couplingbool, optional

On a multimode capillary whose radius varies along z, carry the taper coupling – the connection <psi_m|d_z psi_n> that moves power between the HE_1m channels as the bore changes – lossless or not. True, the default; False is the explicit opt-out to the adiabatic route, on which each channel follows its local mode and exchanges no power. It is refused beside wall, which always carries the connection, and has no effect on one channel, a constant bore (a pressure gradient included, which does not change the modes’ shape) or a set that is not the contiguous HE_11 to HE_1N block (docs/guide/waveguides/capillaries.md, “Tapers”).

model{‘full’, ‘reduced’}, optional

Which Marcatili model the modes use; beside a supplied set, refused unless it is the default or the modes’ own.

lossbool, float or callable, optional

Propagation loss of the modes; beside a supplied set, refused unless it is the default or the modes’ own.

claddingGlassIndex, complex or None, optional

Cladding index; None is the package’s cited silica. Beside a supplied set, refused unless it is the default or the modes’ own.

susceptibilityGasSusceptibility or None, optional

A gas susceptibility replacing the one gas selects, for a comparison against another code’s refractive data. Refused for a fraction mapping or an existing mixture, which own their species models.

temperaturefloat, ZProfile or None, optional

Gas temperature, K, or a path of it along z in m. Sets the density the pressure path maps to, so it changes both the dispersion and the nonlinearity. A path also weights a steady-flow gradient by the gas’s eta(T) T (docs/guide/waveguides/profiles.md), makes a shared mixture’s populations independent parameters, and holds the rotational Raman populations at one reference temperature with a RamanTemperatureWarning (solprop.nonlinear.mixtures.raman_temperature()). A constant path is the number, bit for bit. None (the default) is 293.15 K. A Mixture owns its temperature: beside one, a temperature must be omitted or be the mixture’s own (the same number or path object), and any other is refused by name.

kerrbool, optional

Include the Kerr response.

thgbool or None, optional

Include third-harmonic generation in the Kerr term; None takes not envelope.

plasmabool, IonisationRate, Mapping or None, optional

Include photoionisation. None takes not envelope. True selects optmat’s recommended rate model of each built-in gas (SEP 3, D1; OptmatRate, or the model the selection’s ionisation names), for a single gas and for every component of a mixture; a custom species needs its own rate. A rate object is used as given; a mapping selects a rate or switch per component label, and omitted labels are off.

preionisationfloat, ZProfile, Mapping or None, optional

Initial ionised fraction in [0, 1], globally or per label: a number, or a path along z in m giving the fraction ionised before the pulse arrives at each position. None and omitted mapping labels retain the component’s existing declaration.

plasma_integration{‘band’, ‘trapezoid’} or None, optional

How the field-grid plasma forms its population and free-current integrals (SEP 18): 'band' filters each integrand with taps designed for the grid, exact to a certified 1e-5 across the active band; 'trapezoid' is the plain cumulative trapezoid, short by up to 11 % per integral at the top of the default active band, which the frozen witness comparisons use. None takes PlasmaResponse’s default. Refused with envelope plasma, whose currents are converted exactly, and when the plasma is off.

ramanbool, sequence of str, Mapping or None, optional

None (the default) turns the Raman response on for every species whose optmat response is curated – N2, O2, H2, D2, CH4 and SF6 – leaves an atom without one, and warns (solprop.exceptions.SolpropWarning) for a molecule whose response is provisional (N2O, unless the selection’s raman is "provisional") rather than leaving it out silently; with kerr=False the default is off. False disables it; True selects the available models of a mixture and is refused by name for a single gas without data; explicit labels or MolecularOptions select components and terms, and a named unavailable model fails explicitly.

n_rint or None, optional

Radial nodes of the fixed rule. None takes default_radial_order() of the mode count.

n_thetaint or None, optional

Azimuthal nodes. Refused for a set of purely radial modes, which need none.

radial_rulestr, optional

The radial rule family (SEP 19): "gauss_kronrod" (the default), whose embedded Gauss subset is the quadrature alarm’s error estimate; "gauss", with no alarm; or "field_scale" and "field_scale_radau", Gaussian in the HE_11 field scale for expensive responses, which need exactly one Marcatili HE_11 mode and have no alarm (docs/guide/waveguides/radial-quadrature.md).

ionisation_field_rangetuple of float or None, optional

Field amplitudes in V/m the rate table must cover. None derives them from the input’s peak field over the axis and the transverse nodes; see solprop.driver.simulation.default_field_range().

absorbersolprop.boundaries.Absorber or None, optional

The collar rates; None builds the default collar of the grid.

absorber_scheme{‘nonlinear’, ‘split_step’} or None, optional

How the temporal collar is applied (ADR-025): inside every stage, the default, or once per accepted step. The low-call Adams methods of SEP 13 step much further with 'split_step', whose first-order splitting error stays inside the collar.

noise{‘default’, None, ‘input’, ‘modified’}, optional

Which shot-noise model to carry. "default", the default, resolves to "input" wherever the run can carry noise, and records the resolution (SEP 37).

seedint or None, optional

Entropy of the noise generator.

rtolfloat or None, optional

Relative step tolerance; the default is CAPILLARY_RTOL, the capillary default. Calibrate it for a production run (docs/dev/stepper.md section 3).

atolfloat, optional

Absolute step tolerance, in the square root of watts.

dz_maxfloat or None, optional

Cap on the step, m; None takes half the capillary.

dz_initfloat or None, optional

First step, m; None takes length * 1e-4.

schedulesolprop.stepper.schedule.FixedSchedule or None, optional

A fixed schedule to replay instead of stepping adaptively.

integratorMultistep, RungeKutta or LowStorageRungeKutta, optional

The method that steps the run (docs/guide/numerics/choosing-a-stepper.md). None, the default, takes Multistep(): the low-call exponential Adams method, one response evaluation per step. RungeKutta() is the interaction-picture DOPRI5 march, for a cheap response or a state too large for the Adams history, and faster on a long run with Raman or plasma (SEP 37). LowStorageRungeKutta() replays schedule in three registers (SEP 24).

interpolate_planesbool, optional

Observe the save planes inside accepted steps instead of landing on them (SEP 14): through the Adams march’s own polynomial, or DOPRI5’s continuous extension with RungeKutta(). Default False.

step_planesint or None, optional

Also save the end of every step_planes-th accepted step, the march’s own positions, beside the requested planes (SEP 14); 0 saves the requested planes only. None, the default, is 0, or 1 with a tdse response, which saves every accepted step without imposing a landing (SEP 20 section 5.8).

save_planessequence of float or None, optional

Positions to save at, m. Give this or n_save.

n_saveint or None, optional

How many planes to save, counting z = 0.

statssolprop.stats.StatsSpec or None, optional

Which statistics to record; None takes solprop.stats.default_spec() for a multimode run with the profiles, or for a mode-averaged one under mode_average, plus every statistic only a backend can compute.

node_budgetint, optional

Bytes of node-chunk buffers the response pass may hold.

backendstr, optional

Registry name, or "auto" (the default) to prefer native if installed and otherwise use Numba CPU. Import or construction errors do not fall back.

precision{‘double’, ‘single’}, optional

The arithmetic the run is held in (SEP 33): "double", the default, or "single", which takes rtol at the floor SINGLE_RTOL_FLOOR by default, RungeKutta() and backend="numpy_ref" (SimulationSettings.precision).

polarisationstr, float or None, optional

Refused; this path is scalar.

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take the run’s built-in materials from optmat under this selection: a gas or fraction mapping of built-in gases, "air" and Gas.Air resolve through solprop.physdata.species() and solprop.physdata.mixtures.Mixture.air() with it, and the default cladding (cladding=None with a numbered mode set) is optmat’s recommended silica. A supplied mixture, mode set, cladding or susceptibility is taken as it is. The run records its material manifest (output schema 8). None (the default) is MaterialSelection().

tdsesolprop.nonlinear.tdse.TDSEGasResponse or None, optional

A helium TDSE response, SAE or haCC, used as the complete electronic response of the fill instead of the Kerr, plasma and Raman responses (SEP 20 section 5.2); plasma, raman, preionisation, plasma_integration, ionisation_field_range and thg must then be left unset and kerr true. backend="auto" resolves to "numpy_ref", the only backend that executes it; statistics default to those the route defines; omitted save_planes and n_save save only the final position beside every accepted step. An atomic window whose duration is unresolved takes trange. None keeps the rate-based responses.

tdse_executionsolprop.nonlinear.tdse.TDSEExecution or None, optional

Atomic runtime resources of tdse: device, memory limit, rows per call and call cap. None beside tdse takes TDSEExecution(); refused without tdse.

Returns:
Simulation

The simulation, ready to translate and run.

Raises:
DriverError

If a keyword is missing, inconsistent, or names something this path does not carry.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_capillary(
...     125e-6, 0.1, "He", (0.8, 0.1), lambda0=800e-9,
...     wavelength_limits=(150e-9, 2e-6), trange=200e-15,
...     fwhm=10e-15, energy=100e-6, modes=2, n_save=3,
... )
>>> len(simulation.modes), simulation.settings.quadrature.n_nodes
(2, 33)
>>> sorted(simulation.profiles)
['core_radius', 'density', 'pressure']
classmethod from_free(grid, space, medium, responses, initial, *, settings, frame=None, noise='default', seed=None, materials=None)[source]#

Build a Cartesian propagation with constant media and transverse FFTs.

A solprop.grid.LineGrid runs the same transform with one y column: the beam is uniform in y, the run records transverse_measure = "per_unit_width", and its energies and powers are per metre of y.

Parameters:
gridsolprop.grid.TimeGrid

Field or envelope time grid, in SI units.

spacesolprop.grid.FreeGrid

Cartesian axes, area measure and spatial collar, or a solprop.grid.LineGrid.

mediumsolprop.spatial.SpatialMedium

Constant bulk material; varying profiles are refused.

responsescollections.abc.Sequence

Existing Kerr, plasma or explicitly declared Raman response objects.

initialsolprop.pulses.SpatialPulse or numpy.ndarray

Beam specification or internal Cartesian DFT spectrum in V/m, with shape (n_x*n_y, n_pol, n_omega).

settingsSimulationSettings

Step tolerances, positive save positions in m, statistics and backend. Absolute tolerance has the input spectrum’s units, V/m.

framesolprop.linear.Frame or None, optional

Moving frame. None uses the declared responses’ THG choice.

noise{‘default’, None, ‘input’, ‘modified’}, optional

One photon per transverse column, polarisation and active bin. "default", the default, resolves to "input" wherever the run can carry noise, and records the resolution (SEP 37).

seedint or None, optional

Random generator seed; None draws and records system entropy.

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take the medium’s gas from optmat under this selection: a SpatialMedium naming a built-in gas becomes the one-population Mixture of that gas under the selection at the same pressure and temperature (a supplied susceptibility is kept). A mixture, glass or constant index is taken as it is. An optmat rate’s energy per event is bound to the input’s peak field (SEP 3, Q14); every response, a KerrResponse included, is the caller’s (gamma3("Ar", wavelength=...) is optmat’s coefficient at a carrier). The run records its material manifest (output schema 8). None (the default) is MaterialSelection().

Returns:
Simulation

Cached translation and the ordinary resumable execution interface.

Raises:
DriverError

If a noise seed is given without noise or the input shape is invalid.

classmethod from_gnlse(gamma, length, betas=None, *, lambda0, wavelength_limits=None, trange=None, grid=None, beta=None, fibre=None, n2=None, fwhm=None, width=None, pulseshape='gauss', energy=None, peak_power=None, phases=(), pulses=None, loss_db_per_m=None, shock=True, raman=False, raman_fraction=None, noise='default', seed=None, rtol=None, atol=1e-14, dz_max=None, dz_init=None, schedule=None, integrator=None, interpolate_planes=False, step_planes=0, save_planes=None, n_save=None, stats=None, polarisation_taper=False, backend='auto', precision='double', materials=None)[source]#

Build a simulation of a GNLSE fibre from its coefficients.

The constructor solprop.driver.interface.prop_gnlse() calls; its docstring documents every keyword, and this method takes them unchanged. The GNLSE is not a separate solver path: it is the mode-averaged envelope problem with a dispersion-specified mode, density = 1, prefactor_index = 1 and the shock term supplied by the prefactor’s omega dependence (docs/guide/waveguides/gnlse.md).

Parameters:
gammafloat or None

Nonlinear coefficient in 1/(W m).

lengthfloat

Fibre length, m, positive.

betasarray_like, optional

Taylor coefficients of beta about lambda0, beta_0, beta_1, ... in s^n/m. Give exactly one of this, beta or fibre.

lambda0float

Reference wavelength, m: the gamma mapping’s, the Taylor expansion’s, the grid’s and the pulse’s centre.

wavelength_limitstuple of float, optional

Shortest and longest wavelength of the frequency window, m. Required unless grid is given.

trangefloat, optional

Extent of the time window, s. Required unless grid is given.

gridsolprop.grid.TimeGrid, optional

An envelope grid to use instead of building one. A field grid is refused.

betatuple or callable, optional

The propagation constant as data: a pair of arrays (omega, beta) in rad/s and 1/m, or a callable of omega sampled onto the grid’s active band. Both go through solprop.nonlinear.gnlse.TabulatedDispersion.

fibreMode or IndexTable, optional

Whole dispersion and loss instead of betas or beta. A mode goes through solprop.nonlinear.gnlse.SpecifiedMode.from_mode(), so one whose geometry moves along z – a tapered mode, a moving guide’s provider channel, a SpecifiedMode with dispersion and area paths – hands over its dispersion and its area along z; only the fixed-step scaffold requires a z-constant fibre. Its fill is ignored as a nonlinear material: the GNLSE uses gamma or n2, retaining the mode only for dispersion, loss and area. A table’s area is evaluated at lambda0, and so is a provider channel’s, by a fresh solve there (along the path of a moving guide); without an area column a table requires gamma and uses the 1 m^2 convention.

n2float or str, optional

Nonlinear index in m^2/W, requiring fibre and gamma=None. Exactly one of gamma and n2 is required. The mapping is gamma = n2 omega0 / (c A_eff), with unit prefactor index. Under materials, "recommended" takes optmat’s silica bundle’s total n2 at lambda0.

fwhmfloat, optional

Intensity full width at half maximum of the input, s.

widthfloat, optional

Natural width of a sech**2 input, s. Give this or fwhm.

pulseshape{‘gauss’, ‘sech’}, optional

Shape of the input.

energyfloat, optional

Pulse energy, J. Give this or peak_power.

peak_powerfloat, optional

Peak power, W.

phasesarray_like, optional

Optics-convention spectral phase about lambda0: CEP in rad, then group delay, GDD, TOD, … in s^n.

pulsessequence of solprop.pulses.Pulse or None, optional

Several pulses launched together, for two-colour and multi-colour inputs: each a solprop.pulses object with its own wavelength, duration, energy or peak power, phase and delay; the input is the sum of their fields (PulseSum). Replaces the single-pulse keywords fwhm, width, pulseshape, energy, peak_power and phases, which must then be left unset; lambda0 still sets the grid’s reference wavelength.

loss_db_per_mfloat or None, optional

Omitted means zero loss on the coefficient routes. Refused beside fibre, which carries its own loss. Power loss in dB/m, converted by solprop.nonlinear.gnlse.attenuation_from_db().

shockbool, optional

Keep the prefactor’s omega dependence, which is the shock term.

ramanbool, optional

Whether a fused-silica Raman response takes raman_fraction of gamma.

raman_fractionfloat or None, optional

Share of gamma held back from the Kerr term, between 0 and 1. Omitted, the silica bundle’s f_R with raman true and 0 with it false; given, held back either way.

noise{‘default’, None, ‘input’, ‘modified’}, optional

Which shot-noise model to carry (docs/guide/media/noise.md). "default", the default, resolves to "input" wherever the run can carry noise, and records the resolution (SEP 37).

seedint, optional

Entropy of the generator the realisation is drawn from, recorded in the output so a run is reproducible.

rtolfloat or None, optional

Relative tolerance of the step controller.

atolfloat, optional

Absolute tolerance, in the square root of watts.

dz_maxfloat, optional

Cap on the controller’s proposal, m; None uses half the length.

dz_initfloat, optional

First step, m; None uses a ten-thousandth of the length.

schedulesolprop.stepper.schedule.FixedSchedule, optional

A fixed schedule to replay instead of stepping adaptively (docs/dev/stepper.md section 8).

integratorMultistep, RungeKutta or LowStorageRungeKutta, optional

The method that steps the run (docs/guide/numerics/choosing-a-stepper.md). None, the default, takes RungeKutta(), the interaction-picture DOPRI5 march, which SEP 37 measured fastest at matched accuracy on the GNLSE. Multistep() is the low-call exponential Adams method, one response evaluation per step. LowStorageRungeKutta() replays schedule in three registers (SEP 24).

interpolate_planesbool, optional

Observe the save planes inside accepted steps instead of landing on them (SEP 14): through the Adams march’s own polynomial, or DOPRI5’s continuous extension with RungeKutta(). Default False.

step_planesint, optional

Also save the end of every step_planes-th accepted step, the march’s own positions, beside the requested planes (SEP 14); 0, the default, saves the requested planes only.

save_planesarray_like, optional

Positions to save at, m. Give this or n_save.

n_saveint, optional

Number of planes to store, counting the one at z = 0, spread evenly over the fibre. Default 201.

statssolprop.stats.StatsSpec, optional

Which statistics to record; None records solprop.stats.default_spec() of a mode-averaged run.

polarisation_taperbool, optional

Whether the spectral collar tapers the nonlinear polarisation. Default False: the taper costs a systematic error of the size of the field’s content in the collar, and the rate absorber acts either way.

backendstr, optional

Registry name, or "auto" (the default) to prefer native if installed and otherwise use Numba CPU. Import or construction errors do not fall back.

precision{‘double’, ‘single’}, optional

The arithmetic the run is held in (SEP 33): "double", the default, or "single", which takes rtol at the floor SINGLE_RTOL_FLOOR by default, RungeKutta() and backend="numpy_ref" (SimulationSettings.precision).

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take fused silica’s nonlinear response from optmat’s silica bundle (SilicaBundle): with raman on, an omitted fraction is the bundle’s f_R and the response its sampled shape; n2="recommended" is its total n2. The fibre’s dispersion, area and a given gamma or n2 are the caller’s. The run records its manifest (output schema 8), the held-back fraction and its origin included. None (the default) is MaterialSelection().

Returns:
Simulation

Ready to run().

Raises:
DriverError

If the fibre, the grid, the input or the save planes are specified in a way this interface does not accept; the message names what is wrong.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3,
... )
>>> simulation.settings.save_planes.tolist()
[0.005, 0.01]
classmethod from_planar(grid, space, responses, initial, *, settings, frame=None, materials=None)[source]#

Build a hybrid planar propagation: slab modes in x, an FFT in y.

The hollow planar guide resolved in both transverse directions: the slab modes of space in x and its periodic y axis, exact (non-paraxial) in y, so whole-beam self-focusing and the modulational instability in y – which a slab uniform in y cannot show – are in the model. The fill is the modes’ own, as a bulk medium; it and the gap must be constant along z. The geometry integrates over y, so energies are in J and powers in W. The collar in y absorbs only when settings declares an absorber, as for from_free().

Parameters:
gridsolprop.grid.TimeGrid

Field or envelope time grid, in SI units.

spacesolprop.modes.slab.PlanarGrid

The slab modes (one gap, one polarisation family, one constant fill) and the y axis with its collar.

responsescollections.abc.Sequence

Existing Kerr, plasma or explicitly declared Raman response objects, scaled by the fill’s number density.

initialsolprop.pulses.PlanarPulse or numpy.ndarray

The astigmatic launch, or an internal (p, k_y) spectrum of slab amplitudes in sqrt(W/m), shape (n_p*n_y, 1, n_omega), the mode index fastest. Any other pulse is refused by name.

settingsSimulationSettings

Step tolerances, positive save positions in m, statistics and backend. Absolute tolerance has the input spectrum’s units, sqrt(W/m).

framesolprop.linear.Frame or None, optional

Moving frame. None uses the declared responses’ THG choice, following the first mode at k_y = 0 as the modal route does.

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take the slab modes’ built-in materials from optmat under this selection and record it in the run’s manifest (output schema 8): a fill of a built-in gas with its default susceptibility takes the selection’s single-species susceptibility (no mixture is needed), and a slab without a declared cladding takes optmat’s recommended fused silica (SEP 3, Q5). A supplied susceptibility or cladding is taken as it is. An optmat rate’s energy per event is bound to the input’s peak field (SEP 3, Q14), and the input is checked against each rate. None (the default) is MaterialSelection().

Returns:
Simulation

Cached translation and the ordinary resumable execution interface.

Raises:
DriverError

If the fill varies along z or is a mixture, the input is neither a solprop.pulses.PlanarPulse nor a spectrum of the planar shape.

classmethod from_radial(grid, space, medium, responses, initial, *, settings, frame=None, noise='default', seed=None, materials=None)[source]#

Build a radial propagation using physical fields and the scalar QDHT.

Parameters:
gridsolprop.grid.TimeGrid

Field or envelope time grid, in SI units.

spacesolprop.grid.RadialGrid

Radial nodes, outer radius and spatial collar.

mediumsolprop.spatial.SpatialMedium

Homogeneous transverse material; gas density may vary along z.

responsescollections.abc.Sequence

Existing Kerr, plasma or explicitly declared Raman response objects.

initialsolprop.pulses.SpatialPulse or numpy.ndarray

Beam specification or internal Hankel spectrum in V m, with shape (n_r, n_pol, n_omega).

settingsSimulationSettings

Step tolerances, positive save positions in m, statistics and backend. Absolute tolerance has the input spectrum’s units, V m.

framesolprop.linear.Frame or None, optional

Moving frame. None uses the declared responses’ THG choice.

noise{‘default’, None, ‘input’, ‘modified’}, optional

One photon per transverse column, polarisation and active bin. "default", the default, resolves to "input" wherever the run can carry noise, and records the resolution (SEP 37).

seedint or None, optional

Random generator seed; None draws and records system entropy.

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take the medium’s gas from optmat under this selection: a SpatialMedium naming a built-in gas becomes the one-population Mixture of that gas under the selection at the same pressure and temperature (a supplied susceptibility is kept). A mixture, glass or constant index is taken as it is. An optmat rate’s energy per event is bound to the input’s peak field (SEP 3, Q14); every response, a KerrResponse included, is the caller’s (gamma3("Ar", wavelength=...) is optmat’s coefficient at a carrier). The run records its material manifest (output schema 8). None (the default) is MaterialSelection().

Returns:
Simulation

Cached translation and the ordinary resumable execution interface.

Raises:
DriverError

If a noise seed is given without noise or the input shape is invalid.

classmethod from_waveguide(modes, length, gas=None, pressure=None, *, provider=None, channel=None, incident=None, coupling=None, kerr_form='real', observable_rtol=None, observable_atol=None, pressure_floor=None, vacuum_end=None, lambda0, wavelength_limits=None, trange=None, grid=None, envelope=False, fwhm=None, width=None, pulseshape='gauss', energy=None, peak_power=None, phases=(), pulses=None, susceptibility=None, temperature=None, kerr=True, thg=None, plasma=None, preionisation=None, plasma_integration=None, raman=None, mode_average=False, n_r=None, n_theta=None, radial_rule='gauss_kronrod', ionisation_field_range=None, absorber=None, noise='default', seed=None, rtol=None, atol=1e-10, dz_max=None, dz_init=None, schedule=None, integrator=None, save_planes=None, n_save=None, stats=None, node_budget=67108864, backend='auto', precision='double', polarisation=None, taper_coupling=True, memory_budget=None, materials=None)[source]#

Build a pulse simulation in a waveguide: a gas-filled mode set, or a guide.

Without `provider` this is the gas-filled route: modes keep their geometry, cladding and loss and receive the declared fill, their nonzero field components determine the transverse quadrature layout, and rectangular polarisation partners are separate rows with separate operators. A hollow planar set (SlabMode) is uniform in y and runs per unit width: energy is J/m, peak_power W/m, and the run records transverse_measure = "per_unit_width". Step-index fibres use prop_gnlse(fibre=...) instead.

With `provider` this is the general modal route (docs/guide/waveguides/general-modal.md): a guide that solves its own three-component E and H at quadrature nodes, whose material regions own their responses and whose channels are Poynting-normalised, so that a channel amplitude is a true-power amplitude by construction. It is qualified on numpy_ref, numba_cpu and the native CPU backend, a declared split block’s coupled flow included, and propagates constant geometry on a field grid. Every gas keyword is refused by name beside a provider, because a guide’s materials are its regions’ and not a fill.

Parameters:
modessequence of solprop.modes.protocol.Mode

Non-empty gas-filled mode set with a common transverse geometry. Each mode is rebound to this constructor’s fill (with_mixture): its own gas, pressure and temperature – a temperature path included – are replaced by gas, pressure and temperature, and only its geometry is kept. Beside provider it must be empty or exactly the guide’s own ordered channels: a guide supplies its channels itself, and the provider has already validated their order against its fields.

lengthfloat

Waveguide length, m.

gasGas, str, Mapping, Mixture or None

Built-in gas, mole fractions keyed by species name, or ordered populations carrying their own density paths. A mapping uses total pressure. Required without provider and refused beside one.

pressurefloat, sequence, ZProfile or None, optional

None uses one bar for a gas or fractions. Omit pressure beside a Mixture; every explicit pressure is refused because it already carries its paths. Fill pressure in bar: a number for a constant fill, a pair (p_in, p_out) for the steady-flow gradient of solprop.profiles.PressureGradient.two_point(), or (z, p) with the positions and the pressures there for solprop.profiles.PressureGradient.from_stages().

providersolprop.modes.guide.ModalGuide or None, optional

A guide built by solprop.modes.guide.ModalGuide.from_provider(), so that it carries the sampling its dense E/H reference is rebuilt from. Its knots must span the run’s whole active band, which starts at half the lowest declared frequency; a narrower guide is refused with both bands in the message.

channelint or str or None, optional

Which channel the pulse enters, by index or by display label ("HE1,1:even"); None takes the first, as a gas-filled multimode run puts a single pulse in its fundamental. The launch is the pulse’s amplitude placed in that channel unchanged – a Poynting basis needs no conversion – so the launched true-power energy is the pulse’s. Requires provider.

incidentsolprop.pulses.SpatialPulse or None, optional

An incident beam to launch instead of a named channel: the beam and its temporal pulse, whose energy or peak power is met over the whole beam in the paraxial measure of the guide’s core medium (solprop.pulses.SpatialPulse.incident()). The beam is coupled into the channels by solprop.coupling.coupler.couple() under coupling (SEP 31): it is sampled on a radial plane that resolves it, evaluated at the guide’s nodes, and its coordinates are recovered with the flux pairing and the forward closure H_t = Y0 z x E_t. The recovered amplitudes are launched as they are. Light the channels do not capture is lost, not restored: a beam much wider than the core launches a small share of its energy, and a beam the channels cannot see launches nothing, which is a valid zero launch. The coupling’s CouplingReport – incident and launched energy per frequency and in total, and its admission budget – is recorded as configuration["launch"], and the launch’s provenance as configuration["coupling"]. The beam is launched at its waist (propz=0) and centred on the guide’s axis. The pulse keywords (fwhm, width, energy, peak_power, phases, pulses and pulseshape) are refused beside it, because the beam carries its own pulse. Requires provider and coupling, and is refused beside channel.

couplingsolprop.coupling.models.CouplingModel or None, optional

The model an incident beam is coupled under: CouplingModel("vector_paraxial", model_error=...), whose budget the guide’s contrast, closure and angular content must fit (SEP 31, section 4.3); a strongly guiding core is refused. Requires incident.

kerr_form{‘real’, ‘analytic’}, optional

Which instantaneous cubic a general modal run’s material regions respond with. "real", the default, is the real-field cubic P = eps0 chi3 (E.E) E the legacy field route evaluates, third harmonic included; "analytic" is the analytic-signal form eps0 chi3 (2 |E|^2 E + (E.E) E*) / 4, which carries the fundamental band alone and is what a comparison with an envelope route wants. The real form needs a grid with n_to >= 2 n_t, which is FieldGrid’s default ffac=6, and is refused on a narrower one. Under one of SEP 6’s dispersive electronic policies a region’s gas fill takes the dispersive cubic in the matching sector: "real" its full cubic, "analytic" its number-conserving sector. Requires provider.

observable_rtol, observable_atolfloat or None, optional

Requested accuracy of the named physical observables of a general modal run. None, the only value accepted, means the solver’s own rtol and atol: the route’s basis is orthonormal in true power, so the controller’s weighted norm on the amplitudes already is a norm on the physical channel powers. A different number is refused by name, because the separate error allocation it would ask for – over the table’s interpolation, the transverse rule and the step – is not implemented. Require provider.

pressure_floorfloat or None, optional

Lowest pressure the fill is allowed to reach, bar; None takes solprop.profiles.DEFAULT_PRESSURE_FLOOR_FRACTION of the highest stage pressure. With vacuum_end="floor", pass 0.0 for a true vacuum end, which warns, because dp/dz diverges there.

vacuum_end{‘choked’, ‘floor’} or None, optional

How a pressure gradient’s outer end below its choked pressure is treated. None (the default) means "choked" for a circular hollow guide: the fill follows the bore (Pennetta et al. 2019, eq. 6) and an end exhausting into vacuum takes the choked pressure of the flow (solprop.gasflow.steady_fill()), with a warning if the flow is not laminar. "floor" concerns the ends only: it keeps the declared end pressures, raised only to pressure_floor, for a comparison with a model that imposes them, while a taper’s fill still follows the bore (on a uniform bore, bitwise the uniform law). Refused beside a constant pressure, a pressure profile or a Mixture, which have no end to choke, and on the general route. Every mode declaring core_radius – every MarcatiliMode subclass, a TabulatedMode built from arrays included – is taken as a circular bore of that radius; a rectangular guide keeps the uniform law.

lambda0float

Reference wavelength, m, and the pulse’s centre wavelength.

wavelength_limitstuple of float or None, optional

Shortest and longest wavelength of the frequency window, m. Required unless grid is given.

trangefloat or None, optional

Requested width of the time window, s. Required unless grid is given.

gridsolprop.grid.TimeGrid or None, optional

A grid of one’s own, instead of the three keywords above; the only way to reach dt, ffac or the transform size.

envelopebool, optional

Propagate an envelope. Plasma is off by default; explicit plasma=True selects cycle averaging of instantaneous rates. Plasma forbids THG.

fwhmfloat or None, optional

Pulse duration at half maximum, s.

widthfloat or None, optional

Natural width of a sech pulse, s; give this or fwhm.

pulseshape{‘gauss’, ‘sech’}, optional

Transform-limited shape of the input.

energyfloat or None, optional

Pulse energy, J. Give this or peak_power.

peak_powerfloat or None, optional

Peak power, W, realised after the spectral phases.

phasessequence of float, optional

Taylor spectral phases about lambda0, optics convention: CEP in rad, group delay in s, GDD in s^2, and so on.

pulsessequence of solprop.pulses.Pulse or None, optional

Several pulses launched together, for two-colour and multi-colour inputs: each a solprop.pulses object with its own wavelength, duration, energy or peak power, phase and delay; the input is the sum of their fields (PulseSum). Replaces the single-pulse keywords fwhm, width, pulseshape, energy, peak_power and phases, which must then be left unset; lambda0 still sets the grid’s reference wavelength.

susceptibilityGasSusceptibility or None, optional

A gas susceptibility replacing the one gas selects, for a comparison against another code’s refractive data. Refused for a fraction mapping or an existing mixture, which own their species models.

temperaturefloat, ZProfile or None, optional

Gas temperature, K, or a path of it along z in m. Sets the density the pressure path maps to, so it changes both the dispersion and the nonlinearity. A path also weights a steady-flow gradient by the gas’s eta(T) T (docs/guide/waveguides/profiles.md), makes a shared mixture’s populations independent parameters, and holds the rotational Raman populations at one reference temperature with a RamanTemperatureWarning (solprop.nonlinear.mixtures.raman_temperature()). A constant path is the number, bit for bit. None (the default) is 293.15 K. A Mixture owns its temperature: beside one, a temperature must be omitted or be the mixture’s own (the same number or path object), and any other is refused by name.

kerrbool, optional

Include the Kerr response.

thgbool or None, optional

Include third-harmonic generation in the Kerr term; None takes not envelope.

plasmabool, IonisationRate, Mapping or None, optional

Include photoionisation. None takes not envelope. True selects optmat’s recommended rate model of each built-in gas (SEP 3, D1; OptmatRate, or the model the selection’s ionisation names), for a single gas and for every component of a mixture; a custom species needs its own rate. A rate object is used as given; a mapping selects a rate or switch per component label, and omitted labels are off.

preionisationfloat, ZProfile, Mapping or None, optional

Initial ionised fraction in [0, 1], globally or per label: a number, or a path along z in m giving the fraction ionised before the pulse arrives at each position. None and omitted mapping labels retain the component’s existing declaration.

plasma_integration{‘band’, ‘trapezoid’} or None, optional

How the field-grid plasma forms its population and free-current integrals (SEP 18): 'band' filters each integrand with taps designed for the grid, exact to a certified 1e-5 across the active band; 'trapezoid' is the plain cumulative trapezoid, short by up to 11 % per integral at the top of the default active band, which the frozen witness comparisons use. None takes PlasmaResponse’s default. Refused with envelope plasma, whose currents are converted exactly, and when the plasma is off.

ramanbool, sequence of str, Mapping or None, optional

None (the default) turns the Raman response on for every species whose optmat response is curated – N2, O2, H2, D2, CH4 and SF6 – leaves an atom without one, and warns (solprop.exceptions.SolpropWarning) for a molecule whose response is provisional (N2O, unless the selection’s raman is "provisional") rather than leaving it out silently; with kerr=False the default is off. False disables it; True selects the available models of a mixture and is refused by name for a single gas without data; explicit labels or MolecularOptions select components and terms, and a named unavailable model fails explicitly.

mode_averagebool, optional

Propagate the one mode mode-averaged, as a uniform disc of its effective area, instead of resolving it on the transverse rule (docs/guide/waveguides/mode-averaging.md). The plasma then sees the area-mean field, below the on-axis one (HE_11’s axis intensity is 1.768 times P/A_eff), and peak_intensity stays on the axis. False, the default, resolves the mode. Refused beside more than one mode and beside n_r, n_theta or a radial_rule. Refused beside provider.

n_rint or None, optional

Radial nodes of the fixed rule, or the x-axis nodes of a Cartesian product or slab rule. None takes default_radial_order() of the mode count, or cartesian_nodes() of the set’s highest transverse order where that is larger.

n_thetaint or None, optional

Azimuthal nodes, or the y-axis nodes of a Cartesian product rule, whose default is cartesian_nodes(). Refused for a set of purely radial modes, which need none, and for a slab set, which is uniform in y.

radial_rulestr, optional

The radial rule family (SEP 19): "gauss_kronrod" (the default), whose embedded Gauss subset is the quadrature alarm’s error estimate; "gauss", with no alarm; or "field_scale" and "field_scale_radau", Gaussian in the HE_11 field scale for expensive responses, which need exactly one Marcatili HE_11 mode and have no alarm (docs/guide/waveguides/radial-quadrature.md).

ionisation_field_rangetuple of float or None, optional

Field amplitudes in V/m the rate table must cover. None derives them from the input’s peak field over the axis and the transverse nodes; see solprop.driver.simulation.default_field_range().

absorbersolprop.boundaries.Absorber or None, optional

The collar rates; None builds the default collar of the grid.

noise{‘default’, None, ‘input’, ‘modified’}, optional

Which shot-noise model to carry. "default", the default, resolves to "input" wherever the run can carry noise, and records the resolution (SEP 37).

seedint or None, optional

Entropy of the noise generator.

rtolfloat or None, optional

Relative step tolerance; the default is WAVEGUIDE_RTOL, the modal capillary default. Calibrate it for a production run (docs/dev/stepper.md section 3).

atolfloat, optional

Absolute step tolerance, in the square root of watts.

dz_maxfloat or None, optional

Cap on the step, m; None takes half the waveguide.

dz_initfloat or None, optional

First step, m; None takes length * 1e-4.

schedulesolprop.stepper.schedule.FixedSchedule or None, optional

A fixed schedule to replay instead of stepping adaptively.

integratorMultistep, RungeKutta or LowStorageRungeKutta, optional

The method that steps the run (docs/guide/numerics/choosing-a-stepper.md). None, the default, takes RungeKutta(), the interaction-picture DOPRI5 march (SEP 37). Multistep() is the low-call exponential Adams method. LowStorageRungeKutta() replays schedule in three registers.

save_planessequence of float or None, optional

Positions to save at, m. Give this or n_save.

n_saveint or None, optional

How many planes to save, counting z = 0.

statssolprop.stats.StatsSpec or None, optional

Which statistics to record; None takes solprop.stats.default_spec() for a multimode run with the profiles, or for a mode-averaged one under mode_average, plus every statistic only a backend can compute.

node_budgetint, optional

Bytes of node-chunk buffers the response pass may hold.

backendstr, optional

Registry name, or "auto" (the default) to prefer native if installed and otherwise use Numba CPU. Import or construction errors do not fall back.

precision{‘double’, ‘single’}, optional

The arithmetic the run is held in (SEP 33): "double", the default, or "single", which takes rtol at the floor SINGLE_RTOL_FLOOR by default, RungeKutta() and backend="numpy_ref" (SimulationSettings.precision).

polarisationstr, float or None, optional

Refused; this path is scalar.

taper_couplingbool, optional

Carry the taper coupling of a supplied capillary set on a varying radius, as from_capillary() does; False is the opt-out to the adiabatic route. Refused as False beside a provider, whose moving guide carries its own connection.

memory_budgetint or str or None, optional

The budget a guide’s route is admitted against before its dense E/H reference and maps are built, which happens here rather than when the run starts (solprop.driver.memory.admit_guide_memory()): a declaration as run() takes it, and None takes SOLPROP_MEMORY_BUDGET or the machine’s memory, warned on. Requires provider.

materialssolprop.physdata.selection.MaterialSelection or None, optional

Take the fill from optmat under this selection: a gas or fraction mapping of built-in gases, "air" and Gas.Air resolve through solprop.physdata.species() and solprop.physdata.mixtures.Mixture.air() with it. The supplied modes, their claddings, a supplied mixture or susceptibility, and a provider’s material regions are taken as they are. The run records its material manifest (output schema 8). None (the default) is MaterialSelection().

Returns:
Simulation

A configured simulation, ready to translate or run.

Raises:
DriverError

If the modes cannot bind a gas mixture, a gas keyword is given beside a provider, a general-guide keyword is given without one, or any supplied setting is invalid.

MemoryBudgetError

If a guide’s reference and maps exceed a budget declared to refuse; nothing of them has been built.

input_port(z=None)[source]#

Return what this simulation can receive at its entrance (SEP 31).

The port is the receiving side of a transfer between simulations: its route, temporal lattice and basis with their identities, the entrance plane and the frame accumulated there, the native metric at the entrance, the reference index of its entrance medium, the coupling models it admits and what they need: an ordinary mode set’s scalar profiles, or a general guide’s E/H reference at its nodes and its regions’ contrast. A launch computed for it (solprop.coupling.coupler.couple()) is accepted by with_input(), and a launch computed for any other port is refused.

Parameters:
zfloat or None, optional

An interior entrance in m, for a modal run continued from inside its own path; None is the simulation’s launch position.

Returns:
solprop.coupling.InputPort

The port and the models it admits.

Raises:
DriverError

For a hybrid planar run, whose slab columns are not exchanged in this release, or an interior entrance outside the run.

material_manifest()[source]#

Collect the run’s material manifest: what it took from optmat, and how.

Every optmat-backed object the run carries is found where it sits – the mixture, the modes’ fills and claddings, a planar grid’s slab modes, a guide’s material regions, a bulk medium – with the selection the run was built with, the policies in force and what was measured about them: the dilute-scaling error over the run’s whole band, collars included, the loss a transparent solid dropped, and the bands outside a model’s qualified intervals that the run’s range warnings named. metadata() records it once; call it after translate() for a complete measurement. After run() it also carries the post-run diagnostic of each optmat ionisation rate (peak_fields), which the file’s record, written before the run, does not: the run writes it beside the record instead, as the output’s post-run annotation PEAK_FIELDS_ANNOTATION, outside the configuration hash.

Returns:
solprop.physdata.selection.MaterialManifest

The manifest; empty for a run that takes nothing from optmat.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12, raman=True,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3,
... )
>>> [record.name for record in simulation.material_manifest().records]
['kerr/SiO2', 'silica_raman/hollenbeck_2002', 'silica_bundle/default']
metadata()[source]#

Build the record of this run, once, and return it.

Cached because the record stamps the time it was created: two runs of the same simulation are the same run, and their files must carry the same digest.

Returns:
solprop.output.schema.RunMetadata

What produced the run, and the key a resume is checked against.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3,
... )
>>> metadata = simulation.metadata()
>>> metadata.simulation_kind, metadata.spectral_convention
('mode_averaged', 'optics')
>>> metadata.configuration_hash() == simulation.metadata().configuration_hash()
True
modes: tuple[Mode, ...]#
run(output=None, *, progress=None, progress_period=10.0, resume=False, memory_budget=None, tdse_archive=None, snapshots=None)[source]#

Execute the run and return the handler it was written to.

Parameters:
outputsolprop.output.schema.Output or pathlib.Path or str or None, optional

Where the planes go: a handler, a path to write an HDF5 file at, or None for a solprop.output.memory.MemoryOutput. The handler is closed when the run ends, so a file handler is returned closed and is read back with solprop.output.hdf5.open_file(); a memory handler stays readable. A run with optmat ionisation rates then annotates it with their peak-field report (PEAK_FIELDS_ANNOTATION).

progressProgressReporter, {‘auto’, ‘bar’, ‘log’, ‘none’} or None, optional

Where progress goes; None takes the process default: a solprop.log.BarReporter on a terminal or in a notebook, a solprop.log.LogReporter otherwise (solprop.driver.run.run_problem()).

progress_periodfloat, optional

Seconds between the line reporter’s periodic lines, s; 0 leaves only the plane and closing lines. A bar has its own redraw period and a given reporter its own business.

resumebool or {‘interpolated’}, optional

Continue the file at output if it holds this same run, instead of replacing it. Only a path can be resumed: the driver has to open the file in append mode itself. A run interpolating its planes (interpolate_planes) whose last plane was interpolated inside a step is refused unless this is "interpolated": it then continues afresh from the interpolated field, and the position is recorded in the annotation INTERPOLATED_RESUMES_ANNOTATION.

memory_budgetint or str or None, optional

The memory budget this run is admitted against before its backend allocates: bytes, or a string such as "16 GiB" or "warn:16 GiB", or "none"; None takes SOLPROP_MEMORY_BUDGET and otherwise four fifths of the machine’s memory, which only warns (solprop.driver.memory).

tdse_archivesolprop.output.TDSEArchive or None, optional

Archive every raw TDSE provider evaluation of a run with a TDSE response in this separate HDF5 file (SEP 20 section 5.8); None archives nothing. It is opened and validated before any atomic work, a resume appends a new session to its own run’s archive, and the optical output records the archive’s run UUID and relative path. It changes neither the propagation nor the call ledger.

snapshotssolprop.output.SnapshotController or None, optional

Publish immutable local checkpoints without rebuilding the backend or atomic provider. Requires HDF5, step_planes=1, fields='all' and no interpolated output. Adams history cannot be explicitly disabled. A configured archive is copied together with the optical file.

Returns:
solprop.output.schema.Output

The handler the run was written to.

Raises:
DriverError

If a resume is asked for and output is not a path, or the last plane of a dense run was interpolated and resume is not "interpolated"; or tdse_archive is given without a TDSE response or at the path of the optical file.

TDSEArchiveError

If the archive’s path holds another file, or a write to it fails; the run then stops at its last optical checkpoint.

MemoryBudgetError

If the run’s estimated persistent memory exceeds its budget; nothing has been allocated or written.

OutputError

If a file is there and was written for a different run; the message names the fields that changed.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3, rtol=1e-6,
... )
>>> handler = simulation.run()
>>> handler.n_saved, handler["z"].tolist()
(3, [0.0, 0.005, 0.01])
runner(*, memory_budget=None)[source]#

Return a runner that keeps this translation and one backend for many inputs.

Translates (or reuses the cached translation), admits memory and constructs the backend once; each SimulationRunner.run() then runs one input on it (SEP 22 section 5.2). Close it, or use it in a with block.

Parameters:
memory_budgetint or str or None, optional

The budget the backend is admitted against, as for run().

Returns:
SimulationRunner

The open runner.

Raises:
DriverError

If the run has a TDSE response.

MemoryBudgetError

If the backend does not fit its budget.

property settings: SimulationSettings[source]#

Return how the run steps, records and executes; fixed once translated.

Assigning a new SimulationSettings before the first translate() (or run()) takes effect. After it the translated problem is cached, so an assignment that changes anything the translation consumed is refused, because it could no longer change the run; the backend and tdse_execution resources, which are read when the run executes, may still change.

Returns:
SimulationSettings

The settings the run is, or will be, translated with.

translate()[source]#

Assemble the kernel problem, once, and return it.

Everything expensive about a run that does not depend on the state happens here (docs/dev/architecture.md section 7): the cumulative linear operator, the masks, the modal transform and the compiled responses. The result is cached, so two runs of the same simulation translate once.

Returns:
solprop.translate.problem.KernelProblem

Validated, versioned and ready for a backend.

Examples

>>> from solprop.driver import Simulation
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3,
... )
>>> problem = simulation.translate()
>>> problem.shape, simulation.translate() is problem
((1, 1, 1, 1024), True)
with_input(initial, *, noise='keep', initial_z=None, configuration=None)[source]#

Replace the input while sharing the translated propagation problem.

Only what changed is validated (SEP 22 section 5.2): the replaced input’s shape, dtype and one finiteness pass, and the replaced noise’s, with every other leaf of the translated problem shared by identity rather than scanned again. A new initial_z, which changes the save planes, also keeps the stepper’s checks: the launch before the first plane, and a replayed schedule containing every plane. An array input above INLINE_ARRAY_LIMIT elements is recorded by its digest (ArrayDigest), not inline.

Parameters:
initialPulse, SpatialPulse, numpy.ndarray or solprop.coupling.CouplingLaunch

Pulse or internal-convention spectrum on the existing grid. The built shape must match the original input, including modes and polarisation. Modal amplitudes are in sqrt(W); spatial units follow the spatial grid. A CouplingLaunch (SEP 31) must be bound to this simulation’s input_port() – its route, lattice, basis, entrance and metric – or it is refused whatever its shape; its entrance sets the launch position, and its provenance and inherited reference origin are recorded as configuration["coupling"].

noiseNoiseRealisation, {‘keep’} or None, optional

Keep the existing noise, replace it explicitly, or disable it with None. Noise spectra must match the existing grid and input shape. A launch carries the realised field of its source, so for a launch 'keep' means no noise: no second floor is drawn unless a realisation is given.

initial_zfloat or None, optional

Absolute launch position in metres. None retains this simulation’s launch. An explicit position keeps only existing save planes beyond it, preserving all absolute profiles, propagation tables and the frame.

configurationcollections.abc.Mapping or None, optional

Caller keys merged into the derived run’s configuration record, and so into its configuration hash: the delay of a scan, the label of an input. A key the run already records is refused.

Returns:
Simulation

Translated simulation sharing all propagation tables. Metadata is rebuilt for the replacement input and noise. Existing ionisation table ranges remain in force, and so does the reference field of an optmat rate’s constant energy per event, which is the original input’s peak; use a fresh translation to change them.

Raises:
DriverError

If the new field or noise shape differs or any sample is not finite, a configuration key is one the run records itself, or a launch is bound to another port or given beside an initial_z.

Warns:
MaterialRangeWarning

Once per run, when the new input’s peak exceeds an optmat rate’s maximum field, or the input is not linearly polarised at a Keldysh parameter above one there (SEP 3, D12).

with_mixture(mixture)[source]#

Update material paths while preserving the run’s geometry and input.

Rate tables and unchanged undamped Raman kernels are shared by identity. Expansion terms are reused only for the identical sampled function with covered parameter ranges; changing fill fractions invalidates a pressure expansion. Every replacement weight and density or decay table is rebuilt.

Parameters:
mixtureMixture

New paths and populations with the same ordered labels and species data. Public capillary response selections are retained; changed temperature or Raman component options rebuild the affected molecular models.

Returns:
Simulation

A translated simulation sharing the grid, input field, noise realisation, numerical settings and transverse geometry with this one.

Raises:
DriverError

If there is no mixture declaration, or labels, species or unsupported mode geometries differ.

class solprop.driver.simulation.SimulationRunner(simulation, *, memory_budget=None)[source]#

Bases: Displayed

One translated problem and one backend, run for many inputs (SEP 22 section 5.2).

Built by Simulation.runner(): the problem is translated (or the cached translation reused), memory is admitted and one backend is constructed, once. Each run() then derives the input with Simulation.with_input(), loads it into the same backend and runs the save-plane loop, returning that input’s own handler. A large problem so pays its backend’s allocation and transform planning once rather than for every input.

A run on the reused backend repeats a fresh backend’s run, to the rounding that separates any two runs: loading an input restores everything the march reads (solprop.backends.driver.StepDriver.set_initial()). Each run’s record is its own input’s, so each has its own configuration hash.

Use it as a context manager, or call close(): the backend holds about fifteen copies of the state until then. A closed runner refuses run(). A run that raises leaves the runner open, since the next input resets everything; a backend that closed itself closes the runner.

Parameters:
simulationSimulation

The run to repeat. Its settings, and the translation they fix, are used as they are; only the input changes from run to run.

memory_budgetint or str or None, optional

The budget the backend is admitted against (solprop.driver.memory.admit_memory()); each run’s in-memory output is admitted against it again when the run starts.

Raises:
DriverError

If the simulation has a TDSE response, whose atomic binding has its own lifecycle and is never reused.

MemoryBudgetError

If the backend does not fit its budget; nothing has been allocated.

Examples

>>> from solprop.driver import Simulation
>>> from solprop.pulses import SechPulse
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech", n_save=3, rtol=1e-6,
... )
>>> def pulse(power):
...     return SechPulse(wavelength=835e-9, width=100e-15, peak_power=power)
>>> with simulation.runner() as runner:
...     outputs = [
...         runner.run(pulse(power), configuration={"peak_power": power},
...                    progress="none")
...         for power in (5.0, 9.8)
...     ]
>>> [output.n_saved for output in outputs], runner.closed
([3, 3], True)
property backend: Backend[source]#

Return the backend every run is stepped on.

Returns:
solprop.backends.protocol.Backend

The one backend the runner constructed.

close()[source]#

Close the backend, releasing its buffers; calling it twice does nothing.

A run in progress on another thread finishes first: the close waits for it.

property closed: bool[source]#

Return whether the runner, and its backend, are closed.

Returns:
bool

True once close() has run.

run(initial, *, output=None, configuration=None, noise='keep', progress=None, progress_period=10.0)[source]#

Run one input on the runner’s backend and return its handler.

Parameters:
initialPulse, SpatialPulse or numpy.ndarray

The input, as Simulation.with_input() takes it.

outputsolprop.output.schema.Output or pathlib.Path or str or None, optional

Where this input’s planes go: a handler, a path for an HDF5 file, or None for a new MemoryOutput.

configurationcollections.abc.Mapping or None, optional

Caller keys recorded in this input’s run record and hash, such as the delay of a scan (Simulation.with_input()).

noiseNoiseRealisation, {‘keep’} or None, optional

The noise, as for Simulation.with_input(): kept by default, or replaced by another realisation of the same model.

progressProgressReporter, {‘auto’, ‘bar’, ‘log’, ‘none’} or None, optional

Where progress goes (solprop.driver.run.run_problem()).

progress_periodfloat, optional

Seconds between the line reporter’s periodic lines, s.

Returns:
solprop.output.schema.Output

This input’s handler, closed; a memory handler stays readable.

Raises:
DriverError

If the runner is closed or already running an input; if the derived problem is not the runner’s but for its input (a different launch position, or a shared leaf replaced); or if the noise model differs from the runner’s, which the backend could not carry.

MemoryBudgetError

If this input’s in-memory output does not fit beside the backend.

class solprop.driver.simulation.SimulationSettings(controller=None, *, save_planes, dz_max, dz_init, dz_min=None, stretch=None, auto_init=False, interval_cap=None, interpolate_planes=False, step_planes=0, schedule=None, propagator_mode='auto', density=None, shock=True, prefactor_index=None, absorber=None, absorber_scheme='nonlinear', quadrature=None, components=None, ionisation_field_range=None, node_budget=None, stats=None, polarisation_taper=False, backend='auto', integrator=None, precision='double', resume_history=None, tdse_execution=None, fields='all', field_planes=(), evanescent_rate=None, transverse_absorber=None, adiabatic_accuracy=None, _default_integrator=None)[source]#

Bases: Displayed

How a run is stepped, what it records and which backend executes it.

Everything that is not a physics object, in one group, so that a simulation can be constructed from the physics and this. Equality is by identity (eq=False) because save_planes is an array.

Attributes:
controllersolprop.stepper.controller.PIController or None

Tolerances, safety and gains; the tolerances and the norm choice live here and nowhere else (docs/dev/kernel-contract.md section 7). None, the default, takes the interface’s own (SEP 37): SPATIAL_RTOL and SPATIAL_ATOL for Simulation.from_radial() and Simulation.from_planar(). An explicit controller always wins. The other fields are keyword-only.

save_planesnumpy.ndarray

Positions to save at, m, increasing and positive, shape (n_z,). The plane at z = 0 is saved as well and is not listed here. A sequence is adopted as a read-only float64 array, so that two runs specified the same way record the same planes whichever type they passed and therefore hash alike.

dz_maxfloat

Cap on the controller’s proposal, m.

dz_initfloat

First step, m.

dz_minfloat or None

Floor on the proposal, m; None takes solprop.stepper.controller.default_dz_min() of the run length. A proposal below it raises rather than being clamped silently.

stretchfloat or None

Landing stretch factor; None takes solprop.translate.problem.DEFAULT_STRETCH.

auto_initbool

Whether the start-up rule takes the step after the first from the first step’s own error estimate, rather than growing from dz_init at the growth cap (SEP 14). The convenience constructors set it when no dz_init is given. It is off for a coupled flow and a reject-free controller.

interval_capbool or None

Whether a step is capped at the width of its operator-table interval. None caps it only for a coupled flow or a reject-free controller (SEP 14).

interpolate_planesbool

Observe the save planes inside accepted steps instead of landing on them (SEP 14 phase 3): through the Adams march’s own polynomial or, with RungeKutta(), DOPRI5’s continuous extension. Every plane but the run’s end and a hard kink is then interpolated. Refused beside a coupled flow, the per-step temporal collar and the modified noise.

step_planesint

A positive k also saves the end of every k-th accepted step, the march’s own positions, beside the requested planes (SEP 14 phase 3); 0 saves the requested planes only. Not in scans.

integratorMultistep, RungeKutta, LowStorageRungeKutta or None

The method that steps the run (docs/guide/numerics/choosing-a-stepper.md). None, the default, takes Multistep() under double precision and RungeKutta() under single precision, which refuses the Adams method until its single-precision survival is established (SEP 33, Q2); the stored value is the resolved method. Multistep() is the low-call exponential Adams method, which numpy_ref, numba_cpu and native execute for supported configurations; RungeKutta() is the interaction-picture DOPRI5 march, which every backend executes and which holds a third of the Adams history’s memory. LowStorageRungeKutta() replays schedule with RK4 in three registers and no error estimate (SEP 24); every backend executes it (LOW_STORAGE_BACKENDS), and "auto" resolves as for any integrator.

schedulesolprop.stepper.schedule.FixedSchedule or None

A fixed schedule to replay instead of stepping adaptively (docs/dev/stepper.md section 8). Its edges must contain every save plane, which solprop.stepper.schedule.FixedSchedule.uniform() guarantees.

propagator_mode{‘auto’, ‘tabulate’, ‘recompute’}

Whether the backend tabulates the stage propagators (docs/dev/kernel-contract.md).

densitysolprop.profiles.ZProfile or float or None

Number density along z in m^-3 that multiplies the compiled responses; None takes the mode’s own path. The GNLSE passes 1.0 (docs/guide/waveguides/gnlse.md). Refused beside a mixture and beside a gas medium, which carry their own.

shockbool

Keep the omega dependence of the normalisation prefactor, which is the optical shock term.

prefactor_indexfloat or None

Use this constant in the prefactor and power weight; None uses Re n_eff. The GNLSE passes 1.0, leaving its power normalisation and Phi unchanged.

absorber_scheme{‘nonlinear’, ‘split_step’}

How the temporal collar is applied (docs/guide/numerics/boundaries.md). "nonlinear", the default, adds -alpha(t) E(t) / 2 inside every stage; "split_step" multiplies the accepted state by exp(-alpha(t) h / 2) once per step, which is a Lie splitting and first order wherever the collar does any work. The second stays reachable so the comparison can be re-measured and older results reproduced.

absorbersolprop.boundaries.Absorber or None

The collar rates. Its spectral part folds into the linear operator and its temporal part crosses the seam as a rate (docs/guide/numerics/boundaries.md).

quadraturesolprop.modes.quadrature.TransverseQuadrature or None

The fixed transverse rule a multimode run integrates the nonlinear polarisation on (docs/guide/waveguides/mode-sets.md). None builds the mode-averaged single-node transform, which needs exactly one mode.

componentssequence of str or None

Which transverse Cartesian components the multimode transform resolves at each node, a non-empty subset of ("x", "y"); None takes the union of the modes’ nonzero components at the entrance (("x",) for HE_1m modes at phi = 0; docs/dev/conventions.md section 5). Refused without a quadrature.

ionisation_field_rangetuple of float or None

Lowest and highest field amplitude in V/m the compiled ionisation-rate table has to cover. Required beside a plasma response whose rate is not already a table; the table holds its last value above the upper limit, so one set too low is a silent clip.

node_budgetint or None

Bytes of node-chunk buffers a response pass may hold (docs/dev/architecture.md section 13). None, the default, takes 1 GiB on a free-space, line or planar grid and 64 MiB otherwise (DEFAULT_SPATIAL_NODE_BUDGET, DEFAULT_NODE_BUDGET).

statssolprop.stats.StatsSpec or None

Which statistics to collect at every saved plane; None collects none.

polarisation_taperbool

Whether the spectral collar tapers the nonlinear polarisation as well as absorbing the field through the linear operator. Default False, which is solprop.translate.problem.assemble()’s: the taper costs a systematic error of the size of the field’s content in the collar, and the rate absorber acts either way (docs/guide/numerics/boundaries.md).

backendstr

Registry name of the backend to execute the run. The default "auto" resolves to "native" when installed, otherwise "numba_cpu", at settings construction. The stored name is concrete, including in scan workers. An installed backend’s import or construction errors never trigger a fallback.

precision{‘double’, ‘single’}

The arithmetic the run is held in (SEP 33, docs/guide/performance/single-precision.md). "double", the default, is binary64 throughout and changes nothing. "single" holds the state, the stages, the transforms and the responses in binary32, with the controller and every host scalar in binary64; it admits backend="numpy_ref" (the single-precision oracle), refuses an adaptive rtol below SINGLE_RTOL_FLOOR, the Adams integrator and noise models, and is refused by numba_cpu and native. backend="auto" resolves to a GPU backend that computes in binary32 when one is installed and is otherwise refused. Part of the hashed configuration; outputs are binary64 either way.

resume_historybool or None

Whether the output keeps the Adams march’s state at every save plane and terminal checkpoint, so that a resume continues the history – its samples, its order and its proposed step – as the uninterrupted run would, instead of starting it afresh at order one. None, the default, keeps it while it is at most solprop.driver.run.MARCH_SNAPSHOT_AUTO_BYTES; it is outside the resume key. Every backend’s fused and exponential Adams engines, the native backend’s resident one included, export and install their history; a march that cannot (the general path of a comparison method) restarts it and warns.

fields{‘all’, ‘planes’, ‘none’}

Which saved planes keep their field (SEP 22): every one, the default; those of field_planes; or none, for a run wanted as statistics alone. A plane without its field stores no field and no noise phase, and an in-memory output is charged and allocated for the kept fields only; the march is the same. A terminal checkpoint carries the field anyway, so a stopped run resumes, but a file whose last regular plane kept no field resumes only from one. Outside the resume key, like resume_history: it changes what is kept, not what is computed. In a scan, run_scan()’s own fields decide, and a builder that sets this is refused. Beside LowStorageRungeKutta() the backend holds the last field-free plane’s state, one more state volume charged at admission, so a step abandoned in flight still leaves a resumable checkpoint (SEP 22, Q14).

field_planessequence of int

Saved-plane indices for fields='planes', the entrance as 0 and negative from the end; empty otherwise. Refused beside step_planes, whose plane count is not known in advance.

evanescent_ratefloat or None

The spatial operator’s evanescent field attenuation cap in m^-1, positive and finite (SEP 22 section 4.4). None, the default, keeps solprop.spatial.EVANESCENT_RATE; solprop.spatial.physical_evanescent_rate() gives the rate at which the grid’s non-propagating content decays physically. Refused without a spatial grid; a replayed step it would overflow is refused at translation.

transverse_absorbersolprop.boundaries.TransverseCollar or None

A transverse-wavevector safety ramp on a Cartesian or line grid (SEP 22 section 4.3), folded into the operator as an exact diagonal rate. None, the default, carries none. It damps content reaching the grid’s outer wavenumbers; it does not replace sizing the grid by the one-half rule. Refused on the radial and hybrid planar kinds and on modal runs.

adiabatic_accuracysolprop.adiabatic.AdiabaticAccuracy or None

The forward-field and reflected-energy budgets a radial medium varying along z must meet (SEP 34 section 4.5). None, the default, is AdiabaticAccuracy(), both 1e-4; a path exceeding them is refused.

tdse_executionsolprop.nonlinear.tdse.TDSEExecution or None

Explicit atomic runtime resources for a TDSE response. Requires an explicit backend="numpy_ref" and a Multistep integrator. Execution resources are outside the scientific resume identity; attempted-call budgets are cumulative.

Raises:
DriverError

If the save planes are empty, not increasing, or not positive. The same check runs again in solprop.translate.problem.assemble(); here it fires before a run has built anything. Also if the field retention is not valid, asks for fields='planes' beside step_planes.

Examples

>>> from solprop.driver import SimulationSettings
>>> from solprop.stepper import PIController
>>> settings = SimulationSettings(
...     controller=PIController(rtol=1e-8, atol=1e-14),
...     save_planes=[0.5, 1.0], dz_max=0.1, dz_init=1e-3,
...     backend="numpy_ref",
... )
>>> settings.save_planes.tolist(), settings.backend
([0.5, 1.0], 'numpy_ref')
absorber: Absorber | None = None#
absorber_scheme: Literal['split_step', 'nonlinear'] = 'nonlinear'#
adiabatic_accuracy: AdiabaticAccuracy | None = None#
auto_init: bool = False#
backend: str = 'auto'#
components: Sequence[str] | None = None#
controller: PIController | None = None#
density: ZProfile | float | None = None#
dz_init: float#
dz_max: float#
dz_min: float | None = None#
evanescent_rate: float | None = None#
field_planes: Sequence[int] = ()#
fields: Literal['none', 'planes', 'all'] = 'all'#
integrator: Multistep | RungeKutta | LowStorageRungeKutta | None = None#
integrator_named = False#
interpolate_planes: bool = False#
interval_cap: bool | None = None#
ionisation_field_range: tuple[float, float] | None = None#
node_budget: int | None = None#
polarisation_taper: bool = False#
precision: Literal['double', 'single'] = 'double'#
prefactor_index: float | None = None#
propagator_mode: Literal['auto', 'tabulate', 'recompute'] = 'auto'#
quadrature: TransverseQuadrature | None = None#
resume_history: bool | None = None#
save_planes: Float[ndarray, 'n_z'] | Sequence[float]#
schedule: FixedSchedule | None = None#
shock: bool = True#
stats: StatsSpec | None = None#
step_planes: int = 0#
stretch: float | None = None#
tdse_execution: TDSEExecution | None = None#
transverse_absorber: TransverseCollar | None = None#
solprop.driver.simulation.TDSE_NOISE = 'a TDSE run carries no noise by default: it is expensive, rarely repeated as an ensemble, and its checks are coherent'#

Why a default resolves to no noise beside the TDSE response (SEP 37).

solprop.driver.simulation.WAVEGUIDE_ATOL = 1e-10#

Absolute tolerance of a modal waveguide run, in sqrt(W).

The companion of CAPILLARY_RTOL and WAVEGUIDE_RTOL. It was never binding in SEP 37’s measurements.

solprop.driver.simulation.WAVEGUIDE_RTOL = 1e-05#

Relative tolerance a modal waveguide run asks for unless told otherwise.

The default of Simulation.from_waveguide() and prop_waveguide() with their default RungeKutta(), set by SEP 37’s convergence protocol on the benchmark suite’s grin_nonlinear window. A starting point, not a guarantee: a production run should calibrate it.

solprop.driver.simulation.check_derived_problem(constructed, derived)[source]#

Refuse a derived problem that is not the constructed one but for its input.

What a SimulationRunner checks before loading an input into the backend it built for constructed (SEP 22 section 5.2): the leaves Simulation.with_input() shares are the same objects, the stepper and the flags, which it rebuilds, agree field by field (the save planes elementwise), and the launch position and the noise model are the backend’s.

Parameters:
constructedsolprop.translate.problem.KernelProblem

The problem the backend was built for.

derivedsolprop.translate.problem.KernelProblem

The problem of one input.

Raises:
DriverError

Naming the first leaf or setting that differs.

Examples

>>> from solprop.driver import Simulation
>>> from solprop.driver.simulation import check_derived_problem
>>> simulation = Simulation.from_gnlse(
...     0.11, 0.01, [0.0, 0.0, -1.183e-26], lambda0=835e-9,
...     wavelength_limits=(500e-9, 2e-6), trange=1e-12,
...     width=100e-15, peak_power=9.8, pulseshape="sech",
... )
>>> problem = simulation.translate()
>>> derived = simulation.with_input(problem.initial.field0[0]).translate()
>>> check_derived_problem(problem, derived) is None
True
solprop.driver.simulation.default_field_range(peak_field)[source]#

Return the field amplitudes an ionisation table covers, from the input’s peak.

The table is built in log field and its knots double until it is converged (solprop.translate.ionisation.build_rate_table()), so a generous range costs little; getting it wrong is what costs. Below field_min the rate is taken as zero, which is right because every rate this package carries is exactly zero below its threshold, and the threshold is where the lower limit ends up anyway. Above field_max the table holds its last value, so an upper limit that is too low is a silent clip of the rate exactly where ionisation matters most.

Hence three decades below the input peak and thirty times above it. The lower factor only has to reach under the rate’s threshold, which for the noble gases at the intensities a capillary reaches sits one to two decades below the peak. The upper factor has to clear the self-compressed peak: a capillary compressing a pump to a few optical cycles raises the on-axis field by a small single-digit factor before ionisation-induced defocusing and loss clamp it, so thirty is roughly an order of margin on that – a thousand times in intensity.

Parameters:
peak_fieldfloat

Peak field amplitude of the input, V/m, > 0: on a capillary the largest over the axis and the transverse nodes.

Returns:
tuple of float

Lower and upper field amplitude in V/m.

Raises:
DriverError

If the peak field is not positive, which means the input is empty.

Examples

>>> from solprop.driver.simulation import default_field_range
>>> low, high = default_field_range(1e10)
>>> f"{low:.3g} {high:.3g}"
'1e+07 3e+11'
solprop.driver.simulation.default_radial_order(n_modes)[source]#

Return the radial order of the fixed rule a capillary run uses by default.

The rule has to integrate the quartic of the mode profiles, because the Kerr polarisation is cubic in the field and its projection multiplies by one more profile. Those are Bessel functions of r/a, so a Gauss rule converges spectrally and the only question is where. Two measurements set the number: the quartic overlap tensor of four HE_1m modes is converged to 2e-14 at n_r = 32 (docs/guide/waveguides/mode-sets.md), and the embedded error estimate for three modes falls 1.6e-1, 2.1e-2, 4.1e-5, 7.2e-9, 1.2e-15 at n_r = 8, 16, 24, 32, 48. Thus 32 clears the alarm by two orders on three modes and is the reference’s rounding on four. Eight nodes per mode carries that scaling to larger sets, since the highest radial order in the quartic grows with the set.

A flat, larger order whatever the mode count would be safer and slower; 32 nodes on the sets a capillary run actually uses, with the alarm watching, is the trade this makes. The number rests on these two measurements and has not been calibrated further.

Parameters:
n_modesint

How many modes the set carries, >= 1.

Returns:
int

Radial nodes asked of solprop.modes.quadrature.transverse_quadrature(), which with radial_rule="gauss_kronrod" rounds an even count up by one so that the rule is the Kronrod extension of the half-order Gauss rule.

Examples

>>> from solprop.driver.simulation import default_radial_order
>>> default_radial_order(1), default_radial_order(4), default_radial_order(8)
(32, 32, 64)
solprop.driver.simulation.metadata_for(problem, grid, *, modes=(), configuration=None, noise=None, modal=None, materials=None, quadrature=None, frame=None, noise_resolution=None)[source]#

Build the record that says what produced a run, and whether it may be resumed.

Everything that describes what is computed goes into the digest solprop.output.schema.RunMetadata.configuration_hash() takes – the grid, the modes, the configuration, the noise and the stepper settings, plus the save planes and the statistics, which are read off the contract here – and nothing that describes when or with which build, so a resume survives an unrelated commit or a NumPy upgrade.

Parameters:
problemsolprop.translate.problem.KernelProblem

The translated problem the run will step.

gridsolprop.grid.TimeGrid

The grid the state lives on.

modescollections.abc.Sequence, optional

The propagated modes, in state order.

configurationcollections.abc.Mapping, optional

The physics objects that built the run – responses, the input, profiles, boundaries – recorded by solprop.output.schema.serialise(). Nothing is dropped: a callable is recorded as its repr and marked unreproducible, which also makes the digest unstable across processes, so prefer objects that carry their data (docs/guide/setup/running.md).

noisesolprop.noise.NoiseRealisation or None, optional

The realisation the run carries, recorded with its seed.

modalcollections.abc.Mapping or None, optional

The general modal identity of output schema 7, as solprop.translate.general.modal_identity() writes it: the channel labels, the table, metric, response and guide identities, the frame, the active band and the accessors the basis admits. None for every other route. It is part of the schema-7 resume key.

materialssolprop.physdata.selection.MaterialManifest or None, optional

The run’s material manifest of output schema 8 (solprop.driver.material_output.material_manifest()); None is the empty manifest of a run of solprop’s own materials. Its identities and policies are part of the schema-8 resume key.

quadraturesolprop.modes.quadrature.TransverseQuadrature or None, optional

The transverse rule of a resolved modal run, recorded with its nodes and physical weights on the first mode’s cross-section and part of the schema-17 resume key (SEP 19). None for every other route.

framesolprop.linear.Frame or None, optional

The run’s frame, whose reference frequency is the origin of the linear frame term on an envelope grid; None is the grid’s co-moving frame. It enters the schema-24 plane-reference record, not the hash.

noise_resolutionsolprop.output.schema.NoiseResolution or None, optional

How the noise model was chosen (output schema 26, SEP 37). Outside the hash.

Returns:
solprop.output.schema.RunMetadata

The record, ready for solprop.output.schema.Output.open().

Examples

>>> from solprop.driver.simulation import metadata_for
>>> from solprop.grid import EnvelopeGrid
>>> from solprop.nonlinear.gnlse import problem_from
>>> from solprop.pulses import SechPulse
>>> from solprop.stepper import PIController
>>> from solprop.translate.problem import assemble
>>> grid = EnvelopeGrid.from_limits(0.01, 835e-9, (500e-9, 2e-6), 1e-12)
>>> gnlse = problem_from([0.0, 0.0, -1.2e-26], omega_ref=grid.omega0, gamma=0.11)
>>> start = SechPulse(wavelength=835e-9, width=1e-13, peak_power=1.0).build(grid)
>>> problem = assemble(grid, gnlse.mode, [gnlse.kerr], start,
...                    controller=PIController(rtol=1e-8, atol=1e-14),
...                    save_planes=[0.01], dz_max=0.01, dz_init=1e-3,
...                    density=1.0, shock=False, prefactor_index=1.0)
>>> metadata = metadata_for(problem, grid, modes=[gnlse.mode])
>>> metadata.simulation_kind, len(metadata.configuration_hash())
('mode_averaged', 64)