layout: post
title: GROMACS电场的使用
categories:
GROMACS源代码中有关电场的代码至少可追溯至3.3版本, 但由于低版本手册中没有提及, 所以很多人以为GROMACS是不支持电场的. 在GROMACS 5.x版本的手册中虽然提到了电场的选项, 但仍语焉不详, 且说明与实际代码实现不一致, 导致很多误解. 在这里, 我根据网上查阅到的资料, 以及源代码和实际测试, 对GROMACS的电场选项说明一下. 使用的GROMACS版本为5.1.2.
手册7.3.26中电场选项的说明
如果你想在某个方向上使用电场, 在适当的E-*后输入3个数字. 第一个数字为余弦的数目, 因为只实现了单个余弦项(频率为0), 所以输入1即可; 第二个数字: 电场强度, 以V/nm为单位; 第三个数字: 余弦的相位, 你可以在这里输入任何数字, 因为频率为零的余弦没有相位.
补充说明
实际上, 这几个选项在源码中称为电场的空间部分, 也就是电场不随时间变化的部分, 即用以设定电场强度. 这里你也可以使用多个余弦项, 每个余弦项指定两个参数, 强度大小和相位. 但正如上面所说, 代码中只实现了使用一个余弦项的功能, 所以即便指定了多个余弦项, 也只有第一个起作用, 其他被忽略. 另外, 只有设定的电场强度有意义, 相位参数没有在代码中使用, 所有随意给个数字即可.
例如, 你可以使用两个余弦项, 那就指定E-x = 2 第一项电场强度 任意数字 第二项电场强度 任意数字
, 但效果与E-x = 1 电场强度 任意数字
是一样的. 还要注意, 第一个数字必须写为整数, 不能带小数点, 写成1.0
这种会出问题.
使用这些选项你可以设置一个脉冲交变电场. 这个交变电场的形式为高斯脉冲:
$$E(t) = E_0 \exp \left[-{(t-t_0)^2 \over 2 \s^2} \right] \cos\left[\w(t-t_0)\right]$$
例如, x方向的E-x
和E-xt
各自有三个字段, 一共需要定义四个参数, 就像下面这样:
E-x = 1 E0 0
<del><code>E-xt = omega t0 sigma</code></del>
<del>在特殊的例子里如果 <code>sigma = 0</code>, 那么指数项将被省略, 只使用余弦项.</del>
更多的细节可参考论文Carl Caleman and David van der Spoel: Picosecond Melting of Ice by an Infrared Laser Pulse - A Simulation Study Angew. Chem. Intl. Ed. 47 pp. 14 17-1420 (2008)。
补充说明
这几个选项称为电场的时间部分, 也就是电场随时间变化的部分, 不包含空间强度部分的信息. 手册中的说明有误, 错误部分已经标识删除线.
在这里你可以选择使用单个余弦变化的电场, 或是高斯脉冲交变电场. 但选项参数的设置有讲究, 且高斯脉冲电场的sigma
参数不能为0
, 否则运行出错.
与E-x
等选项一样, E-xt
等选项的参数设置格式中, 第一个数字也是余弦项的数目, 后面跟着每个余弦项的频率omega和相位phi, 但源码中没有使用phi, 所以只有设定的omega有意义, phi可以随意给个数字.
使用高斯脉冲电场时, E-xt
等选项的第一个参数必须为3
, 且后面跟着6个数字, 分别是omega 任意数字 t0 任意数字 sigma 任意数字
.
使用余弦电场时, Ex-t
等选项的第一个参数不为3
即可, 但仍然只有第一项起作用, 所以使用1 omega 任意数字
即可.
源代码中的电场部分
GROMACS中电场的实现代码位于.\gromacs-5.1.2\src\gromacs\mdlib\sim_util.cpp
的calc_f_el
函数,
<table class="highlighttable"><th colspan="2" style="text-align:left">c</th><tr><td><div class="linenodiv" style="background-color: #f0f0f0; padding-right: 10px"><pre style="line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67</pre></div></td><td class="code"><div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008800; font-style: italic">/*</span>
<span style="color: #008800; font-style: italic"> * calc_f_el calculates forces due to an electric field.</span>
<span style="color: #008800; font-style: italic"> *</span>
<span style="color: #008800; font-style: italic"> * force is kJ mol^-1 nm^-1 = e * kJ mol^-1 nm^-1 / e</span>
<span style="color: #008800; font-style: italic"> *</span>
<span style="color: #008800; font-style: italic"> * Et[] contains the parameters for the time dependent</span>
<span style="color: #008800; font-style: italic"> * part of the field.</span>
<span style="color: #008800; font-style: italic"> * Ex[] contains the parameters for</span>
<span style="color: #008800; font-style: italic"> * the spatial dependent part of the field.</span>
<span style="color: #008800; font-style: italic"> * The function should return the energy due to the electric field</span>
<span style="color: #008800; font-style: italic"> * (if any) but for now returns 0.</span>
<span style="color: #008800; font-style: italic"> *</span>
<span style="color: #008800; font-style: italic"> * WARNING:</span>
<span style="color: #008800; font-style: italic"> * There can be problems with the virial.</span>
<span style="color: #008800; font-style: italic"> * Since the field is not self-consistent this is unavoidable.</span>
<span style="color: #008800; font-style: italic"> * For neutral molecules the virial is correct within this approximation.</span>
<span style="color: #008800; font-style: italic"> * For neutral systems with many charged molecules the error is small.</span>
<span style="color: #008800; font-style: italic"> * But for systems with a net charge or a few charged molecules</span>
<span style="color: #008800; font-style: italic"> * the error can be significant when the field is high.</span>
<span style="color: #008800; font-style: italic"> * Solution: implement a self-consistent electric field into PME.</span>
<span style="color: #008800; font-style: italic"> */</span>
<span style="color: #AA22FF; font-weight: bold">static</span> <span style="color: #00BB00; font-weight: bold">void</span> <span style="color: #00A000">calc_f_el</span>(<span style="color: #00BB00; font-weight: bold">FILE</span> <span style="color: #666666">*</span>fp, <span style="color: #00BB00; font-weight: bold">int</span> start, <span style="color: #00BB00; font-weight: bold">int</span> homenr,
real charge[], rvec f[],
t_cosines Ex[], t_cosines Et[], <span style="color: #00BB00; font-weight: bold">double</span> t)
{
rvec Ext;
real t0;
<span style="color: #00BB00; font-weight: bold">int</span> i, m;
<span style="color: #AA22FF; font-weight: bold">for</span> (m <span style="color: #666666">=</span> <span style="color: #666666">0</span>; (m <span style="color: #666666"><</span> DIM); m<span style="color: #666666">++</span>)
{
<span style="color: #AA22FF; font-weight: bold">if</span> (Et[m].n <span style="color: #666666">></span> <span style="color: #666666">0</span>)
{
<span style="color: #AA22FF; font-weight: bold">if</span> (Et[m].n <span style="color: #666666">==</span> <span style="color: #666666">3</span>)
{
t0 <span style="color: #666666">=</span> Et[m].a[<span style="color: #666666">1</span>];
Ext[m] <span style="color: #666666">=</span> cos(Et[m].a[<span style="color: #666666">0</span>]<span style="color: #666666">*</span>(t<span style="color: #666666">-</span>t0))<span style="color: #666666">*</span>exp(<span style="color: #666666">-</span>sqr(t<span style="color: #666666">-</span>t0)<span style="color: #666666">/</span>(<span style="color: #666666">2.0*</span>sqr(Et[m].a[<span style="color: #666666">2</span>])));
}
<span style="color: #AA22FF; font-weight: bold">else</span>
{
Ext[m] <span style="color: #666666">=</span> cos(Et[m].a[<span style="color: #666666">0</span>]<span style="color: #666666">*</span>t);
}
}
<span style="color: #AA22FF; font-weight: bold">else</span>
{
Ext[m] <span style="color: #666666">=</span> <span style="color: #666666">1.0</span>;
}
<span style="color: #AA22FF; font-weight: bold">if</span> (Ex[m].n <span style="color: #666666">></span> <span style="color: #666666">0</span>)
{
<span style="color: #008800; font-style: italic">/* Convert the field strength from V/nm to MD-units */</span>
Ext[m] <span style="color: #666666">*=</span> Ex[m].a[<span style="color: #666666">0</span>]<span style="color: #666666">*</span>FIELDFAC;
<span style="color: #AA22FF; font-weight: bold">for</span> (i <span style="color: #666666">=</span> start; (i <span style="color: #666666"><</span> start<span style="color: #666666">+</span>homenr); i<span style="color: #666666">++</span>)
{
f[i][m] <span style="color: #666666">+=</span> charge[i]<span style="color: #666666">*</span>Ext[m];
}
}
<span style="color: #AA22FF; font-weight: bold">else</span>
{
Ext[m] <span style="color: #666666">=</span> <span style="color: #666666">0</span>;
}
}
<span style="color: #AA22FF; font-weight: bold">if</span> (fp <span style="color: #666666">!=</span> <span style="color: #AA22FF">NULL</span>)
{
fprintf(fp, <span style="color: #BB4444">"%10g %10g %10g %10g #FIELD</span><span style="color: #BB6622; font-weight: bold">\n</span><span style="color: #BB4444">"</span>, t,
Ext[XX]<span style="color: #666666">/</span>FIELDFAC, Ext[YY]<span style="color: #666666">/</span>FIELDFAC, Ext[ZZ]<span style="color: #666666">/</span>FIELDFAC);
}
}
</pre></div>
</td></tr></table>可以看到, 函数calc_f_el
中传入的Ex[]
和Et[]
的数据类型都是t_cosines
. 这种数据类型的定义于.\gromacs-5.1.2\src\gromacs\legacyheaders\types\inputrec.h
:
<table class="highlighttable"><th colspan="2" style="text-align:left">c</th><tr><td><div class="linenodiv" style="background-color: #f0f0f0; padding-right: 10px"><pre style="line-height: 125%"> 1
2
3
4
5
6
7
8
9
10
11
12</pre></div></td><td class="code"><div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #AA22FF; font-weight: bold">typedef</span> <span style="color: #AA22FF; font-weight: bold">struct</span> {
<span style="color: #00BB00; font-weight: bold">int</span> n; <span style="color: #008800; font-style: italic">/* Number of terms */</span>
real <span style="color: #666666">*</span>a; <span style="color: #008800; font-style: italic">/* Coeffients (V / nm ) */</span>
real <span style="color: #666666">*</span>phi; <span style="color: #008800; font-style: italic">/* Phase angles */</span>
} t_cosines;
<span style="color: #AA22FF; font-weight: bold">typedef</span> <span style="color: #AA22FF; font-weight: bold">struct</span> {
real E0; <span style="color: #008800; font-style: italic">/* Field strength (V/nm) */</span>
real omega; <span style="color: #008800; font-style: italic">/* Frequency (1/ps) */</span>
real t0; <span style="color: #008800; font-style: italic">/* Centre of the Gaussian pulse (ps) */</span>
real sigma; <span style="color: #008800; font-style: italic">/* Width of the Gaussian pulse (FWHM) (ps) */</span>
} t_efield;
</pre></div>
</td></tr></table>在这里我们还可以看到, 虽然定义了高斯脉冲电场使用的数据类型_efield
, 但它没有传入函数calc_f_el
, 所以没有办法直接使用.
如果你需要实现特殊的电场形式, 修改calc_f_el
函数即可, 且可以像目前实现高斯脉冲电场的方法一样, 重用传入的参数.
<code>mdrun</code>时查看电场信息
mdrun
运行模拟后, 输出的.log
文件中会给出设定的电场信息, 类似于
E-x:
n = 2
a = 1.000000e+001 2.000000e+001
phi = 1.000000e+001 3.000000e+001
E-xt:
n = 3
a = 1.000000e+003 1.000000e-001 1.000000e-002
phi = 0.000000e+000 0.000000e+000 0.000000e+000
E-y:
n = 0
E-yt:
n = 0
E-z:
n = 0
E-zt:
n = 0
你可以从这里看到自己设定的值是否正确读入了.
mdrun
运行时有一个选项-field
, 可以指定一个.xvg
文件, 里面记录每个时间步的电场大小, 默认输出文件为field.xvg
. 利用这个文件你可以查看所加的电场是否正确.
余弦电场
在.mdp
中的设置强度为10 V/nm, 频率为100 ps<sup>-1</sup>(即100 THz)的余弦电场
E-x = 1 10 0
E-xt = 1 100 0
GROMACS输出的数据与设置完全一致
高斯脉冲电场
在.mdp
中的设置强度为10 V/nm, 频率为100 ps<sup>-1</sup>(即100 THz), 脉冲中心0.1 ps, 方差0.01 ps的高斯脉冲电场
E-x = 1 10 0
E-xt = 3 100 0 .1 0 .01 0
GROMACS输出的数据与设置完全一致
使用电场的示例
研究电场对体系的影响时, 最好先使用NVE系综进行测试, 看看.mdp
中的选项设置在不加电场时能否保证能量守恒. 严格的能量守恒是很难做到的, 只要在关心的时间尺度内能量守恒即可, 也可以根据能量漂移的速率来决定, 大致小于相应温度下的平动能就能接受. 能量守恒测试通过后, 再打开电场选项, 看电场对体系总能量的影响. 成品模拟时一般是使用NVT或NPT的.
下面测试下GROMACS自带的spc216.gro
水盒子NVE系综下不同电场的影响, 电场设置与上面的相同.
可以看到加了电场后, 体系总能量会增大很多. 你可以下载所用的文件, 自己进行测试.
参考资料
评论
- 2017-02-20 14:29:52
hjx
非常不错,学习了。感谢李老师。