四、输入文件结构:分子拓扑、力场参数、模拟参数
说实话,FEP 计算真正“跑起来”之前,最容易被忽略的恰恰是那几份输入文件。你想想看,拓扑、力场、模拟参数,这三样东西就像三根柱子,少一根整个计算就塌了。我在项目中接手过不少“跑不出来”的案例,十有八九是输入文件版本出了乱子。所以这章咱们好好捋一捋,到底每份文件里装着什么,版本控制又该盯住哪些细节。
4.1 分子拓扑文件
分子拓扑文件,说白了就是告诉程序“这个分子长什么样”。它定义原子编号、键的连接、角度、二面角、等价原子、电荷等。常见的文件后缀是 .top 或 .itp。GROMACS 里通常用 .itp 作为包含片段,用 .top 作为主拓扑。
我个人习惯把每个配体或蛋白的拓扑单独写成一个 .itp,再用 #include 合进主拓扑。这样版本控制里每个配体的变更记录就清晰很多——你改了一个基团的电荷,只需要看那个 .itp 的 diff 就够了。
来看一个简单的配体拓扑片段:
[ moleculetype ]
; name nrexcl
MOL 3
[ atoms ]
; nr type resnr residue atom cgnr charge mass
1 opls_135 1 MOL C1 1 0.000 12.011
2 opls_140 1 MOL H1 2 0.060 1.008
3 opls_140 1 MOL H2 3 0.060 1.008
4 opls_140 1 MOL H3 4 0.060 1.008
[ bonds ]
; ai aj funct r k
1 2 1 0.1090 284512.0
1 3 1 0.1090 284512.0
1 4 1 0.1090 284512.0
这里每个原子的类型(比如 opls_135)直接对应着力场参数文件里的定义。一旦改了原子类型,力场参数也必须跟着换。嗯,这就是版本控制里最容易踩坑的地方——改拓扑忘了改力场。
曾经踩过的坑:有一次我改了一个配体的二面角类型,顺手在 .itp 里把原子类型从 opls_135 换成了 opls_136。结果跑能量极小化时报错,说是力场里找不到参数。查了半小时才意识到力场文件还是旧版。从那以后我每次修改拓扑都会同步检查力场参数的版本。
4.2 力场参数文件
力场参数文件通常是一堆 .itp 或 .dat 的集合,定义了原子间的非键相互作用参数(σ、ε)、键长平衡值、键角平衡值、二面角势垒等。不同的力场(AMBER、CHARMM、OPLS)文件结构差异很大。
举个例子,你可能会看到一个 OPLS 力场目录是这样的:
ff_opls/
ffoplsaa.itp # 主力场文件
ffoplsaanb.itp # 非键参数
ffoplsaabon.itp # 键参数
ffoplsaa.atp # 原子类型定义
...
这里最关键的其实是各个文件的 [ defaults ] 段和 [ atomtypes ] 段。一旦组合规则改成了 1-4 作用方式,或者把 fudgeLJ 从 0.5 改成了 0.0,计算结果会产生明显差异。我在项目中就遇到过两次 FEP 结果因为力场版本不一致而无法复现的情况——一次是用了不同的 fudgeLJ 值,另一次是二面角参数被误改成 CHARMM 风格。
| 力场类型 | 常见文件后缀 | 版本控制要点 |
|---|---|---|
| AMBER | .prm, .frcmod |
注意补充参数文件是否对应同一力场版本 |
| CHARMM | .prm, .rtf |
键参数使用多个段,检查原子类型名称一致性 |
| OPLS | .itp, .atp |
组合规则和1-4作用矩阵极易被修改 |
小技巧:我习惯在仓库里放一个 ff_version.txt 文件,专门记录每个力场文件的来源和版本号(比如“OPLS-AA 2023-05-31”)。这样即使文件内容没变,也能知道它来自哪个 release。
4.3 模拟参数文件
模拟参数文件通常以 .mdp 结尾(GROMACS 常用),它控制模拟的“软条件”:温度、压力、步长、约束算法、周期性、能量组等。你会发现同一个分子体系,换一个 .mdp 能跑出截然不同的结果。版本控制里,.mdp 文件的每一次变更都应该被严格记录。
来看看一个典型的平衡阶段 .mdp:
define = -DPOSRES
integrator = md
nsteps = 50000 ; 100 ps at 2 fs
dt = 0.002
nstxout = 500 ; output every 1 ps
nstenergy = 500
nstlist = 10
cutoff-scheme = Verlet
rcoulomb = 1.0
rvdw = 1.0
tcoupl = v-rescale
tc-grps = System
tau-t = 0.1
ref-t = 298.15
Pcoupl = berendsen
pcoupltype = isotropic
tau-p = 1.0
ref-p = 1.0
compressibility = 4.5e-5
gen-vel = yes
gen-temp = 298.15
注意这里的 ref-t、tau-t、dt 和 nsteps。你改一个数字,就需要重新平衡或生产。我见过有人把 dt 从 0.002 改成 0.004,结果模拟直接炸掉——因为约束算法来不及处理氢原子振动。版本控制里如果只改了这一个数字,提交信息要写清楚为什么改。
4.4 版本控制中的结构化组织
把上面三份文件组合进同一个仓库时,目录结构的设计直接影响可追踪性。我个人推荐这样的树形组织:
fep_project/
topology/
protein.itp
ligand_a.itp
ligand_b.itp
topol.top
ff/
ff_opls/
ffoplsaa.itp
ffoplsaanb.itp
ff_charmm36/
...
mdp/
em.mdp
npt_eq.mdp
prod.mdp
scripts/
prep_fep.py
analysis/
...
你看,拓扑、力场、参数三个目录清晰分离。每个目录下的文件都可以独立做版本控制。比如你为了测试新力场,可以新开一个 ff_new 目录,然后在 topol.top 里用 #include 切换。切换前先 commit 一次,切换后再 commit,这样回溯时你就能看到所有的变更路径。
核心原则:任何一个文件内容的变动,都应该对应一个单独的 commit。不要攒一堆改动再一次性提交——那样你根本不知道是哪个参数导致的结果变化。
最后,补上一张这章提到的输入文件结构关系图。它帮你快速理解三份文件如何构成完整的模拟输入,以及版本控制怎么把它们串起来。
好了,这三类输入文件的结构和版本控制要点就是这样。你下次遇到“模拟跑不完”或者“结果不对劲”的时候,不妨先回头查查这些文件在仓库里的 commit 历史——多半能找到线索。