solprop.backends.numba_cpu.multistep#

The fused Adams step’s passes, compiled (SEP 14 phase 2, SEP 16 phase 3).

solprop.backends.multistep.AdamsKernels states the arithmetic in NumPy; here each pass is one traversal of the field, which on a modal problem of a few thousand complex elements turns some thirty array operations a step into three loops. The integrated weights are compiled too, with the reference’s operations in the reference’s order, so both backends take the same weights.

The exponential formulation’s passes (NumbaExponentialKernels) form every element’s moments k! phi_{k+1}(x) and its flow exp(x) once per trial, in one traversal, with the reference’s algorithm (solprop.backends.exponential) and reciprocal multiplications in place of its divisions; the predictor and the corrector read them. The moments are a per-trial scratch of (q + 2) state-sized rows, reused from trial to trial, never a cached coefficient volume (SEP 16 section 6): forming them in each pass instead cost twice the moment work, which on the Cartesian pilot was ten times the source evaluation.

Beside a coupled flow (NumbaCoupledExponentialKernels, SEP 16 phase 5) the trial’s flow and moments are matrices in the channel axis on the bins that carry a block. On the bins of the flow actions’ eigenbasis route each is W f(x + h lambda) Y, formed per bin from the eigenvalues’ moments in one compiled pass; the predictor and the corrector apply them per bin and the diagonal ones elsewhere, one traversal each, with the defects factored as on the diagonal path.

Rows in parallel (SEP 28). The diagonal passes are built by make_passes() in two variants, the row loop a prange in the parallel one, which the backend chooses for a large problem and which is never disk-cached (docs/dev/backends.md section 3.2). A row’s arithmetic is the same in both, and each defect’s squared norm is summed in two stages, one partial per row, in both.

Strict passes (SEP 25 section 4.2). The integrated weights, the phi-functions, the correctors with their defects and the varying operator’s compensation (_carry, _carry_flows) form small differences of large numbers, so they compile with strict=True: no contraction, called and never inlined. The predictors, the transport and the moments’ traversal take the default contraction.

Functions

make_passes(*, parallel)

Compile the Adams passes, their rows serial or in a prange.

Classes

AdamsPasses(predict, correct, transport, ...)

The element-wise passes of both Adams formulations, one compiled variant.

NumbaAdamsKernels(*[, parallel])

The fused passes of AdamsKernels, compiled.

NumbaCoupledExponentialKernels(*[, parallel])

The exponential formulation's passes beside a coupled flow, compiled.

NumbaExponentialKernels(*[, parallel])

The exponential formulation's passes, compiled (SEP 16 phase 3).

class solprop.backends.numba_cpu.multistep.AdamsPasses(predict, correct, transport, moments, exponential_predict, exponential_correct, carry)[source]#

Bases: NamedTuple

The element-wise passes of both Adams formulations, one compiled variant.

Attributes:
predict, correct, transportcallable

The interaction formulation’s predictor, corrector and history transport.

moments, exponential_predict, exponential_correct, carrycallable

The exponential formulation’s moments and flow, predictor, corrector and a varying operator’s compensation.

carry: Any#

Alias for field number 6

correct: Any#

Alias for field number 1

exponential_correct: Any#

Alias for field number 5

exponential_predict: Any#

Alias for field number 4

moments: Any#

Alias for field number 3

predict: Any#

Alias for field number 0

transport: Any#

Alias for field number 2

class solprop.backends.numba_cpu.multistep.NumbaAdamsKernels(*, parallel=False)[source]#

Bases: AdamsKernels

The fused passes of AdamsKernels, compiled.

The canonical (n_batch, n_modes, n_pol, n_omega) arrays are viewed as rows of n_omega bins; every pass reads each element once, its rows in a prange when the backend steps a large problem (make_passes()).

Parameters:
parallelbool, optional

Whether the passes run their rows in parallel.

correct(state, propagator, source, store, slots, corrector, rows, dz, mask, divisor)[source]#

Return the corrected field and the defects’ norms in one pass.

Parameters:
state, propagator, sourcenumpy.ndarray

The accepted state, U(z_n + dz, z_n) and the new source.

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows after the source, newest first.

correctornumpy.ndarray

The corrector’s weights.

rowsnumpy.ndarray

The defects’ weights.

dzfloat

The step, m.

masknumpy.ndarray

The in-band bins.

divisornumpy.ndarray

The scale per bin.

Returns:
tuple

The corrected field and one norm per defect.

predict(state, propagator, store, slots, weights, dz)[source]#

Return the predictor’s lab-frame field in one pass.

Parameters:
state, propagatornumpy.ndarray

The accepted state and U(z_n + dz, z_n).

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows combined, newest first.

weightsnumpy.ndarray

One weight per row.

dzfloat

The step, m.

Returns:
numpy.ndarray

The predicted field at the end of the step.

transport(store, slots, propagator, new_slot, source)[source]#

Re-anchor the kept rows and store the new derivative in one pass.

Parameters:
storenumpy.ndarray

The history rows, updated in place.

slotsnumpy.ndarray

The kept rows.

propagatornumpy.ndarray

U(z_n + dz, z_n).

new_slotint

The row the new derivative goes to.

sourcenumpy.ndarray

The new derivative in the step’s anchor frame.

weights(nodes, upper=1.0)[source]#

Return the integrated weights of an interpolant on distinct nodes.

Parameters:
nodeslist of float or numpy.ndarray

The normalised nodes.

upperfloat, optional

The integral’s upper limit.

Returns:
numpy.ndarray

One weight per node.

class solprop.backends.numba_cpu.multistep.NumbaCoupledExponentialKernels(*, parallel=False)[source]#

Bases: NumbaExponentialKernels, CoupledExponentialKernels

The exponential formulation’s passes beside a coupled flow, compiled.

The reference’s arithmetic (CoupledExponentialKernels): the block’s flow and moments on its eigenbasis route from one compiled pass, the bins off the route from the reference’s augmented exponential, the predictor and the corrector one traversal each, and every sample’s compensation carried in one more. These passes are serial in either variant: a coupled flow belongs to a guided problem, whose state is far below the parallel regime; parallel chooses the inherited diagonal passes’ variant.

carry_coupled(exponent, dz, rows, slots, spans, block)[source]#

Return each sample’s compensation, carried in one compiled pass.

The terms are the reference’s (carry_coupled()); their flows, every sample’s at once, are formed in the block’s eigenbasis (_carry_flows). A block with bins off the route takes the reference’s.

Parameters:
exponentnumpy.ndarray

x = Delta Phi over the step.

dzfloat

The step, m.

rowstuple

The history’s rates and states, by slot, and each slot’s flow weights.

slotsnumpy.ndarray

The samples carried, newest first.

spansnumpy.ndarray

1 - theta_j per sample.

blockCoupledBlock

The step’s frozen block.

Returns:
numpy.ndarray

One carried row per sample.

correct(state, flow, moments, source, store, slots, corrector, rows, dz, mask, divisor, extra=None)[source]#

Return the corrected field and the defects’ norms through the block.

Parameters:
statenumpy.ndarray

The accepted state at the anchor.

flow, moments_MatrixMoments

The coupled trial’s flow and moments, one object.

sourcenumpy.ndarray

The untransported source at the predicted field.

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows after the source, newest first.

correctornumpy.ndarray

The corrector’s coefficients over the samples.

rowsnumpy.ndarray

The defects, factored by defect_rows().

dzfloat

The step, m.

masknumpy.ndarray

The in-band bins.

divisornumpy.ndarray

The scale per bin.

extratuple or None, optional

The compensation’s corrector term and its term in each defect.

Returns:
tuple

The corrected field and one norm per defect.

coupled()[source]#

Return these passes.

Returns:
CoupledExponentialKernels

This object.

coupled_moments(exponent, count, block, dz)[source]#

Return a coupled trial’s flow and moments, the route’s bins compiled.

Parameters:
exponentnumpy.ndarray

Delta Phi over the step.

countint

The moments formed.

blockCoupledBlock

The step’s frozen block.

dzfloat

The step, m.

Returns:
_MatrixMoments

The flow and the moments.

predict(state, flow, moments, store, slots, coefficients, dz)[source]#

Return the predicted field through the trial’s block, in one pass.

Parameters:
statenumpy.ndarray

The accepted state at the anchor.

flow, moments_MatrixMoments

The coupled trial’s flow and moments, one object.

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows the predictor combines, newest first.

coefficientsnumpy.ndarray

The predictor’s Lagrange coefficients.

dzfloat

The step, m.

Returns:
numpy.ndarray

The predicted lab-frame field at the end of the step.

class solprop.backends.numba_cpu.multistep.NumbaExponentialKernels(*, parallel=False)[source]#

Bases: ExponentialKernels

The exponential formulation’s passes, compiled (SEP 16 phase 3).

moments() forms every element’s moments and flow in one traversal into buffers reused from trial to trial; predict() and correct() are one traversal each, their rows in a prange when the backend steps a large problem (make_passes()). Dense observation keeps the reference’s NumPy passes: it is one evaluation per plane.

Parameters:
parallelbool, optional

Whether the passes run their rows in parallel.

carry(exponent, dz, rates, states, slots, spans)[source]#

Return each sample’s carried compensation in one compiled traversal.

Parameters:
exponentnumpy.ndarray

x = Phi(z + h) - Phi(z).

dzfloat

The step, m.

rates, statesnumpy.ndarray

The history’s rates and states, by slot.

slotsnumpy.ndarray

The samples carried, newest first.

spansnumpy.ndarray

1 - theta_j per sample.

Returns:
numpy.ndarray

One carried row per sample.

correct(state, flow, moments, source, store, slots, corrector, rows, dz, mask, divisor, extra=None)[source]#

Return the corrected field and the defects’ norms in one pass.

Parameters:
statenumpy.ndarray

The accepted state at the anchor.

flownumpy.ndarray

exp(x).

momentsnumpy.ndarray

M_k from moments().

sourcenumpy.ndarray

The untransported source at the predicted field.

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows after the source, newest first.

correctornumpy.ndarray

The corrector’s coefficients over the samples.

rowsnumpy.ndarray

The defects, factored by defect_rows().

dzfloat

The step, m.

masknumpy.ndarray

The in-band bins.

divisornumpy.ndarray

The scale per bin.

extratuple or None, optional

A varying operator’s compensation: its corrector term and its term in each defect.

Returns:
tuple

The corrected field and one norm per defect.

coupled()[source]#

Return the compiled passes beside a coupled flow, one per kernel object.

Returns:
CoupledExponentialKernels

A NumbaCoupledExponentialKernels.

defect_rows(nodes, orders, width)[source]#

Return each defect factored: a divided difference and a node polynomial.

Order k’s defect, its k + 1-node corrector through the new sample less its k-node predictor, vanishes at the predictor’s nodes, so it is f[1, theta_0, ..., theta_{k-1}] prod_{j<k} (theta - theta_j): one divided difference of the samples times one polynomial, whose integral against the flow is one combination of the moments. That is 2 (k + 1) products an element instead of (k + 1) n_k, the reference’s monomial rows.

Parameters:
nodeslist of float

The history’s normalised positions, newest first.

orderslist of int

The orders scored, the step’s own first.

widthint

1 + max(orders): the samples and the moments of the trial.

Returns:
numpy.ndarray

Shape (len(orders), 2 width): the divided-difference coefficients over (source, newest, ...), then the node polynomial’s ascending monomial coefficients.

flow(exponent)[source]#

Return exp(x) as moments() formed it for this trial.

Parameters:
exponentnumpy.ndarray

The trial’s exponent, whose moments were formed last.

Returns:
numpy.ndarray

The flow, a view of this object’s scratch.

moments(exponent, count)[source]#

Return k! phi_{k+1}(x) for k < count, forming exp(x) beside them.

Parameters:
exponentnumpy.ndarray

x = Phi(z + h) - Phi(z).

countint

The most nodes a formula of the trial has.

Returns:
numpy.ndarray

Shape (count, *x.shape), a view of this object’s scratch.

predict(state, flow, moments, store, slots, coefficients, dz)[source]#

Return the predicted field in one pass.

Parameters:
statenumpy.ndarray

The accepted state at the anchor.

flownumpy.ndarray

exp(x).

momentsnumpy.ndarray

M_k from moments().

storenumpy.ndarray

The history rows.

slotsnumpy.ndarray

The rows the predictor combines, newest first.

coefficientsnumpy.ndarray

The predictor’s Lagrange coefficients.

dzfloat

The step, m.

Returns:
numpy.ndarray

The predicted lab-frame field at the end of the step.

solprop.backends.numba_cpu.multistep.make_passes(*, parallel)[source]#

Compile the Adams passes, their rows serial or in a prange.

Every pass traverses rows of n_omega bins, each row independent, so the row loop is the parallel one. A row’s arithmetic is the same in either variant, and a defect’s squared norm is two-stage in both: one partial per row, summed by the caller.

Parameters:
parallelbool

Whether independent rows execute in parallel.

Returns:
AdamsPasses

The compiled passes.