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 field attenuation cap in m^-1. |
|
The side of a declared index jump a flux plane is evaluated on (SEP 34 §4.4). |
|
The edge profile of a far-field aperture (SEP 23 section 4.4). |
|
Every aperture edge profile, in the order of their integer profile codes. |
|
The first moment |
|
The five statistics |
|
The far-field statistic that needs the run's linear operator. |
|
The channels of |
|
Per-chunk admittance and absorption rates of the plane's medium (SEP 34). |
Functions
|
Return an aperture's profile |
|
Return the paraxial mask-plane scale |
|
Form the far-field statistics of one Cartesian or line spectrum (SEP 23). |
|
Return each frequency's extreme field attenuations over the columns. |
|
Measure a beam radius from its time-integrated axial flux. |
|
Measure centroid-based moments and radially averaged Cartesian widths. |
|
Refuse, by name, anything that is not one of the aperture edge profiles. |
|
Return the physical Townes critical-power baseline. |
|
Return the central fluence profile's full width at half maximum. |
|
Return how far each column's mask-plane image lies from an aperture's centre. |
|
Return the largest signed axial flux in time on the beam axis. |
|
Return the on-axis spectral fluence density summed over polarisation. |
|
Return the largest physical analytic field magnitude at any node and time. |
|
Return the largest physical evanescent field attenuation the grid holds. |
|
Return a planar beam's signed time-integrated axial flux at its nodes. |
|
Return a planar beam's signed local axial flux at its nodes in time. |
|
Integrate a planar beam's physical energy in each slab mode. |
|
Return where to evaluate the medium for a plane, checking its jump side. |
|
Return the axial power through a plane in time from column spectra. |
|
Return the half-width at which a profile used once integrates a hard hole. |
|
Return second-moment radius, first 1/e^2 radius and central FWHM. |
|
Integrate the physical energy crossing the plane, in joules. |
|
Return the signed time-integrated axial flux at the spatial nodes. |
|
Return the signed local axial flux at every spatial node and time sample. |
|
Return the axial power crossing the plane at every time sample. |
Classes
|
Hold the constants the far-field statistics read, formed once (SEP 23 §6). |
|
Evaluate exact longitudinal propagation in the existing temporal frame. |
|
The axial-flux measure of one physical plane (SEP 34). |
|
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:
objectHold 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 andsolprop.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,); columnix + n_x*iycarries(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/2orD_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']#
- 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/win 1/m fortanhandrcos, zeros otherwise, shape(n_apertures,): the factoraperture_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']#
- property profile_code: int[source]#
Return the profile’s integer code, its index in
APERTURE_PROFILES.- Returns:
- int
0 for
hard, 1 fortanh, 2 forrcos, 3 forsupergauss.
- 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 ofABSORBED_CHANNELSin 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 andSpatialFlux.admittance()the saved-plane one.
- solprop.spatial.EDGE_MOMENTS: Mapping[str, float] = mappingproxy({'hard': 0.0, 'tanh': 0.2056167583560283, 'rcos': 0.04735763271532445})#
The first moment
m_2of 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\) forrcos, as SEP 23 section 4.5 anddocs/guide/results/statistics.md(Far-field apertures and angular regions) derive them; the tests check both against quadrature.hardneeds no correction;supergausshas 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:
objectEvaluate 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_sqin 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.
- 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
beta0in m^-1 andbeta1in s/m, followingsolprop.linear.Frame, including its fixed overrides.
- 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)**2in 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/2in that band; inactive frequencies are zero.
- Raises:
- MaterialError
If a transverse frequency is negative or nonfinite.
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:
objectThe 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 / omegaof 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.
- property energy_scale: float[source]#
Return the factor turning weighted
|X|^2sums into joules.- Returns:
- float
eps0 c / 2for a field in V/m; one for planar slab amplitudes, whose mode functions already carry it.
- medium: SpatialMedium#
- classmethod resolve(grid, space, medium, *, z=0.0, side=None, evanescent_rate=200.0)[source]#
Resolve the measure of the plane at
zinmedium.- 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.
- space: RadialGrid | FreeGrid | PlanarGrid#
- class solprop.spatial.SpatialMedium(material=1.0, pressure=1.0, temperature=None, susceptibility=None)[source]#
Bases:
objectDescribe 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.
- 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.
- 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.
- susceptibility: GasSusceptibility | None = None#
- solprop.spatial.aperture_profile(radius, half_width, edge, kind)[source]#
Return an aperture’s profile
Wat distances from its centre.How
Wenters depends on the aperture set’s weighting (SEP 23 section 4.6): under"amplitude"weighting (the default) it is the field transmission, andaperture_spectrumweighs the collected power byW**2; under"quadrature"weighting it weighs the power itself, once. The on-axis amplitude behind the aperture appliesWonce under both weightings.With
rthe half-width andt = (rho - r)/w, the four profiles of SEP 23 section 4.4 are:hard, one forrho <= rand zero beyond;tanh, \(\tfrac12[1-\tanh t]\);rcos, \(\tfrac12[1-\sin(\pi t/2)]\) withtclipped to[-1, 1], exactly one insider - wand exactly zero outsider + w; andsupergauss, \(\exp[-(\rho/r)^n]\).tanhandrcossatisfy 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
rin m, finite and positive:D/2under amplitude weighting, the correctedD_q/2under quadrature weighting (quadrature_half_width()).- edgefloat
The edge width
win m fortanhandrcos(finite and positive), the ordernforsupergauss(finite, at least 2); not used forhard.- 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 / omegaof each aperture.Equation (3) of SEP 23: a plane-wave component of transverse wavevector
kappareaches the mask plane atx = s kappa. The table is formed as(z * c) / omegaand 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 byabsorbed_power.- chunkint or None, optional
Columns per chunk, at least 1;
Nonebounds the chunk’s temporaries at 64 MiB.
- Returns:
- dict
Each requested statistic:
aperture_spectrumandregion_spectrumin J/(rad/s), shapes(n_apertures, n_omega)and(n_regions, n_omega);aperture_on_axis_spectrumin J s/m^2,(n_apertures, n_omega);beam_spectrumin J/(rad/s),(n_omega,);absorbed_powerin J/m,(4,), in the order ofABSORBED_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.SeparableOperatorstores them;Noneis 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 (-infand+infwhere 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.
xhas at least two samples, and so hasyexcept on a line uniform in y (solprop.grid.LineGrid), whereyis 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 is2*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(),ApertureTablesandsolprop.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)/2of 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
n0of 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.LineGridis refused: a beam uniform in y has one free transverse dimension, where Kerr self-focusing does not collapse. Asolprop.modes.slab.PlanarGridis 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 givesQ''+Q'/r-Q+Q**3=0. Its radial massintegral(Q**2 r dr)=1.86226gives a threshold inintegral(|E_a|^2 dS)in which the index cancels; the paraxial powern0*eps0*c/2times it isPcrit=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 is8*n0*eps0*c/(3*k0**2*chi3*x0)for every widthx0(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 ofP/Pcof 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. Withn2 = 3 chi3 / (4 eps0 c n0**2)theirPcis2 n0**2 / 1.86226times this value: the Gaussian mass 2 against the Townes mass, and then0**2of thatn2convention, 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, neverhypot– 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
EandG, 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 timesgrid.d_omegais 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 atEVANESCENT_RATE. Pass it asSimulationSettings(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.LineGridis aFreeGrid. Asolprop.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:
EandGare both built from the slab mode functions,Gwith each column’s complex admittanceeps0 c**2 q / omegaapplied 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]), flattenedix + 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]), flattenedix + 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 = 0the 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 isspatial_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 / omegaper column and bin, shape(n_modes, n_omega).- weightsnumpy.ndarray
Transverse Parseval weight of each column.
- gridsolprop.grid.TimeGrid
Temporal grid.
- scalefloat
eps0 c / 2for 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 (fortanhup 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/2in m, positive.- widtharray_like or float
The edge width
win m, positive; not used forhard.- kind{‘hard’, ‘tanh’, ‘rcos’}
The edge profile;
supergausshas no symmetric edge.
- Returns:
- numpy.ndarray
D_q/2in 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
Greconstructed 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 isspatial_energy().
- Raises:
- GridError
If the spectrum’s shape or finiteness is invalid.