1. Overview and Quick Start

1.1. Purpose

wigner collects the SU(2) angular-momentum operations used repeatedly in partial-wave, finite-volume, and scattering calculations. It is independent of ADAT and of the other spectrum-suite packages, and its only library requirement is the C++23 standard library.

The package provides:

  • Wigner 3j, 6j, 9j, and first- and second-kind 12j symbols;

  • Clebsch-Gordan, Racah-W, and three-angular-momentum recoupling coefficients;

  • Wigner little-d and full-D rotation matrices and SU(2) characters;

  • complex spherical harmonics and Gaunt coefficients;

  • selection rules and helpers for enumerating admissible couplings; and

  • small command-line programs for inspecting coefficients and tables.

Numerical algorithms are compiled into a static library. The small discrete selection rules remain constexpr so they can also be used while building fixed bases at compile time.

1.2. Requirements

A normal build needs:

  • CMake 3.24 or newer; and

  • a compiler with the C++23 language mode.

The project is routinely checked with AppleClang and GCC. Documentation adds Doxygen, Python with the packages in docs/requirements.txt, and, for the PDF manual, a LaTeX distribution containing latexmk.

1.3. Build and Test

From the package root, run:

./scripts/build.sh

This performs a fresh strict build, runs the numerical tests, stages an installation, and verifies that a separate CMake project can find and link the installed archive. Documentation remains optional during routine work:

./scripts/build.sh --docs

Use ./scripts/build.sh --help for the complete short interface.

1.4. First Program

The aggregate header exposes the complete public API:

 1// SPDX-License-Identifier: MIT
 2
 3/**
 4 * @file basic.cpp
 5 * @brief Minimal end-to-end example of the principal Wigner APIs.
 6 */
 7
 8#include <cmath>
 9#include <complex>
10#include <iostream>
11#include <numbers>
12
13#include <wigner/wigner.hpp>
14
15int main()
16{
17    const double three_j = wigner::wigner_3j(1, 1, 0, 1, -1, 0);
18    const double six_j = wigner::wigner_6j(1, 1, 0, 1, 1, 0);
19    const double nine_j = wigner::wigner_9j(0, 1, 1, 1, 0, 1, 1, 1, 0);
20    const double racah = wigner::racah_w(1, 1, 0, 1, 1, 0);
21    const double recoupling = wigner::recoupling(1, 1, 0, 1, 1, 0);
22    const double cg = wigner::clebsch_gordan(1, 1, 1, -1, 0, 0);
23    const double gaunt = wigner::gaunt(1, 0, 1, 0, 0, 0);
24    const double d = wigner::wigner_d(1, 1, -1, 0.73);
25    const std::complex<double> D = wigner::wigner_D(0, 0, 0, 0.2, 0.3, 0.4);
26    const std::complex<double> Y = wigner::spherical_harmonic(
27        1, 1, 0.5 * std::numbers::pi, 0.0);
28
29    std::cout << "wigner_3j(1,1,0; 1,-1,0) = " << three_j << '\n';
30    std::cout << "wigner_6j(1,1,0; 1,1,0) = " << six_j << '\n';
31    std::cout << "wigner_9j(...)          = " << nine_j << '\n';
32    std::cout << "racah_w(...)            = " << racah << '\n';
33    std::cout << "recoupling(...)         = " << recoupling << '\n';
34    std::cout << "clebsch_gordan(...)     = " << cg << '\n';
35    std::cout << "gaunt(...)              = " << gaunt << '\n';
36    std::cout << "wigner_d(...)           = " << d << '\n';
37    std::cout << "wigner_D(0,0,0,...)     = " << D << '\n';
38    std::cout << "spherical_harmonic(...) = " << Y << '\n';
39
40    const double expected_three_j = 1.0 / std::sqrt(2.0);
41    return std::abs(three_j - expected_three_j) < 1.0e-12 ? 0 : 1;
42}

The integer arguments are deliberately doubled. For example, the call

wigner::wigner_3j(1, 1, 0, 1, -1, 0)

represents

\[\begin{split}\begin{pmatrix} \tfrac12 & \tfrac12 & 0 \\ \tfrac12 & -\tfrac12 & 0 \end{pmatrix}.\end{split}\]

This convention represents both integer and half-integer quantum numbers exactly without a rational-number type. It is developed carefully in Conventions.

1.5. Using Only What You Need

Applications may include the umbrella header:

#include <wigner/wigner.hpp>

or a narrow header such as:

#include <wigner/clebsch_gordan.hpp>

The narrow form documents the actual dependency of a translation unit and can reduce recompilation. Both forms link to the same target:

find_package(wigner CONFIG REQUIRED)
target_link_libraries(my_analysis PRIVATE wigner::wigner)

1.6. Where to Continue

Read Conventions before comparing signs with another implementation. Then use Coupling and Recoupling Coefficients for coupling and recoupling objects, Rotations and Spherical Harmonics for angular functions, and Numerical Design and Validation for the tested range and current limitations. Installation and dependency patterns are collected in Building and Integration.