如何在我对有吸引力的颗粒的模拟中添加硬球排斥

How to add hard-sphere repulsion in my simulation of attractive particles?

本文关键字:模拟 添加 吸引力      更新时间:2023-10-16

我模拟了一个互相吸引的粒子系统。吸引力的强度取决于颗粒之间的距离。边界条件和相互作用是周期性的。由于吸引力,粒子彼此相处并聚集了一个圆圈。

我想添加硬球的排斥,以便每当两个或多个粒子聚集在相同位置时,我希望它们在连接其中心的线路中分开,直到它们不重叠为止。我该怎么做?

当存在吸引人的相互作用时,添加硬球的情况比通常的情况要困难,因为在某些情况下可能有4个或更多粒子在同一位置。

这是我的代码:

#include <iostream>
#include <math.h>
#include <vector>
#include <array>
#include <list>
#include <random>
#include <functional>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <chrono>
#include <set>
using namespace std;
    std::minstd_rand gen(std::random_device{}());
    std::uniform_real_distribution<double> unirnd(0, 1);
double PBCtwo(double pos, double L)
    {
    if(pos > L / 2.0)
        return pos-L;
    else if (pos < -L /2.0)
        return L + pos;
    else
        return pos;
    }
// main function
int main()
{   long c = 0;
    int N=4000; 
    double rho, v0, tr,xr,l0, eta,dt, x[N],y[N],L=pow(N / rho , 0.5),l0_two = l0 * l0;
                rho = 2;
                v0 =300;eta = 1;dt = 0.0001;l0 = 1; c_prod = 500;c_display = 100;tr = -0.4;        
    // write initial configuration to the file
    ofstream configFile;
    configFile.open ("Initial Configuration.txt");
    configFile << to_string(N) << "n";
    configFile << to_string(L) << "n";
    for (int i = 0; i < N; i++)
    {   x[i] = unirnd(gen) * L;
        y[i] = unirnd(gen) * L;
        configFile << to_string(x[i]) << "t" << to_string(y[i]) <<   "n";
    }
    configFile.close();
    while (c < c_prod)
        {
        double dx[N], dy[N];
        c++;
        for(int i = 0; i < N; i++)
           {
            dx[i] = 0;
            dy[i] = 0;
            double S_try = 0.0, S_trx = 0.0;
            for(int j = 0; j < N; j++)
              {
                if (j==i) continue;
                   double delta_x = x[i]-x[j],  
                          delta_y = y[i]-y[j];
                       double r_x_ij = PBCtwo(delta_x,L),
                              r_y_ij = PBCtwo(delta_y,L),
                              r_ij_square = r_x_ij * r_x_ij + r_y_ij * r_y_ij;
                       if (r_ij_square > l0_two)
                          { 
                          double r_ij = sqrt(r_ij_square);
                          r_x_ij/= r_ij; 
                          r_y_ij/= r_ij;
                          double S_tr = 1 /r_ij_square;
                          S_trx += r_x_ij * S_tr;
                          S_try += r_y_ij * S_tr;
                          }
                }
            dx[i] += tr * S_trx;  
            dy[i] +=  tr * S_try;
            }
        for(int i = 0; i < N; i++)
            {
            x[i]+=  dt * dx[i];
            y[i]+=  dt * dy[i];
            if (x[i] > L){
              x[i]-= L;} 
            else if( x[i] < 0) {
            x[i]+= L;}
            if (y[i] > L){
             y[i]-= L;} 
            else if( y[i] < 0){
                y[i]+= L;}
            }
        }
    ofstream finalConfigFile;
    finalConfigFile.open ("Final Configuration.txt");
    finalConfigFile << to_string(N) << "n";
    finalConfigFile << to_string(L) << "n";
    for (int i = 0; i < N; i++)
        {
        finalConfigFile << to_string(x[i]) << "t" << to_string(y[i]) <<"n";   
        }
    finalConfigFile.close();
    return 0;
}

我假设您想模拟具有吸引人和硬核排斥部分的粒子气体。

许多粒子系统的分子动力学模拟是一个发达的科学领域。这种模拟的困难部分是最初以不重叠的方式采样粒子。这是在Metropolis等人的古典论文中解决的。但是无论如何,您还是忽略了这部分。也有许多教科书和论文解释,如何用硬球进行分子动力学模拟,例如This或This或1959年的论文,它们首先使用了分子动力学。

如果您的项目要显示出像Windows屏幕保护程序一样碰撞的不错的球体,则只需使您的硬核潜力更柔软,请降低您的时间步骤,并且它将像魅力一样工作。如果您针对科学严谨,请阅读这些论文,不要忘记控制节能。例如,可以通过更换

来添加软排斥。
double S_tr = 1 /r_ij_square;

double S_tr = 1.0 / r_ij_square - 1.0 / (r_ij_square * r_ij_square);

代码格式,结构和可变命名有很多不足之处。我建议尝试使用Clang-Format工具。结构上,周期性边界条件有很多重复。

凭借排斥潜力,您可能会获得经历相变的系统,这是一个令人兴奋的研究对象。祝你好运!

更新:

请注意,以下代码被错误:

double rho, v0, tr, xr, l0, eta, dt, x[N], y[N];
double L = pow(N / rho , 0.5), l0_two = l0 * l0;
// ...
l0 = 1;

您首先计算l0_two = l0 * l0(切勿使用l启动变量名称,将其与1,sqrt(x)相混淆,应该优先使用POW(x,0.5)),然后分配L0 = 1。因此,l0_two是未定义的,可能分配给0。这可能会导致您的问题的一部分。

修复该错误后,您可以使用两个解决方案。如果颗粒足够接近,则第一个是上面描述的软排斥潜力。第二个是在上述引用的基于事件的MD中与论文完全一样。

如果每个粒子之间的距离都小于半径的总和(它们在太空中重叠),则考虑每个粒子都有半径,模拟该硬球的最常见方法是。将他们的中心与(虚拟)弹簧联系起来,将它们带走。

排斥力的公式类似于f = -k*(l-l_0),其中k是修改接触硬度的经验常数,l_0是两个粒子的半径和l是实际的两个中心之间的距离。仅当两个粒子重叠时,才考虑这项力量!

要这样做,如果粒子重叠,则必须在每时每刻对粒子的每一对夫妻进行测试。如果是这样,请计算弹簧的力并考虑到它。