solprop.coupling.plane#

One physical plane of an ultrafast field, with everything needed to use it.

A FieldPlane binds a field’s native coefficients to what they mean (SEP 31, sections 4.1, 4.5 and 5.1): the representation and its units, the temporal lattice, the reference the spectrum is written in, the oriented plane, the medium and power metric there, the scoped path certificate of the run that produced it, and its provenance. It is immutable and owns read-only copies of its arrays, so a validated plane cannot be changed through an alias.

Samples. The stored array is what an output file stores: the optics-convention raw forward DFT of each column, referenced to the centre of the time window (solprop.fourier.spectrum_to_optics()), shape (n_modes, n_pol, n_omega). Its columns are

kind

columns and units

modal

true-power coefficients b = sqrt(Re n_eff) a of an ordinary mode set, sqrt(W); metric the identity

general_modal

general-modal coordinates, sqrt(W); metric the basis Gram

radial

order-zero Hankel spectrum of the electric field, V m

cartesian

transverse raw DFT of the electric field, V/m

planar

slab amplitude per y frequency, sqrt(W/m)

Reference. A run’s spectrum is in its moving frame. The absolute optics-convention spectrum is the stored one times \(\exp[i(\phi + \omega\tau)]\) (PlaneReference), with ω the absolute angular frequency of each bin: τ is the absolute time of the record’s t = 0 and φ a carrier phase. The pair is the frame integral the linear operator removed, \(\int R\,dz\), so a long path never has to translate a femtosecond pulse across its window.

The plane is a P-layer value type: NumPy and other physics modules only. Extracting one from a run is solprop.processing.planes.field_plane(), and a receiving simulation is described by solprop.coupling.port.InputPort.

Module Attributes

PlaneKind

The native representation of a plane's columns.

PLANE_KINDS

Every PlaneKind, in a fixed order.

Exterior

What a finite record says outside its samples: zero, or not known.

Calibration

An affine reference term a plane knows absolutely.

MetricKind

How a plane's native power metric is represented.

AnalyticField

An analytic field: field(r, omega) or field(x, y, omega), see FieldPlane.from_analytic().

Functions

basis_identity(route, record)

Return the identity of a plane's basis: a digest of its route and record.

lattice_identity(grid)

Return the identity of a temporal lattice: its layout, samples and reference.

modal_basis_identity(modes, grid, z)

Return the identity of an ordinary mode set's basis at one plane.

reference_at(record, z)

Return the reference of a run's plane at z from its persisted record.

space_record(space)

Return the JSON-ready record of a transverse grid: its class and arguments.

Classes

AnalyticRecord(support, domain_change, ...)

What a plane sampled from an analytic field declares and was checked for.

FieldPlane(kind, samples, grid, units, ...)

A coherent field at one physical plane, in its native representation.

NodalField(nodes, weights, electric[, magnetic])

A plane's physical electric and magnetic fields at transverse nodes.

PlaneBasis(kind, identity[, labels, space])

What the columns of a plane are, and the identity they are checked by.

PlaneGeometry(z[, side, origin, normal, x_axis])

An oriented physical plane: its position, side, origin and local axes.

PlaneMetric(kind[, matrix, admittance, ...])

The native power metric of a plane's columns at its own position.

PlaneProvenance([source, plane, z, lineage, ...])

Where a plane came from and what was done to it.

PlaneReference([phase, delay, calibrated])

The affine reference a stored spectrum is written in.

solprop.coupling.plane.AnalyticField#

An analytic field: field(r, omega) or field(x, y, omega), see FieldPlane.from_analytic().

alias of Callable[[…], ndarray]

class solprop.coupling.plane.AnalyticRecord(support, domain_change, resolution_change)[source]#

Bases: object

What a plane sampled from an analytic field declares and was checked for.

Attributes:
supportfloat or None

The declared radius beyond which the field is zero, m; None for an unbounded field.

domain_changefloat

Relative change of the plane’s energy when its window is doubled at the same node spacing: the share of the beam the window misses, to leading order.

resolution_changefloat

Relative change of the plane’s energy when the node spacing is halved in the same window: the sampling error of the energy.

domain_change: float#
property error: float[source]#

Return the larger of the two checks, the energy’s numerical error bound.

Returns:
float

max(domain_change, resolution_change), dimensionless.

resolution_change: float#
support: float | None#
solprop.coupling.plane.Calibration#

An affine reference term a plane knows absolutely.

alias of Literal[‘phase’, ‘delay’]

solprop.coupling.plane.Exterior#

What a finite record says outside its samples: zero, or not known.

alias of Literal[‘zero’, ‘unknown’]

class solprop.coupling.plane.FieldPlane(kind, samples, grid, units, basis, reference, geometry, metric, exterior='zero', medium=None, certificate=None, nodal=None, provenance=<factory>, profiles=None, analytic=None)[source]#

Bases: object

A coherent field at one physical plane, in its native representation.

Build one with solprop.processing.planes.field_plane() from a saved run, with from_pulse() from the package’s beam builder, or with from_samples() from arrays; never by hand unless the parts are already validated.

Attributes:
kind{‘modal’, ‘general_modal’, ‘radial’, ‘cartesian’, ‘planar’}

The native representation; the module’s table gives each one’s columns.

samplesnumpy.ndarray

Optics-convention raw spectrum of each column referenced to the window centre, complex128, shape (n_modes, n_pol, n_omega), read-only.

gridsolprop.grid.TimeGrid

The temporal grid: layout (field or envelope), time samples, the absolute frequency of each bin and the carrier (grid.omega0).

unitsstr

Units of samples: "sqrt(W)", "V m", "V/m" or "sqrt(W/m)".

basisPlaneBasis

What the columns are, with their identity.

referencePlaneReference

The affine reference of the stored spectrum.

geometryPlaneGeometry

The oriented plane.

metricPlaneMetric

The native power metric at the plane.

exterior{‘zero’, ‘unknown’}, optional

What the record says outside its samples. A run’s own planes are zero outside their window and grid; a cropped measurement may not be.

mediumsolprop.spatial.SpatialMedium or None, optional

The bulk medium at a spatial plane, when it is at hand.

certificatesolprop.adiabatic.AdiabaticAdmission or None, optional

The path certificate of the producing run through a varying medium (SEP 34, section 4.5), as its record rebuilds it, the path’s identity kept as the recorded text. Its scope is the linear background’s forward field: it bounds the background path, not the nonlinear run or an omitted reflection.

nodalNodalField or None, optional

Physical E (and H) at transverse nodes, for a general modal plane read with its source simulation.

provenancePlaneProvenance, optional

Source identity, plane index, lineage and preparation history.

profilessolprop.coupling.models.ScalarModeBasis or None, optional

The scalar transverse profiles of an ordinary modal plane’s columns, for a plane read with its source simulation; what a coupling model or Outcouple synthesises the field from.

analyticAnalyticRecord or None, optional

The declared support and the domain and resolution checks of a plane sampled from an analytic field (from_analytic()).

Raises:
CouplingError

If the samples are not finite and three-dimensional, or disagree with the grid or the basis kind.

absolute()[source]#

Return the samples in the absolute reference.

Returns:
numpy.ndarray

samples * reference.factor(omega), shape (n_modes, n_pol, n_omega).

Raises:
CouplingError

If the reference is not calibrated in both terms.

analytic: AnalyticRecord | None = None#
basis: PlaneBasis#
certificate: AdiabaticAdmission | None = None#
energy()[source]#

Return the physical energy crossing the plane, J.

Returns:
float

The sum of spectral_energy(); J per metre of y on a line.

exterior: Literal['zero', 'unknown'] = 'zero'#
classmethod from_analytic(grid, geometry, field, *, space, medium=None, index=None, support=None, exterior='zero', reference=None)[source]#

Sample a physical analytic field on a transverse grid (SEP 31, section 5.1).

field is called with the grid’s node positions and the absolute angular frequency of every positive bin, and returns the optics-convention Fourier transform \(\tilde E(\mathbf r,\omega) = \int E(\mathbf r,t) e^{+i\omega t}\,dt\) of the real electric field, in V s/m, with t measured from the plane’s reference time (the window centre, plus reference):

  • on a radial grid field(r, omega) with r of shape (n_nodes,);

  • on a Cartesian grid field(x, y, omega) with x and y of shape (n_nodes,);

each returning shape (n_nodes, n_pol, n_bins) (n_pol 1 for x, 2 for x and y) or (n_nodes, n_bins) for an x-polarised field. A raw DFT bin of a localised record is \(q\tilde E/\Delta t\), with \(q = 1\) on a field grid and 2 on an envelope grid, whose envelope is the analytic signal.

Support and exterior. support declares the field zero beyond a radius (m), where it is not evaluated; without it the field is unbounded and only a convergence check bounds what the window misses. The plane records (AnalyticRecord) the relative change of its energy when the window is doubled at the same spacing (the domain check) and when the spacing is halved in the same window (the resolution check), so a coupling counts both as numerical error rather than assuming a crop is the whole beam. exterior is what the record says beyond the window: 'zero' for a field whose tails the domain check bounds, 'unknown' where they are not known.

Parameters:
gridsolprop.grid.TimeGrid

Temporal grid.

geometryPlaneGeometry

The plane.

fieldcallable

The analytic field, as above.

spacesolprop.grid.RadialGrid or solprop.grid.FreeGrid

Transverse grid.

mediumsolprop.spatial.SpatialMedium or None, optional

The medium at the plane.

indexnumpy.ndarray or None, optional

Real phase index at each bin instead of medium, shape (n_omega,).

supportfloat or None, optional

Radius beyond which the field is declared zero, m; inside the window.

exterior{‘zero’, ‘unknown’}, optional

What the record says beyond its window.

referencePlaneReference or None, optional

Reference of the spectrum; default zero phase and delay.

Returns:
FieldPlane

A radial or Cartesian plane with its admittance metric and its AnalyticRecord.

Raises:
CouplingError

If not exactly one of medium and index is given, the support lies outside the window, or the field returns the wrong shape or nonfinite values.

Examples

>>> import numpy as np
>>> from solprop.coupling import FieldPlane, PlaneGeometry
>>> from solprop.grid import EnvelopeGrid, RadialGrid
>>> grid = EnvelopeGrid.from_limits(1e-3, 800e-9, (700e-9, 900e-9), 300e-15)
>>> def beam(r, omega):
...     spectral = np.exp(-(((omega - grid.omega0) * 20e-15) ** 2))
...     return np.exp(-((r / 50e-6) ** 2))[:, None] * spectral[None, :]
>>> index = np.where(grid.omega > 0, 1.0, 0.0)
>>> plane = FieldPlane.from_analytic(
...     grid, PlaneGeometry(0.0), beam, space=RadialGrid(300e-6, 128),
...     index=index,
... )
>>> plane.analytic.domain_change < 1e-12
True
classmethod from_pulse(pulse, grid, geometry, *, space, medium=None, index=None, reference=None)[source]#

Build a spatial plane from the package’s beam builder.

No second Gaussian is written: the beam is the SpatialPulse’s own, in one of its two measures.

  • With medium, it is solprop.pulses.SpatialPulse.build() on the grid, its requested energy or peak power the physical axial flux through the plane in that medium (SEP 34).

  • With index – the real phase index of a medium for which no SpatialMedium exists, such as a guide’s core – it is solprop.pulses.SpatialPulse.incident() sampled at the grid’s nodes: the request is met over the beam’s whole plane in the paraxial measure \(M_0 = n\varepsilon_0c\,dA/2\), in closed form, and the plane’s metric is the axial admittance \(\sqrt{n^2 - (c\kappa/ \omega)^2}\) of that index. The two measures differ by the beam’s obliquity, which a coupling model reports as its source-measure defect.

The exterior is zero: the closed-form beam is resolved on the grid’s window.

Parameters:
pulsesolprop.pulses.SpatialPulse

The beam, launched at its waist with index.

gridsolprop.grid.TimeGrid

Temporal grid.

geometryPlaneGeometry

The plane; its z and side select the medium’s sample.

spacesolprop.grid.RadialGrid or solprop.grid.FreeGrid

Transverse grid.

mediumsolprop.spatial.SpatialMedium or None, optional

The medium at the plane.

indexnumpy.ndarray or None, optional

Real phase index at each bin, shape (n_omega,), instead of medium; zero on bins that carry no flux.

referencePlaneReference or None, optional

The reference of the built spectrum; default zero phase and delay.

Returns:
FieldPlane

A radial or Cartesian plane with its admittance metric.

Raises:
CouplingError

If pulse is not a spatial beam, or not exactly one of medium and index is given, or the beam builder refuses it.

classmethod from_samples(samples, grid, geometry, *, exterior, space=None, medium=None, basis=None, metric=None, reference=None, profiles=None)[source]#

Bind physical arrays to explicit axes, units, domain, medium and reference.

Two forms. With space and medium, samples is the electric field at the grid’s nodes: optics-convention raw temporal spectra in V/m, referenced to the window centre, shape (n_nodes, n_pol, n_omega); they are transformed to the grid’s native columns and measured with the medium’s axial admittance. With basis (a modal basis), samples is already the optics-convention coefficient spectrum in sqrt(W), shape (n_modes, n_pol, n_omega), measured with metric (the identity by default).

Parameters:
samplesnumpy.ndarray

The arrays, as above.

gridsolprop.grid.TimeGrid

Temporal grid of the samples.

geometryPlaneGeometry

The plane.

exterior{‘zero’, ‘unknown’}

Whether the field is declared zero outside the samples, or unknown there. There is no default: a crop of a measured beam is not a complete beam.

spacesolprop.grid.RadialGrid or solprop.grid.FreeGrid or None, optional

Transverse grid of node samples.

mediumsolprop.spatial.SpatialMedium or None, optional

Medium at the plane, required with space.

basisPlaneBasis or None, optional

Modal basis of coefficient samples, instead of space.

metricPlaneMetric or None, optional

Metric of a modal basis; default the identity.

referencePlaneReference or None, optional

Reference of the spectrum; default zero phase and delay.

profilessolprop.coupling.models.ScalarModeBasis or None, optional

The scalar profiles of an ordinary modal basis’s columns.

Returns:
FieldPlane

The plane.

Raises:
CouplingError

If neither or both forms are given, the shapes disagree, or a spatial form has no medium.

geometry: PlaneGeometry#
grid: TimeGrid#
kind: Literal['modal', 'general_modal', 'radial', 'cartesian', 'planar']#
medium: SpatialMedium | None = None#
metric: PlaneMetric#
nodal: NodalField | None = None#
node_spectra()[source]#

Return a spatial plane’s electric field at its grid’s nodes.

Returns:
numpy.ndarray

Optics-convention raw spectra in V/m, shape (n_nodes, n_pol, n_omega), nodes in the grid’s order.

Raises:
CouplingError

For a plane that is not radial or Cartesian.

property omega: Float[ndarray, 'n_omega'][source]#

Return the absolute angular frequency of each stored bin.

Returns:
numpy.ndarray

Angular frequencies in rad/s, shape (n_omega,), in storage order.

profiles: ScalarModeBasis | None = None#
provenance: PlaneProvenance#
reference: PlaneReference#
samples: Complex[ndarray, 'n_modes n_pol n_omega']#
spectral_energy()[source]#

Return the energy each bin carries through the plane, J.

Returns:
numpy.ndarray

PlaneMetric.spectral_energy() of the samples, shape (n_omega,).

units: str#
solprop.coupling.plane.MetricKind#

How a plane’s native power metric is represented.

alias of Literal[‘identity’, ‘dense’, ‘admittance’, ‘unknown’]

class solprop.coupling.plane.NodalField(nodes, weights, electric, magnetic=None)[source]#

Bases: object

A plane’s physical electric and magnetic fields at transverse nodes.

Attributes:
nodesnumpy.ndarray

Node positions (x, y) in m, shape (n_nodes, 2).

weightsnumpy.ndarray

Area weights in m^2, shape (n_nodes,).

electricnumpy.ndarray

Optics-convention raw spectra of E_x, E_y, E_z in V/m, shape (n_nodes, 3, n_omega).

magneticnumpy.ndarray or None, optional

The same of H in A/m, when the basis supplies it.

electric: Complex[ndarray, 'n_nodes 3 n_omega']#
magnetic: Complex[ndarray, 'n_nodes 3 n_omega'] | None = None#
nodes: Float[ndarray, 'n_nodes 2']#
weights: Float[ndarray, 'n_nodes']#
solprop.coupling.plane.PLANE_KINDS: tuple[Literal['modal', 'general_modal', 'radial', 'cartesian', 'planar'], ...] = ('modal', 'general_modal', 'radial', 'cartesian', 'planar')#

Every PlaneKind, in a fixed order.

class solprop.coupling.plane.PlaneBasis(kind, identity, labels=(), space=None)[source]#

Bases: object

What the columns of a plane are, and the identity they are checked by.

Attributes:
kind{‘modal’, ‘general_modal’, ‘radial’, ‘cartesian’, ‘planar’}

The representation.

identitystr

basis_identity() of the basis: a plane and a port with the same identity have the same columns.

labelstuple of str, optional

Channel labels of a modal basis, in column order.

spacesolprop.grid.RadialGrid, solprop.grid.FreeGrid or None, optional

The transverse grid of a spatial basis.

Raises:
CouplingError

If the identity is not a digest, or a spatial basis has no grid.

identity: str#
kind: Literal['modal', 'general_modal', 'radial', 'cartesian', 'planar']#
labels: tuple[str, ...] = ()#
classmethod of_space(space)[source]#

Return the basis of a spatial grid.

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

The grid.

Returns:
PlaneBasis

radial for a radial grid and cartesian for a Cartesian one.

space: RadialGrid | FreeGrid | None = None#
class solprop.coupling.plane.PlaneGeometry(z, side=None, origin=(0.0, 0.0, 0.0), normal=(0.0, 0.0, 1.0), x_axis=(1.0, 0.0, 0.0))[source]#

Bases: object

An oriented physical plane: its position, side, origin and local axes.

The local transverse basis is right-handed: x_axis cross y_axis = normal, and the field’s propagation is forward along normal (SEP 31, section 4.1). A reflection changes these axes and the polarisation together; it is never an unexplained conjugation.

Attributes:
zfloat

Position of the plane along its own path, m.

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

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

origintuple of float, optional

Physical origin of the transverse coordinates, m, in the laboratory frame.

normaltuple of float, optional

Unit forward normal, laboratory frame. Default (0, 0, 1).

x_axistuple of float, optional

Unit local x axis, orthogonal to the normal. Default (1, 0, 0).

Raises:
CouplingError

If a value is not finite, an axis is not of unit length, or the two axes are not orthogonal.

Examples

>>> from solprop.coupling import PlaneGeometry
>>> PlaneGeometry(0.02).y_axis
(0.0, 1.0, 0.0)
normal: tuple[float, float, float] = (0.0, 0.0, 1.0)#
oriented_as(other)[source]#

Return whether two planes share their normal, axes and origin.

Parameters:
otherPlaneGeometry

The other plane.

Returns:
bool

True when origin, normal and x axis agree to rounding.

origin: tuple[float, float, float] = (0.0, 0.0, 0.0)#
side: Literal['before', 'after'] | None = None#
x_axis: tuple[float, float, float] = (1.0, 0.0, 0.0)#
property y_axis: tuple[float, float, float][source]#

Return the local y axis, normal cross x_axis.

Returns:
tuple of float

The unit vector completing the right-handed frame.

z: float#
solprop.coupling.plane.PlaneKind#

The native representation of a plane’s columns.

alias of Literal[‘modal’, ‘general_modal’, ‘radial’, ‘cartesian’, ‘planar’]

class solprop.coupling.plane.PlaneMetric(kind, matrix=None, admittance=None, weights=None, scale=1.0, flux=None, reason='')[source]#

Bases: object

The native power metric of a plane’s columns at its own position.

Each kind gives the energy crossing the plane per stored bin as a quadratic form of the samples (SEP 31, section 4.3, the metric Q):

identity

e_k sum |s|^2: ordinary true-power coefficients

dense

e_k s_k^H Q_k s_k: a general basis Gram, optics convention

admittance

scale e_k sum_j v_j Re(Y_jk) |s_jk|^2: a spatial plane’s axial admittance Y = c k_z / omega (SEP 34)

unknown

no energy can be formed; reason says why

with e_k the bin weights of solprop.fourier.energy_weights(). A dense metric’s per-channel diagonal is not a set of channel powers.

Attributes:
kind{‘identity’, ‘dense’, ‘admittance’, ‘unknown’}

The representation.

matrixnumpy.ndarray or None, optional

The optics-convention Gram Q = conj(W), shape (n_modes, n_modes, n_omega), dimensionless; exactly for dense.

admittancenumpy.ndarray or None, optional

Dimensionless c k_z / omega of each column, shape (n_modes, n_omega); exactly for admittance.

weightsnumpy.ndarray or None, optional

Transverse Parseval weights of the columns, shape (n_modes,); with admittance.

scalefloat, optional

Factor turning the weighted sum into joules: eps0 c / 2 for a field in V/m, one otherwise.

fluxsolprop.spatial.SpatialFlux or None, optional

The plane’s measure, when its medium is at hand; it can be resolved again on another temporal grid.

reasonstr, optional

Why an unknown metric is unknown.

Raises:
CouplingError

If the arrays present are not the ones kind names, or an unknown metric gives no reason.

admittance: Complex[ndarray, 'n_modes n_omega'] | None = None#
flux: SpatialFlux | None = None#
classmethod from_flux(flux)[source]#

Return the admittance metric of a resolved spatial measure.

Parameters:
fluxsolprop.spatial.SpatialFlux

The plane’s measure (SEP 34).

Returns:
PlaneMetric

The admittance metric, keeping flux.

kind: Literal['identity', 'dense', 'admittance', 'unknown']#
matrix: Complex[ndarray, 'n_modes n_modes_q n_omega'] | None = None#
classmethod paraxial(space, index, grid)[source]#

Return the axial admittance metric of a lossless medium given by its index.

Each column’s admittance is \(ck_z/\omega = \sqrt{n^2 - (c\kappa/\omega)^2}\), zero where the column does not propagate and on bins where the index is zero: the definition SEP 34’s flux uses, for a medium known only by its real phase index.

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

The transverse grid.

indexnumpy.ndarray

Real phase index at each bin, shape (n_omega,), non-negative.

gridsolprop.grid.TimeGrid

The temporal grid.

Returns:
PlaneMetric

The admittance metric, with eps0 c / 2; no flux.

Raises:
CouplingError

If the index has the wrong shape or is negative or nonfinite.

reason: str = ''#
scale: float = 1.0#
spectral_energy(samples, grid)[source]#

Return the energy each bin carries through the plane, J.

Parameters:
samplesnumpy.ndarray

Stored spectrum, shape (n_modes, n_pol, n_omega).

gridsolprop.grid.TimeGrid

Its temporal grid.

Returns:
numpy.ndarray

Energy per bin, J (J/m per unit width on a line), shape (n_omega,).

Raises:
CouplingError

For an unknown metric, or arrays of the wrong shape.

weights: Float[ndarray, 'n_modes'] | None = None#
class solprop.coupling.plane.PlaneProvenance(source='samples', plane=None, z=None, lineage=(), history=())[source]#

Bases: object

Where a plane came from and what was done to it.

Attributes:
sourcestr, optional

The source: a run’s configuration hash, "pulse" or "samples".

planeint or None, optional

The saved-plane index it was read from, counted from the start.

zfloat or None, optional

The saved plane’s position, m.

lineagetuple of str, optional

Configuration hashes of the runs this one descends from, oldest first.

historytuple of str, optional

The preparation steps applied, in order.

history: tuple[str, ...] = ()#
lineage: tuple[str, ...] = ()#
plane: int | None = None#
record()[source]#

Return the JSON-ready record of the provenance.

Returns:
dict

Every field.

source: str = 'samples'#
then(step)[source]#

Return the provenance with one more preparation step.

Parameters:
stepstr

What was done.

Returns:
PlaneProvenance

The same source, with step appended to the history.

z: float | None = None#
class solprop.coupling.plane.PlaneReference(phase=0.0, delay=0.0, calibrated=('phase', 'delay'))[source]#

Bases: object

The affine reference a stored spectrum is written in.

The absolute optics-convention spectrum is the stored one times \(\exp[i(\phi + \omega\tau)]\), with ω the absolute angular frequency of each bin (SEP 31, section 4.5). In the time domain τ is the absolute time of the record’s t = 0: the field at record time t happened at t + delay.

Attributes:
phasefloat, optional

Carrier phase φ, rad.

delayfloat, optional

Time origin τ, s.

calibratedtuple of {‘phase’, ‘delay’}, optional

Which terms are known absolutely. A run knows both from its frame; a phase-only optical model may leave the constant unknown.

Raises:
CouplingError

If a value is not finite.

Examples

>>> import numpy as np
>>> from solprop.coupling import PlaneReference
>>> reference = PlaneReference(phase=0.5, delay=1e-12)
>>> bool(np.isclose(np.angle(reference.factor(np.array([0.0]))[0]), 0.5))
True
calibrated: tuple[Literal['phase', 'delay'], ...] = ('phase', 'delay')#
delay: float = 0.0#
factor(omega)[source]#

Return the factor taking stored to absolute spectra.

Parameters:
omeganumpy.ndarray

Absolute angular frequencies, rad/s, shape (n_omega,).

Returns:
numpy.ndarray

\(\exp[i(\phi + \omega\tau)]\), complex128, shape (n_omega,).

classmethod from_record(record)[source]#

Return the reference a record describes.

Parameters:
recordcollections.abc.Mapping

As record() writes it.

Returns:
PlaneReference

The reference.

minus(other)[source]#

Return this reference measured from another.

Parameters:
otherPlaneReference

The reference subtracted.

Returns:
PlaneReference

(phase - other.phase, delay - other.delay), calibrated where both are.

phase: float = 0.0#
plus(other)[source]#

Return the sum of two references, calibrated where both are.

Parameters:
otherPlaneReference

The reference added.

Returns:
PlaneReference

(phase + other.phase, delay + other.delay).

record()[source]#

Return the JSON-ready record of the reference.

Returns:
dict

phase, delay and calibrated.

solprop.coupling.plane.basis_identity(route, record)[source]#

Return the identity of a plane’s basis: a digest of its route and record.

The one function both ends of a transfer call, so that a plane read from a file and the port of a receiving simulation compare the same digest. The record is JSON-ready: for a spatial route, space_record() of the grid; for a modal route, the run’s serialised mode records and general-modal identity.

Parameters:
route{‘modal’, ‘general_modal’, ‘radial’, ‘cartesian’, ‘planar’}

The representation.

recordcollections.abc.Mapping

The JSON-ready description of the basis.

Returns:
str

Sixty-four lowercase hexadecimal characters.

Examples

>>> from solprop.coupling import basis_identity, space_record
>>> from solprop.grid import RadialGrid
>>> record = space_record(RadialGrid(1e-3, 64))
>>> basis_identity("radial", record) == basis_identity("radial", dict(record))
True
solprop.coupling.plane.lattice_identity(grid)[source]#

Return the identity of a temporal lattice: its layout, samples and reference.

Two grids with the same identity have the same time samples and the same absolute frequency of every bin, so their spectra can be copied bin for bin. The spectral collar (the requested band) is not part of the lattice.

Parameters:
gridsolprop.grid.TimeGrid

The grid.

Returns:
str

Sixty-four lowercase hexadecimal characters.

Examples

>>> from solprop.coupling import lattice_identity
>>> from solprop.grid import EnvelopeGrid
>>> one = EnvelopeGrid.from_limits(1.0, 800e-9, (600e-9, 1.2e-6), 1e-12)
>>> two = EnvelopeGrid.from_limits(2.0, 800e-9, (600e-9, 1.2e-6), 1e-12)
>>> lattice_identity(one) == lattice_identity(two)
True
solprop.coupling.plane.modal_basis_identity(modes, grid, z)[source]#

Return the identity of an ordinary mode set’s basis at one plane.

An ordinary mode’s saved coefficient is a true-power amplitude of the mode’s own profile at the plane, so the basis there is fixed by each mode’s class and channel label, its effective area and its real effective index on the grid’s active band at that plane, quantised to twelve significant digits. The guide’s path elsewhere does not enter: the exit of one capillary and the entrance of an identical one of another length are the same basis.

Parameters:
modessequence of solprop.modes.protocol.Mode

The mode set, in state order.

gridsolprop.grid.TimeGrid

The temporal grid; its active band is sampled.

zfloat

The plane’s position along the guide, m.

Returns:
str

Sixty-four lowercase hexadecimal characters.

solprop.coupling.plane.reference_at(record, z)[source]#

Return the reference of a run’s plane at z from its persisted record.

The record is the run’s plane-reference record of output schema 24: origin, the reference of the run’s own path origin (its parent’s, for a run launched from another), and frame, the antiderivatives \(\Phi_0(z)=\int_0^z\beta_0\) and \(T(z)=\int_0^z\beta_1\) of the terms its linear operator removed, with the frequency origin \(\omega_o\) of the linear term (the reference frequency on an envelope grid, zero on a field grid). Then \(\phi = \phi_0 + \Phi_0 - \omega_oT\) and \(\tau = \tau_0 + T\). A record without a frame (an operator supplied directly) leaves both terms uncalibrated.

Parameters:
recordcollections.abc.Mapping

The persisted plane-reference record.

zfloat

Position of the plane along the run’s path, m.

Returns:
PlaneReference

The reference of the stored spectrum at z.

Raises:
CouplingError

If z lies outside the frame record’s span.

Examples

>>> from solprop.coupling import reference_at
>>> record = {
...     "origin": {"phase": 0.0, "delay": 1e-12, "calibrated": ["phase", "delay"]},
...     "frame": {"frequency_origin": 0.0,
...               "phase": {"breakpoints": [0.0, 1.0], "coefficients": [[0.0]]},
...               "delay": {"breakpoints": [0.0, 1.0],
...                         "coefficients": [[2e-9, 2e-9]]}},
... }
>>> f"{reference_at(record, 1.0).delay:.3e}"
'4.001e-09'
solprop.coupling.plane.space_record(space)[source]#

Return the JSON-ready record of a transverse grid: its class and arguments.

The grid’s constructor arguments determine every axis, weight and transform, so they are its identity; the record has the form the output layer serialises a grid in, which is what makes a plane read from a file comparable with a live grid. A PlanarGrid carries slab modes and has no such record.

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

The transverse grid.

Returns:
dict

{"__class__": "module.Name", <init fields>...}.

Raises:
CouplingError

For a planar grid.

Examples

>>> from solprop.coupling import space_record
>>> from solprop.grid import RadialGrid
>>> space_record(RadialGrid(1e-3, 64))["n_r"]
64