optmat.solid.kerr#

The Kerr response of a solid: the nonlinear index, its dispersion, its Raman part.

A solid’s intensity-dependent index n = n0 + n2 I has an instantaneous electronic part and a delayed nuclear (Raman) part. A measurement with pulses of length tau sees the Raman part only in so far as the response can follow the pulse:

\[n_{2,\mathrm{meas}}(\lambda, \tau) = n_{2}(\lambda) \left[(1 - f_R) + f_R\,\eta(\tau)\right], \qquad \eta(\tau) = \frac{\int I(t) \int_0^\infty h_R(s)\, I(t - s)\, ds\, dt} {\int I(t)^2\, dt},\]

where n2(lambda) is the long-pulse (total) index, f_R its Raman fraction and h_R the normalised Raman response (Hollenbeck & Cantrell 2002, hollenbeck_2002). eta is 1 for pulses much longer than the response (about 100 fs), 0 in the limit of very short ones. Electrostriction (nanosecond pulses and longer) is not modelled; such measurements enter only as validators.

The Raman fraction is constrained by measured steady-state Raman gains, predicted as g(Omega) = 2 omega_s n2(lambda_p) f_R Im H_R(Omega) / c with Hollenbeck & Cantrell’s H_R (optmat.solid.raman_response): the gain fixes f_R n2 at the pump, and so pairs f_R with that shape (TC-696). A prior on f_R may be set instead, or as well.

The dispersion of n2 below the two-photon absorption edge is modelled as an even polynomial in the photon energy, n2(lambda) = N [1 + a E^2 + b E^4] (E in eV), the form of the gases’ Taylor-series dispersion (optmat.gas.nonlinear). The fit (data/solid/kerr/<name>.toml, tools/fit/kerr_solid.py) gives each source a calibration scale with a prior. Its result is stored with its covariance (TC-393).

Values printed in esu, n = n0 + n2 <E^2> (nonlinear_index_field), are converted with I = c n0 <E^2> / (4 pi) (Gaussian units): n2 [cm^2/W] = 4 pi 1e7 n2 [esu] / (c [cm/s] n0), with n0 from the material’s recommended linear model.

Module Attributes

KERR_DIRECTORY

The Kerr fit configurations and their stored results.

Functions

dumps(result)

Serialise a Kerr fit as JSON text.

fit(config)

Fit n2(lambda), f_R and the calibration scales to the configured data.

gain_points(options)

Build a measured Raman gain for a Kerr fit.

kerr_models()

Return every stored Kerr fit, named kerr/<name>.

load_config(name)

Load a Kerr fit configuration.

points(options)

Build one dataset's points: its n2 in m^2/W with their pulses' Raman weights.

raman_response(time)

Return fused silica's Raman response h_R(t), normalised to unit integral.

raman_weight(pulse_fwhm)

Return eta, the share of the Raman response a Gaussian pulse's index sees.

Classes

GainOptions(key[, sigma])

How one curated Raman gain enters a Kerr fit.

GainPoints(key, wavelength, shift, value, ...)

A measured Raman gain, with what the model needs to predict it.

KerrConfig(name, material, description, ...)

A Kerr fit's configuration.

KerrModel(material, name, citation, ...[, ...])

A fitted Kerr response: n2(lambda) with its Raman fraction and covariance.

KerrOptions(key[, group, scale_sigma, ...])

How one curated n2 dataset enters a Kerr fit.

KerrResult(config, model, chi2, dof, ...)

A Kerr fit and its statistics.

Points(key, group, wavelength, value, sigma, eta)

The n2 values of one dataset, in m^2/W, with what the model needs.

class optmat.solid.kerr.GainOptions(key, sigma=None)[source]#

Bases: object

How one curated Raman gain enters a Kerr fit.

Attributes:
keystr

source/dataset: a raman_gain of the material, with its pump (parameters.pump_nm) and its Stokes shift (parameters.shift_cm1).

sigmafloat or None

The relative uncertainty used where the dataset states none.

key: str#
sigma: float | None = None#
class optmat.solid.kerr.GainPoints(key, wavelength, shift, value, sigma, response)[source]#

Bases: object

A measured Raman gain, with what the model needs to predict it.

Attributes:
keystr

The dataset.

wavelengthfloat

The pump’s wavelength, m.

shiftfloat

The Stokes shift, rad/s.

valuefloat

The gain, m/W.

sigmafloat

Its uncertainty, m/W.

responsefloat

Im H_R at the shift, Hollenbeck & Cantrell’s normalised response.

factor()[source]#

Return 2 omega_s Im H_R / c: the gain over f_R n2(pump).

Returns:
float

The factor, 1/m.

key: str#
response: float#
shift: float#
sigma: float#
value: float#
wavelength: float#
optmat.solid.kerr.KERR_DIRECTORY: Final = PosixPath('/home/docs/checkouts/optmat/checkouts/7/src/optmat/data/solid/kerr')#

The Kerr fit configurations and their stored results.

class optmat.solid.kerr.KerrConfig(name, material, description, range_nm, raman_fraction, quartic=True, fitted=(), validators=(), raman_gains=(), digest='')[source]#

Bases: object

A Kerr fit’s configuration.

Attributes:
namestr

The configuration’s name.

materialstr

The material.

descriptionstr

What it is.

range_nmtuple of float

The range the fitted dispersion supports, nm.

raman_fractiontuple of float or None

The prior of f_R, value and sigma; None for none (the gains then set it).

quarticbool

Whether the E^4 term of the dispersion is fitted (else it is zero).

fitted, validatorstuple of KerrOptions

The fitted datasets and those only compared.

raman_gainstuple of GainOptions

The measured Raman gains fitted.

digeststr

The configuration’s SHA-256.

description: str#
digest: str = ''#
fitted: tuple[KerrOptions, ...] = ()#
material: str#
name: str#
quartic: bool = True#
raman_fraction: tuple[float, float] | None#
raman_gains: tuple[GainOptions, ...] = ()#
range_nm: tuple[float, float]#
validators: tuple[KerrOptions, ...] = ()#
class optmat.solid.kerr.KerrModel(material, name, citation, wavelength_range, parameters, covariance, scales=<factory>, *, status='user', status_reason='', modified=(), base='')[source]#

Bases: Identified

A fitted Kerr response: n2(lambda) with its Raman fraction and covariance.

Attributes:
materialstr

The material.

namestr

kerr/<name>.

citationstr

The fit.

wavelength_rangetuple of float

Where the dispersion is fitted, m.

parameterstuple of float

N (m^2/W), a (eV^-2), b (eV^-4) and f_R.

covariancenumpy.ndarray

Their covariance (Birge-scaled).

scalesdict of str to float

The calibration scale of each group.

statusstr

validated for the stored fit; user for a model a caller built.

EVALUATION_VERSION: ClassVar[int] = 1#
IDENTITY_KIND: ClassVar[str] = 'kerr'#
citation: str#
covariance: Float[ndarray, '4 4']#
material: str#
n2(wavelength)[source]#

Return the long-pulse (total, electronic plus Raman) n2.

Parameters:
wavelengtharray_like or float

Vacuum wavelength, m.

Returns:
numpy.ndarray

The index n2, m^2/W.

n2_effective(wavelength, pulse_fwhm)[source]#

Return the n2 a Gaussian pulse of the given length measures.

Parameters:
wavelengtharray_like or float

Vacuum wavelength, m.

pulse_fwhmfloat

The pulse’s intensity FWHM, s.

Returns:
numpy.ndarray

The index n2, m^2/W.

n2_electronic(wavelength)[source]#

Return the instantaneous (electronic) part, (1 - f_R) n2.

Parameters:
wavelengtharray_like or float

Vacuum wavelength, m.

Returns:
numpy.ndarray

The index n2, m^2/W.

n2_sigma(wavelength)[source]#

Return the one-sigma uncertainty of the long-pulse n2 (from the fit).

Parameters:
wavelengtharray_like or float

Vacuum wavelength, m.

Returns:
numpy.ndarray

The uncertainty sigma, m^2/W.

name: str#
parameters: tuple[float, float, float, float]#
property raman_fraction: float#

The Raman fraction f_R of the long-pulse n2.

Returns:
float

The fraction f_R.

scales: Mapping[str, float]#
wavelength_range: tuple[float, float]#
class optmat.solid.kerr.KerrOptions(key, group='', scale_sigma=0.1, raman='pulse', pulse_fs=None, sigma=None, extra=0.0, range_nm=(0.0, inf))[source]#

Bases: object

How one curated n2 dataset enters a Kerr fit.

Attributes:
keystr

source/dataset.

groupstr

The calibration group (its own source by default): the group’s values share one scale factor.

scale_sigmafloat

The prior of the group’s scale (relative, one sigma).

ramanstr

pulse (eta from the stated pulse length), none (the source isolates the electronic part), or full (pulses much longer than the response).

pulse_fsfloat or None

The pulse FWHM where the dataset states none, fs.

sigmafloat or None

The relative uncertainty used where the dataset states none.

extrafloat

A relative scatter added in quadrature.

range_nmtuple of float

The wavelength window used, nm.

extra: float = 0.0#
group: str = ''#
key: str#
pulse_fs: float | None = None#
raman: str = 'pulse'#
range_nm: tuple[float, float] = (0.0, inf)#
scale_sigma: float = 0.1#
sigma: float | None = None#
class optmat.solid.kerr.KerrResult(config, model, chi2, dof, dataset_chi2, validation)[source]#

Bases: object

A Kerr fit and its statistics.

Attributes:
configKerrConfig

The configuration.

modelKerrModel

The fitted model.

chi2float

The chi-squared, priors included.

dofint

Degrees of freedom.

dataset_chi2dict of str to tuple

Points and chi-squared per dataset.

validationdict of str to list of float

Per validator, the ratio of each value to the model’s prediction for its pulse.

chi2: float#
config: KerrConfig#
dataset_chi2: Mapping[str, tuple[int, float]]#
dof: int#
model: KerrModel#
validation: Mapping[str, list[float]]#
class optmat.solid.kerr.Points(key, group, wavelength, value, sigma, eta)[source]#

Bases: object

The n2 values of one dataset, in m^2/W, with what the model needs.

Attributes:
keystr

The dataset.

groupstr

Its calibration group.

wavelengthnumpy.ndarray

Vacuum wavelengths, m.

valuenumpy.ndarray

n2, m^2/W (self coefficients; esu values converted).

sigmanumpy.ndarray

Their uncertainties, m^2/W.

etanumpy.ndarray

The Raman weight of each value’s pulse.

eta: Float[ndarray, 'n']#
group: str#
key: str#
sigma: Float[ndarray, 'n']#
value: Float[ndarray, 'n']#
wavelength: Float[ndarray, 'n']#
optmat.solid.kerr.dumps(result)[source]#

Serialise a Kerr fit as JSON text.

Parameters:
resultKerrResult

The fit.

Returns:
str

Indented JSON.

optmat.solid.kerr.fit(config)[source]#

Fit n2(lambda), f_R and the calibration scales to the configured data.

Parameters:
configKerrConfig

The configuration.

Returns:
KerrResult

The fit.

optmat.solid.kerr.gain_points(options)[source]#

Build a measured Raman gain for a Kerr fit.

Parameters:
optionsGainOptions

How it enters.

Returns:
GainPoints

The gain in m/W, with its pump, shift and Im H_R.

Raises:
DataError

If the dataset is not one gain in cm/W or m/W with its pump and shift, or has no uncertainty.

optmat.solid.kerr.kerr_models()[source]#

Return every stored Kerr fit, named kerr/<name>.

Returns:
dict of str to KerrModel

The models.

optmat.solid.kerr.load_config(name)[source]#

Load a Kerr fit configuration.

Parameters:
namestr or pathlib.Path

The name (data/solid/kerr/<name>.toml) or a path.

Returns:
KerrConfig

The configuration.

Raises:
DataError

If it is malformed or names an unknown dataset.

optmat.solid.kerr.points(options)[source]#

Build one dataset’s points: its n2 in m^2/W with their pulses’ Raman weights.

Parameters:
optionsKerrOptions

How it enters.

Returns:
Points

The values inside the window, in m^2/W.

Raises:
DataError

If a point lacks an uncertainty or a pulse length it needs.

optmat.solid.kerr.raman_response(time)[source]#

Return fused silica’s Raman response h_R(t), normalised to unit integral.

Hollenbeck & Cantrell’s intermediate-broadening model (J. Opt. Soc. Am. B 19, 2886 (2002), Eq. (9) and Table 1; hollenbeck_2002), whose normalisation the paper does not state: optmat.solid.raman_response.SilicaRamanResponse.response() of its hollenbeck_2002 model, normalised analytically (TC-691).

Parameters:
timenumpy.ndarray

Time after the impulse, s (the response is zero before it).

Returns:
numpy.ndarray

The response h_R, 1/s.

Examples

>>> t = np.arange(0, 4e-12, 0.1e-15)
>>> f"{np.trapezoid(raman_response(t), t):.4f}"
'1.0000'
optmat.solid.kerr.raman_weight(pulse_fwhm)[source]#

Return eta, the share of the Raman response a Gaussian pulse’s index sees.

The intensity-weighted mean of the delayed response over the pulse, relative to a response that follows the pulse instantly (module docstring). For a Gaussian pulse of rms duration s it is, exactly, eta = int exp(-s^2 w^2) Re H(w) dw / int exp(-s^2 w^2) dw, with H the Fourier transform of h_R (H(0) = 1).

Parameters:
pulse_fwhmfloat

The intensity FWHM of a Gaussian pulse, s; inf for a long pulse.

Returns:
float

The weight eta, between 0 and 1.

Examples

>>> f"{raman_weight(math.inf):.1f}"
'1.0'
>>> f"{raman_weight(10e-12):.3f}"
'1.000'