colour.phenomena.multilayer_tmm#

colour.phenomena.multilayer_tmm(n: ArrayLike, t: ArrayLike, wavelength: ArrayLike, theta: ArrayLike = 0) tuple[TypeAliasForwardRef('NDArrayFloat'), TypeAliasForwardRef('NDArrayFloat')][source]#

Calculate multilayer reflectance and transmittance using Transfer Matrix Method.

Unified function that returns both R and T in a single call, eliminating duplication and matching industry-standard TMM implementations. Computes both values from the same transfer matrix for efficiency.

Parameters:
  • n (array_like) –

    Complete refractive index stack \(n_j\) including incident medium, layers, and substrate. Shape: (media_count,) or (media_count, wavelengths_count). Can be complex for absorbing materials. The array should contain [n_incident, n_layer_1, …, n_layer_n, n_substrate].

    For example: single layer [1.0, 1.5, 1.0] (air | film | air), two layers [1.0, 1.5, 2.0, 1.0] (air | film1 | film2 | air), or with dispersion [[1.0, 1.0, 1.0], [1.52, 1.51, 1.50], [1.0, 1.0, 1.0]] for wavelength-dependent n.

  • t (array_like) –

    Thicknesses of each layer \(t_j\) in nanometers (excluding incident and substrate). Shape: (layers_count,).

    Important: This parameter specifies ONE thickness value per layer in the multilayer stack. It does NOT perform thickness sweeps.

    For example: single layer [250], two-layer stack [250, 150], three-layer stack [100, 200, 100].

    For thickness sweeps, use thin_film_tmm() with an array of thickness values (e.g., [200, 250, 300]), which computes all combinations via outer product broadcasting.

  • wavelength (array_like) – Wavelength values \(\lambda\) in nanometers.

  • theta (array_like, optional) – Incident angle \(\theta\) in degrees. Scalar or array of shape (angles_count,) for angle broadcasting. Default is 0 (normal incidence).

Returns:

(R, T) where:

  • R: Reflectance, numpy.ndarray, shape (W, A, 1, 2) for [R_s, R_p]

  • T: Transmittance, numpy.ndarray, shape (W, A, 1, 2) for [T_s, T_p]

where W = number of wavelengths, A = number of angles (the Spectroscopy Convention). The thickness dimension is always 1 for multilayer stacks.

Return type:

tuple

Examples

Single layer:

>>> R, T = multilayer_tmm([1.0, 1.5, 1.0], [250], 555)
>>> R.shape, T.shape
((1, 1, 1, 2), (1, 1, 1, 2))
>>> np.allclose(R + T, 1.0)  # Energy conservation
True

Two-layer stack:

>>> R, T = multilayer_tmm([1.0, 1.5, 2.0, 1.0], [250, 150], 555)
>>> R.shape  # (W, A, T, 2) = (1 wavelength, 1 angle, 1 thickness, 2 pols)
(1, 1, 1, 2)

Multiple wavelengths:

>>> R, T = multilayer_tmm([1.0, 1.5, 1.0], [250], [400, 500, 600])
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 1 angle, 1 thickness, 2 pols)
(3, 1, 1, 2)

Multiple angles (angle broadcasting):

>>> R, T = multilayer_tmm([1.0, 1.5, 1.0], [250], [400, 500, 600], [0, 30, 45, 60])
>>> R.shape  # (W, A, T, 2) = (3 wavelengths, 4 angles, 1 thickness, 2 pols)
(3, 4, 1, 2)

Notes

  • The reflectance is calculated from (Equation 15 from [Byr16]):

\[r = \frac{\tilde{M}_{10}}{\tilde{M}_{00}}, \quad R = |r|^2\]
  • The transmittance is calculated from (Equations 14 and 21-22 from [Byr16]):

\[t = \frac{1}{\tilde{M}_{00}}\]
\[T = |t|^2 \frac{\text{Re}[n_{\text{substrate}} \cos \theta_{\text{final}}]}{\text{Re}[n_{\text{incident}} \cos \theta_i]}\]

Where:

  • \(\tilde{M}\): Overall transfer matrix for the multilayer stack

  • \(r, t\): Complex reflection and transmission amplitude coefficients

  • \(R, T\): Reflectance and transmittance (fraction of incident power)

  • Energy conservation: For non-absorbing media, R + T = 1.

  • Supports complex refractive indices for absorbing materials (e.g., metals).

  • For absorbing media: R + T < 1 (absorption A = 1 - R - T).

References

[Byr16]