0

我正在用 C++ 模拟分子动力学。我的代码的主要结构如下

particle Molecule[N];
collider Newton;
//initialization of the molecules
    for(t=0; t<=tmax; t+=dt){
    for(int i=0; I<N; i++)Newton.MovePosition(Molecule[i]);
    Newton.CalculateForces(Molecule);
    for(int i=0; I<N; i++)Newton.MoveVelocity(Molecule[i])
    for(int i=0; I<N; i++)Newton.MovePosition(Molecule[i]);
    .
    .
    .
}

对撞机类是粒子类的朋友,它知道每个粒子在哪里,它的速度是多少,等等。粒子与正常的 Lenard Jhones 势相互作用。在计算力中,我有这样的东西

for(int i=0; i<N; i++)
  for(int j=i+1;j<N; j++ )
    Molecule[i].F=......

我本质上是在计算每个其他分子对分子 i 所做的力。我遇到的问题是这个程序效率很低。我有 2 个嵌套的 for 循环。计算力和积分算法中的力。我想优化这段代码,因为使用 25 个粒子和 10^5 次迭代需要很长时间才能运行,而对于模拟,我想要这样做,我必须至少有 10^3 个分子和 10^5 次迭代。我尝试了以下方法:

  1. 我尝试使用 #omp parallel for 并行化 for 循环,并且工作速度比串行版本慢。
  2. 我读到了 Verlet 列表,基本上,粒子不会与所有粒子相互作用,而只会与它们的邻居相互作用。这意味着力计算嵌套循环的大小变得更小。这样做的问题是,要列出你必须遍历所有粒子并以某种方式告诉每个粒子它的邻居如何。然后遍历该邻居数组。我一直在考虑如何以有效的方式做到这一点,但我还没有想出答案。
  3. 为了减少 Verlet 列表实现的计算成本,我发现了一种叫做跳过列表的东西,这使得在列表中搜索某物成为 O(ln(N)) 操作而不是 O(N)。但实际上我不太了解它是如何工作的,也不知道如何集成到 Verlet 列表问题中。
  4. 在过去,我进行了空间并行化,其中每个核心都对空间中的某个区域进行计算。这样做的问题是与 Verlet 列表不兼容,我读过 Verlet 列表更好。
  5. 因为移动位置和速度的操作类似于 V+=F dt常数,所以我认为一些缩减算法会有所帮助,但我对缩减算法一无所知,所以有帮助。
  6. 最后,我认为也许在 c++ 17 或 20 中,算法库中可能有一些可以提供帮助的东西,但我对算法知之甚少,所以我花了很长时间阅读文档并确定它的用处。到目前为止,我已经开始使用向量而不是数组添加 for auto。另外,我有一个小型库,允许我将变量定义为 3D 向量并进行法线向量运算。

所以我被困在这里,我对编程知之甚少,不知道该做什么,我发现的解决方案与我现在遇到的问题相同。所以,如果有人可以帮助我就如何集成所有这些东西,或者如何优化我的代码,或者如果它知道可以帮助我的特殊数据结构或算法提供建议,我真的很感激帮助。目标是使单个时间步长的积分算法至少为 O(N)。谢谢。

4

0 回答 0