solprop.backends.registry#

Selecting a backend by name, and saying why one is not usable.

docs/dev/backends.md section 1: selection is by name, availability is detected with importlib.util.find_spec() and never cached. The errors are two-tier, because the two failures need different answers from the reader: a name this package has never heard of is a ValueError listing what is usable, and a known name whose dependencies are missing is an ImportError naming the extra to install.

The native backend is a second distribution, solprop-native, built from native/ in this repository and installed with the native extra; probing availability does not import it. Automatic selection prefers it when installed and otherwise chooses Numba CPU. Import, compatibility and construction errors remain visible; they never trigger a fallback to different arithmetic, with one exception. A distribution build of solprop-native is compiled for a CPU baseline, and on a processor below it automatic selection chooses Numba CPU with a SolpropWarning, once per process. It finds that out without importing the package: it loads the package’s own pure-Python processor check (solprop_native/_cpu.py) by path and runs it, so the check that refuses the import and the one that chooses the fallback are one code. An explicit backend="native" still raises the package’s refusal.

Module Attributes

BACKENDS

The backends this package knows, by name.

SINGLE_ONLY

The backends that compute in binary32 only (SEP 33): Apple GPUs have no binary64.

FAR_FIELD_BACKENDS

The backends that form the far-field statistics of SEP 23.

Functions

available([precision])

Return the names of the backends that can run a precision here and now.

available_device_memory(name)

Return a backend's free accelerator bytes before it is constructed.

metal_available()

Return whether the mlx backend can run on a Metal GPU here (SEP 33, Q8).

resolve_name([name])

Resolve automatic selection to an installed backend's registry name.

select(name, problem, *[, grid, modes, ...])

Construct the named backend for a validated kernel problem.

select_batch(owners)

Select batch arithmetic without substituting a different backend.

statistics_refusal(name, names)

Return why a backend cannot form some of the statistics named, or None.

Classes

BackendEntry(requires, extras)

What a backend needs before it can be constructed.

solprop.backends.registry.BACKENDS: Mapping[str, BackendEntry] = {'mlx': BackendEntry(requires=('mlx',), extras=('mlx',)), 'native': BackendEntry(requires=('solprop_native',), extras=()), 'numba_cpu': BackendEntry(requires=('numba', 'pyfftw'), extras=()), 'numpy_ref': BackendEntry(requires=(), extras=())}#

The backends this package knows, by name.

class solprop.backends.registry.BackendEntry(requires, extras)[source]#

Bases: object

What a backend needs before it can be constructed.

Attributes:
requirestuple of str

Importable module names that must be present. Empty for a backend that needs nothing beyond the package’s own dependencies.

extrastuple of str

The optional-dependency groups that supply requires, for the error message.

extras: tuple[str, ...]#
requires: tuple[str, ...]#
solprop.backends.registry.FAR_FIELD_BACKENDS: tuple[str, ...] = ('numpy_ref', 'numba_cpu', 'native')#

The backends that form the far-field statistics of SEP 23.

numpy_ref and numba_cpu always do; the native backend does from SEP 23’s third phase, which a build declares by its backend’s far_field_statistics attribute. An older build is refused them by name on this side of the seam (statistics_refusal()), before it is built.

solprop.backends.registry.SINGLE_ONLY: frozenset[str] = frozenset({'mlx'})#

The backends that compute in binary32 only (SEP 33): Apple GPUs have no binary64.

solprop.backends.registry.available(precision='double')[source]#

Return the names of the backends that can run a precision here and now.

Detection is by importlib.util.find_spec(), so nothing is imported and nothing is cached: a backend whose optional dependency is installed while the process runs becomes available without a restart, and initializing a native runtime is never a side effect of asking.

Parameters:
precision{‘double’, ‘single’}, optional

The arithmetic asked for (SEP 33). "double", the default, lists the binary64 backends, which leaves out mlx; "single" lists those that admit single precision (solprop.translate.precision.SINGLE_PRECISION_BACKENDS).

Returns:
tuple of str

The usable names, in the table’s order.

Examples

>>> from solprop.backends.registry import available
>>> "numpy_ref" in available()
True
solprop.backends.registry.available_device_memory(name)[source]#

Return a backend’s free accelerator bytes before it is constructed.

The driver admits a run’s persistent memory against them before the backend allocates (solprop.driver.memory.admit_memory()). Only the native backend reports them, and only a device build; asking imports the plugin, as selecting it would.

Parameters:
namestr

A concrete registry name.

Returns:
int or None

Free bytes on the selected accelerator, or None for a host backend, a host build or a plugin that does not report them.

Examples

>>> from solprop.backends.registry import available_device_memory
>>> available_device_memory("numpy_ref") is None
True
solprop.backends.registry.metal_available()[source]#

Return whether the mlx backend can run on a Metal GPU here (SEP 33, Q8).

Imports MLX only when it is installed: asking on another platform imports nothing.

Returns:
bool

True when MLX is installed and reports a Metal device.

solprop.backends.registry.resolve_name(name='auto')[source]#

Resolve automatic selection to an installed backend’s registry name.

Parameters:
namestr, optional

"auto" prefers "native" when solprop_native can be found and this processor meets the installed build’s CPU baseline, otherwise "numba_cpu". Explicit names pass through unchanged.

Returns:
str

Concrete selection to store in simulation settings. This uncached probe does not import a backend or initialize a native runtime. select() validates the name and constructs the backend; failures there never cause a fallback.

Warns:
SolpropWarning

Once per process, when "auto" passes over an installed native build because this processor lacks features of its CPU baseline.

Examples

>>> resolve_name("numpy_ref")
'numpy_ref'
solprop.backends.registry.select(name, problem, *, grid=None, modes=None, profiles=None, tdse_binding=None)[source]#

Construct the named backend for a validated kernel problem.

Parameters:
namestr

The backend’s registry name, for example "numpy_ref", or "auto" to prefer the installed native backend and otherwise use Numba CPU.

problemsolprop.translate.problem.KernelProblem

The problem to step. The backend validates it again.

gridsolprop.grid.TimeGrid, optional

The grid the state lives on. Statistics need it and the kernel contract does not carry it, so it is passed alongside rather than inside the problem.

modescollections.abc.Sequence, optional

The propagated modes, in state order, for the statistics that need them.

profilescollections.abc.Mapping, optional

The z-profiles keyed by statistic name, for the profile statistics.

tdse_bindingsolprop.translate.tdse.TDSEBinding or None, optional

Driver-owned host response binding for a TDSE problem on NumPy.

Returns:
Backend

The constructed backend.

Raises:
ValueError

If name is not a backend this package knows; the message lists what is usable.

BackendError

If name is a backend that has been removed, or one that does not form a statistic the problem asks for; the message says what to use instead.

ImportError

If name is known but its dependencies are missing; the message names the extra to install.

Examples

>>> from solprop.backends.registry import BACKENDS
>>> sorted(BACKENDS)
['mlx', 'native', 'numba_cpu', 'numpy_ref']
solprop.backends.registry.select_batch(owners)[source]#

Select batch arithmetic without substituting a different backend.

Parameters:
ownerssequence of solprop.backends.protocol.Backend

Compatible, loaded member owners.

Returns:
BatchBackend

Common fixed march using the selected backend’s arithmetic.

Raises:
BackendError

If the backend does not expose the shared step-driver contract.

solprop.backends.registry.statistics_refusal(name, names)[source]#

Return why a backend cannot form some of the statistics named, or None.

Asking about the native backend for a far-field statistic imports the installed plugin, as selecting it would, to read which far-field statistics it declares.

Parameters:
namestr

The resolved backend name.

namescollections.abc.Sequence of str

The statistics asked for.

Returns:
str or None

The refusal, naming the backends that do form them, or None when the backend forms every one (or is not installed, which selecting it reports).

Examples

>>> from solprop.backends.registry import statistics_refusal
>>> statistics_refusal("numba_cpu", ["energy", "beam_spectrum"]) is None
True