Python 使用scipy.integrate将布朗运动纳入粒子轨迹积分

Python 使用scipy.integrate将布朗运动纳入粒子轨迹积分,python,numpy,Python,Numpy,我想在一个简单的线性粒子相互作用模型上加上热涨落。到目前为止(没有布朗运动),一切都是使用scipy.integrate.odeint完成的,并且工作得非常完美。因此,通过使用scipy.integrate方法之一,找到一种包含随机运动的方法是很好的。 问题如下:使用朗之万热浴,我必须更新粒子位置(x)和速度(v),如下所示: x=x+v*dt v=v+(相互作用力*dt+随机作用力*dt)/质量 式中:随机力=sqrt(常数/dt)*随机数 我认为有两个问题: 步长dt在随机力中出现。但我不知

我想在一个简单的线性粒子相互作用模型上加上热涨落。到目前为止(没有布朗运动),一切都是使用scipy.integrate.odeint完成的,并且工作得非常完美。因此,通过使用scipy.integrate方法之一,找到一种包含随机运动的方法是很好的。 问题如下:使用朗之万热浴,我必须更新粒子位置(x)和速度(v),如下所示:

x=x+v*dt

v=v+(相互作用力*dt+随机作用力*dt)/质量

式中:随机力=sqrt(常数/dt)*随机数

我认为有两个问题:

  • 步长dt在随机力中出现。但我不知道当前步长在自适应步长控制运行期间会发生什么变化

  • 步长控制会遇到麻烦,因为只要使用两个不同的随机数来比较不同的步长,就会有相对较大的差异。(我不确定是否使用了两个不同的随机数)


  • 我唯一的想法就是使用固定步长的方法。但我还没找到飞机。有更好的方法解决这个问题吗?

    如果可以访问模型中的绝对时间,可以使用伪随机数生成器为给定时间生成唯一的随机数

    这种依赖于时间的伪随机数生成器可以独立于步长操作,并且每当重复访问时间点时生成相同的值

    如果你没有绝对时间,你可以简单地积分1*dt得到时间

    下面是这种时间相关随机数生成器的一个非常粗略的实现:

    import numpy as np
    import matplotlib.pyplot as plt    
    import struct
    
    # create a gaussian "random number" that is deterministic in the time parameter
    def t_rand(time):
        tmp = struct.pack('f', time)
        int_time = struct.unpack('i', tmp)
        np.random.seed(int_time)
        return np.random.randn()
    
    # demonstrate the behavior of t_rand
    
    t1 = np.linspace(0, 1, 21)
    t2 = np.linspace(0, 1, 41)
    
    plt.subplot(2, 1, 1)
    plt.plot(t1, [t_rand(t) for t in t1])
    plt.plot(t2, [t_rand(t) for t in t2])
    
    plt.subplot(2, 1, 2)
    plt.hist([t_rand(t) for t in np.linspace(0, 10, 10000)], 30)
    
    为此目的操纵全局随机种子可能不明智,但如果问题足够孤立,它将起作用

    上图显示,对于具有不同时间步长的两个序列,相同时间点生成相同的值。下图显示了随机值的柱状图,这表明至少分布的形状似乎没有受到这种对随机种子的粗略操纵的影响


    我不知道我的方法是否真的在积分器中有效。问题2可能仍然是一个问题,但我认为问题1已得到充分解决。这可能不能完全解决问题,但可以让你开始。更专业的解决方案可能是使用随机微分方程求解器,例如。

    类似于
    odeint
    的方法不适用于SDE。可调整大小的时间步方法实际上不适用于布朗运动,因为随着时间步变小,解不会收敛到平滑的状态

    你最好还是用这个。此方法非常简单,您可以自己编写集成例程


    还有更先进的方法:下一个最著名的方法是Milstein方法,该方法对乘法SDE更精确,但对加法SDE(如您的SDE)是等效的。一般来说,使用更复杂的方法对SDE的好处不如对ODE的好处大,因此我想说,使用EM即可。

    您有权访问积分例程中的绝对时间t吗?谢谢您提供了有趣的答案。不幸的是,这并不能解决问题。我试着按照你的建议使用依赖时间的随机数。保存在全局变量中的时间步长dt。即使在这种情况下,我只使用最后一次步长,而不是当前步长,它也应该是可比较的。然而,步长控制仍然会产生许多非常小的步长。因此,它似乎只适用于没有控制的恒定步长。你知道可以关闭步长控制的任何积分器吗?我从未在python中使用过ODE集成,所以很遗憾,我不能推荐任何积分器。您是否考虑过随机积分(答案底部的链接)?我也不是这些方面的专家,但从它们的描述来看,它们似乎是为您的用例设计的。