#gravity #nbody

bigbang

用于n-(硬)体引力模拟的优化框架

10个版本

0.0.11 2021年5月2日
0.0.10 2021年5月2日
0.0.9 2020年1月23日
0.0.6 2019年12月8日
0.0.5 2019年9月19日

#54 in 模拟

Download history 2/week @ 2024-03-10 70/week @ 2024-03-31 1/week @ 2024-04-07

57 每月下载量

自定义许可

1.5MB
739

docs.rs crates.io 构建状态 您在工作中使用过这个项目吗?我很乐意了解并与其合作。请通过[email protected]给我发邮件。

关于项目

这是一个为了速度比较而重新实现C++粒子模拟的Rust项目。我最初与Trinity大学的Mark Lewis博士在2015年创建了此分支。Rust在接下来的几年中变化很大,所以我于2019年重新编写了它。

3d示例 3D基于Websocket的模拟在示例目录中可用,由Casey Primozic提供。

它到底做了什么?

它构建一个k维空间树(3维)并最优地计算引力加速度力和碰撞。

开始使用bigbang

实现AsEntityResponsive特性

为了在这个树中使用你的任意类型,你的结构体必须是AsEntity + Responsive + Clone + Send + Sync。我希望最终去除Clone要求,但当前树以不可变方式工作,每次时间步长都会构建一个完全新的树,并将引力加速度应用于它。这使得并行化更容易推理和更安全,需要Clone。需要SendSync以实现并行化。

AsEntity要求你将你的结构体表示为引力实体,这意味着提供速度和位置向量,以及半径和质量(在此模拟中,所有物体都是球体)。

您必须实现的核心功能是特性 Responsive。这个特性定义了您的结构体如何对每个时间步的模拟结果做出响应。

impl bigbang::AsEntity for MyStruct {
    fn as_entity(&self) -> bigbang::Entity;
}

impl bigbang::Responsive for MyStruct {
    fn respond(&self, simulation_result: bigbang::SimulationResult, time_step: f64) -> Self;
}

as_entity 函数必须接收您的结构体,并返回一个由速度向量、位置向量、半径和质量组成的重力实体。

struct MyEntity {
    pub vx: f64,
    pub vy: f64,
    pub vz: f64,
    pub x: f64,
    pub y: f64,
    pub z: f64,
    pub radius: f64,
    pub mass: f64,
}

如果您的结构体具有这些字段,并且已经按照这种方式命名,则可以派生 AsEntity 特性。

use bigbang::AsEntity;
#[derive(AsEntity)]
struct MyEntity {
    pub vx: f64, // because these fields are named 
    pub vy: f64, // the standard way, the same as in
    pub vz: f64, // the `AsEntity` trait, we can use
    pub x: f64,  // the automatic derive.
    pub y: f64,
    pub z: f64,
    pub radius: f64,
    pub mass: f64,
}

respond(&self, simulation_result: SimulationResult, time_step: f64) -> Self 允许用户决定如何对模拟结果做出响应。在 examples 目录中提供了许多示例,以及在 collisions 模块中的一些辅助碰撞计算函数。

启动模拟

现在,您已经有了足够特性实现的合规类型,可以构建一个包含所有这些实体起始位置的向量。将这个向量的可变引用和一个 time_step 系数传递给 GravTree::new(),然后您就可以开始比赛了

use bigbang::{ GravTree, AsEntity };

struct MyEntity { ... }

impl AsEntity for MyEntity { ... }

impl Responsive for MyEntity { ... }

let mut my_vec:Vec<MyEntity> = vec![entity1, entity2, entity3];
let grav_tree = GravTree::new(&my_vec, 0.2);

time_step 系数稍后会被传递给 respond()。它可以用来有效地控制模拟的粒度,即每个模拟帧实际上对实体运动的影响程度。较小的 time_step 将导致更细粒度、更精确的模拟。您可能需要稍微调整一些常数,以找到适合您用例的理想值。为了推进模拟,请调用 grav_tree.time_step()

请参阅示例目录中的最小化工作示例。

C/C++ 接口

曾经有一个健壮的 C/C++ 接口用于这个库,但在开发过程中随着 API 的快速变化,维护变得困难。如果您使用过这个 FFI,并且希望重新引入它,请 联系我,我会帮助您设置它。否则,FFI 将暂停,直到这个包稳定下来。

依赖关系