solprop.translate.spatial#
Freeze spatial geometry and separable coefficients for the kernel contract.
These records contain arrays and scalars only. Geometry is independent of the
temporal grid. A separable operator keeps frequency-only material coefficients and
one transverse-frequency square per column, avoiding a full coefficient volume.
Kernel schema 15 adds the hybrid planar kind "slab" (slab modes in x, an FFT in
y) and the one per-channel table it needs, kappa_sq.
Functions
|
Form the far-field statistics' tables once, for every backend (SEP 23 §6). |
|
Return the dimensionless forward admittance |
|
Return a chunk's admittance and absorption rates for the far-field statistics. |
|
Return the longitudinal wave number, its propagating test and its field rate. |
|
Bound the real part of a separable operator without forming it. |
|
Evaluate a separable operator and prefactor for the host reference. |
Classes
|
The plane-measure coefficients of a spatial run at any position (SEP 34). |
|
Bounds on a separable operator's real part, for the exponent budget. |
|
Store a constant spatial operator and prefactor without coefficient volumes. |
|
Carry spatial axes, quadrature, reconstruction and absorption across the seam. |
- class solprop.translate.spatial.FluxPlan(base, material=None, admission=None)[source]#
Bases:
objectThe plane-measure coefficients of a spatial run at any position (SEP 34).
Kernel schema 35. The run’s statistics read the axial admittance of the medium at the plane they measure through
at(): a uniform medium’s is the run’s own separable coefficients, and a radial gas path’s replaces the material square by its z table, so the root islongitudinal_root()’s at that position.- Attributes:
- baseSeparableOperator
Transverse squares, wall terms and active band, with the material square at the entrance.
- materialsolprop.translate.chebyshev.PiecewiseChebyshev or None
The complex material square
(omega n(omega, z) / c)**2in m^-2 along z, value shape(n_omega,), for a radial medium that varies; None for a uniform medium.- admissionsolprop.adiabatic.AdiabaticAdmission or None
The varying path’s adiabatic certificate (SEP 34 section 4.5); None for a uniform medium, which needs none.
- admission: AdiabaticAdmission | None = None#
- at(z)[source]#
Return the coefficients of the plane at
z.- Parameters:
- zfloat
Position in m inside the translated span.
- Returns:
- SeparableOperator
The coefficients whose root is the plane’s
k_z.
- base: SeparableOperator#
- material: PiecewiseChebyshev | None = None#
- class solprop.translate.spatial.RateBounds(loss, gain, propagating, evanescent, spectral, transverse)[source]#
Bases:
objectBounds on a separable operator’s real part, for the exponent budget.
SEP 22 section 4.5: the decaying factor
exp(lambda_minus h)of the inverse propagator and the growing oneexp(lambda_plus h)of a gain medium overflow once their exponent passeslog(DBL_MAX). Each bound is the largest over the frequencies of a sufficient per-frequency bound, and the terms are those of the frequency where the loss bound is largest.- Attributes:
- lossfloat
lambda_minus, a bound onmax(-Re D)in m^-1, nonnegative.- gainfloat
lambda_plus, a bound onmax(Re D)in m^-1, nonnegative.- propagatingfloat
The largest propagating attenuation at the binding frequency, m^-1.
- evanescentfloat
The capped evanescent attenuation there,
min(|Im k_z|, evanescent_rate).- spectralfloat
Half the spectral rate there.
- transversefloat
Half the transverse collar’s largest rate, applied on active frequencies.
- class solprop.translate.spatial.SeparableOperator(k_squared, kperp_sq, k_squared_low, kperp_sq_low, frame, spectral_rate, prefactor_numerator, prefactor_clamped, active, evanescent_rate, n_pol, z_span, kappa_sq=None, kperp_rate=None)[source]#
Bases:
objectStore a constant spatial operator and prefactor without coefficient volumes.
- Attributes:
- k_squarednumpy.ndarray
Shared complex material wave-number square in m^-2, shape
(n_omega,).- kperp_sqnumpy.ndarray
Transverse wave-number square in m^-2, shape
(n_modes,), nonnegative.- k_squared_lownumpy.ndarray
Complex residual of the material square in m^-2, shape
(n_omega,).- kperp_sq_lownumpy.ndarray
Real residual of the transverse square in m^-2, shape
(n_modes,).- framenumpy.ndarray
Shared real frame subtraction in m^-1, shape
(n_omega,).- spectral_ratenumpy.ndarray
Shared spectral power absorption in m^-1, shape
(n_omega,), nonnegative.- prefactor_numeratornumpy.ndarray
Shared purely imaginary numerator of the nonlinear prefactor, with the temporal crop scale included, shape
(n_omega,).- prefactor_clampednumpy.ndarray
Shared prefactor when the real longitudinal square is nonpositive, with the temporal crop scale included, shape
(n_omega,).- activenumpy.ndarray
Physical frequency mask, bool, shape
(n_omega,).- evanescent_ratefloat
Largest evanescent field attenuation rate in m^-1, positive and finite.
- n_polint
State polarisation components, 1 or 2; every coefficient is shared by them.
- z_spantuple of float
Valid propagation interval in m, finite and increasing.
- kappa_sqnumpy.ndarray or None
Kernel schema 15, the hybrid planar kind only: each slab channel’s complex transverse wave-number square
kappa_p(omega)**2 = k_squared - beta_p(omega)**2in m^-2, shape(n_channels, n_omega), wherebeta_p = omega n_eff,p / cis the mode’s own complex propagation constant (the wall term under the mode’s loss policy). Columncbelongs to channelc % n_channels(the channel index fastest). Zero at inactive frequencies.None(the default) for every other kind, which leaves the operator exactly as before.- kperp_ratenumpy.ndarray or None
Kernel schema 31: the transverse-wavevector power absorption rate
alpha_perpof asolprop.boundaries.TransverseCollar, in m^-1, one per column, shape(n_modes,), finite and nonnegative. It enters the operator on the active band only, beside the spectral rate,D -= alpha_perp / 2(SEP 22 section 5.3), and never the unitary phase.None(the default) is stored as zeros, whose operator is today’s to the last bit. Refused nonzero on the hybrid planar kind.
- Raises:
- TranslationError
If arrays, scales, frequency counts or the valid interval disagree, or the transverse rate is negative, misshaped or set on the hybrid planar kind.
- active: Bool[ndarray, 'n_active']#
- frame: Float[ndarray, 'n_frame']#
- k_squared: Complex[ndarray, 'n_k']#
- k_squared_low: Complex[ndarray, 'n_k_low']#
- kperp_sq: Float[ndarray, 'n_transverse']#
- kperp_sq_low: Float[ndarray, 'n_transverse_low']#
- property n_channels: int[source]#
Return the number of slab channels the columns cycle through.
- Returns:
- int
The rows of kappa_sq, or 1 when it is absent.
- prefactor_clamped: Complex[ndarray, 'n_clamped']#
- prefactor_numerator: Complex[ndarray, 'n_numerator']#
- spectral_rate: Float[ndarray, 'n_spectral_rate']#
- class solprop.translate.spatial.SpatialGeometry(kind, shape, axes, spectral_axes, spatial_weights, spectral_weights, coordinates, window, absorber_rate, on_axis, forward_scale, inverse_scale)[source]#
Bases:
objectCarry spatial axes, quadrature, reconstruction and absorption across the seam.
- Attributes:
- kind{‘radial’, ‘free’, ‘slab’}
Radial QDHT, Cartesian FFT, or the hybrid planar transform: slab modes in x (the transform’s own synthesis and projection on the slab rule) times an FFT in y. Modal transforms carry no such record.
- shapetuple of int
(n_r,)or(n_x, n_y): the physical node grid. Cartesian columnix + n_x*iyhas x fastest. Every entry is at least 2, exceptn_y = 1for a line uniform in y, whose one y sample isy = k_y = 0with unit measure (per metre of y). For"slab",n_xcounts the slab rule’s x nodes and the state’s columns are(p, k_y),p + n_p*iywith the mode index fastest, son_modes = n_p*n_ywhilen_nodes = n_x*n_y.- axestuple of numpy.ndarray
(r,)or(x, y), float64 in m, strictly increasing. A slab’s x axis is its quadrature nodes inside the gap, not uniformly spaced.- spectral_axestuple of numpy.ndarray
(k_r,)or(k_x, k_y), in rad/m; for"slab"(k_y,)alone, the x direction’s spectrum being the mode index. Cartesian axes are in FFT order.- spatial_weightsnumpy.ndarray
Physical area weights in m^2, shape
(n_nodes,)in node order.- spectral_weightsnumpy.ndarray
Parseval weights for the stored transverse spectrum, shape
(n_modes,). Units are m^-2 for radial Hankel spectra and m^2 for Cartesian raw DFTs. A slab column is a modal amplitude in sqrt(W/m) and its weight2 dy / (eps0 c n_y)is the raw DFT’sdy/n_ydivided byeps0 c / 2, in m ohm, so that the commoneps0 c / 2energy measure gives joules on every kind.- coordinatesnumpy.ndarray
(r, 0)or(x, y)per physical node, in m, shape(n_nodes, 2).- windownumpy.ndarray
Spatial collar window in [0, 1], shape
(n_nodes,). For"slab"it is the y collar alone, the same at every x node of a row.- absorber_ratenumpy.ndarray
In-stage spatial power absorption rate, in 1/m, shape
(n_nodes,); for"slab"a function of y alone, like window.- on_axisnumpy.ndarray
Linear reconstruction weights from transverse spectral columns to the axis, complex128, shape
(n_modes,). Temporal oversampling is not folded in.- forward_scalefloat
Common transverse forward scaling; m^2 radially, dimensionless for the FFT.
- inverse_scalefloat
Common transverse inverse scaling; m^-2 radially, dimensionless for the FFT (
1/n_yfor the slab’s y transform).
- Raises:
- TranslationError
If dimensions, axes, measures, collar values or scalings disagree.
- absorber_rate: Float[ndarray, 'n_rate']#
- coordinates: Float[ndarray, 'n_points 2']#
- property n_columns: int[source]#
Return the number of state columns the geometry describes.
- Returns:
- int
n_rorn_x*n_yfor the radial and Cartesian kinds, where columns and nodes coincide, andn_p*n_yfor a slab, where they do not.
- on_axis: Complex[ndarray, 'n_axis_columns']#
- spatial_weights: Float[ndarray, 'n_area']#
- spectral_weights: Float[ndarray, 'n_spectral_area']#
- window: Float[ndarray, 'n_window']#
- solprop.translate.spatial.aperture_tables(spec, grids, geometry)[source]#
Form the far-field statistics’ tables once, for every backend (SEP 23 §6).
The per-aperture constants – the profile’s half-width,
D/2or, under quadrature weighting, the correctedD_q/2ofsolprop.spatial.quadrature_half_width()(unchanged on a line, whose edges are straight) – and the scale table ofsolprop.spatial.aperture_scale(), with the geometry’s column axes, weights and on-axis vector and the spec’s regions. Every backend calls this at construction andsolprop.stats.collect()calls it for a saved plane, so all of them use the same scale to the bit.- Parameters:
- specsolprop.stats.StatsSpec
The request and its far-field tables.
- gridssolprop.translate.masks.Grids or solprop.grid.TimeGrid
Anything carrying the physical frequency axis
omegain rad/s.- geometrySpatialGeometry, solprop.grid.FreeGrid, solprop.grid.RadialGrid or None
The run’s geometry record or a saved plane’s grid.
- Returns:
- solprop.spatial.ApertureTables or None
The tables, or
Nonewhen the spec names no far-field statistic.
- Raises:
- OutputError
For a radial or planar-hybrid geometry or none at all; and on a line, for an aperture whose centre is off
y = 0or a region whosekappa_yinterval excludes zero, which would select nothing.
- solprop.translate.spatial.axial_admittance(coefficients, omega, columns)[source]#
Return the dimensionless forward admittance
c k_z / omegaof a chunk.The physical axial admittance is
eps0 ctimes this value (SEP 34). It is the root oflongitudinal_root()on active propagating bins at positive frequency, in the optics convention (positive imaginary part for loss), and zero elsewhere: a nonpropagating or inactive column is not a forward power port.- Parameters:
- coefficientsSeparableOperator
The plane’s or the run’s constant coefficients.
- omeganumpy.ndarray
Physical angular frequencies in rad/s, shape
(n_omega,).- columnsslice
The transverse columns of the chunk.
- Returns:
- numpy.ndarray
Complex admittance, shape
(n_chunk, n_omega).
Examples
>>> import numpy as np >>> from solprop.constants import C >>> from solprop.translate.spatial import SeparableOperator, axial_admittance >>> omega = np.array([0.0, C, 2 * C]) >>> vacuum = SeparableOperator( ... k_squared=(omega / C) ** 2 + 0j, kperp_sq=np.array([0.0, 2.25]), ... k_squared_low=np.zeros(3, complex), kperp_sq_low=np.zeros(2), ... frame=np.zeros(3), spectral_rate=np.zeros(3), ... prefactor_numerator=np.zeros(3, complex), ... prefactor_clamped=np.zeros(3, complex), ... active=np.array([False, True, True]), evanescent_rate=200.0, n_pol=1, ... z_span=(0.0, 1.0), ... ) >>> np.round(axial_admittance(vacuum, omega, slice(None)).real, 12).tolist() [[0.0, 1.0, 1.0], [0.0, 0.0, 0.661437827766]]
- solprop.translate.spatial.axial_factors(coefficients, omega, columns)[source]#
Return a chunk’s admittance and absorption rates for the far-field statistics.
The weights of the far-field statistics (SEP 23 sections 4.8 and 4.9, measured by SEP 34’s axial flux), from
longitudinal_root(). The admittance isaxial_admittance(). The four power rates, in the order ofsolprop.spatial.ABSORBED_CHANNELS, are the operator’s spectral rate on every bin, as the stages apply it; the transverse collar’s rate on active bins (zero without one);2 min(|Im k_z|, cap)on active evanescent bins; and2 Im k_zon active propagating bins, the material loss (negative for gain). Together they are twice the negated real part of the operator; weighted by the real admittance, their power is the physical flux the linear flow removes. The evanescent channel, whose admittance is zero, removes no physical flux.- Parameters:
- coefficientsSeparableOperator
The run’s constant coefficients.
- omeganumpy.ndarray
Physical angular frequencies in rad/s, shape
(n_omega,).- columnsslice
The transverse columns of the chunk.
- Returns:
- tuple of numpy.ndarray
The dimensionless complex admittance, shape
(n_chunk, n_omega), and the rates in m^-1, shape(4, n_chunk, n_omega).
- solprop.translate.spatial.longitudinal_root(coefficients, columns=None)[source]#
Return the longitudinal wave number, its propagating test and its field rate.
The one evaluation of the root the stages use: the principal square root
k_zof the compensated squareq = (k^2 - k_perp^2) + (k_low^2 - k_perp,low^2)(with a slab channel’s wall term subtracted last), the testRe q > 0that separates propagating from evanescent columns, and the field attenuation,Im k_zwhere propagating andmin(|Im k_z|, evanescent_rate)where not.separable_values()builds the operator from it, and the far-field statistics read it (axial_factors()), so both see the same root (SEP 23 section 6).- Parameters:
- coefficientsSeparableOperator
Constant coefficients in the internal convention.
- columnsslice or None, optional
Transverse columns to evaluate; None selects all columns.
- Returns:
- tuple of numpy.ndarray
k_zin m^-1 (complex), the propagating mask (bool) and the field attenuation in m^-1, each of shape(n_columns, n_omega). Inactive bins are not masked here: every consumer appliescoefficients.active.
- solprop.translate.spatial.rate_bounds(coefficients)[source]#
Bound the real part of a separable operator without forming it.
The search of
solprop.spatial.attenuation_extremes()per slab channel (one on every kind but the hybrid planar), so the cost isO(n_omega log n_modes). On an active frequency the loss bound is the larger of the propagating attenuation’s positive part and the capped evanescent one, plus half the largest transverse rate, plus half the spectral rate; on an inactive one it is half the spectral rate alone (SEP 22, Q6). The gain bound is the negated smallest propagating attenuation where it is negative.- Parameters:
- coefficientsSeparableOperator
The operator.
- Returns:
- RateBounds
The bounds and the binding frequency’s terms.
Examples
>>> import numpy as np >>> from solprop.translate.spatial import SeparableOperator, rate_bounds >>> operator = SeparableOperator( ... k_squared=np.array([0j, 4 + 0j]), kperp_sq=np.array([0.0, 9.0]), ... k_squared_low=np.zeros(2, complex), kperp_sq_low=np.zeros(2), ... frame=np.zeros(2), spectral_rate=np.array([6.0, 0.0]), ... prefactor_numerator=np.zeros(2, complex), ... prefactor_clamped=np.zeros(2, complex), ... active=np.array([False, True]), evanescent_rate=2.0, n_pol=1, ... z_span=(0.0, 1.0), kperp_rate=np.array([0.0, 4.0]), ... ) >>> bounds = rate_bounds(operator) >>> bounds.loss, bounds.evanescent, bounds.transverse (4.0, 2.0, 2.0)
- solprop.translate.spatial.separable_values(coefficients, columns=None)[source]#
Evaluate a separable operator and prefactor for the host reference.
The reference may select bounded transverse columns. Compiled backends evaluate the same formula per element and retain only shared vectors.
- Parameters:
- coefficientsSeparableOperator
Constant coefficients, already validated and in the internal convention.
- columnsslice or None, optional
Transverse columns to evaluate; None selects all columns.
- Returns:
- tuple of numpy.ndarray
Linear rate in m^-1, shape
(1, n_modes, n_pol, n_omega), and nonlinear prefactor, shape(n_modes, n_pol, n_omega).