optmat.gas.models.oscillator#

Oscillator-strength (pseudo-spectral) polarizability models.

The dynamic dipole polarizability of an atom or molecule below its first resonance is a sum over its dipole oscillator-strength distribution. Represented by a finite set of lines, or pseudo-states, of energies \(E_i\) and oscillator strengths \(f_i\),

\[\alpha(\omega) = \sum_i \frac{f_i}{E_i^2 - \omega^2}\]

in atomic units (hartree for \(E_i\) and \(\omega\), \(a_0^3\) for \(\alpha\)). This is the form of Kumar and Meath’s constrained distributions and, in the dilute limit, of every Sellmeier formula; its Cauchy moments are \(S(-2k) = \sum_i f_i E_i^{-2k}\), with \(\alpha(\omega) = \sum_{k \geq 1} S(-2k)\,\omega^{2k-2}\) below the lowest \(E_i\), and the Thomas-Reiche-Kuhn sum \(S(0) = \sum_i f_i\) equals the number of electrons for a complete distribution.

A model whose lowest pseudo-states sit at the measured resonance lines has physical poles: it can be evaluated up to the first line and down to zero frequency without the spurious structure a free Sellmeier fit may place in between.

The refractive index measures the refractive polarizability: the electric polarizability plus the atom’s (diamagnetic) magnetic susceptibility \(\chi_0\), because \(n^2 = \varepsilon\mu\). The model carries \(\chi_0\) as a frequency-independent offset_au; its sums \(S(k)\) are those of the electric distribution alone. Where it is known (helium), the retardation of the forward-scattering amplitude adds a term \(c\,\omega^2\) to the refractive polarizability (retardation_au; Pachucki & Puchalski 2019, TC-705), which the sums do not contain either.

Functions

angular_frequency_au(wavelength)

Return the photon energy in hartree of a vacuum wavelength.

Classes

OscillatorModel(gas, name, citation, ...[, ...])

A polarizability model made of oscillator strengths at fixed energies.

class optmat.gas.models.oscillator.OscillatorModel(gas, name, citation, wavelength_range, kind, strengths=(), energies=(), labels=(), offset_au=0.0, retardation_au=0.0, absorption=None, *, status='user', status_reason='', modified=(), base='', intervals=())[source]#

Bases: Model

A polarizability model made of oscillator strengths at fixed energies.

from_parameters() builds one from a caller’s poles, in SI; the overrides (with_parameters()) name the fields, in atomic units: INPUTS.

Attributes:
strengthstuple of float

Oscillator strengths f_i (dimensionless).

energiestuple of float

Energies E_i, hartree, > 0.

labelstuple of str

What each term represents (“He 1s2p 1P”, “effective continuum”, …).

offset_aufloat

A frequency-independent term added to the sum, atomic units: the magnetic susceptibility chi_0 that makes the sum’s electric polarizability the refractive one.

retardation_aufloat

The coefficient c of a term c omega^2 (omega in hartree) added to the refractive polarizability, atomic units: the retardation (quadrupole and magnetic-dipole) part of the forward-scattering amplitude, known for helium (Pachucki & Puchalski 2019; TC-705). Zero for the other gases.

absorptionMeasuredAbsorption or None

A measured absorption spectrum whose complex polarizability (Kramers-Kronig) is added to the sum: the model then absorbs (ozone). None for a transparent model.

EVALUATION_VERSION: ClassVar[int] = 2#
INPUTS: ClassVar[tuple[str, ...]] = ('energies', 'intervals', 'labels', 'offset_au', 'retardation_au', 'strengths')#

The parameters with_parameters() may change.

property absorbing: bool#

Whether the model has a measured absorption term.

Returns:
bool

True when absorption is set.

absorption: MeasuredAbsorption | None = None#
cauchy_moment(k)[source]#

Return the electric distribution’s dipole sum S(k) = sum_i f_i E_i^k.

Parameters:
kint

The order: S(-2) is the static polarizability, S(0) the Thomas-Reiche-Kuhn sum, S(-4) the first dispersion coefficient.

Returns:
float

The sum, atomic units.

Examples

>>> from optmat.gas.gases import Gas
>>> model = OscillatorModel(
...     gas=Gas.He, name="demo", citation="", kind="fitted",
...     wavelength_range=(60e-9, float("inf")),
...     strengths=(0.5, 1.5), energies=(0.8, 1.2), labels=("a", "b"),
... )
>>> model.cauchy_moment(-2) == float(model.polarizability_au(np.array(0.0)))
True

(offset_au is 0 here; otherwise the static refractive polarizability is S(-2) + offset_au. The refractive polarizability’s omega^2 coefficient is S(-4) + retardation_au.)

dispersion_au(omega, order)[source]#

Return the order-th derivative of omega alpha(omega), analytically.

In the dilute limit beta = (omega / c) [1 + N alpha / (2 epsilon_0)], so for order >= 2 the dispersion coefficient beta_k is proportional to this derivative with a factor that depends only on the density: its ratio between models, or its relative change, needs no state. The magnetic term contributes only to orders 0 and 1, the retardation term c omega^3 to orders 0 to 3.

Parameters:
omeganumpy.ndarray

Photon energy, hartree, below the lowest term’s energy.

orderint

The order k >= 0.

Returns:
numpy.ndarray

d^k (omega alpha) / d omega^k, atomic units.

Raises:
ValueError

If order is negative.

Examples

>>> from optmat.gas.gases import Gas
>>> model = OscillatorModel(
...     gas=Gas.He, name="demo", citation="", kind="fitted",
...     wavelength_range=(60e-9, float("inf")),
...     strengths=(0.5,), energies=(0.8,), labels=("a",),
... )
>>> omega = np.array([0.3])
>>> first = model.dispersion_au(omega, 1)
>>> direct = (model.polarizability_au(omega)
...           + omega * model.dpolarizability_domega_au(omega))
>>> bool(abs(first[0] / direct[0] - 1) < 1e-12)
True
dpolarizability_domega_au(omega)[source]#

Return the derivative of the polarizability with frequency, analytically.

Parameters:
omeganumpy.ndarray

Photon energy, hartree.

Returns:
numpy.ndarray

sum_i 2 f_i omega / (E_i^2 - omega^2)^2 + 2 retardation_au omega, atomic units (a0^3 per hartree).

Examples

>>> from optmat.gas.gases import Gas
>>> model = OscillatorModel(
...     gas=Gas.He, name="demo", citation="", kind="fitted",
...     wavelength_range=(60e-9, float("inf")),
...     strengths=(0.5,), energies=(0.8,), labels=("a",),
... )
>>> omega, h = np.array([0.3]), 1e-6
>>> numeric = (model.polarizability_au(omega + h)
...            - model.polarizability_au(omega - h)) / (2 * h)
>>> bool(abs(model.dpolarizability_domega_au(omega)[0] / numeric[0] - 1) < 1e-8)
True
energies: tuple[float, ...] = ()#
classmethod from_parameters(species, strengths, energies, *, intervals, offset=0.0, labels=None, citation='', name='')[source]#

Return a gas polarizability as a sum of poles, from SI parameters.

alpha(omega) = (e^2/m_e) sum_k f_k / (omega_k^2 - omega^2) + offset, the form of OEP 2’s compact models, with E_k = hbar omega_k.

Parameters:
speciesGas or str

A curated gas, or a custom species’ name, the identity’s material.

strengthsarray_like

The oscillator strengths f_k, dimensionless.

energiesarray_like

The poles’ photon energies E_k, J, > 0.

intervalssequence of (float, float)

The qualified intervals, vacuum wavelength, m, disjoint and ascending.

offsetfloat, optional

A frequency-independent term, C m^2/V (a magnetic susceptibility).

labelssequence of str or None, optional

What each pole is; pole 1, … by default.

citationstr, optional

Where the parameters come from.

namestr, optional

The model’s name; user/<species> by default.

Returns:
OscillatorModel

The model, status user.

Raises:
ValueError

If the lengths differ, an energy is not positive or the intervals are not disjoint and ascending.

Examples

>>> from optmat.constants import E_CHARGE
>>> model = OscillatorModel.from_parameters(
...     "Ar", [1.2, 4.0], [11.8 * E_CHARGE, 20.0 * E_CHARGE],
...     intervals=[(150e-9, float("inf"))])
>>> model.identity.status, model.name
('user', 'user/Ar')
labels: tuple[str, ...] = ()#
offset_au: float = 0.0#
polarizability_au(omega)[source]#

Return the refractive polarizability in atomic units.

Parameters:
omeganumpy.ndarray

Photon energy, hartree.

Returns:
numpy.ndarray

sum_i f_i / (E_i^2 - omega^2) + offset_au + retardation_au omega^2, atomic units.

retardation_au: float = 0.0#
strengths: tuple[float, ...] = ()#
optmat.gas.models.oscillator.angular_frequency_au(wavelength)[source]#

Return the photon energy in hartree of a vacuum wavelength.

Parameters:
wavelengthnumpy.ndarray

Vacuum wavelength, m (inf gives 0).

Returns:
numpy.ndarray

omega in atomic units.

Examples

>>> f"{float(angular_frequency_au(np.array(45.5634e-9))):.5f}"
'1.00000'