Skip to content

ajackura/wigner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

wigner

Modern C++23 library for low-spin SU(2) Wigner symbols, Racah and recoupling coefficients, Clebsch-Gordan and Gaunt coefficients, spherical harmonics, and Wigner rotation matrix elements.

This project is currently oriented around:

  • doubled-spin integer APIs (two_j = 2j, two_m = 2m)
  • low-lying spins
  • direct closed-form/runtime algorithms for 3j, 6j, 9j, d, and D
  • header-only use through CMake
  • no dependencies beyond the C++ standard library

Current API

Public headers are gathered by:

#include <wigner/wigner.hpp>

Currently available functions:

  • wigner::wigner_3j(two_j1, two_j2, two_j3, two_m1, two_m2, two_m3)
  • wigner::wigner_3j(const wigner::wigner_3j_args&)
  • wigner::wigner_12j_first(const wigner::wigner_12j_first_args&)
  • wigner::wigner_12j_second(const wigner::wigner_12j_second_args&)
  • wigner::wigner_6j(two_a, two_b, two_c, two_d, two_e, two_f)
  • wigner::wigner_6j(const wigner::wigner_6j_args&)
  • wigner::wigner_9j(two_a, two_b, two_c, two_d, two_e, two_f, two_g, two_h, two_i)
  • wigner::wigner_9j(const wigner::wigner_9j_args&)
  • wigner::triangle_coefficient(two_j1, two_j2, two_j3)
  • wigner::allowed_projections(two_j)
  • wigner::allowed_couplings(two_j1, two_j2)
  • wigner::allowed_couplings_12(two_j1, two_j2, two_j3, two_j)
  • wigner::allowed_couplings_13(two_j1, two_j2, two_j3, two_j)
  • wigner::allowed_couplings_23(two_j1, two_j2, two_j3, two_j)
  • wigner::allowed_canonical_3j_arguments(max_two_j)
  • wigner::allowed_canonical_6j_arguments(max_two_j)
  • wigner::allowed_canonical_9j_arguments(max_two_j)
  • wigner::allowed_canonical_12j_first_arguments(max_two_j)
  • wigner::allowed_canonical_12j_second_arguments(max_two_j)
  • wigner::racah_w(two_j1, two_j2, two_j12, two_j3, two_j, two_j23)
  • wigner::recoupling_12_23(two_j1, two_j2, two_j12, two_j3, two_j, two_j23)
  • wigner::recoupling_12_13(two_j1, two_j2, two_j12, two_j3, two_j, two_j13)
  • wigner::recoupling_13_23(two_j1, two_j2, two_j13, two_j3, two_j, two_j23)
  • wigner::recoupling(two_j1, two_j2, two_j12, two_j3, two_j, two_j23)
  • wigner::clebsch_gordan(two_j1, two_m1, two_j2, two_m2, two_j3, two_m3)
  • wigner::gaunt(l1, m1, l2, m2, l3, m3)
  • wigner::spherical_harmonic(l, m, theta, phi)
  • wigner::spherical_harmonic(l, m, x, y, z)
  • wigner::wigner_d(two_j, two_m, two_n, beta)
  • wigner::wigner_D(two_j, two_m, two_n, alpha, beta, gamma)

Example:

#include <iostream>
#include <wigner/wigner.hpp>

int main()
{
    std::cout << wigner::wigner_3j(1, 1, 0, 1, -1, 0) << '\n';
    std::cout << wigner::wigner_6j(1, 1, 0, 1, 1, 0) << '\n';
    std::cout << wigner::wigner_9j(0, 1, 1, 1, 0, 1, 1, 1, 0) << '\n';
    std::cout << wigner::racah_w(1, 1, 0, 1, 1, 0) << '\n';
    std::cout << wigner::recoupling(1, 1, 0, 1, 1, 0) << '\n';
}

A buildable version of this lives in examples/basic.cpp. There is also a doubled-spin walkthrough in examples/doubled_spin.cpp. For the new spherical-harmonic helpers, see examples/spherical_harmonics.cpp. Reference-style command-line tools live in exe.

Doubled-Spin Convention

All angular momenta are passed as doubled integers.

  • two_j = 0 means j = 0
  • two_j = 1 means j = 1/2
  • two_j = 2 means j = 1

Likewise for magnetic quantum numbers:

  • two_m = -1 means m = -1/2
  • two_m = 2 means m = 1

This keeps the core SU(2) API simple while supporting both integer and half-integer spins without a custom rational type.

The 12j helpers use the same doubled notation, but package their 12 angular momenta into explicit argument structs so the ring ordering is clear at the call site:

  • wigner::wigner_3j_args
  • wigner::wigner_6j_args
  • wigner::wigner_9j_args
  • wigner::wigner_12j_first_args
  • wigner::wigner_12j_second_args

The same helper layer also exposes canonical argument enumerators. These are mainly useful for tests, table-generation experiments, or user code that wants to scan only one representative from each symmetry class instead of every raw argument tuple.

Two public helpers use ordinary integer orbital-angular-momentum notation instead:

  • wigner::gaunt(l1, m1, l2, m2, l3, m3)
  • wigner::spherical_harmonic(l, m, theta, phi)
  • wigner::spherical_harmonic(l, m, x, y, z)

A small example focused just on this convention is available in examples/doubled_spin.cpp.

Implementation Notes

The current library keeps the implementation deliberately simple:

  • wigner_3j, wigner_6j, and wigner_9j use direct algorithms in detail
  • wigner_12j_first and wigner_12j_second use Wei's factorized single-sum formulas over reduced 6j factors
  • racah_w and recoupling are computed from wigner_6j
  • clebsch_gordan is computed from wigner_3j
  • gaunt is computed from wigner_3j
  • spherical_harmonic is computed from wigner_d
  • the Cartesian spherical_harmonic(l,m,x,y,z) overload converts the vector direction to polar angles and then reuses the same implementation
  • wigner_d and wigner_D are computed directly

This makes the code easier to reason about while the library is still being stabilized.

The helper APIs for allowed_projections, allowed_couplings*, and allowed_canonical_*_arguments are intended to make basis enumeration explicit and reusable, rather than having each executable or test build those loops by hand.

Executable Tools

Standalone inspection tools live in exe and are built when WIGNER_BUILD_EXECUTABLES=ON.

  • print_cg_table <target_two_j> [--two-j-max=N] [--all-rows] prints a fixed-j Clebsch-Gordan table grouped by contributing j1 x j2 channels
  • print_cg <two_j1> <two_j2> [two_j] prints the Clebsch-Gordan coefficient tables for all allowed coupled two_j values, or one chosen coupling channel when two_j is provided
  • print_3j <two_j1> <two_j2> <two_j3> prints all nonzero Wigner 3j rows for one fixed channel
  • print_6j <two_a> <two_b> <two_c> <two_d> <two_e> <two_f> prints one Wigner 6j symbol in decimal and symbolic form
  • print_9j <two_a> <two_b> <two_c> <two_d> <two_e> <two_f> <two_g> <two_h> <two_i> prints one Wigner 9j symbol in decimal and symbolic form
  • print_3j_table <target_two_j3> [--two-j-max=N] [--all-rows] prints a fixed-j3 Wigner 3j table grouped by contributing j1 x j2 channels
  • print_6j_table [--two-j-max=N] prints a Varshalovich-inspired canonical 6j table
  • print_9j_table [--two-j-max=N] prints a canonical nonzero 9j table in standard 3 x 3 layout
  • print_wigner_d_matrix <two_j> [--symbolic] prints the Wigner little d matrix for fixed j at beta = pi/2, either numerically or in rationalized symbolic form
  • print_triangle_table [--two-j-max=N] prints a Varshalovich-inspired triangle-coefficient table
  • print_recoupling <two_j1> <two_j2> <two_j3> [two_j] [--matrix] [--symbolic] [--scheme=12-23|12-13|13-23] prints recoupling coefficients for every allowed total J, or for one fixed J when two_j is provided, in flat or matrix form for the chosen coupling scheme, with optional symbolic output

Build

The project is set up for g++-14 and C++23.

Build Script

A small helper script is available at scripts/build.sh. It configures the project in build/gcc14 with g++-14, examples, tests, and executable tools enabled.

Examples:

./scripts/build.sh
./scripts/build.sh --tests

Configure and build

cmake -S . -B build/gcc14 \
  -DCMAKE_CXX_COMPILER=g++-14 \
  -DWIGNER_BUILD_TESTS=ON \
  -DWIGNER_BUILD_EXAMPLES=ON \
  -DWIGNER_BUILD_EXECUTABLES=ON
cmake --build build/gcc14
./build/gcc14/examples/wigner_example_basic
./build/gcc14/examples/wigner_example_doubled_spin
./build/gcc14/examples/wigner_example_spherical_harmonics
./build/gcc14/exe/print_cg_table 2 --two-j-max=6
./build/gcc14/exe/print_cg 1 1
./build/gcc14/exe/print_3j 1 1 0
./build/gcc14/exe/print_6j 1 1 0 1 1 0
./build/gcc14/exe/print_9j 0 1 1 1 0 1 1 1 0
./build/gcc14/exe/print_9j_table --two-j-max=4
./build/gcc14/exe/print_wigner_d_matrix 2
./build/gcc14/exe/print_wigner_d_matrix 2 --symbolic
./build/gcc14/exe/print_recoupling 1 1 1 1 --matrix
./build/gcc14/exe/print_recoupling 1 1 1 1 --matrix --symbolic
./build/gcc14/exe/print_recoupling 1 1 1 1 --matrix --scheme=12-13
ctest --test-dir build/gcc14 --output-on-failure

CMake Options

Important cache variables:

  • WIGNER_BUILD_TESTS build the test executable
  • WIGNER_BUILD_EXAMPLES build the example programs
  • WIGNER_BUILD_EXECUTABLES build standalone executable tools

You can override them directly at configure time. For example:

cmake -S . -B build/custom \
  -DCMAKE_CXX_COMPILER=g++-14 \
  -DWIGNER_BUILD_TESTS=ON \
  -DWIGNER_BUILD_EXAMPLES=ON \
  -DWIGNER_BUILD_EXECUTABLES=ON

Notes

License

MIT License. See LICENSE.

  • This library currently targets practical low-spin use, not arbitrarily large angular momentum.
  • The public API is intentionally small and integer-based.
  • clebsch_gordan is computed from wigner_3j; it does not maintain a separate table.
  • gaunt uses the standard spherical-harmonic relation to wigner_3j.
  • spherical_harmonic uses the standard relation to wigner_d.
  • wigner_d and wigner_D are computed directly.

Documentation

The project documentation uses Doxygen for C++ extraction and Sphinx for the published HTML and PDF output.

To install the docs-only Python dependencies:

./scripts/setup_docs.sh

To build the documentation:

./scripts/build_docs.sh

Outputs are written to:

  • docs/build/html/index.html
  • docs/build/latex/wigner.pdf

Status

Implemented and tested:

  • wigner_3j
  • wigner_12j_first
  • wigner_12j_second
  • wigner_6j
  • wigner_9j
  • racah_w
  • recoupling
  • clebsch_gordan
  • gaunt
  • spherical_harmonic
  • wigner_d
  • wigner_D

The test suite currently uses CTest with a small standard-library-only executable in tests/test_main.cpp.

About

C++23 library for SU(2) Wigner symbols and related angular-momentum coefficients

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors