solprop.backends.export#

Destination-based export of a session’s field (SEP 47 section 5.4).

The output layer owns the definition of what a saved field means: true-power modal amplitudes, or a spatial route’s field measure, in the optics convention on disk (ADR-017; docs/dev/conventions.md). It states that definition once, as an ExportRecipe, and a session applies it while filling a destination: the reference session with apply_recipe(), the native session in its own fused pass. The definition does not move; only where it is evaluated does.

Every conversion step is exact or is the one multiplication today’s two-step path makes: a real square-root weight times the amplitude, then a conjugation and a multiplication by (-1)**k. Applied in that order, the fused pass is bitwise equal to solprop.fourier.power_amplitude() followed by solprop.fourier.spectrum_to_optics(), so lossless storage stays exact.

A destination is either an array the caller supplies – a preallocated store row – or a newly owned array the session allocates. Either way the result is detached: it is never a view of a live workspace, and the session never writes to it again. A plane store asks for its own room (solprop.output.schema.PlaneStore.field_destination()), so that a kept field is written once, where it is kept.

The destination is always host memory. A session whose state lives on a device fills it the same way: the recipe runs where the state is, into the device’s own scratch, and one copy crosses into the host destination; whether the conversion is better made before or after that crossing is the device’s choice to measure (SEP 47 section 5.4). No device array crosses this interface.

Functions

apply_recipe(state, recipe, *, weight[, out])

Fill a destination with a field converted by a recipe, in one pass.

destination_refusal(out, shape)

Return why an array cannot be an export destination, or None if it can.

Classes

ExportRecipe(power, optics)

What conversion a field export applies on its way to a destination.

class solprop.backends.export.ExportRecipe(power, optics)[source]#

Bases: object

What conversion a field export applies on its way to a destination.

Attributes:
powerbool

Multiply modal amplitudes by the square root of the route’s true-power weight at the exported position (fourier.power_amplitude). False on spatial routes, whose field measure is already the stored quantity.

opticsbool

Convert from the internal FFT convention to the optics convention about the window centre, (-1)**k conj(.) (fourier.spectrum_to_optics). True for a plane store; False for a consumer that works in the internal convention, such as a plane observer or a terminal checkpoint record.

Examples

>>> from solprop.backends.export import ExportRecipe
>>> ExportRecipe(power=True, optics=False)
ExportRecipe(power=True, optics=False)
optics: bool#
power: bool#
solprop.backends.export.apply_recipe(state, recipe, *, weight, out=None)[source]#

Fill a destination with a field converted by a recipe, in one pass.

The reference implementation of SEP 47’s export. state is only read; the result is out when given, and otherwise a new array, so it never aliases state.

Parameters:
statenumpy.ndarray

The committed field, complex128, internal FFT convention, internal amplitude units, shape (n_modes, n_pol, n_omega).

recipeExportRecipe

The conversion.

weightnumpy.ndarray or None

The true-power weight at the field’s position, positive and finite, the shape of state; required when recipe.power and ignored otherwise.

outnumpy.ndarray or None, optional

The destination, complex128, C-contiguous, the shape of state, not overlapping it; a new array by default. state itself converts in place, for a session that owns the only reference to it; each step is elementwise, so the result is the same bits.

Returns:
numpy.ndarray

The converted field: out when given.

Raises:
BackendError

If out has the wrong shape, dtype or layout, or overlaps state.

GridError

If a weight is required and missing, or not positive and finite.

Examples

>>> import numpy as np
>>> from solprop.backends.export import ExportRecipe, apply_recipe
>>> state = np.array([[[1 + 1j, 2 - 1j]]])
>>> apply_recipe(state, ExportRecipe(power=True, optics=True),
...              weight=np.full((1, 1, 2), 4.0)).tolist()
[[[(2-2j), (-4-2j)]]]
solprop.backends.export.destination_refusal(out, shape)[source]#

Return why an array cannot be an export destination, or None if it can.

Every session validates a destination by this one rule before it writes to it (SEP 47 section 5.4), and names what is wrong: its shape, its dtype, its layout or that it is read-only. One whose elements overlap one another is not contiguous.

Parameters:
outnumpy.ndarray

The proposed destination.

shapetuple of int

The field’s shape, (n_modes, n_pol, n_omega).

Returns:
str or None

The refusal, or None for a writeable, C-contiguous complex128 array of shape.

Examples

>>> import numpy as np
>>> from solprop.backends.export import destination_refusal
>>> destination_refusal(np.empty((1, 1, 4), complex), (1, 1, 4)) is None
True
>>> destination_refusal(np.empty((1, 1, 4), np.complex64), (1, 1, 4))
'an export destination has dtype complex64, expected complex128'