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 saying what to install.

The native backend is a second distribution, solprop-native, built from native/ in this repository and a required dependency; probing availability does not import it. Automatic selection is that backend, with no fallback (SEP 43). It refuses when the package is absent or this processor is below the installed build’s CPU baseline, using the package’s own check (solprop_native._cpu), loaded by path and read from the same code that refuses the import. Import, compatibility and construction errors remain visible, and they never trigger different arithmetic.

Module Attributes

BACKENDS

The backends this package knows, by name.

REMOVED_BACKENDS

What to say about a backend that no longer exists, by the name it had.

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.

REQUIRE_DEVICE_SETTING

Where a run must execute: cuda, hip or any; unset for no requirement.

Functions

available([precision])

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

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=()), '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', 'native')#

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

numpy_ref always does; 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.REMOVED_BACKENDS: Mapping[str, str] = {'numba_cpu': "the numba_cpu backend was removed in SEP 43: use backend='native', the solprop-native package, or backend='numpy_ref', the reference, which is unthreaded and far slower. Output and snapshots that record numba_cpu still load"}#

What to say about a backend that no longer exists, by the name it had.

solprop.backends.registry.REQUIRE_DEVICE_SETTING: Final = 'SOLPROP_REQUIRE_DEVICE'#

Where a run must execute: cuda, hip or any; unset for no requirement.

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.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" is "native", and has no fallback: it refuses if solprop_native can’t be found or this processor doesn’t meet the installed build’s CPU baseline. Other names pass through unchanged, but for a removed backend (REMOVED_BACKENDS).

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.

Raises:
BackendError

If name is a removed backend, or "auto" has nothing to select; the message says what to do.

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" for the native backend, with no fallback (resolve_name()).

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 says what to install.

Examples

>>> from solprop.backends.registry import BACKENDS
>>> sorted(BACKENDS)
['mlx', 'native', '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("numpy_ref", ["energy", "beam_spectrum"]) is None
True