solprop.physdata.mixtures#

Compose ordered gas populations with their own number-density paths.

Module Attributes

DILUTE_SCALING_THRESHOLD

Relative error in n - 1 of linear density scaling above which a fill warns.

Functions

check_preionisation(value[, owner])

Validate an initial ionised fraction, a number or a path in [0, 1].

Classes

Component(species, density[, label, ...])

Bind one labelled population to a species and a density path.

Mixture(components[, temperature, shared, ...])

Keep ordered populations and their shared fill, when present.

class solprop.physdata.mixtures.Component(species, density, label='', preionisation=0.0, dephasing=None, raman=None)[source]#

Bases: Displayed

Bind one labelled population to a species and a density path.

Attributes:
speciesSpecies

The population’s material data.

densityZProfile

Number density in m^-3 along z, with non-negative values.

labelstr

Unique mixture label; an empty default takes the species’ name.

preionisationfloat or ZProfile

Initial ionised fraction, between zero and one inclusive: a number, or a path along z giving the fraction ionised before the pulse arrives at each position.

dephasingDephasing or None

Supplied partner-aware Raman linewidth, if available.

ramanMolecularOptions or None

Raman term selection; None selects every available term.

density: ZProfile#
dephasing: Dephasing | None = None#
label: str = ''#
preionisation: float | ZProfile = 0.0#
raman: MolecularOptions | None = None#
species: Species#
solprop.physdata.mixtures.DILUTE_SCALING_THRESHOLD: Final = 0.01#

Relative error in n - 1 of linear density scaling above which a fill warns.

Measured against optmat’s Lorentz–Lorenz law with its refractivity virial: at 800 nm and 293.15 K argon and nitrogen pass 1 % near 52 and 53 bar, krypton near 31 bar, xenon near 17 bar and SF6 near 15 bar. The error is recorded in the run’s manifest whatever its size; the bound only decides the warning, until a finite-density law replaces the dilute one (SEP 11).

class solprop.physdata.mixtures.Mixture(components, temperature=293.15, shared=None, fractions=None, composition=None)[source]#

Bases: Displayed

Keep ordered populations and their shared fill, when present.

Attributes:
componentstuple of Component

Non-empty ordered populations with unique labels.

temperaturefloat or ZProfile

Positive temperature in K, or a path of it along z, which every density path of a fill follows (solprop.profiles.DensityPath); a constant path is stored as its value. A varying temperature makes a shared fill’s populations independent parameters of the linear operator (density:<label>), since one pressure no longer fixes every density, and the rotational Raman populations take one reference temperature (solprop.nonlinear.mixtures).

sharedZProfile or None

Shared total-pressure path in bar, or None for independent densities.

fractionstuple of float or None

Mole fractions of a shared fill, in component order.

compositionstr or None

The named optmat composition the fractions were taken from, such as "dry air (N2, O2)", which a run’s material manifest records; None for fractions given otherwise. Set by air() under a selection; a mixture derived from it by with_fill(), with_densities() or at_parameters() does not keep it.

classmethod air(pressure, *, temperature=293.15, fractions=None, argon=True, length=None, floor=None, radius=None, vacuum_end=None, selection=None)[source]#

Construct dry air from nitrogen, oxygen and argon; omit carbon dioxide.

Parameters:
pressurefloat or sequence or ZProfile

Total pressure in bar, with the vocabulary of fill().

temperaturefloat or ZProfile, optional

Positive temperature in K, or a path of it along z, as in fill().

fractionscollections.abc.Mapping or None, optional

Mole fractions. None takes the named composition of the selection (below).

argonbool, optional

Whether the default composition carries argon. False is the two-component convenience the capillary interface’s "air" means: nitrogen and oxygen renormalised to each other, a declared approximation. Ignored when fractions is given.

lengthfloat or None, optional

Positive length in m, required for endpoint pressure pairs.

floorfloat or None, optional

Pressure-gradient floor in bar.

radiusfloat, ZProfile or None, optional

Core radius in m for a steady-flow gradient, as in fill().

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

How a vacuum end is treated, as in fill().

selectionMaterialSelection or None, optional

Resolve the species from optmat, as in fill(). The default composition is optmat’s named one: CIPM-2007’s "dry air (N2, O2, Ar)", or with argon=False "dry air (N2, O2)", each renormalised over what it keeps.

Returns:
Mixture

The resolved gas populations, not the dispersion-only Gas.Air entry.

Examples

>>> from solprop.physdata import Mixture
>>> Mixture.air(1.0).labels
('N2', 'O2', 'Ar')
>>> Mixture.air(1.0, argon=False).labels
('N2', 'O2')
>>> f"{Mixture.air(1.0).fractions[0]:.6f}", Mixture.air(1.0).composition
('0.781184', 'dry air (N2, O2, Ar)')
at_parameters(values)[source]#

Sample pressure or labelled densities without changing material data.

Parameters:
valuescollections.abc.Mapping

Total pressure under ‘pressure’, or densities under ‘density:label’.

Returns:
Mixture

Constant sampled populations with the same labels and species.

Raises:
MaterialError

If a parameter is unknown or incompatible with the fill: a total pressure beside a temperature that varies along z, where one pressure does not fix the densities, is refused by name.

components: tuple[Component, ...]#
composition: str | None = None#
density(z)[source]#

Evaluate every component density in mixture order.

Parameters:
znumpy.ndarray

Positions in m.

Returns:
numpy.ndarray

Non-negative densities in m^-3, shape (n_species, n_z).

dilute_scaling_checks(omega)[source]#

Measure the error of linear density scaling of each optmat population.

Parameters:
omeganumpy.ndarray

Angular frequencies in rad/s of the band, > 0.

Returns:
tuple of DiluteScalingCheck

One per optmat-selected population with a non-zero density, at its largest density along the fill.

dsusceptibility_domega(omega, z)[source]#

Sum the analytic species susceptibility derivatives.

Parameters:
omeganumpy.ndarray

Angular frequencies in rad/s, within each active species’ support.

znumpy.ndarray

Positions in m.

Returns:
numpy.ndarray

Derivative in s, shape (n_z, n_omega).

classmethod fill(fractions, pressure, *, temperature=293.15, floor=None, length=None, radius=None, vacuum_end=None, selection=None)[source]#

Construct a fill using each species’ partial-pressure equation of state.

Parameters:
fractionscollections.abc.Mapping

Species to non-negative mole fraction, summing to one.

pressurefloat or sequence or ZProfile

Total pressure in bar; a scalar, endpoint pair, (z, p) pair or profile.

temperaturefloat or ZProfile, optional

Positive temperature in K, or a path of it along z in m. Every density follows it; a gradient built here follows the flow weight eta(T) T (solprop.gasflow.temperature_weight()), which needs the species’ transport data; a varying pressure profile given beside a varying temperature must carry that weight.

floorfloat or None, optional

Pressure-gradient floor in bar; None uses the standard floor.

lengthfloat or None, optional

Positive length in m, required for endpoint pressure pairs.

radiusfloat, ZProfile or None, optional

Core radius in m of the guide the gas flows through. Given, an endpoint pair or (z, p) pair becomes the steady flow of the whole mixture (solprop.gasflow.steady_fill(), with the mixture’s Wilke viscosity and sound speed): it follows the bore, chokes a vacuum end and checks the flow regime. None keeps the uniform law and the numerical floor; the simulation constructors supply the guide’s radius.

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

How an outer end below its choked pressure is treated; None chokes it when radius is given. Refused beside a constant pressure or a profile, which have no end to choke.

selectionMaterialSelection or None, optional

Resolve the named species from optmat under this selection (species()); None is MaterialSelection(), optmat’s recommended models. A supplied Species is taken as it is. Each population’s density is still the pure gas’s at its partial pressure.

Returns:
Mixture

The fill in mapping iteration order.

Raises:
MaterialError

If fractions, species or the pressure specification are invalid.

fractions: tuple[float, ...] | None = None#
gamma3_path(wavelength=None)[source]#

Compose the density-weighted third-order susceptibility path.

Parameters:
wavelengthfloat or None, optional

The vacuum carrier wavelength in m at which a species’ optmat Kerr model is evaluated (kerr_coefficient()); required when one has such a model, ignored by fixed coefficients.

Returns:
ZProfile

Sum of density times gamma3, in m^2/V^2.

Raises:
MaterialError

If any component lacks third-order response data, or an optmat model needs a carrier and none is given.

property labels: tuple[str, ...][source]#

Return the labels in mixture order.

Returns:
tuple of str

Unique population labels.

property material_records: tuple[MaterialRecord, ...][source]#

Return the records of the optmat models the populations carry, once each.

Returns:
tuple of MaterialRecord

In component order, a model shared by two populations once.

classmethod of(*components, temperature=293.15)[source]#

Construct a mixture from labelled density populations.

Parameters:
*componentsComponent

Ordered populations with unique labels.

temperaturefloat or ZProfile, optional

Positive temperature in K, or a path of it along z in m. The densities are given, so it reaches the run only through the Raman populations’ reference temperature.

Returns:
Mixture

A mixture with independent density paths.

classmethod partial_pressures(pressures, *, temperature=293.15, selection=None)[source]#

Construct populations from independent partial pressures.

Parameters:
pressurescollections.abc.Mapping

Species to non-negative partial pressure in bar, scalar or profile.

temperaturefloat or ZProfile, optional

Positive temperature in K, or a path of it along z in m, which every density follows. Beside it a varying pressure profile must carry its species’ flow weight (the equal mixture’s for one path shared by all).

selectionMaterialSelection or None, optional

Resolve the named species from optmat, as in fill().

Returns:
Mixture

The populations in mapping order. Identical profile objects share a fill.

serialise()[source]#

Describe the composition and sampled profiles in explicit units.

Returns:
dict

Labels, species names, temperature in K (a number, or the sampled record of a path along z) and density samples in m^-3, and the named composition where there is one. Breakpoints accompany every path; no callable is claimed reconstructible.

shared: ZProfile | None = None#
susceptibility(omega, z)[source]#

Sum species susceptibilities before forming any refractive index.

Parameters:
omeganumpy.ndarray

Angular frequencies in rad/s, within each active species’ support.

znumpy.ndarray

Positions in m.

Returns:
numpy.ndarray

Dimensionless susceptibility, shape (n_z, n_omega); complex if absorbing.

temperature: float | ZProfile = 293.15#
total_density(z)[source]#

Evaluate total number density.

Parameters:
znumpy.ndarray

Positions in m.

Returns:
numpy.ndarray

Total density in m^-3, shape (n_z,).

with_densities(mapping)[source]#

Replace labelled density paths while preserving component order and data.

Parameters:
mappingcollections.abc.Mapping

Labels to density paths or constant densities in m^-3.

Returns:
Mixture

Updated independent profiles; omitted labels keep their paths.

Raises:
MaterialError

If a label is unknown or a supplied density is invalid.

with_fill(fractions=None, pressure=None, *, length=None, floor=None, radius=None, vacuum_end=None)[source]#

Replace fill fractions or pressure without replacing species or labels.

Parameters:
fractionscollections.abc.Mapping or None, optional

New mole fraction for every label; None retains the current fractions.

pressurefloat or sequence or ZProfile or None, optional

New total pressure in bar; None retains the shared path.

lengthfloat or None, optional

Length in m required for new endpoint pressures.

floorfloat or None, optional

New pressure-gradient floor in bar.

radiusfloat, ZProfile or None, optional

Core radius in m for a new steady-flow gradient, as in fill().

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

How a new gradient’s vacuum end is treated, as in fill().

Returns:
Mixture

Updated populations sharing the supplied total pressure.

Raises:
MaterialError

If fractions or pressure are missing for an independent mixture, or new fractions are given beside a retained fill whose choked end or flow weight was computed for the old composition.

solprop.physdata.mixtures.check_preionisation(value, owner='')[source]#

Validate an initial ionised fraction, a number or a path in [0, 1].

A number is the fraction ionised before the pulse arrives, the same everywhere. A path is that fraction at each position along the fibre, still set before the pulse arrives there; it is sampled at its breakpoints and at evenly spaced probes over its span (at its start alone when the span is unbounded). A feature narrower than those samples is not seen: declare it with breakpoints.

Parameters:
valueobject

The fraction, dimensionless in [0, 1]: a real number (a Python or NumPy scalar, or a zero-dimensional array), or a ZProfile of it along z in m.

ownerstr, optional

What carries the value, for the message: a species or component label.

Returns:
float or ZProfile

The value itself when it is a Python number or a path; a NumPy scalar or a zero-dimensional array as the Python float it holds, which is what the translation layer takes.

Raises:
MaterialError

If value is a boolean, neither a real number nor a ZProfile, not finite, or outside [0, 1] at any sampled position.

Examples

>>> import numpy as np
>>> from solprop.physdata.mixtures import check_preionisation
>>> from solprop.profiles import Linear
>>> check_preionisation(0.1)
0.1
>>> check_preionisation(np.array(0.25))
0.25
>>> check_preionisation(Linear(0.0, 0.2, 1.0), "Ar")
Linear(0 to 0.2 over 1 m)
>>> check_preionisation(Linear(0.0, 1.5, 1.0), "Ar")
Traceback (most recent call last):
    ...
solprop.exceptions.MaterialError: preionisation must be in [0, 1] for Ar at ...