solprop.backends.bodies#

Per-element mathematics, written once and compiled for each backend family.

The define_bodies(decorate) factory of docs/dev/backends.md section 3.2: every body is defined inside a function of the compiler decorator and bound to the others through the closure, never through a module global, so one family can never reach another’s dispatcher. Two families exist:

PLAIN

the identity, which is what the coverage lane executes with NUMBA_DISABLE_JIT=1 and what makes the wiring testable without a compiler.

HOST

njit(inline="always"), built by solprop.backends.numba_cpu.kernels from this factory and inlined into its fused kernels.

The formulas are read off solprop.backends.numpy_ref.passes and solprop.translate.ionisation.RateTable rather than re-derived, and the order of operations is preserved: cross-backend agreement at 1e-16 rather than 1e-13 rests on performing the same products in the same order. The floating-point licence is SEP 25’s: the host family’s bodies are inlined and take their kernel’s flags (contraction by default), and the protected bodies (define_bodies’s protect) are compiled strict and called.

Plasma bodies describe one channel’s fraction and loss. Mixtures loop over independent channel states outside these bodies and weight their currents by partial density; neither the body signatures nor their operation order depend on composition.

Why every body carries @no_type_check. The test session installs jaxtyping’s import hook over the whole package (tests/conftest.py), and the hook appends its checker to the end of a function’s decorator list – that is, innermost – so a compiler decorator above it would compile the checker’s wrapper rather than the body. An annotated body fails with UnsupportedBytecodeError: Use of unsupported opcode (DICT_MERGE) raised from the wrapper. @no_type_check is what the hook itself looks for and skips, so the annotations stay readable and statically checked while the compiler sees the function that was written.

Examples#

>>> from solprop.backends.bodies import PLAIN
>>> PLAIN.kerr_real(2.0, 4.0, 0.5)
4.0
>>> PLAIN.propagator_pair(0.0, 0.0)
(1.0, 0.0, 1.0, -0.0)

Module Attributes

FOLD_COMPLETE

A low-storage pass's only evaluation, folded whole (SEP 24 section 4.3).

FOLD_EXCHANGE

The first of a pass's two evaluations, the material response, at the exchange.

FOLD_SECOND

The second of a pass's two evaluations, the in-stage absorber's term.

GENERAL_PAIR_ENTRY

Which stored pair history holds Q_kl, for k and l in 0, 1, 2.

GENERAL_PAIRS

The component pair of each stored history entry, the inverse of the table above.

PLAIN

The interpreted family: what the coverage lane executes and what tests the wiring.

Functions

define_bodies(decorate[, protect])

Return the per-element bodies, compiled by decorate.

Classes

Bodies(spatial_element, slab_element, ...)

The per-element bodies of one compiler family.

RateArrays(coefficients, log_field_min, ...)

The compiled ionisation rate as the flat arrays a kernel can take.

class solprop.backends.bodies.Bodies(spatial_element, slab_element, longitudinal_rate, longitudinal_root, mask_plane_radius, aperture_weight, region_member, propagator_pair, rate_at, magnitude_pair, kerr_real, kerr_analytic, dispersive_isotropic, dispersive_conserving, dispersive_harmonic, dispersive_isotropic3, dispersive_conserving3, dispersive_real_self, dispersive_real_pair, dispersive_real_cross, dispersive_conserving_self, dispersive_conserving_pair, dispersive_conserving_cross, dispersive_harmonic_self, dispersive_harmonic_pair, dispersive_harmonic_cross, held_plasma_source, loss_scale, trapezoid, fraction_at, accumulate, low_storage_fold, raman_drive, raman_tensor_drive, raman_damped, raman_finish, raman_tensor_finish, absorber_sample, envelope_population, envelope_axes, envelope_moments, envelope_loss, general_kerr_component, general_kerr, general_symmetric_row, general_symmetric_sum, general_real_kerr, general_pair_drive, general_delayed)[source]#

Bases: object

The per-element bodies of one compiler family.

Attributes:
spatial_elementcollections.abc.Callable

Exact longitudinal rate and prefactor from shared spatial coefficients.

slab_elementcollections.abc.Callable

The same for a hybrid planar column, its channel’s wall term subtracted last.

longitudinal_ratecollections.abc.Callable

The rate and prefactor of one longitudinal square, which both elements share.

longitudinal_rootcollections.abc.Callable

The principal root of one longitudinal square, its propagating test and its field attenuation, which the rate and the far-field statistics share.

mask_plane_radiuscollections.abc.Callable

A column’s image’s distance from an aperture’s centre in the mask plane, evaluated strictly (SEP 23 equation (4)); protected.

aperture_weightcollections.abc.Callable

One aperture’s transmission at one column and bin, with its exact zeros.

region_membercollections.abc.Callable

Whether a column lies in a half-open box of physical transverse wavevector.

propagator_paircollections.abc.Callable

Both signs of exp(dPhi) from one real exp, one sincos and one reciprocal.

rate_atcollections.abc.Callable

The tabulated ionisation rate at one field amplitude, s^-1.

magnitude_paircollections.abc.Callable

Scaled Euclidean magnitude of two finite real field components.

kerr_realcollections.abc.Callable

The real cubic c rho (sum_q E_q^2) E_p of a field grid.

kerr_analyticcollections.abc.Callable

The analytic cubic of an envelope, as a real and imaginary pair.

dispersive_isotropiccollections.abc.Callable

The isotropic Kleinman contraction of three two-component fields.

dispersive_conservingcollections.abc.Callable

The number-conserving group of three two-component analytic fields.

dispersive_harmoniccollections.abc.Callable

The two harmonic groups of three two-component envelopes.

dispersive_isotropic3collections.abc.Callable

The isotropic Kleinman contraction of three three-component fields.

dispersive_conserving3collections.abc.Callable

The number-conserving group of three three-component analytic fields.

dispersive_real_selfcollections.abc.Callable

The full cubic x^3 of one real component.

dispersive_real_paircollections.abc.Callable

The product x^2 f of one real component.

dispersive_real_crosscollections.abc.Callable

The product x f^2 of one real component.

dispersive_conserving_selfcollections.abc.Callable

The conserving group of (u, u, u), 3 |u|^2 u.

dispersive_conserving_paircollections.abc.Callable

The conserving group of (u, u, f).

dispersive_conserving_crosscollections.abc.Callable

The conserving group of (u, f, f).

dispersive_harmonic_selfcollections.abc.Callable

The harmonic groups of (u, u, u).

dispersive_harmonic_paircollections.abc.Callable

The harmonic groups of (u, u, f).

dispersive_harmonic_crosscollections.abc.Callable

The harmonic groups of (u, f, f).

held_plasma_sourcecollections.abc.Callable

Combine the two held-current spectra in polarisation units on an active bin.

loss_scalecollections.abc.Callable

The guarded coefficient of the ionisation-loss current.

trapezoidcollections.abc.Callable

One increment of a cumulative trapezoid.

fraction_atcollections.abc.Callable

The ionised fraction at one sample of the exposure.

accumulatecollections.abc.Callable

One weighted stage accumulation.

low_storage_foldcollections.abc.Callable

One element of a low-storage RK4IP pass’s finish: a source folded into the three registers.

raman_drivecollections.abc.Callable

Scalar field-square or cycle-averaged envelope drive.

raman_tensor_drivecollections.abc.Callable

Trace, difference and twice-coherence drives of a Cartesian field pair.

raman_dampedcollections.abc.Callable

One undamped Raman sample times its exponential decay.

raman_finishcollections.abc.Callable

Delayed polarisation addition followed by the temporal collar.

raman_tensor_finishcollections.abc.Callable

One component of the delayed tensor polarisation and temporal collar.

absorber_samplecollections.abc.Callable

Temporal absorption as an in-stage rate or an accepted-step exponential.

envelope_populationcollections.abc.Callable

Return stable ionised fraction and surviving neutral fraction from exposure.

envelope_axescollections.abc.Callable

Scaled real Gram decomposition of a complex Cartesian envelope.

envelope_momentscollections.abc.Callable

Refined positive directional moments and a convergence status.

envelope_losscollections.abc.Callable

Two complex current components from the directional moments.

general_kerr_componentcollections.abc.Callable

One component of the instantaneous tensor contraction from a pair history.

general_kerrcollections.abc.Callable

A general modal guide’s instantaneous tensor cubic at one node and sample, densely, on the analytic signal.

general_symmetric_rowcollections.abc.Callable

One component’s coefficients of the real cubic’s symmetric contraction.

general_symmetric_sumcollections.abc.Callable

One component of the symmetric contraction from its coefficients and the monomials.

general_real_kerrcollections.abc.Callable

The real cubic by its symmetric contraction at one node and sample.

general_pair_drivecollections.abc.Callable

One entry of the real symmetric pair history a delayed tensor response is driven by.

general_delayedcollections.abc.Callable

One component of the delayed tensor contraction at one node and sample.

absorber_sample: Any#
accumulate: Any#
aperture_weight: Any#
dispersive_conserving: Any#
dispersive_conserving3: Any#
dispersive_conserving_cross: Any#
dispersive_conserving_pair: Any#
dispersive_conserving_self: Any#
dispersive_harmonic: Any#
dispersive_harmonic_cross: Any#
dispersive_harmonic_pair: Any#
dispersive_harmonic_self: Any#
dispersive_isotropic: Any#
dispersive_isotropic3: Any#
dispersive_real_cross: Any#
dispersive_real_pair: Any#
dispersive_real_self: Any#
envelope_axes: Any#
envelope_loss: Any#
envelope_moments: Any#
envelope_population: Any#
fraction_at: Any#
general_delayed: Any#
general_kerr: Any#
general_kerr_component: Any#
general_pair_drive: Any#
general_real_kerr: Any#
general_symmetric_row: Any#
general_symmetric_sum: Any#
held_plasma_source: Any#
kerr_analytic: Any#
kerr_real: Any#
longitudinal_rate: Any#
longitudinal_root: Any#
loss_scale: Any#
low_storage_fold: Any#
magnitude_pair: Any#
mask_plane_radius: Any#
propagator_pair: Any#
raman_damped: Any#
raman_drive: Any#
raman_finish: Any#
raman_tensor_drive: Any#
raman_tensor_finish: Any#
rate_at: Any#
region_member: Any#
slab_element: Any#
spatial_element: Any#
trapezoid: Any#
solprop.backends.bodies.FOLD_COMPLETE = 0#

A low-storage pass’s only evaluation, folded whole (SEP 24 section 4.3).

solprop.backends.bodies.FOLD_EXCHANGE = 1#

The first of a pass’s two evaluations, the material response, at the exchange.

solprop.backends.bodies.FOLD_SECOND = 2#

The second of a pass’s two evaluations, the in-stage absorber’s term.

solprop.backends.bodies.GENERAL_PAIRS = ((0, 0), (1, 1), (2, 2), (0, 1), (0, 2), (1, 2))#

The component pair of each stored history entry, the inverse of the table above.

solprop.backends.bodies.GENERAL_PAIR_ENTRY = ((0, 3, 4), (3, 1, 5), (4, 5, 2))#

Which stored pair history holds Q_kl, for k and l in 0, 1, 2.

The six independent entries of a real symmetric three-by-three history are stored in the order xx, yy, zz, xy, xz, yz, the order of solprop.backends.numpy_ref.general_modal.PAIR_HISTORIES’ documentation.

solprop.backends.bodies.PLAIN = Bodies(spatial_element=<function define_bodies.<locals>.spatial_element>, slab_element=<function define_bodies.<locals>.slab_element>, longitudinal_rate=<function define_bodies.<locals>.longitudinal_rate>, longitudinal_root=<function define_bodies.<locals>.longitudinal_root>, mask_plane_radius=<function define_bodies.<locals>.mask_plane_radius>, aperture_weight=<function define_bodies.<locals>.aperture_weight>, region_member=<function define_bodies.<locals>.region_member>, propagator_pair=<function define_bodies.<locals>.propagator_pair>, rate_at=<function define_bodies.<locals>.rate_at>, magnitude_pair=<function define_bodies.<locals>.magnitude_pair>, kerr_real=<function define_bodies.<locals>.kerr_real>, kerr_analytic=<function define_bodies.<locals>.kerr_analytic>, dispersive_isotropic=<function define_bodies.<locals>.dispersive_isotropic>, dispersive_conserving=<function define_bodies.<locals>.dispersive_conserving>, dispersive_harmonic=<function define_bodies.<locals>.dispersive_harmonic>, dispersive_isotropic3=<function define_bodies.<locals>.dispersive_isotropic3>, dispersive_conserving3=<function define_bodies.<locals>.dispersive_conserving3>, dispersive_real_self=<function define_bodies.<locals>.dispersive_real_self>, dispersive_real_pair=<function define_bodies.<locals>.dispersive_real_pair>, dispersive_real_cross=<function define_bodies.<locals>.dispersive_real_cross>, dispersive_conserving_self=<function define_bodies.<locals>.dispersive_conserving_self>, dispersive_conserving_pair=<function define_bodies.<locals>.dispersive_conserving_pair>, dispersive_conserving_cross=<function define_bodies.<locals>.dispersive_conserving_cross>, dispersive_harmonic_self=<function define_bodies.<locals>.dispersive_harmonic_self>, dispersive_harmonic_pair=<function define_bodies.<locals>.dispersive_harmonic_pair>, dispersive_harmonic_cross=<function define_bodies.<locals>.dispersive_harmonic_cross>, held_plasma_source=<function define_bodies.<locals>.held_plasma_source>, loss_scale=<function define_bodies.<locals>.loss_scale>, trapezoid=<function define_bodies.<locals>.trapezoid>, fraction_at=<function define_bodies.<locals>.fraction_at>, accumulate=<function define_bodies.<locals>.accumulate>, low_storage_fold=<function define_bodies.<locals>.low_storage_fold>, raman_drive=<function define_bodies.<locals>.raman_drive>, raman_tensor_drive=<function define_bodies.<locals>.raman_tensor_drive>, raman_damped=<function define_bodies.<locals>.raman_damped>, raman_finish=<function define_bodies.<locals>.raman_finish>, raman_tensor_finish=<function define_bodies.<locals>.raman_tensor_finish>, absorber_sample=<function define_bodies.<locals>.absorber_sample>, envelope_population=<function define_bodies.<locals>.envelope_population>, envelope_axes=<function define_bodies.<locals>.envelope_axes>, envelope_moments=<function define_bodies.<locals>.envelope_moments>, envelope_loss=<function define_bodies.<locals>.envelope_loss>, general_kerr_component=<function define_bodies.<locals>.general_kerr_component>, general_kerr=<function define_bodies.<locals>.general_kerr>, general_symmetric_row=<function define_bodies.<locals>.general_symmetric_row>, general_symmetric_sum=<function define_bodies.<locals>.general_symmetric_sum>, general_real_kerr=<function define_bodies.<locals>.general_real_kerr>, general_pair_drive=<function define_bodies.<locals>.general_pair_drive>, general_delayed=<function define_bodies.<locals>.general_delayed>)#

The interpreted family: what the coverage lane executes and what tests the wiring.

class solprop.backends.bodies.RateArrays(coefficients, log_field_min, d_log_field, field_min, field_max, rate_max)[source]#

Bases: NamedTuple

The compiled ionisation rate as the flat arrays a kernel can take.

solprop.translate.ionisation.RateTable is a frozen dataclass a compiled kernel cannot accept; these are the same numbers, in the order the interpolant uses them.

Attributes:
coefficientsnumpy.ndarray

Cubic spline coefficients, shape (4, n_intervals), highest power first.

log_field_minfloat

Natural logarithm of the first knot’s field amplitude, the field in V/m.

d_log_fieldfloat

Knot spacing in log E, positive.

field_minfloat

Field amplitude below which the rate is exactly zero, V/m.

field_maxfloat

Field amplitude above which the rate is held at rate_max, V/m.

rate_maxfloat

The rate at field_max, s^-1.

coefficients: Any#

Alias for field number 0

d_log_field: float#

Alias for field number 2

field_max: float#

Alias for field number 4

field_min: float#

Alias for field number 3

log_field_min: float#

Alias for field number 1

classmethod of(table)[source]#

Bundle a compiled rate table into the arrays a kernel takes.

Parameters:
tablesolprop.translate.ionisation.RateTable

The table the kernel problem carries.

Returns:
RateArrays

The same numbers, in the layout a kernel accepts.

rate_max: float#

Alias for field number 5

solprop.backends.bodies.define_bodies(decorate, protect=None)[source]#

Return the per-element bodies, compiled by decorate.

Parameters:
decoratecollections.abc.Callable

The compiler decorator: njit(inline="always") for the host family and the identity for the plain family.

protectcollections.abc.Callable, optional

The decorator of the protected bodies, which form a small difference or rely on an exact cancellation (SEP 25 section 4.2): the population maps fraction_at and envelope_population, and the ellipse resolution and moments of envelope_axes and envelope_moments, whose determinant xr yi - xi yr must vanish for a linear field; and the far-field statistics’ mask_plane_radius, whose hard-edge decisions must be the reference’s exactly (SEP 23 section 6). The host family passes njit(strict=True): compiled on their own without fastmath flags and called, never inlined, since an inlined body takes its caller’s flags. None uses decorate.

Returns:
Bodies

The family, whose members are bound to each other through this closure.

Examples

>>> from solprop.backends.bodies import define_bodies
>>> plain = define_bodies(lambda function: function)
>>> plain.trapezoid(2.0, 4.0, 0.5)
1.5