⚛︎ ⋆。°✩ ⭐ ⋆。°✩

Dynamics 物理模拟实验室

用代码让小球动起来!从牛顿力学到分子模拟
🎯 适合高一同学 · 零基础也能上手

🤔 这是什么?

想象一下:你把一个弹珠从桌子上推下去——它会怎么运动?如果同时扔两个弹珠,它们会互相碰撞吗?如果弹珠之间用弹簧连着呢?

Dynamics 就是一个在电脑上做这些"弹珠实验"的程序。你只需要告诉电脑:

然后电脑就会帮你算出每个小球每一瞬间的位置和速度,最后画出一张漂亮的轨迹图!

🎮 把它想象成一个超级物理沙盒游戏
你设置物理规则,电脑负责计算,然后你看到结果。和 Minecraft 有点像,但这里的「物理引擎」是真的物理公式!

它能做什么?

🛠️ 安装

1 安装 Python

python.org 下载安装包, 安装时一定记得勾选 "Add Python to PATH"。

2 安装依赖包
终端pip install numpy pyyaml tqdm matplotlib

如果下载慢,试试国内镜像:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ...

3 下载程序

把整个项目文件夹放到电脑上。打开终端,cd 到项目目录。

4 验证安装
终端py -3 examples/case01/run_dynamics.py --no-plot

看到 [run] 完成! 就说明成功了!

💡 小提示:如果你只想看看效果,装好 numpypyyaml 就能跑了。matplotlib 是用来画图的,建议也装上。

📖 快速物理课

别怕,你学过的物理知识在这里全用得上!

🌍 力(Force)

力是让物体运动状态改变的东西。程序里支持四种力:

生活中的例子程序里的开关
均匀重力 苹果从树上往下掉,方向朝地面 gravity_field
万有引力 太阳和地球互相吸引,质量越大越明显 gravity_interaction
弹簧力 蹦极的绳子把你拉回来 elastic_force
阻尼(阻力) 在水里挥手比在空气里费劲得多 damping_force

🏃 运动

程序用 蛙跳法(Leapfrog) 来模拟运动。名字很形象:

🐸 蛙跳的步骤:
  1. 前半步:根据当前受力,把速度往前推一小半步
  2. :用新的速度把位置往前推一步
  3. 后半步:到新位置后重新算受力,再推另一半速度

就像青蛙跳一样——先蹲下蓄力(半步速度),跳出去(位置更新),再调整(后半步速度)!

⚡ 能量(Energy)

程序还会帮你计算各种能量,画出漂亮的能量图:

💡 核心思想:能量守恒! 如果没有外力干扰,总能量应该保持不变。 动能和势能之间互相转换——像荡秋千一样,荡到最高点速度最慢(动能最小、势能最大), 荡到最低点速度最快(动能最大、势能最小)。

🚀 第一次运行

让我们来运行第一个模拟——两个小球用弹簧连着,在重力场中下落。

运行命令

终端py -3 examples/case01/run_dynamics.py

你会看到:

  1. 终端里跳出进度条 |[compute] 计算中: 100%| —— 电脑正在算
  2. 然后弹出一个窗口,里面有 9 张图(位置、速度、能量)
  3. 最后会生成动画文件
📈 这里会显示轨迹图:x-t, y-t, z-t, vx-t, vy-t, vz-t 和能量图
(运行程序后就能看到啦!)

只看不画图

如果不想看图片(比如在服务器上跑),加个 --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=自由运动)
⚠️ 注意:massradius 必须 > 0。 如果设置了 fix_x: 1,那这个小球在 x 方向上就「钉死」了,拉不动。

🧪 动手实验

以下实验可以帮你理解不同的物理概念。每个实验都告诉你怎么改参数。

实验 1:自由落体

🎯 目标:观察小球在重力场中下落的过程,验证自由落体公式。
操作:
  1. coord.txt 改成只有 1 个原子,位置 0 0 10,速度全 0
  2. gravity_field: 1,关闭其他所有力
  3. 运行 py -3 examples/case01/run_dynamics.py
  4. 观察 z-t 图(z 坐标随时间变化)—— 应该是一条抛物线!
🤔 想一想:根据物理公式 z = ½gt²,你能从图中算出重力加速度 g 吗?

实验 2:弹簧振子

🎯 目标:观察弹簧振子的简谐振动。
操作:
  1. 放两个原子,用弹簧连起来
  2. 关掉重力 gravity_field: 0,打开 elastic_force: 1
  3. 把其中一个原子拉远一点(改 coord.txt 的初始位置)
  4. 观察两个小球来回振动
🤔 想一想:弹性势能和动能是怎么互相转换的?看看能量图,橙色线和蓝色线的变化规律。

实验 3:双星绕转

🎯 目标:模拟两颗星球在万有引力下互相绕转。
操作:
  1. 放两个原子,给它们不同的质量(比如 10 和 1)
  2. 关掉所有其他力,只打开 gravity_interaction: 1
  3. 给轻的原子一个切向初速度(比如 vx: 0 vy: 1.5 vz: 0
  4. 观察轻的原子绕着重的原子转!
🤔 想一想:这和太阳系中行星绕太阳转的原理是一样的吗?哪个原子是「太阳」?

实验 4:单摆

🎯 目标:用固定约束做一个单摆。
操作:
  1. 放两个原子:原子 1 在 (0, 0, 5),原子 2 在 (0, 0, 0)
  2. 原子 1 设 fix_x: 1 fix_y: 1 fix_z: 1(钉在天花板上)
  3. 用弹簧连接两个原子
  4. 打开重力,运行看效果 — 下面的原子会像摆锤一样摆动!

🔬 高手进阶

改变积分方法

程序支持 4 种计算方法,精度和速度不一样:

input.txtmethod: leapfrog   # 可选: explicit_euler | implicit_euler | midpoint | leapfrog
方法精度特点
explicit_euler最简单的方法,不精确但快
implicit_euler⭐⭐比显式欧拉稳定一些
midpoint⭐⭐⭐中点法,精度不错
leapfrog⭐⭐⭐⭐默认方法,精度最高,还能很好地保持能量守恒
💡 试试:method 改成 explicit_euler,关掉所有阻尼,看能量图—— 你会发现总能量(红色虚线)慢慢增加,因为显式欧拉法不守恒能量! 再换回 leapfrog,总能量几乎是一条水平线!

换成 C 语言引擎

Python 版本跑大模拟可能会慢。程序还支持用 C 语言引擎来加速:

input.txtengine: c    # 改成 c  就用 C 引擎,比 Python 快 26 倍!
⚠️ 前提:需要先安装 C 编译器(gcc)。Windows 上推荐用 MSYS2 + MinGW64, 具体步骤见 INSTALL.md

调整模拟规模

input.txtNT: 100000       # 总步数(越大模拟时间越长)
DT: 0.001         # 每步的时间(秒)
NSTEP: 100        # 抽帧间隔(每 NSTEP 步记录一帧)
T_total: 100.0    # 总模拟时间(秒),程序会自动计算 NT = T_total / DT

3D 动画

装好 VisPy 和 PyQt5 还能看 3D 动画:

终端pip install vispy PyQt5
py -3 draw.py examples/case01/output

出现 3D 窗口后,可以用鼠标拖拽旋转视角!

常见问题

Q: 报错 "pip 不是内部或外部命令"?

试试 py -3 -m pip install ...。Windows 上有时需要这样用。

Q: 为什么我改了参数但结果没变?

检查一下 force_calc: 1 有没有设置。如果 force_calc: 0,程序会使用缓存的结果。 或者把 force_calc 改成 1 强制重新计算。

Q: 总能量曲线为什么不是完全水平的?

因为程序用了硬壁边界(小球碰到盒子壁会弹回来),这种"碰撞"会导致微小的能量损失。 这是正常的物理现象,不是 Bug。如果用软壁边界会好很多。

Q: 为什么我的动画闪一下就没了?

先确认装好了 vispyPyQt5pip install vispy PyQt5。如果还是不行, 直接在终端运行 py -3 draw.py examples/case01/output 看错误信息。

Q: 为什么 C/C++/Fortran 引擎有"两个进度条"?

之前确实有两个,但现在已经修好了!外部引擎只会显示一个 tqdm 进度条, 引擎自己的输出被静默收集到日志文件里了。

Q: 我想模拟更多的原子,怎么加?

coord.txt 里增加行就可以。每行一个原子。 如果原子之间有弹簧连接,还要在 connection.txtbond.txt 里添加对应的键。