2 个版本

0.2.1 2022年6月19日
0.2.0 2022年4月7日

#278科学

MIT/Apache

485KB
9K SLoC

Lattice QCD rs

License Build codecov

经典晶格量子场论模拟和工具。

这个库提供了一个在晶格上模拟纯规范 SU(3) 理论的工具。它旨在提供通用的工具,以便可以使用多种不同的模拟或方法。您可以轻松选择蒙特卡洛算法,您可以实现自己的哈密顿量等。它还提供了一种在 1 到 usize::MAX 维度之间进行模拟的简单方法。因此,这个库不仅限于 d = 3 或 d = 4。

查看我的其他仓库 plaquette,这是我在研究中使用的模拟二进制文件集。

功能:

  • 通用维度;
  • 可配置的蒙特卡洛算法;
  • 多平台;
  • 可配置的哈密顿量;
  • Serde 支持;
  • 原生 Rust;
  • 一些统计工具;

尚未实现的功能:

  • 更多的统计工具;
  • 费米子支持;
  • SU(N) 支持;
  • 配置文件;
  • C 兼容的 API / ABI;

使用方法

lattice_qcd_rs = { version = "0.2.1", git = "https://github.com/ABouttefeux/lattice_qcd_rs" } 添加到您的 cargo.toml。默认启用的功能集包括

  • serde-serialize 允许在结构中使用 serde;
  • no-overflow-test 用于禁用覆盖范围的溢出测试。

目前它不在 crates.io 上。也许我会添加它。但到目前为止,它仍在开发中。请注意,您可能需要指定特定的提交,因为现在我可能会引入破坏性变更。然而,一旦我准备好发布版本 0.2.0,我将致力于更高的稳定性。

首先,让我们看看如何在10x10x10x10的晶格上使用beta = 1进行模拟。我们想要计算在经过一定步数后所有面砖迹线的 1/3 <Re(Tr(P_{ij}))>。在我们的例子中,Beta值较小,所以我们选择了100,000步。

extern crate lattice_qcd_rs as lq;
extern crate rand_xoshiro;

use lq::prelude::*;

# use std::error::Error;
# fn main() -> Result<(), Box<dyn Error>> {
    let mut rng = rand_xoshiro::Xoshiro256PlusPlus::from_entropy();

    let size = 1000_f64;
    let number_of_pts = 10;
    let beta = 1_f64;

    let mut simulation =
        LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?;

    let spread_parameter = 0.1_f64;
    let mut mc = MetropolisHastingsDeltaDiagnostic::new(spread_parameter, rng)?;

    for _ in 0..100 {
        for _ in 0..1_000 {
            simulation = simulation.monte_carlo_step(&mut mc)?;
        }
        // the more we advance te more the link matrices
        // will deviate form SU(3), so we reprojet to SU(3)
        // every 1_000 steps.
        simulation.normalize_link_matrices();
    }

    let average = simulation.average_trace_plaquette().ok_or(ImplementationError::Unreachable)?.real() / 3_f64;
# Ok(())
# }

这个库使用rayon作为并行计算的一种方式。但是并不是所有事情都可以并行化。如果您想要进行多次类似的模拟(例如,您想对Beta = 1、1.1、1.2等进行模拟),请使用rayon。为了进行多次并行模拟。

需要更具体的例子吗?请查看我的其他仓库 plaquette。它包含了我用于研究的二进制文件。

我想做自己的事情。

我想使用自己的哈密顿量

实现 LatticeState 特性。

如果您想使用 hybride Monte Carlo 使用您自己的状态,您将需要为 LatticeStateEFSyncDefault<YourState> 实现 LatticeStateWithEField

我想使用自己的蒙特卡罗算法。

我提供了两种算法: Metropolis Hastingshybride Monte Carlo

查看 MonteCarlo 特性,或者也可以查看 MonteCarloDefault

MonteCarloDefault 可以更容易实现,但请注意,每次我们为之前和新的状态进行步骤时,都会重新计算整个哈密顿量,这可能会导致计算增量哈密顿量较慢。

要使用 MonteCarloDefault 作为 MonteCarlo,有一个包装器: MCWrapper

为什么?

这是一些用于我博士论文的代码。主要我使用 arXiv:0707.2458arXiv:0902.28568arXiv:2010.07316 作为基础。

目标

目标是提供一个易于使用、快速且安全的库,用于进行经典晶格模拟。

关于随机数生成器(RNGs)的讨论

此库在任何需要随机数生成器时都会使用特性 rand::RngCore。RNG的选择由库的用户决定。然而,需要考虑一些权衡。

让我们将不同的生成器分为几类。更多详情请参阅 https://rust-random.github.io/book/guide-gen.html

一些可能的选择

  • 推荐 rand_xoshiro::Xoshiro256PlusPlus 非密码学。它具有良好的性能和统计质量,可重放,并且具有有用的 jump 函数。它是推荐的 PRNG。
  • rand::rngs::ThreadRng 是一个 CSPRNG。数据不可重放,并且经常重新播种。然而,它的速度较慢。
  • rand::rngs::StdRng 是加密安全的,可以播种。它是确定性的,但不同平台之间不可重放。然而,它的速度较慢。
  • rand_jitter::JitterRng 是真正的 RNG,但速度非常慢。

此外,ranlux 也是一个不错的选择。但是,据我所知,没有本地的 Rust 实现它(除了我的,但速度非常慢)。

其他示例

use lattice_qcd_rs::{
    error::ImplementationError,
    ComplexField,
    simulation::monte_carlo::MetropolisHastingsDeltaDiagnostic,
    simulation::state::{LatticeState, LatticeStateDefault},
};

# use std::error::Error;
# fn main() -> Result<(), Box<dyn Error>> {
let mut rng = rand::thread_rng();

let size = 1_000_f64;
let number_of_pts = 4;
let beta = 2_f64;
let mut simulation =
    LatticeStateDefault::<4>::new_determinist(size, beta, number_of_pts, &mut rng)?;

let spread_parameter = 1E-5_f64;
let mut mc = MetropolisHastingsDeltaDiagnostic::new(spread_parameter, rng)
    .ok_or(ImplementationError::OptionWithUnexpectedNone)?;

let number_of_sims = 100;
for _ in 0..number_of_sims / 10 {
    for _ in 0..10 {
        simulation = simulation.monte_carlo_step(&mut mc)?;
    }
    simulation.normalize_link_matrices(); // we renormalize all matrices back to SU(3);
}
let average = simulation.average_trace_plaquette()
    .ok_or(ImplementationError::OptionWithUnexpectedNone)?
    .real();
# Ok(())
# }

或者可以使用其他蒙特卡洛算法,例如

use lattice_qcd_rs::{
    error::ImplementationError,
    simulation::monte_carlo::{McWrapper, MetropolisHastingsDiagnostic},
    simulation::state::{LatticeState, LatticeStateDefault},
};

# use std::error::Error;
# fn main() -> Result<(), Box<dyn Error>> {
let mut rng = rand::thread_rng();

let size = 1_000_f64;
let number_of_pts = 4;
let beta = 2_f64;
let mut simulation =
    LatticeStateDefault::<3>::new_determinist(size, beta, number_of_pts, &mut rng)?;

let number_of_rand = 20;
let spread_parameter = 1E-5_f64;
let mut mc = McWrapper::new(
    MetropolisHastingsDiagnostic::new(number_of_rand, spread_parameter)
        .ok_or(ImplementationError::OptionWithUnexpectedNone)?,
    rng,
);

simulation = simulation.monte_carlo_step(&mut mc)?;
simulation.normalize_link_matrices();
# Ok(())
# }

或者

use lattice_qcd_rs::{
    integrator::SymplecticEulerRayon,
    simulation::monte_carlo::HybridMonteCarloDiagnostic,
    simulation::state::{LatticeState, LatticeStateDefault},
};

# use std::error::Error;
# fn main() -> Result<(), Box<dyn Error>> {
let mut rng = rand::thread_rng();

let size = 1_000_f64;
let number_of_pts = 4;
let beta = 2_f64;
let mut simulation =
    LatticeStateDefault::<3>::new_determinist(size, beta, number_of_pts, &mut rng)?;

let delta_t = 1E-3_f64;
let number_of_step = 10;
let mut mc =
    HybridMonteCarloDiagnostic::new(delta_t, number_of_step, SymplecticEulerRayon::new(), rng);

simulation = simulation.monte_carlo_step(&mut mc)?;
simulation.normalize_link_matrices();
# Ok(())
# }

依赖项

~6MB
~125K SLoC