MD 模拟:邻居列表方法的参考

计算科学 算法 C++ 模拟 分子动力学 最近邻
2021-12-05 21:17:20

凭借相当基本的 C++ 知识,我编写了自己的 MD 模拟代码。目前,我以最幼稚的方式计算力:我遍历所有原子并解释它们的相互作用。这当然是一个O(N2)算法,而且效率很低。这不是问题,除了我的研究目的,我需要模拟 1000 个或更多的原子,而目前这需要很长时间。

我想学习如何实现邻居的列表方法。我读过一些标准的 MD 书籍,但它们通常是 Fortran 或某种我无法破译的语言。我正在寻找有关如何实现此算法的相当现代且易于遵循的指南。这不是我研究的重要部分,所以我想花尽可能少的时间。我不得不承认,我基本上是在问是否有一种快速而肮脏的方法可以让我学习和实现这个算法!有人知道这样的指南吗?或者有实现邻居列表方法的经验吗?

1个回答

我推荐 DC Rapaport 的“分子动力学模拟艺术”。代码示例是用 C 编写的。我不是这本书的编程风格的忠实粉丝,但至少它不是 FORTRAN。话虽如此,我的建议是使用任何解释邻居列表的书(例如 Frenkel & Smit 的书,我想这就是你现在正在使用的书),然后执行通常用伪代码编写的算法.

如果你想要一个 TL;DR,有几种类型的邻居列表。所有这些都依赖于你的交互潜力在一定范围之外为 0rc.

  • Verlet 列表(O(N2)-O(N3/2)但有一个小的前置因子):
    1. 做一个N2扫描每个粒子的位置,您填充的邻居数组比rc+rv, 在哪里rv是一个参数并保存每个粒子的当前位置(我们称之为ri(t0).
    2. 通过使用邻居列表计算力来改进您的模拟。
    3. 在每个积分步骤之后,检查是否对于任何粒子i,|ri(t)ri(t0)|rv/2. 如果是,则更新所有列表(参见步骤 1)。
  • 单元格列表(O(N)):
    1. 将您的模拟框划分为线性大小的单元格l>rc.
    2. 使用链接列表将粒子分配给单元格。
    3. 对于每个粒子i, 邻居列表由所有在i的单元格和每个(2D 中的 8 个和 3D 中的 26 个)相邻单元格中的一个。计算之间的力i及其邻居。
    4. 在每个集成步骤之后,检查粒子是否跨越单元边界并相应地更新数据结构
  • 使用单元列表构建的 Verlet 列表(通常是最佳选择,O(N)使用比仅使用单元更小的前置因子):
    1. “Verlet 列表”部分的第 1 步是通过使用单元格列表来执行的。存储单元数据结构的链表在整个模拟过程中保持更新

使用 Verlet 列表而不是单元列表(在 MD 模拟中)更好的原因是前者的平均邻居数小于后者。不同之处在于,对于每个粒子,单元列表都会为您提供一个体积中的邻居列表(3l)3, 其中, 如果rv明智地选择,远大于 Verlet 球体的体积 (4/3π(rc+rv)3)。因此,平均而言,您使用 Verlet 列表计算的距离要少得多。