solprop.backends.numpy_ref.admission#

The general modal route’s and the coupled flow’s admission, for every backend.

One list, run by each backend under its own name: numpy_ref calls refuse_general_route() from its own admission, the native backend calls it from its adapter, and numba_cpu runs the same checks. A combination admitted or refused here is admitted or refused on every backend that calls it, and each refusal names the calling backend and the leaf, so a new refusal is written once and cannot drift between copies.

What a backend has not built is said with flow_methods: the section methods of linear.coupled_flow it executes. A section method outside them is refused by name before anything is allocated. Everything else – the batch axis, a backend’s own kernels’ limits – stays with the backend that has the limit.

The list runs before solprop.translate.problem.KernelProblem.validate() and before any buffer is allocated, and repeats checks the translation layer also makes, because a problem can be assembled by something other than solprop.translate.problem.assemble() and a backend does not rely on a caller having been careful.

Module Attributes

FLOW_METHODS

Every section method of linear.coupled_flow the reference executes.

Functions

refuse_coupled_flow(problem, *[, backend, ...])

Refuse, by name, every coupled flow the calling backend does not execute.

refuse_general_route(problem, *[, backend, ...])

Refuse, by name, every general modal or coupled-flow problem not executed.

solprop.backends.numpy_ref.admission.FLOW_METHODS: Final[tuple[Literal['diagonal', 'constant_schur', 'frozen_residual', 'cf4'], ...]] = ('constant_schur', 'frozen_residual', 'cf4')#

Every section method of linear.coupled_flow the reference executes.

"diagonal" is not among them: it is the existing cumulative flow and needs no leaf. A backend that executes fewer passes its own subset to refuse_coupled_flow(); "cf4" is executed by the reference alone: it is not yet implemented on the compiled backends.

solprop.backends.numpy_ref.admission.refuse_coupled_flow(problem, *, backend='numpy_ref', flow_methods=('constant_schur', 'frozen_residual', 'cf4'))[source]#

Refuse, by name, every coupled flow the calling backend does not execute.

The reference executes exactly two combinations: the dense generator of one constant section with no connection and no residual, by a Schur matrix-function action, and a varying flow whose every section is "frozen_residual" or "cf4" – the dense generator at any degree along z and an optional connection, a frozen-residual section by the Schur action of its frozen block with a residual the interaction-picture source carries explicitly, and a CF4 section by the commutator-free exponentials of its whole generator with none. A backend’s flow_methods narrows that; naming linear.coupled_flow among a backend’s admitted leaves says only that the field may be present, and this says which contents are executed: every other method, representation, mixture of the two and certificate row is named here rather than silently ignored.

Parameters:
problemsolprop.translate.problem.KernelProblem

The problem to check.

backendstr, optional

The registry name each refusal names.

flow_methodscollection of str, optional

The section methods the backend executes (FLOW_METHODS by default).

Raises:
BackendError

Naming the part of the leaf, or of the problem around it, it cannot execute.

solprop.backends.numpy_ref.admission.refuse_general_route(problem, *, backend='numpy_ref', flow_methods=('constant_schur', 'frozen_residual', 'cf4'), moving_maps=False)[source]#

Refuse, by name, every general modal or coupled-flow problem not executed.

The coupled flow first: a metric or a table beside it is this route’s refusal to make, not the general route’s, and its message names the flow (refuse_coupled_flow()). Then the general modal route: a field grid, one channel axis and no state polarisation axis, the tables’ own execution maps of a constant guide, an identity metric or the dense metric of a declared unitary change of basis of one, the constant unit power weight, no legacy response beside the route’s own, and per-region responses the route executes (refuse_regional_responses, in solprop.backends.numpy_ref.general_modal). A problem carrying none of the four general-modal leaves passes untouched.

Parameters:
problemsolprop.translate.problem.KernelProblem

The problem to check.

backendstr, optional

The registry name each refusal names.

flow_methodscollection of str, optional

The section methods of linear.coupled_flow the backend executes; every one of FLOW_METHODS by default, which is the reference’s own list.

moving_mapsbool, optional

Whether the backend executes a moving guide’s maps – synthesis and projection of more than one coefficient along z, combined per stage over the bundle’s transform_weights (kernel schema 14). False by default, so a backend that has not built them refuses them by name whatever else it admits; numpy_ref, numba_cpu and the native backend pass True.

Raises:
BackendError

Naming the calling backend and what it does not execute.

Examples

>>> from solprop.backends.numpy_ref.admission import refuse_general_route
>>> from solprop.grid import EnvelopeGrid
>>> from solprop.nonlinear.gnlse import problem_from
>>> from solprop.pulses import SechPulse
>>> from solprop.stepper import PIController
>>> from solprop.translate.problem import assemble
>>> grid = EnvelopeGrid.from_limits(1.0, 835e-9, (500e-9, 2e-6), 1e-12)
>>> gnlse = problem_from([0.0, 0.0, -1.183e-26], omega_ref=grid.omega0,
...                      gamma=0.11, shock=False)
>>> start = SechPulse(wavelength=835e-9, width=100e-15, peak_power=9.8).build(grid)
>>> problem = assemble(grid, gnlse.mode, [gnlse.kerr], start,
...                    controller=PIController(rtol=1e-8, atol=1e-16),
...                    save_planes=[0.01], dz_max=0.01, dz_init=1e-3,
...                    density=1.0, shock=False, prefactor_index=1.0)
>>> refuse_general_route(problem, backend="native") is None
True