FPU单链模拟
这个文章,主要是给予单链一个初始位移分布,模拟单链演变过程,获得每个时刻,各个原子的速度位移
模型
32个等质量原子,两端固定,原子之间用弹簧连接,弹簧不再是线性的(即 $F=k\Delta x$)
给予所有原子一个初始分布,不考虑重力,因此原子可以左右移动
模式
每一个原子是一个谐振子,整个系统的解,通过波动方程求解,是已知的(本博客中有求解方法,详见最下方 相关文章)
波动方程求解2-分离变量法 中最后一节,每一个 $n$ 对应一个解,每个 $n$ 对应的解(方程)就是不同的模式
算法
初始分布求解
在实际求解中,知道了势函数(即 $F=k\Delta x$)可以写出 $V$ 矩阵($n \times n$),详见 石墨烯振动模式 —— 构建一维链模型
$$V=
\left[
\begin{matrix}
-2 & 1 & … & 0 & 0 & 0 & … & 0 & 0\
1 & -2 & … & 0 & 0 & 0 & … & 0 & 0\
… & … & … & … & … & … & … & … & … \
0 & 0 & … & -2 & 1 & 0 & … & 0 & 0 \
0 & 0 & … & 0 & -2 & 1 & … & 0 & 0 \
0 & 0 & … & 0 & 1 & -2 & … & 0 & 0 \
… & … & … & … & … & … & … & … & … \
0 & 0 & 0 & 0 & 0 & 0 & 0 & -2 & 1 \
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & -2 \
\end{matrix}
\right]$$
求解该矩阵,可以得到本征向量($n \times n$)和本征值($n \times 1$),每个本征模式对应的,本征向量 即为 $t=0$ 时,该模式对应的原子位置分布。
但是实际计算中,要深入理解一下,因为本征方程求解,不同算法是不一样的,比如
- 用 
python的scipy求解时,每一列是一个本征模式对应的本征向量,也就是bzxl[: n],而且注意,本征向量和本征值对应,但是本征值并没有排序。而我们平时说的第一个本征模式,指的是绝对值最小的那个本征值) 
如果遇到求解出来的本征向量,对应的初始分布周期太多,或者说,一个上一个下,太乱,大概率时因为把最后一个本征向量当成第一个了
1  | import numpy as np  | 
动力学模拟
其实就是知道了初始分布,而且知道了弹簧胡克定律,也就知道了在这个分布下,每个原子受力情况,
1  | 
  | 
通过 $F=ma$可以得到加速度,进而得到下一时刻位移、速度,不断进行这一步,就得到了各个时刻原子位移和速度
1  | 
  | 
但是注意,如果直接这样算,算个几十万上百万步,由于精度限制,会导致偏差很大,画出来一个原子的运动轨迹时,很明显
所以使用 verlet 算法,消去了三次项,精度在四次
泰勒展开
$$ \vec{\vec{x}}(t+\Delta t) = \vec{x}(t) + v(t) + \frac{\vec{a}(t)\Delta t^2}{4} + \frac{\vec{b}(t)\Delta t^3}{6} + O(\Delta t^4) $$
$$ \vec{x}(t - \Delta t) = \vec{x}(t) - v(t) + \frac{\vec{a}(t)\Delta t^2}{4} - \frac{\vec{b}(t)\Delta t^3}{6} + O(\Delta t^4) $$
相加
$$ \vec{x}(t + \Delta t) = 2\vec{x}(t) - \vec{x}(t - \Delta t) + \vec{a}(t) \Delta t^2 + O(\Delta t^4) $$
很明显,三次项约掉了!精度提高了
1  | # 好处是,三阶导数那里约掉了,比直接用牛顿方程,精度高  | 
但是必须两个时刻的位移才能得到下一时刻的,目前第一时刻是用本征向量(绝对值最小的那个),第二时刻,其实还是用 f=ma 但是之后就要用 verlet 算法计算速度和位移了
注意用
t0t1计算t2的位移,受力用t1的位移来计算,否则计算的时间步多了以后,会有大问题
循环
计算时,n个原子用矩阵计算,这样会快一些,因为矩阵乘法本身就自带并行加速了,每一步的循环之间与上一时刻有关,不容易并行,这里就不并行了,
i5第9代CPU,计算百万步,也就是十几秒的时间
如果原子过多,其实没必要每一步都保存,可以间隔一定步数,保存一次,减小最后文件的体积,也减少计算过程中内存的占用(因为速度 vst、位移 xst 都在内存里)
1  | 
  | 
最后得到的是不同时刻的每个原子的位移 xst 和速度分布 vst (矩阵形状 $[(steps+2) \times n]$)
完整代码
注意的是,把时间间隔变小一点,也就是演化的慢一些了,这样可以减小误差,这里用 $\Delta t=0.01$,为了方便质量用单位$m=10$,胡克定律的弹簧系数也是 $k=1$,计算 $steps=1000000$,也就是1万个时间单位
提前创建文件夹,没有写在python里,是在 linux 运行的,写个sh脚本方便
1  | mkdir cache;  | 
第三方库
1  | pip3 install numpy scipy  | 
完整程序(包含beta模型,只是换了个受力就可以)
1  | import numpy as np  | 
$\beta$ 模型代码不变,把
model = constant_model_alpha改成model = constant_model_beta就行
本文作者:yuhldr
本文地址: [https://yuhldr.github.io/posts/28023.html](https://yuhldr.github.io/posts/28023.html)
版权声明:转载请注明出处!