2
c empirical dispersion: derivatives
4
subroutine nwxc_vdw_der(s6,s8,sr6,sr8,n,x,z,force)
6
c S. Grimme J Comp Chem 25, 1463 (2004)
7
c U. Zimmerli, M Parrinello and P. Koumoutsakos, JCP. 120, 2693 (2004)
8
c Q. Wu and W. Yang, JCP. 116, 515 (2002)
12
#include "mafdecls.fh"
14
#include "nwxc_vdw.fh"
17
double precision s6,s8,sr6,sr8
19
double precision x(3,n),force(3,n)
22
integer i,j,k,A,l_cnij,k_cnij,l_cnijk,k_cnijk
23
double precision c6ij_sk
25
double precision drajdxa
26
double precision ff1,rr,ff
27
double precision fdmp,f1dmp,cnA,cnj
29
double precision c6cn,crd_nr
30
double precision fac6,fac8,fdmp6,fdmp6a,fdmp8,fdmp8a,Qfac
31
double precision rAj,rAk,rjk,r0aj,r0ak,r0jk,c6Aj,grad_c6(3)
32
double precision dxAj,dyAj,dzAj,dxAk,dyAk,dzAk,dxjk,dyjk,dzjk
33
double precision tmp6,tmp6a,tmp8,tmp8a
35
c Derivatives of Grimme dispersion term
48
+ (x(1,A)-x(1,j))**2 +
49
+ (x(2,A)-x(2,j))**2 +
51
r0aj=r0(z(A))+r0(z(j))
53
ff1= f1dmp(rAj,r0aj,ff)
54
rr=c6ij_sk(A,j,z)/(rAj**6)*
57
drAjdxa=(x(i,A)-x(i,j))/rAj
58
force(i,A)=force(i,A)-rr*drAjdxa
64
if(abs(s6-1d0).gt.1d-9)
65
F call dscal(3*n,s6,force,1)
69
else if (ivdw.eq.3) then
71
c Precompute coordinate derivatives C6 dependency
73
if (.not.ma_push_get(mt_dbl,3*n,'xcvdw cnij',l_cnij,k_cnij))
74
& call errquit('xcvdw cnij: cannot allocate cnij',0, MA_ERR)
75
if (.not.ma_push_get(mt_dbl,3*n*n,'vdw cnijk',l_cnijk,k_cnijk))
76
& call errquit('vdw cnijk: cannot allocate cnijk',0, MA_ERR)
78
call crd_nr_der(n,x,z,dbl_mb(k_cnij),dbl_mb(k_cnijk))
90
rAj=dxAj**2+dyAj**2+dzAj**2
92
c Two center derivatives. Grimme uses screening to reduce
95
c Screening r^2 distance vs threshold of 20000.0
97
if (rAj.gt.20000.d0) goto 901
102
Qfac=Qatom(z(A))*Qatom(z(j))
103
fac6=(dsqrt(rAj)/(sr6*r0aj))**(-alpha)
104
fac8=(dsqrt(rAj)/(sr8*r0aj))**(-(alpha+2.0d0))
105
fdmp6=1.0d0/(1.0d0+6.0d0*fac6)
106
fdmp8=1.0d0/(1.0d0+6.0d0*fac8)
108
c Coordination dependent C6_AB value
112
c6Aj=c6cn(z(A),z(j),cnA,cnj)
114
c Get gradient for coordination number dependent C6
116
call c6_grad(grad_c6,A,j,A,x,z,n,
117
& dbl_mb(k_cnij),dbl_mb(k_cnijk))
119
tmp6=6.0d0*fdmp6*s6*c6Aj/(rAj**4.0d0)
120
tmp8=6.0d0*fdmp8*s8*c6Aj*Qfac/(rAj**5.0d0)
122
c dx contribution to A
126
force(1,A)=force(1,A)
127
$ +(1.0d0-fdmp6*fac6*alpha)*tmp6a
128
$ -fdmp6*s6*grad_c6(1)/(rAj**3.0d0)
129
$ +(4.0d0-3.0d0*fdmp8*fac8*(alpha+2.0d0))*tmp8a
130
$ -3.0d0*fdmp8*s8*grad_c6(1)*Qfac/(rAj**4.0d0)
132
c dy contribution to A
136
force(2,A)=force(2,A)
137
$ +(1.0d0-fdmp6*fac6*alpha)*tmp6a
138
$ -fdmp6*s6*grad_c6(2)/(rAj**3.0d0)
139
$ +(4.0d0-3.0d0*fdmp8*fac8*(alpha+2.0d0))*tmp8a
140
$ -3.0d0*fdmp8*s8*grad_c6(2)*Qfac/(rAj**4.0d0)
142
c dz contribution to A
146
force(3,A)=force(3,A)
147
$ +(1.0d0-fdmp6*fac6*alpha)*tmp6a
148
$ -fdmp6*s6*grad_c6(3)/(rAj**3.0d0)
149
$ +(4.0d0-3.0d0*fdmp8*fac8*(alpha+2.0d0))*tmp8a
150
$ -3.0d0*fdmp8*s8*grad_c6(3)*Qfac/(rAj**4.0d0)
155
c Three center derivatives. Grimme uses aggressive screening
156
c to get this N^3 contribution back to N^2
161
+ (x(1,A)-x(1,j))**2 +
162
+ (x(2,A)-x(2,j))**2 +
163
+ (x(3,A)-x(3,j))**2)
166
c Screening per Grimme
168
if (rAj.gt.1600d0*r0aj/r0AB(1,1)) goto 910
170
c Third center involved
177
rAk=dxAk**2+dyAk**2+dzAk**2
182
rjk=dxjk**2+dyjk**2+dzjk**2
185
c Screening r^2 distance vs threshold of 1600.0*(radii Ak)
187
if ((rAk.gt.1600.0d0*r0ak/r0AB(1,1)).or.
188
$ (rjk.gt.1600.0d0*r0jk/r0AB(1,1))) goto 911
190
c Get gradient for coordination number dependent C6 for three centers
192
call c6_grad(grad_c6,j,k,A,x,z,n,
193
& dbl_mb(k_cnij),dbl_mb(k_cnijk))
194
fac6=(sr6*r0jk/dsqrt(rjk))**(alpha)
195
fac8=(sr8*r0jk/dsqrt(rjk))**(alpha+2.0d0)
196
fdmp6=1.0d0/(1.0d0+6.0d0*fac6)
197
fdmp8=1.0d0/(1.0d0+6.0d0*fac8)
199
c dx, dy, and dz contribution to A
201
Qfac=Qatom(z(j))*Qatom(z(k))
202
force(1,A)=force(1,A)
203
$ -fdmp6*s6*grad_c6(1)/(rjk**3.0d0)
204
$ -3.0d0*fdmp8*s8*grad_c6(1)*Qfac/(rjk**4.0d0)
205
force(2,A)=force(2,A)
206
$ -fdmp6*s6*grad_c6(2)/(rjk**3.0d0)
207
$ -3.0d0*fdmp8*s8*grad_c6(2)*Qfac/(rjk**4.0d0)
208
force(3,A)=force(3,A)
209
$ -fdmp6*s6*grad_c6(3)/(rjk**3.0d0)
210
$ -3.0d0*fdmp8*s8*grad_c6(3)*Qfac/(rjk**4.0d0)
219
if (.not.ma_pop_stack(l_cnijk))
220
$ call errquit('xcvdw cnijk: cannot pop cnijk',4, MA_ERR)
221
if (.not.ma_pop_stack(l_cnij))
222
$ call errquit('xcvdw cnij: cannot pop cnij',4, MA_ERR)
226
write(6,*) ' gradient vdw called'