可能是最简单的 MD 模拟的困难

计算科学 分子动力学
2021-11-25 15:09:55

我将继续询问可能出现的调试问题。但是,我正在寻找一些我可能错过的概念,这个问题与我之前的问题有些相关:惰性气体的 NVE MD 模拟:保持平衡的问题,尽管现在是一个不同的问题。如果版主决定关闭它,我理解。

我正在使用以下方法对 100x100 2D 盒子中的 49 个氩粒子进行恒定能量 (NVE) 模拟,Lennard Jones 势在 240 KI 温度下:

1) 单位系统:自然单位系统,质量,LJ 参数,,玻尔兹曼常数,使得 120 K 的温度为 1。m=1σ=1ϵ=1k=1

2)初始条件:方格位置,麦克斯韦-玻尔兹曼速度

3) 积分:具有周期性边界条件的 Velocity-verlet。时间步长 0.001(实际时间为 2fs)

4)我正在检查非零平均速度(飞冰块)的发生:它没有发生。

我无法在超过 2000 个时间步长(实际总时间为 4ps)内将能量守恒保持在 1% 以内。大多数研究、讲义、在线教程等似乎都在使用这些相同的时间步长、参数等值。虽然这些从未说明它们能够保存多长时间(以及在什么精度范围内),但我发现研究论文确实如此平均10ns。我在以下 3 个订单中失败了。至少对于如此简单的事情来说,Velocity verlet 似乎是一个被广泛接受的算法!

这似乎不是一个基本的编码(即非概念性)错误,因为代码在达到大约 4ps 之前运行良好。有些运行我可以达到 6 或 7ps,我猜这只是幸运的初始条件。关于我可能出错的地方有什么有用的建议吗?谢谢。


更新: 1)错误似乎与时间步长无关。大多数论文似乎使用 =0.001,我尝试了从1e-2到1e-5的范围。ΔtΔt

2) 我的积分器代码如下所示: { while(t

  //Energy Calculation
  Ven(t)=ven;
  KE(U,V,ken,N);
  Ken(t)=ken;
  if(t==0)
{
  Hen1=Ken(0)+Ven(0);
  cout<<"Total energy at t=0  is: "<<Hen1<<endl;
}

  //Error Checking
  ErrMeanVel=(U.sum())/N;
  ErrEConserve=(abs(Ken(t)+Ven(t)-Hen1)*100)/Hen1;
  if(ErrMeanVel>1e-6)
{
  cout<<"Flying ice cube at t="<<t*Deltat<<"ps. The mean velocity is"<<ErrMeanVel<<endl;
  break;
}
  if(ErrEConserve>ETol)
    {
      cout<<"Energy conservation violated at t="<<t*Deltat<<"ps. The energy at this time is "<<(Ken(t)+Ven(t))<<" and the percentage error is "<<((abs(Ken(t)+Ven(t)-Hen1)*100)/Hen1)<<endl;
      break;
    }

  //Velocity Verlet
  for (i=0;i<N;i++)
{
  X(0,i)=X(0,i)+(U(0,i)*Deltat)+0.5*Ax(i)*Deltat*(Deltat/mass);
  Y(0,i)=Y(0,i)+(V(0,i)*Deltat)+0.5*Ay(i)*Deltat*(Deltat/mass);
  U(0,i)=U(0,i)+(0.5*Ax(i)*Deltat/mass);
  V(0,i)=V(0,i)+(0.5*Ay(i)*Deltat/mass);
}
  LJ(X,Y,N,ven,Fx,Fy,ctr);
  Ax=Fx.rowwise().sum();
  Ay=Fy.rowwise().sum();
  for (i=0;i<N;i++)
    {
      U(0,i)=U(0,i)+(0.5*Ax(i)*Deltat/mass);
      V(0,i)=V(0,i)+(0.5*Ay(i)*Deltat/mass);
    }
  //Boundary Conditions      
  PeriodicBoundary(X,Y,L,N);
  t++;
}

\力计算器是:(无截止)

 int i=0, j=0;
  double dx=0, dy=0,r2=0,F6=0,F12=0,F=0,Vcut=0;
  fx=MatrixXd::Zero(n,n);
  fy=MatrixXd::Zero(n,n);
  ven=0;
  MatrixXd ft(n,n);
  for (j=0;j<n;j++)
    {
      for(i=j+1;i<n;i++)
    {
      dx=(a(0,j)-a(0,i));
      dy=(b(0,j)-b(0,i));
      r2=dx*dx+dy*dy;
      if(r2<sigma)
        {
          ctr++;
        }
      F6=pow((sigma*sigma/r2),3);
      F12=pow((sigma*sigma/r2),6);
      F=(24*epsilon/r2)*(F6-2*F12);
      ven=ven+4*epsilon*(F12-F6);
      fx(i,j)=F*dx;
      fy(i,j)=F*dy;
    }
    }
  ft=fx.transpose();
  fx=fx-ft;
  ft=fy.transpose();
  fy=fy-ft;
}
1个回答

这是我上面的评论作为答案的重新表述。

您需要在计算时强制执行边界条件dxdy考虑在周期性边界上相互作用的粒子。想象一下域两端的两个粒子:在您当前的设置中,它们不会相互作用,但是一旦它们中的一个稍微移动并越过边界,它们就会突然看到彼此。

大多数模拟只使用所谓的最小图像约定