Public Documentation
These functions and types are to be used for transfer matrix calculation based on the sources used. If you wish to modify any of the steps in the calculation, refer to the private API.
Index
TransferMatrix.CircularTransferResultTransferMatrix.ElectricFieldTransferMatrix.LayerTransferMatrix.LayerTransferMatrix.MagneticFieldTransferMatrix.SheetTransferMatrix.TransferResultTransferMatrix.airyTransferMatrix.calculate_trTransferMatrix.calculate_trTransferMatrix.dbr_reflectivityTransferMatrix.dielectric_constantTransferMatrix.dielectric_tensorTransferMatrix.drudeTransferMatrix.drude_lorentzTransferMatrix.efieldTransferMatrix.euler_rotation_matrixTransferMatrix.find_boundsTransferMatrix.fresnelTransferMatrix.fresnel_coefficientsTransferMatrix.get_euler_anglesTransferMatrix.get_permeabilityTransferMatrix.get_refractive_indicesTransferMatrix.gyrotropic_tensorTransferMatrix.hfieldTransferMatrix.isanisotropicTransferMatrix.ismagneticTransferMatrix.isrotatedTransferMatrix.lorentzTransferMatrix.polder_permeabilityTransferMatrix.refractive_indexTransferMatrix.rotate_dielectric_tensorTransferMatrix.stopbandTransferMatrix.sweep_angleTransferMatrix.sweep_thicknessTransferMatrix.transfer
Transfer Matrix Functions
TransferMatrix.sweep_angle — Method
sweep_angle(λs, θs, layers; threads=true, verbose=false, basis=:linear)Calculate transmittance/reflectance spectra over wavelength and angle of incidence.
Returns a TransferResult with fields Tpp, Tss, Rpp, Rss, each a matrix of size (length(θs), length(λs)).
Arguments
λs: Vector of wavelengths in μmθs: Vector of angles of incidence in radianslayers:AbstractVector{<:Layer}representing the stackthreads: Enable multithreading (default: true)verbose: Print thread count info (default: false)basis::linear(default) →TransferResult;:circular→CircularTransferResult(seetransfer)method: propagation backend,:exp(default) or:eig(seetransfer)
Units
- Wavelengths: μm (micrometers) recommended
- Angles: radians
TransferMatrix.sweep_thickness — Method
sweep_thickness(λs, ts, layers, t_index; θ=0.0, threads=true, verbose=false, basis=:linear)Sweep the thickness of a specific layer and calculate transmittance/reflectance spectra.
Returns a TransferResult with fields Tpp, Tss, Rpp, Rss, each a matrix of size (length(ts), length(λs)).
Arguments
λs: Vector of wavelengths in μmts: Vector of thicknesses in μm to sweeplayers:AbstractVector{<:Layer}representing the stackt_index: Index of the layer (1-based) whose thickness to varyθ: Angle of incidence in radians (default: 0.0, normal incidence)threads: Enable multithreading (default: true)verbose: Print thread count info (default: false)basis::linear(default) →TransferResult;:circular→CircularTransferResult(seetransfer)method: propagation backend,:exp(default) or:eig(seetransfer)
Units
- Wavelengths and thicknesses: μm (micrometers) recommended
- Angle: radians
TransferMatrix.transfer — Method
transfer(λ, layers; θ=0.0, μ=1.0, validate=false, basis=:linear, method=:exp)Calculate the transmittance and reflectance of a layered structure.
With the default basis=:linear, returns a TransferResult with fields Tpp, Tss, Rpp, Rss (and cross-polarization terms Tps, Tsp, Rps, Rsp). With basis=:circular, returns a CircularTransferResult.
Reflectance and transmittance calculation
Reflectance uses $R = |r|^2$ from the transfer matrix coefficients (Passler & Paarmann 2017, Eq. 17). This is exact for transparent incident media. For absorbing incident media, $|r|^2$ is not a true energy ratio — Poynting vectors become non-additive due to interference cross-terms between incident and reflected waves (Ortiz & Mochan 2005, JOSA A 22, 2827). Proper treatment of that case requires the power_entering formalism (Byrnes 2016, arXiv:1603.02720), which is not yet implemented here.
Transmittance uses Poynting vectors (energy flux ratio $S_out / S_in$) rather than $|t|^2$, because the transmitted wave propagates in a different medium than the incident wave. As noted in the 2019 erratum (JOSAB 36, 3246): $T ≠ |t|^2$ in general; only when the substrate is vacuum does $T = |t|^2$.
All four linear transmittances are per-output-mode flux ratios: the transmitted field is decomposed into the two forward substrate eigenmodes (p-like and s-like), and each channel is that mode's own Poynting z-flux — with its own wavevector — divided by the incident flux. Distinct eigenmodes of a lossless substrate carry no cross z-flux, so this decomposition is exact for any transparent exit medium, isotropic or birefringent, at any incidence angle. The per-input-polarization energy budgets therefore close exactly for a lossless stack:
$R_{pp} + R_{ps} + T_{pp} + T_{ps} = 1$, and likewise for s input.
Arguments
λ: Wavelength in μm (must match units used for layer thicknesses)layers: Vector ofLayerobjects representing the stackθ: Angle of incidence in radians (default: 0.0, normal incidence)μ: Relative magnetic permeability (default: 1.0, non-magnetic)validate: Check energy conservation R + T ≈ 1 for non-absorbing media (default: false)basis: Output polarization basis —:linear(default) or:circularmethod: propagation backend —:eig(eigenmode) or:exp(matrix exponential, seelayer_transfer_exp)
Numerical backend
method selects how interior layers are propagated:
:exp(default) computes each interior layer's transfer matrix as the matrix exponential of the Berreman Δ matrix (seelayer_transfer_exp). It needs no eigenmode sorting and is degeneracy-immune, so it handles near-degenerate and mixed propagating/evanescent interior layers that:eigcannot.:eigis the eigenmode/dynamical-matrix path, retained as a cross-check.
Both agree to ~1e-12 on all supported cases. The semi-infinite ambient and substrate use the eigenmode path in either mode, so the anisotropic-ambient (#71) and anisotropic-substrate (#107) boundary limitations are unaffected by method.
Mackay & Lakhtakia, 2020, https://doi.org/10.1007/978-3-031-02022-3 ; Higham, 2005, https://doi.org/10.1137/04061101X
Polarization basis
basis=:linear(default) returns aTransferResultin the linear p/s basis.basis=:circularreturns aCircularTransferResultin the right/left circular basis. R/L are fixed-lab-frame helicities under this package'sexp(-iωt)convention. The Jones matrices transform asr_circ = C⁻¹ r_lin CwithC = (1/√2)[1 1; i -i](columns ordered L, R); the helicity flip on reflection is encoded automatically in the opposite signs ofrpp/rss.Circular reflectance is
|r_circ|²(a true energy ratio under the same condition as linearR: transparent incident medium, cf. issue #72). Circular transmittance maps each circular input through the linear Jones matrix to the substrate (p,s) amplitude pair, whose per-eigenmode Poynting flux gives the exact total transmitted power for that input; the total is then split between the L/R outputs in proportion to|t_circ|². For an isotropic substrate (degenerate eigenmodes) the split itself is exact, so circularTis energy-conserving to machine precision (and reduces to|t_circ|²for a vacuum/index-matched substrate). For an anisotropic substrate the two transmitted eigenmodes carry different wavevectors and are not circular, so the L/R split is only the natural|t_circ|²-weighted estimate — but the per-input totalTrr+Tlr(resp.Tll+Trl) remains exact, so the energy budget still closes. (The linear basis is per-mode exact in all channels, because the substrate eigenmodes ARE the linear output channels.)validateapplies to the linear basis only.
Wave Propagation Convention
- Light propagates in the +z direction (from first layer toward last layer)
- The first and last layers are treated as semi-infinite media
- θ is measured from the surface normal (z-axis)
Units
- Wavelength and thicknesses: μm by default. With
using Unitful,λmay carry units — a length, or a wavenumber/frequency/photon-energy that maps to wavelength (e.g.1550u"nm",193u"THz",0.8u"eV"). - Angle: radians
- Transmittance/Reflectance: dimensionless (0 to 1)
Physics Validation
When validate=true, the function checks:
- Bounds: 0 ≤ R, T ≤ 1 (catches NaN, negative values, numerical instability)
- Energy conservation: R + T ≈ 1 for non-absorbing media (imag(n) < 1e-10)
- Absorption bound: R + T ≤ 1 for absorbing media
Warnings are issued for any violations.
TransferMatrix.calculate_tr — Method
calculate_tr(M_sys)Read the reflection and transmission coefficients off the full-stack transfer matrix M_sys.
M_sys is the $4\times4$ transfer matrix for the whole stack, reordered into the p/s block convention (the two p modes first, then the two s modes) so the reflection and transmission Jones blocks can be read straight off its elements. The function returns the co- and cross-polarized amplitude coefficients (rpp, rss, rps, rsp, tpp, tss, tps, tsp) and their squared magnitudes.
Reflectance is $R = |r|^2$ directly. The returned $|t|^2$ values (all four, co- and cross-polarized) are not physical transmittances — the transmitted wave is in a different medium — so every transmittance reported by transfer (Tpp, Tss, Tps, Tsp) comes from the per-mode Poynting-vector calculation (calculate_tr(S::Poynting)) instead.
The $2\times2$ transfer-matrix relations originate with Yeh (1979); the generalized $4\times4$ coefficient formulas follow Passler & Paarmann (2017).
References:
- Yeh, 1979, https://doi.org/10.1364/JOSA.69.000742
- Passler & Paarmann, 2017, https://doi.org/10.1364/JOSAB.34.002128
TransferMatrix.efield — Method
efield(λ, layers; θ=0.0, μ=1.0, dz=0.001, sheets=nothing)Calculate the electric field profile throughout the layered structure.
Returns an ElectricField struct containing:
z: Position coordinates along the structurep: Electric field components (Ex, Ey, Ez) for p-polarized incidences: Electric field components (Ex, Ey, Ez) for s-polarized incidenceboundaries: z-positions of layer interfaces
Arguments
λ: Wavelength in μm (must match units used for layer thicknesses)layers: Vector ofLayerobjects representing the stackθ: Angle of incidence in radians (default: 0.0, normal incidence)μ: Relative magnetic permeability (default: 1.0, non-magnetic)dz: Spatial step size in μm for field sampling (default: 0.001)sheets: Optional conductive sheets at interfaces (seeSheetandtransfer); keyed by the index of the layer above each interface.
Wave Propagation Convention
- Light propagates in the +z direction (from first layer toward last layer)
- z = 0 is at the first interface (between layer 1 and layer 2)
- Negative z values are inside the first (incident) layer
- θ is measured from the surface normal (z-axis)
Units
- All lengths (λ, thickness, dz, z): μm by default; with
using Unitful,λanddzmay carry units (e.g.efield(1.55u"μm", layers; dz=1u"nm")). - Angle: radians
- Electric field: arbitrary units (normalized to incident field)
TransferMatrix.hfield — Method
hfield(λ, layers; θ=0.0, μ=1.0, dz=0.001, sheets=nothing)Calculate the magnetic-field profile through the structure, returning a MagneticField. Shares the sampling grid with efield (same dz and arguments), so E and H can be overlaid; the in-plane H discontinuity at a conductive sheet equals the surface current ẑ × (σ_s E∥).
Units / normalization
H is returned in impedance-normalized units H̃ = Z₀ H_SI (Z₀ = √(μ₀/ε₀)), so |E| ~ |H̃| for a plane wave. Arguments and conventions match efield.
TransferMatrix.calculate_tr — Method
calculate_tr(S::Poynting)Calculate transmittance and reflectance from the Poynting vector struct, which contains incident, transmitted, and reflected energy flux for both p-polarized and s-polarized waves.
Returns (Tpp, Tss, Rpp, Rss, Tps, Tsp).
The transmittances are per-output-mode flux ratios: Tpp is the power carried by the p-like substrate eigenmode alone (co-polarized channel) and Tps the power carried by the s-like eigenmode (cross-polarized channel), each divided by the incident p flux; likewise Tss/Tsp for s input. For a lossless stack the per-input budgets close exactly: Rpp + Rps + Tpp + Tps = 1.
Rpp/Rss here are the TOTAL reflected flux per input polarization (the reflected field is a coherent sum of both backward modes, so for converting stacks this equals |rpp|² + |rps|², not the co-polarized piece alone). transfer takes its per-channel reflectances from $|r|^2$ instead — see the calculate_tr(M_sys) method.
Sign Convention
The reflected Poynting vector z-component is negative (pointing in -z direction), so the negative sign in Rpp = -S.refl_p[3] / S.in_p[3] yields positive reflectance.
TransferMatrix.CircularTransferResult — Type
CircularTransferResult{T}Circular-polarization (RCP/LCP) basis transmittance/reflectance — the analogue of TransferResult. Fields are right/left co- and cross-handedness terms: Trr is T_{R←R}, Trl is T_{R←L}, etc.
As with TransferResult, T is Float64 for a single transfer(λ, layers; basis=:circular) call and Matrix{Float64} for the sweep functions.
Convention
R/L are viewer-facing helicities defined in the fixed lab frame relative to +z, under this package's exp(-iωt) time convention (basis states e_R = (x̂ - iŷ)/√2, e_L = (x̂ + iŷ)/√2). Reflection flips the helicity label, so at normal incidence on an isotropic interface the diagonal Rrr/Rll vanish and reflection appears entirely in the off-diagonal Rrl/Rlr; at oblique incidence the diagonal terms are small but nonzero. Unequal Rrl ≠ Rlr signals genuine optical activity / magneto-optic coupling, not a bug.
See transfer for energy-ratio caveats.
TransferMatrix.ElectricField — Type
ElectricFieldSpatial electric-field profile through a layered structure, mirrored by MagneticField.
z: position coordinatesp:(Ex, Ey, Ez)for p-polarized incidences:(Ex, Ey, Ez)for s-polarized incidenceboundaries: z-positions of interfaces
TransferMatrix.MagneticField — Type
MagneticFieldSpatial magnetic-field profile through a layered structure, mirroring ElectricField. Fields are in impedance-normalized units H̃ = Z₀ H_SI so |E| ~ |H̃| for a plane wave and E/H can be overlaid directly.
z: position coordinates (same grid asefield)p:(Hx, Hy, Hz)for p-polarized incidences:(Hx, Hy, Hz)for s-polarized incidenceboundaries: z-positions of interfaces
TransferMatrix.TransferResult — Type
TransferResult{T}Container for reflectance and transmittance results from transfer matrix calculations.
Fields
Tpp::T: p-polarized transmittance (p-in → p-out)Tss::T: s-polarized transmittance (s-in → s-out)Tps::T: cross-polarized transmittance (p-in → s-out)Tsp::T: cross-polarized transmittance (s-in → p-out)Rpp::T: p-polarized reflectance (p-in → p-out)Rss::T: s-polarized reflectance (s-in → s-out)Rps::T: cross-polarized reflectance (p-in → s-out)Rsp::T: cross-polarized reflectance (s-in → p-out)
For single-wavelength calculations via transfer(), T is Float64. For sweep calculations via sweep_angle() or sweep_thickness(), T is Matrix{Float64}.
The cross-polarization terms (Tps, Tsp, Rps, Rsp) are zero for isotropic media and become non-zero for anisotropic (birefringent) materials.
Every entry is a true energy flux ratio: transmittances are per-output-mode Poynting fluxes (see transfer) and reflectances are $|r|^2$. For a lossless stack the per-input-polarization budgets close exactly: Rpp + Rps + Tpp + Tps = 1 and Rss + Rsp + Tss + Tsp = 1.
Examples
# Single wavelength - returns TransferResult{Float64}
result = transfer(1.0, layers)
result.Tpp # Float64
# Sweep - returns TransferResult{Matrix{Float64}}
result = sweep_angle(λs, θs, layers)
result.Tpp # Matrix{Float64}
# Destructuring works
(; Tpp, Rpp) = transfer(1.0, layers)TransferMatrix.Layer — Type
Layer(material, thickness)
Layer(nx, ny, nz, thickness)Construct a single layer for transfer matrix calculations.
Isotropic Layer (single refractive index)
Layer(material, thickness)material: a dispersion functionλ -> n(λ), or aRefractiveMaterialfrom RefractiveIndex.jl (the material form requiresusing RefractiveIndex, which activates theRefractiveIndexExtextension)thickness: Layer thickness in the same units as wavelength (typically μm)
Anisotropic Layer (biaxial: three refractive indices)
Layer(nx, ny, nz, thickness)nx,ny,nz: Dispersion functionsλ -> n(λ)for each principal axisthickness: Layer thickness in μm
For uniaxial materials, set two axes equal (e.g., nx = ny for optic axis along z).
Units Convention
Lengths default to micrometers (μm) as bare numbers (Layer(n, 0.1) = 0.1 μm). With using Unitful, thickness may carry units and is normalized to μm: Layer(n, 100u"nm"). RefractiveIndex.jl dispersion functions are parameterized in μm, so μm remains the internal unit.
Layer is parametric as Layer{F,Mf,T} where F is the dispersion function type, Mf is the permeability type (Nothing or a callable λ -> SMatrix{3,3,ComplexF64}), and T is the thickness type. For anisotropic layers, F is a Tuple of three dispersion functions.
Examples
# Isotropic: Using a RefractiveIndex.jl material (requires `using RefractiveIndex`)
n_sio2 = RefractiveMaterial("main", "SiO2", "Malitson")
layer = Layer(n_sio2, 0.1) # 100 nm = 0.1 μm
# Isotropic: Using custom dispersion function
layer = Layer(λ -> 1.5 + 0.01im, 0.25) # constant n = 1.5 + 0.01i
# Anisotropic: Uniaxial crystal (calcite-like, optic axis along z)
no = λ -> 1.658 # ordinary index
ne = λ -> 1.486 # extraordinary index
layer = Layer(no, no, ne, 0.5)
# Anisotropic: Biaxial crystal
layer = Layer(λ -> 1.5, λ -> 1.6, λ -> 1.7, 0.3)Magnetic / Permeability (mu=)
All constructors accept an optional mu= keyword that sets the layer's magnetic permeability. Accepted forms: nothing (default, use the global μ= fallback), a scalar Number (isotropic μ), a constant 3×3 AbstractMatrix, or a callable λ -> 3×3 matrix for wavelength-dependent tensors.
# Gyromagnetic (Polder) ferrite film, bias ∥ z
film = Layer(λ -> 1.0, 0.4; mu = gyrotropic_tensor(2.0, 0.6))
# Uniaxial-μ slab
slab = Layer(λ -> 1.5, 0.3; mu = [2 0 0; 0 2 0; 0 0 3])TransferMatrix.Layer — Method
Layer(nx, ny, nz, thickness; euler=(0,0,0))Construct an anisotropic layer with different refractive indices along each principal axis.
Arguments
nx,ny,nz: Dispersion functionsλ -> n(λ)for each principal axisthickness: Layer thickness in μmeuler: Optional tuple(φ, θ, ψ)of ZYZ Euler angles in radians (default: no rotation)
The dielectric tensor is constructed as a diagonal matrix with εi = ni² in the crystal frame, then rotated to the lab frame using the Euler angles.
Euler Angle Convention (ZYZ)
φ(phi): First rotation about z-axisθ(theta): Rotation about new y-axis (tilt angle from z)ψ(psi): Second rotation about new z-axis
Examples
# Uniaxial crystal with optic axis along z (no rotation needed)
layer = Layer(no, no, ne, 0.5)
# Same crystal with optic axis tilted 45° from z in the xz-plane
layer = Layer(no, no, ne, 0.5; euler=(0, π/4, 0))
# Optic axis in the xy-plane at 30° from x
layer = Layer(no, no, ne, 0.5; euler=(π/6, π/2, 0))TransferMatrix.dielectric_constant — Method
dielectric_constant(n_re::Real, n_im::Real)Return the complex dielectric function from the real and imaginary parts of the index of refraction.
The complex index of refraction, given by
n' = n_re + i * n_im(in terms of nre and nim), can be used to obtain the frequency-dependent complex dielectric function
ε_r(ω) = ε' + iε''via the relation
(n_re + i * n_im)^2 = ε' + iε''.TransferMatrix.find_bounds — Method
find_bounds(layers)Return cumulative thickness positions measured from the start of layer 1, along with the total thickness.
The returned vector has one entry per layer, where entry i is the sum of thicknesses from layer 1 through layer i. These are not interface positions relative to z = 0; callers that need z-coordinates (e.g., efield) must subtract the first layer thickness.
TransferMatrix.get_euler_angles — Method
get_euler_angles(layer::Layer)Return the Euler angles (φ, θ, ψ) for crystal rotation.
For isotropic layers or unrotated anisotropic layers, returns (0.0, 0.0, 0.0). For rotated anisotropic layers, returns the stored angles.
TransferMatrix.get_permeability — Method
get_permeability(layer::Layer, λ)Return the 3×3 permeability tensor SMatrix{3,3,ComplexF64} for the layer at wavelength λ, or nothing if the layer is non-magnetic.
TransferMatrix.get_refractive_indices — Method
get_refractive_indices(layer::Layer, λ)Return the refractive indices for a layer at wavelength λ.
For isotropic layers, returns (n, n, n) where n is the scalar refractive index. For anisotropic layers, returns (nx, ny, nz) for each principal axis.
TransferMatrix.isanisotropic — Method
isanisotropic(layer::Layer)Return true if the layer has anisotropic optical properties (different refractive indices along principal axes), false for isotropic layers.
TransferMatrix.ismagnetic — Method
ismagnetic(layer::Layer)Return true if the layer has a non-trivial magnetic permeability (mu ≠ nothing).
TransferMatrix.isrotated — Method
isrotated(layer::Layer)Return true if the layer has non-zero Euler angles for crystal rotation.
TransferMatrix.refractive_index — Method
refractive_index(λs, ns, ks)Build a complex dispersion function λ -> n(λ) + i·k(λ) by linearly interpolating tabulated real (ns) and imaginary (ks) refractive-index data over wavelengths λs (sorted, increasing). Evaluation outside the tabulated range throws a DomainError.
A refractive_index(material::RefractiveMaterial) method that derives the dispersion function from a RefractiveIndex.jl material is provided by the RefractiveIndexExt package extension — load RefractiveIndex to enable it (along with the Layer(::RefractiveMaterial, d) and Sheet(::RefractiveMaterial, d) constructors).
TransferMatrix.dielectric_tensor — Method
dielectric_tensor(ε1, ε2, ε3)Return the diagonal complex dielectric tensor
\[\varepsilon = \begin{pmatrix} \varepsilon_1 & 0 & 0 \\0 & \varepsilon_2 & 0 \\0 & 0 & \varepsilon_3 \end{pmatrix}\]
TransferMatrix.euler_rotation_matrix — Method
euler_rotation_matrix(φ, θ, ψ)Return the 3×3 rotation matrix for ZYZ Euler angles (in radians).
This transforms vectors from the crystal frame to the lab frame: v_lab = R * v_crystal
The rotation is performed as: R = Rz(φ) * Ry(θ) * Rz(ψ)
Convention
- φ (phi): First rotation about z-axis (0 to 2π)
- θ (theta): Rotation about new y-axis (0 to π) - the tilt angle
- ψ (psi): Second rotation about new z-axis (0 to 2π)
Common cases
- Optic axis along z:
(0, 0, 0)- no rotation needed - Optic axis in xz-plane at angle θ from z:
(0, θ, 0) - Quarter-wave plate at 45°:
(π/4, π/2, 0)for optic axis in xy-plane
TransferMatrix.gyrotropic_tensor — Method
gyrotropic_tensor(d, od; axis=:z)Constant gyrotropic (e.g. gyromagnetic Polder) tensor with diagonal d and antisymmetric imaginary off-diagonal ±i·od, with the gyration vector along axis. For axis=:z:
[ d i·od 0
−i·od d 0
0 0 1 ]Hermitian (hence lossless) for real d, od. The sign/handedness follows the package exp(-iωt) convention (validated against the t_ps = -t_sp non-reciprocity relation).
TransferMatrix.polder_permeability — Method
polder_permeability(; f0, fm, linewidth=0.0, axis=:z)Return a function f -> μ_tensor giving the gyromagnetic (Polder) permeability tensor of a saturated ferrite at frequency f:
\[μ(f) = 1 + \frac{f_0 f_m}{f_0^2 - f^2}, \qquad κ(f) = \frac{f f_m}{f_0^2 - f^2}\]
with the gyration axis axis. f0 is the ferromagnetic-resonance frequency (= γμ₀H₀/2π), f_m = γμ₀M_s/2π, and γ = g·e/2mₑ. A nonzero linewidth (ΔH, in the same units as f0) adds loss via f0 → f0 − i·linewidth/2.
Use as a layer permeability with Layer(...; mu = λ -> polder_permeability(...)(f(λ))), mapping wavelength to frequency as appropriate for your unit system.
TransferMatrix.rotate_dielectric_tensor — Method
rotate_dielectric_tensor(ε_diag, R)Rotate a diagonal dielectric tensor from crystal frame to lab frame.
Given a diagonal tensor ε in the crystal's principal axis frame and a rotation matrix R, returns the rotated tensor: ε_lab = R * ε * R'
Arguments
ε_diag: Diagonal dielectric tensor in crystal frameR: 3×3 rotation matrix fromeuler_rotation_matrix
Returns
Full 3×3 SMatrix (may have off-diagonal elements after rotation)
TransferMatrix.Sheet — Type
Sheet(σ)
Sheet(; xx, yy, xy=0, yx=0)
Sheet(material, d)
Sheet(nx, ny, d)A zero-thickness 2D conductive sheet (e.g. a TMDC monolayer) for the transfer matrix. The internal representation is a callable λ -> SMatrix{2,2,ComplexF64} returning the SI sheet conductivity tensor [σxx σxy; σyx σyy] in Siemens.
Sheet(σ)— scalar isotropic conductivity (σ::Numberorσ(λ)->Number), stored asdiag(σ, σ).Sheet(; xx, yy, xy=0, yx=0)— anisotropic tensor; each entry aNumberorλ->Number.Sheet(material, d)— convert a refractive index to a sheet viaσ = -i ω ε₀ d (n²-1)(isotropic).materialis ann(λ)function (or aRefractiveMaterialwhen the RefractiveIndex extension is loaded);dis the effective thickness in μm.Sheet(nx, ny, d)— in-plane anisotropic index conversion (σxxfromnx,σyyfromny).
The factor Z₀ = √(μ₀/ε₀) is applied exactly once, later, in sheet_matrix.
Dispersion Models
TransferMatrix.drude — Method
drude(ω_p, γ; ε_inf=1.0)Return a closure λ -> n for the Drude free-carrier (metal) model:
\[ε(ω) = ε_\infty - \frac{ω_p^2}{ω^2 + iγω}, \qquad n = \sqrt{ε}.\]
Arguments
ω_p: plasma energy (eV by default; aUnitfulenergy/wavenumber/frequency is normalized to eV whenUnitfulis loaded).γ: damping/collision rate (eV).ε_inf: high-frequency dielectric constant (dimensionless, default1.0).
The returned closure takes a vacuum wavelength λ in μm and returns the complex refractive index n (with n″ > 0 for absorption under the package's exp(-iωt) convention).
Example
# Gold-like Drude metal, 50 nm film
au = drude(9.0, 0.07) # ω_p = 9 eV, γ = 0.07 eV
layer = Layer(au, 0.05)See also: lorentz, drude_lorentz.
TransferMatrix.drude_lorentz — Method
drude_lorentz(ω_p, γ_D, oscillators; ε_inf=1.0)Return a closure λ -> n for a combined Drude + Lorentz model (the standard form for real metals such as gold):
\[ε(ω) = ε_\infty - \frac{ω_p^2}{ω^2 + iγ_D ω} + \sum_j \frac{Δε_j\, ω_{0j}^2}{ω_{0j}^2 - ω^2 - iγ_j ω}.\]
Arguments
ω_p,γ_D: Drude plasma energy and damping (eV).oscillators: iterable of Lorentz(ω_0, Δε, γ)3-tuples (may be empty for a pure Drude metal).ε_inf: high-frequency dielectric constant (default1.0).
The returned closure takes a vacuum wavelength λ in μm.
TransferMatrix.lorentz — Method
lorentz(ω_0, Δε, γ; ε_inf=1.0)
lorentz(oscillators; ε_inf=1.0)Return a closure λ -> n for the Lorentz oscillator model:
\[ε(ω) = ε_\infty + \sum_j \frac{Δε_j\, ω_{0j}^2}{ω_{0j}^2 - ω^2 - iγ_j ω}, \qquad n = \sqrt{ε}.\]
Arguments
ω_0: resonance energy (eV by default).Δε: dimensionless oscillator strength (the static contribution of the mode;ε(0) = ε_inf + Σ Δε_j).γ: damping (eV).ε_inf: high-frequency dielectric constant (default1.0).oscillators: an iterable of(ω_0, Δε, γ)3-tuples for a multi-oscillator model (e.g. several phonon modes).
The returned closure takes a vacuum wavelength λ in μm.
Examples
# Single oscillator
n = lorentz(2.0, 3.0, 0.05) # ω_0 = 2 eV
# Two oscillators on top of ε∞ = 2.5
n = lorentz([(2.0, 1.0, 0.05), (3.5, 0.4, 0.1)]; ε_inf=2.5)See also: drude, drude_lorentz.
Miscellaneous Optics Functions
TransferMatrix.airy — Method
airy(n0, nf, ns, d, λ; θ=0.0)Calculate the reflectance and transmittance of a single thin film using the exact Airy formula (multiple-beam interference).
Arguments
n0: refractive index of incident medium (can be complex)nf: refractive index of the film (can be complex)ns: refractive index of the substrate (can be complex)d: film thickness (same units as λ)λ: wavelength (same units as d)θ=0.0: angle of incidence in radians
Returns
(Rs, Rp, Ts, Tp) - reflectance and transmittance for s and p polarizations.
Physics
The Airy formula accounts for all multiple reflections within the film:
\[r = \frac{r_{01} + r_{12} e^{2i\delta}}{1 + r_{01} r_{12} e^{2i\delta}}\]
where δ = 2π nf d cos(θf) / λ is the phase thickness and r₀₁, r₁₂ are the Fresnel reflection coefficients at the two interfaces.
This provides an exact analytical solution for validating numerical TMM results.
Example
# Quarter-wave anti-reflection coating
n_air, n_film, n_glass = 1.0, 1.38, 1.52
λ = 0.55 # μm
d = λ / (4 * n_film) # quarter-wave thickness
Rs, Rp, Ts, Tp = airy(n_air, n_film, n_glass, d, λ)See also: fresnel, fresnel_coefficients
TransferMatrix.dbr_reflectivity — Method
dbr_reflectivity(no, ns, n1, n2, N)Approximate the reflectivity of a DBR structure with originating medium with refractive index no, substrate with index ns, and alternating materials with indices n1 and n2 and number of repetitions N. The repeated pair of materials are assumed to have quarter-wave thickness $nd = \lambda / 4$, where $n$ is the refractive index, $d$ is the layer thickness, and $\lambda$ is the wavelength of the light.
TransferMatrix.fresnel — Method
fresnel(θ, n1, n2)Calculate the reflectance for s-polarized and p-polarized light given the incidence angle θ (in radians) and indices of refraction of two media n1 and n2 at a plane interface.
Returns (Rs, Rp) where Rs is s-polarized reflectance and Rp is p-polarized reflectance.
The Fresnel equations for reflectance are:
\[R_s = \left| \frac{n_1 \cos\theta_i - n_2 \cos\theta_t}{n_1 \cos\theta_i + n_2 \cos\theta_t} \right|^2\]
\[R_p = \left| \frac{n_2 \cos\theta_i - n_1 \cos\theta_t}{n_2 \cos\theta_i + n_1 \cos\theta_t} \right|^2\]
where $\theta_t$ is the transmitted angle given by Snell's law: $n_1 \sin\theta_i = n_2 \sin\theta_t$.
Special cases:
- At grazing incidence (θ → π/2), returns
(1.0, 1.0) - For total internal reflection (when
n1 > n2andθ > θ_critical), returns(1.0, 1.0)
See also: fresnel_coefficients for complex amplitude coefficients.
TransferMatrix.fresnel_coefficients — Method
fresnel_coefficients(θ, n1, n2)Calculate the Fresnel reflection and transmission amplitude coefficients for s-polarized and p-polarized light at a plane interface.
Returns (rs, rp, ts, tp) where:
rs,rp: reflection amplitude coefficients (complex)ts,tp: transmission amplitude coefficients (complex)
These are the amplitude (not intensity) coefficients, so reflectance R = |r|² and transmittance requires the full expression T = (n2 cosθt)/(n1 cosθi) |t|².
For total internal reflection, the reflection coefficients have unit magnitude with a phase shift (evanescent wave), and transmission coefficients are zero.
See also: fresnel for intensity reflectances.
TransferMatrix.stopband — Method
stopband(n1, n2)Calculate the frequency bandwidth Δf of the photonic stopband for a distributed bragg reflector (DBR) with two alternating materials of refractive indices n1 and n2.
\[ \frac{\Delta f_0}{f_0} = \frac{4}{\pi} \arcsin \left( \frac{n_2 - n_1}{n_2 + n_1} \right)\]