solprop.backends.numba_cpu.coupled_flow#
The coupled flow of a coherent wall or a split block, on the CPU backend.
The second execution path of the reference’s linear.coupled_flow – the
constant-Schur section (the scalar wall, the TE/TM wall and the split block on the
general route) and the varying "frozen_residual" flow with its explicit residual in
the Runge-Kutta source. A "cf4" section is refused by name: the fourth-order
commutator-free flow is not yet implemented on the compiled backends.
What is host-side and what is compiled. The Schur decomposition of every
section’s frozen block is the reference’s own code, run on the host once at
construction (solprop.backends.numpy_ref.backend._coupled_flow_maps), and so is
the eigenbasis of each triangular factor
(solprop.translate.coupled.schur_eigenbasis()), shared with the native backend.
The actions U = Z exp(l T) Z^H and U^-1 = Z exp(-l T) Z^H of every stage
length, and the certificate’s measured norm(U) norm(U^-1), are formed by compiled
kernels into the held buffers whenever a step’s section or length changes, exactly
when the reference’s own memo re-forms them:
form_flow_actions() takes each bin by its eigenbasis, W exp(l Lambda) Y, or
– where that basis is ill-conditioned, a nearly degenerate nonnormal pair – by the
reference’s own scaling, sixteen-term series and squaring, and
flow_conditioning() measures both spectral norms by a Jacobi iteration on the
Gram matrix. The decision is the reference’s (_refuse_flow_conditioning), in its
words. The matrices are no longer the reference’s to the last bit; their departure
is bounded in tests/flow_parity.py (the formation bound) and carried through the
step’s parity bound. An adaptive run, which changes its length every step, re-forms
the actions every trial; forming them on the host spent 44 to 68 % of such a step
there, this spends about one per cent.
What is compiled is every traversal of the state: the stage combination mixed by the forward action, the pad onto the transform grid, the explicit residual’s combination over the stage weights and its application, the return to the interaction variable by the inverse action with both accumulations, and the accept pass with the error norm’s partials. None of them allocates.
Parity is a rounding statement (SEP 25). The matrices are within the formation
bound of the reference’s, and each pass’s sums – the stage combination over the
previous stages, each action’s channel sum, the residual’s weighted sum over the terms
– are this backend’s own order, held with the matrices to the parity bound of
tests/flow_parity.py, never to the reference’s bits. The combination, the
accumulation and the accept pass thread over bins (columns for the accept) on a state
of at least FLOW_ELEMENTS elements (flow_kernels()).
Module Attributes
The coupled flow's ledger rows, named on every route and zero where it is absent. |
|
State size from which the flow's stage combination, accumulation and accept thread. |
Functions
|
Take the accept pass through the whole step's flow, with the norm's partials. |
|
Carry a stage's source back by |
|
Form one stage's lab-frame input with the forward flow action. |
|
Measure |
|
Choose the serial or the threaded combination, accumulation and accept pass. |
|
Scatter the lab-frame input onto a transform grid, zeroing the rest. |
|
Form the forward and inverse actions of one section at every stage fraction. |
|
Compile the stage's source before the inverse action: crop, frame, residual. |
|
Form the explicit residual |
Classes
|
The coupled flow's held factors, actions and buffers, allocated once. |
- solprop.backends.numba_cpu.coupled_flow.FLOW_ELEMENTS = 32768#
State size from which the flow’s stage combination, accumulation and accept thread.
Every bin of the combination and the accumulation is independent, and the accept pass sums each column on its own, so the parallel variants (a
prangeover bins, and over columns for the accept) agree with the serial ones bin by bin. Measured on six threads of an Apple-silicon laptop under load, microseconds serial -> threaded: 4 channels x 8192 bins, combination 1121 -> 192, accumulation 330 -> 99, accept 352 -> 123; 8 x 16384, 10025 -> 2671, 1611 -> 351, 2862 -> 831; 2 x 4096 the accumulation and the accept were slower threaded (18 -> 52, 43 -> 62).
- solprop.backends.numba_cpu.coupled_flow.FLOW_LEDGER_ROWS = ('coupled_flow_factors', 'coupled_flow_residual_terms', 'coupled_flow_actions', 'coupled_flow_eigenbasis', 'coupled_flow_formation', 'coupled_flow_residual_action', 'coupled_flow_lab', 'coupled_flow_drive', 'coupled_flow_error', 'coupled_flow_slots')#
The coupled flow’s ledger rows, named on every route and zero where it is absent.
The first three are the reference’s rows with the reference’s sizes: the Schur factors and frozen blocks of every section, the residual’s terms, and one forward and inverse action per distinct stage fraction. The rest are this backend’s own: every section’s eigenbasis with its route and row-sum norm, the formation kernels’ scratch and the measured conditioning, the stage’s residual block, the lab-frame stage input the residual and the pad both read, the stage’s source before the inverse action, the accepted step’s mixed error and the two bin-to-block indices, the actions’ and the residual’s, which leaves out the bins the error norm does not score.
- class solprop.backends.numba_cpu.coupled_flow.FlowWorkspace(problem, fractions, *, contiguous, absorber)[source]#
Bases:
objectThe coupled flow’s held factors, actions and buffers, allocated once.
- Parameters:
- problemsolprop.translate.problem.KernelProblem
A problem the backend has admitted, carrying
linear.coupled_flow.- fractionsnumpy.ndarray
The step’s distinct stage fractions in increasing order, the backend’s own propagator slots; an action pair is held per fraction.
- contiguousbool
Whether the crop index is the leading block of the transform grid.
- absorberbool
Whether the in-stage absorber contributes a term.
- form_residual(weights)[source]#
Form the stage’s explicit residual into
block, when there is one.A constant-Schur section has none and forms nothing, as in the reference, whose
_residualreturnsNonethere rather than multiplying by zero.- Parameters:
- weightsnumpy.ndarray or None
The stage bundle’s
flow_weights, which every stage of a problem carrying a flow has.
- memory_ledger()[source]#
Return the size of every buffer the flow holds, in bytes.
- Returns:
- dict
Every row of
FLOW_LEDGER_ROWS.
- prepare(section, dz)[source]#
Hold the forward and inverse actions of one step, re-formed on a change.
The reference’s memo (
NumpyRefBackend._flow_actions): the generator is frozen across the step, so an action depends on the stage fraction only through the lengthc_i dz, and the pairs survive between steps for the one section and length last seen. A step that crosses into the next section re-forms them, which is the cache invalidation that makes a section edge a kink of the flow. The whole step’s pair is checked against the certificate’s declared conditioning, which bounds every shorter one. The pairs are formed byform_flow_actions()and measured byflow_conditioning()into the held buffers, so a new length allocates nothing either.- Parameters:
- sectionint
The section the step’s anchor lies in, from the step bundle’s
flow_section.- dzfloat
The trial step, m.
- Raises:
- BackendError
If a pair needs more squarings than admitted, or the whole step’s measured conditioning exceeds the declared bound, in the reference’s words under this backend’s name.
- solprop.backends.numba_cpu.coupled_flow.flow_accept(state, propagator, dz, solution, error, action, slots, mask, advanced, mixed_error, partials)[source]#
Take the accept pass through the whole step’s flow, with the norm’s partials.
The reference’s
exp(dPhi) (U a + dz U s)and the norm ofexp(dPhi) (dz U e): the action is applied to the state, the solution sum and the error sum separately, and the error norm’s|y|^2is of the state before the action, as the reference’serror_normtakes it. The mixed error is kept, because a weighted controller’s second traversal reads it.- Parameters:
- statenumpy.ndarray
The state at the start of the step.
- propagatornumpy.ndarray
exp(dPhi)over the whole step.- dzfloat
The step, m.
- solutionnumpy.ndarray
The weighted stage sum of the solution.
- errornumpy.ndarray
The weighted stage sum of the embedded difference.
- actionnumpy.ndarray
Uover the whole step, on the active bins.- slotsnumpy.ndarray
Each bin’s row of action, or
-1.- masknumpy.ndarray
The in-band mask the norm is taken over.
- advancednumpy.ndarray
Written with the state at the end of the step.
- mixed_errornumpy.ndarray
Written with
U e.- partialsnumpy.ndarray
Written with the three sums per column, shape
(3, n_columns).
- solprop.backends.numba_cpu.coupled_flow.flow_accumulate(drive, action, slots, mix, weight, error_weight, stage, solution, error)[source]#
Carry a stage’s source back by
U_i^-1and accumulate it into both sums.- Parameters:
- drivenumpy.ndarray
The source from the finish kernel.
- actionnumpy.ndarray
U_i^-1on the active bins.- slotsnumpy.ndarray
Each bin’s row of action, or
-1.- mixbool
False at the zero fraction, where the action is the identity.
- weightfloat
The tableau’s solution weight for this stage.
- error_weightfloat
The tableau’s embedded-difference weight.
- stagenumpy.ndarray
Written with the stage derivative.
- solutionnumpy.ndarray
Accumulated into.
- errornumpy.ndarray
Accumulated into.
- solprop.backends.numba_cpu.coupled_flow.flow_combine(state, stages, weights, n_previous, dz, propagator, action, slots, mix, lab)[source]#
Form one stage’s lab-frame input with the forward flow action.
The reference’s
exp(dPhi_i) (U_i a + dz U_i sum_j a_ij k_j): the action is applied to the state and to the stage combination separately, as the reference’s_channelsdoes, and the combination is summed over the previous stages from zero in tableau order. A bin the block does not cover, and every bin at the zero fraction, is the diagonal route’s own expression.- Parameters:
- statenumpy.ndarray
The state at the start of the step, complex, shape
(n_columns, n_omega).- stagesnumpy.ndarray
The stage derivatives so far.
- weightsnumpy.ndarray
The tableau row for this stage.
- n_previousint
How many stages the row combines.
- dzfloat
The step, m.
- propagatornumpy.ndarray
exp(dPhi_i)for this stage.- actionnumpy.ndarray
U_ion the active bins, shape(n_active, n_columns, n_columns).- slotsnumpy.ndarray
Each bin’s row of action, or
-1off the block.- mixbool
False at the zero fraction, where the action is the identity.
- labnumpy.ndarray
Written with the lab-frame stage input.
- solprop.backends.numba_cpu.coupled_flow.flow_conditioning(forward, inverse, gram, measured)[source]#
Measure
norm(U)_2 norm(U^-1)_2of the whole step’s actions per bin.The certificate’s measurement (
_check_flow_conditioning), each spectral norm by_spectral_norm, within a fewn uof the singular value the reference takes and never below it by more than the rotations’ rounding; the comparison with the declared row is the reference’s own.- Parameters:
- forward, inversenumpy.ndarray
The whole step’s actions per active bin.
- gramnumpy.ndarray
Scratch, one
n x nblock.- measurednumpy.ndarray
Written with the product per bin.
- solprop.backends.numba_cpu.coupled_flow.flow_kernels(threads, n_columns, n_omega)[source]#
Choose the serial or the threaded combination, accumulation and accept pass.
- Parameters:
- threadsint
Threads the kernel pool has.
- n_columnsint
Columns of the state.
- n_omegaint
Bins per column.
- Returns:
- tuple
flow_combine(),flow_accumulate()andflow_accept(), or their parallel variants for a state of at leastFLOW_ELEMENTS.
Examples
>>> from solprop.backends.numba_cpu import coupled_flow >>> coupled_flow.flow_kernels(1, 4, 8192)[0] is coupled_flow.flow_combine True
- solprop.backends.numba_cpu.coupled_flow.flow_pad(lab, crop, fine, scale)[source]#
Scatter the lab-frame input onto a transform grid, zeroing the rest.
The pad of
solprop.backends.numba_cpu.kernels.make_combine_and_pad()on an input the flow has already formed: the whole of fine is written, because a complex-to-real plan destroys its input while it executes.- Parameters:
- labnumpy.ndarray
The lab-frame stage input.
- cropnumpy.ndarray
Where each coarse bin sits on the grid,
numpy.intp.- finenumpy.ndarray
Written with the padded spectrum.
- scalefloat
The inverse transform’s
1 / n_to, or one for the general route’s coarse buffer.
- solprop.backends.numba_cpu.coupled_flow.form_flow_actions(fractions, dz, left, right, eigenvalues, route, vectors, triangular, forward, inverse, exponents, work)[source]#
Form the forward and inverse actions of one section at every stage fraction.
On a bin whose eigenbasis is well conditioned (
route),U(l) = W exp(l Lambda) YandU(-l) = W exp(-l Lambda) Y: each entrysum_k (W_ik e_k) Y_kjfrom zero in increasingk, withe_kfrom one real exponential and one cosine and sine ofl lambda_k, shared by the pair. Elsewhere the reference’s scaling and squaring (_squared_series_action). A zero fraction is the identity and is left untouched, as the backend never applies it.- Parameters:
- fractionsnumpy.ndarray
The distinct stage fractions, dimensionless.
- dzfloat
The step, m; the lengths are
fraction * dz, as the reference forms them.- left, rightnumpy.ndarray
The section’s
WandYper active bin.- eigenvaluesnumpy.ndarray
The section’s
lambdaper active bin, 1/m.- routenumpy.ndarray
True where a bin takes its eigenbasis.
- vectors, triangularnumpy.ndarray
The section’s Schur factors per active bin, for the other bins.
- forward, inversenumpy.ndarray
Written with the actions, one slot per fraction.
- exponentsnumpy.ndarray
Scratch for one bin’s
exp(+-l lambda).- worknumpy.ndarray
Scratch for one bin’s scaling and squaring.
- solprop.backends.numba_cpu.coupled_flow.make_flow_finish(*, contiguous, absorber, residual)[source]#
Compile the stage’s source before the inverse action: crop, frame, residual.
- Parameters:
- contiguousbool
Whether the crop index is the leading block of the transform grid.
- absorberbool
Whether the in-stage temporal absorber contributes its term.
- residualbool
Whether the flow carries an explicit residual (a
"frozen_residual"flow); a constant-Schur section’s is identically zero and is never formed, as in the reference.
- Returns:
- numba.core.dispatcher.Dispatcher
The compiled kernel.
- solprop.backends.numba_cpu.coupled_flow.residual_action(weights, terms, frozen, out)[source]#
Form the explicit residual
R_s(z_1) = sum_t w_t T_t - G_sof one stage.The reference’s
combine(weights, terms) - frozen[section], summed over the terms from zero in their order. A term of zero weight adds an exact zero, since every term is finite (CoupledFlowTablesrefuses anything else), so it is skipped: the weights vanish outside the stage’s own section.- Parameters:
- weightsnumpy.ndarray
The stage bundle’s
flow_weights, float64, shape(n_terms,).- termsnumpy.ndarray
The held coefficients of
G(z) - C(z)on the active bins, 1/m.- frozennumpy.ndarray
The step’s section’s frozen block, 1/m.
- outnumpy.ndarray
Written with the residual, 1/m.