4. Rotations and Spherical Harmonics
4.1. Wigner d Matrices
wigner_d(two_j, two_m, two_n, beta) evaluates the real reduced rotation
matrix element \(d^j_{mn}(\beta)\). Angular-momentum arguments are doubled
integers and beta is in radians.
const double value = wigner::wigner_d(2, 2, 0, beta);
Here the call requests \(d^1_{1,0}(\beta)\). Invalid spin states return
zero. For fixed j and beta, the reduced Wigner matrix is real and
orthogonal:
Equivalently, its columns obey
The familiar row-normalization relation follows from the first equation by setting \(m'=m\).
4.2. Wigner D Matrices
wigner_D adds the outer Euler-angle phases and returns
std::complex<double>:
const auto value = wigner::wigner_D(
two_j, two_m, two_n,
alpha, beta, gamma);
The convention is stated explicitly in Conventions. This is important when using these matrices to rotate helicity amplitudes or define subduction coefficients, since active/passive rotation choices can complex-conjugate the result.
The full matrix is unitary rather than merely real-orthogonal:
4.3. SU(2) Characters
character(two_j, omega) evaluates
The removable limits at zero, \(\pi\), and \(2\pi\) are handled explicitly. Characters are useful for representation checks and group projection formulas without constructing the complete rotation matrix.
4.4. Complex Spherical Harmonics
spherical_harmonic implements standard complex
\(Y_l^m(\theta,\phi)\) with the Condon-Shortley phase. Unlike the Wigner
symbols, l and m are ordinary integers.
The angular overload accepts theta and phi. The Cartesian overload
accepts x, y, and z and uses only the vector’s direction:
const auto angular = wigner::spherical_harmonic(l, m, theta, phi);
const auto cartesian = wigner::spherical_harmonic(l, m, x, y, z);
The complete example evaluates both forms at the same direction:
1// SPDX-License-Identifier: MIT
2
3/**
4 * @file spherical_harmonics.cpp
5 * @brief Example evaluations of complex spherical harmonics.
6 */
7
8#include <cmath>
9#include <complex>
10#include <iostream>
11
12#include <wigner/wigner.hpp>
13
14int main()
15{
16 const double theta = 0.7;
17 const double phi = 1.1;
18 const double r = 2.0;
19 const double x = r * std::sin(theta) * std::cos(phi);
20 const double y = r * std::sin(theta) * std::sin(phi);
21 const double z = r * std::cos(theta);
22
23 const std::complex<double> y00 = wigner::spherical_harmonic(0, 0, theta, phi);
24 const std::complex<double> y10 = wigner::spherical_harmonic(1, 0, theta, phi);
25 const std::complex<double> y11 = wigner::spherical_harmonic(1, 1, theta, phi);
26 const std::complex<double> y11_cartesian = wigner::spherical_harmonic(1, 1, x, y, z);
27 const double gaunt = wigner::gaunt(1, 1, 1, -1, 0, 0);
28
29 std::cout << "theta = " << theta << ", phi = " << phi << '\n';
30 std::cout << "r = (" << x << ", " << y << ", " << z << ")\n";
31 std::cout << "Y_0^0(theta, phi) = " << y00 << '\n';
32 std::cout << "Y_1^0(theta, phi) = " << y10 << '\n';
33 std::cout << "Y_1^1(theta, phi) = " << y11 << '\n';
34 std::cout << "Y_1^1(r) = " << y11_cartesian << '\n';
35 std::cout << "Gaunt(1,1;1,-1;0,0) = " << gaunt << '\n';
36 std::cout << "-Y_0^0(theta, phi) = " << -y00 << '\n';
37
38 return 0;
39}
At the zero Cartesian vector, no direction exists; the implementation returns zero rather than choosing an arbitrary axis.
4.5. Gaunt Coefficients
gaunt evaluates the integral of three complex spherical harmonics,
through two Wigner 3j symbols. It is nonzero only when the projection sum
vanishes, the orbital angular momenta satisfy the triangle condition, and
\(l_1+l_2+l_3\) is even.
const double integral = wigner::gaunt(
l1, m1, l2, m2, l3, m3);
Using gaunt instead of reproducing the formula in client code keeps the
spherical-harmonic and Wigner-symbol phase conventions synchronized.