5 个不稳定版本
0.3.0 | 2023 年 3 月 28 日 |
---|---|
0.2.1 | 2022 年 4 月 5 日 |
0.2.0 | 2022 年 4 月 4 日 |
0.1.1 | 2022 年 2 月 3 日 |
0.1.0 | 2022 年 2 月 3 日 |
#206 在 科学
每月 28 下载
48KB
887 行
Wigner 符号和相关常数的计算
此包使用纯 Rust 计算 Wigner 3j 系数和 Clebsch-Gordan 系数。计算基于系数中不同阶乘的素因子分解,尽可能长时间地保持值为有理根形式(sign * \sqrt{s / n}
),此算法的想法在
H. T. Johansson 和 C. Forssén,SIAM Journal on Scientific Computing 38 (2016) 376-384
此实现从 Julia 实现 WignerSymbols 中汲取了大量的灵感(甚至最初是它的直接翻译),非常感谢他们!此包的许可与 Julia 包相同。
用法
从 Python
pip install wigners
然后调用其中一个导出函数
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()
从 Rust
将此 crate 添加到您的 Cargo.toml
依赖项部分
wigners = "0.3"
然后调用其中一个导出函数
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 3j 符号,因为这是我自身工作中唯一需要的部分。
6j 和 9j 符号也可以使用这种方法计算;并且半整数的支持应该是可行的。我对实现这些功能的 pull-request 开放。
基准测试
此基准测试测量计算所有可能的 Wigner 3j 符号所需的时间,直到固定的最大角动量;在开始循环之前清除先前角动量的任何缓存值。在伪代码中,基准测试看起来像这样
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()
以下是在 Apple M1 Max(10 核心)CPU 上的结果
角动量 | wigners(本实现) | wigner-symbols v0.5 | WignerSymbols.jl v2.0 | wigxjpf v1.11 | sympy v1.11 |
---|---|---|---|---|---|
4 | 0.190 毫秒 | 7.50 毫秒 | 2.58 毫秒 | 0.228 毫秒 | 28.7 毫秒 |
8 | 4.46 毫秒 | 227 毫秒 | 47.0 毫秒 | 7.36 毫秒 | 1.36 秒 |
12 | 34.0 毫秒 | 1.94 秒 | 434 毫秒 | 66.2 毫秒 | 23.1 秒 |
16 | 156 毫秒 | 9.34 秒 | 1.98 秒 | 333 毫秒 | / |
20 | 531 毫秒 | / | 6.35 秒 | 1.21秒 | / |
另一组基准测试检查大j
的Wigner符号计算,相应的m
从-10变化到10,即伪代码如下
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()
(j1, j2, j3) | wigners(本实现) | wigner-symbols v0.5 | WignerSymbols.jl v2.0 | wigxjpf v1.11 | sympy v1.11 |
---|---|---|---|---|---|
(300, 100, 250) | 38.7毫秒 | 16.5毫秒 | 32.9毫秒 | 7.60毫秒 | 2.31秒 |
要在您的机器上运行基准测试,请执行以下命令
cd benchmarks
cargo bench # this gives the results for wigners, wigner-symbols and wigxjpf
python sympy-bench.py # this gives the results for sympy
julia wigner-symbol.jl # this gives the results for WignerSymbols.jl
与wigner-symbols
的比较
还有一个Rust实现的Wigner符号:名为wigner-symbols的crate。 wigner-symbols
也实现了6j和9j符号,但由于它依赖于rug进行任意精度整数计算,并通过它依赖于GMP库,所以它不适合我的情况。GMP库可能有以下问题
- 它相对较慢(见上面的基准测试)
- 它以LGPL许可证分发(这个crate以Apache/MIT许可证分发);
- 它用C和C++编写,因此难以交叉编译或编译到WASM;
- 它不支持Windows上的MSVC编译器,只支持GNU编译器
如上图基准测试所示,对于大j,这种GMP的使用成为优势,因为此crate中使用的算法在扩展性方面表现不佳。
许可证
此crate同时以MIT许可证和Apache 2.0许可证分发。
依赖项
~3.5–9MB
~73K SLoC