周期边界条件下Verlet算法MD模拟的逃逸能量 我试图在C++中编写一个非常基本的MD仿真代码,用于在具有周期性边界条件的30x30x30盒中的125个粒子系统。我已经成功地初始化了盒子,但是每当我在多个时间步上运行代码时,对于某些粒子,能量会爆炸,位置

周期边界条件下Verlet算法MD模拟的逃逸能量 我试图在C++中编写一个非常基本的MD仿真代码,用于在具有周期性边界条件的30x30x30盒中的125个粒子系统。我已经成功地初始化了盒子,但是每当我在多个时间步上运行代码时,对于某些粒子,能量会爆炸,位置,c++,C++,周期边界条件下Verlet算法MD模拟的逃逸能量 我试图在C++中编写一个非常基本的MD仿真代码,用于在具有周期性边界条件的30x30x30盒中的125个粒子系统。我已经成功地初始化了盒子,但是每当我在多个时间步上运行代码时,对于某些粒子,能量会爆炸,位置不会落在盒子内。我相当肯定这是一个周期性边界条件的问题,但我不能弄清楚问题是什么。我已在下面附上我的代码,如有任何建议,我将不胜感激。谢谢 /***************************************************

周期边界条件下Verlet算法MD模拟的逃逸能量 我试图在C++中编写一个非常基本的MD仿真代码,用于在具有周期性边界条件的30x30x30盒中的125个粒子系统。我已经成功地初始化了盒子,但是每当我在多个时间步上运行代码时,对于某些粒子,能量会爆炸,位置不会落在盒子内。我相当肯定这是一个周期性边界条件的问题,但我不能弄清楚问题是什么。我已在下面附上我的代码,如有任何建议,我将不胜感激。谢谢

/******************************************************************************************************************************************
 * Program:
 * Create MD simulation for small system of particles
 ******************************************************************************************************************************************/

//include
#include <fstream>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <cstring>
#include <iostream>
#include <stdio.h>
#include <unistd.h>

int N; //number of particles
int l; //length of box
double T; //temp
double dt; //time step
double m; //mass
int nsteps; //number of time steps

//properties of lj potential
double sigma;
double rcut;
double ecut;
double ep;

double K; //kinetic energy of system
double Kp; //I have a time delay in the KE calculation so I need to store the value
double energy; //energy

//vector with position data
std::vector<std::vector<double> > r;
//vector with previous position data
std::vector<std::vector<double> > rp;
//vector with velocity data
std::vector<std::vector<double> > v;
//vector with force data
std::vector<std::vector<double> > f;
//vector with acceleration data
std::vector<std::vector<double> > a;
//vector to store position difference between two steps
std::vector<std::vector<double> > dr2t;

void init_pos(int l, int N);
void init_vel(int N, double T, double dt);
void force(int N, double dt);
void accel(double m);
void integrate(double dt);
void vel(double dt);


int main () {

  // simulation parameters
  N = 125;
  l = 30;
  T = 0.3;
  dt = 0.001;
  m = 1;
  nsteps = 501;

  //properties of lj potential
  sigma = 1;
  rcut = 3.5*sigma;
  ep = 1;
  ecut = 4*ep*(pow((sigma/rcut),12.0) - pow((sigma/rcut),6.0));

  //initialize the positions and velocities
  init_pos(l,N);
  init_vel(N,T,dt);

  //open file to store positions
  FILE * out_pos;
  out_pos = fopen("Shea_positions.dat", "w");

  //open file to store energy info
  FILE * out_en;
  out_en = fopen("Shea_energy.dat", "w");

  //header in pos file for time step 0
  fprintf(out_pos, "%d \n", N);
  fprintf(out_pos, "Time Step: 0 \n");

  //print positions of each particle
  for(int i=0; i<N; i++) {

    fprintf(out_pos, "%d %f %f %f\n", i, r[i][0], r[i][1], r[i][2]);

  }

  //time loop to perform multiple steps
  for (int t=1; t<nsteps; t++) {

    //header in file for each time step
    //fprintf(out_pos, "\n");
    fprintf(out_pos, "%d \n", N);
    fprintf(out_pos, "Time Step: \t%d \n", t);

    Kp = K; //kinetic energy of system at current time step (calculated in next time step after initialization)

    //perform calculations at each time step
    force(N, dt);
    accel(m);
    integrate(dt);
    vel(dt);

    //print positions of each particle
    for(int i=0; i<N; i++) {

      fprintf(out_pos, "%d %f %f %f\n", i, r[i][0], r[i][1], r[i][2]);

    }

  //output to energy file
    fprintf(out_en, "%d %f %f %f\n", t-1, energy, Kp, energy+Kp);


  }

    fclose(out_pos);
    fclose(out_en);  

}


/*********************************************************************************************************************************/

//function to initialize positions

void init_pos(int l, int N) {

  int n = (int) cbrt(N); //number of particles in row
  int a = 1; //lattice spacing
  r.resize(N, std::vector<double>(3, 0));


  for (int i=0; i<n; i++) {
    for (int j=0; j<n; j++) {
      for (int k=0; k<n; k++) {

        int num_part = i*n*n+j*n+k;
        r[num_part][0] = i*a-n/2*a;
        r[num_part][1] = j*a-n/2*a;
        r[num_part][2] = k*a-n/2*a;

      }
    }
  }

}

/*********************************************************************************************************************************/

//function to initialize velocities

void init_vel(int N, double T, double dt) {
  int RANDMAX=10000;
  rp.resize(N, std::vector<double>(3, 0));
  v.resize(N, std::vector<double>(3, 0));
  std::vector<double> vcom(3, 0);
  double sumv2 = 0;

  K=0; //initialize kinetic energy at 0

  for (int i=0; i<N; i++) {
    for (int alpha=0; alpha<3; alpha++) {
      v[i][alpha] = ((double)(rand() % RANDMAX) / RANDMAX)-0.5; //assign random velocities from -0.5 to 0.5
      vcom[alpha] += v[i][alpha]; //calculate the com velocity
      sumv2 += v[i][alpha]*v[i][alpha];

    }
  }

  for (int alpha=0; alpha<3; alpha++) {
    vcom[alpha] /= N; //translational velocity of system to remove
  }

  sumv2 = sumv2/N; //average KE per particle
  double sf = sqrt(3*T/(sumv2)); //scaling factor

  for (int i=0; i<N; i++) {
    for (int alpha=0; alpha<3; alpha++) {
      v[i][alpha] -= vcom[alpha]; //correct for com velocity
      v[i][alpha] *= sf; //multiply by scaling factor to give the correct temp
      rp[i][alpha] = r[i][alpha] - v[i][alpha]*dt; //calculate the previous position

    }

  K += 0.5*m*(v[i][0]*v[i][0]+v[i][1]*v[i][1]+v[i][2]*v[i][2]); //find total kinetic energy of the system

  }   

}

/*********************************************************************************************************************************/

//calculate force on each particle from the lj potential

void force(int N, double dt) {

  f.resize(N, std::vector<double>(3, 0));
  energy = 0.;

  std::vector<double> dr(3, 0);
  double dr2;

  for (int i=0; i<N; i++) {
    for (int j=0; j<i; j++) {

      //calculate distance vector between two particles
      dr[0] = r[i][0]-r[j][0];
      dr[1] = r[i][1]-r[j][1];
      dr[2] = r[i][2]-r[j][2];

      //make sure pbc works by taking minimum dist between particles i and j
      dr[0] -= l*round(dr[0]/l);
      dr[1] -= l*round(dr[1]/l);
      dr[2] -= l*round(dr[2]/l);

      dr2 = dr[0]*dr[0] + dr[1]*dr[1] + dr[2]*dr[2]; //distance between particles i and j squared


      if(dr2<rcut*rcut) {
        double invr2 = 1./dr2;
        double invr6 = invr2*invr2*invr2;
        double ff = 48.* invr2*invr6*(invr6-0.5); //modulus of the force on a particle

        //add force to particle i
        f[i][0] += ff*dr[0];
        f[i][1] += ff*dr[1];
        f[i][2] += ff*dr[2];

        //add equal and oppostie force to particle j  
        f[j][0] -= ff*dr[0];
        f[j][1] -= ff*dr[1];
        f[j][2] -= ff*dr[2];

        //calculate the potential energy of the particle
        energy += 4*invr6*(invr6-1)-ecut;

      }

    }
  }

}

/*********************************************************************************************************************************/

//calculate the acceleration of the particle from the force

void accel(double m) {

  a.resize(N, std::vector<double>(3, 0));

  for (int i=0; i<N; i++) {
    for (int alpha=0; alpha<3; alpha++) {
      a[i][alpha] = f[i][alpha]/m;

    }
  }
}

/*********************************************************************************************************************************/

//integrate to get the new position of the particle after one time step

void integrate(double dt) {

  dr2t.resize(N, std::vector<double>(3, 0));

  for (int i=0; i<N; i++) {

    for (int alpha=0; alpha<3; alpha++) {

      double rr = 2*r[i][alpha] - rp[i][alpha] + dt*dt*a[i][alpha]; //new pos from velocity verlet alg
     printf("%f %f %f \n", rr,r[i][alpha],rp[i][alpha]);
//printf("%f \n", a[i][alpha]);
      if (rr >= l/2) {
        rr -= l;
      }
      if (rr < -l/2) {
        rr += l;
      }

      dr2t[i][alpha] = rr - rp[i][alpha]; //difference between new position and previous position so you can find velocity
      dr2t[i][alpha] -= l*round(dr2t[i][alpha]/l);

      rp[i][alpha] = r[i][alpha]; //current position becomes previous position
      r[i][alpha] = rr; //new position becomes current positions

    }     

  }

}

/*********************************************************************************************************************************/

//velocity

void vel(double dt) {

  K = 0;

  for (int i=0; i<N; i++) {
    for (int alpha=0; alpha<3; alpha++) {

  //printf("%f %f %f \n", dr2t[i][0], dr2t[i][1], dr2t[i][2]);

      v[i][alpha] = dr2t[i][alpha]/(2*dt);

    }

  K += 0.5*m*(v[i][0]*v[i][0]+v[i][1]*v[i][1]+v[i][2]*v[i][2]);

  }

}

/*********************************************************************************************************************************/        
/******************************************************************************************************************************************
*节目:
*为小粒子系统创建MD模拟
******************************************************************************************************************************************/
//包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int N//粒子数
int l//箱长
双T//临时雇员
双dt//时间步长
双m//大量
int nsteps//时间步数
//lj势的性质
双西格玛;
双rcut;
双ecut;
双ep;
双K//系统动能
双Kp//我在KE计算中有一个时间延迟,所以我需要存储该值
双能量//能量
//带位置数据的向量
std::向量r;
//具有先前位置数据的向量
std::向量rp;
//带速度数据的矢量
std::向量v;
//带有力数据的向量
std::向量f;
//带加速度数据的矢量
std::载体a;
//用于存储两个步骤之间的位置差的向量
std::载体dr2t;
无效初始位置(整数l,整数N);
无效初始值(整数N,双T,双dt);
空隙力(int N,双dt);
真空加速(双m);
虚积分(双dt);
无效水平(双dt);
int main(){
//模拟参数
N=125;
l=30;
T=0.3;
dt=0.001;
m=1;
nsteps=501;
//lj势的性质
西格玛=1;
rcut=3.5*西格玛;
ep=1;
ecut=4*ep*(功率((sigma/rcut),12.0)-功率((sigma/rcut),6.0);
//初始化位置和速度
初始位置(l,N);
初始水平(N,T,dt);
//打开文件以存储位置
文件*输出位置;
out_pos=fopen(“Shea_positions.dat”、“w”);
//打开文件以存储能量信息
文件*out_en;
out_en=fopen(“Shea_energy.dat”,“w”);
//时间步长0的pos文件中的标头
fprintf(输出位置,“%d\n”,n);
fprintf(out_pos,“时间步长:0\n”);
//打印每个粒子的位置

对于(int i=0;i问题通常是浮点物理不精确,小错误会累积。可以使用缩放整数,也可以添加一个小阻尼因子。一种诊断方法是检查每个粒子总能量的百分比。如果只有一个粒子增长,则输出值并调试它。如果所有粒子都有规律地增长,则只需对其进行归一化和调整通过相同的因子使总能量保持不变。问题是你的势是奇异的。Verlet方法只有在势是光滑的情况下才能很好地工作。因此,每当两个粒子非常接近时,能量就会发生无法形容的事情。在某种程度上,这可以通过减小步长来减少,但一般问题仍然存在s