solprop.coupling.remap#
Move a field plane onto another temporal lattice, or another reference.
The one controlled temporal conversion of SEP 31 (section 4.5). Three things are kept apart: the sign convention (a plane’s samples are already optics-convention), the raw DFT’s time origin (the window centre) and its amplitude scaling. With \(s_k\) a plane’s stored spectrum, its normalised analytic spectral density is
\(q_k = 2\) on interior positive bins of a field grid, 1 at its zero-frequency and Nyquist bins, and 1 on an envelope grid, so that \(\Delta\omega\sum_k f_k^\dagger Q_k f_k\) is the energy in the native metric Q. Copying raw DFT amplitudes between lattices of different N or Δt is not this operation; copying f between identical physical frequencies is.
The map. The source record is the analytic signal at its own time samples, \(a_j = N^{-1}\sum_k q_k s_k e^{-i\omega_k t_j}\), zero outside its window. A target bin of absolute frequency \(\omega'_m\) receives its finite-time Fourier sum
with \(\Delta = \tau - \tau'\) and \(\Delta\phi = \phi - \phi'\) the change of
reference (PlaneReference), so that the absolute
spectrum is unchanged. The sum is evaluated only on target bins inside the source
lattice’s own span: beyond it the sum of samples spaced Δt repeats with period 2π/Δt
and returns aliases of the record, not light. The direct sum is the reference
implementation; it is evaluated in bounded chunks of target bins. The one
acceleration is the identical lattice in an unchanged reference, where the map is the
identity and the samples are copied; the tests check it against the direct sum.
Complex spectral zeros need no special case: no phase is unwrapped and nothing is
interpolated.
What is lost is reported, and what cannot be represented is refused. Light outside the target’s active band, or outside its time window after the shift, is removed only on request (crop_band, truncate), with its share in the report. A record whose edges carry light, or whose exterior is unknown, is not extended into a larger window without truncate, which declares it zero outside. Nothing is renormalised: the energy out is whatever the map gives.
Module Attributes
Share of a record's norm below which a band or a window is unoccupied. |
Functions
|
Convert a plane to another temporal lattice and reference. |
Classes
|
What a temporal conversion did, and what it removed. |
- solprop.coupling.remap.DEFAULT_TOLERANCE = 1e-10#
Share of a record’s norm below which a band or a window is unoccupied.
Ten digits below the record: well above the rounding of a double-precision sum over a few thousand samples (about 1e-13 relative), and well below any share a person would call physical light. A share above it is occupied, and removing it is lossy.
- class solprop.coupling.remap.RegridReport(method, source_lattice, target_lattice, shift, phase_shift, record_norm, window_loss, band_loss, edge_share, truncated, energy_in, energy_out)[source]#
Bases:
objectWhat a temporal conversion did, and what it removed.
The shares are of the source’s record norm: the time-integrated squared analytic signal of every column, weighted by the column’s transverse weight (one for a modal basis, the Parseval weight times
eps0 c / 2for a spatial one), so that on an identity metric it is the energy in joules, and on a spatial one the vacuum-equivalent energy. The energies are physical.- Attributes:
- method{‘copy’, ‘direct’}
Identity copy on an identical lattice and reference, or the direct sum.
- source_lattice, target_latticestr
lattice_identity()of the two grids.- shiftfloat
Record-time shift applied,
old delay - new delay, s.- phase_shiftfloat
Phase applied,
old phase - new phase, rad.- record_normfloat
The source’s record norm, in its units (above).
- window_lossfloat
Share of the record norm outside the target window after the shift.
- band_lossfloat
Share of the record norm outside the target’s active band.
- edge_sharefloat
Share of the record norm inside the source’s temporal collar.
- truncatedbool
Whether the record was declared zero outside its window or cropped to the target’s (truncate).
- energy_infloat or None
Physical energy of the source, J; None when its metric is unknown.
- energy_outfloat or None
Physical energy of the result, J; None when its metric is unknown.
- solprop.coupling.remap.regrid(plane, grid, *, phase=None, delay=None, truncate=False, crop_band=False, tolerance=1e-10, method='auto')[source]#
Convert a plane to another temporal lattice and reference.
The module’s notes give the map. The plane’s transverse representation, basis, geometry and medium are unchanged; only the temporal record moves.
- Parameters:
- planeFieldPlane
The source.
- gridsolprop.grid.TimeGrid
The receiving temporal grid, field or envelope, of any length, spacing and carrier.
- phasefloat or None, optional
The result’s reference phase, rad; None keeps the plane’s.
- delayfloat or None, optional
The result’s reference delay (time origin), s; None keeps the plane’s. A later delay moves the record earlier in the window.
- truncatebool, optional
Declare the record zero outside its window, so that a larger or shifted target may extend it, and allow the part outside the target window to be cut, with its share reported. Default False refuses both.
- crop_bandbool, optional
Allow light outside the target’s active band to be removed, with its share reported. Default False refuses it.
- tolerancefloat, optional
Share of the record norm below which a band or a window counts as unoccupied; default
DEFAULT_TOLERANCE.- method{‘auto’, ‘direct’}, optional
'auto'copies on an identical lattice in an unchanged reference and evaluates the direct sum otherwise;'direct'always evaluates it.
- Returns:
- tuple
The converted
FieldPlaneand itsRegridReport.
- Raises:
- CouplingError
If the target band cannot hold the occupied frequencies, the target window the record, or a nonlocalised or unknown-exterior record would be extended, without the matching permission; or a value is invalid.
Examples
>>> import numpy as np >>> from solprop.coupling import FieldPlane, PlaneBasis, PlaneGeometry, regrid >>> from solprop.coupling import basis_identity >>> from solprop.fourier import spectrum_to_optics >>> from solprop.grid import EnvelopeGrid >>> from solprop.pulses import GaussianPulse >>> source = EnvelopeGrid.from_limits(1.0, 800e-9, (600e-9, 1.2e-6), 1e-12) >>> target = EnvelopeGrid.from_limits(1.0, 800e-9, (500e-9, 1.5e-6), 2e-12) >>> pulse = GaussianPulse(wavelength=800e-9, fwhm=30e-15, energy=1e-6) >>> samples = spectrum_to_optics(pulse.build(source), kind="envelope") >>> basis = PlaneBasis("modal", basis_identity("modal", {"modes": ["one"]})) >>> plane = FieldPlane.from_samples(samples, source, PlaneGeometry(0.0), ... exterior="zero", basis=basis) >>> moved, report = regrid(plane, target) >>> bool(np.isclose(moved.energy(), plane.energy(), rtol=1e-9)) True >>> report.method, report.band_loss < 1e-10 ('direct', True)