我想在一个体积内随机分布 N 粒子,使它们满足Plummer电位分布。我试图从Hut的“计算科学的艺术”开始工作,它有一个描述,但我似乎无法实现它。我与Hut的不同之处在于我需要为每个粒子提供3个速度分量。以下是我到目前为止所做的事情:
f=0
g=0.1
if g >f*f*(1-f*f)**3.5:
f=np.random.uniform(0,1,N)
g=np.random.uniform(0,0.1,N)
vel_x= f*np.sqrt(2)*(1+x*x)**(-0.25)
vel_y= f*np.sqrt(2)*(1+y*y)**(-0.25)
vel_z= f*np.sqrt(2)*(1+z*z)**(-0.25)
vel = np.zeros((N,3))
vel[:,0]=vel_x
vel[:,1]=vel_y
vel[:,2]=vel_z
但是,当我运行Hut描述的能量检查时,N个体单位的动能约为0.147,此代码失败。关于我出错的地方的任何建议将不胜感激
答案 0 :(得分:1)
你可能在Hut的书中误读了Ruby代码,因为它也生成了三维速度向量:
x = 0.0
y = 0.1
while y > x*x*(1.0-x*x)**3.5
x = frand(0,1)
y = frand(0,0.1)
end
velocity = x * sqrt(2.0) * ( 1.0 + radius*radius)**(-0.25)
theta = acos(frand(-1, 1))
phi = frand(0, 2*PI)
b.vel[0] = velocity * sin( theta ) * cos( phi )
b.vel[1] = velocity * sin( theta ) * sin( phi )
b.vel[2] = velocity * cos( theta )
第一部分生成| v |通过速度分布的拒绝采样。第二部分在空间中生成随机方向(在极坐标中),代码的最后部分从极坐标转换为笛卡尔坐标。
您的代码完全不同。您应该在Python中修改上面显示的代码片段,例如:
f = 0.0
g = 0.1
while g > f*f*(1.0-f*f)**3.5:
f = np.random.uniform(0,1)
g = np.random.uniform(0,0.1)
velocity = f * np.sqrt(2.0) * (1.0 + radius*radius)**(-0.25)
theta = np.arccos(np.random.uniform(-1, 1))
phi = np.random.uniform(0, 2*np.pi)
vel[n,0] = velocity * np.sin(theta) * np.cos(phi)
vel[n,1] = velocity * np.sin(theta) * np.sin(phi)
vel[n,2] = velocity * np.cos(theta)
代码可能是矢量化的,但实际上它没有多大意义,因为拒绝采样不是可矢量的(它可能并且很可能每个样本需要不同的迭代次数)。