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:
- T. Risbo, "Fourier-transform summation of Legendre series by D-matrix transform", https://doi.org/10.1007/BF01090814
- S. Trapani & J. Navaza, "Calculation of spherical harmonics and Wigner d functions by FFT.", https://doi.org/10.1107/S0108767306017478
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:
- wigner-symbols: https://crates.io/crates/wigner-symbols
- WignerSymbols.jl: https://github.com/Jutho/WignerSymbols.jl
- wigxjpf: http://fy.chalmers.se/subatom/wigxjpf/
- 0382/WignerSymbol: https://github.com/0382/WignerSymbol
- sympy: https://docs.sympy.org/latest/modules/physics/quantum/cg.html
| 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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34c956a91b47ca8b360060977fe9104de25d1238ce57cabdd2c844fc4c1fff4e
|
|
| MD5 |
381ef4d2257ccfa6bbe4d8c21d1fe9eb
|
|
| BLAKE2b-256 |
e374e2175c5cd59aabefa9c32d681d0156f7c2a78ff23dedf0a3920c5ac46831
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ead0e2a8232f76200591490693de716c116128a1ac02e4255553d9443b8d5489
|
|
| MD5 |
ed41ac3bd16c1b1444d1f70f817c8b12
|
|
| BLAKE2b-256 |
c92bd6242b181a5e8ced73d7390a2db686d0f9c4dc9d9a9fae4239fc495c1644
|
File details
Details for the file wigners-0.4.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: wigners-0.4.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 312.3 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9c30a7d7ba7c323cb53cc73e6419111ced562558d57fc63621f0ba01239ba88
|
|
| MD5 |
3e427978f63ab07efb0c0f8db51e745e
|
|
| BLAKE2b-256 |
63d977ac528bc2a3a4e49525e0c920f73315b8dff0997bc170d70fdcb5f01042
|
File details
Details for the file wigners-0.4.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.
File metadata
- Download URL: wigners-0.4.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
- Upload date:
- Size: 304.0 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5eb3b43e2834a1a3e4e44f0775873771a1a53d9cf43007554c35133a49d5afb4
|
|
| MD5 |
55f8d036b24fda60ac01a98df39eb284
|
|
| BLAKE2b-256 |
04e467e7e222eac268a0702723a0c4c021dd4b2dc1569bab1ed3e56278dc4cd1
|
File details
Details for the file wigners-0.4.0-py3-none-macosx_11_0_x86_64.whl.
File metadata
- Download URL: wigners-0.4.0-py3-none-macosx_11_0_x86_64.whl
- Upload date:
- Size: 275.2 kB
- Tags: Python 3, macOS 11.0+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59427903261c45a1efd06da480d4773b71370618f85f4b644d1302fe42c1b794
|
|
| MD5 |
690e930800e5894f8df5a9097c761ff0
|
|
| BLAKE2b-256 |
218a2db9fb81dce1f63282b7133498a69abb27d648bba101a9df07156f3d9a97
|
File details
Details for the file wigners-0.4.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: wigners-0.4.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 266.4 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a2caed85dc5d9d7cc23da34a183853a944e45fa50781cf93b3e53efe7fa2d8e
|
|
| MD5 |
f67c5a064b9d5c42d3e246549fca57d2
|
|
| BLAKE2b-256 |
5284238f04748bb8ab8c42a7acded04cb56d03aaae1d16d021039ac94df07415
|