Skip to content

Particles and waves

A sphere and its fields

import numpy as np
import treams_rs as tr

sphere = tr.sphere_tmatrix(
    k0=1.3,
    lmax=3,
    radius=0.2,
    material=tr.Material(epsilon=3.0),
)
incident = tr.plane_wave(
    direction=[0, 0, 1],
    pol="positive_helicity",
    k0=sphere.k0,
)
scattered = sphere.scatter(incident)
assert scattered.kind == "singular"
points = [[0.3, 0.2, 0.7], [-0.4, 0.1, 0.8]]
total_e = incident.efield(points) + scattered.efield(points)
assert total_e.shape == (2, 3)
power = sphere.cross_sections(incident)
np.testing.assert_allclose(power.scattering, power.extinction, rtol=1e-11)
assert abs(power.absorption) < 1e-12
assert sphere.array.shape == (30, 30)  # 2 lmax (lmax + 2) modes
average = sphere.average_cross_sections
np.testing.assert_allclose(average.extinction, average.scattering, rtol=1e-11)

Fields belong to waves. sphere.scatter(incident) returns the scattered wave, and scattered.efield(points) evaluates it; add incident.efield(points) for the total field. hfield, dfield, bfield, gfield and ffield give the other fields. A T-matrix has no field methods: applying one to scattered coefficients would apply the response twice. operators.efield builds an explicit field matrix when you need one.

cross_sections(incident) returns areas in the length unit squared; average_cross_sections gives the averages over all incident directions and both polarizations.

Materials and media

material is the particle or layer; medium is the space around it (vacuum by default). A number is a relative permittivity; Material(epsilon, mu, kappa) adds the relative permeability and the chirality parameter. multilayer_sphere_tmatrix takes increasing radii and one material per layer, from the inside out:

import numpy as np
import treams_rs as tr

core_shell = tr.multilayer_sphere_tmatrix(
    k0=1.3, lmax=2, radii=[0.1, 0.2], materials=[3, 3], medium=1.69
)
solid = tr.sphere_tmatrix(k0=1.3, lmax=2, radius=0.2, material=3, medium=1.69)
# Two layers of the same material make one solid sphere.
np.testing.assert_allclose(core_shell.array, solid.array, atol=1e-15)
# Only a chiral material (kappa != 0) treats the two helicities differently.
chiral = tr.sphere_tmatrix(
    k0=1.3, lmax=2, radius=0.2, material=tr.Material(epsilon=3, kappa=0.1)
)
assert abs(solid.circular_dichroism) < 1e-12 < abs(chiral.circular_dichroism)

Cylinders

Cylinders are infinite along z. cylinder_tmatrix takes the axial wavenumbers kz and the largest azimuthal order mmax in place of lmax. Their cross sections are widths per unit length, so use cross_widths:

import numpy as np
import treams_rs as tr

cylinder = tr.cylinder_tmatrix(k0=1.0, kz=[0.0], mmax=3, radius=0.4, material=4)
incident = tr.plane_wave(direction=[1, 0, 0], pol="positive_helicity", k0=1.0)
widths = cylinder.cross_widths(incident)
np.testing.assert_allclose(widths.extinction, widths.scattering, rtol=1e-12)

Waves and bases

A Wave stores coefficients with their basis, k0, medium, polarization convention and kind:

Basis Modes kind
SphericalBasis l, m, pol at one or more positions "regular" (finite at the origin) or "singular" (radiating, with the Hankel function of the first kind)
CylindricalBasis kz, m, pol at one or more axes "regular" or "singular"
PlaneWaveBasis unit directions and pol "up" or "down"
PlaneWavePorts transverse wavevectors and pol "up" or "down"

plane_wave builds a plane wave, spherical_wave and cylindrical_wave a single multipole. pol sets the polarization state: "positive_helicity", "negative_helicity", an index 0 or 1, two amplitudes [a0, a1] or the three Cartesian components of the electric field. in_basis expands a wave in another basis; with_polarization changes the polarization convention:

import numpy as np
import treams_rs as tr

plane = tr.plane_wave(direction=[0, 0, 1], pol="positive_helicity", k0=1.3)
local = plane.in_basis(tr.SphericalBasis.default(8))
assert local.kind == "regular"
point = [[0.1, 0.2, 0.3]]
# Near the origin, the multipole expansion reproduces the plane wave.
np.testing.assert_allclose(local.efield(point), plane.efield(point), atol=1e-9)

Coefficient batches have the shape (modes, illuminations). The Python reference lists the basis constructors, mode selections and geometry operations.