solprop.adiabatic#

Certify adiabatic forward transport through a real index that varies along z.

A radial or Cartesian spectral column propagates along z with the real longitudinal wave number \(q(z) = \operatorname{Re}k_z = \sqrt{k(\omega, z)^2 - k_\perp^2}\). The forward-only model keeps the exact forward directional amplitude and drops its coupling to the backward one. For a positive real q of bounded variation over the run path, constant outside it, the exact scalar problem bounds what that drops (SEP 34, section 4.5): with

\[\Lambda = \tfrac12\operatorname{TV}_{[z_0, z_1]}(\ln q),\]

which counts kinks and declared jumps alike, the reflected power is at most \(R_* = \tanh^2\Lambda\) and the relative complex error of the retained forward field at most \(\delta_* = \operatorname{expm1}(\Lambda\tanh\Lambda)\). A monotone path has \(\Lambda = \tfrac12|\ln(q_1/q_0)|\), and the abrupt step attains \(R_*\). The bound is for the linear background problem only: it says nothing about the omitted backward field’s local interference, nonlinear feedback or ionisation.

Admission. AdiabaticAccuracy holds the two budgets (both \(10^{-4}\) by default). Every propagating column of the active band must satisfy \(\delta_* \le\) field_error and \(R_* \le\) reflected_energy over the whole path; a column that is propagating at one point and not at another (it crosses \(q = 0\)) refuses, as does a varying imaginary index and a custom path without declared variation.

The enclosure is not sampled. Every material this module reads has a wave-number square affine in its number densities,

\[s(z) = q^2 = (\omega/c)^2\Bigl(\varepsilon(\omega) + \sum_i \rho_i(z)\,\chi_i(\omega)\Bigr) - k_\perp^2,\]

with \(\varepsilon = 1\) for a gas or mixture (whose index is \(\sqrt{1 + \sum_i\rho_i\chi_i}\)) and \(\varepsilon = n^2\) for a glass or constant index, which carries no path. Each density path supplies a solprop.profiles.PathVariation: pieces between knots on which its values and variation are enclosed, exactly where it is certified monotone. On the union of those pieces:

  • where every density is monotone and every term \(\chi_i\,\Delta\rho_i\) moves one way, s is monotone, so \(\ln q\) is too and its variation is the endpoint difference \(|\tfrac12\ln(s_1/s_0)|\), evaluated as log1p of the exactly formed difference over s: exact, and attained;

  • otherwise \(\operatorname{TV}\ln q \le \sum_i|b_i|\operatorname{TV}\rho_i / (2 s_{\min})\) with \(b_i = (\omega/c)^2\operatorname{Re}\chi_i\) and \(s_{\min}\) the minimum of the affine s over the box of density ranges, reached at a corner;

  • a declared jump adds its own one-sided \(|\Delta\ln q|\).

Positivity follows from the same quantities: s is positive on a monotone piece when it is at both ends, and on a box when it is at the lowest corner. The arithmetic is bounded by a relative margin on each term: a few unit roundoffs for forming the difference and the ratio, plus the conditioning \(4u\,S/s_{\min}\) of a square whose terms of magnitude S cancel towards cutoff, amplified by the log1p condition number. The certificate is of the represented path, the function the profile evaluates; how well that represents a physical medium (an equation-of-state table, a measured profile) is a separate envelope.

Functions

certify_radial_path(dispersion, kperp_sq, z_span)

Certify a spatial medium's z-varying path for every column of a radial grid.

certify_wave_path(omega, permittivity, ...)

Certify the columns of a material whose wave-number square is affine in z.

field_error_bound(variation)

Return the forward-field error bound expm1(Lambda tanh Lambda).

reflection_bound(variation)

Return the reflected-power bound tanh(Lambda)**2.

Classes

AdiabaticAccuracy([field_error, ...])

The budgets a z-varying path must meet to use adiabatic forward transport.

AdiabaticAdmission(identity, z_span, ...[, ...])

The record that a path met its adiabatic budgets.

class solprop.adiabatic.AdiabaticAccuracy(field_error=0.0001, reflected_energy=0.0001)[source]#

Bases: object

The budgets a z-varying path must meet to use adiabatic forward transport.

These are model budgets chosen by the maintainer, not physical constants or integrator tolerances. Callers may tighten them.

Attributes:
field_errorfloat

Largest certified relative error of the retained forward field, expm1(Lambda tanh Lambda), finite and positive. Default 1e-4.

reflected_energyfloat

Largest certified reflected fraction of the power, tanh(Lambda)**2, finite and positive. Default 1e-4.

Raises:
MaterialError

If a budget is not finite and positive.

Examples

>>> from solprop.adiabatic import AdiabaticAccuracy
>>> AdiabaticAccuracy().field_error
0.0001
field_error: float = 0.0001#
reflected_energy: float = 0.0001#
class solprop.adiabatic.AdiabaticAdmission(identity, z_span, accuracy, variation, reflection, field_error, worst_kperp_sq, worst_omega, omega, spectral_variation, support, jumps, exact=True, interpolation_envelope=0.0)[source]#

Bases: object

The record that a path met its adiabatic budgets.

Attributes:
identitycollections.abc.Mapping

The represented material path: the material and each density path’s structural identity (None for a custom path, which has none).

z_spantuple of float

The certified run path (z0, z1) in m.

accuracyAdiabaticAccuracy

The budgets met.

variationfloat

The largest enclosed Lambda over the propagating columns.

reflectionfloat

tanh(variation)**2, the largest reflected-power bound.

field_errorfloat

expm1(variation tanh variation), the largest forward-field bound.

worst_kperp_sqfloat or None

Transverse wave-number square in m^-2 of the column attaining variation; None when no column varies.

worst_omegafloat or None

Its angular frequency in rad/s.

omeganumpy.ndarray

The certified angular frequencies in rad/s, shape (n_omega,).

spectral_variationnumpy.ndarray

The largest Lambda over the propagating columns at each frequency, zero where none propagates, shape (n_omega,).

supportnumpy.ndarray

Which columns propagate over the whole path, shape (n_modes, n_omega); the others are nonpropagating everywhere.

jumpsnumpy.ndarray

Declared jumps of the material inside the path, in m.

exactbool

Whether every piece was certified monotone, so that variation is the attained value up to rounding rather than an upper bound.

interpolation_envelopefloat

Relative error of the run’s tabulated operator against the represented path, a separate envelope from the certificate’s bounds (SEP 34 section 4.5); zero when no table stands between them.

accuracy: AdiabaticAccuracy#
exact: bool = True#
field_error: float#
identity: Mapping[str, object]#
interpolation_envelope: float = 0.0#
jumps: Float[ndarray, 'n_jumps']#
omega: Float[ndarray, 'n_omega']#
reflection: float#
spectral_variation: Float[ndarray, 'n_omega']#
support: Bool[ndarray, 'n_modes n_omega']#
variation: float#
worst_kperp_sq: float | None#
worst_omega: float | None#
z_span: tuple[float, float]#
solprop.adiabatic.certify_radial_path(dispersion, kperp_sq, z_span, accuracy=None)[source]#

Certify a spatial medium’s z-varying path for every column of a radial grid.

Parameters:
dispersionsolprop.spatial.SpatialDispersion

The medium and the temporal grid, whose active band is certified.

kperp_sqnumpy.ndarray

Transverse wave-number squares in m^-2, for a radial grid k_r**2.

z_spantuple of float

The run path (z0, z1) in m.

accuracyAdiabaticAccuracy or None, optional

The budgets; None takes the defaults.

Returns:
AdiabaticAdmission

The record of a path within budget; a uniform medium is admitted with zero variation.

Raises:
MaterialError

As certify_wave_path().

solprop.adiabatic.certify_wave_path(omega, permittivity, susceptibilities, paths, kperp_sq, z_span, accuracy=None, *, identity=None)[source]#

Certify the columns of a material whose wave-number square is affine in z.

The longitudinal square of every column is \(s = (\omega/c)^2(\varepsilon + \sum_i\rho_i(z)\chi_i) - k_\perp^2\) (the module docstring gives the enclosure).

Parameters:
omeganumpy.ndarray

Finite positive angular frequencies in rad/s, shape (n_omega,).

permittivitynumpy.ndarray

The constant part epsilon of the relative permittivity, shape (n_omega,).

susceptibilitiesnumpy.ndarray

Per-density susceptibility chi_i, in the inverse unit of the paths, shape (n_paths, n_omega).

pathssequence of ZProfile

The densities rho_i(z); each must enclose its variation.

kperp_sqnumpy.ndarray

Transverse wave-number squares in m^-2, finite and nonnegative, shape (n_modes,).

z_spantuple of float

The run path (z0, z1) in m, finite with z0 < z1.

accuracyAdiabaticAccuracy or None, optional

The budgets; None takes the defaults.

identitycollections.abc.Mapping or None, optional

The represented path’s identity, recorded in the admission.

Returns:
AdiabaticAdmission

The record of a path within budget.

Raises:
MaterialError

If a budget is exceeded (naming the worst column, its frequency and the bound), a column crosses q = 0 over the path, the imaginary index varies, a path cannot enclose its variation, or an input is invalid.

Examples

>>> import numpy as np
>>> from solprop.adiabatic import certify_wave_path
>>> from solprop.profiles import Linear
>>> omega = np.array([2.35e15])
>>> admission = certify_wave_path(
...     omega, np.ones(1), np.array([[1e-3]]), [Linear(0.0, 1.0, 1e-3)],
...     np.zeros(1), (0.0, 1e-3))
>>> f"{admission.variation:.6e}"
'2.498751e-04'
solprop.adiabatic.field_error_bound(variation)[source]#

Return the forward-field error bound expm1(Lambda tanh Lambda).

Parameters:
variationfloat or numpy.ndarray

Lambda, half the total variation of ln q, nonnegative.

Returns:
float or numpy.ndarray

The relative complex error bound of the retained forward field.

Examples

>>> from solprop.adiabatic import field_error_bound
>>> float(field_error_bound(1e-9))
1e-18
solprop.adiabatic.reflection_bound(variation)[source]#

Return the reflected-power bound tanh(Lambda)**2.

Parameters:
variationfloat or numpy.ndarray

Lambda, half the total variation of ln q, nonnegative.

Returns:
float or numpy.ndarray

The bound; tanh is accurate to a few ulps for tiny arguments.

Examples

>>> from solprop.adiabatic import reflection_bound
>>> float(reflection_bound(1e-9))
1e-18