LCOV - code coverage report
Current view: top level - src/41_geometry - m_ewald.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.8 % 698 641
Test Date: 2026-09-19 17:42:43 Functions: 100.0 % 4 4

            Line data    Source code
       1              : !!****m* ABINIT/m_ewald
       2              : !! NAME
       3              : !!  m_ewald
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module gathers routines to compute the Ewald energy and its derivatives
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2014-2026 ABINIT group (DCA, XG, JJC, GMR)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_ewald
      23              : 
      24              :  use defs_basis
      25              :  use m_abicore
      26              :  use m_errors
      27              :  use m_splines
      28              :  use m_time
      29              :  use m_xmpi
      30              : 
      31              :  use m_gtermcutoff,    only : termcutoff
      32              :  use m_special_funcs,  only : abi_derfc
      33              :  use m_matrix,         only : matr3inv
      34              : 
      35              :  implicit none
      36              : 
      37              :  private
      38              : 
      39              :  public :: ewald    ! Compute Ewald energy and derivatives with respect to xred
      40              :  public :: ewald2   ! Derivative of the Ewald energy with respect to strain.
      41              :  public :: ewald9   ! Compute ewald contribution to the dynamical matrix, at a given
      42              :                     ! q wavevector, including anisotropic dielectric tensor and effective charges
      43              :  public :: ewald9_2D! Compute ewald contribution to the dynamical matrix, at a given
      44              :             ! q wavevector, in the case of a 2D material with an external
      45              :             ! dielectric environment
      46              : 
      47              : contains
      48              : !!***
      49              : 
      50              : !!****f* m_ewald/ewald
      51              : !!
      52              : !! NAME
      53              : !! ewald
      54              : !!
      55              : !! FUNCTION
      56              : !! Compute Ewald energy and derivatives with respect to dimensionless
      57              : !! reduced atom coordinates xred.
      58              : !!
      59              : !! INPUTS
      60              : !! gmet(3,3)=metric tensor in reciprocal space (bohr^-2)
      61              : !! natom=number of atoms in unit cell
      62              : !! ntypat=numbe of type of atoms
      63              : !! rmet(3,3)=metric tensor in real space (bohr^2)
      64              : !! typat(natom)=integer label of each type of atom (1,2,...)
      65              : !! ucvol=unit cell volume (bohr^3)
      66              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
      67              : !! zion(ntypat)=charge on each type of atom (real number)
      68              : !!
      69              : !! OUTPUT
      70              : !! eew=final ewald energy in hartrees
      71              : !! grewtn(3,natom)=grads of eew wrt xred(3,natom), hartrees.
      72              : !!
      73              : !! SOURCE
      74              : 
      75         7644 : subroutine ewald(eew,gmet,grewtn,gsqcut,icutcoul,natom,ngfft,nkpt,ntypat,rcut,&
      76         7644 :                  rmet,rprimd,typat,ucvol,vcutgeo,xred,zion)
      77              : 
      78              : !Arguments ------------------------------------
      79              : !scalars
      80              :  integer,intent(in) :: icutcoul,natom,nkpt,ntypat
      81              :  real(dp),intent(in) :: gsqcut,rcut,ucvol
      82              :  real(dp),intent(out) :: eew
      83              : !arrays
      84              :  integer,intent(in) :: ngfft(18),typat(natom)
      85              :  real(dp),intent(in) :: gmet(3,3),rmet(3,3),rprimd(3,3),xred(3,natom),vcutgeo(3),zion(ntypat)
      86              :  real(dp),intent(out) :: grewtn(3,natom)
      87              : 
      88              : !Local variables-------------------------------
      89              : !scalars
      90              :  integer  :: ia,ib,ig1,ig2,ig3,ig23,ii,ir1,ir2,ir3,newg,newr,ng,nr
      91              :  real(dp) :: arg,c1i,ch,chsq,derfc_arg,direct,drdta1,drdta2,drdta3,eta,fac
      92              :  real(dp) :: fraca1,fraca2,fraca3,fracb1,fracb2,fracb3,gsq,gsum,phi,phr,r1
      93              :  real(dp) :: minexparg
      94              :  real(dp) :: r1a1d,r2,r2a2d,r3,r3a3d,recip,reta,rmagn,rsq,sumg,summi,summr,sumr
      95              :  real(dp) :: t1,term ,zcut !, gcart_para, gcart_perp
      96              :  !character(len=500) :: msg
      97              : !arrays
      98         7644 :  real(dp),allocatable :: gcutoff(:)
      99              : ! *************************************************************************
     100              : 
     101              : !This is the minimum argument of an exponential, with some safety
     102         7644 :  minexparg=log(tiny(0._dp))+five
     103              : 
     104              : !Add up total charge and sum of $charge^2$ in cell
     105              : 
     106         7644 :  chsq=0._dp
     107         7644 :  ch=0._dp
     108        29994 :  do ia=1,natom
     109        22350 :    ch=ch+zion(typat(ia))
     110        29994 :    chsq=chsq+zion(typat(ia))**2
     111              :  end do
     112              : 
     113              :  !Compute eta, the Ewald summation convergence parameter,
     114              :  ! for approximately optimized summations:
     115              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
     116         7644 :         rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
     117              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
     118         7644 :        gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
     119              : 
     120              : !A bias is introduced, because G-space summation scales
     121              : !better than r space summation ! Note: debugging is the most easier at fixed eta.
     122              : zcut=SQRT(DOT_PRODUCT(rprimd(:,3),rprimd(:,3)))/2.0_dp
     123         7644 : if(icutcoul.eq.1) then
     124            0 :    eta=SQRT(16.0_dp/SQRT(DOT_PRODUCT(rprimd(:,1),rprimd(:,1))))
     125              : ! else if (icutcoul.eq.2) then
     126              : !   zcut=SQRT(DOT_PRODUCT(rprimd(:,3),rprimd(:,3)))/2.0_dp
     127              : !   eta=217.6_dp/zcut**2.0_dp
     128              : !   eta=1.0_dp/zcut**2.0_dp
     129              : !   eta=SQRT(16.0_dp/SQRT(DOT_PRODUCT(rprimd(:,1),rprimd(:,1))))
     130              : ! else if (icutcoul.eq.2) then
     131              : !   zcut=SQRT(DOT_PRODUCT(rprimd(:,3),rprimd(:,3)))/2.0_dp
     132              : !   eta=SQRT(8.0_dp/zcut)
     133              : !   eta=SQRT(16.0_dp/SQRT(DOT_PRODUCT(rprimd(:,1),rprimd(:,1))))
     134              : ! else if (icutcoul.eq.2) then
     135              : !   zcut=SQRT(DOT_PRODUCT(rprimd(:,3),rprimd(:,3)))/2.0_dp
     136              : !   eta=SQRT(8.0_dp/zcut)
     137              :  else
     138         7644 :    eta=pi*200.0_dp/33.0_dp*sqrt(1.69_dp*recip/direct)
     139              :  end if
     140              : 
     141              : !Conduct reciprocal space summations
     142         7644 :  fac=pi**2/eta
     143         7644 :  gsum=0._dp
     144        97044 :  grewtn(:,:)=0.0_dp
     145              : 
     146              :  !Initialize Gcut-off array from m_gtermcutoff
     147              :  !ABI_MALLOC(gcutoff,(ngfft(1)*ngfft(2)*ngfft(3)))
     148         7644 :  call termcutoff(gcutoff,gsqcut,icutcoul,ngfft,nkpt,rcut,rprimd,vcutgeo)
     149              : 
     150              : !if (icutcoul.eq.3) then
     151              : !Sum over G space, done shell after shell until all
     152              : !contributions are too small.
     153         7644 :  ng=0
     154              :  do
     155       318596 :    ng=ng+1
     156       318596 :    newg=0
     157              : !   Instead of this warning that most normal users do not understand (because they are doing GS calculations, and not RF calculations),
     158              : !   one should optimize this routine. But usually this is a very small fraction of any ABINIT run.
     159              : !   if (ng > 20 .and. mod(ng,10)==0) then
     160              : !      write (msg,'(3a,I10)') "Very large box of G neighbors in ewald: you probably do not want to do this.", ch10,&
     161              : !&       " If you have a metal consider setting dipdip 0.  ng = ", ng
     162              : !      ABI_WARNING(msg)
     163              : !   end if
     164       318596 :    ii=1
     165     15902136 :    do ig3=-ng,ng
     166   1241482172 :      do ig2=-ng,ng
     167  >18129*10^7 :        do ig1=-ng,ng
     168              : !        Exclude shells previously summed over
     169  >18127*10^7 :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng .or. ng==1 ) then
     170              : 
     171              : !          gsq is G dot G = |G|^2
     172              :            gsq=gmet(1,1)*dble(ig1*ig1)+gmet(2,2)*dble(ig2*ig2)+&
     173              : &           gmet(3,3)*dble(ig3*ig3)+2._dp*(gmet(2,1)*dble(ig1*ig2)+&
     174   7169034148 : &           gmet(3,1)*dble(ig1*ig3)+gmet(3,2)*dble(ig3*ig2))
     175              : 
     176              : !          Skip g=0:
     177   7169034148 :            if (gsq>1.0d-20) then
     178   7169026504 :              arg=fac*gsq
     179              : 
     180              : !            Larger arg gives 0 contribution because of exp(-arg)
     181   7169026504 :              if (arg <= -minexparg ) then
     182              : !              When any term contributes then include next shell
     183   1843245502 :                newg=1
     184              : 
     185              :                if((abs(ig1).lt.ngfft(1)).and.&
     186   1843245502 :                  &(abs(ig2).lt.ngfft(2)).and.&
     187              :                  &(abs(ig3).lt.ngfft(3))) then
     188    566536172 :                   ig23=ngfft(1)*(abs(ig2)+ngfft(2)*(abs(ig3)))
     189    566536172 :                   ii=abs(ig1)+ig23+1
     190              :                   !term= ( exp(-arg) + gcutoff(ii) - 1.0_dp )/gsq
     191              :                   !term=exp(-arg)/gsq*gcutoff(ii)
     192              :                   !term= ( exp(-arg) + gcutoff(ii) - 1.0_dp)/gsq
     193    566536172 :                   term=exp(-arg)/gsq*gcutoff(ii)
     194   1276709330 :                else if (icutcoul.ne.3) then
     195              :                   term=zero !exp(-arg)/gsq
     196              :                else
     197   1276487284 :                   term=exp(-arg)/gsq
     198              :                endif
     199              : 
     200   1843245502 :                summr = 0.0_dp
     201   1843245502 :                summi = 0.0_dp
     202              : 
     203              : 
     204              : !              XG 20180531  : the two do-loops on ia should be merged, in order to spare
     205              : !              the waste of computing twice the sin and cos.
     206              : 
     207              : !              Note that if reduced atomic coordinates xred drift outside
     208              : !              of unit cell (outside [0,1)) it is irrelevant in the following
     209              : !              term, which only computes a phase.
     210   7593912754 :                do ia=1,natom
     211   5750667252 :                  arg=two_pi*(ig1*xred(1,ia)+ig2*xred(2,ia)+ig3*xred(3,ia))
     212              : !                Sum real and imaginary parts (avoid complex variables)
     213   5750667252 :                  summr=summr+zion(typat(ia))*cos(arg)
     214   7593912754 :                  summi=summi+zion(typat(ia))*sin(arg)
     215              :                end do
     216              : 
     217              : !              The following two checks avoid an annoying underflow error msg
     218   1843245502 :                if (abs(summr)<1.d-16) summr=0.0_dp
     219   1843245502 :                if (abs(summi)<1.d-16) summi=0.0_dp
     220              : 
     221              : !              The product of term and summr**2 or summi**2 below
     222              : !              can underflow if not for checks above
     223   1843245502 :                t1=term*(summr*summr+summi*summi)
     224   1843245502 :                gsum=gsum+t1
     225              : 
     226   7593912754 :                do ia=1,natom
     227              : !                Again only phase is computed so xred may fall outside [0,1).
     228   5750667252 :                  arg=two_pi*(ig1*xred(1,ia)+ig2*xred(2,ia)+ig3*xred(3,ia))
     229   5750667252 :                  phr= cos(arg)
     230   5750667252 :                  phi=-sin(arg)
     231              : !                (note: do not need real part, commented out)
     232              : !                c1r=(phr*summr-phi*summi)*(term*zion(typat(ia)))
     233   5750667252 :                  c1i=(phi*summr+phr*summi)*(term*zion(typat(ia)))
     234              : !                compute coordinate gradients
     235   5750667252 :                  grewtn(1,ia)=grewtn(1,ia)-c1i*ig1
     236   5750667252 :                  grewtn(2,ia)=grewtn(2,ia)-c1i*ig2
     237   7593912754 :                  grewtn(3,ia)=grewtn(3,ia)-c1i*ig3
     238              :                end do
     239              : 
     240              :              end if ! End condition of not larger than -minexparg
     241              :            end if ! End skip g=0
     242              :          end if ! End triple loop over G s and associated new shell condition
     243              : 
     244              :        end do
     245              :      end do
     246              :    end do
     247              : 
     248              : !  Check if new shell must be calculated
     249       318596 :    if (newg==0) exit
     250              : 
     251              :  end do !  End the loop on ng (new shells). Note that there is one exit from this loop.
     252              : !endif
     253              : 
     254         7644 :  sumg=gsum/(two_pi*ucvol)
     255              : 
     256              : !Stress tensor is now computed elsewhere (ewald2) hence do not need
     257              : !length scale gradients (used to compute them here).
     258              : 
     259              : !normalize coordinate gradients by unit cell volume ucvol
     260         7644 :  term=-2._dp/ucvol
     261        97044 :  grewtn(:,:)=grewtn(:,:)*term
     262              : !call DSCAL(3*natom,term,grewtn,1)
     263              : 
     264              : !Conduct real space summations
     265         7644 :  reta=sqrt(eta)
     266         7644 :  fac=2._dp*sqrt(eta/pi)
     267         7644 :  sumr=0.0_dp
     268              : 
     269              : !In the following a summation is being conducted over all
     270              : !unit cells (ir1, ir2, ir3) so it is appropriate to map all
     271              : !reduced coordinates xred back into [0,1).
     272              : !
     273              : !Loop on shells in r-space as was done in g-space
     274         7644 :  nr=0
     275              :  do
     276        22241 :    nr=nr+1
     277        22241 :    newr=0
     278              : !   Instead of this warning that most normal users do not understand (because they are doing GS calculations, and not RF calculations),
     279              : !   one should optimize this routine. But usually this is a very small fraction of any ABINIT run.
     280              : !   if (nr > 20 .and. mod(nr,10)==0) then
     281              : !      write (msg,'(3a,I10)') "Very large box of R neighbors in ewald: you probably do not want to do this.", ch10,&
     282              : !&       " If you have a metal consider setting dipdip 0.  nr = ", nr
     283              : !      ABI_WARNING(msg)
     284              : !   end if
     285              : !
     286       134942 :    do ir3=-nr,nr
     287       782687 :      do ir2=-nr,nr
     288      4912683 :        do ir1=-nr,nr
     289      4799982 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
     290              : 
     291     11479280 :            do ia=1,natom
     292              : !            Map reduced coordinate xred(mu,ia) into [0,1)
     293      8759650 :              fraca1=xred(1,ia)-aint(xred(1,ia))+0.5_dp-sign(0.5_dp,xred(1,ia))
     294      8759650 :              fraca2=xred(2,ia)-aint(xred(2,ia))+0.5_dp-sign(0.5_dp,xred(2,ia))
     295      8759650 :              fraca3=xred(3,ia)-aint(xred(3,ia))+0.5_dp-sign(0.5_dp,xred(3,ia))
     296      8759650 :              drdta1=0.0_dp
     297      8759650 :              drdta2=0.0_dp
     298      8759650 :              drdta3=0.0_dp
     299              : 
     300    103188764 :              do ib=1,natom
     301              : !              fraca and fracb should be precomputedi and become arrays with natom dimension.
     302              : !              Also the combination with dble(ir1), dble(ir2), dble(ir3) or fraca should be done outside of the ib loop.
     303     94429114 :                fracb1=xred(1,ib)-aint(xred(1,ib))+0.5_dp-sign(0.5_dp,xred(1,ib))
     304     94429114 :                fracb2=xred(2,ib)-aint(xred(2,ib))+0.5_dp-sign(0.5_dp,xred(2,ib))
     305     94429114 :                fracb3=xred(3,ib)-aint(xred(3,ib))+0.5_dp-sign(0.5_dp,xred(3,ib))
     306     94429114 :                r1=dble(ir1)+fracb1-fraca1
     307     94429114 :                r2=dble(ir2)+fracb2-fraca2
     308     94429114 :                r3=dble(ir3)+fracb3-fraca3
     309              :                rsq=rmet(1,1)*r1*r1+rmet(2,2)*r2*r2+rmet(3,3)*r3*r3+&
     310     94429114 : &               2.0_dp*(rmet(2,1)*r2*r1+rmet(3,2)*r3*r2+rmet(3,1)*r1*r3)
     311              : 
     312              : !              Avoid zero denominators in 'term':
     313    103188764 :                if (rsq>=1.0d-24) then
     314              : 
     315              : !                Note: erfc(8) is about 1.1e-29, so do not bother with larger arg.
     316              : !                Also: exp(-64) is about 1.6e-28, so do not bother with larger arg**2 in exp.
     317     94406764 :                  term=0._dp
     318     94406764 :                  if (eta*rsq<64.0_dp) then
     319      5549124 :                    newr=1
     320      5549124 :                    rmagn=sqrt(rsq)
     321      5549124 :                    arg=reta*rmagn
     322              : !                  derfc is the real(dp) complementary error function
     323      5549124 :                    derfc_arg = abi_derfc(arg)
     324      5549124 :                    term=derfc_arg/rmagn
     325      5549124 :                    sumr=sumr+zion(typat(ia))*zion(typat(ib))*term
     326              :                    term=zion(typat(ia))*zion(typat(ib))*&
     327      5549124 : &                   (term+fac*exp(-eta*rsq))/rsq
     328              : !                  Length scale grads now handled with stress tensor in ewald2
     329      5549124 :                    r1a1d=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
     330      5549124 :                    r2a2d=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
     331      5549124 :                    r3a3d=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
     332              : !                  Compute terms related to coordinate gradients
     333      5549124 :                    drdta1=drdta1+term*r1a1d
     334      5549124 :                    drdta2=drdta2+term*r2a2d
     335      5549124 :                    drdta3=drdta3+term*r3a3d
     336              :                  end if
     337              :                end if ! End avoid zero denominators in'term'
     338              :              end do ! end loop over ib:
     339              : 
     340      8759650 :              grewtn(1,ia)=grewtn(1,ia)+drdta1
     341      8759650 :              grewtn(2,ia)=grewtn(2,ia)+drdta2
     342     12911887 :              grewtn(3,ia)=grewtn(3,ia)+drdta3
     343              :            end do ! end loop over ia:
     344              :          end if
     345              :        end do ! end triple loop over real space points and associated condition of new shell
     346              :      end do
     347              :    end do
     348              : 
     349              : !  Check if new shell must be calculated
     350        22241 :    if(newr==0) exit
     351              :  end do ! End loop on nr (new shells). Note that there is an exit within the loop
     352              : !
     353         7644 :  sumr=0.5_dp*sumr
     354         7644 :  fac=pi*ch**2.0_dp/(2.0_dp*eta*ucvol)
     355              : 
     356              : !Finally assemble Ewald energy, eew
     357         7644 :  if(icutcoul.ne.3) then
     358              :     !eew=sumg+sumr-chsq*reta/sqrt(pi)-fac
     359           10 :     eew=sumg+sumr-chsq*reta/sqrt(pi)
     360              :  else
     361         7634 :    eew=sumg+sumr-chsq*reta/sqrt(pi)-fac
     362              :  end if
     363              : 
     364         7644 :  ABI_FREE(gcutoff)
     365              : 
     366              : !DEBUG
     367              : !write(std_out,*)'eew=sumg+sumr-chsq*reta/sqrt(pi)-fac'
     368              : !write(std_out,*)eew,sumg,sumr,chsq*reta/sqrt(pi),fac
     369              : !ENDDEBUG
     370              : 
     371              : !Length scale grads handled with stress tensor, ewald2
     372              : 
     373              : !Output the final values of ng and nr
     374              : ! write(msg, '(a,a,i4,a,i4)' )ch10,' ewald : nr and ng are ',nr,' and ',ng
     375              : ! call wrtout(std_out,msg,'COLL')
     376              : 
     377         7644 : end subroutine ewald
     378              : !!***
     379              : 
     380              : !----------------------------------------------------------------------
     381              : 
     382              : !!****f* m_ewald/ewald2
     383              : !!
     384              : !! NAME
     385              : !! ewald2
     386              : !!
     387              : !! FUNCTION
     388              : !! Compute the part of the stress tensor coming from the Ewald energy
     389              : !! which is calculated by derivating the Ewald energy with respect to strain.
     390              : !! See Nielsen and Martin, Phys. Rev. B 32, 3792 (1985) [[cite:Nielsen1985a]].
     391              : !! Definition of stress tensor is $(1/ucvol)*d(Etot)/d(strain(a,b))$.
     392              : !!
     393              : !! INPUTS
     394              : !! gmet(3,3)=metric tensor in reciprocal space (bohr^-2)
     395              : !! natom=number of atoms in umit cell
     396              : !! ntypat=number of type of atoms
     397              : !! rmet(3,3)=metric tensor in real space (bohr^2) (inverse transpose of gmet)
     398              : !! rprimd(3,3)=dimensional primitive translations in real space (bohr)
     399              : !! typat(natom)=integer label of each type of atom (1,2,...)
     400              : !! ucvol=unit cell volume (bohr^3)
     401              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
     402              : !! zion(ntypat)=charge on each type of atom (real number)
     403              : !!
     404              : !! OUTPUT
     405              : !! $stress(6)=(1/ucvol)*gradient$ of Ewald energy with respect to strain,
     406              : !!      in hartrees/bohr^3
     407              : !! Cartesian components of stress are provided for this symmetric
     408              : !! tensor in the order 11 22 33 32 31 21.
     409              : !!
     410              : !! SOURCE
     411              : 
     412         6302 : subroutine ewald2(gmet,natom,ntypat,rmet,rprimd,stress,typat,ucvol,xred,zion)
     413              : 
     414              : !Arguments ------------------------------------
     415              : !scalars
     416              :  integer,intent(in) :: natom,ntypat
     417              :  real(dp),intent(in) :: ucvol
     418              : !arrays
     419              :  integer,intent(in) :: typat(natom)
     420              :  real(dp),intent(in) :: gmet(3,3),rmet(3,3),rprimd(3,3),xred(3,natom)
     421              :  real(dp),intent(in) :: zion(ntypat)
     422              :  real(dp),intent(out) :: stress(6)
     423              : 
     424              : !Local variables-------------------------------
     425              : !scalars
     426              :  integer :: ia,ib,ig1,ig2,ig3,ir1,ir2,ir3,newg,newr,ng,nr
     427              :  real(dp) :: arg1,arg2,arg3,ch,dderfc,derfc_arg,direct,eta,fac,fraca1
     428              :  real(dp) :: fraca2,fraca3,fracb1,fracb2,fracb3,g1,g2,g3,gsq,r1,r1c,r2,r2c
     429              :  real(dp) :: minexparg
     430              :  real(dp) :: r3,r3c,recip,reta,rmagn,rsq,summi,summr,t1,t2,t3,t4,t5,t6,term1
     431              :  real(dp) :: term2,term3,term4
     432              : !arrays
     433              :  real(dp) :: gprimd(3,3),strg(6),strr(6)
     434              : ! *************************************************************************
     435              : 
     436              : !Define dimensional reciprocal space primitive translations gprimd
     437              : !(inverse transpose of rprimd)
     438         6302 :  call matr3inv(rprimd,gprimd)
     439              : 
     440              : !This is the minimum argument of an exponential, with some safety
     441         6302 :  minexparg=log(tiny(0._dp))+five
     442              : 
     443              : !Add up total charge and sum of charge^2 in cell
     444         6302 :  ch=0._dp
     445        24956 :  do ia=1,natom
     446        24956 :    ch=ch+zion(typat(ia))
     447              :  end do
     448              : 
     449              : !Compute eta, the Ewald summation convergence parameter,
     450              : !for approximately optimized summations:
     451              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
     452         6302 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
     453              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
     454         6302 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
     455              : !Here, a bias is introduced, because G-space summation scales
     456              : !better than r space summation !
     457         6302 :  eta=pi*200.0_dp/33.0_dp*sqrt(1.69_dp*recip/direct)
     458              : 
     459         6302 :  fac=pi**2/eta
     460              : 
     461              : !Conduct reciprocal space summations
     462         6302 :  strg(1:6)=0.0_dp
     463              : 
     464              : !Sum over G space, done shell after shell until all
     465              : !contributions are too small
     466         6302 :  ng=0
     467              :  do
     468       270096 :    ng=ng+1
     469       270096 :    newg=0
     470              : 
     471     13808420 :    do ig3=-ng,ng
     472   1110349444 :      do ig2=-ng,ng
     473  >17019*10^7 :        do ig1=-ng,ng
     474              : 
     475              : !        Exclude shells previously summed over
     476  >17017*10^7 :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng .or. ng==1 ) then
     477              : 
     478              : !          Compute Cartesian components of each G
     479              : ! TODO : make this a blas call, and batch things up
     480   6418953326 :            g1=gprimd(1,1)*ig1+gprimd(1,2)*ig2+gprimd(1,3)*ig3
     481   6418953326 :            g2=gprimd(2,1)*ig1+gprimd(2,2)*ig2+gprimd(2,3)*ig3
     482   6418953326 :            g3=gprimd(3,1)*ig1+gprimd(3,2)*ig2+gprimd(3,3)*ig3
     483              : !          Compute |G|^2 (no pi factors)
     484   6418953326 :            gsq=(g1**2+g2**2+g3**2)
     485              : 
     486              : !          skip g=0:
     487   6418953326 :            if (gsq>1.0d-20) then
     488   6418947024 :              arg1=fac*gsq
     489              : 
     490              : !            larger arg1 gives 0 contribution because of exp(-arg1)
     491   6418947024 :              if (arg1<= -minexparg) then
     492              : !              When any term contributes then include next shell
     493   1644036704 :                newg=1
     494   1644036704 :                term1=exp(-arg1)/arg1
     495   1644036704 :                summr = 0.0_dp
     496   1644036704 :                summi = 0.0_dp
     497   6750263198 :                do ia=1,natom
     498   5106226494 :                  arg2=two_pi*(ig1*xred(1,ia)+ig2*xred(2,ia)+ig3*xred(3,ia))
     499              : !                Sum real and imaginary parts (avoid complex variables)
     500   5106226494 :                  summr=summr+zion(typat(ia))*cos(arg2)
     501   6750263198 :                  summi=summi+zion(typat(ia))*sin(arg2)
     502              :                end do
     503              : 
     504              : !              Avoid underflow error messages
     505   1644036704 :                if (abs(summr)<1.d-16) summr=0.0_dp
     506   1644036704 :                if (abs(summi)<1.d-16) summi=0.0_dp
     507              : 
     508   1644036704 :                term2=(2._dp/gsq)*(1._dp+arg1)
     509   1644036704 :                t1=term2*g1*g1-1._dp
     510   1644036704 :                t2=term2*g2*g2-1._dp
     511   1644036704 :                t3=term2*g3*g3-1._dp
     512   1644036704 :                t4=term2*g2*g3
     513   1644036704 :                t5=term2*g1*g3
     514   1644036704 :                t6=term2*g1*g2
     515   1644036704 :                term3=term1*(summr*summr+summi*summi)
     516   1644036704 :                strg(1)=strg(1)+t1*term3
     517   1644036704 :                strg(2)=strg(2)+t2*term3
     518   1644036704 :                strg(3)=strg(3)+t3*term3
     519   1644036704 :                strg(4)=strg(4)+t4*term3
     520   1644036704 :                strg(5)=strg(5)+t5*term3
     521   1644036704 :                strg(6)=strg(6)+t6*term3
     522              : 
     523              :              end if ! End condition not being larger than -minexparg
     524              :            end if ! End skip g=0
     525              : 
     526              :          end if ! End triple loop and condition of new shell
     527              :        end do
     528              :      end do
     529              :    end do
     530              : 
     531              : !  Check if new shell must be calculated
     532       270096 :    if (newg==0) exit
     533              :  end do ! End loop on new shell. Note that there is an "exit" instruction within the loop
     534              : 
     535              : 
     536              : !Conduct real space summations
     537         6302 :  reta=sqrt(eta)
     538         6302 :  strr(1:6)=0.0_dp
     539              : 
     540              : !Loop on shells in r-space as was done in g-space
     541         6302 :  nr=0
     542              :  do
     543        18130 :    nr=nr+1
     544        18130 :    newr=0
     545              : 
     546       109696 :    do ir3=-nr,nr
     547       635250 :      do ir2=-nr,nr
     548      3993998 :        do ir1=-nr,nr
     549      3902432 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
     550              : 
     551      9405204 :            do ia=1,natom
     552              : !            Convert reduced atomic coordinates to [0,1)
     553      7199330 :              fraca1=xred(1,ia)-aint(xred(1,ia))+0.5_dp-sign(0.5_dp,xred(1,ia))
     554      7199330 :              fraca2=xred(2,ia)-aint(xred(2,ia))+0.5_dp-sign(0.5_dp,xred(2,ia))
     555      7199330 :              fraca3=xred(3,ia)-aint(xred(3,ia))+0.5_dp-sign(0.5_dp,xred(3,ia))
     556     92731002 :              do ib=1,natom
     557     82154794 :                fracb1=xred(1,ib)-aint(xred(1,ib))+0.5_dp-sign(0.5_dp,xred(1,ib))
     558     82154794 :                fracb2=xred(2,ib)-aint(xred(2,ib))+0.5_dp-sign(0.5_dp,xred(2,ib))
     559     82154794 :                fracb3=xred(3,ib)-aint(xred(3,ib))+0.5_dp-sign(0.5_dp,xred(3,ib))
     560     82154794 :                r1=ir1+fracb1-fraca1
     561     82154794 :                r2=ir2+fracb2-fraca2
     562     82154794 :                r3=ir3+fracb3-fraca3
     563              : !              Convert from reduced to cartesian coordinates
     564     82154794 :                r1c=rprimd(1,1)*r1+rprimd(1,2)*r2+rprimd(1,3)*r3
     565     82154794 :                r2c=rprimd(2,1)*r1+rprimd(2,2)*r2+rprimd(2,3)*r3
     566     82154794 :                r3c=rprimd(3,1)*r1+rprimd(3,2)*r2+rprimd(3,3)*r3
     567              : !              Compute |r|^2
     568     82154794 :                rsq=r1c**2+r2c**2+r3c**2
     569     82154794 :                rmagn=sqrt(rsq)
     570              : 
     571              : !              Avoid zero denominators in 'term':
     572     89354124 :                if (rmagn>=1.0d-12) then
     573              : 
     574              : !                Note: erfc(8) is about 1.1e-29, so do not bother with larger arg.
     575              : !                Also: exp(-64) is about 1.6e-28, so do not bother with larger arg**2 in exp.
     576     82136140 :                  arg3=reta*rmagn
     577     82136140 :                  if (arg3<8.0_dp) then
     578      4500952 :                    newr=1
     579              : !                  derfc computes the complementary error function
     580              : !                  dderfc is the derivative of the complementary error function
     581      4500952 :                    dderfc=(-2/sqrt(pi))*exp(-eta*rsq)
     582      4500952 :                    derfc_arg = abi_derfc(arg3)
     583      4500952 :                    term3=dderfc-derfc_arg/arg3
     584      4500952 :                    term4=zion(typat(ia))*zion(typat(ib))*term3
     585      4500952 :                    strr(1)=strr(1)+term4*r1c*r1c/rsq
     586      4500952 :                    strr(2)=strr(2)+term4*r2c*r2c/rsq
     587      4500952 :                    strr(3)=strr(3)+term4*r3c*r3c/rsq
     588      4500952 :                    strr(4)=strr(4)+term4*r2c*r3c/rsq
     589      4500952 :                    strr(5)=strr(5)+term4*r1c*r3c/rsq
     590      4500952 :                    strr(6)=strr(6)+term4*r1c*r2c/rsq
     591              :                  end if ! End the condition of not being to large
     592              :                end if ! End avoid zero denominator
     593              : 
     594              :              end do ! End loop over ib:
     595              :            end do  ! End loop over ia:
     596              : 
     597              :          end if ! End triple loop overs real space points, and associated new shell condition
     598              :        end do
     599              :      end do
     600              :    end do
     601              : 
     602              : !  Check if new shell must be calculated
     603        18130 :    if(newr==0) exit
     604              :  end do ! End loop on new shells
     605              : 
     606              : !Finally assemble stress tensor coming from Ewald energy, stress
     607              : !(note division by unit cell volume in accordance with definition
     608              : !found in Nielsen and Martin, Phys. Rev. B 32, 3792 (1985) [[cite:Nielsen1985a]]
     609              : 
     610         6302 :  fac = pi/(2._dp*ucvol*eta)
     611         6302 :  stress(1)=(0.5_dp*reta*strr(1)+fac*(strg(1)+(ch**2)))/ucvol
     612         6302 :  stress(2)=(0.5_dp*reta*strr(2)+fac*(strg(2)+(ch**2)))/ucvol
     613         6302 :  stress(3)=(0.5_dp*reta*strr(3)+fac*(strg(3)+(ch**2)))/ucvol
     614         6302 :  stress(4)=(0.5_dp*reta*strr(4)+fac*strg(4))/ucvol
     615         6302 :  stress(5)=(0.5_dp*reta*strr(5)+fac*strg(5))/ucvol
     616         6302 :  stress(6)=(0.5_dp*reta*strr(6)+fac*strg(6))/ucvol
     617              : 
     618         6302 : end subroutine ewald2
     619              : !!***
     620              : 
     621              : !!****f* m_ewald/ewald9
     622              : !! NAME
     623              : !! ewald9
     624              : !!
     625              : !! FUNCTION
     626              : !! Compute Ewald contribution to the dynamical matrix, at a given
     627              : !! q wavevector, including anisotropic dielectric tensor and effective charges
     628              : !! See Phys. Rev. B 55, 10355 (1997) [[cite:Gonze1997a]], equations (72) to (75).
     629              : !! This has been generalized to quadrupoles.
     630              : !! Delivers the left hand side of Eq.(72), possibly generalized.
     631              : !!
     632              : !! INPUTS
     633              : !! acell = lengths by which lattice vectors are multiplied
     634              : !! dielt(3,3)=dielectric tensor
     635              : !! gmet(3,3) = metric in reciprocal space.
     636              : !! gprim(3,3)=dimensionless primitive translations in reciprocal space
     637              : !! natom=number of atoms in unit cell
     638              : !! qphon(3)=phonon wavevector (same system of coordinates as the reciprocal lattice vectors)
     639              : !! rmet = metric in real space
     640              : !! rprim(3,3)=dimensionless primitive translations in real space
     641              : !! sumg0: if=1, the sum in reciprocal space must include g=0,
     642              : !!  if=0, this contribution must be skipped (q=0 singularity)
     643              : !! ucvol=unit cell volume in (whatever length scale units)**3
     644              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
     645              : !! zeff(3,3,natom)=effective charge on each atom, versus electric
     646              : !!  field and atomic displacement
     647              : !! qdrp_cart(3,3,3,natom)=Quadrupole tensor on each atom in cartesian cordinates
     648              : !! option= 0: use old implementation;
     649              : !!         1: reduce the smalest argument of the exponentials to be evaluated,
     650              : !!            set eta to 1 and skip real space sum, leads to a significant speedup
     651              : !! [dipquad] = if 1, atmfrc has been build without dipole-quadrupole part
     652              : !! [quadquad] = if 1, atmfrc has been build without quadrupole-quadrupole part
     653              : !!
     654              : !! OUTPUT
     655              : !! dyew(2,3,natom,3,natom)= Ewald part of the dynamical matrix,
     656              : !!  second energy derivative wrt xred(3,natom) in Hartrees
     657              : !! Set to zero if all(zeff == zero)
     658              : !! eta: parameter used to split R and G-space summation
     659              : !!
     660              : !! NOTES
     661              : !! 1. The q=0 part should be subtracted, by another call to
     662              : !! the present routine, with q=0. The present routine correspond
     663              : !! to the quantity written A-bar in the explanatory notes.
     664              : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
     665              : !! 2. Because this routine can be used many times in the
     666              : !! evaluation of phonons in ppddb9, it has been
     667              : !! optimized carefully. There is still possibility
     668              : !! for improvement, by using bloking on G and R!
     669              : !! 3. There can be small numerical variations due to the
     670              : !! fact that the input dielectric tensor is usually
     671              : !! not perfectly symmetric.
     672              : !!
     673              : !! SOURCE
     674              : 
     675       181081 : subroutine ewald9(acell,dielt,dyew,gmet,gprim,natom,qphon,rmet,rprim,sumg0,ucvol,xred,zeff, qdrp_cart, eta, &
     676              :                   option, dipquad, quadquad)  ! optional
     677              : 
     678              : !Arguments -------------------------------
     679              : !scalars
     680              :  integer,intent(in) :: natom,sumg0
     681              :  integer,optional,intent(in) :: option, dipquad, quadquad
     682              :  real(dp),intent(in) :: ucvol
     683              : !arrays
     684              :  real(dp),intent(in) :: acell(3),dielt(3,3),gmet(3,3),gprim(3,3),qphon(3)
     685              :  real(dp),intent(in) :: rmet(3,3),rprim(3,3),xred(3,natom),zeff(3,3,natom)
     686              :  real(dp),intent(in) :: qdrp_cart(3,3,3,natom)
     687              :  real(dp),intent(out) :: dyew(2,3,natom,3,natom), eta
     688              : 
     689              : !Local variables -------------------------
     690              : !scalars
     691              :  integer,parameter :: mr=10000
     692              :  integer :: ia,ib,ig1,ig2,ig3,ii,ll,kk,ir,ir1,ir2,ir3,jj
     693              :  integer :: info,lwork,mu,newg,newr,ng,nr,nu,ng_expxq
     694              :  integer :: ewald_option
     695              :  integer :: dipquad_,quadquad_
     696              :  logical :: do_quadrupole
     697              :  logical, save :: firstcall = .TRUE.
     698              :  real(dp),parameter :: fac=4.0_dp/3.0_dp/sqrt(pi)
     699              :  real(dp),parameter :: fact2=2.0_dp/sqrt(pi)
     700              :  real(dp),parameter :: y2max=64.0_dp, y2min=1.0d-24
     701              :  real(dp) :: cddi,cddr,cqdi,cqdr,cqqi,cqqr,g3,g4
     702              :  real(dp) :: arg1,arg2,arg3,arga,c123r,c123i,c23i,c23r,detdlt,inv_detdlt
     703              :  real(dp) :: direct,fact1,fact3,gsq,recip,reta,reta3,inv4eta
     704              :  real(dp) :: minexparg,sigma_max
     705              :  real(dp) :: term1,term2,term3,term4,term5,y2,yy,invy,invy2,derfc_yy
     706              :  character(len=700) :: msg
     707              : !arrays
     708              :  real(dp) :: c1i(2*mr+1),c1r(2*mr+1),c2i(2*mr+1),c2r(2*mr+1),c3i(2*mr+1)
     709       362162 :  real(dp) :: c3r(2*mr+1),cosqxred(natom),wdielt(3,3),eig_dielt(3),gpq(3),gpqfac(3,3),gpqgpq(3,3)
     710       362162 :  real(dp) :: invdlt(3,3),ircar(3),ircax(3),rr(3),sinqxred(natom)
     711       362162 :  real(dp) :: xredcar(3,natom),xredcax(3,natom),xredicar(3),xredicax(3),xx(3)
     712              :  real(dp) :: gprimbyacell(3,3) !,tsec(2)
     713       181081 :  real(dp),allocatable :: dyddt(:,:,:,:,:), dydqt(:,:,:,:,:,:), dyqqt(:,:,:,:,:,:,:)
     714       181081 :  real(dp),allocatable :: work(:)
     715       181081 :  complex(dp) :: exp2piqx(natom)
     716       181081 :  complex(dp),allocatable :: expx1(:,:), expx2(:,:), expx3(:,:)
     717              : ! *********************************************************************
     718              : 
     719              :  ! This routine is expensive so skip the calculation and return zeros if zeff == zero.
     720              :  ! Typically this happens when the DDB file does not contains zeff but dipdip = 1 is used (default).
     721     16422890 :  if (all(zeff == zero).and.all(qdrp_cart == zero)) then
     722      3128282 :    dyew = zero; return
     723              :  end if
     724     13103851 :  do_quadrupole = any(qdrp_cart /= zero)
     725              : 
     726              :  ! Keep track of total time spent.
     727              :  !call timab(1749, 1, tsec)
     728              : 
     729              :  ! Initialize dipquad and quadquad options
     730       141171 :  dipquad_=0; if(present(dipquad)) dipquad_=dipquad
     731       141171 :  quadquad_=0; if(present(quadquad)) quadquad_=quadquad
     732              : 
     733              :  ! Deactivate real space sums for quadrupolar fields or for dipdip = -1
     734       141171 :  ewald_option = 0; if (present(option)) ewald_option = option
     735       141171 :  if (do_quadrupole.and.(dipquad_==1.or.quadquad_==1)) ewald_option = 1
     736              :  !ewald_option = 0
     737              : 
     738              : !This is the minimum argument of an exponential, with some safety
     739       141027 :  minexparg=log(tiny(0._dp))+five
     740       141171 :  if (ewald_option == 1) minexparg=-20.0_dp
     741              : 
     742              : ! initialize complex phase factors
     743       491992 :  do ia = 1, natom
     744              :    arga = two_pi*( (qphon(1))*xred(1,ia)&
     745              :                   +(qphon(2))*xred(2,ia)&
     746       350821 :                   +(qphon(3))*xred(3,ia) )
     747       491992 :    exp2piqx(ia) = exp(arga*j_dpc)
     748              :  end do
     749       141171 :  ng_expxq = 1000
     750       423513 :  ABI_MALLOC(expx1, (-ng_expxq:ng_expxq, natom))
     751       282342 :  ABI_MALLOC(expx2, (-ng_expxq:ng_expxq, natom))
     752       282342 :  ABI_MALLOC(expx3, (-ng_expxq:ng_expxq, natom))
     753       491992 :  do ia = 1, natom
     754    702484813 :    do ig1 = -ng_expxq, ng_expxq
     755    701992821 :      expx1(ig1, ia) = exp(ig1*two_pi*xred(1,ia)*j_dpc)
     756    701992821 :      expx2(ig1, ia) = exp(ig1*two_pi*xred(2,ia)*j_dpc)
     757    702343642 :      expx3(ig1, ia) = exp(ig1*two_pi*xred(3,ia)*j_dpc)
     758              :    end do
     759              :  end do
     760              : 
     761       141171 :  gprimbyacell = gprim
     762       564684 :  gprimbyacell(:,1) = gprimbyacell(:,1) / acell(1)
     763       564684 :  gprimbyacell(:,2) = gprimbyacell(:,2) / acell(2)
     764       564684 :  gprimbyacell(:,3) = gprimbyacell(:,3) / acell(3)
     765              : 
     766              :  ! compute eta for approximately optimized summations:
     767              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
     768       141171 :         rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
     769              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
     770       141171 :        gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
     771              : 
     772       141171 :  eta=pi*100.0_dp/33.0_dp*sqrt(1.69_dp*recip/direct)
     773              : 
     774              :  ! Compute a material-dependent width for the Gaussians that hopefully
     775              :  ! will make the Ewald real-space summation unnecessary.
     776       141171 :  if (ewald_option == 1) then
     777              : 
     778          145 :    wdielt(:,:)=dielt(:,:)
     779              : 
     780              :    ! Diagonalize dielectric matrix
     781          145 :    lwork=-1
     782          145 :    ABI_MALLOC(work,(10))
     783          145 :    call dsyev('N','U',3, wdielt, 3, eig_dielt, work, lwork,info)
     784          145 :    lwork=nint(work(1))
     785          145 :    ABI_FREE(work)
     786              : 
     787          435 :    ABI_MALLOC(work,(lwork))
     788          145 :    call dsyev('V','U',3, wdielt, 3, eig_dielt, work, lwork,info)
     789          145 :    ABI_FREE(work)
     790              : 
     791              :    ! This is a tentative maximum value for the gaussian width in real space
     792          145 :    sigma_max=three
     793              : 
     794              :    ! Set eta taking into account that the eps_inf is used as a metric in reciprocal space
     795          725 :    eta=sqrt(maxval(eig_dielt))/sigma_max
     796              : 
     797          145 :    if (firstcall) then
     798            3 :      firstcall = .FALSE.
     799            3 :      write(msg, '(4a,f9.4,9a)' ) ch10,&
     800            3 :     ' Warning : due to the use of quadrupolar fields, the width of the reciprocal space gaussians', ch10, &
     801            3 :     ' in ewald9 has been set to eta= ', eta, ' 1/bohr and the real-space sums have been neglected.', ch10, &
     802            3 :     ' One should check whether this choice leads to correct results for the specific system under study', &
     803            3 :     ' and q-point grid.',ch10, &
     804            3 :     ' It is recommended to check that calculations with dipdip=1 and -1 (both with dipquad=0 and quadquad=0)', ch10, &
     805            6 :     ' lead to identical results. Otherwise increase the resolution of the q-point grid and repeat this test.', ch10
     806            9 :      call wrtout([ab_out,std_out], msg)
     807              :    end if
     808              : 
     809              :    !Internally eta is the square of the gaussians width
     810          145 :    eta=eta*eta
     811              :  end if
     812              : 
     813       141171 :  inv4eta = one / four / eta
     814              : 
     815       705855 :  ABI_MALLOC(dyddt,(2,3,natom,3,natom))
     816       705855 :  ABI_MALLOC(dydqt,(2,3,natom,3,natom,3))
     817       705855 :  ABI_MALLOC(dyqqt,(2,3,natom,3,natom,3,3))
     818              : 
     819     37471225 :  dyddt = zero
     820    112554846 :  dydqt = zero
     821    337805709 :  dyqqt = zero
     822              : 
     823              : !Sum terms over g space:
     824              :  ng=0
     825              :  do
     826      1898918 :    ng=ng+1
     827              : 
     828              :    ! if needed, update the complex phases for larger G vectors
     829      1898918 :    if (ng > ng_expxq) then
     830              :      !write(std_out,*)"have to realloc"
     831            0 :      ABI_FREE(expx1)
     832            0 :      ABI_FREE(expx2)
     833            0 :      ABI_FREE(expx3)
     834              : 
     835            0 :      ng_expxq = ng_expxq*2
     836              :      ! TODO: half of this space is not needed, as it contains the complex conjugate of the other half.
     837              :      ! present duplication avoids if statements inside the loop, however
     838            0 :      ABI_MALLOC(expx1, (-ng_expxq:ng_expxq, natom))
     839            0 :      ABI_MALLOC(expx2, (-ng_expxq:ng_expxq, natom))
     840            0 :      ABI_MALLOC(expx3, (-ng_expxq:ng_expxq, natom))
     841            0 :      do ia = 1, natom
     842            0 :        do ig1 = -ng_expxq, ng_expxq
     843            0 :          expx1(ig1, ia) = exp(ig1*two_pi*xred(1,ia)*j_dpc)
     844            0 :          expx2(ig1, ia) = exp(ig1*two_pi*xred(2,ia)*j_dpc)
     845            0 :          expx3(ig1, ia) = exp(ig1*two_pi*xred(3,ia)*j_dpc)
     846              :        end do
     847              :      end do
     848              :    end if
     849              : 
     850      1898918 :    newg=0
     851     34005968 :    do ig3=-ng,ng
     852    802421358 :      do ig2=-ng,ng
     853  27092131162 :        do ig1=-ng,ng
     854  27060024112 :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng .or. ng==1 )then
     855              : 
     856              :            gpq(1)=(ig1+qphon(1))*gprimbyacell(1,1)+(ig2+qphon(2))*&
     857   4240540255 :                                  gprimbyacell(1,2)+(ig3+qphon(3))*gprimbyacell(1,3)
     858              :            gpq(2)=(ig1+qphon(1))*gprimbyacell(2,1)+(ig2+qphon(2))*&
     859   4240540255 :                                  gprimbyacell(2,2)+(ig3+qphon(3))*gprimbyacell(2,3)
     860              :            gpq(3)=(ig1+qphon(1))*gprimbyacell(3,1)+(ig2+qphon(2))*&
     861   4240540255 :                                  gprimbyacell(3,2)+(ig3+qphon(3))*gprimbyacell(3,3)
     862   4240540255 :            gsq=zero
     863  16962161020 :            do jj=1,3
     864  55127023315 :              do ii=1,3
     865  38164862295 :                gpqgpq(ii,jj)=gpq(ii)*gpq(jj)
     866  50886483060 :                gsq=gsq+gpqgpq(ii,jj)*dielt(ii,jj)
     867              :              end do
     868              :            end do
     869              : 
     870              :            ! Skip q=0:
     871   4240540255 :            if (gsq<1.0d-20) then
     872        19491 :              if (sumg0==1) then
     873              :                write(msg,'(5a)' )&
     874            0 :                'The phonon wavelength should not be zero :',ch10,&
     875            0 :                'there are non-analytical terms that cannot be treated.',ch10,&
     876            0 :                'Action: subtract this wavelength from the input file.'
     877            0 :                ABI_ERROR(msg)
     878              :              end if
     879              : 
     880              :            else
     881              : 
     882   4240520764 :              arg1=(two_pi**2)*gsq* inv4eta
     883              : 
     884              :              ! Larger arg gives 0 contribution:
     885   4240520764 :              if (arg1<= -minexparg ) then
     886   1118988781 :                newg=1
     887              : 
     888              :                ! Here calculate the term
     889   1118988781 :                term1=exp(-arg1)/gsq
     890   4475955124 :                do jj=1,3
     891  14546854153 :                  do ii=1,3
     892  13427865372 :                    gpqfac(ii,jj)=gpqgpq(ii,jj)*term1
     893              :                  end do
     894              :                end do
     895              : 
     896              :                ! MJV: replaced old calls to cos and sin.
     897              :                ! Checked for 10 tests in v2 that max error is about 6.e-15, usually < 2.e-15
     898   4594649808 :                do ia=1,natom
     899   3475661027 :                  cosqxred(ia)= real(exp2piqx(ia)*expx1(ig1, ia)*expx2(ig2, ia)*expx3(ig3, ia))
     900   4594649808 :                  sinqxred(ia)=aimag(exp2piqx(ia)*expx1(ig1, ia)*expx2(ig2, ia)*expx3(ig3, ia))
     901              :                end do
     902              : 
     903              :                ! First, the diagonal terms
     904   4475955124 :                do nu=1,3
     905  14902938205 :                  do ia=1,natom
     906  34637915586 :                    do mu=nu,3
     907  31280949243 :                      dyddt(1,mu,ia,nu,ia)=dyddt(1,mu,ia,nu,ia)+gpqfac(mu,nu)
     908              :                    end do
     909              :                  end do
     910              :                end do
     911              : 
     912              :                ! Then, the non-diagonal ones
     913   3475661027 :                do ib=2,natom
     914   9936789130 :                  do ia=1,ib-1
     915              :                    ! phase factor dipole-dipole
     916   6461128103 :                    cddr=cosqxred(ia)*cosqxred(ib)+sinqxred(ia)*sinqxred(ib)
     917   6461128103 :                    cddi=sinqxred(ia)*cosqxred(ib)-cosqxred(ia)*sinqxred(ib)
     918              : 
     919              :                    ! Dipole-dipole contribution
     920  28201184658 :                    do nu=1,3
     921  64611281030 :                      do mu=nu,3
     922  38766768618 :                        dyddt(1,mu,ia,nu,ib)=dyddt(1,mu,ia,nu,ib)+gpqfac(mu,nu)*cddr
     923  58150152927 :                        dyddt(2,mu,ia,nu,ib)=dyddt(2,mu,ia,nu,ib)+gpqfac(mu,nu)*cddi
     924              :                      end do
     925              :                    end do
     926              :                  end do
     927              :                end do
     928              : 
     929   1118988781 :                if (do_quadrupole) then
     930    415900706 :                  do ib=1,natom
     931    997315061 :                    do ia=1,natom
     932              : 
     933              :                      ! phase factor for dipole-quadrupole
     934    581414355 :                      cqdr=cosqxred(ia)*sinqxred(ib)-sinqxred(ia)*cosqxred(ib)
     935    581414355 :                      cqdi=cosqxred(ia)*cosqxred(ib)+sinqxred(ia)*sinqxred(ib)
     936              : 
     937              :                      ! phase factor quadrupole-quadrupole
     938    581414355 :                      cqqr=cosqxred(ia)*cosqxred(ib)+sinqxred(ia)*sinqxred(ib)
     939    581414355 :                      cqqi=sinqxred(ia)*cosqxred(ib)-cosqxred(ia)*sinqxred(ib)
     940              : 
     941              :                      ! Dipole-quadrupole contribution
     942   2325657420 :                      do ii=1,3
     943   7558386615 :                        do jj=1,3
     944  22675159845 :                          do kk=1,3
     945  15698187585 :                            g3=gpq(ii)*gpq(jj)*gpq(kk)
     946  15698187585 :                            dydqt(1,ii,ia,jj,ib,kk)=dydqt(1,ii,ia,jj,ib,kk)+g3*term1*cqdr
     947  20930916780 :                            dydqt(2,ii,ia,jj,ib,kk)=dydqt(2,ii,ia,jj,ib,kk)+g3*term1*cqdi
     948              :                          end do ! kk
     949              :                        end do ! jj
     950              :                      end do ! ii
     951              : 
     952              :                      ! Quadrupole-quadrupole contribution
     953   2605368201 :                      do ii=1,3
     954   7558386615 :                        do jj=1,3
     955  22675159845 :                          do kk=1,3
     956  68025479535 :                            do ll=1,3
     957  47094562755 :                              g4 = gpq(ii)*gpq(jj)*gpq(kk)*gpq(ll)
     958  47094562755 :                              dyqqt(1,ii,ia,jj,ib,kk,ll)=dyqqt(1,ii,ia,jj,ib,kk,ll)+g4*term1*cqqr
     959  62792750340 :                              dyqqt(2,ii,ia,jj,ib,kk,ll)=dyqqt(2,ii,ia,jj,ib,kk,ll)+g4*term1*cqqi
     960              :                            end do
     961              :                          end do ! kk
     962              :                        end do ! jj
     963              :                      end do ! ii
     964              :                    end do ! ia
     965              :                  end do ! ib
     966              :                end if
     967              : 
     968              :              end if ! endif exp() argument is smaller than -minexparg
     969              :            end if ! Endif g/=0 :
     970              :          end if ! End triple summation over Gs:
     971              :        end do
     972              :      end do
     973              :    end do
     974              : 
     975              :    !  Check if new shell must be calculated
     976      1898918 :    if(newg==0)exit
     977              :  end do
     978              : 
     979              :  ! Multiplies by common factor
     980       141171 :  fact1=4.0_dp*pi/ucvol
     981       491992 :  do ib=1,natom
     982      1266182 :    do ia=1,ib
     983      3447581 :      do nu=1,3
     984      7741900 :        do mu=nu,3
     985      4645140 :          dyddt(1,mu,ia,nu,ib)=dyddt(1,mu,ia,nu,ib)*fact1
     986      6967710 :          dyddt(2,mu,ia,nu,ib)=dyddt(2,mu,ia,nu,ib)*fact1
     987              :        end do
     988              :      end do
     989              :    end do
     990              :  end do
     991       141171 :  if (do_quadrupole) then
     992      6039836 :    dydqt=dydqt*fact1/two  * two_pi
     993     18131300 :    dyqqt=dyqqt*fact1/four * two_pi ** 2
     994              :  end if
     995              : 
     996       141171 :  reta=sqrt(eta)
     997       141171 :  reta3=-eta*reta
     998              : 
     999              :  !Calculating the inverse (transpose) of the dielectric tensor
    1000       141171 :  call matr3inv(dielt,invdlt)
    1001              : 
    1002              :  !Calculating the determinant of the dielectric tensor
    1003              :  detdlt=dielt(1,1)*dielt(2,2)*dielt(3,3)+dielt(1,3)*dielt(2,1)*&
    1004              :         dielt(3,2)+dielt(1,2)*dielt(2,3)*dielt(3,1)-dielt(1,3)*&
    1005              :         dielt(2,2)*dielt(3,1)-dielt(1,1)*dielt(2,3)*dielt(3,2)-&
    1006       141171 :         dielt(1,2)*dielt(2,1)*dielt(3,3)
    1007              : 
    1008       141171 :  if(detdlt<tol6)then
    1009              :    write(msg, '(a,es16.6,11a)' )&
    1010            0 :    'The determinant of the dielectrix matrix, detdlt=',detdlt,' is smaller than 1.0d-6.',ch10,&
    1011            0 :    'The use of the dipole-dipole model for interatomic force constants is not possible.',ch10,&
    1012            0 :    'It is likely that you have not treated the electric field perturbations,',ch10,&
    1013            0 :    'because you not are dealing with an insulator, so that',ch10,&
    1014            0 :    'your dielectric matrix was simply set to zero in the Derivative DataBase.',ch10,&
    1015            0 :    'Action: set the input variable dipdip to 0 .'
    1016            0 :    ABI_ERROR(msg)
    1017              :  end if
    1018              : 
    1019       141171 :  inv_detdlt = one / sqrt(detdlt)
    1020       141171 :  fact3=reta3 * inv_detdlt
    1021              : 
    1022       141171 :  if (ewald_option /= 1) then
    1023              :  ! Preparing the loop on real space
    1024       491557 :  do ia=1,natom
    1025      1543150 :    do ii=1,3
    1026              :      xredcar(ii,ia)=(xred(1,ia)*acell(1)*rprim(ii,1)+&
    1027              :                      xred(2,ia)*acell(2)*rprim(ii,2)+&
    1028      1402124 :                      xred(3,ia)*acell(3)*rprim(ii,3) )*reta
    1029              :    end do
    1030              :  end do
    1031       491557 :  do ia=1,natom
    1032      1543150 :    do ii=1,3
    1033              :      xredcax(ii,ia)= invdlt(1,ii)*xredcar(ii,ia)+&
    1034              :                      invdlt(2,ii)*xredcar(ii,ia)+&
    1035      1402124 :                      invdlt(3,ii)*xredcar(ii,ia)
    1036              :    end do
    1037              :  end do
    1038              : 
    1039              :  ! Prepare the evaluation of exp(iq*R)
    1040   2820802052 :  do ir=-mr,mr
    1041   2820661026 :    arg1=-two_pi*qphon(1)*ir
    1042   2820661026 :    arg2=-two_pi*qphon(2)*ir
    1043   2820661026 :    arg3=-two_pi*qphon(3)*ir
    1044   2820661026 :    c1r(ir+mr+1)=cos(arg1)
    1045   2820661026 :    c1i(ir+mr+1)=sin(arg1)
    1046   2820661026 :    c2r(ir+mr+1)=cos(arg2)
    1047   2820661026 :    c2i(ir+mr+1)=sin(arg2)
    1048   2820661026 :    c3r(ir+mr+1)=cos(arg3)
    1049   2820802052 :    c3i(ir+mr+1)=sin(arg3)
    1050              :  end do
    1051              : 
    1052      1216218 :  do nr=1,mr
    1053      1216218 :    newr=0
    1054              : 
    1055              :    ! Begin big loop on real space vectors
    1056     15491768 :    do ir3=-nr,nr
    1057    242017034 :      do ir2=-nr,nr
    1058              : 
    1059              :        ! Here, construct the cosine and sine of q*R for components 2 and 3
    1060    226525266 :        c23r = c2r(ir2+mr+1) * c3r(ir3+mr+1) - c2i(ir2+mr+1) * c3i(ir3+mr+1)
    1061    226525266 :        c23i = c2i(ir2+mr+1) * c3r(ir3+mr+1) + c2r(ir2+mr+1) * c3i(ir3+mr+1)
    1062              : 
    1063              :        ! Also multiplies by fact3, because it is a rather economical place to do so
    1064    226525266 :        c23r=c23r * fact3
    1065    226525266 :        c23i=c23i * fact3
    1066              : 
    1067   4669927318 :        do ir1=-nr,nr
    1068   4655651768 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
    1069              : 
    1070              :            ! This is the real part and imaginary part of the phase factor exp(iq*R)
    1071   1197715766 :            c123r = c1r(ir1+mr+1) * c23r - c1i(ir1+mr+1) * c23i
    1072   1197715766 :            c123i = c1i(ir1+mr+1) * c23r + c1r(ir1+mr+1) * c23i
    1073              : 
    1074   4790863064 :            do ii=1,3
    1075              :              ircar(ii)= ( ir1*acell(1)*rprim(ii,1)+&
    1076              :                           ir2*acell(2)*rprim(ii,2)+&
    1077   4790863064 :                           ir3*acell(3)*rprim(ii,3) ) * reta
    1078              :            end do
    1079   4790863064 :            do ii=1,3
    1080              :              ircax(ii)= invdlt(1,ii)*ircar(ii)+&
    1081              :                         invdlt(2,ii)*ircar(ii)+&
    1082   4790863064 :                         invdlt(3,ii)*ircar(ii)
    1083              :            end do
    1084              : 
    1085              :            ! Here loops on atoms
    1086   4111740513 :            do ib=1,natom
    1087  11656098988 :              do ii=1,3
    1088   8742074241 :                xredicar(ii)=ircar(ii)-xredcar(ii,ib)
    1089  11656098988 :                xredicax(ii)=ircax(ii)-xredcax(ii,ib)
    1090              :              end do
    1091  13018818028 :              do ia=1,ib
    1092  22702667116 :                do ii=1,3
    1093  17027000337 :                  rr(ii)=xredicar(ii)+xredcar(ii,ia)
    1094  22702667116 :                  xx(ii)=xredicax(ii)+xredcax(ii,ia)
    1095              :                end do
    1096              : 
    1097   5675666779 :                y2=rr(1)*xx(1)+rr(2)*xx(2)+rr(3)*xx(3)
    1098              : 
    1099              :                ! The atoms should not be too far of each other
    1100   8589691526 :                if (y2 < y2max) then
    1101              :                ! Note: erfc(8) is about 1.1e-29, so dont bother with larger y.
    1102              :                ! Also: exp(-64) is about 1.6e-28, do dont bother with larger y**2 in exp.
    1103              : 
    1104              :                  ! Avoid zero denominators in term:
    1105   1307663559 :                  if (y2 >= y2min) then
    1106   1307313028 :                    newr=1
    1107   1307313028 :                    yy=sqrt(y2)
    1108   1307313028 :                    invy=1.0_dp/yy
    1109   1307313028 :                    invy2=invy**2
    1110   1307313028 :                    derfc_yy = abi_derfc(yy)
    1111   1307313028 :                    term2=derfc_yy*invy*invy2
    1112   1307313028 :                    term3=fact2*exp(-y2)*invy2
    1113   1307313028 :                    term4=-(term2+term3)
    1114   1307313028 :                    term5=(3.0_dp*term2+term3*(3.0_dp+2.0_dp*y2))*invy2
    1115   5229252112 :                    do nu=1,3
    1116  13073130280 :                      do mu=nu,3
    1117   7843878168 :                        dyddt(1,mu,ia,nu,ib)=dyddt(1,mu,ia,nu,ib)+c123r*(xx(nu)*xx(mu)*term5+term4*invdlt(nu,mu))
    1118  11765817252 :                        dyddt(2,mu,ia,nu,ib)=dyddt(2,mu,ia,nu,ib)+c123i*(xx(nu)*xx(mu)*term5+term4*invdlt(nu,mu))
    1119              :                      end do
    1120              :                    end do
    1121              :                  else
    1122              :                    ! If zero denominator, the atoms should be identical
    1123       350531 :                    if (ia/=ib)then
    1124              :                      write(msg, '(5a,i0,a,i0,a)' )&
    1125            0 :                        'The distance between two atoms seem to vanish.',ch10,&
    1126            0 :                        'This is not allowed.',ch10,&
    1127            0 :                        'Action: check the input for the atoms number',ia,' and',ib,'.'
    1128            0 :                      ABI_ERROR(msg)
    1129              :                    else
    1130              :                      ! This is the correction when the atoms are identical
    1131      1402124 :                      do nu=1,3
    1132      4556903 :                        do mu=1,3
    1133              :                          dyddt(1,mu,ia,nu,ib)=dyddt(1,mu,ia,nu,ib)+&
    1134      4206372 :                                   fac*reta3*invdlt(nu,mu) * inv_detdlt
    1135              :                        end do
    1136              :                      end do
    1137              :                    end if
    1138              :                  end if ! End the condition for avoiding zero denominators
    1139              :                end if ! End the condition of too large distance between atoms
    1140              :              end do
    1141              :            end do ! End loop over ia and ib :
    1142              :          end if ! End triple loop over real space points:
    1143              :        end do ! ir1
    1144              :      end do ! ir2
    1145              :    end do ! ir3
    1146              : 
    1147              :    ! Check if new shell must be calculated
    1148      1216218 :    if(newr==0)exit
    1149      1216218 :    if(newr==1 .and. nr==mr) ABI_BUG('mr is too small')
    1150              :  end do
    1151              :  end if ! check if should compute real part
    1152              : 
    1153              :  ! Now, symmetrizes
    1154       350821 :  do ib=1,natom-1
    1155       979771 :    do nu=1,3
    1156      2108707 :      do ia=ib+1,natom
    1157      4439271 :        do mu=nu,3
    1158      2540214 :          dyddt(1,mu,ia,nu,ib)= dyddt(1,mu,ib,nu,ia)
    1159      3810321 :          dyddt(2,mu,ia,nu,ib)=-dyddt(2,mu,ib,nu,ia)
    1160              :        end do
    1161              :      end do
    1162              :    end do
    1163              :  end do
    1164              : 
    1165       491992 :  do ib=1,natom
    1166      1193634 :    do nu=2,3
    1167      3447581 :      do ia=1,natom
    1168      6689437 :        do mu=1,nu-1
    1169      3592677 :          dyddt(1,mu,ia,nu,ib)=dyddt(1,nu,ia,mu,ib)
    1170      5987795 :          dyddt(2,mu,ia,nu,ib)=dyddt(2,nu,ia,mu,ib)
    1171              :        end do
    1172              :      end do
    1173              :    end do
    1174              :  end do
    1175              : 
    1176              :  !Tests
    1177              :  !write(std_out,*)' ewald9 : take into account the effective charges '
    1178     37471225 :  dyew = zero
    1179       491992 :  do ib=1,natom
    1180      1544455 :    do nu=1,3
    1181      4995961 :      do ia=1,natom
    1182     15423171 :        do mu=1,3
    1183     46704801 :          do ii=1,3
    1184    140114403 :            do jj=1,3
    1185              :              ! dipole-dipole correction
    1186              :              dyew(1,mu,ia,nu,ib)=dyew(1,mu,ia,nu,ib) + &
    1187     97002279 :               zeff(ii,mu,ia)*zeff(jj,nu,ib)*dyddt(1,ii,ia,jj,ib)
    1188              :              dyew(2,mu,ia,nu,ib)=dyew(2,mu,ia,nu,ib) + &
    1189     97002279 :               zeff(ii,mu,ia)*zeff(jj,nu,ib)*dyddt(2,ii,ia,jj,ib)
    1190    129336372 :              if (do_quadrupole) then
    1191     20417832 :                do kk=1,3
    1192     15313374 :                  if (dipquad_==1) then
    1193              :                    ! dipole-quadrupole correction
    1194              :                    dyew(1,mu,ia,nu,ib)=dyew(1,mu,ia,nu,ib) + &
    1195              :                      (zeff(ii,nu,ib)*qdrp_cart(kk,jj,mu,ia) - &
    1196       139968 :                       zeff(ii,mu,ia)*qdrp_cart(kk,jj,nu,ib)) * dydqt(1,ii,ia,jj,ib,kk)
    1197              :                    dyew(2,mu,ia,nu,ib)=dyew(2,mu,ia,nu,ib) + &
    1198              :                      (zeff(ii,nu,ib)*qdrp_cart(kk,jj,mu,ia) - &
    1199       139968 :                       zeff(ii,mu,ia)*qdrp_cart(kk,jj,nu,ib)) * dydqt(2,ii,ia,jj,ib,kk)
    1200              :                  end if
    1201              : 
    1202              :                  ! quadrupole-quadrupole correction
    1203     20417832 :                  if (quadquad_==1) then
    1204       559872 :                    do ll=1,3
    1205              :                      dyew(1,mu,ia,nu,ib)=dyew(1,mu,ia,nu,ib) + &
    1206       419904 :                      (qdrp_cart(ll,ii,mu,ia)*qdrp_cart(kk,jj,nu,ib)) * dyqqt(1,ii,ia,jj,ib,kk,ll)
    1207              :                      dyew(2,mu,ia,nu,ib)=dyew(2,mu,ia,nu,ib) + &
    1208       559872 :                      (qdrp_cart(ll,ii,mu,ia)*qdrp_cart(kk,jj,nu,ib)) * dyqqt(2,ii,ia,jj,ib,kk,ll)
    1209              :                    end do
    1210              :                  end if
    1211              :                end do
    1212              :              end if
    1213              : 
    1214              :            end do
    1215              :          end do
    1216              :        end do
    1217              :      end do
    1218              :    end do
    1219              :  end do
    1220              : 
    1221       141171 :  ABI_FREE(expx1)
    1222       141171 :  ABI_FREE(expx2)
    1223       141171 :  ABI_FREE(expx3)
    1224       141171 :  ABI_FREE(dyddt)
    1225       141171 :  ABI_FREE(dydqt)
    1226       141171 :  ABI_FREE(dyqqt)
    1227              :  !call timab(1749, 2, tsec)
    1228              : 
    1229              : end subroutine ewald9
    1230              : !!***
    1231              : 
    1232              : !!****f* m_ewald/ewald9_2D
    1233              : !!
    1234              : !! NAME
    1235              : !! ewald9_2D
    1236              : !!
    1237              : !! FUNCTION
    1238              : !! Compute the long-range electrostatics contribution to interatomic force constants
    1239              : !! in the bi-dimensional (2D) case, considering the 2D is embedded in a dielectric environment
    1240              : !! and has a given dielectric thickness. The singularity of the Coulomb potential is treated
    1241              : !! using the Ewald summation approach. It is possible to input a more complicate model
    1242              : !! with two consecutive dielectric slabs.
    1243              : !!
    1244              : !! INPUTS
    1245              : !! natom=number of atoms in unit cell
    1246              : !! acell(3)=length of unit cell vectors
    1247              : !! xred(3,natom)=reduced coordinates of the atoms
    1248              : !! rprim(3,3)=unit cell vectors (unscaled)
    1249              : !! dielt(3,3)=dielectric tensor of the 2D
    1250              : !! dyew(2,3,natom,3,natom)=long-range electrostatics IFCs following Ewald
    1251              : !! qphon(3)=phonon wavevector in reduced coordinates
    1252              : !! zeff(3,3,natom)=Born effective charge tensor
    1253              : !! qdrp_cart(3,3,3,natom)=Dynamical quadrupoles
    1254              : !! dielt_env=dielectric constant of the embedding environment (1 in vacuum)
    1255              : !! thick(2)=dielectric thicknesses of the slab, first value correspond to the outer
    1256              : !! dielectric, second to the inner dielectric slab (if any)
    1257              : !! sys_dim= system dimensionality (indicates axis without periodicity)
    1258              : !!
    1259              : !! OUTPUT
    1260              : !! dyew(2,3,natom,3,natom)=long-range electrostatics IFCs following Ewald
    1261              : !!
    1262              : !! SOURCE
    1263              : 
    1264          561 : subroutine ewald9_2D(natom,acell,xred,rprim,dielt,dyew,qphon,zeff,qdrp_cart,dielt_env,thick,sys_dim)
    1265              : 
    1266              : !Arguments -------------------------------
    1267              : !scalars
    1268              :  real(dp), intent(in) :: dielt_env
    1269              :  integer :: natom, sys_dim
    1270              : !arrays
    1271              :  real(dp),intent(in) :: acell(3),thick(2),xred(3,natom),dielt(3,3),qphon(3)
    1272              :  real(dp),intent(in) :: rprim(3,3),zeff(3,3,natom),qdrp_cart(3,3,3,natom)
    1273              :  real(dp),intent(out) :: dyew(2,3,natom,3,natom)
    1274              :  character(len=700) :: msg
    1275              :  
    1276              : !Local variables -------------------------
    1277              : !scalars
    1278              :  integer :: gmax,idir1,idir2,ibz1,ibz2,ipert1,ipert2,inner_thick,ndir,mdir
    1279              :  real(dp) :: detdlt, delta_perp, lambda, dielt_perp,dielt_perp1,dielt_perp2, eta,eta1,xi, dielt_eff
    1280              :  real(dp) :: dielt_eff1,dielt_eff2, norm_kvec, norm_kvec0, phi 
    1281              :  real(dp) :: ewald_fun, ewald_fun1, ewald_fun2, rflct_coeff, out_thick
    1282              :  real(dp) :: rflct_coeff1, rflct_coeff2, rprimd_perp
    1283              :  real(dp) :: fac_erfc, fac_ewald1, fac_ewald2, fac_ewald2b,fac_exp
    1284              :  real(dp) :: fac_exp1, trans_fun, fac_gauss, fac_mirror, fac_mirror1, fac_real
    1285              :  real(dp) :: mean2_perp, mirror_diff, mirror_parapara, mirror_paraperp, mirror_perpperp
    1286              :  real(dp) :: rvec_norm, sqrt_norm, ucsurf, xmean
    1287              :  logical, save :: firstcall = .TRUE.
    1288              : !arrays
    1289              :  integer :: periodic_dir(3)
    1290         1122 :  real(dp) :: dyew_real(2,3,natom,3,natom),dyew_rec(2,3,natom,3,natom),kvec(2),invdlt_para(2,2)
    1291              :  real(dp) :: rprimd_para(2,2), gprimd_para(2,2), gvec(2)
    1292              :  real(dp) :: norm_dielt(2), dielt_para(2,2), invdlt(3,3), qvec(3), qvec_para(2)
    1293         1122 :  real(dp) :: diff_xcart(3), xcart_para(2,natom),xcart_perp(natom)
    1294         1122 :  real(dp) :: kvec_para(2),zeff_para(2,3,natom), zeff_perp(3,natom)
    1295         1122 :  real(dp) :: xcart(3,natom), rprimd(3,3), gprimd(3,3), rvec_dielt(3)
    1296         1122 :  real(dp) :: qdrp_parapara(2,2,3,natom),qdrp_perpperp(3,natom), qdrp_paraperp(2,3,natom)
    1297              :  real(dp) :: rho_gerade1(2),rho_gerade2(2), rho_ungerade1(2), rho_ungerade2(2)
    1298              : ! *************************************************************************
    1299              :  
    1300          561 :  periodic_dir(:) = 0
    1301          561 :  if (sys_dim ==2) then ! 2D along x
    1302            0 :          periodic_dir(2) =1 ; periodic_dir(3) = 1
    1303          561 :  elseif (sys_dim==3) then ! 2D along y
    1304            0 :          periodic_dir(1) = 1 ; periodic_dir(3) = 1
    1305          561 :  elseif (sys_dim==4) then ! 2D along z
    1306          561 :          periodic_dir(1) = 1 ; periodic_dir(2) = 1
    1307              :  end if
    1308              :  
    1309          561 :  rprimd=zero
    1310         2244 :  do idir1=1,3
    1311         7293 :  do idir2=1,3
    1312         6732 :  rprimd(idir1,idir2) = rprim(idir1,idir2)*acell(idir2)
    1313              :  end do
    1314              :  end do
    1315              :  
    1316              :  
    1317         8017 :  xcart=zero
    1318         2425 :  do ipert1=1,natom
    1319        30385 :  xcart(:,ipert1)=matmul(rprimd, xred(:,ipert1))
    1320              :  end do
    1321              :  
    1322          561 :  call matr3inv(rprimd,gprimd)
    1323        26657 :  zeff_para=zero ; zeff_perp=zero
    1324         2244 :  qvec(:) = qphon(1)*gprimd(:,1)+qphon(2)*gprimd(:,2)
    1325              :  ndir=0
    1326         2244 :  do idir1=1,3
    1327         2244 :  if (periodic_dir(idir1)==1) then
    1328         1122 :          ndir=ndir+1
    1329         1122 :          qvec_para(ndir)=qvec(idir1)
    1330        16034 :          zeff_para(ndir,:,:) = zeff(idir1,:,:)
    1331         4850 :          xcart_para(ndir,:) = xcart(idir1,:)
    1332              :  else
    1333         8017 :          zeff_perp(:,:) = zeff(idir1,:,:)
    1334         2425 :          xcart_perp(:) = xcart(idir1,:)
    1335          561 :          if (qvec(idir1)>tol6) then !Check if phonon mode is not out-of-plane
    1336              :                  write(msg, '(a,es16.6,5a)')&
    1337            0 :                          'The phonon wavevector along the confined direction is',qvec(idir1),' 1/Bohr >1.0d-6',ch10,&
    1338            0 :                          'The phonon wavevector should be purely along the periodic direction', ch10, &
    1339            0 :                          'when using Ewald summation in 2D. Please check your input file and structure'
    1340            0 :                  ABI_ERROR(msg)
    1341              :          end if
    1342              :  end if
    1343              :  end do
    1344         2425 :  xmean = sum(xcart_perp)/natom
    1345         2425 :  xcart_perp(:)=xcart_perp(:)-xmean
    1346              :  
    1347              :  !Calculating the inverse (transpose) of the dielectric tensor
    1348          561 :  call matr3inv(dielt,invdlt)
    1349              :  !Calculating the determinant of the dielectric tensor
    1350              :  detdlt=dielt(1,1)*dielt(2,2)*dielt(3,3)+dielt(1,3)*dielt(2,1)*&
    1351              :          & dielt(3,2)+dielt(1,2)*dielt(2,3)*dielt(3,1)-dielt(1,3)*&
    1352              :          & dielt(2,2)*dielt(3,1)-dielt(1,1)*dielt(2,3)*dielt(3,2)-&
    1353          561 :          & dielt(1,2)*dielt(2,1)*dielt(3,3)
    1354              :  
    1355          561 :  if(detdlt<tol6)then
    1356              :          write(msg, '(a,es16.6,11a)' )&
    1357            0 :                  'The determinant of the dielectrix matrix, detdlt=',detdlt,' is smaller than 1.0d-6.',ch10,&
    1358            0 :                  'The use of the dipole-dipole model for interatomic force constants is not possible.',ch10,&
    1359            0 :                  'It is likely that you have not treated the electric field perturbations,',ch10,&
    1360            0 :                  'because you not are dealing with an insulator, so that',ch10,&
    1361            0 :                  'your dielectric matrix was simply set to zero in the Derivative DataBase.',ch10,&
    1362            0 :                  'Action: set the input variable dipdip to 0 .'
    1363            0 :          ABI_ERROR(msg)
    1364              :  end if
    1365              :  
    1366              :  ! The dielectric tensor must be diagonal in the confined direction
    1367          561 :  rprimd_para = zero ; rprimd_perp = zero
    1368          561 :  dielt_para = zero ; dielt_perp = zero
    1369          561 :  invdlt_para = zero ; gprimd_para = zero
    1370          561 :  ndir=0
    1371         2244 :  do idir1=1,3
    1372         1683 :  if (periodic_dir(idir1)==1) then
    1373         1122 :          ndir=ndir+1
    1374              :  end if
    1375         1683 :  mdir=0
    1376         7293 :  do idir2=1,3
    1377         5049 :  if (periodic_dir(idir2)==1) then
    1378         3366 :          mdir=mdir+1
    1379              :  end if
    1380         5049 :  if ((periodic_dir(idir1)==1 .and. periodic_dir(idir2)==0) .or. &
    1381         1683 :          (periodic_dir(idir1)==0 .and. periodic_dir(idir2)==1)) then
    1382         2244 :          if (abs(dielt(idir1,idir2))>tol6 .or. abs(rprimd(idir1,idir2))>tol6) then !No cross in-plane out-of-plane are allowed
    1383              :                  write(msg, '(7a)' )&
    1384            0 :                          'The dielectric matrix shows off-diagonal components in the confined direction larger than 1d-6',ch10,&
    1385            0 :                          'This is forbidden when considering the Ewald summation for 2D systems. Please check if your', ch10, &
    1386            0 :                          'confined direction is correctly specified in the anaddb input or if the vacuum size if sufficiently', ch10, &
    1387            0 :                          'large in the confined direction to avoid spurious interactions between unit cells'
    1388            0 :                  ABI_ERROR(msg)
    1389              :          end if
    1390        32068 :          qdrp_paraperp(ndir,:,:) = qdrp_cart(idir1,idir2,:,:)
    1391         2805 :  elseif (periodic_dir(idir1)==0 .and. periodic_dir(idir2)==0) then
    1392          561 :          dielt_perp = dielt(idir1,idir2)
    1393          561 :          rprimd_perp = rprimd(idir1,idir2)
    1394         8017 :          qdrp_perpperp(:,:) = qdrp_cart(idir1,idir2,:,:)
    1395              :  else
    1396         2244 :          dielt_para(ndir,mdir) = dielt(idir1,idir2)
    1397         2244 :          rprimd_para(ndir,mdir)=rprimd(idir1,idir2)
    1398         2244 :          gprimd_para(ndir,mdir) = gprimd(idir1,idir2)
    1399         2244 :          invdlt_para(ndir,mdir)=invdlt(idir1,idir2)
    1400        32068 :          qdrp_parapara(ndir,mdir,:,:) = qdrp_cart(idir1,idir2,:,:)
    1401              :  end if
    1402              :  end do
    1403              :  end do
    1404              : 
    1405              : 
    1406              :  ! Consistency check for dielectric thicknesses
    1407          561 :  inner_thick = thick(2)
    1408          561 :  out_thick = thick(1)
    1409              : 
    1410         2425 :  do ipert1=1,natom
    1411         9121 :    do ipert2=1,natom
    1412         8560 :      if (xcart_perp(ipert1)-xcart_perp(ipert2)>out_thick .or. xcart_perp(ipert1)+xcart_perp(ipert2)>out_thick) then
    1413              :        write(msg, '(5a)' )&
    1414            0 :        'Some atoms seem to be located away from the dielectric slab.',ch10,&
    1415            0 :        'The present model only allows for this specific scenario. Please increases slightly',ch10,&
    1416            0 :        'the dielectric slab thickness'
    1417            0 :        ABI_ERROR(msg)        
    1418              :      end if
    1419              :    end do
    1420              :  end do
    1421          561 :  if (inner_thick>zero) then
    1422          190 :    if (inner_thick>out_thick) then
    1423              :         write(msg, '(3a)' )&
    1424            0 :          'When considering consecutive dielectric slab models, inner thickness',ch10,&
    1425            0 :          'should be smaller than the outer thickness. Please check your input file'
    1426            0 :          ABI_ERROR(msg)
    1427              :    else
    1428          570 :        do ipert1=1,natom
    1429         1330 :          do ipert2=1,natom
    1430         1140 :            if (xcart_perp(ipert1)-xcart_perp(ipert2)>inner_thick .or. xcart_perp(ipert1)+xcart_perp(ipert2)>inner_thick) then
    1431              :              write(msg, '(5a)' )&
    1432            0 :              'Some atoms seem to be located away from the inner dielectric slab.',ch10,&
    1433            0 :              'The present model only allows for this specific scenario. Please increases slightly',ch10,&
    1434            0 :              'the inner dielectric slab thickness'
    1435            0 :              ABI_ERROR(msg)        
    1436              :            end if
    1437              :          end do
    1438              :        end do
    1439              :    end if
    1440              :  end if
    1441              : 
    1442              :  ! First needs to determine the Gaussian broadening intrinsic to the Ewald summation. In 2D, both the real and
    1443              :  ! reciprocal summation are related to the complementary error function. We want to restrict the real-part to
    1444              :  ! the first Wigner cell. We use the fact that sqrt(1-e^{-x^2}) < erf(x) < sqrt(1-e^{-4x^2/pi})
    1445              :  ! and invert those relationships to estimate the broadening required  to restrict the real-part summation of
    1446              :  !the Ewald summation; here fixes the threshold to 1e-9 for contribution from later unit cells
    1447              :  rvec_dielt = zero
    1448          561 :  ndir=0
    1449         1683 :  do idir1=1,2
    1450        10659 :  norm_dielt(idir1) = dot_product(rprimd_para(idir1,:),matmul(invdlt_para(:,:),rprimd_para(idir1,:)))
    1451              :  end do
    1452              :  
    1453         2244 :  lambda = dsqrt(maxval(norm_dielt))/dsqrt(-two*dlog(one-(one-tol9)**2))
    1454              :  
    1455              :  ! Now that we have computed the value of lambda, we can compute the Ewald summation, starting from the
    1456              :  ! reciprocal sum. We need first to estimate the max. number of reciprocal vectors we need to consider
    1457              :  ! for the Ewald summation. We use here a stricter tolerance than for the determination of lambda
    1458              :  ! Note that the worst case scenario is always when considering Rka=Rk'b in this case
    1459              :  
    1460         2244 :  gmax = int(dsqrt(-two*dlog(one-(one-tol12)**2))/lambda/(two_pi/dsqrt(minval(norm_dielt))))
    1461          561 :  if (firstcall) then
    1462            2 :    firstcall = .FALSE.
    1463            2 :    write(msg, '(6a,f9.4,3a,i3,1a)' ) ch10,&
    1464            2 :          ' Ewald treatment of 2D long-range electrostatics interatomic force constants', ch10,  &
    1465            2 :          ' To restrict the real-part summation of Ewald to the first unit cell, the Gaussian broadening', ch10, &
    1466            2 :          ' has been set to ', lambda, ' 1/Bohr. For the reciprocal sum, this corresponds to max.', ch10, &
    1467            4 :          ' ',2*gmax-1, ' Brillouin zone repetitions in either in-plane directions'
    1468            6 :  call wrtout([ab_out,std_out], msg)
    1469              :  end if
    1470              :  
    1471       208897 :  dyew_rec = zero
    1472              :  ! If one dielectric slab model, same dielectric for both regions
    1473              :  ! Otherwise, inner dielectric ~1 and the other has been computed
    1474              :  ! accordingly in the anaddb driver
    1475          561 :  if (inner_thick> zero) then
    1476              :     dielt_perp1 = one
    1477              :  else
    1478          371 :     dielt_perp1=dielt_perp
    1479              :  end if
    1480          561 :  dielt_perp2 = dielt_perp
    1481         8216 :  do ibz1 = -gmax,gmax
    1482       114681 :    do ibz2 = -gmax,gmax
    1483       319395 :      gvec(:) = ibz1*gprimd_para(:,1)+ibz2*gprimd_para(:,2)
    1484       319395 :      kvec(:) = gvec(:) + qvec_para(:)
    1485       319395 :      kvec(:) = kvec(:)*two_pi
    1486       745255 :      kvec_para(:) = matmul(dielt_para,kvec)
    1487       319395 :      norm_kvec0 = dot_product(kvec,kvec)
    1488       319395 :      norm_kvec = dot_product(kvec,kvec_para)
    1489       114120 :      if (abs(norm_kvec)>tol6) then !Remove G=q=0 case
    1490       106456 :         eta = dsqrt(norm_kvec/dielt_perp)
    1491       106456 :         eta1 = dsqrt(norm_kvec/dielt_perp1)
    1492       106456 :         xi = dsqrt(norm_kvec/dielt_perp2)
    1493              :         ! Effective dielectric constants (depends on direction)
    1494       106456 :         dielt_eff = dsqrt(norm_kvec*dielt_perp/norm_kvec0)
    1495       106456 :         dielt_eff1 = dsqrt(norm_kvec*dielt_perp1/norm_kvec0)
    1496       106456 :         dielt_eff2 = dsqrt(norm_kvec*dielt_perp2/norm_kvec0)
    1497              :         ! Reflection coefficient at the dielectric interfaces
    1498       106456 :         rflct_coeff = (dielt_eff-dielt_env)/(dielt_eff+dielt_env)
    1499       106456 :         rflct_coeff2 = (dielt_eff2-dielt_env)/(dielt_eff2+dielt_env)
    1500       106456 :         trans_fun = (one+rflct_coeff2*dexp(-xi*(out_thick-inner_thick)))
    1501       106456 :         trans_fun = trans_fun/(one-rflct_coeff2*dexp(-xi*(out_thick-inner_thick)))
    1502       106456 :         rflct_coeff1 = (dielt_eff1*trans_fun-dielt_eff2)/(dielt_eff1*trans_fun+dielt_eff2)
    1503              :         ! Dipole-dipole charges prefactors
    1504       106456 :         fac_exp = rflct_coeff*dexp(-eta*out_thick)
    1505       106456 :         fac_exp1 = rflct_coeff1*dexp(-eta1*inner_thick)
    1506       106456 :         fac_mirror = two*fac_exp/(one-fac_exp**2)
    1507       106456 :         fac_mirror1 = two*fac_exp1/(one-fac_exp1**2)
    1508              :         ! Ewald factor in error function
    1509       106456 :         fac_ewald1= eta*dsqrt(dielt_perp)*lambda/dsqrt(two)
    1510       486310 :         do ipert1=1,natom
    1511      1913786 :           do ipert2=1,natom
    1512      1427476 :             delta_perp = (xcart_perp(ipert2)-xcart_perp(ipert1))
    1513      1427476 :             mean2_perp = (xcart_perp(ipert2)+xcart_perp(ipert1))
    1514      1427476 :             fac_ewald2= delta_perp/lambda/sqrt(two*dielt_perp)
    1515      1427476 :             fac_ewald2b= delta_perp/lambda/sqrt(two*dielt_perp1)
    1516              :             ! Ewald function and derivatives (eta factorized)
    1517              :             ewald_fun = half*(dexp(-eta*delta_perp)*(one-erf(fac_ewald1-fac_ewald2)))+ &
    1518      1427476 :                 half*(dexp(eta*delta_perp)*(one-erf(fac_ewald1+fac_ewald2)))
    1519              :             ewald_fun1 = half*(-dexp(-eta*delta_perp)*(one-erf(fac_ewald1-fac_ewald2)))+ &
    1520      1427476 :                 half*(dexp(eta*delta_perp)*(one-erf(fac_ewald1+fac_ewald2)))
    1521              :             ! For second derivative, there is in principle a Gaussian term as well
    1522              :             ! However, by an appropriate choice of the electrostatic gauge (mean average
    1523              :             ! potential), we can neglect it. This approximation has been validated
    1524              :             ! with respect to real-space dipoles and exact calculated points
    1525              :             ewald_fun2 = half*(dexp(-eta1*delta_perp)*(one-erf(fac_ewald1-fac_ewald2b)))+ &
    1526      1427476 :                  half*(dexp(eta1*delta_perp)*(one-erf(fac_ewald1+fac_ewald2b)))
    1527      1427476 :             ewald_fun2=-ewald_fun2*eta1**2
    1528              :  
    1529              :             ! Phase factor and mirror terms
    1530      4282428 :             phi = dot_product(kvec,xcart_para(:,ipert1)-xcart_para(:,ipert2))
    1531      1427476 :             mirror_parapara = fac_mirror*(dcosh(eta*mean2_perp)+fac_exp*dcosh(eta*delta_perp))
    1532      1427476 :             if (inner_thick >tol6) then 
    1533        91940 :               mirror_perpperp = fac_mirror1*(dcosh(eta1*mean2_perp)-fac_exp1*dcosh(eta1*delta_perp))
    1534              :             else
    1535      1335536 :               mirror_perpperp = fac_mirror*(dcosh(eta*mean2_perp)-fac_exp1*dcosh(eta*delta_perp))
    1536              :             end if
    1537      1427476 :             mirror_paraperp = fac_mirror*fac_exp*dsinh(eta*delta_perp)
    1538      1427476 :             mirror_diff = fac_mirror*dsinh(eta*mean2_perp)
    1539              :         ! Then compute the charge prefactor
    1540      6089758 :             do idir1=1,3
    1541     18557188 :             do idir2=1,3
    1542    115625556 :             rho_gerade1(1) = -half*dot_product(kvec,matmul(qdrp_parapara(:,:,idir1,ipert1),kvec))
    1543    115625556 :             rho_gerade2(1) = -half*dot_product(kvec,matmul(qdrp_parapara(:,:,idir2,ipert2),kvec))
    1544     12847284 :             rho_gerade1(1) = rho_gerade1(1)+half*eta1**2*qdrp_perpperp(idir1,ipert1)
    1545     12847284 :             rho_gerade2(1) = rho_gerade2(1)+half*eta1**2*qdrp_perpperp(idir2,ipert2)
    1546     38541852 :             rho_gerade1(2) = -dot_product(kvec,zeff_para(:,idir1,ipert1))
    1547     38541852 :             rho_gerade2(2) = -dot_product(kvec,zeff_para(:,idir2,ipert2))
    1548     12847284 :             rho_ungerade1(1) = -zeff_perp(idir1,ipert1)
    1549     38541852 :             rho_ungerade1(2) = eta1*dot_product(kvec,qdrp_paraperp(:,idir1,ipert1))
    1550     12847284 :             rho_ungerade2(1) = -zeff_perp(idir2,ipert2)
    1551     38541852 :             rho_ungerade2(2) = eta1*dot_product(kvec,qdrp_paraperp(:,idir2,ipert2))
    1552              :             ! First, add the source charges (gerade gerade)
    1553              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1554              :                     (rho_gerade1(1)*rho_gerade2(1)+rho_gerade1(2)*rho_gerade2(2))&
    1555     12847284 :                     *ewald_fun/eta/dielt_perp*cos(phi)
    1556              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1557              :                     (rho_gerade1(2)*rho_gerade2(1)-rho_gerade1(1)*rho_gerade2(2))&
    1558     12847284 :                     *ewald_fun/eta/dielt_perp*sin(phi)
    1559              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1560              :                     (rho_gerade1(1)*rho_gerade2(1)+rho_gerade1(2)*rho_gerade2(2))&
    1561     12847284 :                     *ewald_fun/eta/dielt_perp*sin(phi)
    1562              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1563              :                     (rho_gerade1(2)*rho_gerade2(1)-rho_gerade1(1)*rho_gerade2(2))&
    1564     12847284 :                     *ewald_fun/eta/dielt_perp*cos(phi)
    1565              :             ! Second, add the source charges (ungerade ungerade)
    1566              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1567              :                     (rho_ungerade1(1)*rho_ungerade2(1)+rho_ungerade1(2)*rho_ungerade2(2))&
    1568     12847284 :                     *ewald_fun2/eta1/dielt_perp1*cos(phi)
    1569              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1570              :                     (rho_ungerade1(2)*rho_ungerade2(1)-rho_ungerade1(1)*rho_ungerade2(2))&
    1571     12847284 :                     *ewald_fun2/eta1/dielt_perp1*sin(phi)
    1572              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1573              :                     (rho_ungerade1(1)*rho_ungerade2(1)+rho_ungerade1(2)*rho_ungerade2(2))&
    1574     12847284 :                     *ewald_fun2/eta1/dielt_perp1*sin(phi)
    1575              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1576              :                     (rho_ungerade1(2)*rho_ungerade2(1)-rho_ungerade1(1)*rho_ungerade2(2))&
    1577     12847284 :                     *ewald_fun2/eta1/dielt_perp1*cos(phi)
    1578              :             ! Third, add the source charge (gerade ungerade)
    1579              :             ! For sake of consistenty, only used when there is only one dielectric thickness
    1580     12847284 :             if (inner_thick <tol6) then 
    1581              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1582              :                     (rho_gerade1(1)*rho_ungerade2(1)+rho_ungerade1(1)*rho_gerade2(1)&
    1583              :                     +rho_gerade1(2)*rho_ungerade2(2)+rho_ungerade1(2)*rho_gerade2(2)) &
    1584     12019824 :                     *ewald_fun1/eta/dielt_perp*cos(phi)
    1585              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1586              :                     (rho_gerade1(2)*rho_ungerade2(1)+rho_ungerade1(2)*rho_gerade2(1)&
    1587              :                      -rho_gerade1(1)*rho_ungerade2(2)-rho_ungerade1(1)*rho_gerade2(2)) &
    1588     12019824 :                     *ewald_fun1/eta/dielt_perp*sin(phi)
    1589              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)-&
    1590              :                     (rho_gerade1(1)*rho_ungerade2(1)+rho_ungerade1(1)*rho_gerade2(1)&
    1591              :                      +rho_gerade1(2)*rho_ungerade2(2)+rho_ungerade1(2)*rho_gerade2(2)) &
    1592     12019824 :                     *ewald_fun1/eta/dielt_perp*sin(phi)
    1593              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)-&
    1594              :                     (rho_gerade1(2)*rho_ungerade2(1)+rho_ungerade1(2)*rho_gerade2(1)&
    1595              :                      -rho_gerade1(1)*rho_ungerade2(2)-rho_ungerade1(1)*rho_gerade2(2)) &
    1596     12019824 :                     *ewald_fun1/eta/dielt_perp*cos(phi)
    1597              :             end if
    1598              :             ! Now add the interactions with the mirror charges... para para
    1599              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1600              :                     (rho_gerade1(1)*rho_gerade2(1)+rho_gerade1(2)*rho_gerade2(2))&
    1601     12847284 :                     *mirror_parapara/eta/dielt_perp*cos(phi)
    1602              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1603              :                     (rho_gerade1(2)*rho_gerade2(1)-rho_gerade1(1)*rho_gerade2(2))&
    1604     12847284 :                     *mirror_parapara/eta/dielt_perp*sin(phi)
    1605              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1606              :                     (rho_gerade1(1)*rho_gerade2(1)+rho_gerade1(2)*rho_gerade2(2))&
    1607     12847284 :                     *mirror_parapara/eta/dielt_perp*sin(phi)
    1608              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1609              :                     (rho_gerade1(2)*rho_gerade2(1)-rho_gerade1(1)*rho_gerade2(2))&
    1610     12847284 :                     *mirror_parapara/eta/dielt_perp*cos(phi)
    1611              :             ! Now with perp perp
    1612              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1613              :                     (rho_ungerade1(1)*rho_ungerade2(1)+rho_ungerade1(2)*rho_ungerade2(2))&
    1614     12847284 :                     *mirror_perpperp*eta1/dielt_perp1*cos(phi)
    1615              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1616              :                     (rho_ungerade1(2)*rho_ungerade2(1)-rho_ungerade1(1)*rho_ungerade2(2))&
    1617     12847284 :                     *mirror_perpperp*eta1/dielt_perp1*sin(phi)
    1618              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1619              :                     (rho_ungerade1(1)*rho_ungerade2(1)+rho_ungerade1(2)*rho_ungerade2(2))&
    1620     12847284 :                     *mirror_perpperp*eta1/dielt_perp1*sin(phi)
    1621              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1622              :                     (rho_ungerade1(2)*rho_ungerade2(1)-rho_ungerade1(1)*rho_ungerade2(2))&
    1623     12847284 :                     *mirror_perpperp*eta1/dielt_perp1*cos(phi)
    1624              :             ! Third, add the source charge (gerade ungerade)
    1625     17129712 :             if (inner_thick <tol6) then
    1626              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1627              :                     (rho_gerade1(1)*rho_ungerade2(1)+rho_ungerade1(1)*rho_gerade2(1)&
    1628              :                     +rho_gerade1(2)*rho_ungerade2(2)+rho_ungerade1(2)*rho_gerade2(2)) &
    1629     12019824 :                     *mirror_paraperp/eta/dielt_perp*cos(phi)
    1630              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)+&
    1631              :                     (rho_gerade1(2)*rho_ungerade2(1)+rho_ungerade1(2)*rho_gerade2(1)&
    1632              :                      -rho_gerade1(1)*rho_ungerade2(2)-rho_ungerade1(1)*rho_gerade2(2)) &
    1633     12019824 :                     *mirror_paraperp/eta/dielt_perp*sin(phi)
    1634              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)-&
    1635              :                     (rho_gerade1(1)*rho_ungerade2(1)+rho_ungerade1(1)*rho_gerade2(1)&
    1636              :                      +rho_gerade1(2)*rho_ungerade2(2)+rho_ungerade1(2)*rho_gerade2(2)) &
    1637     12019824 :                     *mirror_paraperp/eta/dielt_perp*sin(phi)
    1638              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1639              :                     (rho_gerade1(2)*rho_ungerade2(1)+rho_ungerade1(2)*rho_gerade2(1)&
    1640              :                      -rho_gerade1(1)*rho_ungerade2(2)-rho_ungerade1(1)*rho_gerade2(2)) &
    1641     12019824 :                     *mirror_paraperp/eta/dielt_perp*cos(phi)
    1642              :             ! Finally, there is a term on the sum of charge, only for mirror charges
    1643              :                     ! Third, add the source charge (gerade ungerade)
    1644              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1645              :                     (rho_gerade1(1)*rho_ungerade2(1)-rho_ungerade1(1)*rho_gerade2(1)&
    1646              :                     +rho_gerade1(2)*rho_ungerade2(2)-rho_ungerade1(2)*rho_gerade2(2)) &
    1647     12019824 :                     *mirror_diff/eta/dielt_perp*cos(phi)
    1648              :             dyew_rec(1,idir1,ipert1,idir2,ipert2)= dyew_rec(1,idir1,ipert1,idir2,ipert2)-&
    1649              :                     (rho_gerade1(2)*rho_ungerade2(1)-rho_ungerade1(2)*rho_gerade2(1)&
    1650              :                      -rho_gerade1(1)*rho_ungerade2(2)+rho_ungerade1(1)*rho_gerade2(2)) &
    1651     12019824 :                     *mirror_diff/eta/dielt_perp*sin(phi)
    1652              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)+&
    1653              :                     (rho_gerade1(1)*rho_ungerade2(1)-rho_ungerade1(1)*rho_gerade2(1)&
    1654              :                      +rho_gerade1(2)*rho_ungerade2(2)-rho_ungerade1(2)*rho_gerade2(2)) &
    1655     12019824 :                     *mirror_diff/eta/dielt_perp*sin(phi)
    1656              :             dyew_rec(2,idir1,ipert1,idir2,ipert2)= dyew_rec(2,idir1,ipert1,idir2,ipert2)-&
    1657              :                     (rho_gerade1(2)*rho_ungerade2(1)-rho_ungerade1(2)*rho_gerade2(1)&
    1658              :                      +rho_gerade1(1)*rho_ungerade2(2)+rho_ungerade1(1)*rho_gerade2(2)) &
    1659     12019824 :                     *mirror_diff/eta/dielt_perp*sin(phi)
    1660              :             end if
    1661              :             end do
    1662              :             end do
    1663              :           end do
    1664              :         end do
    1665              :       end if
    1666              :    end do
    1667              :  end do
    1668          561 :  ucsurf = rprimd_para(1,1)*rprimd_para(2,2)-rprimd_para(1,2)*rprimd_para(2,1)
    1669              :  ! Renormalize by surface of periodic 2D lattice and out-of-plane dielectric constant
    1670       208897 :  dyew_rec = dyew_rec*(two_pi)/ucsurf
    1671              :  ! Reciprocal summation completes. Remains some real-space contribution from first
    1672              :  ! unit cells (ipert1 neq ipert2), impacting all IFCs the same way
    1673       208897 :  dyew_real = zero
    1674         2425 :  do ipert1=1,natom
    1675         9121 :    do ipert2=1,natom
    1676        26784 :      diff_xcart(:) =xcart(:,ipert2)-xcart(:,ipert1)
    1677        87048 :      rvec_dielt(:) = matmul(invdlt,diff_xcart)
    1678        26784 :      rvec_norm = dot_product(diff_xcart,rvec_dielt)
    1679         6696 :      sqrt_norm = dsqrt(rvec_norm)
    1680         6696 :      fac_erfc = sqrt_norm/dsqrt(two)/lambda
    1681         6696 :      fac_gauss = -rvec_norm/two/lambda**2
    1682        28648 :      do idir1=1,3
    1683        87048 :        do idir2=1,3
    1684        80352 :          if (ipert1 .NE. ipert2) then ! Only off-sites contributions
    1685              :            ! First, contribution from eps^-1 (Rk'b-Rka) eps^-1
    1686              :            fac_real = three*(one-erf(fac_erfc))/sqrt_norm**5+6*exp(fac_gauss)/rvec_norm**2/&
    1687        43488 :            sqrt(two_pi)/lambda+two*exp(fac_gauss)/rvec_norm/sqrt(two_pi)/lambda**3
    1688              :            dyew_real(1,idir1,ipert1,idir2,ipert2) = dyew_real(1,idir1,ipert1,idir2,ipert2)+&
    1689        43488 :            fac_real*rvec_dielt(idir1)*rvec_dielt(idir2)
    1690              :            ! Second contribution from esp^-1(alpha,beta)
    1691        43488 :            fac_real = (one-erf(fac_erfc))/sqrt_norm**3+exp(fac_gauss)/rvec_norm/sqrt(two_pi)/lambda
    1692              :            dyew_real(1,idir1,ipert1,idir2,ipert2)=dyew_real(1,idir1,ipert1,idir2,ipert2)-&
    1693        43488 :            fac_real*dielt(idir1,idir2)
    1694              :          end if
    1695              :        end do
    1696              :      end do
    1697              :    end do
    1698              :  end do
    1699       208897 :  dyew_real = dyew_real / dsqrt(detdlt)
    1700       208897 :  dyew = dyew_real + dyew_rec
    1701          561 : end subroutine ewald9_2D
    1702              : 
    1703              : end module m_ewald
    1704              : !!***
    1705              : 
        

Generated by: LCOV version 2.3-1