想象一下:你把一个弹珠从桌子上推下去——它会怎么运动?如果同时扔两个弹珠,它们会互相碰撞吗?如果弹珠之间用弹簧连着呢?
Dynamics 就是一个在电脑上做这些"弹珠实验"的程序。你只需要告诉电脑:
然后电脑就会帮你算出每个小球每一瞬间的位置和速度,最后画出一张漂亮的轨迹图!
从 python.org 下载安装包, 安装时一定记得勾选 "Add Python to PATH"。
终端pip install numpy pyyaml tqdm matplotlib
如果下载慢,试试国内镜像:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ...
把整个项目文件夹放到电脑上。打开终端,cd 到项目目录。
终端py -3 examples/case01/run_dynamics.py --no-plot
看到 [run] 完成! 就说明成功了!
numpy 和 pyyaml 就能跑了。matplotlib 是用来画图的,建议也装上。
别怕,你学过的物理知识在这里全用得上!
力是让物体运动状态改变的东西。程序里支持四种力:
| 力 | 生活中的例子 | 程序里的开关 |
|---|---|---|
| 均匀重力 | 苹果从树上往下掉,方向朝地面 | gravity_field |
| 万有引力 | 太阳和地球互相吸引,质量越大越明显 | gravity_interaction |
| 弹簧力 | 蹦极的绳子把你拉回来 | elastic_force |
| 阻尼(阻力) | 在水里挥手比在空气里费劲得多 | damping_force |
程序用 蛙跳法(Leapfrog) 来模拟运动。名字很形象:
就像青蛙跳一样——先蹲下蓄力(半步速度),跳出去(位置更新),再调整(后半步速度)!
程序还会帮你计算各种能量,画出漂亮的能量图:
让我们来运行第一个模拟——两个小球用弹簧连着,在重力场中下落。
终端py -3 examples/case01/run_dynamics.py
你会看到:
|[compute] 计算中: 100%| —— 电脑正在算如果不想看图片(比如在服务器上跑),加个 --no-plot 就行:
终端py -3 examples/case01/run_dynamics.py --no-plot
运行完后在 examples/case01/output/ 里会生成:
| 文件名 | 内容 |
|---|---|
| trajectory.txt | 所有小球的全部轨迹数据(很大的文件) |
| display.txt | 抽帧后的显示数据(动画用) |
| trajectory_plots.png | 轨迹和能量图 |
| dynamics.log | 运行日志(看看电脑算了多长时间) |
所有参数都在 input.txt 里(注意:虽然是 .txt 后缀,但内容是 YAML 格式)。
试试改这几个参数,看看效果有什么不同:
input.txtG: [0.0, 0.0, -9.8] # 改成更大的数字,比如 -20
G 的 3 个数字分别对应 x、y、z 方向的重力分量。
把 z 方向改成 -50,小球"叮"一下就掉下去了!
bond.txtk1 100.0 2.0
中间那个数字是弹簧的劲度系数(k),越大弹簧越硬。改成 1000 试试?
input.txtDT: 0.001 # 时间步长(秒)
DT 越小计算越精确,但跑得越慢。试试 0.0001 看看效果?
程序里每种力都可以独立开关:
input.txt# ── 力开关(0=关闭, 1=开启)──────────────────
gravity_field: 1 # 均匀重力场
gravity_interaction: 0 # 原子间万有引力
elastic_force: 1 # 弹簧键力
damping_force: 0 # 阻尼(阻力)
gravity_field: 0 → 小球就飘在空中了gravity_interaction: 1 → 两个小球会互相吸引damping_force: 1 → 小球会慢慢停下来
coord.txt 存放每个小球(原子)的初始位置和速度:
coord.txtn mass radius x y z vx vy vz fix_x fix_y fix_z
1 1 0.28 -1 0 0 0 0 0 0 0 0 0
2 1 0.28 1 0 1 0 0 0 0 0 0 0
| 列名 | 含义 |
|---|---|
n | 小球编号 |
mass | 质量(越大越「重」,越不容易被推动) |
radius | 半径(画出来的大小) |
x y z | 初始位置坐标 |
vx vy vz | 初始速度 |
fix_x fix_y fix_z | 固定约束(1=锁定该方向不动,0=自由运动) |
mass 和 radius 必须 > 0。
如果设置了 fix_x: 1,那这个小球在 x 方向上就「钉死」了,拉不动。
以下实验可以帮你理解不同的物理概念。每个实验都告诉你怎么改参数。
0 0 10,速度全 0gravity_field: 1,关闭其他所有力py -3 examples/case01/run_dynamics.pygravity_field: 0,打开 elastic_force: 1gravity_interaction: 1vx: 0 vy: 1.5 vz: 0)(0, 0, 5),原子 2 在 (0, 0, 0)fix_x: 1 fix_y: 1 fix_z: 1(钉在天花板上)程序支持 4 种计算方法,精度和速度不一样:
input.txtmethod: leapfrog # 可选: explicit_euler | implicit_euler | midpoint | leapfrog
| 方法 | 精度 | 特点 |
|---|---|---|
explicit_euler | ⭐ | 最简单的方法,不精确但快 |
implicit_euler | ⭐⭐ | 比显式欧拉稳定一些 |
midpoint | ⭐⭐⭐ | 中点法,精度不错 |
leapfrog | ⭐⭐⭐⭐ | 默认方法,精度最高,还能很好地保持能量守恒 |
method 改成 explicit_euler,关掉所有阻尼,看能量图——
你会发现总能量(红色虚线)慢慢增加,因为显式欧拉法不守恒能量!
再换回 leapfrog,总能量几乎是一条水平线!
Python 版本跑大模拟可能会慢。程序还支持用 C 语言引擎来加速:
input.txtengine: c # 改成 c 就用 C 引擎,比 Python 快 26 倍!
input.txtNT: 100000 # 总步数(越大模拟时间越长)
DT: 0.001 # 每步的时间(秒)
NSTEP: 100 # 抽帧间隔(每 NSTEP 步记录一帧)
T_total: 100.0 # 总模拟时间(秒),程序会自动计算 NT = T_total / DT
装好 VisPy 和 PyQt5 还能看 3D 动画:
终端pip install vispy PyQt5
py -3 draw.py examples/case01/output
出现 3D 窗口后,可以用鼠标拖拽旋转视角!
试试 py -3 -m pip install ...。Windows 上有时需要这样用。
检查一下 force_calc: 1 有没有设置。如果 force_calc: 0,程序会使用缓存的结果。
或者把 force_calc 改成 1 强制重新计算。
因为程序用了硬壁边界(小球碰到盒子壁会弹回来),这种"碰撞"会导致微小的能量损失。 这是正常的物理现象,不是 Bug。如果用软壁边界会好很多。
先确认装好了 vispy 和 PyQt5:pip install vispy PyQt5。如果还是不行,
直接在终端运行 py -3 draw.py examples/case01/output 看错误信息。
之前确实有两个,但现在已经修好了!外部引擎只会显示一个 tqdm 进度条,
引擎自己的输出被静默收集到日志文件里了。
在 coord.txt 里增加行就可以。每行一个原子。 如果原子之间有弹簧连接,还要在 connection.txt 和 bond.txt 里添加对应的键。