一篇长文里嵌着一块可操作的演示:随机行走的轨迹和三条斜率不同的均方位移直线

左边是文章,右边是它验证的那条直线:斜率 = 4D

布朗运动笔记:
从花粉抖动到 ⟨r²⟩ = 4Dt

1827 年,植物学家罗伯特·布朗在显微镜下观察悬在水里的花粉颗粒,看到它们永不停歇地抖动。他换了研磨过的无机矿物粉末——抖动照旧。既然死的粉末也这样动,这就不是生命现象;可它到底是什么,此后七十八年没人说得清。

1905 年,爱因斯坦给出了答案。这个答案的漂亮之处在于它的形式:单个颗粒下一步往哪走,原则上无从预测;但位移平方的平均,与时间严格成正比。同年他还给出了这个比例系数与温度、黏度、颗粒大小的关系。

三年后,佩兰用显微镜和秒表把这两个式子做成了对阿伏伽德罗常数的测量,原子不再只是解释工具,它有了数。这篇文章要做的是把这条链条搬到浏览器里:先讲清原理,再复盘把一个统计物理公式跑成实时演示时,真正会踩到的坑。

↓ 不想看推导,直接跳到可操作的演示

全篇的一条主线

⟨r²⟩ = 4 D t  ·  D = kBT / (6 π η a)

单个颗粒的轨迹不可预测,但它位移平方的平均值是确定的。决定这个平均值的,只有温度 T、黏度 η、粒径 a——三个宏观可测的量。把 ⟨r²⟩ 对 t 作图的斜率量出来,就能反推微观常数。

01

原理:一个不可预测的东西,为什么会有确定的公式

先看涨落从哪里来

水分子在常温下以每秒数百米的速度乱飞。一颗微米级的颗粒浸在水里,每秒钟被撞的次数在 1018 次量级(按下式 n·v̄/4 · πa² 估算)。单次撞击的冲量极小,根本推不动比水分子大上亿倍的颗粒——但撞击的数目与力度在每一瞬间都有微小涨落,方向上不再相互抵消的那一点剩余,就是颗粒被推动的原因。

这个数值无法预测:涨落从哪里来、往哪去,都需要知道每一个分子的位置和速度。爱因斯坦的关键一步,是放弃追踪轨迹,改看概率——颗粒的数密度满足扩散方程 ∂n/∂t = D∇²n,而扩散方程的解自带一个结论:位移平方的平均随时间线性增长:

⟨x²⟩ = 2 D t 一维
⟨r²⟩ = 4 D t 二维
⟨r²⟩ = 6 D t 三维

注意它和匀速运动的区别:匀速直线运动里 ⟨r²⟩ ∝ t²(走两倍时间,位移是两倍,平方是四倍)。⟨r²⟩ ∝ t 是随机行走的指纹——路线越绕,走得越慢。看到斜率是一条直线,就知道这是一个扩散过程,而不是被谁推着走。

再把微观接上

到这里 D 还是个待定系数。斯托克斯–爱因斯坦公式把它和分子的热运动接了起来:颗粒半径 a 在黏度 η 的液体里受到的黏滞阻力是 6πηa(斯托克斯定律),把热运动的能量尺度 kBT 和它组合,就得到

D = kBT / (6 π η a)   ⟹   D ∝ T / (η a)

温度越高、液体越稀、颗粒越小,扩散越快。这条式子是双向的:测出 ⟨r²⟩–t 的斜率得到 D,再由 D、T、η、a 反解出 kB,除以气体常数就得到阿伏伽德罗常数。佩兰 1908 年起做成了这件事,1926 年因此获诺贝尔物理学奖。

这就是这条链条最反直觉的地方:微观的随机性一点都没有被消除,它只是被平均成了宏观的确定规律。随机是本体,线性的 ⟨r²⟩–t 是统计的结果。你以为你在看公式,其实你在看大数定律。

02

亲手验证:这条式子能当场跑给你看

嵌在文章里的演示

下面这个模拟器就在这篇文章里运行。微粒按过阻尼朗之万方程行走,右侧实时统计均方位移并作 ⟨r²⟩–t 图;左侧滑块是温度 T、黏度 η、粒径 a。可以直接动手,不用跳出去。

内嵌演示 · 显示异常或想看完整的说明与公式?在新窗口打开完整版模拟器

上手三步

看:蓝线是 3000 个统计样本的平均,灰线是画面里那十几个微粒的平均。灰线一直在抖,不是模拟错了,是样本少。
拖:把温度从 1.0 拉到 3.0,⟨r²⟩ 的斜率和「实测 D」一起变大;再把黏度、粒径拉大,看它们反向走。
改:关掉「周期边界」,等一会儿,看实测曲线怎样慢慢滑到理论线下方。

一句必须说清楚的话

完整版页面里写着「实测 D 会紧随理论 D」,严格讲,这里的「实测」并不是独立测出了斯托克斯–爱因斯坦公式——微粒每步的位移本身就是用理论 D 生成的(Δx = √(2DΔt)·ξ),两者当然接近。它真正验证的是这三件事:积分格式没错、统计样本已收敛、⟨r²⟩ 确实与 t 成正比。
想让演示变成一次真正的「测量」,得反过来做:让微粒的随机力来自一个独立的微观模型,再把拟合出的 D 拿去和 kBT/(6πηa) 比。这是个诚实的边界,也是这个演示的边界。

03

实现踩坑:10 个必须算过一遍才知道的取舍

模型层 · 4 个

坑 01 · 惯性项可以删,但要先算一遍弛豫时间

严格写法是朗之万方程 m·dv/dt = −γv + ξ(t),其中 γ = 6πηa。但速度被黏滞"洗掉"的时间尺度 τ = m/γ 在微米级、水介质下只有 10⁻⁸ 秒量级,远小于任何可观测的时间尺度。所以可以直接用过阻尼形式,把惯性整项拿掉:Δx = √(2DΔt)·ξ。这不是顺手偷懒,是算过之后才敢删。而黏滞阻力对扩散的抑制也没有消失——它全部包在 D = kBT/(6πηa) 里了。

坑 02 · 分子不能真的去"撞"出布朗运动

画面里 1600 个小点在飞、在弹、在撞微粒,看上去布朗运动就是被它们撞出来的。但如果真让微粒的位移只由这些硬球碰撞驱动,曲线会立刻坏掉:真实碰撞频率极高、单次冲量极小,而在离散步长里只放几千个"分子",微粒会在两次碰撞之间匀速直线飞很远,于是 ⟨r²⟩ 变成 ∝ t²,还强烈依赖你把分子数量设成多少——那已经不是扩散了。
所以正确的分工是:微粒的净随机力由爱因斯坦形式承担,分子只负责把"分子在撞"这个微观图像画出来。把"看得见的机制"和"算得出的机制"分开,是这个页面里最关键的一次取舍。

坑 03 · 步长的系数:漏掉一个 2,结果整体偏一半

一维扩散解给出 ⟨x²⟩ = 2Dt,所以每个时间步的高斯位移必须是 Δx = √(2DΔt)·ξ(ξ 为标准正态随机数)。很容易写成 √(DΔt)·ξ,理由是"反正就是这个量级"——那样每步方差只有一半,⟨r²⟩ 整体差 2 倍,拟合出的 D 恰好是理论值的一半。这个 2 不是可选的常数,它是扩散方程解的一部分。
好消息是:系数写对之后,⟨r²⟩ = 4Dt 对任意步长 Δt 都精确成立,不需要把 Δt 取到无穷小。这正是爱因斯坦形式相对硬球动力学的最大好处——也是坑 02 之所以能成立的前提。

坑 04 · 不能看平均位移,它恒等于 0

各向同性、又无外力,⟨Δr⟩ = 0。想用"平均位移"描述布朗运动,得到的结果永远是零。特征量只能是位移平方的平均 ⟨r²⟩。这一步看着像定义问题,实际上它决定了后面所有事:拟合的是 ⟨r²⟩ 对 t 的斜率,那么噪信比、样本量、拟合区间的取舍,全都围绕这个量展开。

数值与绘制层 · 6 个

坑 05 · 画面里 10 个微粒 ≠ 统计上的 3000 个样本

最初的版本直接拿画面里十几个微粒算 ⟨r²⟩,曲线抖得像噪声。原因很简单:均方位移是统计量,样本越少,相对涨落越大(大致按 1/√N 收敛)。画 10 个,是为了看清轨迹;要得到能读数的 ⟨r²⟩,得让 3000 个"幕后"样本按同样参数同步积分。
所以页面上有两条线:蓝线是 3000 个样本的平均(贴合理论线),灰线是画面微粒的平均(明显抖动)。两条线的距离就是样本量的差距——这不是画错,是刻意留给你看的。

坑 06 · 拟合 D 要跳过起步段

把 ⟨r²⟩–t 的斜率除以 4 就得到 D。代码用的是过原点最小二乘 k = Σ(tᵢvᵢ) / Σtᵢ²,再取 D = k/4;并且只用后 60% 的数据点参与拟合:起步阶段 ⟨r²⟩ 本身很小,一点统计涨落就构成很大的相对偏差,把这段排除后再拟合,读数明显更稳。这是经验做法,不是推导出来的最优解——但它足够好用。

坑 07 · 周期边界必须把轨迹画断

打开周期边界后,微粒从右边出去会从左边回来。坐标上它只是"跳"了一下;如果照常连线,画面上就会出现一条横贯整个画布的长直线,一串这样的线会把轨迹糊成网格。所以绘制时要做跳变检测:相邻采样点的距离超过画布尺寸的 40%,就抬笔另起一段(moveTo 而非 lineTo)。物理上没错的东西,画出来可能完全不是那个意思。

坑 08 · 反射边界下 ⟨r²⟩ 会饱和,那不是 bug

把周期边界关掉换成器壁反射,过一会儿实测曲线就会明显地滑到理论线下方。这不是数值错误,是物理:容器有限,微粒被限制在里面,位移不可能无限制地长大,⟨r²⟩ 自然要偏离 4Dt。想让 ⟨r²⟩ 长期严格线性,就必须排除器壁的影响——所有扩散实验都得处理同一个问题,只不过它们用的是更大的容器和更短的时间窗。

坑 09 · canvas 第一帧取到的宽度是 0

页面刚加载时,脚本可能跑在布局完成之前,getBoundingClientRect() 拿到的是 0,画布尺寸和坐标缩放全部会算错。稳妥做法是:取不到有效尺寸就用 requestAnimationFrame 再试一轮。同时把 devicePixelRatio 算进去(上限取 2,避免高倍屏上白烧算力),用 ctx.setTransform 一次性缩放——否则整块画布在高分屏上是糊的。

坑 10 · 分子数量不影响曲线——这既是特性,也是提醒

把"分子数量"滑块从 200 拉到 4000,⟨r²⟩ 曲线纹丝不动。因为它只决定画面里有多少个点在飞,真正决定曲线的是 D。这个现象值得记住:它说明在这个模型里,分子只是图像,不是机制(见坑 02)。如果哪天你真想让分子参与计算,第一件要重做的事,就是回头检查 ⟨r²⟩ 与 t 还成不成正比。

这条链路真正漂亮的地方,是它把「不可预测」和「严格确定」放进了同一个式子里。单个颗粒下一步往哪走,谁也说不准;一万个颗粒走同样长的时间,位移平方的平均值是钉死的。随机性没有被消除,它只是被平均成了规律。

而工程上的那一半——哪些项可以删、哪些机制只能当图像、什么时候该抬笔断线——是算过之后才知道的,不是写代码时顺手选的。这大概就是"把公式跑起来"和"把公式看懂"之间的差距。

— END —
完整版演示:布朗运动模拟器
公式、数值格式与实现细节均取自演示页源码;文中数量级估算为便于阅读做了取整