我想模拟盒子内的粒子运动。当粒子撞到盒子里的4个墙壁中的一个时,我希望它们能够反弹回来。弹性碰撞[碰撞后速度变化的绘制] [1]
修改
添加了更多代码。如果测试(x,y,z)限制则更改。我知道当粒子撞到墙壁时,与墙壁平行的速度将保持不变,但垂直于墙壁的速度将变为-v_perpendicular_vel_before
完整代码
fig0 = plt.figure()
fig1 = plt.figure()
n = 1000 # time steps
M = 1000. #[kg]
N = 1000 #10**5
a = 0
答案 0 :(得分:2)
由于你还没有发布完整的代码,我无法重现这次运行。我是从视觉检查中做到这一点的。
除此之外,你还没有定义变量 k,T,m ,所以我不知道速度的大小。上限是否足够高,粒子完全跳过碰撞?如果v * dt可以> tol * 2,你可以完全错过碰撞。当我编写这样的代码时,我确保 tol 受到最大更改的限制。
除此之外,您的位置更新是正确的。
使用单个粒子运行时会发生什么?你能让它从三面墙上反弹吗?当你手工编码两个沿着一个维度直接相互对齐的粒子时会发生什么?我想你在装载10000个粒子之前测试了这些基本功能。
我不确定您的代码中包含 L ;我唯一理性的想法是它是盒子尺寸的上限,我在你的情节中读到的是1.2 ^ 10-6。
我看到的最大问题是您的仅冲突检查是针对该框的x +侧。你还没有检查其他尺寸或下限(0?)的任何东西,并且没有一个粒子与另一个粒子的比较。因此,您获得的唯一变化是大约一半的粒子撞击右侧墙壁(x +)和反方向。除此之外,一切都将永远漂移,x值不断下降。
处理一个BOUNCE
首先,让你的速度和位置表达式彼此同步:每个表达式应该是三元组(元组或列表),因此你可以将它们一起索引。您目前将它们作为粒子列表的第二个索引(好主意),但在其他地方有三个独立的变量(糟糕的想法)。相反,将newVel作为一个列表,这样您就可以简单地遍历粒子并更新:
for dim in range(3):
if r[i, dim] < tol or # hit the lower wall
r[i, dim] > b - tol: # hit the upper wall
v[i, dim] = -v[i, dim]
另外,请恰当地更新位置;无需涉及本地临时变量:
for dim in range(3):
r[i, dim] += v[i, dim] * dt
编写一些服务功能
编写一些常用功能通常会有所帮助,只是为了在您编写主代码时将它们排除在外。目前,当你应该一次只担心一种技术时,你会处理很多细节。例如,由于您将要处理粒子碰撞,因此您需要进行距离计算。不要将它放在活动代码的中间;只写一个函数来做到这一点。例如:
def dist(a, b): # a, b are positions: triples of coordinates
return math.sqrt(sum([(a[dim] - b[dim])**2 for dim in range(3)]))
我没有评论如何实施粒子碰撞,因为你还没有表现出解决问题的任何努力,而你还没有到达攻击该扩展的程度。首先,让这个部分工作:一个粒子弹跳,然后两个粒子弹跳,然后可能有4个粒子,表明你可以为任意数量的粒子做。
一旦有了这个,就可以担心粒子碰撞。 当到达那一点时,做出一个好的尝试;如果你遇到困难,请发一个新问题。