LCOV - code coverage report
Current view: top level - src/66_vdwxc - m_vdw_dftd2.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 61.7 % 188 116
Test Date: 2026-11-10 11:05:29 Functions: 100.0 % 2 2
Branches: 39.9 % 291 116

             Branch data     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                 :             : !!***
        

Generated by: LCOV version 2.3-1