Conventions¶
treams-rs follows the numerical conventions of treams. Arrays from one package can be compared entry by entry with arrays from the other.
Units and frequency¶
- Lengths and
1 / k0share one unit. With lengths in nm,k0is in 1/nm. k0 = ω / cis the vacuum angular wavenumber. In a medium the wavenumber isk0 n, and in a chiral mediumk0 (n - κ)for pol 0 andk0 (n + κ)for pol 1.- A
Materialholds the relative permittivityepsilon, the relative permeabilitymuand the chirality parameterkappa.Material(4)hasepsilon = 4,mu = 1andkappa = 0. - Cross sections are areas and cross widths are lengths, in the length unit.
Time convention¶
Fields vary in time as exp(-iωt), as in the
treams theory page.
Outgoing waves therefore use the Hankel function of the first kind, and lossy
media have Im(epsilon) > 0.
Polarization¶
The polarization convention is "helicity" (the default) or "parity", which
treams calls poltype. The index pol of a mode is 0 or 1:
| Convention | pol 0 | pol 1 |
|---|---|---|
"helicity" |
negative helicity | positive helicity |
"parity" |
TE, the M multipoles | TM, the N multipoles |
A helicity mode combines the parity modes as (N + (2 pol - 1) M) / sqrt(2).
For a plane wave, pol=[a0, a1] gives the amplitudes of pol 0 and pol 1, as
in treams.
Mode ordering¶
The default bases order their modes as in treams:
| Basis | Order, slowest index first |
|---|---|
SphericalBasis.default(lmax, nmax) |
position index, degree l, order m, then pol 1 before pol 0 |
CylindricalBasis.default(kzs, mmax, nmax) |
position index, kz in input order, order m, then pol 1 before pol 0 |
PlaneWavePorts.default(kpars) |
transverse wavevector in input order, then pol 1 before pol 0 |
import numpy as np
import treams_rs as tr
basis = tr.SphericalBasis.default(1)
labels = np.column_stack([basis.l, basis.m, basis.pol])
np.testing.assert_array_equal(
labels, [[1, -1, 1], [1, -1, 0], [1, 0, 1], [1, 0, 0], [1, 1, 1], [1, 1, 0]]
)
plane_wave(...) builds a two-mode PlaneWaveBasis with pol 0 first; treams
orders it pol 1 first. The field is the same, and pol=[a0, a1] means the same
in both.
The incident coefficients of a sphere cluster list the modes of each particle in
turn, in the order above. A vector describes one illumination; a matrix of shape
(modes, P) describes P illuminations. See
large clusters.
Degree, order and axial wavenumbers¶
- The degree is
land the order ism;lmaxandmmaxbound them. Thedifffunctions and the framework adapters spell themdegree=andorder=. kzis the axial wavenumber of one cylindrical mode:basis.kzhas one value per mode, as in treams.kzsare the distinct axial wavenumbers of a cylindrical T-matrix, one per block, as in treams'TMatrixC.cylinder(kzs, ...).diff.cylinder(kzs, ...)requires distinct values and returns the gradient ofkzsin input order.context.pullback_axialof the expansion, lattice-expansion and field records returns one gradient per distinctkz, in increasing order.
Planar sides and S-matrix blocks¶
| Term | Meaning |
|---|---|
| negative side | below, at smaller coordinates along the basis normal (z by default) |
| positive side | above, at larger coordinates along the basis normal |
negative_medium, positive_medium |
the media on the two sides of an interface, slab or SMatrix |
kind="up", index 0 |
propagation towards the positive side |
kind="down", index 1 |
propagation towards the negative side |
stack([a, b]), a.cascade(b) |
a is the lower layer, b sits on its positive side |
SMatrix.material |
(positive_medium, negative_medium), the treams order |
An SMatrix array has shape (2, 2, n, n). Entry [i, j] maps waves that
arrive travelling in direction j to waves that leave in direction i, with
0 for up and 1 for down. So [0, 0] transmits upwards, [1, 0] reflects
light from below, [0, 1] reflects light from above and [1, 1] transmits
downwards, as in treams. Port 0, the up direction, leaves through the positive
side.
import numpy as np
import treams_rs as tr
ports = tr.PlaneWavePorts.default([0, 0])
glass = tr.interface(basis=ports, k0=1.0, negative_medium=1, positive_medium=2.25)
upward = glass.block(outgoing="positive", incoming="negative")
np.testing.assert_array_equal(upward.array, glass.array[0, 0])
Field normalization¶
All fields come in the unit of the electric field:
| Method | Quantity |
|---|---|
efield |
E |
hfield |
Z0 H, with the vacuum impedance Z0 |
dfield |
D / ε0 |
bfield |
c B |
gfield, ffield |
Riemann–Silberstein fields G and F, combinations of E and i Z H |
gfield(pol, r) and ffield(pol, r) keep the scale factors of treams, which
differ between wave families and conventions. For a single positive-helicity
wave, gfield(1, r) returns:
| Wave | "helicity" |
"parity" |
|---|---|---|
| plane or cylindrical | E | 2 E |
| spherical | sqrt(2) E | 2 sqrt(2) E |
pol of gfield and ffield is 1, 0 or -1; 0 means -1, as in treams.
ffield also weights each helicity mode by n_pol / n, the ratio of its
helicity refractive index to the mean index.
Complex branches¶
- The normal wavenumber
kz = sqrt(k^2 - kx^2 - ky^2)takes the root withIm(kz) >= 0, andRe(kz) >= 0when it is real.misc.wave_vec_zreturns it. Evanescent waves then decay away from their source. - The radial wavenumber of cylindrical waves,
krho = sqrt(k^2 - kz^2), takes the same branch.
Label bounds¶
treams-rs limits mode labels with three constants of the Rust core
(treams-core); treams has no limits. A label beyond its bound raises
ValueError.
| Rust constant | Value | Bounds |
|---|---|---|
MAX_DEGREE |
128 | degree l of multipoles, special.wignerd and angular functions; the size of cylindrical orders m |
MAX_ORDER |
256 | radial orders and cylindrical order differences inside translations |
MAX_LABEL |
260 | the labels of special.wigner3j, orders of Kambe integrals and Wigner labels inside translations |
Bessel and Hankel functions in special take any finite order.
Reference version¶
treams-rs follows treams 0.4.7 at commit
1f5d0d6ebb007288f28bc9e16f6d266e8b55dc39
(2026-08-24), one documentation commit after the v0.4.7 tag. The tests compare
with treams 0.4.7, and the differences page describes it.