Skip to main content

Compute Wigner 3j and Clebsch-Gordan coefficients

Project description

Calculation of Wigner symbols and related constants

This package computes Wigner 3j coefficients, Clebsch-Gordan coefficients, and complex Wigner D-matrices in pure Rust. The 3j/CG calculation is based on the prime factorization of the different factorials involved in the coefficients, keeping the values in a rational root form (sign * \sqrt{s / n}) for as long as possible. The Wigner D-matrix uses the Risbo/Trapani-Navaza recurrence to compute all matrices for j from 0 to j_max simultaneously.

Wigner 3j / Clebsch-Gordan algorithm:

H. T. Johansson and C. Forssén, SIAM Journal on Scientific Compututing 38 (2016) 376-384

Wigner D-matrix algorithm:

This implementation takes a lot of inspiration from the WignerSymbols Julia implementation (and even started as a direct translation of it), many thanks to them! This package is available under the same license as the Julia package.

Usage

From python

pip install wigners

And then call one of the exported function:

import wigners

w3j = wigners.wigner_3j(j1, j2, j3, m1, m2, m3)

cg = wigners.clebsch_gordan(j1, m1, j2, m1, j3, m3)

# full array of Clebsch-Gordan coefficients, computed in parallel
cg_array = wigners.clebsch_gordan_array(ji, j2, j3)

# we have an internal cache for recently computed CG coefficients, if you
# need to clean it up you can use this function
wigners.clear_wigner_3j_cache()

# Wigner D matrices for all j up to max_j, using ZYZ Euler angles
matrices = wigners.wigner_D_array(max_j, alpha, beta, gamma)
# matrices[j] is a (2*j+1) x (2*j+1) complex128 matrix

From rust

Add this crate to your Cargo.toml dependencies section:

wigners = "0.3"

And then call one of the exported function:

let w3j = wigners::wigner_3j(j1, j2, j3, m1, m2, m3);

let cg = wigners::clebsch_gordan(j1, m1, j2, m1, j3, m3);

wigners::clear_wigner_3j_cache();

// Wigner D matrices for all j up to max_j, using ZYZ Euler angles
let mut output = vec![0.0; 2 * total_d_matrix_size(max_j)];
wigners::wigner_d_array(max_j, alpha, beta, gamma, &mut output);

Limitations

Only Wigner 3j symbols for full integers (no half-integers) are implemented, since that's the only part I need for my own work.

6j and 9j symbols can also be computed with this approach; and support for half-integers should be feasible as well. I'm open to pull-request implementing these!

The Wigner D-matrix implementation uses the ZYZ convention and only supports full-integer j (no half-integers). It is limited to j ≤ 100 for numerical stability of the recurrence.

Benchmarks

This benchmark measure the time to compute all possible Wigner 3j symbols up to a fixed maximal angular momentum; clearing up any cached values from previous angular momentum before starting the loop. In pseudo code, the benchmark looks like this:

if cached_wigner_3j:
    clear_wigner_3j_cache()

# only measure the time taken by the loop
start = time.now()
for j1 in range(max_angular):
    for j2 in range(max_angular):
        for j3 in range(max_angular):
            for m1 in range(-j1, j1 + 1):
                for m2 in range(-j2, j2 + 1):
                    for m3 in range(-j3, j3 + 1):
                        w3j = wigner_3j(j1, j2, j3, m1, m2, m3)

elapsed = start - time.now()

Here are the results on an Apple M1 Max (10 cores) CPU, against a handful of other libraries:

code & version max_angular=4 8 12 16 20
wigners (this) 0.190 ms 4.60 ms 36.5 ms 172 ms 572 ms
wigner-symbols v0.5 6.00 ms 181 ms 1.53 s 7.32 s /
WignerSymbols.jl v2.0 1.09 ms 21.1 ms 179 ms 902 ms 3.09 s
wigxjpf v1.11 0.237 ms 7.65 ms 68.3 ms 342 ms 1.24 s
0382/WignerSymbol vf8c8dce 0.070 ms 2.26 ms 19.3 ms 93.5 ms 320 ms
sympy v1.11 24.8 ms 1.15 s 20.8 s / /

A second set of benchmarks checks computing Wigner symbols for large j, with the corresponding m varying from -10 to 10, i.e. in pseudo code:

if cached_wigner_3j:
    clear_wigner_3j_cache()

# only measure the time taken by the loop
start = time.now()
for m1 in range(-10, 10 + 1):
    for m2 in range(-10, 10 + 1):
        for m3 in range(-10, 10 + 1):
            w3j = wigner_3j(j1, j2, j3, m1, m2, m3)

elapsed = start - time.now()
code & version j1=300, j2=100, j3=250
wigners (this) 29.2 ms
wigner-symbols v0.5 13.8 ms
WignerSymbols.jl v2.0 11.5 ms
wigxjpf v1.11 7.45 ms
0382/WignerSymbol vf8c8dce / (wrong result)
sympy v1.11 2.34 s

To run the benchmarks yourself on your own machine, execute the following commands:

cd benchmarks
cargo bench # this gives the results for wigners, wigner-symbols, wigxjpf and 0382/WignerSymbol

python sympy-bench.py # this gives the results for sympy

julia wigner-symbol.jl # this gives the results for WignerSymbols.jl

Comparison to wigner-symbols

There is another Rust implementation of wigner symbols: the wigner-symbols crate. wigner-symbols also implements 6j and 9j symbols, but it was not usable for my case since it relies on rug for arbitrary precision integers and through it on the GMP library. The GMP library might be problematic for you for one of these reason:

  • it is relatively slow (see the benchmarks above)
  • it is distributed under LGPL (this crate is distributed under Apache/MIT);
  • it is written in C and C++; and as such is hard to cross-compile or compile to WASM;
  • it does not support the MSVC compiler on windows, only the GNU compilers

As you can see in the benchmarks above, this usage of GMP becomes an advantage for large j, where the algorithm used in this crate does not scale as well.

License

This crate is distributed under both the MIT license and the Apache 2.0 license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wigners-0.4.0.tar.gz (32.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

wigners-0.4.0-py3-none-win_amd64.whl (167.1 kB view details)

Uploaded Python 3Windows x86-64

wigners-0.4.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (312.3 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

wigners-0.4.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (304.0 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

wigners-0.4.0-py3-none-macosx_11_0_x86_64.whl (275.2 kB view details)

Uploaded Python 3macOS 11.0+ x86-64

wigners-0.4.0-py3-none-macosx_11_0_arm64.whl (266.4 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file wigners-0.4.0.tar.gz.

File metadata

  • Download URL: wigners-0.4.0.tar.gz
  • Upload date:
  • Size: 32.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for wigners-0.4.0.tar.gz
Algorithm Hash digest
SHA256 34c956a91b47ca8b360060977fe9104de25d1238ce57cabdd2c844fc4c1fff4e
MD5 381ef4d2257ccfa6bbe4d8c21d1fe9eb
BLAKE2b-256 e374e2175c5cd59aabefa9c32d681d0156f7c2a78ff23dedf0a3920c5ac46831

See more details on using hashes here.

File details

Details for the file wigners-0.4.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: wigners-0.4.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 167.1 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.4

File hashes

Hashes for wigners-0.4.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 ead0e2a8232f76200591490693de716c116128a1ac02e4255553d9443b8d5489
MD5 ed41ac3bd16c1b1444d1f70f817c8b12
BLAKE2b-256 c92bd6242b181a5e8ced73d7390a2db686d0f9c4dc9d9a9fae4239fc495c1644

See more details on using hashes here.

File details

Details for the file wigners-0.4.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for wigners-0.4.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 b9c30a7d7ba7c323cb53cc73e6419111ced562558d57fc63621f0ba01239ba88
MD5 3e427978f63ab07efb0c0f8db51e745e
BLAKE2b-256 63d977ac528bc2a3a4e49525e0c920f73315b8dff0997bc170d70fdcb5f01042

See more details on using hashes here.

File details

Details for the file wigners-0.4.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for wigners-0.4.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 5eb3b43e2834a1a3e4e44f0775873771a1a53d9cf43007554c35133a49d5afb4
MD5 55f8d036b24fda60ac01a98df39eb284
BLAKE2b-256 04e467e7e222eac268a0702723a0c4c021dd4b2dc1569bab1ed3e56278dc4cd1

See more details on using hashes here.

File details

Details for the file wigners-0.4.0-py3-none-macosx_11_0_x86_64.whl.

File metadata

File hashes

Hashes for wigners-0.4.0-py3-none-macosx_11_0_x86_64.whl
Algorithm Hash digest
SHA256 59427903261c45a1efd06da480d4773b71370618f85f4b644d1302fe42c1b794
MD5 690e930800e5894f8df5a9097c761ff0
BLAKE2b-256 218a2db9fb81dce1f63282b7133498a69abb27d648bba101a9df07156f3d9a97

See more details on using hashes here.

File details

Details for the file wigners-0.4.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for wigners-0.4.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7a2caed85dc5d9d7cc23da34a183853a944e45fa50781cf93b3e53efe7fa2d8e
MD5 f67c5a064b9d5c42d3e246549fca57d2
BLAKE2b-256 5284238f04748bb8ab8c42a7acded04cb56d03aaae1d16d021039ac94df07415

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page