solprop.tools#

Design calculators: soliton numbers and dispersive-wave phase matching.

The numbers a person works out before a run. For a pulse of energy \(E\) and full width at half maximum \(\tau_{\rm fwhm}\) in a mode with group-velocity dispersion \(\beta_2\), effective area \(A_{\rm eff}\) and a fill of nonlinear index \(n_2\),

\[\gamma = \frac{n_2\omega_0}{cA_{\rm eff}},\quad L_D = \frac{\tau_0^2}{|\beta_2|},\quad L_{NL} = \frac{1}{\gamma P_0},\quad N = \sqrt{L_D/L_{NL}},\quad L_{\rm fiss} = L_D/N,\]

with the natural width \(\tau_0\) and the peak power \(P_0\) of the chosen pulse shape (pulse_width(), pulse_peak_power()). One shape runs through the whole chain, so the Gaussian numbers are never computed with a sech width.

A dispersive wave is phase matched to a soliton at the frequencies where

\[\Delta\beta(\omega) = \beta_{\rm dw}(\omega) - \beta_{\rm s}(\omega_0) - \beta_{1,\rm s}(\omega_0)(\omega-\omega_0) - k_{\rm NL}\]

vanishes (phase_mismatch()). The last term is the soliton’s nonlinear wavenumber and uses the largest unchirped constituent when pulse data are given (soliton_content()). Without pulse data the condition is linear. docs/guide/workflows/design-tools.md derives both and says what the nonlinear term assumes.

Everything is SI except pressure, which is in bar as at the rest of the user interface (docs/dev/conventions.md section 1).

Module Attributes

PulseShape

The two pulse shapes the design numbers are defined for.

NonlinearPhase

Choose the constituent, supplied-power or linear RDW phase model.

Fill

A fill as the run interfaces accept it: a species, mole fractions or a mixture.

DesignTarget

A target of solve_parameter().

RootChoice

Which of several roots: the lowest, the highest, or an index into them.

DesignBuild

A builder: a trial value of the parameter to a mode, or to a mode and the fill's nonlinear coefficient in rad/(W m) (nonlinear_coefficient()).

Functions

capillary_design(radius, gas, *, ...[, ...])

Return the pressure and energy that give a capillary a soliton design.

capillary_params(radius, gas[, pressure, ...])

Return the design numbers of a pulse in a gas-filled capillary.

dispersion_length(fwhm, beta2[, shape])

Return the dispersion length \(L_D = \tau_0^2/|\beta_2|\).

field_to_intensity(field)

Return the intensity of a field amplitude, \(I = \epsilon_0 c E^2/2\).

fission_length(peak_power, fwhm, gamma, beta2)

Return the soliton fission length \(L_{\rm fiss} = L_D/N\).

gas_ratio(gas_a, gas_b, wavelength, *[, ...])

Return the ratios of bulk dispersion and Kerr response of two gases.

intensity_to_field(intensity)

Return the field amplitude of an intensity, \(E = \sqrt{2I/\epsilon_0 c}\).

lambda_rdw(mode, wavelength, *[, ...])

Return the phase-matched dispersive-wave wavelength nearest the pump.

lambda_rdw_all(mode, wavelength, *[, ...])

Return every phase-matched wavelength in a window, shortest first.

nonlinear_coefficient(mode, n2, wavelength)

Return the nonlinear coefficient \(\gamma = n_2\omega/(cA_{\rm eff})\).

nonlinear_length(peak_power, gamma)

Return the nonlinear length \(L_{NL} = 1/(\gamma P_0)\).

phase_mismatch(mode, omega, wavelength, *[, ...])

Return the phase mismatch between a soliton and a dispersive wave.

pressure_rdw(radius, gas, target_wavelength, ...)

Return the pressure that phase matches a dispersive wave at a target wavelength.

pressure_zdw(radius, gas, zdw_wavelength, *)

Return the pressure that puts the zero-dispersion point at a wavelength.

pulse_energy(peak_power, fwhm[, shape])

Return the energy of a pulse of given peak power, duration and shape.

pulse_peak_power(energy, fwhm[, shape])

Return the peak power of a pulse of given energy, duration and shape.

pulse_width(fwhm[, shape])

Return the natural width of a pulse from its full width at half maximum.

radius_zdw(gas, pressure, zdw_wavelength, *)

Return the core radius that puts a capillary's zero dispersion at a wavelength.

self_focusing_power(wavelength, index, n2)

Return the critical power for self-focusing, as physical power.

soliton_content(peak_power, fwhm, gamma, beta2)

Calculate the soliton count and largest constituent of an unchirped pulse.

soliton_order(peak_power, fwhm, gamma, beta2)

Return the soliton order \(N = \sqrt{L_D/L_{NL}}\).

soliton_params(mode, gas[, pressure, shape, ...])

Return the design numbers of a pulse in any mode.

soliton_peak_power(order, fwhm, gamma, beta2)

Return the peak power that gives a soliton order.

solve_parameter(build, search, target, *[, z])

Return every value of a guide or fill parameter that meets a design target.

Classes

DesignRoots(roots, search, target, builds, ...)

Every root of a design target over a parameter's search range.

GasRatio(beta2, chi3)

Ratios of the bulk dispersion and the Kerr response of two gases.

RDW(pump, rdw[, peak_power, fwhm, shape, ...])

Target a resonant dispersive wave phase matched at a wavelength.

SolitonContent(area_order, count, ...)

Describe the discrete soliton content of an unchirped single-lobe pulse.

SolitonOrder(order, pulse)

Target a conventional soliton order for a fixed pulse.

SolitonParams(energy, fwhm, width, omega, ...)

The design numbers of one pulse in one mode and one fill.

ZDW(wavelength)

Target a zero-dispersion wavelength: \(\beta_2 = 0\) at a wavelength.

solprop.tools.DesignBuild#

A builder: a trial value of the parameter to a mode, or to a mode and the fill’s nonlinear coefficient in rad/(W m) (nonlinear_coefficient()).

alias of Callable[[float], Mode | tuple[Mode, float]]

class solprop.tools.DesignRoots(roots, search, target, builds, quantity, attainable=None)[source]#

Bases: object

Every root of a design target over a parameter’s search range.

Iterating gives the roots, and its length is their number.

Attributes:
rootstuple of float

The values of the parameter that meet the target, ascending, in the parameter’s unit; empty when none does.

searchtuple of float

The search range, (low, high).

targetZDW, RDW or SolitonOrder

The target.

buildsint

How many times the builder was called, the search’s cost.

quantitystr

What attainable measures, with its unit: the zero-dispersion wavelength nearest the target’s (m), the phase-matched wavelength nearest the target’s (m), or the soliton order.

attainabletuple of float or None

When there is no root, the smallest and largest quantity on a coarser grid of the search range (17 linear and, where low > 0, 17 logarithmic values, the ends included), where it is defined: a mode with no zero dispersion in 100 nm to 3 um, or with no phase-matched wavelength in the RDW window or no soliton, has none. None when there are roots, or no value defines it.

Examples

>>> from solprop.tools import DesignRoots, ZDW
>>> roots = DesignRoots((1.0, 2.0), (0.5, 3.0), ZDW(5e-7), 260,
...                     "zero-dispersion wavelength in m")
>>> len(roots), roots.pick("highest"), roots.pick(0)
(2, 2.0, 1.0)
attainable: tuple[float, float] | None = None#
builds: int#
pick(root='lowest')[source]#

Return one root.

Parameters:
root{‘lowest’, ‘highest’} or int, optional

The lowest or highest root, or an index into the ascending roots (negative from the end, as a sequence’s).

Returns:
float

The root, in the parameter’s unit.

Raises:
ToolsError

If there is no root, naming the attainable range, or the index is out of range, naming the roots.

Examples

>>> from solprop.tools import DesignRoots, ZDW
>>> DesignRoots((1.0, 2.0), (0.5, 3.0), ZDW(5e-7), 260, "").pick(-1)
2.0
quantity: str#
roots: tuple[float, ...]#
search: tuple[float, float]#
target: ZDW | RDW | SolitonOrder#
solprop.tools.DesignTarget = solprop.tools.ZDW | solprop.tools.RDW | solprop.tools.SolitonOrder#

A target of solve_parameter().

solprop.tools.Fill = solprop.physdata.gases.Gas | str | collections.abc.Mapping[str, float] | solprop.physdata.mixtures.Mixture#

A fill as the run interfaces accept it: a species, mole fractions or a mixture.

class solprop.tools.GasRatio(beta2, chi3)[source]#

Bases: object

Ratios of the bulk dispersion and the Kerr response of two gases.

Attributes:
beta2float

Ratio of the bulk group-velocity dispersions, first gas over second.

chi3float

Ratio of the third-order susceptibilities, first gas over second.

beta2: float#
chi3: float#
solprop.tools.NonlinearPhase#

Choose the constituent, supplied-power or linear RDW phase model.

alias of Literal[‘largest’, ‘supplied_power’, ‘linear’]

solprop.tools.PulseShape#

The two pulse shapes the design numbers are defined for.

alias of Literal[‘sech’, ‘gauss’]

class solprop.tools.RDW(pump, rdw, peak_power=None, fwhm=None, shape='sech', nonlinear_phase='largest')[source]#

Bases: object

Target a resonant dispersive wave phase matched at a wavelength.

The residual solve_parameter() brackets is phase_mismatch() of the trial mode at rdw, in 1/m, exactly as pressure_rdw() evaluates it: with peak_power the soliton’s nonlinear wavenumber is included, with the trial mode’s own nonlinear coefficient, and with the largest constituent (fwhm given) a trial value in normal dispersion or below the first soliton threshold has no residual and cannot bracket a root.

Attributes:
pumpfloat

Wavelength of the soliton, m, > 0.

rdwfloat

Wavelength the dispersive wave should have, m, > 0 and not the pump’s.

peak_powerfloat or None

Input peak power in W for the nonlinear term; None is the linear condition. With it, the builder returns (mode, gamma).

fwhmfloat or None

Input power FWHM in s; required with peak_power for the default phase.

shape{‘sech’, ‘gauss’}

Unchirped input shape for the largest constituent.

nonlinear_phase{‘largest’, ‘supplied_power’, ‘linear’}

The nonlinear phase model, as phase_mismatch() takes it.

Raises:
ToolsError

If a wavelength is not positive, the two are equal, or the pulse numbers are incomplete or contradictory for the phase model.

Examples

>>> from solprop.tools import RDW
>>> RDW(800e-9, 200e-9, peak_power=2e9, fwhm=10e-15).nonlinear_phase
'largest'
fwhm: float | None = None#
nonlinear_phase: Literal['largest', 'supplied_power', 'linear'] = 'largest'#
peak_power: float | None = None#
pump: float#
rdw: float#
shape: Literal['sech', 'gauss'] = 'sech'#
solprop.tools.RootChoice = typing.Literal['lowest', 'highest'] | int#

Which of several roots: the lowest, the highest, or an index into them.

class solprop.tools.SolitonContent(area_order, count, largest_eigenvalue, largest_peak_power, largest_width, largest_nonlinear_wavenumber)[source]#

Bases: object

Describe the discrete soliton content of an unchirped single-lobe pulse.

Attributes:
area_orderfloat

Dimensionless field area divided by pi, not the conventional soliton order.

countint

Number of strictly positive discrete eigenvalues; zero at first threshold.

largest_eigenvaluefloat or None

Imaginary part of the largest Zakharov-Shabat eigenvalue, dimensionless with time scaled by the input shape’s natural width. None if count is zero.

largest_peak_powerfloat or None

Peak power of the largest constituent in W, or None if count is zero.

largest_widthfloat or None

Natural sech width of that constituent in s, or None if count is zero.

largest_nonlinear_wavenumberfloat or None

Positive optics-convention phase rate in 1/m, or None if count is zero.

area_order: float#
count: int#
largest_eigenvalue: float | None#
largest_nonlinear_wavenumber: float | None#
largest_peak_power: float | None#
largest_width: float | None#
class solprop.tools.SolitonOrder(order, pulse)[source]#

Bases: object

Target a conventional soliton order for a fixed pulse.

The residual solve_parameter() brackets is soliton_order() of the pulse in the trial mode, with the trial mode’s own nonlinear coefficient, minus order: a guide or fill parameter is solved for, the pulse is held. The order is the conventional measure on either side of a zero-dispersion point, so a search across one may find a root on each side. The opposite question, the pulse that has an order on a given mode, is closed form: soliton_peak_power() and pulse_energy().

Attributes:
orderfloat

Conventional soliton order, > 0.

pulseGaussianPulse or SechPulse

The pulse: its wavelength is the pump, its FWHM and its energy or peak power are held, and its class sets the shape. An ordinary Gaussian (m = 1) with no spectral phase beyond a carrier-envelope phase and a delay.

Raises:
ToolsError

If the order is not positive, the Gaussian is super-Gaussian, or the pulse is chirped.

Examples

>>> from solprop.pulses import SechPulse
>>> from solprop.tools import SolitonOrder
>>> target = SolitonOrder(3.0, SechPulse(wavelength=800e-9, fwhm=10e-15,
...                                      energy=100e-6))
>>> f"{target.peak_power / 1e9:.3f} GW"
'8.814 GW'
property fwhm: float[source]#

Return the pulse’s full width at half maximum of the power.

Returns:
float

FWHM in s; a SechPulse given its natural width converts it.

order: float#
property peak_power: float[source]#

Return the pulse’s peak power.

Returns:
float

Peak power in W: the pulse’s own, or that of its energy (pulse_peak_power()).

pulse: GaussianPulse | SechPulse#
property shape: Literal['sech', 'gauss'][source]#

Return the pulse shape the design numbers use.

Returns:
{‘sech’, ‘gauss’}

"gauss" for a GaussianPulse, "sech" for a SechPulse.

class solprop.tools.SolitonParams(energy, fwhm, width, omega, wavelength, gas, pressure, temperature, shape, peak_power, beta2, density, index, n2, gamma, soliton_order, soliton_content, intensity, peak_intensity, critical_power, dispersion_length, nonlinear_length, fission_length, zdw, loss_length, effective_area, mode)[source]#

Bases: Displayed

The design numbers of one pulse in one mode and one fill.

Attributes:
energyfloat

Pulse energy in J.

fwhmfloat

Full width at half maximum of the power in s.

widthfloat

Natural width tau0 of the shape in s (pulse_width()).

omegafloat

Angular frequency of the pump in rad/s.

wavelengthfloat

Vacuum wavelength of the pump in m.

gasstr

The fill’s species labels, joined by +.

pressurefloat

Total pressure at the position in bar; NaN for a mixture of independent populations, which has no single pressure.

temperaturefloat

Fill temperature in K.

shape{‘sech’, ‘gauss’}

"sech" or "gauss".

peak_powerfloat

Peak power in W.

beta2float

Group-velocity dispersion of the mode at the pump in s^2/m.

densityfloat

Total number density of the fill in m^-3.

indexfloat

Linear refractive index of the fill at the pump.

n2float

Nonlinear index of the fill in m^2/W.

gammafloat

Nonlinear coefficient in rad/(W m).

soliton_orderfloat

sqrt(L_D / L_NL).

soliton_contentSolitonContent or None

Unchirped NLSE constituent count and largest soliton; None for normal GVD.

intensityfloat

Mode-averaged intensity peak_power / effective_area in W/m^2.

peak_intensityfloat

On-axis intensity of the mode at the peak power in W/m^2: what a run’s peak_intensity statistic reports at its first plane. For the fundamental of a capillary it is 1.77 times intensity. NaN for a mode without a transverse profile (a dispersion-specified one).

critical_powerfloat

Self-focusing power in W (self_focusing_power()).

dispersion_lengthfloat

In m.

nonlinear_lengthfloat

In m.

fission_lengthfloat

In m.

zdwfloat

Zero-dispersion wavelength in m within 100 nm to 3 um, or NaN when the dispersion does not change sign there. No second, guess-seeded search is tried.

loss_lengthfloat

The 1/e power loss length of the mode at the pump in m.

effective_areafloat

In m^2.

modeMode

The mode.

beta2: float#
critical_power: float#
density: float#
dispersion_length: float#
effective_area: float#
energy: float#
fission_length: float#
fwhm: float#
gamma: float#
gas: str#
index: float#
intensity: float#
loss_length: float#
mode: Mode#
n2: float#
nonlinear_length: float#
omega: float#
peak_intensity: float#
peak_power: float#
pressure: float#
shape: Literal['sech', 'gauss']#
soliton_content: SolitonContent | None#
soliton_order: float#
temperature: float#
wavelength: float#
width: float#
zdw: float#
class solprop.tools.ZDW(wavelength)[source]#

Bases: object

Target a zero-dispersion wavelength: \(\beta_2 = 0\) at a wavelength.

The residual solve_parameter() brackets is \(\beta_2\) of the trial mode at wavelength, in s^2/m.

Attributes:
wavelengthfloat

Wavelength at which the dispersion should vanish, m, > 0.

Raises:
ToolsError

If the wavelength is not finite and positive.

Examples

>>> from solprop.tools import ZDW
>>> ZDW(500e-9)
ZDW(wavelength=5e-07)
wavelength: float#
solprop.tools.capillary_design(radius, gas, *, zdw_wavelength, fwhm, wavelength, soliton_order=None, soliton_count=None, largest_eigenvalue=None, shape='sech', temperature=293.15, m=1, model='full', loss=True, cladding=None, materials=None, pressure_max=100.0)[source]#

Return the pressure and energy that give a capillary a soliton design.

The inverse of capillary_params(): the pressure puts the zero-dispersion point at zdw_wavelength (pressure_zdw()), and the energy then gives the pulse one soliton target. At that pressure \(\beta_2\) and \(\gamma\) do not depend on the energy and \(N^2 = \gamma P_0\tau_0^2/|\beta_2|\), so the peak power is \(P_0 = N^2|\beta_2|/(\gamma\tau_0^2)\). Give exactly one target:

  • soliton_order, the conventional \(N\);

  • soliton_count, a number \(M\) of solitons in the scattering content (soliton_content()): the pulse area is set to \(M\pi\), the middle of the band of areas with \(M\) solitons, which is \(N = M\) for sech and \(N = M\sqrt{\pi/2}\) for a Gaussian;

  • largest_eigenvalue, the \(\eta\) of the largest constituent, which fixes its width \(\tau_0/(2\eta)\): \(N = \eta + 1/2\) for sech, and a root of the Gaussian scattering problem otherwise.

Parameters:
radiusfloat

Core radius in m, > 0.

gasGas or str

A single built-in gas, as pressure_zdw() takes it.

zdw_wavelengthfloat

Wavelength at which the dispersion should vanish, m.

fwhmfloat

Full width at half maximum of the power in s, > 0.

wavelengthfloat

Pump wavelength in m, > 0.

soliton_orderfloat or None, optional

Target conventional soliton order, > 0.

soliton_countint or None, optional

Target number of solitons, >= 1.

largest_eigenvaluefloat or None, optional

Target imaginary part of the largest Zakharov-Shabat eigenvalue, dimensionless with time in units of the shape’s natural width, > 0.

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

The pulse shape, used for the width, the peak power and the content.

temperaturefloat, optional

Fill temperature in K.

mint, optional

Radial index of the HE_1m mode.

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

Marcatili model.

lossbool, float or callable, optional

Loss policy of the mode in the returned numbers.

claddingGlassIndex, complex or None, optional

Cladding index; None is fused silica.

materialsMaterialSelection or None, optional

Design under this selection, as capillary_params() and pressure_zdw() do. None is MaterialSelection().

pressure_maxfloat, optional

Upper end of the pressure bracket in bar.

Returns:
SolitonParams

The numbers at the designed pressure and energy, with the mode; the pressure is .pressure (bar) and the energy .energy (J).

Raises:
ToolsError

If not exactly one target is given or it is out of range, no pressure in the bracket gives the zero-dispersion point, or a content target is asked of a pump in normal dispersion.

Examples

>>> from solprop.tools import capillary_design
>>> p = capillary_design(125e-6, "Ar", zdw_wavelength=500e-9, fwhm=10e-15,
...                      wavelength=800e-9, soliton_order=3.0, cladding=1.45)
>>> f"{p.pressure:.4f} bar {p.energy * 1e6:.1f} uJ N = {p.soliton_order:.3f}"
'0.0664 bar 100.5 uJ N = 3.000'
>>> g = capillary_design(125e-6, "Ar", zdw_wavelength=500e-9, fwhm=10e-15,
...                      wavelength=800e-9, soliton_count=2, shape="gauss",
...                      cladding=1.45)
>>> f"{g.soliton_order:.4f} {g.soliton_content.count}"
'2.5066 2'
solprop.tools.capillary_params(radius, gas, pressure=None, *, energy, fwhm, wavelength, shape='sech', temperature=None, n=1, m=1, kind='HE', model='full', loss=True, cladding=None, materials=None)[source]#

Return the design numbers of a pulse in a gas-filled capillary.

Builds the mode as solprop.driver.interface.prop_capillary() does for the same arguments – a MarcatiliMode over the fill’s mixture – and hands it to soliton_params().

Parameters:
radiusfloat

Core radius in m, > 0.

gasGas, str, Mapping or Mixture

The fill, as prop_capillary takes it.

pressurefloat or None, optional

Total pressure in bar; None is one bar. For a gradient, evaluate at the pressure of the position of interest.

energyfloat

Pulse energy in J, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

wavelengthfloat

Pump wavelength in m, > 0.

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

The pulse shape.

temperaturefloat or None, optional

Fill temperature in K; None is room temperature, or the mixture’s own beside a Mixture, which refuses any other.

nint, optional

Azimuthal mode index.

mint, optional

Radial mode index, >= 1.

kind{‘HE’, ‘TE’, ‘TM’}, optional

Mode family.

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

Marcatili model.

lossbool, float or callable, optional

Loss policy of the mode.

claddingGlassIndex, complex or None, optional

Cladding index; None is fused silica.

materialsMaterialSelection or None, optional

Build the capillary as prop_capillary does under the same materials=: the fill from optmat (index, density and Kerr coefficient at wavelength) and cladding=None as optmat’s recommended fused silica. None is MaterialSelection().

Returns:
SolitonParams

The numbers, with the mode that was built.

Examples

>>> from solprop.tools import capillary_params
>>> p = capillary_params(125e-6, "He", 0.4, energy=300e-6, fwhm=10e-15,
...                      wavelength=800e-9, model="reduced", cladding=1.45)
>>> f"{p.gamma:.3e} {p.intensity:.3e}"
'4.884e-11 1.130e+18'
solprop.tools.dispersion_length(fwhm, beta2, shape='sech')[source]#

Return the dispersion length \(L_D = \tau_0^2/|\beta_2|\).

Parameters:
fwhmfloat

Full width at half maximum of the power in s, > 0.

beta2float

Group-velocity dispersion in s^2/m, non-zero.

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

The pulse shape; see pulse_width().

Returns:
float

Dispersion length in m.

Raises:
ToolsError

If the dispersion is zero or not finite, or the width is not positive.

Examples

>>> from solprop.tools import dispersion_length
>>> f"{dispersion_length(10e-15, -8e-30):.3f}"
'4.023'
solprop.tools.field_to_intensity(field)[source]#

Return the intensity of a field amplitude, \(I = \epsilon_0 c E^2/2\).

Parameters:
fieldfloat

Field amplitude in V/m.

Returns:
float

Intensity in W/m^2.

Examples

>>> from solprop.tools import field_to_intensity
>>> f"{field_to_intensity(1e10):.4e}"
'1.3272e+17'
solprop.tools.fission_length(peak_power, fwhm, gamma, beta2, shape='sech')[source]#

Return the soliton fission length \(L_{\rm fiss} = L_D/N\).

Parameters:
peak_powerfloat

Peak power in W, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

gammafloat

Nonlinear coefficient in rad/(W m), > 0.

beta2float

Group-velocity dispersion in s^2/m, non-zero.

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

The pulse shape; see pulse_width().

Returns:
float

Fission length in m, the geometric mean of the two lengths.

Examples

>>> from solprop.tools import fission_length
>>> f"{fission_length(1e9, 10e-15, 1e-9, -8e-30):.4f}"
'2.0057'
solprop.tools.gas_ratio(gas_a, gas_b, wavelength, *, pressure=1.0, temperature=293.15, materials=None)[source]#

Return the ratios of bulk dispersion and Kerr response of two gases.

The bulk (unguided) dispersion of each gas, not a mode’s: it answers “how much more pressure of B matches A”, which is a property of the gases alone.

Parameters:
gas_aGas or str

The numerator’s species.

gas_bGas or str

The denominator’s species.

wavelengthfloat

Wavelength in m at which the dispersions are compared, > 0.

pressurefloat, optional

Pressure of both gases in bar, > 0.

temperaturefloat, optional

Temperature of both in K.

materialsMaterialSelection or None, optional

Take both gases from optmat under this selection, as a run’s materials= does: their index, their density and their Kerr coefficient at wavelength; "air" is nitrogen and oxygen. None is MaterialSelection().

Returns:
GasRatio

Named beta2 and chi3 ratios.

Raises:
ToolsError

If the selection names a carrier other than wavelength, or a gas has no Kerr data under it.

Examples

>>> from solprop.tools import gas_ratio
>>> ratio = gas_ratio("Ar", "He", 800e-9)
>>> f"{ratio.beta2:.1f} {ratio.chi3:.1f}"
'18.6 28.4'
solprop.tools.intensity_to_field(intensity)[source]#

Return the field amplitude of an intensity, \(E = \sqrt{2I/\epsilon_0 c}\).

Parameters:
intensityfloat

Intensity in W/m^2, >= 0.

Returns:
float

Field amplitude in V/m.

Raises:
ToolsError

If the intensity is negative.

Examples

>>> from solprop.tools import field_to_intensity, intensity_to_field
>>> f"{intensity_to_field(field_to_intensity(1e10)):.6e}"
'1.000000e+10'
solprop.tools.lambda_rdw(mode, wavelength, *, soliton_mode=None, z=0.0, peak_power=None, gamma=None, fwhm=None, shape='sech', nonlinear_phase='largest', wavelength_limits=None)[source]#

Return the phase-matched dispersive-wave wavelength nearest the pump.

Parameters:
modeMode

The mode the dispersive wave is emitted into.

wavelengthfloat

Wavelength of the soliton in m, > 0.

soliton_modeMode or None, optional

The soliton’s mode; None is mode.

zfloat, optional

Position along the waveguide, m.

peak_powerfloat or None, optional

Peak power in W for the nonlinear term; see phase_mismatch().

gammafloat or None, optional

Nonlinear coefficient in rad/(W m) for the nonlinear term.

fwhmfloat or None, optional

Input power FWHM in s, positive; required with power for the default phase.

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

Unchirped input shape for the largest constituent.

nonlinear_phase{‘largest’, ‘supplied_power’, ‘linear’}, optional

Default uses the largest constituent. Supplied power uses gamma P0/2 and requires omitting fwhm. Linear requires omitting all pulse numbers. Without pulse numbers the default is also linear.

wavelength_limitstuple of float or None, optional

Window searched, m; None is 100 nm to 0.9 of the pump wavelength.

Returns:
float

The longest root inside the window in m, which with the default window is the short-wavelength dispersive wave nearest the pump. lambda_rdw_all() returns all of them.

Raises:
ToolsError

If the window holds no root, rather than returning a missing value that would propagate silently.

Examples

>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import lambda_rdw
>>> mode = MarcatiliMode(125e-6, "He", 1.0, cladding=1.45)
>>> f"{lambda_rdw(mode, 800e-9) * 1e9:.1f}"
'200.1'
solprop.tools.lambda_rdw_all(mode, wavelength, *, soliton_mode=None, z=0.0, peak_power=None, gamma=None, fwhm=None, shape='sech', nonlinear_phase='largest', wavelength_limits=None)[source]#

Return every phase-matched wavelength in a window, shortest first.

Parameters:
modeMode

The mode the dispersive wave is emitted into.

wavelengthfloat

Wavelength of the soliton in m, > 0.

soliton_modeMode or None, optional

The soliton’s mode; None is mode.

zfloat, optional

Position along the waveguide, m.

peak_powerfloat or None, optional

Peak power in W for the nonlinear term; see phase_mismatch().

gammafloat or None, optional

Nonlinear coefficient in rad/(W m) for the nonlinear term.

fwhmfloat or None, optional

Input power FWHM in s, positive; required with power for the default phase.

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

Unchirped input shape for the largest constituent.

nonlinear_phase{‘largest’, ‘supplied_power’, ‘linear’}, optional

Default uses the largest constituent. Supplied power uses gamma P0/2 and requires omitting fwhm. Linear requires omitting all pulse numbers. Without pulse numbers the default is also linear.

wavelength_limitstuple of float or None, optional

Shortest and longest wavelength searched, m. None is 100 nm to 0.9 of the pump wavelength, which keeps the double root at the pump out.

Returns:
tuple of float

The roots in m, ascending; empty when there is none. The mismatch is sampled on 2048 frequencies across the window, each sign change is refined with Brent’s method, and roots closer than one sample are not separated.

Raises:
ToolsError

If the window is not positive and ordered.

Examples

>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import lambda_rdw_all
>>> mode = MarcatiliMode(125e-6, "He", 1.0, cladding=1.45)
>>> [f"{root * 1e9:.0f}" for root in lambda_rdw_all(mode, 800e-9)]
['200']
solprop.tools.nonlinear_coefficient(mode, n2, wavelength, z=0.0)[source]#

Return the nonlinear coefficient \(\gamma = n_2\omega/(cA_{\rm eff})\).

Parameters:
modeMode

The mode, for its effective area.

n2float

Nonlinear index of the fill in m^2/W, >= 0.

wavelengthfloat

Vacuum wavelength in m, > 0.

zfloat, optional

Position along the waveguide, m.

Returns:
float

Nonlinear coefficient in rad/(W m).

Raises:
ToolsError

If the nonlinear index is negative or not finite.

Examples

>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import nonlinear_coefficient
>>> mode = MarcatiliMode(125e-6, "He", 1.0)
>>> f"{nonlinear_coefficient(mode, 3.55e-25, 800e-9):.4e}"
'1.1919e-10'
solprop.tools.nonlinear_length(peak_power, gamma)[source]#

Return the nonlinear length \(L_{NL} = 1/(\gamma P_0)\).

Parameters:
peak_powerfloat

Peak power in W, > 0.

gammafloat

Nonlinear coefficient in rad/(W m), > 0.

Returns:
float

Nonlinear length in m.

Raises:
ToolsError

If either quantity is not positive.

Examples

>>> from solprop.tools import nonlinear_length
>>> nonlinear_length(1e9, 1e-9)
1.0
solprop.tools.phase_mismatch(mode, omega, wavelength, *, soliton_mode=None, z=0.0, peak_power=None, gamma=None, fwhm=None, shape='sech', nonlinear_phase='largest')[source]#

Return the phase mismatch between a soliton and a dispersive wave.

\[\Delta\beta(\omega) = \beta_{\rm dw}(\omega) - \beta_{\rm s}(\omega_0) - \beta_{1,\rm s}(\omega_0)(\omega-\omega_0) - k_{\rm NL} .\]
Parameters:
modeMode

The mode the dispersive wave is emitted into.

omeganumpy.ndarray

Angular frequencies in rad/s, shape (n_omega,).

wavelengthfloat

Wavelength of the soliton in m, > 0.

soliton_modeMode or None, optional

The mode the soliton travels in; None is mode. A different one gives intermodal phase matching.

zfloat, optional

Position along the waveguide, m.

peak_powerfloat or None, optional

Input peak power in W. With gamma and fwhm, adds the soliton’s nonlinear wavenumber; both None (the default) gives the linear condition.

gammafloat or None, optional

Nonlinear coefficient of the soliton’s mode in rad/(W m) (nonlinear_coefficient()).

fwhmfloat or None, optional

Input power FWHM in s, positive; required with power for the default phase.

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

Unchirped input shape for the largest constituent.

nonlinear_phase{‘largest’, ‘supplied_power’, ‘linear’}, optional

Default uses the largest constituent. Supplied power uses gamma P0/2 and requires omitting fwhm. Linear requires omitting all pulse numbers. Without pulse numbers the default is also linear.

Returns:
numpy.ndarray

Mismatch in 1/m, shape (n_omega,). It vanishes at the pump in the linear case, with zero slope there.

Raises:
ToolsError

If pulse arguments are incomplete or contradictory, or the largest constituent does not exist in anomalous dispersion.

Notes

The default nonlinear term is gamma times the largest constituent’s power / 2 (soliton_content()). The supplied-power option treats the quoted power as a fundamental soliton, advancing as exp(i gamma P0 z / 2) (Akhmediev and Karlsson, Phys. Rev. A 51, 2602 (1995)). Both are local estimates; loss, higher-order dispersion, Raman, chirp and plasma evolution are not included.

Examples

>>> import numpy as np
>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import phase_mismatch
>>> mode = MarcatiliMode(125e-6, "He", 1.0)
>>> pump = 2 * np.pi * 299792458.0 / 800e-9
>>> abs(float(phase_mismatch(mode, np.array([pump]), 800e-9)[0])) < 1e-6
True
solprop.tools.pressure_rdw(radius, gas, target_wavelength, wavelength, *, pressure_max=100.0, peak_power=None, fwhm=None, shape='sech', nonlinear_phase='largest', lattice=None, pressure_limits=None, temperature=293.15, m=1, model='full', cladding=None, materials=None)[source]#

Return the pressure that phase matches a dispersive wave at a target wavelength.

Parameters:
radiusfloat

Core radius in m, > 0.

gasGas or str

A single built-in gas.

target_wavelengthfloat

Wavelength the dispersive wave should have, m.

wavelengthfloat

Pump wavelength in m.

pressure_maxfloat, optional

Upper end of the pressure bracket in bar; the lower end is 1e-6 bar.

peak_powerfloat or None, optional

Peak power in W. When given, the soliton’s nonlinear wavenumber is included and its nonlinear coefficient follows the pressure.

fwhmfloat or None, optional

Positive input power FWHM in s, required with power for the default phase.

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

Unchirped input shape.

nonlinear_phase{‘largest’, ‘supplied_power’, ‘linear’}, optional

Largest constituent by default; supplied power preserves gamma P0/2 without fwhm. Linear requires omitting pulse numbers.

latticeTubeLattice or None, optional

Tube geometry for VincettiMode; None builds a Marcatili capillary.

pressure_limitstuple of float or None, optional

Positive ordered search range in bar, within (1e-6, pressure_max). None uses that whole range. Searches 129 logarithmic and 129 linear samples, refining admissible sign changes; sub-grid root pairs or valid intervals can be missed. Narrow the range to resolve them.

temperaturefloat, optional

Fill temperature in K.

mint, optional

Radial index of the HE_1m mode.

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

Marcatili model.

claddingGlassIndex, complex or None, optional

Cladding index; None is fused silica.

materialsMaterialSelection or None, optional

Design the capillary prop_capillary builds under the same materials=: the gas from optmat (index, density, and the Kerr coefficient at wavelength for the nonlinear phase) and cladding=None as optmat’s recommended fused silica. None is MaterialSelection().

Returns:
float

Pressure in bar.

Raises:
ToolsError

If no pressure in the bracket matches, or the selection names a carrier other than wavelength.

Examples

>>> from solprop.tools import pressure_rdw
>>> f"{pressure_rdw(125e-6, 'He', 199.75e-9, 800e-9, cladding=1.45):.2f}"
'1.00'
solprop.tools.pressure_zdw(radius, gas, zdw_wavelength, *, pressure_max=100.0, temperature=293.15, m=1, model='full', cladding=None, materials=None)[source]#

Return the pressure that puts the zero-dispersion point at a wavelength.

Parameters:
radiusfloat

Core radius in m, > 0.

gasGas or str

A single built-in gas.

zdw_wavelengthfloat

Wavelength at which the dispersion should vanish, m.

pressure_maxfloat, optional

Upper end of the pressure bracket in bar; the lower end is 1e-6 bar.

temperaturefloat, optional

Fill temperature in K.

mint, optional

Radial index of the HE_1m mode.

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

Marcatili model.

claddingGlassIndex, complex or None, optional

Cladding index; None is fused silica.

materialsMaterialSelection or None, optional

Design the capillary prop_capillary builds under the same materials=: the gas’s index and density from optmat and cladding=None as optmat’s recommended fused silica. None is MaterialSelection().

Returns:
float

Pressure in bar.

Raises:
ToolsError

If no pressure in the bracket does.

Examples

>>> from solprop.tools import pressure_zdw
>>> f"{pressure_zdw(125e-6, 'Ar', 500e-9, cladding=1.45):.3f}"
'0.066'
solprop.tools.pulse_energy(peak_power, fwhm, shape='sech')[source]#

Return the energy of a pulse of given peak power, duration and shape.

The inverse of pulse_peak_power(), for the same shape.

Parameters:
peak_powerfloat

Peak power in W, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

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

The pulse shape; see pulse_width().

Returns:
float

Pulse energy in J.

Raises:
ToolsError

If the shape is unknown or a quantity is not positive.

Examples

>>> from solprop.tools import pulse_energy
>>> f"{pulse_energy(88.137e9, 10e-15) * 1e3:.4f}"
'1.0000'
solprop.tools.pulse_peak_power(energy, fwhm, shape='sech')[source]#

Return the peak power of a pulse of given energy, duration and shape.

Parameters:
energyfloat

Pulse energy in J, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

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

The pulse shape; see pulse_width().

Returns:
float

Peak power in W: \(E/(2\tau_0)\) for sech and \(E/(\sqrt\pi\,\tau_0)\) for a Gaussian, the integrals of the two shapes.

Raises:
ToolsError

If the shape is unknown or a quantity is not positive.

Examples

>>> from solprop.tools import pulse_peak_power
>>> f"{pulse_peak_power(1e-3, 10e-15) / 1e9:.3f}"
'88.137'
>>> f"{pulse_peak_power(1e-3, 10e-15, 'gauss') / 1e9:.3f}"
'93.944'
solprop.tools.pulse_width(fwhm, shape='sech')[source]#

Return the natural width of a pulse from its full width at half maximum.

Parameters:
fwhmfloat

Full width at half maximum of the power in s, > 0.

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

"sech" for \(P\propto{\rm sech}^2(t/\tau_0)\), "gauss" for \(P\propto\exp(-t^2/\tau_0^2)\).

Returns:
float

\(\tau_0\) in s: fwhm / (2 ln(1 + sqrt 2)) or fwhm / (2 sqrt(ln 2)).

Raises:
ToolsError

If the shape is unknown or the width is not positive.

Examples

>>> from solprop.tools import pulse_width
>>> f"{pulse_width(10e-15) * 1e15:.4f}"
'5.6730'
>>> f"{pulse_width(10e-15, 'gauss') * 1e15:.4f}"
'6.0056'
solprop.tools.radius_zdw(gas, pressure, zdw_wavelength, *, radius_limits=(5e-06, 0.001), temperature=293.15, m=1, model='full', cladding=None, materials=None, root='lowest')[source]#

Return the core radius that puts a capillary’s zero dispersion at a wavelength.

The radius counterpart of pressure_zdw(), through solve_parameter(): the capillary is built once at pressure and re-evaluated at each trial radius.

Parameters:
gasGas or str

A single built-in gas.

pressurefloat

Fill pressure in bar, > 0.

zdw_wavelengthfloat

Wavelength at which the dispersion should vanish, m.

radius_limitstuple of float, optional

Positive ordered search range of the core radius, m.

temperaturefloat, optional

Fill temperature in K.

mint, optional

Radial index of the HE_1m mode.

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

Marcatili model.

claddingGlassIndex, complex or None, optional

Cladding index; None is fused silica.

materialsMaterialSelection or None, optional

Design the capillary prop_capillary builds under the same materials=, as pressure_zdw() does. None is MaterialSelection().

root{‘lowest’, ‘highest’} or int, optional

Which root, should there be several (DesignRoots.pick).

Returns:
float

Core radius in m.

Raises:
ToolsError

If the radius limits are not positive and ordered, the pressure is not positive, or no radius in the range gives the zero (naming the range of zero-dispersion wavelengths it does give).

Examples

>>> from solprop.tools import radius_zdw
>>> f"{radius_zdw('He', 1.0, 400e-9, cladding=1.45) * 1e6:.2f} um"
'89.49 um'
solprop.tools.self_focusing_power(wavelength, index, n2)[source]#

Return the critical power for self-focusing, as physical power.

\(P_{\rm cr} = 1.86226\,\lambda^2/(4\pi n_0 n_2)\), the Townes power of Fibich and Gaeta (Opt. Lett. 25, 335 (2000)). It is solprop.spatial.critical_power() – the package’s one Townes constant – at the linear index, both measuring the physical axial power in the medium (SEP 34). The paper prints the constant as 1.86225; the computed value is 1.8622555, of which 1.86226 is the rounding.

Parameters:
wavelengthfloat

Vacuum wavelength in m, > 0.

indexfloat

Linear refractive index \(n_0\), > 0.

n2float

Nonlinear index in m^2/W, > 0.

Returns:
float

Critical power in W.

Examples

>>> from solprop.tools import self_focusing_power
>>> f"{self_focusing_power(800e-9, 1.0, 3.55e-25) / 1e9:.2f}"
'267.17'
solprop.tools.soliton_content(peak_power, fwhm, gamma, beta2, shape='sech')[source]#

Calculate the soliton count and largest constituent of an unchirped pulse.

This is the scattering content of the lossless cubic focusing NLSE, not a prediction of fission dynamics with higher-order dispersion, Raman or plasma. The conventional soliton_order() remains a separate design parameter.

Parameters:
peak_powerfloat

Input peak power in W, finite and positive.

fwhmfloat

Input power FWHM in s, finite and positive.

gammafloat

Nonlinear coefficient in rad/(W m), finite and positive.

beta2float

Anomalous group-velocity dispersion in s^2/m, finite and negative.

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

Unchirped input field shape; the Gaussian power is exp(-t^2/tau0^2).

Returns:
SolitonContent

Analytic count and largest constituent. The sech eigenvalue is analytic; the Gaussian eigenvalue is numerical, with dimensionless absolute accuracy about 1e-10 away from thresholds. Relative accuracy degrades at threshold.

Raises:
ToolsError

If inputs are invalid, dispersion is not anomalous, or scattering fails.

References

[1]

Klaus and Shaw, SIAM J. Math. Anal. 34, 759 (2003), doi:10.1137/S0036141002403067.

[2]

Kim, Lee and Lyng, arXiv:1310.4145, sections 1-2.

solprop.tools.soliton_order(peak_power, fwhm, gamma, beta2, shape='sech')[source]#

Return the soliton order \(N = \sqrt{L_D/L_{NL}}\).

The number is defined for either sign of the dispersion; it is a soliton order in the physical sense only where beta2 < 0.

Parameters:
peak_powerfloat

Peak power in W, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

gammafloat

Nonlinear coefficient in rad/(W m), > 0.

beta2float

Group-velocity dispersion in s^2/m, non-zero.

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

The pulse shape, used for the width throughout.

Returns:
float

The soliton order, dimensionless.

Examples

>>> from solprop.tools import soliton_order
>>> f"{soliton_order(1e9, 10e-15, 1e-9, -8e-30):.4f}"
'2.0057'
solprop.tools.soliton_params(mode, gas, pressure=None, *, energy, fwhm, wavelength, shape='sech', temperature=None, z=0.0, materials=None)[source]#

Return the design numbers of a pulse in any mode.

The mode supplies the dispersion, the area and the loss; the fill supplies the nonlinear index. They are separate arguments because a mode need not know its fill’s Kerr response (a tabulated mode does not), and the caller is trusted to give the fill the mode was built with – capillary_params() does both.

Parameters:
modeMode

Any mode: a capillary, an antiresonant or tabulated fibre, a rectangular guide.

gasGas, str, Mapping or Mixture

The fill: a registry species, "air", mole fractions, or a mixture. A mixture of species selected from optmat takes their Kerr coefficients at wavelength, the carrier.

pressurefloat or None, optional

Total pressure in bar; None is one bar, and is required beside a Mixture.

energyfloat

Pulse energy in J, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

wavelengthfloat

Pump wavelength in m, > 0.

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

The pulse shape, used consistently for the width and the peak power.

temperaturefloat or None, optional

Fill temperature in K; None is room temperature, or the mixture’s own beside a Mixture, which refuses any other.

zfloat, optional

Position along the waveguide at which everything is evaluated, m.

materialsMaterialSelection or None, optional

Resolve a named fill from optmat under this selection, as a run’s materials= does: its index, density and Kerr coefficient at wavelength. None is MaterialSelection(); a Mixture is taken as it is. The mode is the caller’s either way.

Returns:
SolitonParams

The numbers, with the mode.

Raises:
ToolsError

If a quantity is not positive, the shape is unknown, the mode has no dispersion at the pump, a component of the fill has no Kerr data, the selection names a carrier other than wavelength, or a pressure or a temperature other than its own is given beside a Mixture.

Examples

>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import soliton_params
>>> mode = MarcatiliMode(125e-6, "He", 0.4, model="reduced", cladding=1.45)
>>> p = soliton_params(mode, "He", 0.4, energy=300e-6, fwhm=10e-15,
...                    wavelength=800e-9)
>>> f"{p.soliton_order:.2f} {p.fission_length:.2f}"
'2.26 1.75'
solprop.tools.soliton_peak_power(order, fwhm, gamma, beta2, shape='sech')[source]#

Return the peak power that gives a soliton order.

The inverse of soliton_order() at fixed dispersion, nonlinear coefficient and width: \(N^2 = \gamma P_0\tau_0^2/|\beta_2|\) is linear in the peak power, so \(P_0 = N^2|\beta_2|/(\gamma\tau_0^2)\). pulse_energy() turns it into an energy. On a mode, take beta2 from solprop.modes.base.beta2() at the pump and gamma from nonlinear_coefficient(), both at the launch position.

Parameters:
orderfloat

Conventional soliton order, > 0.

fwhmfloat

Full width at half maximum of the power in s, > 0.

gammafloat

Nonlinear coefficient in rad/(W m), > 0.

beta2float

Group-velocity dispersion in s^2/m, non-zero.

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

The pulse shape, used for the width.

Returns:
float

Peak power in W.

Raises:
ToolsError

If a quantity is not positive, the dispersion is zero, or the shape is unknown.

Examples

>>> from solprop.tools import soliton_order, soliton_peak_power
>>> power = soliton_peak_power(2.0, 10e-15, 1e-9, -8e-30)
>>> f"{power / 1e9:.4f} {soliton_order(power, 10e-15, 1e-9, -8e-30):.4f}"
'0.9943 2.0000'
solprop.tools.solve_parameter(build, search, target, *, z=0.0)[source]#

Return every value of a guide or fill parameter that meets a design target.

The general form of pressure_zdw(), pressure_rdw() and radius_zdw(), for any mode and any parameter: a radius, a pressure, a core size or a wall thickness. The target’s residual is sampled over search on 129 linear values and, where low > 0, 129 logarithmic ones (as pressure_rdw() samples pressure); each sign change between two samples is refined with Brent’s method to a relative tolerance of 2e-12; and a refined change is kept as a root only where the residual has fallen to a thousandth of its value at the bracket’s ends, which discards a change through a pole (a wall resonance, where it diverges instead). Roots closer together than one sample are not separated: narrow search to resolve them.

Parameters:
buildcallable

build(value) returns the mode at a trial value of the parameter, or (mode, gamma) with the fill’s nonlinear coefficient in rad/(W m) (nonlinear_coefficient()), which an RDW target with a peak power and a soliton-order target need: a mode need not know its fill’s Kerr response.

searchtuple of float

Finite ordered range of the parameter, (low, high), in its unit.

targetZDW, RDW or SolitonOrder

What the parameter should achieve.

zfloat, optional

Position along the waveguide at which each mode is evaluated, m: the launch position.

Returns:
DesignRoots

Every root, ascending, with the attainable range of the target’s quantity when there is none; .pick(root) chooses one.

Raises:
ToolsError

If the range or position is not finite or not ordered, the builder returns something other than a mode (and a coefficient where one is needed), a residual is not finite, or a refinement crosses a no-soliton region.

Examples

The radius of a helium capillary at 1 bar with its zero dispersion at 400 nm, re-evaluating one mode at each trial radius:

>>> from solprop.modes import MarcatiliMode
>>> from solprop.tools import ZDW, solve_parameter
>>> mode = MarcatiliMode(125e-6, "He", 1.0, cladding=1.45)
>>> roots = solve_parameter(
...     lambda radius: mode.at_parameters({"core_radius": radius}),
...     (20e-6, 500e-6),
...     ZDW(400e-9),
... )
>>> [f"{radius * 1e6:.2f} um" for radius in roots]
['89.49 um']