我想模拟盒子内的粒子运动。当粒子撞击盒子中 4 个墙壁之一时,我希望它们反弹回来。弹性碰撞【碰撞后速度变化图】[1]
编辑
添加了更多代码。更改了 (x,y,z) 限制的测试。我知道当粒子撞击墙壁时,平行于墙壁的速度将保持不变,但垂直于墙壁的速度将变为 -v_perpendillary_vel_before
完整代码
fig0 = plt.figure()
fig1 = plt.figure()
n = 1000 # time steps
M = 1000. #[kg]
N = 1000 #10**5
a = 0
最佳答案
我无法重现运行,因为您还没有发布完整的代码;我是通过目视检查来做到这一点的。
除此之外,您还没有定义变量k、T、m,因此我不知道速度的大小。上限是否足够高以使粒子完全跳过碰撞?如果 v*dt > tol*2,则完全可以错过碰撞。当我编写这样的代码时,我确保 tol 受到最大变化的限制。
除此之外,您的位置更新是正确的。
当您使用单个粒子运行此程序时会发生什么?你能让它从三堵墙上弹开吗?当你手工编码两个粒子沿单一维度相互直冲时会发生什么?我想您在加载 10000 个粒子之前测试了这些基本功能。
我不确定您的代码中的L是什么;我唯一合理的想法是它是盒子尺寸的上限,我在你的绘图上将其读为 1.2^10-6。
我发现的最大问题是您的唯一碰撞检查是针对盒子的 x+ 侧。你还没有检查任何东西的其他维度或下限(0?),并且没有一个粒子与另一个粒子的比较。因此,您将得到的唯一变化是让大约一半的粒子撞击右侧墙壁 (x+) 并反转方向。除此之外,一切都将永远漂移,x 值不断减小。
<小时/>处理弹跳
首先,使速度和位置表达式彼此同步:每个表达式都应该是一个三元组(元组或列表),以便您可以将它们一起索引。目前,您将它们作为粒子列表的第二个索引(好主意),但在其他地方有三个单独的变量(坏主意)。相反,使 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 个粒子,以表明您可以对任意数量的粒子执行此操作。
一旦你有了这个,你就可以担心粒子碰撞了。 当你达到这一点时,好好尝试一下;如果您遇到困难,请发布新问题。
关于python - 粒子与盒子内壁的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40186702/