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

时间:2016-02-16 15:50:32

标签: python numpy

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

x = x + v * dt

v = v +(interaction_force * dt + random_force * dt)/ mass

其中:random_force = sqrt(常量/ dt )* random_number

我认为有两个问题:

  1. 步骤大小dt出现在random_force中。但我不知道当前步长在自适应步长控制运行期间会发生变化。

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

  3. 我唯一的想法是使用固定步长的方法。但我没有发现任何喷气式飞机。任何更好的想法如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

如果您可以访问模型内​​的绝对时间,则可以使用伪随机数生成器,在给定时间内生成唯一的随机数。

这种与时间相关的伪随机数发生器可以独立于步长运行,并且每当重复访问时间点时都会产生相同的值。

如果您无法访问绝对时间,您可以简单地集成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)

为此目的操纵全局随机种子可能不明智,但如果问题足够孤立,它将起作用。

enter image description here

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

我不知道我的方法是否真的适用于集成商。问题2可能仍然是一个问题,但我认为问题1得到了充分解决。这可能无法完全解决问题,但它可能会让你开始。更专业的解决方案可以是使用stochastich微分方程求解器,例如PyS³DE

答案 1 :(得分:0)

odeint之类的方法不适合SDE。可调整大小的时间步长方法并不适用于布朗运动,因为随着时间步长变小,解决方案无法收敛到平滑的状态。

您最好只使用Euler Maruyama method。此方法非常简单,您可以自己编写集成例程。

还有更先进的方法:下一个最着名的方法是Milstein方法,它对于乘法SDE可以更准确,但对于加性SDE(例如你的)来说是等价的。一般来说,使用更复杂的方法获得的收益对于SDE而言并不像ODE那么大,所以我想说只使用EM。