使用DMFF进行液体碳酸二甲酯(DMC)的力场优化
reporter:冯维
1. 介绍
用DMFF搭建工作流的初始步骤是产生势函数,其流程和API与OpenMM类似,大致如下:
- 首先定义力场对象(DMFF中称之为
Hamiltonian
),其中定义了原子归类(typification
)规则以及所有的力场参数。大体上相当于表达为python对象的openmm的xml文件或是gromacs的itp文件。 - 获取所需要模拟的体系的分子键连拓扑信息(通过pdb文件得到)。
- 根据体系的连接拓扑,使用
Hamiltonian
对其中的每个原子、键长、键角、二面角等进行归类并参数化,创建势函数。势函数一般以原子位置、盒子大小、力场参数为输入,方便后续求导运算。 - 如有必要,对势函数进行必要的修饰和拓展。例如,利用
jax.grad
得到力、维里矩阵的计算函数,可以直接用于MD模拟。 - 也可以利用势函数定义相应性质的
estimator
和损失函数,并利用梯度下降优化器进行相应的参数优化。
在DMFF中,我们提供了传统物理力场中PME、对相互作用、多极矩、可极化力场等势函数的JAX实现。利用JAX提供的修饰工具,用户可以对这些势函数进行微分,向量化、编译等修饰,也可以对其进行再封装和重组合以实现新的势函数,也可以基于这些势函数开发性质估计函数(property estimators
),而这些新的函数也可以进一步被求导或者向量化。可以看出,这种以函数变换为核心的编程范式为DMFF中新力场、新目标函数的定义提供了无与伦比的灵活性。
接下来,为了用户对DMFF中的主要模块和功能有个全面的认识,展示这些模块在力场开发中是如何互相配合的,我们通过碳酸二甲酯(DMC)的粗粒化模型,演示在DMFF中一个模型从定义、优化、到部署的全过程。任务的目标是:使用三个site表示DMC长链(以下称为3-site模型),如何优化这三个site间的相互作用,复现XRD实验测出的液体DMC的径向分布函数(Radial Distribution Function, RDF)并将DMC粗粒化模型力场与全原子模型OPLS-AA力场进行比对。
2. 安装环境依赖
Cloning into 'DMFF'... remote: Enumerating objects: 3233, done. remote: Counting objects: 100% (3233/3233), done. remote: Compressing objects: 100% (1726/1726), done. remote: Total 3233 (delta 2119), reused 2243 (delta 1435), pack-reused 0 Receiving objects: 100% (3233/3233), 17.93 MiB | 1.90 MiB/s, done. Resolving deltas: 100% (2119/2119), done. Updating files: 100% (273/273), done. Branch 'devel' set up to track remote branch 'devel' from 'origin'. Switched to a new branch 'devel'
3. 定义势函数
WARNING:pymbar.timeseries:Warning on use of the timeseries module: If the inherent timescales of the system are long compared to those being analyzed, this statistical inefficiency may be an underestimate. The estimate presumes the use of many statistically independent samples. Tests should be performed to assess whether this condition is satisfied. Be cautious in the interpretation of the data.
载入DMC体系的拓扑,并构建整个模拟盒子的势能函数:
[ 0.2841 -0.5682]
我们通过prm.xml
力场文件文件可以看到,该势函数包含分子内原子间与的弹簧势、静电相互作用和分子间的势:
而我们将优化其中的一些参数。
4. 定义OpenMM采样器:
该函数的功能,就在输入的parameter
下,使用OpenMM生成NPT样本集,并存储在指定的trajectory
文件中。后续优化需要重采样时我们会反复调用该函数。
5. 初始MD采样
#"Step","Density (g/mL)","Speed (ns/day)","Time Remaining" 20000,0.624921661906067,0,-- 40000,0.6391331979020537,855,0:46 60000,0.6171748001381965,852,0:44 80000,0.631699815308414,852,0:42 100000,0.640350584372905,851,0:40 120000,0.6168773853049696,850,0:38 140000,0.6414942044606379,850,0:36 160000,0.6534696552734591,849,0:34 180000,0.6317333458882456,849,0:32 200000,0.6210531465099283,848,0:30 220000,0.6214576455357951,849,0:28 240000,0.6206535881657655,849,0:26 260000,0.6317494504636935,850,0:24 280000,0.6403171723009001,850,0:22 300000,0.6227962311846954,851,0:20 320000,0.599928445277456,851,0:18 340000,0.6360242931559097,851,0:16 360000,0.6059677989583129,851,0:14 380000,0.6297506490660306,852,0:12 400000,0.6098285081649429,852,0:10 420000,0.6276020008188183,852,0:08 440000,0.6279814980876081,853,0:06 460000,0.6221534588630206,852,0:04 480000,0.6206365173268449,852,0:02 500000,0.6083019942192689,852,0:00
6. 定义性质计算函数
在接下来的拟合中我们需要同时拟合RDF和密度,因此我们分别定义RDF和密度的计算函数:
在计算观测量的系综平均时,需要计算如下统计量: ,以上代码就定义了 函数。
一般来说,我们需要把 封装在一个函数里面,然后在每一轮优化时对其整体进行求导。
但在这里,因为RDF和密度都是纯粹的结构性质,和 无关也不参与求导,因此我们可以将每个样本的RDF ( )算好并预存,没有必要每一轮都重复计算。
在上示代码中,我们也完全采用mdtraj
中的现成工具计算每一帧的RDF,而不必采用可微分的jax实现。
7. 读入数据并进行比对
读入实验数据,并使用上面定义的性质计算函数,预先计算出DMC全原子模型在OPLS-AA力场下的RDF,作为比对(OPLS-AA力场参数由LigPargen生成):
我们将RDF计算函数得到的粗粒化模型结果与实验数据及全原子模型在OPLS-AA力场下的结果进行比对。可以先看一下由初始参数采样形成的RDF,这也是我们优化的起点:
8. Estimator 初始化
WARNING:root:Warning: importing 'simtk.openmm' is deprecated. Import 'openmm' instead.
这里,我们创建MBAREstimator
,并对其进行初始化。MBAREstimator
中需要初始化的变量包括两部分:
- 其包含的所有采样态信息(
state
)、样本(sample
) ; - 根据样本和采样态信息估计得到的采样态配分函数 ( )
可以看出,在上述代码中,我们定义了一个OpenMMSampleState
,并将该state
和由该state
采样产生的样本添加到了estimator
中,并调用optimize_mbar
函数(该函数会在后台调用外部的pymbar
工具)对其中所有采样态的配分函数进行估计。注意这些操作都不参与微分,也不依赖jax。完成初始化后的estimator
就可以以可微分的方式直接给出了。
9. 定义目标系综
在这里,我们通过之前已经定义好的可微分3-site模型势函数efunc
定义了我们的目标系综target_state
。作为后续reweighting
的输入参数。后续estimator
在计算时会反复调用target_state
中的efunc
去计算样本在目标系综中的有效能量(对NVT系综为 ,对NPT系综则为 )。
10. 定义损失函数
这里,我们通过estimator.estimate_weight
函数生成当前target_state
所对应的,进而给出当前target_state
下的RDF平均值,与实验参考值比较得到RDF目标函数:
同时我们发现,如果单纯优化RDF,优化器容易探索到非物理的参数区域,导致体系密度降低、直至跨越相边界成为气体。为避免这一现象,我们在损失函数中也加入了密度误差,以求对体系的密度进行控制。因此我们也单独定义了密度的损失函数:
在下面的优化循环中我们将首先针对密度进行几轮优化,然后再开始对RDF的调优。
Fbor
Feng Wei