【发布时间】:2021-07-08 08:52:18
【问题描述】:
背景 我正在用 Python 编写一个简单的 N 体模拟代码,核心物理求解器,例如在 Cython 中实现的加速度和位置集成。代码使用了蛙跳法来整合位置。
条件
- 质量:10,100 用于 2 个主体; 1 表示所有机构,机构数量 > 2。
- 位置:随机生成
- 速度:随机生成
- 时间步长:1e-3
错误
- 如果物体数量 > 2:物体相互排斥而不是相互吸引。
- 对于物体数量 = 2:它们不相互绕行,而是沿直线运动。
- 一般错误(不考虑物体数量):排斥力
预期行为
- 两个物体必须相互绕行
- 这些力量必须具有吸引力
解决问题的努力
- 加速的负号
- 将加速度乘以 -1
- 添加新的临时表达式
代码 加速函数(Cython):
def acceleration(np.ndarray[np.float64_t, ndim=2] pos, np.ndarray[np.float64_t, ndim=1] mass):
cdef int N = pos.shape[0] # Number of bodies
# Memoryview for acceleration
cdef np.float64_t [:,:] acc = np.zeros((N,3),dtype="float64")
cdef double soft = 1e-4 # Softening length
cdef G = 6.673e-11 # Gravitational constant
# Pairwise separations
cdef double dx
cdef double dy
cdef double dz
# Total separation vectors
cdef double r
cdef double tmp
# Mass
cdef mj
# Acceleration calculation loop
for i in range(N):
for j in range(N):
# Remove gravitational self forces
if i==j:
continue
# Calculate pairwise separation vectors
dx = pos[j,0] - pos[i,0]
dy = pos[j,1] - pos[i,1]
dz = pos[j,2] - pos[i,2]
# Vector magnitude of separation vector
r = dx**2 + dy**2 + dz**2
r = np.sqrt(r)
# Mass
mj = mass[j]
tmp = G * mj * r**3
# Calculate accelerations
acc[i,0] += tmp * dx
acc[i,1] += tmp * dy
acc[i,2] += tmp * dz
return np.asarray(acc)
位置整合:
def leapfrog(np.ndarray[np.float64_t, ndim=2] pos, np.ndarray[np.float64_t, ndim=2] vel, np.ndarray[np.float64_t, ndim=2] acc, np.ndarray[np.float64_t, ndim=1] mass):
cdef double dt = 1e-3 # Timestep
# The Leapfrog integration method
# v(t+1/2) = v(t) + a(t) x dt/2
# x(t+1) = x(t) + v(t+1/2) x dt
# a(t+1) = (G * m/((dx^2 + dy^2 + dz^2)^(3/2))) * dx * x
# v(t+1) = v(t+1/2) + a(t+1) x dt/2
vel += acc * dt/2
pos += vel * dt
acc = acceleration(pos, mass)
vel += acc * dt/2
return pos, acc
主模拟循环(Python): 对于 _ 在范围内(Nt): # 计算位置并获得新的加速度值 pos, acc = jumpfrog(pos, vel, acc, m)
绘图(Python):
plt.scatter(pos_arr[:,0], pos_arr[:,1])
请帮我解决这个问题。
有关该错误的更多信息,请参阅图片:
两个物体相互排斥+直线运动而不是轨道运动
错误的 3D 视图。
编辑 1:速度 = 0 这是速度 = 0 (vel = np.zeros((N,3)) 的结果,其中 N=2。 红点是位置数组的第一个元素,绿点是最后一个点。
编辑 2:tmp * dx/2: 这是通过将分离向量除以 r 获得的结果。 更新代码:
acc[i,0] += tmp * dx/r
acc[i,1] += tmp * dy/r
acc[i,2] += tmp * dz/r
编辑 3:速度 = 1e-6 这就是设置两个速度 = 1e-6 的结果。它们保持静止。
【问题讨论】:
-
您好,欢迎来到 Stack Overflow!我在这里删除了几个cmets,因为(A)它们的措辞非常粗鲁,并且(B)它们包含一些误解。 No one is expected to leave a comment when they vote on a post here,无论他们赞成还是反对。投票不是粗鲁的,也不是人身攻击;这仅仅是内容的评级方式。请将鼠标指针悬停在投票按钮上,以查看每种投票的含义。此外,所有投票都是匿名的,所以you've no way of knowing who downvoted.
-
我的第一个猜测是,您将初始速度设置得足够高,以至于在您看到力的任何影响之前,粒子最终会很好地分离。这个问题缺少的是minimal reproducible example - 即有人应该可以在他们的 PC 上重现您的图表。离你不远,但我们绝对不知道起始条件
-
@DavidW 感谢您的回复!我会尝试添加一个 MWE。初始条件很简单:我用np.random.randn生成初始条件:
pos = np.random.randn(N,3), vel = np.random.randn(N,3). -
试试
vel = np.zeros(N,3)- 他们应该直接穿过对方。但这可能是检查它们是否吸引的最简单方法。 -
建议更正:
acc[i,0] += tmp * dx变为acc[i,0] += tmp * dx/r(其他 2 个向量相同)