如何在python中创建“台球”反射边界条件?

2024-04-29 09:05:06 发布

您现在位置:Python中文网/ 问答频道 /正文

根据埃尔文·施罗德(Erwin Schrodinger)的说法(生命是什么?)扩散完全可以用粒子的随机运动来解释。我想通过创建一个程序来测试这一点,这个程序创建了一个封闭容器中“气体分子”扩散的时间步长可视化。初始条件将有两个分区,一个低浓度,一个高浓度。t0之后,隔板被移除,气体被允许扩散。我想使用的唯一机制是向每个分子添加位移随机向量。初始条件应该是这样的。在

enter image description here

我无法解决的问题之一是,当分子撞击到边界表面时,如何创建一个简单的台球式反射。我假设简单的对称反射(角度进入=角度出边界)。我还没有开始编写代码,因为我不知道如何处理这一部分,而我知道如何处理其余部分。我知道这更像是一个数学问题,但是如何在python中创建这些边界条件呢?理想情况下,我想自己编写这个功能,这样我就可以理解它,而不是使用一个预先构建的包来实现这一点。这就是我要找的,对于任何给定的分子。在

最后,我真正需要的是:给定初始位置(x1,y2),矢量大小v,角度θ,以及盒的大小和位置,分子的最终静止位置是什么(x2,y2)。在

enter image description here


Tags: 程序可视化时间粒子分子容器边界角度
3条回答

不需要计算反射角,只需将问题分解为两个:一个用于x,另一个用于y。在这两种情况下,都需要粒子在超出边界时“返回”。在

我之前做过一个练习,研究流体中的粒子密度。最简单的方法是考虑两个方向上的(0,1)边界。下面的代码可以做到这一点(提示:正确使用abs将创建相当于反射的效果):

x0 = [.1, .9]
delta = [-0.2, 0.3]
x1 = [(1-abs(abs(xi + di)-1)) for xi, di in zip(x0, delta)]
print(x1)
# 0.1, 0.8
#or using numpy:
x1 = 1-np.abs(np.abs(np.asarray(x0) + np.asarray(delta))-1)
print(x1)
>> [0.09999999999999998, 0.8]
   array([0.1, 0.8])

我从你的问题中假设你忽略了粒子-粒子碰撞和粒子-粒子“非叠加”

所以有几件事要记住:

  1. 你需要一个摩擦分量,否则粒子将永远移动(能量守恒)。在这种情况下,摩擦力是速度的函数,在弹跳时也会发生摩擦。

  2. 如果它只是一个粒子,可以通过定义边界框来计算它,例如x在0和5之间,y在0和3之间。然后,您可以通过插入x=5值,然后在直线方程中求解y来计算墙的截距。

对于一个粒子,你不必以t_0为增量来参数化,你可以计算截距,然后把它放大。对于多重,你必须计算分子间的扩散和碰撞力…这是一个更难的问题,应该用参数化的方法来完成。在

你必须计算碰撞,也就是说,当两个分子的中心相距2*半径时,再做一个碰撞,即conserves momentum。在

下面是一个简单的实现。我只改变每10步的运动矢量,这样就可以直观地检查边界反射。当运动向量更新时,粒子闪烁红色。在

技巧如ħere所述是“展开”边界框。相反,我们让粒子自由移动,然后将空间折叠到边界框中。在

import numpy as np
import pylab
from matplotlib.animation import FuncAnimation

xy = np.random.uniform(-1, 1, (2, 200))
xy[0, :160] = np.abs(xy[0, :160])
xy[0, 160:] = -np.abs(xy[0, 160:])
xy += 1

f, a = pylab.subplots()
pxy, = pylab.plot(*xy, 'o')

def init():
    a.set_xlim(0, 2)
    a.set_ylim(0, 2)
    return pxy,

def update(frame):
    global inc, xy
    if frame % 1 < 0.01:
        inc = np.random.normal(0, 0.01, xy.shape)
        pxy.set_markerfacecolor('red')
    elif frame % 1 < 0.11:
        pxy.set_markerfacecolor('blue')        
    xy += inc
    fxy = np.abs((xy+2)%4-2)
    pxy.set_data(*fxy)
    return pxy,

anim = FuncAnimation(f, update, frames=np.arange(1200) / 10,
                     init_func=init, blit=True)

pylab.show()

相关问题 更多 >