C++ 寻找一个好的空间分区数据结构,从中快速生成数百万个原子键

C++ 寻找一个好的空间分区数据结构,从中快速生成数百万个原子键,c++,optimization,data-structures,space-partitioning,C++,Optimization,Data Structures,Space Partitioning,我正在进行一些涉及数百万个原子系统的MD模拟 我已经编写了一些代码来生成一个文件,它只是一个XYZ原子坐标列表。现在我需要在原子之间生成键。如果两个原子彼此之间的距离在一定范围内,则认为这是一个键 示例XYZ文件: 1 0 0 2 0 0 7 0 0 10 0 0 9 0 0 所以我有五个原子。如果我的距离阈值为2个单位,那么我的债券列表将为: 1 2 3 5 4 5 (其中数字对应于XYZ文件中坐标的索引) 生成此列表的简单方法是: for i = 1:numAtoms for j

我正在进行一些涉及数百万个原子系统的MD模拟

我已经编写了一些代码来生成一个文件,它只是一个XYZ原子坐标列表。现在我需要在原子之间生成键。如果两个原子彼此之间的距离在一定范围内,则认为这是一个键

示例XYZ文件:

1 0 0
2 0 0
7 0 0
10 0 0
9 0 0
所以我有五个原子。如果我的距离阈值为2个单位,那么我的债券列表将为:

1 2
3 5
4 5
(其中数字对应于XYZ文件中坐标的索引)

生成此列表的简单方法是:

for i = 1:numAtoms
    for j = i+1:numAtoms
        if distance(atom[i], atom[j]) < 2
            bonds.push [i, j]
i=1时的
数值
对于j=i+1:numtoms
如果距离(原子[i],原子[j])<2
bonds.push[i,j]
然而,这很快就达到了算法的极限,而且即使在对数百万个原子进行高度优化的C语言中,速度也很慢,至少和我将要做的一样频繁

我在空间分区数据结构方面的唯一经验是在我写过一次光子映射器时使用了kd树,所以我真的不知道这个问题的最佳解决方案是什么。我相信可能有一些东西是最适合的


我还应该提到我的模拟框是周期性的,这意味着(0.5,0,0)处的原子将以距离阈值(如2)与(框宽-0.5,0,0)处的原子键合。

简单的解决方案是第一个尝试的。它们编码速度快,易于测试。如果这不能提供所需的性能,那么您可以尝试更复杂的方法

因此,你可以通过给你的原子分配网格坐标来大幅削减搜索空间。没什么技术性的。就像一个穷人的八叉树

你所需要做的就是将网格大小设为2,然后搜索本地网格和每个相邻网格中的所有原子。很明显,网格是3D的。原子的网格位置并不比将每个原子的坐标除以网格大小更复杂

显然,你做了一个初步的过程,并创建了一个属于每个细胞的原子列表(或向量)。可以将列表存储在由三维栅格坐标索引的
地图中。然后,对于每个原子,您只需查找本地列表并进行键测试


另外,不要使用距离的平方根。以距离平方来操作。这将节省大量的处理。

您可以使用与光子映射器中使用的kd树完全相同的kd树。然后,将从粒子(针对每个粒子)搜索阈值半径内的所有粒子。您还必须修改搜索算法以考虑边界条件。在您的案例中,这似乎是最容易实现的,因为您已经有了kd树数据结构。感谢您接受我的答案=)这种方法成功了吗,还是需要做一些更棘手的事情?像往常一样,最简单的方法是最好的。我尝试了你的建议和副总裁树。VP树需要太多的维护和认知开销。就“仅仅工作”而言,网格很难被击败。