Post

利用高斯调度xTB完成量子化学计算

利用高斯调度xTB完成量子化学计算

最近一个过渡态找麻了,体系大算得慢,还偶尔会藏个无垒的,此时想到了sobereva老师的高斯external脚本,于是拿来用了一下,非常好用,特此记录。

接口文档

后续可能考虑把atb2弄进来,这样就能算激发态优化了,所以大概记一下接口的使用方法。

根据说明书,external脚本使用关键词external=’‘实现。默认情况下调用方式为:

1
$Gau_External layer InputFile OutputFile MsgFile FChkFile MatElFile
  • layer:指ONIOM的layer。真实系统为R,中间层为M,模型系统为S
  • InputFile:在scratch产生的数据交换文件,用来向外部程序传递信息
  • OutputFile:要求外部程序写入信息的文件名
  • MsgFile:消息文件,创建此文件时会将文件内容复制到高斯log内
  • FChkFile:检查点文件,看原文似乎意思是某些过link402的任务需要往这里写信息,而不是OutputFile,其他没看懂,用到再说
  • MatElFile:矩阵文件,可以在脚本后面加关键词要求Gaussian导出一些单电子积分相关的东西之类的

显然对于不耍杂技的情况,最重要的是InputFile和OutputFile,这两个文件直接承担了信息交换功能。

InputFile格式为:

1
2
3
4
5
#atoms  derivatives-requested  charge  spin
原子数   导数阶数                电荷    自旋
atomic#  x  y  z  MM-charge MM-atom_type 
元素符号    坐标    MM电荷     MM原子类型
...

OutputFile格式为:

1
2
3
4
5
6
7
8
9
10
11
Items                          Pseudo Code                              Line Format
energy, dipole-moment (xyz)    E, Dip(I), I=1,3                         4D20.12
能量和偶极矩
gradient on atom (xyz)         FX(J,I), J=1,3; I=1,NAtoms               3D20.12
梯度
polarizability                 Polar(I), I=1,6                          3D20.12
极化率
dipole derivatives             DDip(I), I=1,9*NAtoms                    3D20.12
偶极导数
force constants                FFX(I), I=1,(3*NAtoms*(3*NAtoms+1))/2    3D20.12
力常数(Hessian)

只要接口程序解析InputFile,调用外部程序计算,写入OutputFile,Gaussian即可利用外部程序的信息开始计算。

gau_xtb

原版gau_xtb接口有三个文件,分别为genxyz、extderi和xtb.sh,在运行时需要全部放在计算目录下。关键词:

1
2
%nproc=1
# opt(ts,calcfc,noeigen,nomicro) external='./xtb.sh'

注意:

  • 如果进行opt任务,则需要写入nomicro,避免Gaussian调用自己的MM优化器
  • %nproc需要设为1,因为Gaussian本体并不进行QC计算,只作为driver引导external程序进行计算

笔者在运行时遇到了问题:

1
2
3
4
5
6
7
Running external command "./xtb.sh R"
         input file       "/home/apprepo/g16/scratch/Gau-123180.EIn"
         output file      "/home/apprepo/g16/scratch/Gau-123180.EOu"
         message file     "/home/apprepo/g16/scratch/Gau-123180.EMs"
         fchk file        "/home/apprepo/g16/scratch/Gau-123180.EFC"
         mat. el file     "/home/apprepo/g16/scratch/Gau-123180.EUF"
Failed to open output file from external program.

几番周折,最终定位到的问题是脚本直接在scratch目录似乎创建不了Gau-123180.EOu,但如果在本地创建Gau-123180.EOu再cp过去则没有问题,很邪门。

1
2
3
4
5
6
7
# 报错Failed to open output file from external program
./extderi $3 $atoms $derivs

# 正常计算
./extderi test $atoms $derivs
cp test $3

怀疑是权限相关的问题,但没有进一步探究,因为感觉三个文件还是有点麻烦,于是合并成了一整个文件,后面也没再出现Failed to open output file from external program的问题

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
!Fixed xtb interface for Gaussian external calls
!Based on original xtb.sh + genxyz + extderi logic
!Written by Dr. Tian Lu at Beijing Kein Research Center for Natural Sciences (www.keinsci.com)

program xtb_interface_fixed
implicit real*8 (a-h,o-z)
parameter (b2a=0.529177249d0)

! Element symbols array (same as original genxyz)
character*2 ind2name(0:86)
data ind2name /"Bq","H ","He", &
"Li","Be","B ","C ","N ","O ","F ","Ne", &
"Na","Mg","Al","Si","P ","S ","Cl","Ar", &
"K ","Ca","Sc","Ti","V ","Cr","Mn","Fe","Co","Ni","Cu","Zn","Ga","Ge","As","Se","Br","Kr", &
"Rb","Sr","Y ","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag","Cd","In","Sn","Sb","Te","I ","Xe", &
"Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy","Ho","Er","Tm","Yb","Lu", &
"Hf","Ta","W ","Re","Os","Ir","Pt","Au","Hg","Tl","Pb","Bi","Po","At","Rn"/

character*256 inputfile,outputfile,cmd,c80
real*8 polar(6)
real*8,allocatable :: ddip(:),hess(:,:)

! Get arguments - handle both 6-arg (Gaussian) and 2-arg (legacy) formats  
nargs = command_argument_count()
if (nargs.eq.6) then
    call get_command_argument(2,inputfile)  ! Second arg is input file
    call get_command_argument(3,outputfile) ! Third arg is output file  
else if (nargs.eq.2) then
    call get_command_argument(1,inputfile)
    call get_command_argument(2,outputfile)
else
    stop
end if

! Read input file (first line: natm derivs charge spin)
open(10,file=inputfile,status='old')
read(10,*) natm,ider,icharge,ispin
close(10)

! Output start message
write(*,*) ">>>>> xTB interface start calculation"

! Generate XYZ file (following original genxyz logic)
open(10,file=inputfile,status='old')  
open(11,file='mol.xyz',status='replace')
read(10,*) natm,ider,icharge,ispin
write(11,*) natm
write(11,*)
do i=1,natm
    read(10,*) idx,x,y,z  ! Read only first 4 fields, ignore MM data
    write(11,*) ind2name(idx),x*b2a,y*b2a,z*b2a
end do
close(10)
close(11)

! Clean up previous files (following original xtb.sh)
call system("rm -f charges energy xtbrestart gradient hessian xtbout")
call system("rm -f xtb_normalmodes g98_canmode.out g98.out wbo xtbhess.coord")

! Run xtb (following original xtb.sh logic)
iuhf = ispin - 1
if (ider.eq.2) then
    write(cmd,'(a,i0,a,i0,a)') "xtb mol.xyz --chrg ",icharge, &
     " --uhf ",iuhf," --hess --grad > xtbout"
else if (ider.eq.1) then  
    write(cmd,'(a,i0,a,i0,a)') "xtb mol.xyz --chrg ",icharge, &
     " --uhf ",iuhf," --grad > xtbout"
else
    write(cmd,'(a,i0,a,i0,a)') "xtb mol.xyz --chrg ",icharge, &
     " --uhf ",iuhf," > xtbout"
end if

call system(cmd)

! Extract results (following original extderi logic)
open(11,file=outputfile,status='replace')

! Extract energy from xtbout (exact format from extderi.f90)
open(10,file='xtbout',status='old')
do while(.true.)
    read(10,'(a)') c80
    if (index(c80,'total energy').ne.0) exit
end do  
close(10)
read(c80,'(30x,f24.12)') ene

! Output Gaussian-style energy line for banelib
write(*,'(" SCF Done:  E(xTB) = ",f15.8)') ene

write(11,'(4d20.12)') ene,0d0,0d0,0d0

! Extract gradients if needed
if (ider.ge.1) then
    open(10,file='gradient',status='old')
    read(10,*)
    read(10,*)
    do iatm=1,natm
        read(10,*)
    end do
    do iatm=1,natm
        read(10,*) fx,fy,fz
        write(11,'(3d20.12)') fx,fy,fz
    end do
    close(10)
end if

! Extract Hessian if needed (following original extderi logic)
if (ider.eq.2) then
    polar=0
    write(11,'(3d20.12)') polar
    allocate(ddip(9*natm))
    ddip=0
    write(11,'(3d20.12)') ddip
    allocate(hess(3*natm,3*natm))
    open(10,file='hessian',status='old')
    read(10,*)
    read(10,*) ((hess(i,j),j=1,3*natm),i=1,3*natm)
    write(11,'(3d20.12)') ((hess(i,j),j=1,i),i=1,3*natm)
    close(10)
end if

close(11)

! Final cleanup (following original xtb.sh)
call system("rm -f charges energy xtbrestart gradient hessian xtbout mol.xyz tmpxx vibspectrum")
call system("rm -f xtb_normalmodes g98_canmode.out g98.out wbo xtbhess.coord .tmpxtbmodef") 
call system("rm -f .engrad *.engrad xtbtopo.mol xtbhess.xyz")

! Output end message
write(*,*) "xTB interface done <<<<<"

end program

编译方法:

1
gfortran -O2 -fdefault-real-8 -o xtb_external xtb_external.f90

其他技巧

如果目标体系hessian非常耗时,但已经得知比较可靠的初猜,可以考虑利用xtb产生初始hessian给过渡态计算读取:

1
2
3
4
5
6
7
8
9
10
%nproc=1
%chk=xtbhess.chk
# freq external='./xtb.sh'

...

--link1--
%oldchk=xtbhess.chk
%chk=ts.chk
# opt=(TS,rcfc,noeigen) freq b3lyp/6-31g* 
This post is licensed under CC BY 4.0 by the author.
Total hits!