solprop.spatial#

Describe bulk media and exact longitudinal propagation of spatial fields.

Spatial fields are in V/m. Energy, fluence and intensity are the axial Poynting flux of the medium at the measured plane (SpatialFlux, SEP 34). On a line uniform in y (solprop.grid.LineGrid) every transverse integral is per metre of y: energy in J/m and power in W/m, while intensity and fluence stay local. Transverse wave numbers are angular frequencies in rad/m. The propagation sign and co-moving frame are those of docs/dev/conventions.md.

Module Attributes

EVANESCENT_RATE

Evanescent field attenuation cap in m^-1.

FluxSide

The side of a declared index jump a flux plane is evaluated on (SEP 34 §4.4).

ApertureProfile

The edge profile of a far-field aperture (SEP 23 section 4.4).

APERTURE_PROFILES

Every aperture edge profile, in the order of their integer profile codes.

EDGE_MOMENTS

The first moment m_2 of each symmetric edge's unit-width outer tail.

FAR_FIELD_STATISTICS

The five statistics aperture_statistics() forms, in catalogue order.

OPERATOR_STATISTICS

The far-field statistic that needs the run's linear operator.

ABSORBED_CHANNELS

The channels of absorbed_power, in the order of its four entries.

AxialFactors

Per-chunk admittance and absorption rates of the plane's medium (SEP 34).

Functions

aperture_profile(radius, half_width, edge, kind)

Return an aperture's profile W at distances from its centre.

aperture_scale(distances, omega)

Return the paraxial mask-plane scale s(omega) = z c / omega of each aperture.

aperture_statistics(names, grid, field, ...)

Form the far-field statistics of one Cartesian or line spectrum (SEP 23).

attenuation_extremes(square, kperp_sq, *[, ...])

Return each frequency's extreme field attenuations over the columns.

beam_radius(spectrum, flux, *[, method])

Measure a beam radius from its time-integrated axial flux.

cartesian_fluence_widths(x, y, fluence)

Measure centroid-based moments and radially averaged Cartesian widths.

check_aperture_profile(kind)

Refuse, by name, anything that is not one of the aperture edge profiles.

critical_power(wavelength, chi3, *, index[, ...])

Return the physical Townes critical-power baseline.

fwhm_r(spectrum, flux)

Return the central fluence profile's full width at half maximum.

mask_plane_radius(scale, k_x, k_y, centre)

Return how far each column's mask-plane image lies from an aperture's centre.

on_axis_intensity(spectrum, flux)

Return the largest signed axial flux in time on the beam axis.

on_axis_spectrum(spectrum, flux)

Return the on-axis spectral fluence density summed over polarisation.

peak_field(grid, space, spectrum)

Return the largest physical analytic field magnitude at any node and time.

physical_evanescent_rate(space, medium, grid, *)

Return the largest physical evanescent field attenuation the grid holds.

planar_fluence(spectrum, flux)

Return a planar beam's signed time-integrated axial flux at its nodes.

planar_intensity(spectrum, flux)

Return a planar beam's signed local axial flux at its nodes in time.

planar_mode_energy(spectrum, flux)

Integrate a planar beam's physical energy in each slab mode.

plane_sample(medium, z, side)

Return where to evaluate the medium for a plane, checking its jump side.

power_trace(spectrum, admittance, weights, ...)

Return the axial power through a plane in time from column spectra.

quadrature_half_width(half_width, width, kind)

Return the half-width at which a profile used once integrates a hard hole.

radial_fluence_widths(radius, fluence, ...)

Return second-moment radius, first 1/e^2 radius and central FWHM.

spatial_energy(spectrum, flux)

Integrate the physical energy crossing the plane, in joules.

spatial_fluence(spectrum, flux)

Return the signed time-integrated axial flux at the spatial nodes.

spatial_intensity(spectrum, flux)

Return the signed local axial flux at every spatial node and time sample.

spatial_power(spectrum, flux)

Return the axial power crossing the plane at every time sample.

Classes

ApertureTables(k_x, k_y, weights, on_axis, ...)

Hold the constants the far-field statistics read, formed once (SEP 23 §6).

SpatialDispersion(medium, grid, frame[, ...])

Evaluate exact longitudinal propagation in the existing temporal frame.

SpatialFlux(grid, space, medium, z, side, ...)

The axial-flux measure of one physical plane (SEP 34).

SpatialMedium([material, pressure, ...])

Describe a gas, a glass or a constant complex bulk refractive index.

solprop.spatial.ABSORBED_CHANNELS: tuple[str, ...] = ('spectral', 'transverse', 'evanescent', 'material')#

The channels of absorbed_power, in the order of its four entries.

solprop.spatial.APERTURE_PROFILES: tuple[Literal['hard', 'tanh', 'rcos', 'supergauss'], ...] = ('hard', 'tanh', 'rcos', 'supergauss')#

Every aperture edge profile, in the order of their integer profile codes.

solprop.spatial.ApertureProfile#

The edge profile of a far-field aperture (SEP 23 section 4.4).

alias of Literal[‘hard’, ‘tanh’, ‘rcos’, ‘supergauss’]

class solprop.spatial.ApertureTables(k_x, k_y, weights, on_axis, regions, centres, half_widths, edges, distances, scale, profile='hard', exponent=2)[source]#

Bases: object

Hold the constants the far-field statistics read, formed once (SEP 23 §6).

solprop.translate.spatial.aperture_tables() builds it from a statistics request, a frequency axis and a Cartesian geometry; every backend and solprop.stats.collect() then read the same values, the scale table among them to the bit. Equality is by identity.

Attributes:
k_x, k_ynumpy.ndarray

The stored transverse axes in rad/m, FFT order, shapes (n_x,) and (n_y,); column ix + n_x*iy carries (k_x[ix], k_y[iy]).

weightsnumpy.ndarray

The geometry’s Parseval spectral weights, m^2 (m on a line), shape (n_x*n_y,).

on_axisnumpy.ndarray

The geometry’s complex on-axis reconstruction weights, shape (n_x*n_y,).

regionsnumpy.ndarray

Boxes of physical transverse wavevector in rad/m, rows (kx_lo, kx_hi, ky_lo, ky_hi), shape (n_regions, 4); empty when none was asked for.

centresnumpy.ndarray

Aperture centres in the mask plane, physical axes, in m, shape (n_apertures, 2).

half_widthsnumpy.ndarray

The profiles’ half-widths in m, D/2 or D_q/2, shape (n_apertures,).

edgesnumpy.ndarray

Edge widths in m (tanh, rcos), orders (supergauss), or zeros (hard), shape (n_apertures,).

distancesnumpy.ndarray

Exit face to mask plane in m, shape (n_apertures,).

scalenumpy.ndarray

aperture_scale() of the distances, m^2, shape (n_apertures, n_omega), zero at and below zero frequency.

profile{‘hard’, ‘tanh’, ‘rcos’, ‘supergauss’}

The edge profile the set shares.

exponentint

The power of the weight in aperture_spectrum: 2 for amplitude weighting, 1 for quadrature weighting.

Raises:
OutputError

If the arrays disagree in shape, the profile is unknown or the exponent is not 1 or 2.

centres: Float[ndarray, 'n_centre_rows 2']#
distances: Float[ndarray, 'n_distances']#
edges: Float[ndarray, 'n_edge_values']#
exponent: int = 2#
half_widths: Float[ndarray, 'n_half_widths']#
property inverse_widths: Float[ndarray, 'n_apertures'][source]#

Return the reciprocal edge widths a compiled pass multiplies by.

Returns:
numpy.ndarray

1/w in 1/m for tanh and rcos, zeros otherwise, shape (n_apertures,): the factor aperture_profile() forms itself.

k_x: Float[ndarray, 'n_kx']#
k_y: Float[ndarray, 'n_ky']#
property n_apertures: int[source]#

Return the number of apertures.

Returns:
int

The rows of the aperture tables, zero when none was asked for.

property n_columns: int[source]#

Return the number of transverse columns the tables describe.

Returns:
int

n_x*n_y.

property n_regions: int[source]#

Return the number of regions of transverse wavevector.

Returns:
int

The rows of regions.

on_axis: Complex[ndarray, 'n_axis_weights']#
profile: Literal['hard', 'tanh', 'rcos', 'supergauss'] = 'hard'#
property profile_code: int[source]#

Return the profile’s integer code, its index in APERTURE_PROFILES.

Returns:
int

0 for hard, 1 for tanh, 2 for rcos, 3 for supergauss.

regions: Float[ndarray, 'n_region_rows 4']#
scale: Float[ndarray, 'n_scale_rows n_scale_omega']#
weights: Float[ndarray, 'n_weights']#
solprop.spatial.AxialFactors#

Per-chunk admittance and absorption rates of the plane’s medium (SEP 34).

Called with a slice of transverse columns, it returns the dimensionless complex admittance c k_z/omega, shape (n_chunk, n_omega), zero on bins that are no forward power port, and the four power rates of ABSORBED_CHANNELS in 1/m, shape (4, n_chunk, n_omega), or None where the run’s operator is not available (a saved plane). solprop.translate.spatial.axial_factors() is the in-run implementation and SpatialFlux.admittance() the saved-plane one.

alias of Callable[[slice], tuple[ndarray, ndarray | None]]

solprop.spatial.EDGE_MOMENTS: Mapping[str, float] = mappingproxy({'hard': 0.0, 'tanh': 0.2056167583560283, 'rcos': 0.04735763271532445})#

The first moment m_2 of each symmetric edge’s unit-width outer tail.

\(m_2=\int_0^\infty t\,W_1(t)\,dt\), a quarter of the edge kernel’s variance in units of the width squared: \(\pi^2/48\) for tanh (the integral of \(t/(1+e^{2t})\)) and \(1/4-2/\pi^2\) for rcos, as SEP 23 section 4.5 and docs/guide/results/statistics.md (Far-field apertures and angular regions) derive them; the tests check both against quadrature. hard needs no correction; supergauss has no symmetric edge and so no entry.

solprop.spatial.EVANESCENT_RATE = 200.0#

Evanescent field attenuation cap in m^-1.

This is a declared numerical model of the nonpropagating band, not a material absorption coefficient. Propagating material loss and gain are not clamped by it.

solprop.spatial.FAR_FIELD_STATISTICS: tuple[str, ...] = ('aperture_spectrum', 'aperture_on_axis_spectrum', 'region_spectrum', 'beam_spectrum', 'absorbed_power')#

The five statistics aperture_statistics() forms, in catalogue order.

solprop.spatial.FluxSide#

The side of a declared index jump a flux plane is evaluated on (SEP 34 §4.4).

alias of Literal[‘before’, ‘after’]

solprop.spatial.OPERATOR_STATISTICS: tuple[str, ...] = ('absorbed_power',)#

The far-field statistic that needs the run’s linear operator.

A saved plane does not carry the operator’s absorption rates, so it is a backend statistic and solprop.stats.collect() refuses it by name.

class solprop.spatial.SpatialDispersion(medium, grid, frame, evanescent_rate=200.0)[source]#

Bases: object

Evaluate exact longitudinal propagation in the existing temporal frame.

Attributes:
mediumSpatialMedium

Bulk material index and its scalar density dependence.

gridsolprop.grid.TimeGrid

Temporal frequency grid; only its active band samples the material.

framesolprop.linear.Frame

Frame at zero transverse frequency, shared by all spatial columns.

evanescent_ratefloat

Maximum evanescent field attenuation in m^-1, finite and positive. Default 200.

Raises:
MaterialError

If the attenuation cap or frame reference is invalid.

cartesian_squares(space, z=0.0)[source]#

Split Cartesian wave-number squares without losing cutoff information.

Parameters:
spacesolprop.grid.FreeGrid

Stored unsquared transverse axes in rad/m, with x fastest.

zfloat, optional

Finite material sampling position in m.

Returns:
tuple of numpy.ndarray

Material high and low parts in m^-2, each complex and frequency-sized, and the real residual of space.kperp_sq in m^-2. Residuals are rounded from exact rational arithmetic on the stored binary inputs. Inactive material bins are zero. No spatial-frequency table is built.

evanescent_rate: float = 200.0#
frame: Frame#
frame_quantities(z=0.0)[source]#

Evaluate the carrier and group-delay terms at zero transverse frequency.

Parameters:
zfloat, optional

Finite position in m.

Returns:
tuple of float

Removed beta0 in m^-1 and beta1 in s/m, following solprop.linear.Frame, including its fixed overrides.

grid: TimeGrid#
material_squares(z=0.0)[source]#

Split the material wave-number square into its rounded value and residual.

Parameters:
zfloat, optional

Finite material sampling position in m.

Returns:
tuple of numpy.ndarray

(omega n / c)**2 in m^-2 and its residual, the exact rational square of the stored binary inputs minus the rounded one, each complex and frequency-sized. Inactive bins are zero.

medium: SpatialMedium#
operator(kperp_sq, z=0.0)[source]#

Evaluate the exact longitudinal rate before spectral boundary loss.

Parameters:
kperp_sqnumpy.ndarray or solprop.grid.FreeGrid

Finite nonnegative transverse wave-number squares in m^-2, or a Cartesian grid whose unsquared axes preserve cutoff precision.

zfloat, optional

Finite position in m.

Returns:
numpy.ndarray

Rate in m^-1, shape (n_modes, n_omega). The positive-real square root propagates with material loss/gain. Nonpositive real longitudinal square attenuates with the declared evanescent cap.

Raises:
MaterialError

If a transverse frequency is negative or nonfinite.

prefactor(kperp_sq, z=0.0)[source]#

Evaluate the spatial UPPE polarisation prefactor before temporal scaling.

Parameters:
kperp_sqnumpy.ndarray or solprop.grid.FreeGrid

Finite nonnegative transverse wave-number squares in m^-2, or a Cartesian grid whose unsquared axes preserve cutoff precision.

zfloat, optional

Finite position in m.

Returns:
numpy.ndarray

Purely imaginary -i*mu0*omega**2/(2*Re(k_z)), shape (n_modes, n_omega). The literal evanescent norm of 1 gives -i*omega/2 in that band; inactive frequencies are zero.

Raises:
MaterialError

If a transverse frequency is negative or nonfinite.

shared_values(z=0.0)[source]#

Evaluate frequency-only material and normalisation coefficients.

Parameters:
zfloat, optional

Finite position in m.

Returns:
tuple of numpy.ndarray

Wave-number square in m^-2, frame subtraction in m^-1, numerator -i*mu0*omega**2/2, and clamped prefactor -i*omega/2. All have shape (n_omega,); physical coefficients vanish outside the active band. Temporal transform scalings are not included.

class solprop.spatial.SpatialFlux(grid, space, medium, z, side, coefficients)[source]#

Bases: object

The axial-flux measure of one physical plane (SEP 34).

Binds the temporal and transverse representation, the medium and the plane’s position once. The scalar forward equation’s axial admittance \(\mathcal Y_c=\varepsilon_0c^2k_z/\omega\) of the medium at that plane measures the field: its real part \(Y_z\) weighs integrated energy, and the complex value reconstructs the local magnetic closure \(G=\mathcal Y_cE\) for signed local flux \(S_z=\tfrac12\operatorname{Re}(E_aG_a^*)\). Only active propagating columns at positive frequency are forward power ports; every other bin has zero admittance. Build one with resolve(); a different plane needs a new record (docs/guide/free-space/flux.md).

Attributes:
gridsolprop.grid.TimeGrid

Temporal grid of the field.

spacesolprop.grid.RadialGrid, solprop.grid.FreeGrid or PlanarGrid

Transverse geometry of the field.

mediumSpatialMedium

The bulk medium; for a planar grid, its slab modes’ own fill.

zfloat

Position of the plane in m.

side{‘before’, ‘after’} or None

Side of a declared index jump at z; None away from one.

coefficientsobject

The plane’s separable coefficients (solprop.translate.spatial.SeparableOperator), resolved once.

admittance(columns=slice(None, None, None))[source]#

Return the dimensionless forward admittance c k_z / omega of columns.

Parameters:
columnsslice, optional

Transverse columns; all by default.

Returns:
numpy.ndarray

Y_c / (eps0 c) in the optics convention (positive imaginary part for loss), zero on nonpropagating, inactive and nonpositive-frequency bins, shape (n_chunk, n_omega).

chunks()[source]#

Return column slices bounding an integrated sum’s working memory.

Returns:
list of slice

Consecutive slices covering every transverse column.

coefficients: object#
property energy_scale: float[source]#

Return the factor turning weighted |X|^2 sums into joules.

Returns:
float

eps0 c / 2 for a field in V/m; one for planar slab amplitudes, whose mode functions already carry it.

grid: TimeGrid#
medium: SpatialMedium#
classmethod resolve(grid, space, medium, *, z=0.0, side=None, evanescent_rate=200.0)[source]#

Resolve the measure of the plane at z in medium.

Parameters:
gridsolprop.grid.TimeGrid

Temporal grid of the field.

spacesolprop.grid.RadialGrid, solprop.grid.FreeGrid or PlanarGrid

Transverse geometry of the field.

mediumSpatialMedium

The bulk medium at the plane; for a planar grid, the modes’ own fill.

zfloat, optional

Finite position of the plane in m. Default 0.

side{‘before’, ‘after’} or None, optional

The side of a declared index jump at z. Required there, and refused away from one.

evanescent_ratefloat, optional

Evanescent attenuation cap of the run, in m^-1.

Returns:
SpatialFlux

The resolved, immutable measure.

Raises:
MaterialError

If the position is not finite, or a jump side is missing or misplaced.

side: Literal['before', 'after'] | None#
space: RadialGrid | FreeGrid | PlanarGrid#
z: float#
class solprop.spatial.SpatialMedium(material=1.0, pressure=1.0, temperature=None, susceptibility=None)[source]#

Bases: object

Describe a gas, a glass or a constant complex bulk refractive index.

Attributes:
materialGas, str, GlassIndex, complex or Mixture

Gas name, existing glass model, or constant index. Default 1 is vacuum. Positive imaginary index is loss; negative imaginary index is gain. A mixture supplies its own density paths, temperature and optical models.

pressurefloat or solprop.profiles.ZProfile

Absolute gas pressure in bar, nonnegative, optionally varying along z. Only gas media use pressure; other materials require the default 1.

temperaturefloat or None

Gas temperature in K, finite and positive; None (the default) is room temperature for a gas and the mixture’s own beside a mixture, which is what the attribute holds after construction. A temperature other than the mixture’s beside a mixture, and a temperature path along z, here or in a mixture, are refused by name: the mixture carries its temperature, and the free-space routes do not carry a path.

susceptibilitysolprop.physdata.sellmeier.GasSusceptibility or None

Per-particle gas susceptibility; None selects the built-in gas’s, optmat’s (solprop.physdata.species.default_species). Not accepted for a glass or constant-index medium.

densitysolprop.profiles.ZProfile

Gas number density in m^-3; dimensionless 1 for nongas media whose nonlinear susceptibilities are absolute. Derived from optmat’s equation of state of the gas.

Raises:
MaterialError

If the material, pressure, temperature or susceptibility is inconsistent.

at_density(density)[source]#

Freeze the scalar density for a parameter-expansion sample.

Parameters:
densityfloat

Finite nonnegative number density in m^-3 for a gas. Nongas media require their dimensionless density of 1.

Returns:
SpatialMedium

The same material with a constant density path.

Raises:
MaterialError

If density is invalid or changes the nongas normalisation.

at_parameters(values)[source]#

Freeze the named material parameters for an operator sample.

Parameters:
valuescollections.abc.Mapping

Values of the declared pressure or density parameters, in bar or m^-3.

Returns:
SpatialMedium

A sampled medium with unchanged species data.

Raises:
MaterialError

If a name is not declared or a value is invalid.

density: ZProfile#
dindex_domega(omega, z=0.0)[source]#

Evaluate the analytic frequency derivative of the material index.

Parameters:
omeganumpy.ndarray

Finite positive angular frequencies in rad/s, shape (n_omega,).

zfloat, optional

Finite position in m.

Returns:
numpy.ndarray

Derivative in s/rad, shape (n_omega,).

Raises:
MaterialError

If the evaluation point or result is invalid.

index(omega, z=0.0)[source]#

Evaluate the material refractive index on a physical frequency band.

Parameters:
omeganumpy.ndarray

Finite positive angular frequencies in rad/s, shape (n_omega,).

zfloat, optional

Position in m, finite; profile endpoint continuation applies.

Returns:
numpy.ndarray

Complex refractive index, dimensionless, shape (n_omega,).

Raises:
MaterialError

If a frequency, position or computed index is invalid.

material: Gas | str | GlassIndex | complex | Mixture = 1.0#
property parameter_paths: Mapping[str, ZProfile][source]#

Return every material path that changes the spatial operator.

Returns:
collections.abc.Mapping

A shared pressure in bar or independent labelled densities in m^-3. A single population retains the original density parameter.

pressure: float | ZProfile = 1.0#
susceptibility: GasSusceptibility | None = None#
temperature: float | None = None#
solprop.spatial.aperture_profile(radius, half_width, edge, kind)[source]#

Return an aperture’s profile W at distances from its centre.

How W enters depends on the aperture set’s weighting (SEP 23 section 4.6): under "amplitude" weighting (the default) it is the field transmission, and aperture_spectrum weighs the collected power by W**2; under "quadrature" weighting it weighs the power itself, once. The on-axis amplitude behind the aperture applies W once under both weightings.

With r the half-width and t = (rho - r)/w, the four profiles of SEP 23 section 4.4 are: hard, one for rho <= r and zero beyond; tanh, \(\tfrac12[1-\tanh t]\); rcos, \(\tfrac12[1-\sin(\pi t/2)]\) with t clipped to [-1, 1], exactly one inside r - w and exactly zero outside r + w; and supergauss, \(\exp[-(\rho/r)^n]\). tanh and rcos satisfy the edge symmetry \(W(r+u)+W(r-u)=1\). The argument is formed as (rho - r) * (1/w), the product with the reciprocal a compiled pass stores, so every backend evaluates the same argument.

Parameters:
radiusarray_like or float

Distances \(\rho\) from the aperture’s centre in m, nonnegative.

half_widthfloat

The profile’s half-width r in m, finite and positive: D/2 under amplitude weighting, the corrected D_q/2 under quadrature weighting (quadrature_half_width()).

edgefloat

The edge width w in m for tanh and rcos (finite and positive), the order n for supergauss (finite, at least 2); not used for hard.

kind{‘hard’, ‘tanh’, ‘rcos’, ‘supergauss’}

The edge profile.

Returns:
numpy.ndarray

The dimensionless profile W(rho) in [0, 1], the shape of radius.

Raises:
OutputError

If the profile is unknown, the half-width is not finite and positive, or the edge is not valid for the profile.

Examples

>>> import numpy as np
>>> from solprop.spatial import aperture_profile
>>> aperture_profile(np.array([0.0, 1.0, 1.5]), 1.0, 0.0, "hard").tolist()
[1.0, 1.0, 0.0]
>>> float(aperture_profile(1.0, 1.0, 0.1, "tanh"))
0.5
>>> aperture_profile(np.array([0.85, 1.0, 1.15]), 1.0, 0.1, "rcos").tolist()
[1.0, 0.5, 0.0]
solprop.spatial.aperture_scale(distances, omega)[source]#

Return the paraxial mask-plane scale s(omega) = z c / omega of each aperture.

Equation (3) of SEP 23: a plane-wave component of transverse wavevector kappa reaches the mask plane at x = s kappa. The table is formed as (z * c) / omega and is exactly zero at and below zero frequency, where the mapping does not exist and every aperture weight is zero.

Parameters:
distancesnumpy.ndarray

Exit face to mask plane (or a lens’s focal length) of each aperture, in m, shape (n_apertures,).

omeganumpy.ndarray

Physical angular frequencies in rad/s, shape (n_omega,).

Returns:
numpy.ndarray

The scale in m^2, shape (n_apertures, n_omega).

Examples

>>> import numpy as np
>>> from solprop.constants import C
>>> from solprop.spatial import aperture_scale
>>> table = aperture_scale(np.array([0.5]), np.array([-1.0, 0.0, C]))
>>> table.tolist()
[[0.0, 0.0, 0.5]]
solprop.spatial.aperture_statistics(names, grid, field, tables, *, axial, chunk=None)[source]#

Form the far-field statistics of one Cartesian or line spectrum (SEP 23).

The reference pass of SEP 23’s equations, measured by the axial flux of the medium (SEP 34): the spectrum collected through each aperture, \(S_a=\tfrac{\varepsilon_0c}{2}\sum_cw_cW_a^p\eta_c\sum_q \operatorname{sd}(E)\) with the real admittance \(\eta=c\operatorname{Re}k_z/\omega\); the on-axis spectrum behind each aperture in a Fourier plane, the same-frequency pairing of the coherent \(A_{a,q}=\sum_c\alpha_cW_aE_{c,q}\) with its magnetic closure; the spectrum in each box of physical transverse wavevector; the beam spectrum; and the power the spectral, transverse, evanescent and material channels of the linear operator remove, \(P_j=\tfrac{\varepsilon_0c}{2}\sum_cw_c\sum_{q,k} \nu_k\eta r_j|E|^2\). It walks the columns in chunks, forms the polarisation-summed spectral density once per chunk and adds the chunk partials in ascending order.

Parameters:
namescollections.abc.Sequence of str

The statistics wanted, a subset of FAR_FIELD_STATISTICS.

gridsolprop.grid.TimeGrid

The temporal grid: its spacing and kind fix the spectral density and the energy weights.

fieldnumpy.ndarray

One internal Cartesian spectrum in V/m (raw transverse DFT), shape (n_x*n_y, n_pol, n_omega).

tablesApertureTables

The far-field tables of the request and the geometry.

axialcallable

The plane’s per-chunk admittance and the operator’s rates (AxialFactors); the rates are needed by absorbed_power.

chunkint or None, optional

Columns per chunk, at least 1; None bounds the chunk’s temporaries at 64 MiB.

Returns:
dict

Each requested statistic: aperture_spectrum and region_spectrum in J/(rad/s), shapes (n_apertures, n_omega) and (n_regions, n_omega); aperture_on_axis_spectrum in J s/m^2, (n_apertures, n_omega); beam_spectrum in J/(rad/s), (n_omega,); absorbed_power in J/m, (4,), in the order of ABSORBED_CHANNELS. On a line the spectra and powers are per metre of y, and the on-axis spectra stay local.

Raises:
OutputError

If a name is not a far-field statistic, the field does not match the tables, a requested statistic needs a table the request does not carry, or an operator statistic is asked for without the operator’s rates.

solprop.spatial.attenuation_extremes(square, kperp_sq, *, square_low=None, kperp_sq_low=None)[source]#

Return each frequency’s extreme field attenuations over the columns.

SEP 22 section 4.4. For \(q = k^2 - k_\perp^2\) and the principal root \(s = \sqrt q\), \(\operatorname{Im}\sqrt z = \operatorname{sign}(\operatorname{Im}z)\sqrt{(|z| - \operatorname{Re}z)/2}\) is monotone in \(k_\perp^2\) at fixed frequency, so the extremes over the propagating columns (\(\operatorname{Re}q > 0\)) lie at the smallest \(k_\perp^2\) and the largest one below \(\operatorname{Re}k^2\), and the largest \(|\operatorname{Im}s|\) over the evanescent columns at the largest \(k_\perp^2\). The columns are sorted once and searched per frequency, in \(O(n_\omega \log n_{\mathrm{modes}})\), and the candidates beside each cutoff are classified with the full split arithmetic.

Parameters:
squarenumpy.ndarray

The material wave-number square \(k^2(\omega)\) in m^-2, complex, shape (n_omega,).

kperp_sqnumpy.ndarray

The columns’ transverse squares in m^-2, nonnegative, shape (n_modes,).

square_low, kperp_sq_lownumpy.ndarray or None, optional

Their residuals in m^-2, as solprop.translate.spatial.SeparableOperator stores them; None is zero.

Returns:
tuple of numpy.ndarray

Per frequency, each of shape (n_omega,) and in m^-1: the largest and the smallest \(\operatorname{Im}s\) over the propagating columns (-inf and +inf where none propagates), and the largest uncapped \(|\operatorname{Im}s|\) over the evanescent columns (zero where none is evanescent).

Examples

>>> import numpy as np
>>> from solprop.spatial import attenuation_extremes
>>> square = np.array([4.0 + 1e-3j])
>>> largest, smallest, evanescent = attenuation_extremes(
...     square, np.array([0.0, 3.0, 5.0])
... )
>>> float(evanescent[0]) == float(abs(np.sqrt(square[0] - 5.0).imag))
True
solprop.spatial.beam_radius(spectrum, flux, *, method='second_moment')[source]#

Measure a beam radius from its time-integrated axial flux.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m or Cartesian spectrum in V/m, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure on a radial or Cartesian grid.

method{‘second_moment’, ‘1/e2’}, optional

sqrt(2 integral r^2 F dA / integral F dA) or the first linearly interpolated crossing of the central fluence divided by e^2.

Returns:
float

Radius in m. Empty beams return NaN; interpolated radii also return NaN for a profile whose axis fluence lies below the threshold (hollow at that level) or that does not cross it within the grid.

Raises:
GridError

If the method or spectrum is invalid, the grid is planar, or the fluence is negative beyond its rounding budget.

solprop.spatial.cartesian_fluence_widths(x, y, fluence)[source]#

Measure centroid-based moments and radially averaged Cartesian widths.

Parameters:
x, yarray_like

Uniform increasing physical axes in m. x has at least two samples, and so has y except on a line uniform in y (solprop.grid.LineGrid), where y is its one sample and the widths are one-dimensional.

fluencearray_like

Finite nonnegative time-integrated intensity in J/m^2, flattened with x fastest, shape (n_x*n_y,).

Returns:
tuple of float

sqrt(2*mean(r**2)) about the fluence centroid, the first 1/e^2 radius, and FWHM in m. Empty beams return three NaNs. Ring profiles or thresholds outside the largest inscribed sampled circle have NaN interpolated widths. On a line the moment is 2*sqrt(mean(x**2)) about the centroid, which is the 1/e^2 half-width of a Gaussian fluence as the plane’s is its 1/e^2 radius, and the threshold widths average the two sides of the centroid.

Raises:
GridError

If axes, samples or finite moments are invalid.

Notes

Radial averages sample the bilinear interpolant at half the finest pixel spacing in radius and at an angular spacing no larger than that arc length on the largest ring. The manual derives the associated interpolation error; scalar widths do not silently select the x or y line through the peak.

solprop.spatial.check_aperture_profile(kind)[source]#

Refuse, by name, anything that is not one of the aperture edge profiles.

The one check behind aperture_profile(), ApertureTables and solprop.stats.ApertureSet. It takes any object, because a caller outside the test session’s runtime type checker can pass anything.

Parameters:
kindobject

The profile asked for.

Raises:
OutputError

If kind is not in APERTURE_PROFILES.

Examples

>>> from solprop.spatial import check_aperture_profile
>>> check_aperture_profile("rcos") is None
True
solprop.spatial.critical_power(wavelength, chi3, *, index, space=None)[source]#

Return the physical Townes critical-power baseline.

This is the scalar, monochromatic, paraxial Kerr lower threshold. It is a diagnostic reference for an exact-UPPE pulse, whose dispersion, bandwidth, evanescent model and losses can change the focusing dynamics; it is not a broadband collapse prediction. Power is the axial Poynting flux n0*eps0*c*integral(|E_a|^2 dS)/2 of the paraxial beam in the medium, as every spatial energy statistic measures it (SEP 34).

Parameters:
wavelengthfloat

Vacuum wavelength in m, finite and positive.

chi3float

Absolute positive Kerr susceptibility in m^2/V^2, including number density.

indexfloat

Real refractive index n0 of the medium at the carrier, finite and positive.

spaceRadialGrid, FreeGrid, PlanarGrid or None, optional

The grid the power is to be compared on, when there is one. A solprop.grid.LineGrid is refused: a beam uniform in y has one free transverse dimension, where Kerr self-focusing does not collapse. A solprop.modes.slab.PlanarGrid is admitted: its field has both transverse dimensions, and the value is the material scale its focusing and modulational-instability lengths are quoted against (Notes).

Returns:
float

Critical-power baseline in W. The numerical Townes mass is quoted to six significant figures; no accuracy beyond that is implied.

Raises:
MaterialError

If the wavelength, susceptibility or index is nonpositive or nonfinite, or they yield a power outside the finite positive floating-point range.

GridError

If space is a solprop.grid.LineGrid.

Notes

The fundamental scalar response gives g=3*k*chi3/(8*n**2) multiplying |A|^2*A. Rescaling the paraxial equation gives Q''+Q'/r-Q+Q**3=0. Its radial mass integral(Q**2 r dr)=1.86226 gives a threshold in integral(|E_a|^2 dS) in which the index cancels; the paraxial power n0*eps0*c/2 times it is Pcrit=1.86226*n0*eps0*c*wavelength**2/(3*pi*chi3). This mass is rounded from the independent boundary-value calculation; the approximate 1.86225 printed in [1] is lower by 5.52049e-6.

A Gaussian’s negative-Hamiltonian sufficient threshold has radial mass 2, above the Townes baseline. Twice this baseline exceeds that Gaussian sufficient threshold, while the actual collapse distance remains a diagnostic.

On a line uniform in y the (1+1)-D equation has no collapse and no critical power: its stationary beam is the stable soliton sech(x/x0), whose power per metre of y is 8*n0*eps0*c/(3*k0**2*chi3*x0) for every width x0 (docs/guide/free-space/model.md). The refusal says so rather than returning a number in W that a power in W/m cannot be compared with.

On a planar grid resolved in y the value is the same material quantity, and it is the scale Arnold et al. (2009, section 2.1) quote a planar compressor against: with Pc = 2 pi n0 / (k0**2 n2), “the critical power for 2D collapse”, they write the whole-beam self-focusing length and the length of the modulational instability in y in terms of P/Pc of the beam’s power in the guide. The plates bound x, so the whole beam does not collapse as it would in free space, but a multimode x basis can still focus in x, and the ratio is the one their stability criterion uses. With n2 = 3 chi3 / (4 eps0 c n0**2) their Pc is 2 n0**2 / 1.86226 times this value: the Gaussian mass 2 against the Townes mass, and the n0**2 of that n2 convention, one to about 1e-3 in a gas. Convert when comparing with their numbers.

References

[1]

G. Fibich and A. L. Gaeta, Opt. Lett. 25, 335-337 (2000), doi:10.1364/OL.25.000335, equations (6)-(8).

[2]

C. L. Arnold et al., Opt. Express 17, 11122-11129 (2009), doi:10.1364/OE.17.011122, section 2.1.

solprop.spatial.fwhm_r(spectrum, flux)[source]#

Return the central fluence profile’s full width at half maximum.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m or Cartesian spectrum in V/m, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure on a radial or Cartesian grid.

Returns:
float

Twice the interpolated half-maximum radius in m, or NaN for an empty profile, one whose axis fluence lies below half the peak (hollow) or one that never falls below it.

Raises:
GridError

If the spectrum is invalid, the grid is planar, or the fluence is negative beyond its rounding budget.

solprop.spatial.mask_plane_radius(scale, k_x, k_y, centre)[source]#

Return how far each column’s mask-plane image lies from an aperture’s centre.

Equation (4) of SEP 23, \(\rho=\sqrt{(s k^{(s)}_x+X)^2+(s k^{(s)}_y+Y)^2}\), with the stored column axes \(k^{(s)}\) (the physical wavevector is their negation, section 4.1) and the physical centre (X, Y). It is evaluated as written – products, sums, two squares, a sum and a correctly rounded square root, never hypot – so a hard edge decides identically on every backend that does the same.

Parameters:
scalenumpy.ndarray

The aperture’s row of aperture_scale(), m^2, shape (n_omega,).

k_x, k_ynumpy.ndarray

Each column’s stored transverse wavevector in rad/m, shape (n_chunk,).

centresequence of float or numpy.ndarray

The aperture centre (X, Y) in the mask plane, physical axes, in m.

Returns:
numpy.ndarray

Distances in m, shape (n_chunk, n_omega).

Examples

>>> import numpy as np
>>> from solprop.spatial import mask_plane_radius
>>> scale, k_x, k_y = np.array([1.0]), np.array([-3.0]), np.zeros(1)
>>> radius = mask_plane_radius(scale, k_x, k_y, (3.0, 4.0))
>>> radius.tolist()
[[4.0]]
solprop.spatial.on_axis_intensity(spectrum, flux)[source]#

Return the largest signed axial flux in time on the beam axis.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m or Cartesian spectrum in V/m, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure.

Returns:
float

Peak on-axis axial flux in W/m^2, summed over polarisation.

Raises:
GridError

If the spectrum is invalid.

solprop.spatial.on_axis_spectrum(spectrum, flux)[source]#

Return the on-axis spectral fluence density summed over polarisation.

The same-frequency real pairing of the coherent on-axis E and G, not a squared coherent field sum: each transverse column carries its own admittance.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m or Cartesian spectrum in V/m, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure.

Returns:
numpy.ndarray

Real spectral fluence in J s/m^2 per angular frequency bin, shape (n_omega,). Its sum times grid.d_omega is the on-axis fluence. It is a density, so changing Fourier convention leaves it unchanged.

Raises:
GridError

If the spectrum is invalid.

solprop.spatial.peak_field(grid, space, spectrum)[source]#

Return the largest physical analytic field magnitude at any node and time.

A named electric-field diagnostic, max sqrt(sum_pol |E_a|^2) in V/m: the physical field that drives ionisation rates, not an axial flux (SEP 34).

Parameters:
gridsolprop.grid.TimeGrid

Temporal grid.

spacesolprop.grid.RadialGrid, solprop.grid.FreeGrid or PlanarGrid

Transverse geometry.

spectrumnumpy.ndarray

Internal radial spectrum in V m, Cartesian spectrum in V/m or planar slab amplitudes, shape (n_modes, n_pol, n_omega).

Returns:
float

Peak field amplitude in V/m.

Raises:
GridError

If the spectrum’s shape or finiteness is invalid.

solprop.spatial.physical_evanescent_rate(space, medium, grid, *, z=0.0)[source]#

Return the largest physical evanescent field attenuation the grid holds.

The largest \(|\operatorname{Im}k_z|\) over the active frequencies and the columns whose \(\operatorname{Re}(k^2 - k_\perp^2) \le 0\) (SEP 22 section 4.4), from attenuation_extremes(): the rate at which a non-propagating component decays physically, which the declared model caps at EVANESCENT_RATE. Pass it as SimulationSettings(evanescent_rate=...) for a thin sample whose evanescent content must decay as it does; the exponent budget then bounds the replayed step (docs/guide/free-space/model.md).

Parameters:
spacesolprop.grid.FreeGrid or solprop.grid.RadialGrid

The transverse grid; a solprop.grid.LineGrid is a FreeGrid. A solprop.modes.slab.PlanarGrid, whose columns are slab channels, is refused.

mediumSpatialMedium

The bulk medium.

gridsolprop.grid.TimeGrid

The temporal grid; its active band is searched.

zfloat, optional

Where the medium is sampled, m. Default 0.

Returns:
float

The rate in m^-1. A grid without an evanescent pair returns EVANESCENT_RATE, since the cap is then inert.

Raises:
GridError

If space is neither Cartesian nor radial.

Examples

>>> from solprop.grid import EnvelopeGrid, FreeGrid
>>> from solprop.spatial import SpatialMedium, physical_evanescent_rate
>>> grid = EnvelopeGrid.from_limits(1e-3, 800e-9, (700e-9, 900e-9), 200e-15)
>>> space = FreeGrid(radius_x=20e-6, n_x=64, radius_y=20e-6, n_y=64)
>>> rate = physical_evanescent_rate(space, SpatialMedium(1.45 + 0j), grid)
>>> rate > 1e6
True
solprop.spatial.planar_fluence(spectrum, flux)[source]#

Return a planar beam’s signed time-integrated axial flux at its nodes.

The coherent synthesis of SEP 34 §4.3: E and G are both built from the slab mode functions, G with each column’s complex admittance eps0 c**2 q / omega applied first, so the modes’ local interference remains.

Parameters:
spectrumnumpy.ndarray

Internal (p, k_y) spectrum of slab amplitudes in sqrt(W/m), shape (n_p*n_y, 1, n_omega).

fluxSpatialFlux

The plane’s measure on a solprop.modes.slab.PlanarGrid.

Returns:
numpy.ndarray

Fluence in J/m^2 at the nodes (x[ix], y[iy]), flattened ix + n_x*iy, shape (n_x*n_y,).

Raises:
GridError

If the spectrum is invalid or the grid is not planar.

solprop.spatial.planar_intensity(spectrum, flux)[source]#

Return a planar beam’s signed local axial flux at its nodes in time.

Parameters:
spectrumnumpy.ndarray

Internal (p, k_y) spectrum of slab amplitudes in sqrt(W/m), shape (n_p*n_y, 1, n_omega).

fluxSpatialFlux

The plane’s measure on a solprop.modes.slab.PlanarGrid.

Returns:
numpy.ndarray

Flux in W/m^2 at the nodes (x[ix], y[iy]), flattened ix + n_x*iy, shape (n_x*n_y, n_t).

Raises:
GridError

If the spectrum is invalid or the grid is not planar.

Examples

>>> import numpy as np
>>> from solprop.grid import EnvelopeGrid
>>> from solprop.modes import PlanarGrid, SlabMode
>>> from solprop.spatial import SpatialFlux, SpatialMedium, planar_intensity
>>> grid = EnvelopeGrid.from_limits(0.1, 800e-9, (650e-9, 1000e-9), 600e-15)
>>> space = PlanarGrid([SlabMode(63.5e-6)], 1e-3, 8)
>>> flux = SpatialFlux.resolve(grid, space, SpatialMedium(1.0))
>>> spectrum = np.zeros((space.n_columns, 1, grid.n_omega), complex)
>>> planar_intensity(spectrum, flux).shape == (space.x.size * 8, grid.n_t)
True
solprop.spatial.planar_mode_energy(spectrum, flux)[source]#

Integrate a planar beam’s physical energy in each slab mode.

The explicit slab metric of SEP 34 §4.3: \(U_p=\frac{\Delta t}{N_t}\frac{\Delta y}{N_y}\sum_{\ell,k}\gamma_kw_{p\ell k} |\hat A_{p\ell k}|^2\) with \(w=c\operatorname{Re}q/\omega\) and \(q=\sqrt{(\omega n_{{\rm eff},p}/c)^2-k_y^2}\). At k_y = 0 the weight is the mode’s real effective index, not the bulk index.

Parameters:
spectrumnumpy.ndarray

Internal (p, k_y) spectrum of slab amplitudes in sqrt(W/m), shape (n_p*n_y, 1, n_omega), the channel fastest.

fluxSpatialFlux

The plane’s measure on a solprop.modes.slab.PlanarGrid.

Returns:
numpy.ndarray

Energy in J per mode, shape (n_p,), in the modes’ order. Their sum is spatial_energy().

Raises:
GridError

If the spectrum is invalid or the grid is not planar.

solprop.spatial.plane_sample(medium, z, side)[source]#

Return where to evaluate the medium for a plane, checking its jump side.

A one-sided limit at a declared index jump is the material one rounding unit to that side; away from a jump the plane’s own position.

Parameters:
mediumSpatialMedium

The bulk medium.

zfloat

Finite position of the plane in m.

side{‘before’, ‘after’} or None

Side of a declared jump at z: required there and refused elsewhere.

Returns:
float

The position at which to evaluate the medium, in m.

Raises:
MaterialError

If the position is not finite, or the side is missing, misplaced or invalid.

solprop.spatial.power_trace(spectrum, admittance, weights, grid, scale)[source]#

Return the axial power through a plane in time from column spectra.

Transverse Parseval turns the area integral of \(\tfrac12\operatorname{Re}(E_aG_a^*)\) into a weighted sum over spectral columns of their temporal analytic signals, so no transverse synthesis is needed.

Parameters:
spectrumnumpy.ndarray

Internal column spectra, shape (n_modes, n_pol, n_omega).

admittancenumpy.ndarray

Dimensionless optics-convention admittance c k_z / omega per column and bin, shape (n_modes, n_omega).

weightsnumpy.ndarray

Transverse Parseval weight of each column.

gridsolprop.grid.TimeGrid

Temporal grid.

scalefloat

eps0 c / 2 for fields in V/m, one for slab amplitudes.

Returns:
numpy.ndarray

Power in W (W/m on a line), shape (n_t,), signed and not clipped.

solprop.spatial.quadrature_half_width(half_width, width, kind)[source]#

Return the half-width at which a profile used once integrates a hard hole.

Equation (6) of SEP 23: \(D_q/2=\sqrt{(D/2)^2-4m_2w^2}\), with \(m_2\) from EDGE_MOMENTS. Evaluated there, a symmetric edge’s two-dimensional area \(\pi(r_q^2+\sigma^2)\) is the hard hole’s \(\pi r^2\) exactly (for tanh up to its exponential tail). On a line the edges are straight and the caller passes the half-width unchanged.

Parameters:
half_widtharray_like or float

The hard hole’s half-width D/2 in m, positive.

widtharray_like or float

The edge width w in m, positive; not used for hard.

kind{‘hard’, ‘tanh’, ‘rcos’}

The edge profile; supergauss has no symmetric edge.

Returns:
numpy.ndarray

D_q/2 in m, the broadcast shape of the inputs.

Raises:
OutputError

For supergauss, or where the radicand is not positive.

Examples

>>> import math
>>> from solprop.spatial import quadrature_half_width
>>> value = float(quadrature_half_width(1.0, 0.1, "rcos"))
>>> math.isclose(value, math.sqrt(1 - 4 * (0.25 - 2 / math.pi**2) * 0.01))
True
>>> float(quadrature_half_width(1.0, 0.1, "hard"))
1.0
solprop.spatial.radial_fluence_widths(radius, fluence, weights, axis_fluence)[source]#

Return second-moment radius, first 1/e^2 radius and central FWHM.

Parameters:
radiusarray_like

Increasing positive radial samples in m.

fluencearray_like

Time-integrated intensity in J/m^2 at each radius.

weightsarray_like

Positive transverse integration weights in m^2.

axis_fluencefloat

Independently reconstructed axial fluence in J/m^2.

Returns:
tuple of float

Second-moment radius, central 1/e^2 radius and FWHM in m. The threshold widths are the first outward crossing of a fraction of the peak fluence, the larger of the axis value and the samples; they are NaN when the axis fluence lies below that threshold (a hollow profile at that level) or when the trace never crosses it, as the statistics catalogue specifies.

Raises:
GridError

If samples disagree, radii or weights are invalid, fluence is negative, or the fluence moments cannot be represented by finite floats.

solprop.spatial.spatial_energy(spectrum, flux)[source]#

Integrate the physical energy crossing the plane, in joules.

\(U=\frac{\Delta t}{2N_t}\sum_{j,p,k}v_j\gamma_kY_{z,jk}|\hat E_{jpk}|^2\) (SEP 34 §4.3): the axial Poynting flux of the medium at the plane, integrated over the plane and time. Only the real admittance enters.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m, Cartesian spectrum in V/m or planar slab amplitudes, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure (SpatialFlux.resolve()).

Returns:
float

Energy in J, summed over the beam and polarisations; in J per metre of y on a solprop.grid.LineGrid.

Raises:
GridError

If the spectrum’s shape or finiteness is invalid.

solprop.spatial.spatial_fluence(spectrum, flux)[source]#

Return the signed time-integrated axial flux at the spatial nodes.

\(F=\tfrac12\int\operatorname{Re}(\mathbf E_a\cdot\mathbf G_a^*)\,dt\), with the complex admittance applied before the transverse synthesis and temporal Parseval for the time integral. Broadband or absorbing fields can give a negative local value; it is not clipped.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m, Cartesian spectrum in V/m or planar slab amplitudes, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure.

Returns:
numpy.ndarray

Fluence in J/m^2 at the spatial nodes (planar nodes flattened ix + n_x*iy).

Raises:
GridError

If the spectrum’s shape or finiteness is invalid.

solprop.spatial.spatial_intensity(spectrum, flux)[source]#

Return the signed local axial flux at every spatial node and time sample.

\(S_z=\tfrac12\operatorname{Re}(\mathbf E_a\cdot\mathbf G_a^*)\) in W/m^2, with G reconstructed from the complex admittance in space and time. It is the axial Poynting flux of the declared scalar forward model, not \(|E_a|^2\), and it is not clipped.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m, Cartesian spectrum in V/m or planar slab amplitudes, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure.

Returns:
numpy.ndarray

Flux in W/m^2, shape (n_nodes, n_t).

Raises:
GridError

If the spectrum’s shape or finiteness is invalid.

Examples

>>> import numpy as np
>>> from solprop.grid import EnvelopeGrid, RadialGrid
>>> from solprop.spatial import SpatialFlux, SpatialMedium, spatial_intensity
>>> grid = EnvelopeGrid.from_limits(0.1, 800e-9, (650e-9, 1000e-9), 600e-15)
>>> space = RadialGrid(1e-3, 16)
>>> flux = SpatialFlux.resolve(grid, space, SpatialMedium("Ar", pressure=1.0))
>>> spectrum = np.zeros((16, 1, grid.n_omega), complex)
>>> spatial_intensity(spectrum, flux).shape == (16, grid.n_t)
True
solprop.spatial.spatial_power(spectrum, flux)[source]#

Return the axial power crossing the plane at every time sample.

Parameters:
spectrumnumpy.ndarray

Internal radial spectrum in V m, Cartesian spectrum in V/m or planar slab amplitudes, shape (n_modes, n_pol, n_omega).

fluxSpatialFlux

The plane’s measure.

Returns:
numpy.ndarray

Cycle-averaged power in W (W/m on a line), shape (n_t,). Its time integral is spatial_energy().

Raises:
GridError

If the spectrum’s shape or finiteness is invalid.