Line data Source code
1 : !!****m* ABINIT/m_vdw_dftd2
2 : !! NAME
3 : !! m_vdw_dftd2
4 : !!
5 : !! FUNCTION
6 : !!
7 : !! COPYRIGHT
8 : !! Copyright (C) 2008-2026 ABINIT group (MT)
9 : !! This file is distributed under the terms of the
10 : !! GNU General Public License, see ~abinit/COPYING
11 : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : !!
13 : !! SOURCE
14 :
15 : #if defined HAVE_CONFIG_H
16 : #include "config.h"
17 : #endif
18 :
19 : #include "abi_common.h"
20 :
21 : module m_vdw_dftd2
22 :
23 : use defs_basis
24 : use m_abicore
25 : use m_errors
26 : use m_atomdata
27 :
28 : use m_geometry, only : metric
29 :
30 : implicit none
31 :
32 : private
33 : !!***
34 :
35 : public :: vdw_dftd2
36 : !!***
37 :
38 : contains
39 : !!***
40 :
41 : !!****f* ABINIT/vdw_dftd2
42 : !!
43 : !! NAME
44 : !! vdw_dftd2
45 : !!
46 : !! FUNCTION
47 : !! Compute energy and derivatives with respect to dimensionless
48 : !! reduced atom coordinates due to Van der Waals interaction.
49 : !! The formalism here follows the DFT-D2 approach of Grimme
50 : !! which consists in adding a semi-empirical dispersion potential
51 : !! (pair-wise force field) to the conventional Kohn-Sham DFT energy.
52 : !!
53 : !! INPUTS
54 : !! ixc=choice of exchange-correlation functional
55 : !! natom=number of atoms
56 : !! ntypat=number of atom types
57 : !! prtvol=printing volume (if >0, print computation parameters)
58 : !! typat(natom)=type integer for each atom in cell
59 : !! rprimd(3,3)=real space primitive translations
60 : !! vdw_tol=tolerance use to converge the potential (a pair of atoms is included
61 : !! in potential if its contribution is larger than vdw_tol)
62 : !! vdw_tol<0 takes default value (10^-10)
63 : !! xred(3,natom)=reduced atomic coordinates
64 : !! znucl(ntypat)=atomic number of atom type
65 : !! === optional inputs ===
66 : !! [qphon(3)]=wavevector of the phonon;
67 : !! used only for dynamical matrix computation
68 : !!
69 : !! OUTPUT
70 : !! e_vdw_dftd2=contribution to energy from DFT-D2 dispersion potential
71 : !! === optional outputs ===
72 : !! [dyn_vdw_dftd2(2,3,natom,3,natom)]=contribution to dynamical matrix from DFT-D2 dispersion potential
73 : !! [elt_vdw_dftd2(6+3*natom,6)]=contribution to elastic tensor and internal strains from DFT-D2 disp. pot.
74 : !! [gred_vdw_dftd2(3,natom)]=contribution to gradients wrt nuclear positions from DFT-D2 dispersion potential
75 : !! [str_vdw_dftd2(6)]=contribution to stress tensor from DFT-D2 dispersion potential
76 : !!
77 : !! NOTES
78 : !! Ref.: S. Grimme, Semiempirical GGA-type density functional
79 : !! constructed with a long-range dispersion correction,
80 : !! J. Comp. Chem. 27, 1787 (2006) [[cite:Grimme2006]]
81 : !!
82 : !! SOURCE
83 :
84 40 : subroutine vdw_dftd2(e_vdw_dftd2,ixc,natom,ntypat,prtvol,typat,rprimd,vdw_tol,xred,znucl,&
85 10 : & dyn_vdw_dftd2,elt_vdw_dftd2,gred_vdw_dftd2,str_vdw_dftd2,qphon) ! Optionals
86 :
87 : !Arguments ------------------------------------
88 : !scalars
89 : integer,intent(in) :: ixc,natom,ntypat,prtvol
90 : real(dp),intent(in) :: vdw_tol
91 : real(dp),intent(out) :: e_vdw_dftd2
92 : !arrays
93 : integer,intent(in) :: typat(natom)
94 : real(dp),intent(in) :: rprimd(3,3),xred(3,natom),znucl(ntypat)
95 : real(dp),intent(in),optional :: qphon(3)
96 : real(dp),intent(out),optional :: dyn_vdw_dftd2(2,3,natom,3,natom)
97 : real(dp),intent(out),optional :: elt_vdw_dftd2(6+3*natom,6)
98 : real(dp),intent(out),optional :: gred_vdw_dftd2(3,natom)
99 : real(dp),intent(out),optional :: str_vdw_dftd2(6)
100 :
101 : !Local variables-------------------------------
102 : !scalars
103 : integer,parameter :: vdw_nspecies=55
104 : integer :: ia,ia1,ii,is1,is2,is3,itypat,ja,ja1,jj,jtypat,kk,ll,mu,npairs,nshell,nu
105 : logical :: need_dynmat,need_elast,need_forces,need_intstr,need_stress
106 : logical :: need_gradient,need_gradient2,newshell,qeq0=.true.
107 : real(dp),parameter :: e_conv=(10/Bohr_Ang)**6/Ha_J/Avogadro ! 1 J.nm^6.mol^-1 in Ha.Bohr^6
108 : real(dp),parameter :: vdw_d=20._dp,vdw_tol_default=tol10
109 : real(dp),parameter :: vdw_s_pbe=0.75_dp, vdw_s_blyp=1.2_dp, vdw_s_b3lyp=1.05_dp
110 : real(dp),parameter :: vdw_s_bp86=1.05_dp, vdw_s_tpss=1.0_dp, vdw_s_b97d=1.25_dp
111 : real(dp) :: c6,c6r6,ex,fr,gr,gr2,grad,grad2,ph,ph1r,ph1i
112 : real(dp) :: r0,r1,r2,r3,rcut,rcut2,rsq,rr,sfact,ucvol,vdw_s
113 : character(len=500) :: msg
114 : type(atomdata_t) :: atom
115 : !arrays
116 20 : integer,allocatable :: ivdw(:)
117 : integer,parameter :: alpha(6)=(/1,2,3,3,3,2/),beta(6)=(/1,2,3,2,1,1/)
118 : real(dp) :: gmet(3,3),gprimd(3,3),mat(3,3),rcart(3),rmet(3,3),vec(3)
119 20 : real(dp),allocatable :: vdw_c6(:,:),vdw_r0(:,:),xred01(:,:)
120 : real(dp),parameter :: vdw_c6_dftd2(vdw_nspecies)= &
121 : & (/ 0.14, 0.08, 1.61, 1.61, 3.13, 1.75, 1.23, 0.70, 0.75, 0.63,&
122 : & 5.71, 5.71,10.79, 9.23, 7.84, 5.57, 5.07, 4.61,10.80,10.80,&
123 : & 10.80,10.80,10.80,10.80,10.80,10.80,10.80,10.80,10.80,10.80,&
124 : & 16.99,17.10,16.37,12.64,12.47,12.01,24.67,24.67,24.67,24.67,&
125 : & 24.67,24.67,24.67,24.67,24.67,24.67,24.67,24.67,37.32,38.71,&
126 : & 38.44,31.74,31.50,29.99, 0.00/)
127 : real(dp),parameter :: vdw_r0_dftd2(vdw_nspecies)= &
128 : & (/1.001,1.012,0.825,1.408,1.485,1.452,1.397,1.342,1.287,1.243,&
129 : & 1.144,1.364,1.639,1.716,1.705,1.683,1.639,1.595,1.485,1.474,&
130 : & 1.562,1.562,1.562,1.562,1.562,1.562,1.562,1.562,1.562,1.562,&
131 : & 1.650,1.727,1.760,1.771,1.749,1.727,1.628,1.606,1.639,1.639,&
132 : & 1.639,1.639,1.639,1.639,1.639,1.639,1.639,1.639,1.672,1.804,&
133 : & 1.881,1.892,1.892,1.881,1.000/)
134 : character(len=2),parameter :: vdw_symb(vdw_nspecies)= &
135 : & (/' H','He','Li','Be',' B',' C',' N',' O',' F','Ne',&
136 : & 'Na','Mg','Al','Si',' P',' S','Cl','Ar',' K','Ca',&
137 : & 'Sc','Ti',' V','Cr','Mn','Fe','Co','Ni','Cu','Zn',&
138 : & 'Ga','Ge','As','Se','Br','Kr','Rb','Sr',' Y','Zr',&
139 : & 'Nb','Mo','Tc','Ru','Rh','Pd','Ag','Cd','In','Sn',&
140 : & 'Sb','Te',' I','Xe','no'/)
141 :
142 : ! *************************************************************************
143 :
144 : DBG_ENTER("COLL")
145 :
146 : !Extract options
147 20 : need_forces=present(gred_vdw_dftd2)
148 20 : need_stress=present(str_vdw_dftd2)
149 20 : need_dynmat=present(dyn_vdw_dftd2)
150 20 : need_elast=present(elt_vdw_dftd2)
151 20 : need_intstr=present(elt_vdw_dftd2)
152 20 : need_gradient=(need_forces.or.need_stress)
153 20 : need_gradient2=(need_dynmat.or.need_elast.or.need_intstr)
154 20 : if (need_dynmat) then
155 0 : if (.not.present(qphon)) then
156 0 : msg='Dynamical matrix required without a q-vector'
157 0 : ABI_BUG(msg)
158 : end if
159 0 : qeq0=(qphon(1)**2+qphon(2)**2+qphon(3)**2<1.d-15)
160 : end if
161 :
162 : !Identify type(s) of atoms
163 60 : ABI_MALLOC(ivdw,(ntypat))
164 40 : do itypat=1,ntypat
165 20 : ivdw(itypat)=-1;jtypat=0
166 20 : call atomdata_from_znucl(atom,znucl(itypat))
167 380 : do while ((ivdw(itypat)<0).and.(jtypat<vdw_nspecies))
168 380 : jtypat=jtypat+1;if (vdw_symb(jtypat)==atom%symbol) ivdw(itypat)=jtypat
169 : end do
170 60 : if (ivdw(itypat)<0) then
171 : write(msg,'(3a)') &
172 0 : & 'Van der Waals DFT-D2 correction not available for atom type: ',atom%symbol,' !'
173 0 : ABI_ERROR(msg)
174 : end if
175 : end do
176 :
177 : !Select DFT-D2 VdW parameters according to system data
178 20 : vdw_s=e_conv
179 20 : if (ixc==11.or.ixc==-101130.or.ixc==-130101) then
180 : vdw_s=vdw_s*vdw_s_pbe
181 : else if (ixc==18.or.ixc==-106131.or.ixc==-131106) then
182 : vdw_s=vdw_s*vdw_s_blyp
183 : else if (ixc==19.or.ixc==-106132.or.ixc==-132106) then
184 : vdw_s=vdw_s*vdw_s_bp86
185 : else if (ixc==-202231.or.ixc==-231202) then
186 : vdw_s=vdw_s*vdw_s_tpss
187 : else
188 0 : write(msg,'(a,i8,a)')' Van der Waals DFT-D2 correction not compatible with ixc=',ixc,' !'
189 0 : ABI_ERROR(msg)
190 : end if
191 80 : ABI_MALLOC(vdw_c6,(ntypat,ntypat))
192 60 : ABI_MALLOC(vdw_r0,(ntypat,ntypat))
193 40 : do itypat=1,ntypat
194 60 : do jtypat=1,ntypat
195 20 : vdw_c6(itypat,jtypat)=sqrt(vdw_c6_dftd2(ivdw(itypat))*vdw_c6_dftd2(ivdw(jtypat)))
196 40 : vdw_r0(itypat,jtypat)=(vdw_r0_dftd2(ivdw(itypat))+vdw_r0_dftd2(ivdw(jtypat)))/Bohr_Ang
197 : end do
198 : end do
199 :
200 : !Computation of cut-off radius according to tolerance
201 : !We take: r_cut=(s6*max(C6)/tol)**(1/6) and rcut<=75 bohr
202 20 : if (vdw_tol<zero) then
203 0 : rcut=(vdw_s/vdw_tol_default*maxval(vdw_c6))**sixth
204 : else
205 60 : rcut=(vdw_s/vdw_tol*maxval(vdw_c6))**sixth
206 : end if
207 : !rcut=min(rcut,100._dp)
208 20 : rcut2=rcut*rcut
209 :
210 : !Retrieve cell geometry data
211 20 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
212 :
213 : !Map reduced coordinates into [0,1]
214 60 : ABI_MALLOC(xred01,(3,natom))
215 40 : do ia=1,natom
216 20 : xred01(1,ia)=xred(1,ia)-aint(xred(1,ia))+half-sign(half,xred(1,ia))
217 20 : xred01(2,ia)=xred(2,ia)-aint(xred(2,ia))+half-sign(half,xred(2,ia))
218 40 : xred01(3,ia)=xred(3,ia)-aint(xred(3,ia))+half-sign(half,xred(3,ia))
219 : end do
220 :
221 : !Set accumulated quantities to zero
222 20 : npairs=0
223 20 : e_vdw_dftd2=zero
224 60 : if (need_forces) gred_vdw_dftd2=zero
225 20 : if (need_stress) str_vdw_dftd2=zero
226 20 : if (need_dynmat) dyn_vdw_dftd2=zero
227 20 : if (need_elast) elt_vdw_dftd2(1:6,1:6)=zero
228 0 : if (need_intstr) elt_vdw_dftd2(7:6+3*natom,1:6)=zero
229 :
230 : !Loop over shells of cell replicas
231 : nshell=0
232 : do
233 140 : newshell=.false.;nshell=nshell+1
234 :
235 : ! Loop over cell replicas in the shell
236 : ! ns1=1+int(rcut*sqrt(SUM(gprimd(:,1)**2))
237 : ! ns2=1+int(rcut*sqrt(SUM(gprimd(:,2)**2))
238 : ! ns3=1+int(rcut*sqrt(SUM(gprimd(:,3)**2))
239 1400 : do is3=-nshell,nshell
240 14980 : do is2=-nshell,nshell
241 177380 : do is1=-nshell,nshell
242 : if (nshell==1.or. &
243 176120 : & abs(is3)==nshell.or.abs(is2)==nshell.or.abs(is1)==nshell) then
244 :
245 : ! Phase for dynamical matrix
246 67500 : if (need_dynmat) then
247 0 : ph1r=one;ph1i=zero !ph1=exp(-iqL)
248 0 : if (.not.qeq0) then
249 0 : ph=-two_pi*(qphon(1)*is1+qphon(2)*is2+qphon(3)*is3)
250 0 : ph1r=cos(ph);ph1i=sin(ph)
251 : end if
252 : end if
253 :
254 : ! Loops over atoms a and b
255 135000 : do ia=1,natom
256 67500 : itypat=typat(ia)
257 297540 : do ja=1,ia
258 67500 : jtypat=typat(ja)
259 67500 : r1=xred01(1,ia)-xred01(1,ja)-dble(is1)
260 67500 : r2=xred01(2,ia)-xred01(2,ja)-dble(is2)
261 67500 : r3=xred01(3,ia)-xred01(3,ja)-dble(is3)
262 : rsq=rmet(1,1)*r1*r1+rmet(2,2)*r2*r2+rmet(3,3)*r3*r3 &
263 67500 : & +two*(rmet(2,1)*r2*r1+rmet(3,2)*r3*r2+rmet(3,1)*r1*r3)
264 :
265 : ! Select atomic pairs (a,b) and avoid atom_a=atom_b
266 135000 : if (rsq>=tol16.and.rsq<=rcut2) then
267 :
268 : ! Data for the selected pair
269 15416 : npairs=npairs+1;newshell=.true.
270 15416 : sfact=vdw_s;if (ia==ja) sfact=half*sfact
271 15416 : rr=sqrt(rsq)
272 15416 : c6=vdw_c6(itypat,jtypat)
273 15416 : r0=vdw_r0(itypat,jtypat)
274 :
275 : ! Computation of pair-wise potential
276 15416 : ex=exp(-vdw_d*(rr/r0-one))
277 15416 : fr=one/(one+ex)
278 15416 : c6r6=c6/rr**6
279 :
280 : ! Contribution to energy
281 15416 : e_vdw_dftd2=e_vdw_dftd2-sfact*fr*c6r6
282 :
283 15416 : if (need_gradient.or.need_gradient2) then
284 15416 : gr=(vdw_d/r0)*(fr**2)*ex
285 15416 : grad=-sfact*(gr-six*fr/rr)*c6r6/rr
286 15416 : rcart(1)=rprimd(1,1)*r1+rprimd(1,2)*r2+rprimd(1,3)*r3
287 15416 : rcart(2)=rprimd(2,1)*r1+rprimd(2,2)*r2+rprimd(2,3)*r3
288 15416 : rcart(3)=rprimd(3,1)*r1+rprimd(3,2)*r2+rprimd(3,3)*r3
289 :
290 : ! Contribution to gradients wrt nuclear positions
291 15416 : if (need_forces.and.ia/=ja) then
292 0 : vec(1:3)=grad*rcart(1:3)
293 0 : gred_vdw_dftd2(1:3,ia)=gred_vdw_dftd2(1:3,ia)+vec(1:3)
294 0 : gred_vdw_dftd2(1:3,ja)=gred_vdw_dftd2(1:3,ja)-vec(1:3)
295 : end if
296 :
297 : ! Contribution to stress tensor
298 15416 : if (need_stress) then
299 53956 : do mu=1,6
300 46248 : ii=alpha(mu);jj=beta(mu)
301 53956 : str_vdw_dftd2(mu)=str_vdw_dftd2(mu)+grad*rcart(ii)*rcart(jj)
302 : end do
303 : end if
304 :
305 15416 : if (need_gradient2) then
306 0 : gr2=(vdw_d/r0)*gr*(2*fr*ex-one)
307 0 : grad2=-sfact*(gr2-13._dp*gr/rr+48._dp*fr/rr**2)*c6r6/rr**2
308 :
309 : ! Contribution to dynamical matrix (phase factors are subtle!)
310 0 : if (need_dynmat) then
311 0 : mat(1:3,1)=grad2*rcart(1:3)*rcart(1) ; mat(1,1)=mat(1,1)+grad
312 0 : mat(1:3,2)=grad2*rcart(1:3)*rcart(2) ; mat(2,2)=mat(2,2)+grad
313 0 : mat(1:3,3)=grad2*rcart(1:3)*rcart(3) ; mat(3,3)=mat(3,3)+grad
314 0 : if (ia/=ja) then
315 0 : do ii=1,3
316 0 : dyn_vdw_dftd2(1,1:3,ia,ii,ia)=dyn_vdw_dftd2(1,1:3,ia,ii,ia)+mat(1:3,ii)
317 0 : dyn_vdw_dftd2(1,1:3,ja,ii,ja)=dyn_vdw_dftd2(1,1:3,ja,ii,ja)+mat(1:3,ii)
318 0 : dyn_vdw_dftd2(1,1:3,ia,ii,ja)=dyn_vdw_dftd2(1,1:3,ia,ii,ja)-mat(1:3,ii)*ph1r
319 0 : dyn_vdw_dftd2(2,1:3,ia,ii,ja)=dyn_vdw_dftd2(2,1:3,ia,ii,ja)-mat(1:3,ii)*ph1i
320 0 : dyn_vdw_dftd2(1,1:3,ja,ii,ia)=dyn_vdw_dftd2(1,1:3,ja,ii,ia)-mat(1:3,ii)*ph1r
321 0 : dyn_vdw_dftd2(2,1:3,ja,ii,ia)=dyn_vdw_dftd2(2,1:3,ja,ii,ia)+mat(1:3,ii)*ph1i
322 : end do
323 0 : else if (.not.qeq0) then
324 0 : do ii=1,3
325 : dyn_vdw_dftd2(1,1:3,ia,ii,ia)=dyn_vdw_dftd2(1,1:3,ia,ii,ia) &
326 0 : & +two*mat(1:3,ii)*(one-ph1r)
327 : end do
328 : end if
329 : end if
330 :
331 : ! Contribution to elastic tensor
332 0 : if (need_elast) then
333 0 : do mu=1,6
334 0 : ii=alpha(mu);jj=beta(mu)
335 0 : do nu=1,6
336 0 : kk=alpha(nu);ll=beta(nu)
337 : elt_vdw_dftd2(mu,nu)=elt_vdw_dftd2(mu,nu) &
338 0 : & +grad2*rcart(ii)*rcart(jj)*rcart(kk)*rcart(ll)
339 0 : if (ii==kk) elt_vdw_dftd2(mu,nu)=elt_vdw_dftd2(mu,nu) &
340 0 : & +half*grad*rcart(jj)*rcart(ll)
341 0 : if (ii==ll) elt_vdw_dftd2(mu,nu)=elt_vdw_dftd2(mu,nu) &
342 0 : & +half*grad*rcart(jj)*rcart(kk)
343 0 : if (jj==kk) elt_vdw_dftd2(mu,nu)=elt_vdw_dftd2(mu,nu) &
344 0 : & +half*grad*rcart(ii)*rcart(ll)
345 0 : if (jj==ll) elt_vdw_dftd2(mu,nu)=elt_vdw_dftd2(mu,nu) &
346 0 : & +half*grad*rcart(ii)*rcart(kk)
347 : end do
348 : end do
349 : end if
350 :
351 : ! Contribution to internal strains
352 0 : if (need_intstr.and.ia/=ja) then
353 0 : ia1=6+3*(ia-1);ja1=6+3*(ja-1)
354 0 : do mu=1,6
355 0 : ii=alpha(mu);jj=beta(mu)
356 0 : vec(1:3)=grad2*rcart(ii)*rcart(jj)*rcart(1:3)
357 0 : vec(ii)=vec(ii)+half*grad*rcart(jj)
358 0 : vec(jj)=vec(jj)+half*grad*rcart(ii)
359 0 : elt_vdw_dftd2(ia1+1:ia1+3,mu)=elt_vdw_dftd2(ia1+1:ia1+3,mu)+vec(1:3)
360 0 : elt_vdw_dftd2(ja1+1:ja1+3,mu)=elt_vdw_dftd2(ja1+1:ja1+3,mu)-vec(1:3)
361 : end do
362 : end if
363 :
364 : end if ! Computation of 2nd gradient
365 : end if ! Computation of gradient
366 : end if ! Pairs selection
367 : end do ! Loop over atom b
368 : end do ! Loop over atom a
369 : end if ! Triple loop over cell replicas in shell
370 : end do
371 : end do
372 : end do
373 140 : if(.not.newshell) exit ! Check if new shell must be calculated
374 : end do ! Loop over shells
375 :
376 : !Gradients: convert them from cartesian to reduced coordinates
377 20 : if (need_forces) then
378 20 : do ia=1,natom
379 20 : call grad_cart2red(gred_vdw_dftd2(:,ia))
380 : end do
381 : end if
382 20 : if (need_dynmat) then
383 0 : do ja=1,natom
384 0 : do ia=1,natom
385 0 : do kk=1,merge(2,1,qeq0)
386 0 : do ii=1,3
387 0 : vec(1:3)=dyn_vdw_dftd2(kk,1:3,ia,ii,ja)
388 0 : call grad_cart2red(vec)
389 0 : dyn_vdw_dftd2(kk,1:3,ia,ii,ja)=vec(1:3)
390 : end do
391 0 : do ii=1,3
392 0 : vec(1:3)=dyn_vdw_dftd2(kk,ii,ia,1:3,ja)
393 0 : call grad_cart2red(vec)
394 0 : dyn_vdw_dftd2(kk,ii,ia,1:3,ja)=vec(1:3)
395 : end do
396 : end do
397 : end do
398 : end do
399 : end if
400 20 : if (need_intstr) then
401 0 : do mu=1,6
402 : ia1=6
403 0 : do ia=1,natom
404 0 : call grad_cart2red(elt_vdw_dftd2(ia1+1:ia1+3,mu))
405 0 : ia1=ia1+3
406 : end do
407 : end do
408 : end if
409 :
410 : !DEBUG
411 : !write(77,*) "---------------"
412 : !write(77,*) "E=",e_vdw_dftd2
413 : !if (need_forces) then
414 : ! do ia=1,natom
415 : ! write(77,*) "F=",ia,gred_vdw_dftd2(:,ia)
416 : ! end do
417 : !end if
418 : !if (need_stress) write(77,*) "S=",str_vdw_dftd2(:)
419 : !if (need_dynmat) then
420 : ! do ia=1,natom
421 : ! do ii=1,3
422 : ! do ja=1,natom
423 : ! write(77,*) "D=",ia,ii,ja,dyn_vdw_dftd2(:,:,ja,ii,ia)
424 : ! end do
425 : ! end do
426 : ! end do
427 : !end if
428 : !if (need_elast) then
429 : ! do ii=1,6
430 : ! write(77,*) "e=",ii,elt_vdw_dftd2(1:6,ii)
431 : ! end do
432 : !end if
433 : !if (need_intstr) then
434 : ! do ii=1,6
435 : ! do ia=1,natom
436 : ! write(77,*) "I=",ii,ia,elt_vdw_dftd2(7+3*(ia-1):9+3*(ia-1),ii)
437 : ! end do
438 : ! end do
439 : !end if
440 : !flush(77)
441 : !DEBUG
442 :
443 : !Stress tensor: divide by volume
444 80 : if (need_stress) str_vdw_dftd2=str_vdw_dftd2/ucvol
445 :
446 : !Printing
447 20 : if (prtvol>0) then
448 10 : write(msg,'(10a)') ch10,&
449 10 : & ' --------------------------------------------------------------',ch10,&
450 10 : & ' Van der Waals DFT-D2 semi-empirical dispersion potential added',ch10,&
451 10 : & ' with following parameters:',ch10,&
452 10 : & ' Specie C6 (J.nm^6.mol^-1) R0 (Ang)',ch10,&
453 20 : & ' ------------------------------------'
454 10 : call wrtout(std_out,msg,'COLL')
455 20 : do itypat=1,ntypat
456 : write(msg,'(9X,a2,11X,f5.2,8X,f6.3)') &
457 10 : & vdw_symb(ivdw(itypat)),vdw_c6_dftd2(ivdw(itypat)),vdw_r0_dftd2(ivdw(itypat))
458 20 : call wrtout(std_out,msg,'COLL')
459 : end do
460 10 : write(msg,'(2a,f6.2,2a,f6.2,2a,f6.2,a)') ch10,&
461 10 : & ' Scaling factor = ',vdw_s/e_conv,ch10,&
462 10 : & ' Damping parameter= ',vdw_d,ch10,&
463 20 : & ' Cut-off radius = ',rcut,' bohr'
464 10 : call wrtout(std_out,msg,'COLL')
465 10 : write(msg,'(2a,i14,2a,es14.5,4a)') ch10,&
466 10 : & ' Number of pairs contributing = ',npairs,ch10,&
467 10 : & ' DFT-D2 energy contribution = ',e_vdw_dftd2,' Ha',ch10,&
468 20 : & ' --------------------------------------------------------------',ch10
469 10 : call wrtout(std_out,msg,'COLL')
470 : end if
471 :
472 20 : ABI_FREE(ivdw)
473 20 : ABI_FREE(vdw_c6)
474 20 : ABI_FREE(vdw_r0)
475 50 : ABI_FREE(xred01)
476 :
477 : DBG_EXIT("COLL")
478 :
479 : contains
480 : !!***
481 :
482 : !!****f* vdw_dftd2/grad_cart2red
483 : !!
484 : !! NAME
485 : !! grad_cart2red
486 : !!
487 : !! FUNCTION
488 : !! Convert gradients from cartesian to reduced coordinates
489 : !!
490 : !! SOURCE
491 :
492 10 : subroutine grad_cart2red(grad)
493 :
494 : !Arguments ------------------------------------
495 : real(dp),intent(inout) :: grad(3)
496 : !Local variables-------------------------------
497 : real(dp) :: tmp(3)
498 :
499 : ! *********************************************************************
500 :
501 10 : tmp(1)=rprimd(1,1)*grad(1)+rprimd(2,1)*grad(2)+rprimd(3,1)*grad(3)
502 10 : tmp(2)=rprimd(1,2)*grad(1)+rprimd(2,2)*grad(2)+rprimd(3,2)*grad(3)
503 10 : tmp(3)=rprimd(1,3)*grad(1)+rprimd(2,3)*grad(2)+rprimd(3,3)*grad(3)
504 10 : grad(1:3)=tmp(1:3)
505 :
506 10 : end subroutine grad_cart2red
507 : !!***
508 :
509 : end subroutine vdw_dftd2
510 : !!***
511 :
512 : end module m_vdw_dftd2
513 : !!***
|