我正在进行一些涉及数百万个原子系统的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]
然而,这很快就会达到算法极限,即使在数百万个原子的高度优化的C中也很慢,至少在这个过程中我会这么频繁。
我对空间分区数据结构的唯一体验是当我写一次光子映射器时使用kd-tree,所以我真的不知道这个问题的最佳解决方案是什么。我确信那里可能有一些最适合这种情况的东西。
我还应该提到我的模拟框是周期性的,这意味着(0.5,0,0)处的原子将与(boxWidth - 0.5,0,0)处的原子结合,距离阈值如2。 / p>
答案 0 :(得分:7)
首先尝试简单的解决方案。它们编码速度快,易于测试。如果这不能提供所需的性能,那么你可以尝试一些比较棘手的事情。
因此,您可以通过为原子分配网格坐标来严格修剪搜索空间。没什么技术性的。就像一个穷人的八叉树......
您需要做的就是网格大小为2,并搜索本地网格和每个相邻网格中的所有原子。网格显然是3D。原子的网格位置并不比将每个坐标除以网格大小复杂得多。
显然,你进行初步传递并创建属于每个细胞的原子列表(或矢量)。您可以将列表存储在由3D网格坐标索引的map
中。然后对于每个原子,您可以只查找本地列表并进行键合测试。
另外,不要使用平方根作为距离。改为以距离平方运行。这样可以节省大量的处理负担。