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, user_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 a run’s safety ramp (SEP 40), 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. On the hybrid planar kind it acts per(p, k_y)column (SEP 40).- user_ratenumpy.ndarray or None
The user’s share of spectral_rate, in m^-1, shape
(n_omega,); onlyabsorbed_powerreads it, since the operator takes the total.None(the default) is stored as zeros.
- Raises:
- TranslationError
If arrays, scales, frequency counts or the valid interval disagree, the transverse rate is negative or misshaped, or the user’s share is not a share of the spectral rate.
- 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 – each row’s outline of
solprop.spatial.aperture_outline(), whose half-width under quadrature weighting is the correctedD_q/2of a circle or an ellipse (unchanged on a line, whose edges are straight, and on the straight edges of a rectangle or a half-plane) – and the scale table ofsolprop.spatial.aperture_scale(), with the geometry’s column axes, weights and on-axis vector and the spec’s regions. On a line every column haskappa_y = 0and the light is uniform in y, so a rectangle has no y edges to meet: it is a slit of its x width, the row a circle of that diameter forms. 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 = 0, a half-plane bounded in y or an ellipse, which have no meaning uniform in y, or 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 power rates, in the order ofsolprop.spatial.ABSORBED_CHANNELS, are the operator’s spectral rate on every bin, as the stages apply it, less the user’s share, its own channel, which comes last; 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. The user’s share of the spectral rate is the fifth channel; the share and the rest sum to the rate the operator applies, so the channels’ sum is unmoved by the split.- 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(5, 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).