LCOV - code coverage report
Current view: top level - src/72_response - m_dfpt_elt.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.7 % 1338 1281
Test Date: 2026-09-19 15:24:51 Functions: 100.0 % 19 19

            Line data    Source code
       1              : !!****m* ABINIT/m_dfpt_elt
       2              : !! NAME
       3              : !!  m_dfpt_elt
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !!
       8              : !! COPYRIGHT
       9              : !! Copyright (C) 1998-2026 ABINIT group (DRH, DCA, XG, GM, AR, MB)
      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_dfpt_elt
      23              : 
      24              :  use defs_basis
      25              :  use m_abicore
      26              :  use m_errors
      27              :  use m_xmpi
      28              :  use m_dtset
      29              : 
      30              :  use defs_datatypes, only : pseudopotential_type
      31              :  use defs_abitypes, only : MPI_type
      32              :  use m_time,        only : timab
      33              :  use m_special_funcs,  only : abi_derfc
      34              :  use m_geometry,    only : metric
      35              :  use m_cgtools,     only : dotprod_vn
      36              :  use m_pawtab,      only : pawtab_type,pawtab_free,pawtab_nullify
      37              :  use m_pawrad,      only : pawrad_type,pawrad_init,pawrad_free
      38              :  use m_pawpsp,      only : pawpsp_cg
      39              :  use m_paw_numeric, only : paw_spline
      40              :  use m_spacepar,    only : redgr
      41              :  use m_atm2fft,     only : atm2fft, dfpt_atm2fft
      42              :  use m_mkcore,      only : dfpt_mkcore
      43              :  use m_dfpt_mkvxcstr, only : dfpt_mkvxcstr
      44              :  use m_paral_atom,   only : get_my_atmtab, free_my_atmtab
      45              :  use m_mpinfo,       only : ptabs_fourdp, proc_distrb_cycle, proc_distrb_nband
      46              :  use m_fftcore,      only : sphereboundary
      47              :  use m_fft,          only : fourdp
      48              :  use m_gtermcutoff,  only : termcutoff
      49              : 
      50              :  implicit none
      51              : 
      52              :  private
      53              : !!***
      54              : 
      55              :  public :: dfpt_eltfrxc
      56              :  public :: dfpt_eltfrloc
      57              :  public :: dfpt_eltfrkin
      58              :  public :: dfpt_eltfrhar
      59              :  public :: elt_ewald
      60              :  public :: dfpt_ewald
      61              :  public :: dfpt_ewalddq
      62              :  public :: dfpt_ewalddqdq
      63              : !!***
      64              : 
      65              : contains
      66              : !!***
      67              : 
      68              : !!****f* ABINIT/dfpt_eltfrxc
      69              : !! NAME
      70              : !! dfpt_eltfrxc
      71              : !!
      72              : !! FUNCTION
      73              : !! Compute the 2nd derivatives of exchange-correlation energy
      74              : !! with respect to all pairs of strain and strain-atomic displacement
      75              : !! for the frozen wavefunction contribution to the elastic
      76              : !! and internal strain tensors
      77              : !!
      78              : !! INPUTS
      79              : !!  atindx(natom)=index table for atoms ordered by type
      80              : !!  dtset <type(dataset_type)>=all input variables for this dataset
      81              : !!   | natom=number of atoms in unit cell
      82              : !!   | nfft=(effective) number of FFT grid points (for this processor)
      83              : !!   | nspden=number of spin-density components
      84              : !!   | ntypat=number of types of atoms in cell.
      85              : !!   | typat(natom)=integer type for each atom in cell
      86              : !!  enxc=exchange and correlation energy (hartree)
      87              : !!  gsqcut=Fourier cutoff on G^2 for "large sphere" of radius double that of the basis sphere
      88              : !!  kxc(nfft,nkxc)=exchange and correlation kernel
      89              : !!  mgfft=maximum size of 1D FFTs
      90              : !!  mpi_enreg=information about MPI parallelization
      91              : !!  ngfft(18)=contain all needed information about 3D FFT,
      92              : !!     see ~abinit/doc/variables/vargs.htm#ngfft
      93              : !!  ngfftf(18)= -PAW ONLY- contain all needed information about 3D FFT for the fine grid
      94              : !!              (ngfftf=ngfft for norm-conserving potential runs)
      95              : !!  nkxc=2nd dimension of kxc
      96              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
      97              : !!  n3xccc=dimension of xccc3d (0 if no core charge, nfft otherwise)
      98              : !!  nhat(nfft,nspden*nhatdim)= -PAW only- compensation density
      99              : !!  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
     100              : !!  ph1d(2,3*(2*mgfft+1)*natom)=1-dim phase (structure factor) information
     101              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
     102              : !!  rhor(nfft,nspden)=electron density in r space
     103              : !!   (if spin polarized, array contains total density in first half and
     104              : !!    spin-up density in second half)
     105              : !!   (for non-collinear magnetism, first element: total density,
     106              : !!    3 next ones: mx,my,mz)
     107              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
     108              : !!  usexcnhat= -PAW only- 1 if nhat density has to be taken into account in Vxc
     109              : !!  vxc(nfft,nspden)=xc potential (spin up in first half and spin down in
     110              : !!   second half if nspden=2)
     111              : !!  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
     112              : !!  xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
     113              : !!   for each type of atom, from psp
     114              : !!  xccc3d(n3xccc)=3D core electron density for XC core correction, bohr^-3
     115              : !!  xred(3,natom)=reduced coordinates for atoms in unit cell
     116              : !!
     117              : !! OUTPUT
     118              : !!  eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
     119              : !!   elastic tensor
     120              : !!
     121              : !! SIDE EFFECTS
     122              : !!
     123              : !! NOTES
     124              : !!      Much of the code in versions of this routine prior to 4.4.5
     125              : !!      has been transfered to its child eltxccore.
     126              : !!
     127              : !! SOURCE
     128              : 
     129           37 : subroutine dfpt_eltfrxc(atindx,dtset,eltfrxc,enxc,gsqcut,kxc,mpi_enreg,mgfft,&
     130           37 : & nattyp,nfft,ngfft,ngfftf,nhat,nkxc,n3xccc,pawtab,ph1d,psps,rhor,rprimd,&
     131           37 : & usexcnhat,vxc,xccc3d,xred)
     132              : 
     133              : !Arguments ------------------------------------
     134              : !type
     135              : !scalars
     136              :  integer,intent(in) :: mgfft,n3xccc,nfft,nkxc,usexcnhat
     137              :  real(dp),intent(in) :: enxc,gsqcut
     138              :  type(MPI_type),intent(in) :: mpi_enreg
     139              :  type(dataset_type),intent(in) :: dtset
     140              :  type(pseudopotential_type),intent(inout) :: psps
     141              : !arrays
     142              :  integer,intent(in) :: atindx(dtset%natom),nattyp(dtset%ntypat),ngfft(18)
     143              :  integer,intent(in) :: ngfftf(18)
     144              :  real(dp),intent(in) :: nhat(nfft,dtset%nspden*psps%usepaw)
     145              :  real(dp),intent(in) :: ph1d(2,3*(2*mgfft+1)*dtset%natom)
     146              :  real(dp),intent(in) :: vxc(nfft,dtset%nspden),xccc3d(n3xccc)
     147              :  real(dp),intent(in) :: xred(3,dtset%natom)
     148              :  real(dp),intent(in),target :: rhor(nfft,dtset%nspden)
     149              :  real(dp),intent(inout) :: kxc(nfft,nkxc)
     150              :  real(dp),intent(out) :: eltfrxc(6+3*dtset%natom,6),rprimd(3,3)
     151              :  type(pawtab_type),intent(in) :: pawtab(dtset%ntypat*dtset%usepaw)
     152              : 
     153              : !Local variables-------------------------------
     154              : !scalars
     155              :  integer,parameter :: mshift=401
     156              :  integer :: cplex,fgga,ia,idir,ielt,ieltx,ierr,ifft,ii,ipert,is1,is2,ispden,ispden_c,jj,ka,kb
     157              :  integer :: kd,kg,n1,n1xccc,n2,n3,n3xccc_loc,optatm,optdyfr,opteltfr,optgr
     158              :  integer :: option,optn,optn2,optstr,optv
     159              :  logical :: nmxc
     160              :  real(dp) :: d2eacc,d2ecdgs2,d2exdgs2,d2gsds1ds2,d2gstds1ds2,decdgs,dexdgs
     161              :  real(dp) :: dgsds10,dgsds20,dgstds10,dgstds20,rstep,spnorm,tmp0,tmp0t
     162              :  real(dp) :: ucvol,valuei,yp1,ypn
     163           37 :  type(pawrad_type) :: core_mesh
     164              : !arrays
     165              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
     166              :  real(dp) :: corstr(6),dummy6(0),dummy_in(0,0)
     167              :  real(dp) :: dummy_out1(0),dummy_out2(0),dummy_out3(0),dummy_out4(0),dummy_out5(0),dummy_out6(0)
     168           74 :  real(dp) :: eltfrxc_test1(6+3*dtset%natom,6),eltfrxc_test2(6+3*dtset%natom,6)
     169              :  real(dp) :: gmet(3,3),gprimd(3,3),qphon(3),rmet(3,3),tsec(2)
     170              :  real(dp) :: strn_dummy6(0), strv_dummy6(0)
     171           37 :  real(dp),allocatable :: d2gm(:,:,:,:),dgm(:,:,:),eltfrxc_tmp(:,:)
     172           37 :  real(dp),allocatable :: eltfrxc_tmp2(:,:),elt_work(:,:),rho0_redgr(:,:,:)
     173           37 :  real(dp),allocatable :: vxc10(:,:),vxc10_core(:),vxc10_coreg(:,:)
     174           37 :  real(dp),allocatable :: vxc1is_core(:),vxc1is_coreg(:,:),vxc_core(:)
     175           37 :  real(dp),allocatable :: vxc_coreg(:,:),work(:),workgr(:,:),xccc1d(:,:,:)
     176           37 :  real(dp),allocatable :: xccc3d1(:),xccc3d1_temp(:,:),xcccrc(:)
     177           37 :  real(dp),pointer :: rhor_(:,:)
     178           37 :  type(pawtab_type),allocatable :: pawtab_test(:)
     179              : 
     180              : ! *************************************************************************
     181              : 
     182              : !Initialize variables
     183           37 :  cplex=1
     184           37 :  qphon(:)=zero
     185           37 :  n1=ngfft(1)
     186           37 :  n2=ngfft(2)
     187           37 :  n3=ngfft(3)
     188              : 
     189           37 :  n1xccc = psps%n1xccc
     190           37 :  if(psps%usepaw==0)then
     191           75 :    ABI_MALLOC(xcccrc,(dtset%ntypat))
     192          100 :    ABI_MALLOC(xccc1d,(n1xccc,6,dtset%ntypat))
     193           89 :    xcccrc = psps%xcccrc
     194       375473 :    xccc1d = psps%xccc1d
     195              :  end if
     196              : 
     197           37 :  if (usexcnhat==0.and.dtset%usepaw==1) then
     198            8 :    ABI_MALLOC(rhor_,(nfft,dtset%nspden))
     199        31112 :    rhor_(:,:) = rhor(:,:)-nhat(:,:)
     200              :  else
     201           35 :    rhor_ => rhor
     202              :  end if
     203              : 
     204              : !HACK - should be fixed globally
     205           37 :  if(n1xccc==0) then
     206            9 :    n3xccc_loc=0
     207              :  else
     208           28 :    n3xccc_loc=n3xccc
     209              :  end if
     210              : 
     211           37 :  fgga=0 ; if(nkxc==7.or.nkxc==19) fgga=1
     212           37 :  nmxc=(dtset%usepaw==1.and.mod(abs(dtset%usepawu),10)==4)
     213              : 
     214          185 :  ABI_MALLOC(eltfrxc_tmp,(6+3*dtset%natom,6))
     215           74 :  ABI_MALLOC(eltfrxc_tmp2,(6+3*dtset%natom,6))
     216          148 :  ABI_MALLOC(vxc10,(nfft,dtset%nspden))
     217          111 :  ABI_MALLOC(xccc3d1,(cplex*nfft))
     218              : 
     219           37 :  if(n1xccc/=0) then
     220           56 :    ABI_MALLOC(vxc_core,(nfft))
     221           56 :    ABI_MALLOC(vxc10_core,(nfft))
     222           56 :    ABI_MALLOC(vxc1is_core,(nfft))
     223              : 
     224           28 :    if(dtset%nspden==1) then
     225       175399 :      vxc_core(:)=vxc(:,1)
     226              :    else
     227        11666 :      vxc_core(:)=0.5_dp*(vxc(:,1)+vxc(:,2))
     228              :    end if
     229              :  end if
     230              : 
     231              : !Compute gmet, gprimd and ucvol from rprimd
     232           37 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     233              : 
     234              : !For GGA case, prepare quantities needed to evaluate contributions
     235              : !arising from the strain dependence of the gradient operator itself
     236              : 
     237           37 :  if(fgga==1) then
     238           16 :    ABI_MALLOC(rho0_redgr,(3,nfft,dtset%nspden))
     239            8 :    ABI_MALLOC(work,(nfft))
     240           12 :    ABI_MALLOC(workgr,(nfft,3))
     241              : 
     242              : !  Set up metric tensor derivatives
     243            4 :    ABI_MALLOC(dgm,(3,3,6))
     244            4 :    ABI_MALLOC(d2gm,(3,3,6,6))
     245              : !  Loop over 2nd strain index
     246           28 :    do is2=1,6
     247           24 :      kg=idx(2*is2-1);kd=idx(2*is2)
     248           96 :      do jj = 1,3
     249          312 :        dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
     250              :      end do
     251              : 
     252              : !    Loop over 1st strain index
     253          172 :      do is1=1,6
     254          144 :        ka=idx(2*is1-1);kb=idx(2*is1)
     255         1872 :        d2gm(:,:,is1,is2)=0._dp
     256          576 :        do jj = 1,3
     257          432 :          if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
     258          672 : &         +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
     259          432 :          if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
     260          480 : &         +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
     261          432 :          if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
     262          480 : &         +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
     263          432 :          if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
     264          816 : &         +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
     265              :        end do
     266         1896 :        d2gm(:,:,is1,is2)=0.5_dp*d2gm(:,:,is1,is2)
     267              :      end do
     268              :    end do
     269              : 
     270              : !  Compute the reduced gradients of the zero-order charge density.
     271              : !  Note that in the spin-polarized case, we are computing the reduced
     272              : !  gradients of 2 X the spin-up or spin-down charge.  This simplifies
     273              : !  subsequent code for the non-spin-polarized case.
     274            4 :    if(dtset%nspden==1) then
     275        12878 :      work(:)=rhor_(:,1)
     276              :    else
     277         5833 :      work(:)=2.0_dp*rhor_(:,2)
     278              :    end if
     279            4 :    if(n1xccc/=0) then
     280        13834 :      work(:)=work(:)+xccc3d(:)
     281              :    end if
     282            4 :    call redgr (work,workgr,mpi_enreg,nfft,ngfft)
     283        18711 :    do ifft=1,nfft
     284        74832 :      rho0_redgr(:,ifft,1)=workgr(ifft,:)
     285              :    end do
     286            4 :    if(dtset%nspden==2) then
     287         5833 :      work(:)=2.0_dp*(rhor_(:,1)-rhor_(:,2))
     288            1 :      if(n1xccc/=0) then
     289         5833 :        work(:)=work(:)+xccc3d(:)
     290              :      end if
     291            1 :      call redgr(work,workgr,mpi_enreg,nfft,ngfft)
     292         5833 :      do ifft=1,nfft
     293        23329 :        rho0_redgr(:,ifft,2)=workgr(ifft,:)
     294              :      end do
     295              :    end if
     296            4 :    ABI_FREE(work)
     297            4 :    ABI_FREE(workgr)
     298              :  end if !GGA
     299              : 
     300              : !Null the elastic tensor accumulator
     301         9849 :  eltfrxc(:,:)=zero;eltfrxc_tmp(:,:)=zero;eltfrxc_tmp2(:,:) = zero
     302              : 
     303              : !Normalization factor
     304           37 :  if(dtset%nspden==1) then
     305              :    spnorm=one
     306              :  else
     307            2 :    spnorm=half
     308              :  end if
     309              : 
     310              : !Big loop over 2nd strain index
     311          259 :  do is2=1,6
     312              : 
     313              : !  Translate strain index as needed by dfpt_mkcore below.
     314          222 :    if(is2<=3) then
     315          111 :      ipert=dtset%natom+3
     316          111 :      idir=is2
     317              :    else
     318          111 :      ipert=dtset%natom+4
     319          111 :      idir=is2-3
     320              :    end if
     321              : 
     322              : !  Generate first-order core charge for is2 strain if core charges are present.
     323          222 :    if(n1xccc/=0)then
     324              : 
     325          168 :      if (psps%usepaw==1 .or. psps%nc_xccc_gspace==1) then
     326              : !      Calculation in Reciprocal space for paw or NC with nc_xccc_gspace
     327          144 :        ABI_MALLOC(xccc3d1_temp,(cplex*nfft,1))
     328       653328 :        xccc3d1_temp = zero
     329              : 
     330              :        call dfpt_atm2fft(atindx,cplex,gmet,gprimd,gsqcut,is2,ipert,&
     331              : &       mgfft,psps%mqgrid_vl,dtset%natom,1,nfft,ngfftf,dtset%ntypat,&
     332              : &       ph1d,psps%qgrid_vl,qphon,dtset%typat,ucvol,psps%usepaw,xred,psps,pawtab,&
     333              : &       atmrhor1=xccc3d1_temp,optn2_in=1,&
     334              : &       comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
     335           72 : &       paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
     336       653256 :        xccc3d1(:) = xccc3d1_temp(:,1)
     337           72 :        ABI_FREE(xccc3d1_temp)
     338              : 
     339              :      else
     340              : !      Calculation in direct space for norm conserving:
     341              :        call dfpt_mkcore(cplex,idir,ipert,dtset%natom,dtset%ntypat,n1,n1xccc,&
     342              : &       n2,n3,qphon,rprimd,dtset%typat,ucvol,&
     343           96 : &       xcccrc,xccc1d,xccc3d1,xred)
     344              :      end if
     345              :    else
     346       229116 :      xccc3d1(:)=zero
     347              :    end if
     348              : 
     349              : !  Compute the first-order potentials.
     350              : !  Standard first-order potential for LDA and GGA with core charge
     351          222 :    if(fgga==0 .or. (fgga==1 .and. n1xccc/=0)) then
     352          210 :      option=0
     353              :      call dfpt_mkvxcstr(cplex,idir,ipert,kxc,mpi_enreg,dtset%natom,nfft,ngfft,nhat,&
     354              : &     dummy_in,nkxc,nmxc,dtset%nspden,n3xccc_loc,option,qphon,rhor,rhor,&
     355          210 : &     rprimd,dtset%usepaw,usexcnhat,vxc10,xccc3d1)
     356          210 :      if(n1xccc/=0)then
     357          168 :        if(dtset%nspden==1) then
     358      1052394 :          vxc10_core(:)=vxc10(:,1)
     359      1052394 :          vxc1is_core(:)=vxc10(:,1)
     360              :        else
     361        69996 :          vxc10_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
     362        69996 :          vxc1is_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
     363              :        end if
     364              :      end if
     365              :    end if
     366              : 
     367              : !  For GGA, first-order potential with doubled gradient operator strain
     368              : !  derivative terms needed for elastic tensor but not internal strain.
     369          222 :    if(fgga==1) then
     370           24 :      option=2
     371              :      call dfpt_mkvxcstr(cplex,idir,ipert,kxc,mpi_enreg,dtset%natom,nfft,ngfft,nhat,&
     372              : &     dummy_in,nkxc,nmxc,dtset%nspden,n3xccc_loc,option,qphon,rhor,rhor,&
     373           24 : &     rprimd,dtset%usepaw,usexcnhat,vxc10,xccc3d1)
     374           24 :      if(n1xccc/=0)then
     375           12 :        if(dtset%nspden==1) then
     376        48006 :          vxc10_core(:)=vxc10(:,1)
     377              :        else
     378        34998 :          vxc10_core(:)=0.5_dp*(vxc10(:,1)+vxc10(:,2))
     379              :        end if
     380              :      end if
     381              :    end if
     382              : 
     383              : 
     384              : !  Additional term for diagonal strains.
     385          222 :    if(is2<=3) then
     386       710862 :      vxc10(:,:)=vxc10(:,:)+vxc(:,:)
     387          111 :      if(n1xccc/=0) then
     388       561195 :        vxc10_core(:)=vxc10_core(:)+2.0_dp*vxc_core(:)
     389       561195 :        vxc1is_core(:)=vxc1is_core(:)+vxc_core(:)
     390              :      end if
     391              :    end if
     392              : 
     393              : !  For GGA, compute the contributions from the strain derivatives acting
     394              : !  on the gradient operators.
     395          222 :    if(fgga==1) then
     396              : 
     397           24 :      if (dtset%nspden==1) then
     398        77268 :        do ifft=1,nfft
     399              : !        Collect the needed derivatives of Exc.  The factors introduced
     400              : !        deal with the difference between density as used here and
     401              : !        spin density as used with these kxc terms in other contexts.
     402        77250 :          dexdgs  =half   *kxc(ifft,2)
     403        77250 :          d2exdgs2=quarter*kxc(ifft,4)
     404              : !        Loop over 1st strain index
     405       540768 :          do is1=1,6
     406              : !          The notation here is .gs... for the derivatives of the squared-
     407              : !          gradient of (2X) each spin density, and .gst... for the total density.
     408              :            dgsds10=zero;dgsds20=zero;d2gsds1ds2=zero
     409      1854000 :            do jj=1,3
     410      6025500 :              do ii=1,3
     411      4171500 :                tmp0=rho0_redgr(ii,ifft,1)*rho0_redgr(jj,ifft,1)
     412      4171500 :                dgsds10=dgsds10+dgm(ii,jj,is1)*tmp0
     413      4171500 :                dgsds20=dgsds20+dgm(ii,jj,is2)*tmp0
     414      5562000 :                d2gsds1ds2=d2gsds1ds2+d2gm(ii,jj,is1,is2)*tmp0
     415              :              end do
     416              :            end do
     417              : !          Volume derivative terms added
     418       463500 :            if(is1<=3) d2gsds1ds2=d2gsds1ds2+dgsds20
     419       463500 :            if(is2<=3) d2gsds1ds2=d2gsds1ds2+dgsds10
     420              : !          Add the gradient derivative terms to eltfrxc.
     421       540750 :            eltfrxc(is1,is2)=eltfrxc(is1,is2)+d2exdgs2*dgsds10*dgsds20+dexdgs*d2gsds1ds2
     422              :          end do !is1
     423              :        end do !ifft
     424              : 
     425              :      else ! nspden==2
     426              : 
     427           18 :        do ispden=1,dtset%nspden
     428           12 :          ispden_c=dtset%nspden-ispden+1
     429              : 
     430        70002 :          do ifft=1,nfft
     431              : 
     432              : !          Collect the needed derivatives of Exc.  The factors introduced
     433              : !          deal with the difference between density as used here and
     434              : !          spin density as used with these kxc terms in other contexts.
     435        69984 :            dexdgs  =quarter       *kxc(ifft,3+ispden)
     436        69984 :            d2exdgs2=quarter*eighth*kxc(ifft,7+ispden)
     437        69984 :            decdgs  =eighth        *kxc(ifft,10)
     438        69984 :            d2ecdgs2=eighth*eighth *kxc(ifft,13)
     439              : 
     440              : !          Loop over 1st strain index
     441       489900 :            do is1=1,6
     442              : 
     443              : !            The notation here is .gs... for the derivatives of the squared-
     444              : !            gradient of (2X) each spin density, and .gst... for the total
     445              : !            density.  Note the hack that the the total density is given
     446              : !            by the same expression for either the non-polarized or spin-
     447              : !            polarized case, implemented with the "complementary" index ispden_c
     448              : !            in the expression for tmp0t below.
     449              :              dgsds10=zero;dgsds20=zero;d2gsds1ds2=zero
     450              :              dgstds10=zero;dgstds20=zero;d2gstds1ds2=zero
     451      1679616 :              do jj=1,3
     452      5458752 :                do ii=1,3
     453      3779136 :                  tmp0=rho0_redgr(ii,ifft,ispden)*rho0_redgr(jj,ifft,ispden)
     454              :                  tmp0t=(rho0_redgr(ii,ifft,ispden)+rho0_redgr(ii,ifft,ispden_c))&
     455      3779136 : &                 *(rho0_redgr(jj,ifft,ispden)+rho0_redgr(jj,ifft,ispden_c))
     456      3779136 :                  dgsds10=dgsds10+dgm(ii,jj,is1)*tmp0
     457      3779136 :                  dgsds20=dgsds20+dgm(ii,jj,is2)*tmp0
     458      3779136 :                  dgstds10=dgstds10+dgm(ii,jj,is1)*tmp0t
     459      3779136 :                  dgstds20=dgstds20+dgm(ii,jj,is2)*tmp0t
     460      3779136 :                  d2gsds1ds2=d2gsds1ds2+d2gm(ii,jj,is1,is2)*tmp0
     461      5038848 :                  d2gstds1ds2=d2gstds1ds2+d2gm(ii,jj,is1,is2)*tmp0t
     462              :                end do
     463              :              end do
     464              : !            Volume derivative terms added
     465       419904 :              if(is1<=3) then
     466       209952 :                d2gsds1ds2=d2gsds1ds2+dgsds20
     467       209952 :                d2gstds1ds2=d2gstds1ds2+dgstds20
     468              :              end if
     469       419904 :              if(is2<=3) then
     470       209952 :                d2gsds1ds2=d2gsds1ds2+dgsds10
     471       209952 :                d2gstds1ds2=d2gstds1ds2+dgstds10
     472              :              end if
     473              : 
     474              : !            Add the gradient derivative terms to eltfrxc.
     475              :              eltfrxc(is1,is2)=eltfrxc(is1,is2)+spnorm*&
     476              : &             (d2exdgs2*(dgsds10 *dgsds20) + dexdgs*d2gsds1ds2&
     477       489888 : &             +d2ecdgs2*(dgstds10*dgstds20)+ decdgs*d2gstds1ds2)
     478              : 
     479              :            end do !is1
     480              :          end do !ifft
     481              :        end do !ispden
     482              : 
     483              :      end if ! nspden
     484              : 
     485              :    end if !GGA
     486              : 
     487              : !  Compute valence electron 1st-order charge contributions.  Recall that
     488              : !  the diagonal strain derivatives of the valence charge are minus the
     489              : !  zero-order density.  The explicit symmetrization avoids the need
     490              : !  to store vxc10 for strain indices other than is2.
     491              : 
     492              :    call dotprod_vn(1,rhor_,d2eacc,valuei,nfft,nfft,dtset%nspden,1,&
     493          222 : &   vxc10,ucvol)
     494          888 :    do is1=1,3
     495          666 :      eltfrxc_tmp(is1,is2)=eltfrxc_tmp(is1,is2)-0.5_dp*d2eacc
     496          888 :      eltfrxc_tmp(is2,is1)=eltfrxc_tmp(is2,is1)-0.5_dp*d2eacc
     497              :    end do
     498              : 
     499              : !  Compute additional core contributions from is1 perturbation
     500              : !  Internal strain terms calculated here.
     501          222 :    if(n1xccc/=0) then
     502              : 
     503          168 :      if (psps%usepaw==1 .or. psps%nc_xccc_gspace==1) then
     504              : !      Calculation in Reciprocal space for paw or NC with nc_xccc_gspace
     505           72 :        optatm=0;optdyfr=0;optgr=0;optstr=0;optv=0;optn=n3xccc/nfft;optn2=1;opteltfr=1
     506          216 :        ABI_MALLOC(vxc10_coreg,(2,nfft))
     507          144 :        ABI_MALLOC(vxc_coreg,(2,nfft))
     508          216 :        ABI_MALLOC(vxc1is_coreg,(2,nfft))
     509              : 
     510      5878872 :        vxc10_coreg(:,:)=zero;vxc10_coreg(:,:)=zero;vxc1is_coreg(:,:)=zero;
     511              : 
     512              : !      Fourier transform of Vxc_core/vxc10_core to use in atm2fft (reciprocal space calculation)
     513           72 :        call fourdp(1,vxc10_coreg,vxc10_core,-1,mpi_enreg,nfft,1, ngfft,0)
     514           72 :        call fourdp(1,vxc_coreg,vxc_core,-1,mpi_enreg,nfft,1, ngfft, 0)
     515           72 :        call fourdp(1,vxc1is_coreg,vxc1is_core,-1,mpi_enreg,nfft,1, ngfft, 0)
     516              : 
     517              :        call atm2fft(atindx,dummy_out1,dummy_out2,dummy_out3,dummy_out4,eltfrxc_tmp2,dummy_in,gmet,gprimd,&
     518              : &       dummy_out5,dummy_out6,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,dtset%ntypat,&
     519              : &       optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab,ph1d,psps%qgrid_vl,dtset%qprtrb,&
     520              : &       dtset%rcut,dummy_in,rprimd,strn_dummy6,strv_dummy6,ucvol,psps%usepaw,&
     521              : &       vxc_coreg,vxc10_coreg,vxc1is_coreg,dtset%vprtrb,psps%vlspl,is2_in=is2,&
     522              : &       comm_fft=mpi_enreg%comm_fft,me_g0=mpi_enreg%me_g0,&
     523           72 : &       paral_kgb=mpi_enreg%paral_kgb,distribfft=mpi_enreg%distribfft)
     524              : 
     525              : !       The indexing array atindx is used to reestablish the correct order of atoms
     526          288 :        ABI_MALLOC(elt_work,(6+3*dtset%natom,6))
     527         3096 :        elt_work(1:6,1:6)=eltfrxc_tmp2(1:6,1:6)
     528          324 :        do ia=1,dtset%natom
     529          252 :          ielt=7+3*(ia-1)
     530          252 :          ieltx=7+3*(atindx(ia)-1)
     531         6372 :          elt_work(ielt:ielt+2,1:6)=eltfrxc_tmp2(ieltx:ieltx+2,1:6)
     532              :        end do
     533         7632 :        eltfrxc_tmp2(:,:)=elt_work(:,:)
     534           72 :        ABI_FREE(elt_work)
     535              : 
     536              : 
     537           72 :        ABI_FREE(vxc10_coreg)
     538           72 :        ABI_FREE(vxc_coreg)
     539           72 :        ABI_FREE(vxc1is_coreg)
     540         7632 :        eltfrxc(:,:)= eltfrxc(:,:) + eltfrxc_tmp2(:,:)
     541              : 
     542              :      else
     543              : 
     544              :        call eltxccore(eltfrxc,is2,mpi_enreg%my_natom,dtset%natom,nfft,dtset%ntypat,&
     545              : &       n1,n1xccc,n2,n3,rprimd,dtset%typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
     546           96 : &       xcccrc,xccc1d,xred,mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom)
     547              : 
     548              : !DEBUG
     549              : !      TEST ZONE (DO NOT REMOVE) USE TO RECIPROCAL SPACE IN NC CASE
     550           96 :        if (dtset%userid==567) then
     551            0 :          eltfrxc_test1(:,is2)=zero;eltfrxc_test2(:,is2)=zero
     552              :          call eltxccore(eltfrxc_test1,is2,mpi_enreg%my_natom,dtset%natom,nfft,dtset%ntypat,&
     553              : &         n1,n1xccc,n2,n3,rprimd,dtset%typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
     554            0 : &         xcccrc,xccc1d,xred,mpi_atmtab=mpi_enreg%my_atmtab,comm_atom=mpi_enreg%comm_atom)
     555              : !        if (is2==1) print*,"elt-frxc from eltxccore",is2,eltfrxc_test1(1,1)*ucvol/dble(nfft)
     556            0 :          ABI_MALLOC(pawtab_test,(dtset%ntypat))
     557            0 :          call pawtab_nullify(pawtab_test)
     558            0 :          do jj=1,dtset%ntypat
     559            0 :            pawtab_test(jj)%mqgrid=psps%mqgrid_vl
     560            0 :            ABI_MALLOC(pawtab_test(jj)%tcorespl,(pawtab_test(jj)%mqgrid,2))
     561            0 :            rstep=xcccrc(jj)/dble(n1xccc-1)
     562            0 :            call pawrad_init(mesh=core_mesh,mesh_size=n1xccc,mesh_type=1,rstep=rstep)
     563              :            call pawpsp_cg(pawtab_test(jj)%dncdq0,pawtab_test(jj)%d2ncdq0,psps%mqgrid_vl,psps%qgrid_vl,&
     564            0 : &           pawtab_test(jj)%tcorespl(:,1),core_mesh,xccc1d(:,1,jj),yp1,ypn)
     565            0 :            call paw_spline(psps%qgrid_vl,pawtab_test(jj)%tcorespl(:,1),psps%mqgrid_vl,yp1,ypn,pawtab_test(jj)%tcorespl(:,2))
     566              : !          if (is2==1) then
     567              : !            do ii=1,n1xccc;write(100+jj,*) (ii-1)*rstep,xccc1d(ii,1,jj);enddo
     568              : !            do ii=1,psps%mqgrid_vl;write(200+jj,*) psps%qgrid_vl(ii),pawtab_test(jj)%tcorespl(ii,1);enddo
     569              : !          end if
     570              :          end do
     571            0 :          ABI_MALLOC(vxc10_coreg,(2,nfft))
     572            0 :          ABI_MALLOC(vxc_coreg,(2,nfft))
     573            0 :          ABI_MALLOC(vxc1is_coreg,(2,nfft))
     574            0 :          vxc10_coreg(:,:)=zero;vxc10_coreg(:,:)=zero;vxc1is_coreg(:,:)=zero;
     575            0 :          call fourdp(1,vxc10_coreg,vxc10_core,-1,mpi_enreg,nfft,1, ngfft, 0)
     576            0 :          call fourdp(1,vxc_coreg,vxc_core,-1,mpi_enreg,nfft,1, ngfft,0)
     577            0 :          call fourdp(1,vxc1is_coreg,vxc1is_core,-1,mpi_enreg,nfft,1, ngfft, 0)
     578            0 :          optatm=0;optdyfr=0;optgr=0;optstr=0;optv=0;optn=1;optn2=1;opteltfr=1;corstr=zero
     579              :          call atm2fft(atindx,dummy_out1,dummy_out2,dummy_out3,dummy_out4,eltfrxc_test2,dummy_in,gmet,gprimd,&
     580              : &         dummy_out5,dummy_out6,gsqcut,mgfft,psps%mqgrid_vl,dtset%natom,nattyp,nfft,ngfft,dtset%ntypat,&
     581              : &         optatm,optdyfr,opteltfr,optgr,optn,optn2,optstr,optv,psps,pawtab_test,ph1d,psps%qgrid_vl,dtset%qprtrb,&
     582              : &         dtset%rcut,dummy_in,rprimd,corstr,dummy6,ucvol,psps%usepaw,&
     583            0 : &         vxc_coreg,vxc10_coreg,vxc1is_coreg,dtset%vprtrb,psps%vlspl,is2_in=is2)
     584            0 :          ABI_FREE(vxc10_coreg)
     585            0 :          ABI_FREE(vxc_coreg)
     586            0 :          ABI_FREE(vxc1is_coreg)
     587            0 :          call pawrad_free(core_mesh)
     588            0 :          call pawtab_free(pawtab_test)
     589            0 :          ABI_FREE(pawtab_test)
     590            0 :          eltfrxc(:,:)= eltfrxc(:,:)+eltfrxc_test2(:,:)
     591              : !        if (is2==1) print*,"cor-str from atm2fft",is2,corstr*ucvol
     592              : !        if (is2==1) print*,"elt-frxc from atm2fft  ",is2,eltfrxc_test2(1,1)
     593              :        end if
     594              : !DEBUG
     595              : 
     596              :      end if
     597              :    end if
     598              : 
     599              : !  Additional term for diagonal strains
     600          259 :    if(is2<=3) then
     601          444 :      do is1=1,3
     602          444 :        eltfrxc_tmp(is1,is2)=eltfrxc_tmp(is1,is2)+enxc
     603              :      end do
     604              :    end if
     605              :  end do !is2 outermost strain loop
     606              : 
     607              : !Accumulate eltfrxc accross processors
     608           37 :  call timab(48,1,tsec)
     609           37 :  call xmpi_sum(eltfrxc,mpi_enreg%comm_fft,ierr)
     610           37 :  call timab(48,2,tsec)
     611              : 
     612              :  !Normalize accumulated 2nd derivatives in NC case
     613           37 :  if(psps%usepaw==1)then
     614         1272 :    eltfrxc(:,:)=eltfrxc_tmp(:,:)+eltfrxc
     615              :  else
     616         2011 :    eltfrxc(:,:)=eltfrxc_tmp(:,:)+eltfrxc*ucvol/dble(nfft)
     617              :  end if
     618              : 
     619           37 :  ABI_FREE(eltfrxc_tmp)
     620           37 :  ABI_FREE(eltfrxc_tmp2)
     621           37 :  ABI_FREE(vxc10)
     622           37 :  ABI_FREE(xccc3d1)
     623           37 :  if(psps%usepaw==0)then
     624           25 :    ABI_FREE(xccc1d)
     625           25 :    ABI_FREE(xcccrc)
     626              :  end if
     627           37 :  if (usexcnhat==0.and.dtset%usepaw==1) then
     628            2 :    ABI_FREE(rhor_)
     629              :  end if
     630              : 
     631           37 :  if(n1xccc/=0) then
     632           28 :    ABI_FREE(vxc_core)
     633           28 :    ABI_FREE(vxc10_core)
     634           28 :    ABI_FREE(vxc1is_core)
     635              :  end if
     636              : 
     637           37 :  if(fgga==1) then
     638            4 :    ABI_FREE(rho0_redgr)
     639            4 :    ABI_FREE(dgm)
     640            4 :    ABI_FREE(d2gm)
     641              :  end if
     642              : 
     643           74 : end subroutine dfpt_eltfrxc
     644              : !!***
     645              : 
     646              : !!****f* ABINIT/eltxccore
     647              : !! NAME
     648              : !! eltxccore
     649              : !!
     650              : !! FUNCTION
     651              : !! Compute the core charge contributions to the 2nd derivatives
     652              : !! of the exchange-correlation energy with respect to all pairs of
     653              : !! strain or strain and atomic displacement for the frozen wavefunction
     654              : !! contribution to the elastic tensor. 1st-order potentials representing
     655              : !! the perturbation by one strain are supplied, and the routine loops
     656              : !! over the second strain and over all atomic displacements.
     657              : !!
     658              : !! COPYRIGHT
     659              : !! Copyright (C) 1998-2026 ABINIT group (DRH, DCA, XG, GMR)
     660              : !! This file is distributed under the terms of the
     661              : !! GNU General Public License, see ~abinit/COPYING
     662              : !! or http://www.gnu.org/copyleft/gpl.txt .
     663              : !!
     664              : !! INPUTS
     665              : !!  mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
     666              : !!  comm_atom=--optional-- MPI communicator over atoms
     667              : !!  my_natom=number of atoms treated by current processor
     668              : !!  natom=number of atoms in cell.
     669              : !!  nfft=number of fft grid points
     670              : !!  ntypat=number of types of atoms in cell.
     671              : !!  n1,n2,n3=fft grid dimensions.
     672              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
     673              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
     674              : !!  typat(natom)=integer type for each atom in cell
     675              : !!  ucvol=unit cell volume (bohr**3).
     676              : !!  vxc_core(nfft)=spin-averaged xc potential
     677              : !!  vxc10_core(nfft)=spin-averaged 1st-order xc potential for elastic tensor
     678              : !!  vxc1is_core(nfft)=spin-averaged 1st-order xc potential for internal strain
     679              : !!  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
     680              : !!  xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
     681              : !!   for each type of atom, from psp
     682              : !!  xred(3,natom)=reduced coordinates for atoms in unit cell
     683              : !!
     684              : !! OUTPUT
     685              : !!  eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
     686              : !!   elastic tensor
     687              : !!
     688              : !! SIDE EFFECTS
     689              : !!  eltfrxc(6+3*natom,6) = xc frozen wavefunction contribution to the
     690              : !!   elastic and internal-strain tensor.  One column is incremented
     691              : !!   by the core contribution.
     692              : !!
     693              : !! NOTES
     694              : !! Note that this routine is related to the mkcore.f routine
     695              : !!
     696              : !! SOURCE
     697              : 
     698          192 : subroutine eltxccore(eltfrxc,is2_in,my_natom,natom,nfft,ntypat,&
     699           96 : & n1,n1xccc,n2,n3,rprimd,typat,ucvol,vxc_core,vxc10_core,vxc1is_core,&
     700           96 : & xcccrc,xccc1d,xred, &
     701           96 : & mpi_atmtab,comm_atom) ! optional arguments (parallelism)
     702              : 
     703              : !Arguments ------------------------------------
     704              : !scalars
     705              :  integer,intent(in) :: is2_in,n1,n1xccc,n2,n3,my_natom,natom,nfft,ntypat
     706              :  integer,optional,intent(in) :: comm_atom
     707              :  real(dp),intent(in) :: ucvol
     708              : !arrays
     709              :  integer,intent(in) :: typat(natom)
     710              :  integer,optional,target,intent(in) :: mpi_atmtab(:)
     711              :  real(dp),intent(in) :: vxc10_core(nfft),vxc1is_core(nfft)
     712              :  real(dp),intent(in) :: vxc_core(nfft),xccc1d(n1xccc,6,ntypat)
     713              :  real(dp),intent(in) :: xcccrc(ntypat),xred(3,natom)
     714              :  real(dp),intent(inout) :: eltfrxc(6+3*natom,6),rprimd(3,3)
     715              : 
     716              : !Local variables-------------------------------
     717              : !scalars
     718              :  integer,parameter :: mshift=401
     719              :  integer :: i1,i2,i3,iat,iatom,ierr,ifft,is1,is2,ishift,ishift1,ishift2
     720              :  integer :: ishift3,ixp,jj,js,ka,kb,kd,kg,mu,my_comm_atom,nu
     721              :  logical :: my_atmtab_allocated,paral_atom
     722              :  real(dp) :: aa,bb,cc,d2rss,dd,delta,delta2div6,deltam1,diff
     723              :  real(dp) :: difmag,difmag2,difmag2_fact,difmag2_part,drss1,drss2,func1
     724              :  real(dp) :: func2,range,range2,rangem1,rdiff1,rdiff2,rdiff3
     725              :  real(dp) :: term1,term2,yy
     726              :  character(len=500) :: message
     727              : !arrays
     728              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
     729              :  integer :: igrid(3),ii(mshift,3),irange(3),ngfft(3)
     730           96 :  integer,pointer :: my_atmtab(:)
     731          192 :  real(dp) :: drm(3,3,6),eltfrxc_core(6+3*natom,6),lencp(3),rmet(3,3),rrdiff(mshift,3)
     732              :  real(dp) :: scale(3),tau(3),ts2(3),tsec(2),tt(3)
     733           96 :  real(dp),allocatable :: d2rm(:,:,:,:)
     734              : 
     735              : ! *************************************************************************
     736              : 
     737              : !Compute lengths of cross products for pairs of primitive
     738              : !translation vectors (used in setting index search range below)
     739              :  lencp(1)=cross_elt(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
     740           96 : & rprimd(1,3),rprimd(2,3),rprimd(3,3))
     741              :  lencp(2)=cross_elt(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
     742           96 : & rprimd(1,1),rprimd(2,1),rprimd(3,1))
     743              :  lencp(3)=cross_elt(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
     744           96 : & rprimd(1,2),rprimd(2,2),rprimd(3,2))
     745              : 
     746              : !Set up parallelism over atoms
     747           96 :  paral_atom=(present(comm_atom).and.(my_natom/=natom))
     748           96 :  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
     749           96 :  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
     750           96 :  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
     751              : 
     752              : !Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
     753              : !(recall ucvol=R1.(R2xR3))
     754          384 :  scale(:)=ucvol/lencp(:)
     755              : 
     756              : !Compute metric tensor in real space rmet
     757          384 :  do nu=1,3
     758              :    rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+&
     759         1248 : &   rprimd(3,:)*rprimd(3,nu)
     760              :  end do
     761              : 
     762              : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
     763              : !and store for use in inner loop below.
     764              : 
     765           96 :  ABI_MALLOC(d2rm,(3,3,6,6))
     766              : 
     767              : !Loop over 2nd strain index
     768          672 :  do is2=1,6
     769          576 :    kg=idx(2*is2-1);kd=idx(2*is2)
     770         2304 :    do jj = 1,3
     771         7488 :      drm(:,jj,is2)=rprimd(kg,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kg,jj)
     772              :    end do
     773              : 
     774              : !  Loop over 1st strain index
     775         4128 :    do is1=1,6
     776              : 
     777         3456 :      ka=idx(2*is1-1);kb=idx(2*is1)
     778        44928 :      d2rm(:,:,is1,is2)=0._dp
     779        14400 :      do jj = 1,3
     780        10368 :        if(ka==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
     781        16128 : &       +rprimd(kb,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kb,jj)
     782        10368 :        if(ka==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
     783        11520 : &       +rprimd(kb,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(kb,jj)
     784        10368 :        if(kb==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
     785        11520 : &       +rprimd(ka,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(ka,jj)
     786        10368 :        if(kb==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
     787        19584 : &       +rprimd(ka,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(ka,jj)
     788              :      end do
     789              :    end do !is1
     790              :  end do !is2
     791              : 
     792           96 :  ngfft(1)=n1
     793           96 :  ngfft(2)=n2
     794           96 :  ngfft(3)=n3
     795           96 :  delta=1.0_dp/(n1xccc-1)
     796           96 :  deltam1=n1xccc-1
     797           96 :  delta2div6=delta**2/6.0_dp
     798              : 
     799              : !Loop over atoms in unit cell
     800         7476 :  eltfrxc_core(:,:)=zero
     801              : 
     802          282 :  do iat=1,my_natom
     803          186 :    iatom=iat;if (paral_atom) iatom=my_atmtab(iat)
     804          186 :    js=7+3*(iatom-1)
     805              : !  Set search range (density cuts off perfectly beyond range)
     806              : !  Cycle if no range.
     807          186 :    range=0.0_dp
     808          186 :    range=xcccrc(typat(iatom))
     809          186 :    if(range<1.d-16) cycle
     810              : 
     811          180 :    range2=range**2
     812          180 :    rangem1=1.0_dp/range
     813              : 
     814              : !  Consider each component in turn
     815          720 :    do mu=1,3
     816          540 :      tau(mu)=mod(xred(mu,iatom)+1._dp-aint(xred(mu,iatom)),1._dp)
     817              : 
     818              : !    Use tau to find nearest grid point along R(mu)
     819              : !    (igrid=0 is the origin; shift by 1 to agree with usual index)
     820          540 :      igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
     821              : 
     822              : !    Use range to compute an index range along R(mu)
     823              : !    (add 1 to make sure it covers full range)
     824          540 :      irange(mu)=1+nint((range/scale(mu))*dble(ngfft(mu)))
     825              : 
     826              : !    Check that the largest range is smallest than the maximum
     827              : !    allowed one
     828          540 :      if(2*irange(mu)+1 > mshift)then
     829            0 :        write(message, '(a,i0,a)' )' The range around atom',iatom,' is too large.'
     830            0 :        ABI_BUG(message)
     831              :      end if
     832              : 
     833              : !    Set up a counter that explore the relevant range
     834              : !    of points around the atom
     835          540 :      ishift=0
     836        19320 :      do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
     837        18600 :        ishift=ishift+1
     838        18600 :        ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
     839        19140 :        rrdiff(ishift,mu)=dble(ixp)/dble(ngfft(mu))-tau(mu)
     840              :      end do
     841              : 
     842              : !    End loop on mu
     843              :    end do
     844              : 
     845              : !  Conduct triple loop over restricted range of grid points for iatom
     846              : 
     847         6468 :    do ishift3=1,1+2*irange(3)
     848              : !    map back to [1,ngfft(3)] for usual fortran index in unit cell
     849         6192 :      i3=ii(ishift3,3)
     850              : !    find vector from atom location to grid point (reduced)
     851         6192 :      rdiff3=rrdiff(ishift3,3)
     852              : 
     853       226506 :      do ishift2=1,1+2*irange(2)
     854       220128 :        i2=ii(ishift2,2)
     855       220128 :        rdiff2=rrdiff(ishift2,2)
     856              : !      Prepare the computation of difmag2
     857              :        difmag2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2&
     858       220128 : &       +2.0_dp*rmet(3,2)*rdiff3*rdiff2
     859       220128 :        difmag2_fact=2.0_dp*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
     860              : 
     861      8302464 :        do ishift1=1,1+2*irange(1)
     862      8076144 :          rdiff1=rrdiff(ishift1,1)
     863              : 
     864              : !        Compute (rgrid-tau-Rprim)**2
     865      8076144 :          difmag2= difmag2_part+rdiff1*(difmag2_fact+rmet(1,1)*rdiff1)
     866              : 
     867              : !        Only accept contribution inside defined range
     868      8296272 :          if (difmag2<range2) then
     869              : 
     870              : !          Prepare computation of core charge function and derivatives,
     871              : !          using splines
     872      2641878 :            difmag=sqrt(difmag2)
     873      2641878 :            if (difmag>=1.0d-10) then
     874      2641764 :              i1=ii(ishift1,1)
     875      2641764 :              yy=difmag*rangem1
     876              : 
     877              : !            Compute index of yy over 1 to n1xccc scale
     878      2641764 :              jj=1+int(yy*(n1xccc-1))
     879      2641764 :              diff=yy-(jj-1)*delta
     880              : 
     881              : !            Will evaluate spline fit (p. 86 Numerical Recipes, Press et al;
     882              : !            NOTE error in book for sign of "aa" term in derivative;
     883              : !            also see splfit routine).
     884      2641764 :              bb = diff*deltam1
     885      2641764 :              aa = 1.0_dp-bb
     886      2641764 :              cc = aa*(aa**2-1.0_dp)*delta2div6
     887      2641764 :              dd = bb*(bb**2-1.0_dp)*delta2div6
     888              : 
     889              : !            Evaluate spline fit of 1st der of core charge density
     890              : !            from xccc1d(:,2,:) and (:,4,:)
     891              :              func1=aa*xccc1d(jj,2,typat(iatom))+bb*xccc1d(jj+1,2,typat(iatom)) +&
     892      2641764 : &             cc*xccc1d(jj,4,typat(iatom))+dd*xccc1d(jj+1,4,typat(iatom))
     893      2641764 :              term1=func1*rangem1
     894              : !            Evaluate spline fit of 2nd der of core charge density
     895              : !            from xccc1d(:,3,:) and (:,5,:)
     896              :              func2=aa*xccc1d(jj,3,typat(iatom))+bb*xccc1d(jj+1,3,typat(iatom)) +&
     897      2641764 : &             cc*xccc1d(jj,5,typat(iatom))+dd*xccc1d(jj+1,5,typat(iatom))
     898      2641764 :              term2=func2*rangem1**2
     899              : 
     900      2641764 :              ifft=i1+n1*(i2-1+n2*(i3-1))
     901     10567056 :              tt(:)=rmet(:,1)*rdiff1+rmet(:,2)*rdiff2+rmet(:,3)*rdiff3
     902              : 
     903              : !            Add contributions to 2nd derivative tensor
     904              :              drss2=&
     905              : &             (rdiff1*(drm(1,1,is2_in)*rdiff1+drm(1,2,is2_in)*rdiff2&
     906              : &             +drm(1,3,is2_in)*rdiff3)&
     907              : &             +rdiff2*(drm(2,1,is2_in)*rdiff1+drm(2,2,is2_in)*rdiff2&
     908              : &             +drm(2,3,is2_in)*rdiff3)&
     909              : &             +rdiff3*(drm(3,1,is2_in)*rdiff1+drm(3,2,is2_in)*rdiff2&
     910      2641764 : &             +drm(3,3,is2_in)*rdiff3))
     911              : 
     912              : !            Loop over 1st strain index
     913     18492348 :              do is1=1,6
     914              : 
     915              :                drss1=&
     916              : &               (rdiff1*(drm(1,1,is1)*rdiff1+drm(1,2,is1)*rdiff2&
     917              : &               +drm(1,3,is1)*rdiff3)&
     918              : &               +rdiff2*(drm(2,1,is1)*rdiff1+drm(2,2,is1)*rdiff2&
     919              : &               +drm(2,3,is1)*rdiff3)&
     920              : &               +rdiff3*(drm(3,1,is1)*rdiff1+drm(3,2,is1)*rdiff2&
     921     15850584 : &               +drm(3,3,is1)*rdiff3))
     922              : 
     923              :                d2rss=&
     924              : &               (rdiff1*(d2rm(1,1,is1,is2_in)*rdiff1+d2rm(1,2,is1,is2_in)*rdiff2&
     925              : &               +d2rm(1,3,is1,is2_in)*rdiff3)&
     926              : &               +rdiff2*(d2rm(2,1,is1,is2_in)*rdiff1+d2rm(2,2,is1,is2_in)*rdiff2&
     927              : &               +d2rm(2,3,is1,is2_in)*rdiff3)&
     928              : &               +rdiff3*(d2rm(3,1,is1,is2_in)*rdiff1+d2rm(3,2,is1,is2_in)*rdiff2&
     929     15850584 : &               +d2rm(3,3,is1,is2_in)*rdiff3))
     930              : 
     931              : !              Vall(0) X Rhocore(2) term
     932              :                eltfrxc_core(is1,is2_in)=eltfrxc_core(is1,is2_in)+0.25_dp*&
     933              : &               (vxc_core(ifft)*(term1*(d2rss/difmag&
     934              : &               -drss1*drss2/difmag**3)&
     935     15850584 : &               +term2*drss1*drss2/difmag**2))
     936              : 
     937              : !              Vall(1) X Rhocore(1) term
     938              :                eltfrxc_core(is1,is2_in)=eltfrxc_core(is1,is2_in)+0.25_dp*&
     939     15850584 : &               vxc10_core(ifft)*drss1*term1/difmag
     940              :                eltfrxc_core(is2_in,is1)=eltfrxc_core(is2_in,is1)+0.25_dp*&
     941     18492348 : &               vxc10_core(ifft)*drss1*term1/difmag
     942              : 
     943              : !              End loop in is1
     944              :              end do
     945              : !            Internal strain contributions
     946              :              ts2(:)=drm(:,1,is2_in)*rdiff1+drm(:,2,is2_in)*rdiff2&
     947     10567056 : &             +drm(:,3,is2_in)*rdiff3
     948              : 
     949              :              eltfrxc_core(js:js+2,is2_in)=eltfrxc_core(js:js+2,is2_in)&
     950              : &             -(vxc1is_core(ifft)*term1/difmag&
     951              : &             +0.5_dp*vxc_core(ifft)*(term2-term1/difmag)*drss2/difmag**2)*tt(:)&
     952     10567056 : &             -(vxc_core(ifft)*term1/difmag)*ts2(:)
     953              : 
     954              : !            End of the condition for the distance not to vanish
     955              :            end if
     956              : 
     957              : !          End of condition to be inside the range
     958              :          end if
     959              : 
     960              : !        End loop on ishift1
     961              :        end do
     962              : 
     963              : !      End loop on ishift2
     964              :      end do
     965              : 
     966              : !    End loop on ishift3
     967              :    end do
     968              : 
     969              : !  End loop on atoms
     970              :  end do
     971              : 
     972              : !In case of parallelism over atoms: communicate
     973           96 :  if (paral_atom) then
     974            0 :    call timab(48,1,tsec)
     975            0 :    call xmpi_sum(eltfrxc_core,my_comm_atom,ierr)
     976            0 :    call timab(48,2,tsec)
     977              :  end if
     978              : 
     979              : !Add core contribution to XC elastic tensor
     980         7476 :  eltfrxc(:,:)=eltfrxc(:,:)+eltfrxc_core(:,:)
     981              : 
     982              : !Destroy atom table used for parallelism
     983           96 :  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
     984              : 
     985          192 :  ABI_FREE(d2rm)
     986              : 
     987              :  contains
     988              : 
     989          288 :    function cross_elt(xx,yy,zz,aa,bb,cc)
     990              : !Define magnitude of cross product of two vectors
     991              :    real(dp) :: cross_elt
     992              :    real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
     993          288 :    cross_elt=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
     994          288 :  end function cross_elt
     995              : 
     996              : end subroutine eltxccore
     997              : !!***
     998              : 
     999              : !!****f* ABINIT/dfpt_eltfrloc
    1000              : !! NAME
    1001              : !! dfpt_eltfrloc
    1002              : !!
    1003              : !! FUNCTION
    1004              : !! Compute the frozen-wavefunction local pseudopotential contribution
    1005              : !! to the elastic tensor and the internal strain (derivative wrt one
    1006              : !! cartesian strain component and one reduced-coordinate atomic displacement).
    1007              : !!
    1008              : !! INPUTS
    1009              : !!  atindx(natom)=index table for atoms (see gstate.f)
    1010              : !!  gmet(3,3)=reciprocal space metric (bohr^-2)
    1011              : !!  gprimd(3,3)=dimensional primitive translations for reciprocal space (bohr**-1)
    1012              : !!  gsqcut=cutoff on G^2 based on ecut
    1013              : !!  mgfft=maximum size of 1D FFTs
    1014              : !!  mpi_enreg=information about MPI parallelization
    1015              : !!  mqgrid=dimensioned number of q grid points for local psp spline
    1016              : !!  natom=number of atoms in unit cell
    1017              : !!  nattyp(ntypat)=number of atoms of each type
    1018              : !!  nfft=(effective) number of FFT grid points (for this processor)
    1019              : !!  ngfft(18)=contain all needed information about 3D FFT,
    1020              : !!    see ~abinit/doc/variables/vargs.htm#ngfft
    1021              : !!  ntypat=number of types of atoms
    1022              : !!  ph1d(2,3*(2*mgfft+1)*natom)=one-dimensional structure factor information
    1023              : !!  qgrid(mqgrid)=q point array for local psp spline fits
    1024              : !!  rhog(2,nfft)=electron density in G space
    1025              : !!  vlspl(mqgrid,2,ntypat)=q^2 v(q) spline for each type of atom.
    1026              : !!
    1027              : !! OUTPUT
    1028              : !!  eltfrloc(6+3*natom,6)=non-symmetrized local pseudopotenial contribution
    1029              : !!   to the elastic tensor and internal strain.
    1030              : !!
    1031              : !! SOURCE
    1032              : 
    1033           37 : subroutine dfpt_eltfrloc(atindx,eltfrloc,gmet,gprimd,gsqcut,mgfft,&
    1034           37 : &  mpi_enreg,mqgrid,natom,nattyp,nfft,ngfft,ntypat,ph1d,qgrid,rhog,vlspl)
    1035              : 
    1036              : !Arguments ------------------------------------
    1037              : !scalars
    1038              :  integer,intent(in) :: mgfft,mqgrid,natom,nfft,ntypat
    1039              :  real(dp),intent(in) :: gsqcut
    1040              :  type(MPI_type),intent(in) :: mpi_enreg
    1041              : !arrays
    1042              :  integer,intent(in) :: atindx(natom),nattyp(ntypat),ngfft(18)
    1043              :  real(dp),intent(in) :: gmet(3,3),gprimd(3,3),ph1d(2,3*(2*mgfft+1)*natom)
    1044              :  real(dp),intent(in) :: qgrid(mqgrid),rhog(2,nfft),vlspl(mqgrid,2,ntypat)
    1045              :  real(dp),intent(out) :: eltfrloc(6+3*natom,6)
    1046              : 
    1047              : !Local variables-------------------------------
    1048              : !scalars
    1049              :  integer,parameter :: im=2,re=1
    1050              :  integer :: i1,i2,i3,ia,ia1,ia2,id1,id2,id3,ielt,ieltx,ierr,ig1,ig2,ig3,ii
    1051              :  integer :: is1,is2,itypat,jj,ka,kb,kd,kg,me_fft,n1,n2,n3,nproc_fft
    1052              :  real(dp),parameter :: tolfix=1.0000001_dp
    1053              :  real(dp) :: aa,bb,cc,cutoff,d2g
    1054              :  real(dp) :: dd,dg1,dg2,diff,dq
    1055              :  real(dp) :: dq2div6,dqdiv6,dqm1,ee,ff,gmag,gsquar
    1056              :  real(dp) :: sfi,sfr,term,term1
    1057              : !real(dp) :: ph1_elt,ph2_elt,ph3_elt,phi_elt,phr_elt
    1058              :  real(dp) :: term2,term3,term4,term5,vion1,vion2,vion3
    1059              : !arrays
    1060              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
    1061           37 :  integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
    1062           37 :  integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
    1063              :  real(dp) :: dgm(3,3,6),tsec(2)
    1064           37 :  real(dp),allocatable :: d2gm(:,:,:,:),elt_work(:,:)
    1065              : 
    1066              : ! *************************************************************************
    1067              : 
    1068           37 :  n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
    1069           37 :  me_fft=ngfft(11) ; nproc_fft=ngfft(10)
    1070              : 
    1071              : !Get the distrib associated with this fft_grid
    1072           37 :  call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
    1073              : 
    1074              : !-----
    1075              : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
    1076              : !and store for use in inner loop below.
    1077           37 :  ABI_MALLOC(d2gm,(3,3,6,6))
    1078              : 
    1079              : !Loop over 2nd strain index
    1080          259 :  do is2=1,6
    1081          222 :    kg=idx(2*is2-1);kd=idx(2*is2)
    1082          888 :    do jj = 1,3
    1083         2886 :      dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
    1084              :    end do
    1085              : !  Loop over 1st strain index, upper triangle only
    1086         1036 :    do is1=1,is2
    1087          777 :      ka=idx(2*is1-1);kb=idx(2*is1)
    1088        10101 :      d2gm(:,:,is1,is2)=0._dp
    1089         3330 :      do jj = 1,3
    1090         2331 :        if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1091         4440 : &       +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
    1092         2331 :        if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1093         2664 : &       +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
    1094         2331 :        if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1095         3108 : &       +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
    1096         2331 :        if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1097         5217 : &       +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
    1098              :      end do
    1099              :    end do !is1
    1100              :  end do !is2
    1101              : 
    1102              : !Zero out array to permit accumulation over atom types below:
    1103         3283 :  eltfrloc(:,:)=0.0_dp
    1104              : 
    1105           37 :  dq=(qgrid(mqgrid)-qgrid(1))/dble(mqgrid-1)
    1106           37 :  dqm1=1.0_dp/dq
    1107           37 :  dqdiv6=dq/6.0_dp
    1108           37 :  dq2div6=dq**2/6.0_dp
    1109           37 :  cutoff=gsqcut*tolfix
    1110           37 :  id1=n1/2+2
    1111           37 :  id2=n2/2+2
    1112           37 :  id3=n3/2+2
    1113              : 
    1114           37 :  ia1=1
    1115           98 :  do itypat=1,ntypat
    1116              : !  ia1,ia2 sets range of loop over atoms:
    1117           61 :    ia2=ia1+nattyp(itypat)-1
    1118           61 :    ii=0
    1119         1411 :    do i3=1,n3
    1120         1350 :      ig3=i3-(i3/id3)*n3-1
    1121        24317 :      do i2=1,n2
    1122        24256 :        if (fftn2_distrib(i2)==me_fft) then
    1123        22906 :          ig2=i2-(i2/id2)*n2-1
    1124       419836 :          do i1=1,n1
    1125       396930 :            ig1=i1-(i1/id1)*n1-1
    1126              : 
    1127       396930 :            ii=ii+1
    1128              : !          Skip G=0:
    1129       396930 :            if (ig1==0 .and. ig2==0 .and. ig3==0) cycle
    1130              : 
    1131              : !          Skip G**2 outside cutoff:
    1132       396869 :            gsquar=gsq_elt(ig1,ig2,ig3)
    1133       419775 :            if (gsquar<=cutoff) then
    1134       132058 :              gmag=sqrt(gsquar)
    1135              : 
    1136              : !            Compute vion(G) for given type of atom
    1137       132058 :              jj=1+int(gmag*dqm1)
    1138       132058 :              diff=gmag-qgrid(jj)
    1139              : 
    1140              : !            Evaluate spline fit from q^2 V(q) to get V(q):
    1141              : !            (p. 86 Numerical Recipes, Press et al; NOTE error in book for sign
    1142              : !             of "aa" term in derivative; also see splfit routine).
    1143       132058 :              bb = diff*dqm1
    1144       132058 :              aa = 1.0_dp-bb
    1145       132058 :              cc = aa*(aa**2-1.0_dp)*dq2div6
    1146       132058 :              dd = bb*(bb**2-1.0_dp)*dq2div6
    1147              :              term1 = (aa*vlspl(jj,1,itypat)+bb*vlspl(jj+1,1,itypat) +&
    1148       132058 : &             cc*vlspl(jj,2,itypat)+dd*vlspl(jj+1,2,itypat))
    1149       132058 :              vion1=term1 / gsquar
    1150              : 
    1151              : !            Also get dV(q)/dq:
    1152              : !            (note correction of Numerical Recipes sign error
    1153              : !             before (3._dp*aa**2-1._dp)
    1154       132058 :              ee= vlspl(jj+1,1,itypat)-vlspl(jj,1,itypat)
    1155              :              ff=  (3._dp*bb**2-1._dp)*vlspl(jj+1,2,itypat) &
    1156       132058 : &             - (3._dp*aa**2-1._dp)*vlspl(jj,2,itypat)
    1157       132058 :              term2 = ee*dqm1 + ff*dqdiv6
    1158       132058 :              vion2 = term2/gsquar - 2._dp*term1/(gsquar*gmag)
    1159              : 
    1160              : !            Also get V''(q)
    1161       132058 :              term3=aa*vlspl(jj,2,itypat)+bb*vlspl(jj+1,2,itypat)
    1162       132058 :              vion3 = (term3 - 4.0_dp*term2/gmag + 6._dp*term1/gsquar)/gsquar
    1163              : 
    1164              : !            Assemble structure factor over all atoms of given type:
    1165       132058 :              sfr=zero;sfi=zero
    1166       361046 :              do ia=ia1,ia2
    1167       228988 :                sfr=sfr+phre_elt(ig1,ig2,ig3,ia)
    1168       361046 :                sfi=sfi-phimag_elt(ig1,ig2,ig3,ia)
    1169              :              end do
    1170       132058 :              term=(rhog(re,ii)*sfr+rhog(im,ii)*sfi)
    1171              : 
    1172              : !            Loop over 2nd strain index
    1173       924406 :              do is2=1,6
    1174       792348 :                dg2=0.5_dp*dgsqds_elt(ig1,ig2,ig3,is2)/gmag
    1175              : !              Loop over 1st strain index, upper triangle only
    1176      3565566 :                do is1=1,is2
    1177      2773218 :                  dg1=0.5_dp*dgsqds_elt(ig1,ig2,ig3,is1)/gmag
    1178      2773218 :                  d2g=(0.25_dp*d2gsqds_elt(ig1,ig2,ig3,is1,is2)-dg1*dg2)/gmag
    1179              :                  eltfrloc(is1,is2)=eltfrloc(is1,is2)+&
    1180      2773218 : &                 term*(vion3*dg1*dg2+vion2*d2g)
    1181      2773218 :                  if(is2<=3)&
    1182       792348 : &                 eltfrloc(is1,is2)=eltfrloc(is1,is2)-term*vion2*dg1
    1183      2773218 :                  if(is1<=3)&
    1184      1980870 : &                 eltfrloc(is1,is2)=eltfrloc(is1,is2)-term*vion2*dg2
    1185      2773218 :                  if(is1<=3 .and. is2<=3)&
    1186      1584696 : &                 eltfrloc(is1,is2)=eltfrloc(is1,is2)+term*vion1
    1187              :                end do !is1
    1188              : 
    1189              : !              Internal strain section - loop over current atoms
    1190      2298334 :                do ia=ia1,ia2
    1191      1373928 :                  if(is2 <=3) then
    1192       686964 :                    term4=vion2*dg2-vion1
    1193              :                  else
    1194       686964 :                    term4=vion2*dg2
    1195              :                  end if
    1196              :                  term5=-two_pi*(rhog(re,ii)*phimag_elt(ig1,ig2,ig3,ia)&
    1197      1373928 : &                 +rhog(im,ii)*phre_elt(ig1,ig2,ig3,ia))*term4
    1198      1373928 :                  eltfrloc(7+3*(ia-1),is2)=eltfrloc(7+3*(ia-1),is2)+term5*dble(ig1)
    1199      1373928 :                  eltfrloc(8+3*(ia-1),is2)=eltfrloc(8+3*(ia-1),is2)+term5*dble(ig2)
    1200      2166276 :                  eltfrloc(9+3*(ia-1),is2)=eltfrloc(9+3*(ia-1),is2)+term5*dble(ig3)
    1201              :                end do
    1202              : 
    1203              :              end do !is2
    1204              : 
    1205              : !            End skip G**2 outside cutoff:
    1206              :            end if
    1207              : 
    1208              : !          End loop on n1, n2, n3. There is a "cycle" inside the loop
    1209              :          end do
    1210              :        end if
    1211              :      end do
    1212              :    end do
    1213              : 
    1214              : !  End loop on type of atoms
    1215           98 :    ia1=ia2+1
    1216              :  end do
    1217              : !Init mpi_comm
    1218           37 :  call timab(48,1,tsec)
    1219           37 :  call xmpi_sum(eltfrloc,mpi_enreg%comm_fft,ierr)
    1220           37 :  call timab(48,2,tsec)
    1221              : 
    1222              : !Fill in lower triangle
    1223          222 :  do is2=2,6
    1224          777 :    do is1=1,is2-1
    1225          740 :      eltfrloc(is2,is1)=eltfrloc(is1,is2)
    1226              :    end do
    1227              :  end do
    1228              : 
    1229              : !The indexing array atindx is used to reestablish the correct
    1230              : !order of atoms
    1231          185 :  ABI_MALLOC(elt_work,(6+3*natom,6))
    1232         1591 :  elt_work(1:6,1:6)=eltfrloc(1:6,1:6)
    1233          131 :  do ia=1,natom
    1234           94 :    ielt=7+3*(ia-1)
    1235           94 :    ieltx=7+3*(atindx(ia)-1)
    1236         2387 :    elt_work(ielt:ielt+2,1:6)=eltfrloc(ieltx:ieltx+2,1:6)
    1237              :  end do
    1238         3283 :  eltfrloc(:,:)=elt_work(:,:)
    1239              : 
    1240           37 :  ABI_FREE(d2gm)
    1241           74 :  ABI_FREE(elt_work)
    1242              : 
    1243              :  contains
    1244              : 
    1245              : !Real and imaginary parts of phase.
    1246      1602916 :    function phr_elt(x1,y1,x2,y2,x3,y3)
    1247              : 
    1248              :    real(dp) :: phr_elt,x1,x2,x3,y1,y2,y3
    1249      1602916 :    phr_elt=(x1*x2-y1*y2)*x3-(y1*x2+x1*y2)*y3
    1250              :  end function phr_elt
    1251              : 
    1252      1602916 :    function phi_elt(x1,y1,x2,y2,x3,y3)
    1253              : 
    1254              :    real(dp):: phi_elt,x1,x2,x3,y1,y2,y3
    1255      1602916 :    phi_elt=(x1*x2-y1*y2)*y3+(y1*x2+x1*y2)*x3
    1256              :  end function phi_elt
    1257              : 
    1258      6411664 :    function ph1_elt(nri,ig1,ia)
    1259              : 
    1260              :    real(dp):: ph1_elt
    1261              :    integer :: nri,ig1,ia
    1262      6411664 :    ph1_elt=ph1d(nri,ig1+1+n1+(ia-1)*(2*n1+1))
    1263      6411664 :  end function ph1_elt
    1264              : 
    1265      6411664 :    function ph2_elt(nri,ig2,ia)
    1266              : 
    1267              :    real(dp):: ph2_elt
    1268              :    integer :: nri,ig2,ia
    1269      6411664 :    ph2_elt=ph1d(nri,ig2+1+n2+(ia-1)*(2*n2+1)+natom*(2*n1+1))
    1270      6411664 :  end function ph2_elt
    1271              : 
    1272      6411664 :    function ph3_elt(nri,ig3,ia)
    1273              : 
    1274              :    real(dp):: ph3_elt
    1275              :    integer :: nri,ig3,ia
    1276      6411664 :    ph3_elt=ph1d(nri,ig3+1+n3+(ia-1)*(2*n3+1)+natom*(2*n1+1+2*n2+1))
    1277      6411664 :  end function ph3_elt
    1278              : 
    1279      1602916 :    function phre_elt(ig1,ig2,ig3,ia)
    1280              : 
    1281              :    real(dp):: phre_elt
    1282              :    integer :: ig1,ig2,ig3,ia
    1283              :    phre_elt=phr_elt(ph1_elt(re,ig1,ia),ph1_elt(im,ig1,ia),&
    1284      1602916 : &   ph2_elt(re,ig2,ia),ph2_elt(im,ig2,ia),ph3_elt(re,ig3,ia),ph3_elt(im,ig3,ia))
    1285      1602916 :  end function phre_elt
    1286              : 
    1287      1602916 :    function phimag_elt(ig1,ig2,ig3,ia)
    1288              : 
    1289              :    real(dp) :: phimag_elt
    1290              :    integer :: ig1,ig2,ig3,ia
    1291              :    phimag_elt=phi_elt(ph1_elt(re,ig1,ia),ph1_elt(im,ig1,ia),&
    1292      1602916 : &   ph2_elt(re,ig2,ia),ph2_elt(im,ig2,ia),ph3_elt(re,ig3,ia),ph3_elt(im,ig3,ia))
    1293      1602916 :  end function phimag_elt
    1294              : 
    1295       396869 :    function gsq_elt(i1,i2,i3)
    1296              : 
    1297              :    real(dp) :: gsq_elt
    1298              :    integer :: i1,i2,i3
    1299              : !Define G^2 based on G space metric gmet.
    1300              :    gsq_elt=dble(i1*i1)*gmet(1,1)+dble(i2*i2)*gmet(2,2)+&
    1301              : &   dble(i3*i3)*gmet(3,3)+dble(2*i1*i2)*gmet(1,2)+&
    1302       396869 : &   dble(2*i2*i3)*gmet(2,3)+dble(2*i3*i1)*gmet(3,1)
    1303       396869 :  end function gsq_elt
    1304              : 
    1305      3565566 :    function dgsqds_elt(i1,i2,i3,is)
    1306              : 
    1307              :    real(dp) :: dgsqds_elt
    1308              :    integer :: i1,i2,i3,is
    1309              : !Define dG^2/ds based on G space metric derivative
    1310              :    dgsqds_elt=dble(i1*i1)*dgm(1,1,is)+dble(i2*i2)*dgm(2,2,is)+&
    1311              : &   dble(i3*i3)*dgm(3,3,is)+&
    1312              : &   dble(i1*i2)*(dgm(1,2,is)+dgm(2,1,is))+&
    1313              : &   dble(i1*i3)*(dgm(1,3,is)+dgm(3,1,is))+&
    1314      3565566 : &   dble(i2*i3)*(dgm(2,3,is)+dgm(3,2,is))
    1315      3565566 :  end function dgsqds_elt
    1316              : 
    1317      2773218 :    function d2gsqds_elt(i1,i2,i3,is1,is2)
    1318              : 
    1319              :    real(dp) :: d2gsqds_elt
    1320              :    integer :: i1,i2,i3,is1,is2
    1321              : !Define 2dG^2/ds1ds2  based on G space metric derivative
    1322              :    d2gsqds_elt=dble(i1*i1)*d2gm(1,1,is1,is2)+&
    1323              : &   dble(i2*i2)*d2gm(2,2,is1,is2)+dble(i3*i3)*d2gm(3,3,is1,is2)+&
    1324              : &   dble(i1*i2)*(d2gm(1,2,is1,is2)+d2gm(2,1,is1,is2))+&
    1325              : &   dble(i1*i3)*(d2gm(1,3,is1,is2)+d2gm(3,1,is1,is2))+&
    1326      2773218 : &   dble(i2*i3)*(d2gm(2,3,is1,is2)+d2gm(3,2,is1,is2))
    1327      2773218 :  end function d2gsqds_elt
    1328              : 
    1329              : end subroutine dfpt_eltfrloc
    1330              : !!***
    1331              : 
    1332              : !!****f* ABINIT/dfpt_eltfrkin
    1333              : !! NAME
    1334              : !! dfpt_eltfrkin
    1335              : !!
    1336              : !! FUNCTION
    1337              : !! Compute the frozen-wavefunction kinetic enegy contribution to the
    1338              : !! elastic tensor
    1339              : !!
    1340              : !! INPUTS
    1341              : !!  cg(2,mpw*nspinor*mband_mem*mkmem*nsppol)=<G|Cnk>=Fourier coefficients of wavefunction
    1342              : !!  ecut=cut-off energy for plane wave basis sphere (Ha)
    1343              : !!  ecutsm=smearing energy for plane wave kinetic energy (Ha) (NOT NEEDED !)
    1344              : !!  effmass_free=effective mass for electrons (1. in common case)
    1345              : !!  istwfk(nkpt)=input option parameter that describes the storage of wfs
    1346              : !!  kg(3,mpw*mkmem)=work array for coordinates of G vectors in basis
    1347              : !!  kptns(3,nkpt)=coordinates of k points in terms of reciprocal space
    1348              : !!   primitive translations
    1349              : !!  mband=maximum number of bands
    1350              : !!  mband_mem=maximum number of bands in memory
    1351              : !!  mgfft=maximum size of 1D FFTs
    1352              : !!  mkmem=number of k points treated by this node.
    1353              : !!  mpi_enreg=information about MPI parallelization
    1354              : !!  mpw=maximum dimension for number of planewaves
    1355              : !!  nband(nkpt*nsppol)=number of bands being considered per k point
    1356              : !!  nkpt=number of k points
    1357              : !!  ngfft(18)=contain all needed information about 3D FFT, i
    1358              : !!    see ~abinit/doc/variables/vargs.htm#ngfft
    1359              : !!  npwarr(nkpt)=number of planewaves at each k point, and boundary
    1360              : !!  nspinor=number of spinorial components of the wavefunctions
    1361              : !!  nsppol=1 for unpolarized, 2 for polarized
    1362              : !!  occ(mband*nkpt*nsppol)=occupation numbers of bands (usually 2)
    1363              : !!    at each k point
    1364              : !!  rprimd(3,3)=dimensional real space primitive translations (bohr)
    1365              : !!  wtk(nkpt)=k point weights
    1366              : !!
    1367              : !! OUTPUT
    1368              : !!  eltfrkin(6,6)=non-symmetrized kinetic energy contribution to the
    1369              : !!                    elastic tensor
    1370              : !!
    1371              : !! SOURCE
    1372              : 
    1373           37 : subroutine dfpt_eltfrkin(cg,eltfrkin,ecut,ecutsm,effmass_free,&
    1374           37 : &  istwfk,kg,kptns,mband,mband_mem,mgfft,mkmem,mpi_enreg,&
    1375           37 : &  mpw,nband,nkpt,ngfft,npwarr,nspinor,nsppol,occ,rprimd,wtk)
    1376              : 
    1377              : !Arguments ------------------------------------
    1378              : !scalars
    1379              :  integer,intent(in) :: mband,mband_mem,mgfft,mkmem,mpw,nkpt,nspinor,nsppol
    1380              :  real(dp),intent(in) :: ecut,ecutsm,effmass_free
    1381              :  type(MPI_type),intent(in) :: mpi_enreg
    1382              : !arrays
    1383              :  integer,intent(in) :: istwfk(nkpt),kg(3,mpw*mkmem),nband(nkpt*nsppol)
    1384              :  integer,intent(in) :: ngfft(18),npwarr(nkpt)
    1385              :  real(dp),intent(in) :: cg(2,mpw*nspinor*mband_mem*mkmem*nsppol),kptns(3,nkpt)
    1386              :  real(dp),intent(in) :: occ(mband*nkpt*nsppol),rprimd(3,3),wtk(nkpt)
    1387              :  real(dp),intent(out) :: eltfrkin(6,6)
    1388              : 
    1389              : !Local variables-------------------------------
    1390              : !scalars
    1391              :  integer :: bdtot_index,iband,icg,ierr,ii,ikg
    1392              :  integer :: ikpt,index,ipw,isppol,istwf_k,jj,master,me,n1,n2
    1393              :  integer :: n3,nband_k,nkinout,npw_k,spaceComm
    1394              :  integer :: nband_me, iband_me
    1395              :  real(dp) :: ucvol
    1396              : !arrays
    1397           37 :  integer,allocatable :: gbound(:,:),kg_k(:,:)
    1398              :  real(dp) :: gmet(3,3),gprimd(3,3),kpoint(3),rmet(3,3),tsec(2)
    1399           37 :  real(dp),allocatable :: cwavef(:,:),ekinout(:)
    1400           37 :  real(dp),allocatable :: eltfrkink(:,:)
    1401              : 
    1402              : ! *************************************************************************
    1403              : 
    1404              :  DBG_ENTER("COLL")
    1405              : 
    1406              : !Default for sequential use
    1407           37 :  master=0
    1408              : !Init mpi_comm
    1409           37 :  spaceComm=mpi_enreg%comm_cell
    1410           37 :  me=mpi_enreg%me_kpt
    1411              : 
    1412              : !Compute gmet, gprimd and ucvol from rprimd
    1413           37 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
    1414              : 
    1415           37 :  eltfrkin(:,:)=0.0_dp
    1416           37 :  bdtot_index=0
    1417           37 :  icg=0
    1418              : 
    1419           37 :  n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
    1420          111 :  ABI_MALLOC(kg_k,(3,mpw))
    1421          111 :  ABI_MALLOC(cwavef,(2,mpw*nspinor))
    1422           37 :  ABI_MALLOC(eltfrkink,(6,6))
    1423              : 
    1424              : !Define k-points distribution
    1425              : 
    1426              : !LOOP OVER SPINS
    1427           76 :  do isppol=1,nsppol
    1428           39 :    ikg=0
    1429              : 
    1430              : !  Loop over k points
    1431         5756 :    do ikpt=1,nkpt
    1432              : 
    1433         5680 :      nband_k=nband(ikpt+(isppol-1)*nkpt)
    1434         5680 :      istwf_k=istwfk(ikpt)
    1435         5680 :      npw_k=npwarr(ikpt)
    1436              : 
    1437              : !    Skip this k-point if not the proper processor
    1438         5680 :      if(proc_distrb_cycle(mpi_enreg%proc_distrb,ikpt,1,nband_k,isppol,me)) then
    1439           32 :        bdtot_index=bdtot_index+nband_k
    1440           32 :        cycle
    1441              :      end if
    1442              : 
    1443              : ! find number of bands I will actually treat
    1444         5648 :      nband_me = proc_distrb_nband(mpi_enreg%proc_distrb,ikpt,nband_k,isppol,me)
    1445              : 
    1446        22592 :      ABI_MALLOC(gbound,(2*mgfft+8,2))
    1447        22592 :      kpoint(:)=kptns(:,ikpt)
    1448              : 
    1449      2776608 :      kg_k(:,:) = 0
    1450              : 
    1451              : 
    1452              : !$OMP PARALLEL DO PRIVATE(ipw) SHARED(ikg,kg,kg_k,npw_k)
    1453       662007 :      do ipw=1,npw_k
    1454       656359 :        kg_k(1,ipw)=kg(1,ipw+ikg)
    1455       656359 :        kg_k(2,ipw)=kg(2,ipw+ikg)
    1456       662007 :        kg_k(3,ipw)=kg(3,ipw+ikg)
    1457              :      end do
    1458              : 
    1459         5648 :      call sphereboundary(gbound,istwf_k,kg_k,mgfft,npw_k)
    1460              : 
    1461         5648 :      index=1+icg
    1462              : 
    1463       242864 :      eltfrkink(:,:)=0.0_dp
    1464              : 
    1465         5648 :      nkinout=6*6
    1466         5648 :      ABI_MALLOC(ekinout,(nkinout))
    1467       208976 :      ekinout(:)=zero
    1468              : 
    1469              :      iband_me = 0
    1470        29080 :      do iband=1,nband_k
    1471              : 
    1472        23432 :        if(mpi_enreg%proc_distrb(ikpt,iband,isppol) /= me) cycle
    1473        23432 :        iband_me = iband_me + 1
    1474              : 
    1475      8715776 :        cwavef(:,1:npw_k*nspinor)=cg(:,1+(iband_me-1)*npw_k*nspinor+icg:iband_me*npw_k*nspinor+icg)
    1476              : 
    1477              :        call d2kindstr2(cwavef,ecut,ecutsm,effmass_free,ekinout,gmet,gprimd,&
    1478        23432 : &       istwf_k,kg_k,kpoint,npw_k,nspinor)
    1479              : 
    1480      1013224 :        eltfrkink(:,:)=eltfrkink(:,:)+ occ(iband+bdtot_index)* reshape(ekinout(:), (/6,6/) )
    1481              : 
    1482              :      end do !iband
    1483              : 
    1484         5648 :      ABI_FREE(ekinout)
    1485              : 
    1486       242864 :      eltfrkin(:,:)=eltfrkin(:,:)+wtk(ikpt)*eltfrkink(:,:)
    1487              : 
    1488         5648 :      ABI_FREE(gbound)
    1489              : 
    1490         5648 :      bdtot_index=bdtot_index+nband_k
    1491              : 
    1492         5687 :      if (mkmem/=0) then
    1493              : !      Handle case in which kg, cg, are kept in core
    1494         5648 :        icg=icg+npw_k*nspinor*nband_me
    1495         5648 :        ikg=ikg+npw_k
    1496              :      end if
    1497              : 
    1498              :    end do
    1499              :  end do  ! End loops on isppol and ikpt
    1500              : 
    1501              : !Fill in lower triangle
    1502          222 :  do jj=2,6
    1503          777 :    do ii=1,jj-1
    1504          740 :      eltfrkin(jj,ii)=eltfrkin(ii,jj)
    1505              :    end do
    1506              :  end do
    1507              : 
    1508              : !Accumulate eltfrkin on all proc.
    1509           37 :  call timab(48,1,tsec)
    1510           37 :  call xmpi_sum(eltfrkin,spaceComm,ierr)
    1511           37 :  call timab(48,2,tsec)
    1512              : 
    1513           37 :  ABI_FREE(cwavef)
    1514           37 :  ABI_FREE(eltfrkink)
    1515           37 :  ABI_FREE(kg_k)
    1516              : 
    1517              :  DBG_EXIT("COLL")
    1518              : 
    1519              :   contains
    1520              : !!***
    1521              : 
    1522              : !!****f* ABINIT/d2kindstr2
    1523              : !! NAME
    1524              : !! d2kindstr2
    1525              : !!
    1526              : !! FUNCTION
    1527              : !! compute expectation value of the second derivatives of the kinetic energy
    1528              : !! wrt strain for one band and kpoint
    1529              : !!
    1530              : !! INPUTS
    1531              : !!  cwavef(2,npw*nspinor)=wavefunction for current band
    1532              : !!  ecut=cut-off energy for plane wave basis sphere (Ha)
    1533              : !!  ecutsm=smearing energy for plane wave kinetic energy (Ha)
    1534              : !!  effmass_free=effective mass for electrons (1. in common case)
    1535              : !!  gmet(3,3)=reciprocal lattice metric tensor ($\textrm{Bohr}^{-2}$)
    1536              : !!  gprimd(3,3)=primitive vectors in reciprocal space
    1537              : !!  istwfk=information about wavefunction storage
    1538              : !!  kg_k(3,npw)=integer coordinates of planewaves in basis sphere.
    1539              : !!  kpt(3)=reduced coordinates of k point
    1540              : !!  npw=number of plane waves at kpt.
    1541              : !!  nspinor=number of spinorial components of the wavefunction
    1542              : !!
    1543              : !! OUTPUT
    1544              : !!  ekinout(36)=expectation values of the second strain derivatives
    1545              : !!   of the (modified) kinetic energy
    1546              : !!
    1547              : !! NOTES
    1548              : !! Usually, the kinetic energy expression is $(1/2) (2 \pi)^2 (k+G)^2 $
    1549              : !! However, the present implementation allows for a modification
    1550              : !! of this kinetic energy, in order to obtain smooth total energy
    1551              : !! curves with respect to the cut-off energy or the cell size and shape.
    1552              : !! Thus the usual expression is kept if it is lower then ecut-ecutsm,
    1553              : !! zero is returned beyond ecut, and in between, the kinetic
    1554              : !! energy is DIVIDED by a smearing factor (to make it infinite at the
    1555              : !! cut-off energy). The smearing factor is $x^2 (3-2x)$, where
    1556              : !! x = (ecut- unmodified energy)/ecutsm.
    1557              : !!
    1558              : !! SOURCE
    1559              : 
    1560        23432 : subroutine d2kindstr2(cwavef,ecut,ecutsm,effmass_free,ekinout,gmet,gprimd,&
    1561        23432 : &            istwfk,kg_k,kpt,npw,nspinor)
    1562              : 
    1563              : !Arguments ------------------------------------
    1564              : !scalars
    1565              :  integer,intent(in) :: istwfk,npw,nspinor
    1566              :  real(dp),intent(in) :: ecut,ecutsm,effmass_free
    1567              : !arrays
    1568              :  integer,intent(in) :: kg_k(3,npw)
    1569              :  real(dp),intent(in) :: cwavef(2,npw*nspinor),gmet(3,3),gprimd(3,3),kpt(3)
    1570              :  real(dp),intent(inout) :: ekinout(36) !vz_i
    1571              : 
    1572              : !Local variables-------------------------------
    1573              : !scalars
    1574              :  integer,parameter :: im=2,re=1
    1575              :  integer :: ig,igs,ii,ispinor,istr1,istr2,ka,kb,kd,kg
    1576              :  real(dp) :: d2fkin,d2fsm,d2kinacc,d2kpg2,dfkin,dfsm,dkpg21,dkpg22,ecutsm_inv
    1577              :  real(dp) :: fsm,gpk1,gpk2,gpk3,htpisq,kpg2,term,xx
    1578              : !arrays
    1579              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
    1580              :  real(dp) :: d2gm(3,3),dgm01(3,3),dgm10(3,3)
    1581              : 
    1582              : ! *************************************************************************
    1583              : !
    1584              : !htpisq is (1/2) (2 Pi) **2:
    1585        23432 :    htpisq=0.5_dp*(two_pi)**2
    1586              : 
    1587        23432 :    ecutsm_inv=0.0_dp
    1588        23432 :    if(ecutsm>1.0d-20)ecutsm_inv=1/ecutsm
    1589              : 
    1590              : !Loop over 2nd strain index
    1591       164024 :    do istr2=1,6
    1592              : !  Loop over 1st strain index, upper triangle only
    1593       656096 :      do istr1=1,istr2
    1594              : 
    1595       492072 :        ka=idx(2*istr1-1);kb=idx(2*istr1);kg=idx(2*istr2-1);kd=idx(2*istr2)
    1596              : 
    1597      1968288 :        do ii = 1,3
    1598      5904864 :          dgm01(:,ii)=-(gprimd(ka,:)*gprimd(kb,ii)+gprimd(kb,:)*gprimd(ka,ii))
    1599      6396936 :          dgm10(:,ii)=-(gprimd(kg,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kg,ii))
    1600              :        end do
    1601              : 
    1602       492072 :        d2gm(:,:)=0._dp
    1603      1968288 :        do ii = 1,3
    1604      1476216 :          if(ka==kg) d2gm(:,ii)=d2gm(:,ii)&
    1605      2811840 : &         +gprimd(kb,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kb,ii)
    1606      1476216 :          if(ka==kd) d2gm(:,ii)=d2gm(:,ii)&
    1607      1687104 : &         +gprimd(kb,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(kb,ii)
    1608      1476216 :          if(kb==kg) d2gm(:,ii)=d2gm(:,ii)&
    1609      1968288 : &         +gprimd(ka,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(ka,ii)
    1610      1476216 :          if(kb==kd) d2gm(:,ii)=d2gm(:,ii)&
    1611      3303912 : &         +gprimd(ka,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(ka,ii)
    1612              :        end do
    1613      6396936 :        d2gm(:,:)=0.5_dp*d2gm(:,:)
    1614              : 
    1615              :        d2kinacc=0._dp
    1616              : 
    1617              : !    loop on spinor index
    1618       984144 :        do ispinor=1,nspinor
    1619       492072 :          igs=(ispinor-1)*npw
    1620              : !      loop on plane waves
    1621     61830552 :          do ig=1,npw
    1622     60846408 :            gpk1=dble(kg_k(1,ig))+kpt(1)
    1623     60846408 :            gpk2=dble(kg_k(2,ig))+kpt(2)
    1624     60846408 :            gpk3=dble(kg_k(3,ig))+kpt(3)
    1625              :            kpg2=htpisq*&
    1626              : &           ( gmet(1,1)*gpk1**2+         &
    1627              : &           gmet(2,2)*gpk2**2+         &
    1628              : &           gmet(3,3)*gpk3**2          &
    1629              : &           +2.0_dp*(gpk1*gmet(1,2)*gpk2+  &
    1630              : &           gpk1*gmet(1,3)*gpk3+  &
    1631     60846408 : &           gpk2*gmet(2,3)*gpk3 )  )
    1632              :            dkpg21=htpisq*&
    1633              : &           ( dgm01(1,1)*gpk1**2+         &
    1634              : &           dgm01(2,2)*gpk2**2+         &
    1635              : &           dgm01(3,3)*gpk3**2          &
    1636              : &           +2.0_dp*(gpk1*dgm01(1,2)*gpk2+  &
    1637              : &           gpk1*dgm01(1,3)*gpk3+  &
    1638     60846408 : &           gpk2*dgm01(2,3)*gpk3 )  )
    1639              :            dkpg22=htpisq*&
    1640              : &           ( dgm10(1,1)*gpk1**2+         &
    1641              : &           dgm10(2,2)*gpk2**2+         &
    1642              : &           dgm10(3,3)*gpk3**2          &
    1643              : &           +2.0_dp*(gpk1*dgm10(1,2)*gpk2+  &
    1644              : &           gpk1*dgm10(1,3)*gpk3+  &
    1645     60846408 : &           gpk2*dgm10(2,3)*gpk3 )  )
    1646              :            d2kpg2=htpisq*&
    1647              : &           ( d2gm(1,1)*gpk1**2+         &
    1648              : &           d2gm(2,2)*gpk2**2+         &
    1649              : &           d2gm(3,3)*gpk3**2          &
    1650              : &           +2.0_dp*(gpk1*d2gm(1,2)*gpk2+  &
    1651              : &           gpk1*d2gm(1,3)*gpk3+  &
    1652     60846408 : &           gpk2*d2gm(2,3)*gpk3 )  )
    1653              : 
    1654     60846408 :            if(kpg2>ecut-tol12)then
    1655              :              dfkin=0._dp
    1656              :              d2fkin=0._dp
    1657     60846408 :            elseif(kpg2>ecut-ecutsm)then
    1658              : !          This kinetic cutoff smoothing function and its xx derivatives
    1659              : !          were produced with Mathematica and the fortran code has been
    1660              : !          numerically checked against Mathematica.
    1661      6141576 :              xx=(ecut-kpg2)*ecutsm_inv
    1662      6141576 :              fsm=1.0_dp/(xx**2*(3+xx*(1+xx*(-6+3*xx))))
    1663      6141576 :              dfsm=-3.0_dp*(-1+xx)**2*xx*(2+5*xx)*fsm**2
    1664              :              d2fsm=6.0_dp*xx**2*(9+xx*(8+xx*(-52+xx*(-3+xx*(137+xx*&
    1665      6141576 : &             (-144+45*xx))))))*fsm**3
    1666      6141576 :              dfkin=fsm-ecutsm_inv*kpg2*dfsm
    1667      6141576 :              d2fkin=ecutsm_inv*(-2.0_dp*dfsm+ecutsm_inv*kpg2*d2fsm)
    1668              :            else
    1669              :              dfkin=1._dp
    1670              :              d2fkin=0._dp
    1671              :            end if
    1672              : 
    1673              : !        accumulate kinetic energy 2nd derivative with wavefunction components
    1674     60846408 :            term=d2fkin*dkpg21*dkpg22 + dfkin*d2kpg2
    1675     60846408 :            if(istwfk==2 .and. ig/=1)term=2.0_dp*term
    1676     60846408 :            if(istwfk>2)term=2.0_dp*term
    1677     61338480 :            d2kinacc=d2kinacc + term*(cwavef(re,ig+igs)**2 + cwavef(im,ig+igs)**2)
    1678              : 
    1679              :          end do  !ig
    1680              :        end do !ispinor
    1681              : 
    1682       632664 :        ekinout(istr1+6*(istr2-1))=d2kinacc/effmass_free
    1683              : 
    1684              :      end do !istr1
    1685              :    end do !istr2
    1686              : 
    1687        23432 :   end subroutine d2kindstr2
    1688              : !!***
    1689              : 
    1690              : end subroutine dfpt_eltfrkin
    1691              : !!***
    1692              : 
    1693              : !!****f* ABINIT/dfpt_eltfrhar
    1694              : !! NAME
    1695              : !! dfpt_eltfrhar
    1696              : !!
    1697              : !! FUNCTION
    1698              : !! Compute the frozen-wavefunction hartree enegy contribution to the elastic tensor
    1699              : !!
    1700              : !! INPUTS
    1701              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
    1702              : !!  gsqcut =Fourier cutoff on G^2 for "large sphere" of radius double
    1703              : !!   that of the basis sphere--appropriate for charge density rho(G),
    1704              : !!   Hartree potential, and pseudopotentials
    1705              : !!  mpi_enreg=information about MPI parallelization
    1706              : !!  nfft =(effective) number of FFT grid points (for this processor)
    1707              : !!  ngfft(18)=contain all needed information about 3D FFT,
    1708              : !!    see ~abinit/doc/variables/vargs.htm#ngfft
    1709              : !!  rhog(2,nfft)=total electron density in G space
    1710              : !!
    1711              : !! OUTPUT
    1712              : !!  eltfrhar(6,6)=non-symmetrized kinetic energy contribution to the
    1713              : !!                    elastic tensor
    1714              : !! NOTES
    1715              : !! *based largely on hartre.f
    1716              : !!
    1717              : !! SOURCE
    1718              : 
    1719           37 : subroutine dfpt_eltfrhar(eltfrhar,rprimd,gsqcut,mpi_enreg,nfft,ngfft,rhog)
    1720              : 
    1721              : !Arguments ------------------------------------
    1722              : !scalars
    1723              :  integer,intent(in) :: nfft
    1724              :  real(dp),intent(in) :: gsqcut
    1725              :  type(MPI_type),intent(in) :: mpi_enreg
    1726              : !arrays
    1727              :  integer,intent(in) :: ngfft(18)
    1728              :  real(dp),intent(in) :: rhog(2,nfft),rprimd(3,3)
    1729              :  real(dp),intent(out) :: eltfrhar(6,6)
    1730              : 
    1731              : !Local variables-------------------------------
    1732              : !scalars
    1733              :  integer,parameter :: im=2,re=1
    1734              :  integer :: i1,i2,i23,i3,id2,id3,ierr,ig,ig2,ig3,ii,ii1,ing,istr1,istr2,jj
    1735              :  integer :: ka,kb,kd,kg,me_fft,n1,n2,n3,nproc_fft
    1736              :  real(dp),parameter :: tolfix=1.000000001_dp
    1737              :  real(dp) :: cutoff,d2eacc,d2etot,d2gs,deacc01,deacc10,dgs01,dgs10,eacc,fact,gs
    1738              :  real(dp) :: term,ucvol
    1739              : !arrays
    1740              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
    1741              :  integer :: id(3)
    1742           37 :  integer, ABI_CONTIGUOUS pointer :: fftn2_distrib(:),ffti2_local(:)
    1743           37 :  integer, ABI_CONTIGUOUS pointer :: fftn3_distrib(:),ffti3_local(:)
    1744              :  real(dp) :: d2gm(3,3),dgm01(3,3),dgm10(3,3),gmet(3,3),gprimd(3,3),gqr(3)
    1745              :  real(dp) :: rmet(3,3),tsec(2)
    1746           37 :  real(dp),allocatable :: gq(:,:)
    1747              : 
    1748              : ! *************************************************************************
    1749              : 
    1750              : !Compute gmet, gprimd and ucvol from rprimd
    1751           37 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
    1752              : 
    1753           37 :  eltfrhar(:,:)=0.0_dp
    1754              : 
    1755           37 :  n1=ngfft(1) ; n2=ngfft(2) ; n3=ngfft(3)
    1756           37 :  me_fft=ngfft(11)
    1757           37 :  nproc_fft=ngfft(10)
    1758              : 
    1759              : !Get the distrib associated with this fft_grid
    1760           37 :  call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
    1761              : 
    1762              : !Initialize a few quantities
    1763           37 :  fact=0.5_dp*ucvol/pi
    1764           37 :  cutoff=gsqcut*tolfix
    1765              : 
    1766              : !In order to speed the routine, precompute the components of g+q
    1767              : !Also check if the booked space was large enough...
    1768          111 :  ABI_MALLOC(gq,(3,max(n1,n2,n3)))
    1769          148 :  do ii=1,3
    1770          111 :    id(ii)=ngfft(ii)/2+2
    1771         2130 :    do ing=1,ngfft(ii)
    1772         1982 :      ig=ing-(ing/id(ii))*ngfft(ii)-1
    1773         2093 :      gq(ii,ing)=ig
    1774              :    end do
    1775              :  end do
    1776              : 
    1777              : !Loop over 2nd strain index
    1778          259 :  do istr2=1,6
    1779              : !  Loop over 1st strain index, upper triangle only
    1780         1036 :    do istr1=1,istr2
    1781              : 
    1782          777 :      ka=idx(2*istr1-1);kb=idx(2*istr1);kg=idx(2*istr2-1);kd=idx(2*istr2)
    1783              : 
    1784         3108 :      do ii = 1,3
    1785         9324 :        dgm01(:,ii)=-(gprimd(ka,:)*gprimd(kb,ii)+gprimd(kb,:)*gprimd(ka,ii))
    1786        10101 :        dgm10(:,ii)=-(gprimd(kg,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kg,ii))
    1787              :      end do
    1788              : 
    1789          777 :      d2gm(:,:)=0._dp
    1790         3108 :      do ii = 1,3
    1791         2331 :        if(ka==kg) d2gm(:,ii)=d2gm(:,ii)&
    1792         4440 : &       +gprimd(kb,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(kb,ii)
    1793         2331 :        if(ka==kd) d2gm(:,ii)=d2gm(:,ii)&
    1794         2664 : &       +gprimd(kb,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(kb,ii)
    1795         2331 :        if(kb==kg) d2gm(:,ii)=d2gm(:,ii)&
    1796         3108 : &       +gprimd(ka,:)*gprimd(kd,ii)+gprimd(kd,:)*gprimd(ka,ii)
    1797         2331 :        if(kb==kd) d2gm(:,ii)=d2gm(:,ii)&
    1798         5217 : &       +gprimd(ka,:)*gprimd(kg,ii)+gprimd(kg,:)*gprimd(ka,ii)
    1799              :      end do
    1800        10101 :      d2gm(:,:)=0.5_dp*d2gm(:,:)
    1801              : 
    1802              : !    initialize energy accumulator
    1803          777 :      eacc=0._dp
    1804          777 :      deacc01=0._dp
    1805          777 :      deacc10=0._dp
    1806          777 :      d2eacc=0._dp
    1807              : 
    1808          777 :      id2=n2/2+2
    1809          777 :      id3=n3/2+2
    1810              : !    Triple loop on each dimension
    1811        17115 :      do i3=1,n3
    1812        16338 :        ig3=i3-(i3/id3)*n3-1
    1813        16338 :        gqr(3)=gq(3,i3)
    1814       292299 :        do i2=1,n2
    1815       291522 :          if (fftn2_distrib(i2)==me_fft) then
    1816       275184 :            gqr(2)=gq(2,i2)
    1817       275184 :            ig2=i2-(i2/id2)*n2-1
    1818       275184 :            i23=n1*(ffti2_local(i2)-1 +(n2/nproc_fft)*(i3-1))
    1819              : !          Do the test that eliminates the Gamma point outside
    1820              : !          of the inner loop
    1821       275184 :            ii1=1
    1822       275184 :            if(i23==0 .and. ig2==0 .and. ig3==0)then
    1823          777 :              ii1=2
    1824              :            end if
    1825              : 
    1826              : !          Final inner loop on the first dimension
    1827              : !          (note the lower limit)
    1828      5003901 :            do i1=ii1,n1
    1829      4728717 :              gqr(1)=gq(1,i1)
    1830              :              gs=(gmet(1,1)*gqr(1)*gqr(1)+gmet(2,2)*gqr(2)*gqr(2)+&
    1831              : &             gmet(3,3)*gqr(3)*gqr(3)+2._dp*&
    1832              : &             (gmet(1,2)*gqr(1)*gqr(2) + gmet(1,3)*gqr(1)*gqr(3)+&
    1833      4728717 : &             gmet(2,3)*gqr(2)*gqr(3)) )
    1834      4728717 :              ii=i1+i23
    1835      5003901 :              if(gs<=cutoff)then
    1836              :                dgs01=(dgm01(1,1)*gqr(1)*gqr(1)+dgm01(2,2)*gqr(2)*gqr(2)+&
    1837              : &               dgm01(3,3)*gqr(3)*gqr(3)+2._dp*&
    1838              : &               (dgm01(1,2)*gqr(1)*gqr(2) + dgm01(1,3)*gqr(1)*gqr(3)+&
    1839      1552110 : &               dgm01(2,3)*gqr(2)*gqr(3)) )
    1840              :                dgs10=(dgm10(1,1)*gqr(1)*gqr(1)+dgm10(2,2)*gqr(2)*gqr(2)+&
    1841              : &               dgm10(3,3)*gqr(3)*gqr(3)+2._dp*&
    1842              : &               (dgm10(1,2)*gqr(1)*gqr(2) + dgm10(1,3)*gqr(1)*gqr(3)+&
    1843      1552110 : &               dgm10(2,3)*gqr(2)*gqr(3)) )
    1844              :                d2gs =(d2gm(1,1)*gqr(1)*gqr(1)+d2gm(2,2)*gqr(2)*gqr(2)+&
    1845              : &               d2gm(3,3)*gqr(3)*gqr(3)+2._dp*&
    1846              : &               (d2gm(1,2)*gqr(1)*gqr(2) + d2gm(1,3)*gqr(1)*gqr(3)+&
    1847      1552110 : &               d2gm(2,3)*gqr(2)*gqr(3)) )
    1848              : 
    1849      1552110 :                term=(rhog(re,ii)**2+rhog(im,ii)**2)/gs
    1850      1552110 :                eacc=eacc+term
    1851      1552110 :                deacc01=deacc01+dgs01*term/gs
    1852      1552110 :                deacc10=deacc10+dgs10*term/gs
    1853      1552110 :                d2eacc=d2eacc+(-d2gs+2._dp*dgs01*dgs10/gs)*term/gs
    1854              :              end if
    1855              : 
    1856              : !            End loop on i1
    1857              :            end do
    1858              :          end if
    1859              : !        End loop on i2
    1860              :        end do
    1861              : !      End loop on i3
    1862              :      end do
    1863              : 
    1864              : !    Add contributions taking account diagonal strain terms (from ucvol
    1865              : !    derivatives)
    1866          777 :      d2etot=d2eacc
    1867          777 :      if(istr1<=3) d2etot=d2etot+deacc10
    1868          777 :      if(istr2<=3) d2etot=d2etot+deacc01
    1869          777 :      if(istr1<=3 .and. istr2<=3) d2etot=d2etot+eacc
    1870              : 
    1871          999 :      eltfrhar(istr1,istr2)=fact*d2etot
    1872              : 
    1873              : !    End loop on istr1
    1874              :    end do
    1875              : !  End loop in istr2
    1876              :  end do
    1877              : 
    1878           37 :  ABI_FREE(gq)
    1879              : 
    1880              : !Init mpi_comm
    1881           37 :  call timab(48,1,tsec)
    1882           37 :  call xmpi_sum(eltfrhar,mpi_enreg%comm_fft,ierr)
    1883           37 :  call timab(48,2,tsec)
    1884              : 
    1885              : !Fill in lower triangle
    1886          222 :  do jj=2,6
    1887          777 :    do ii=1,jj-1
    1888          740 :      eltfrhar(jj,ii)=eltfrhar(ii,jj)
    1889              :    end do
    1890              :  end do
    1891           37 : end subroutine dfpt_eltfrhar
    1892              : !!***
    1893              : 
    1894              : !!****f* ABINIT/elt_ewald
    1895              : !!
    1896              : !! NAME
    1897              : !! elt_ewald
    1898              : !!
    1899              : !! FUNCTION
    1900              : !! Compute 2nd derivatives of Ewald energy wrt strain for frozen wavefunction
    1901              : !! contributions to elastic tensor
    1902              : !!
    1903              : !! INPUTS
    1904              : !! gmet(3,3)=metric tensor in reciprocal space (bohr^-2)
    1905              : !! gprimd(3,3)=dimensional primitive translations for reciprocal space (bohr^-1)
    1906              : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
    1907              : !! comm_atom=--optional-- MPI communicator over atoms
    1908              : !! my_natom=number of atoms treated by current processor
    1909              : !! natom=number of atoms in unit cell
    1910              : !! ntypat=numbe of type of atoms
    1911              : !! rmet(3,3)=metric tensor in real space (bohr^2)
    1912              : !! rprimd(3,3)=dimensional primitive translation vectors (bohr)
    1913              : !! typat(natom)=integer label of each type of atom (1,2,...)
    1914              : !! ucvol=unit cell volume (bohr^3)
    1915              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
    1916              : !! zion(ntypat)=charge on each type of atom (real number)
    1917              : !!
    1918              : !! OUTPUT
    1919              : !! elteew(6+3*natom,6)=2nd derivatives of Ewald energy wrt strain
    1920              : !!
    1921              : !! SOURCE
    1922              : 
    1923           74 : subroutine elt_ewald(elteew,gmet,gprimd,my_natom,natom,ntypat,rmet,rprimd,&
    1924           37 : &                 typat,ucvol,xred,zion, &
    1925           37 : &                 mpi_atmtab,comm_atom) ! optional arguments (parallelism)
    1926              : 
    1927              : !Arguments ------------------------------------
    1928              : !scalars
    1929              :  integer,intent(in) :: my_natom,natom,ntypat
    1930              :  real(dp),intent(in) :: ucvol
    1931              : !arrays
    1932              :  integer,intent(in) :: typat(natom)
    1933              :  integer,optional,intent(in) :: comm_atom
    1934              :  integer,optional,target,intent(in) :: mpi_atmtab(:)
    1935              :  real(dp),intent(in) :: gmet(3,3),gprimd(3,3),rmet(3,3),rprimd(3,3)
    1936              :  real(dp),intent(in) :: xred(3,natom),zion(ntypat)
    1937              :  real(dp),intent(out) :: elteew(6+3*natom,6)
    1938              : 
    1939              : !Local variables-------------------------------
    1940              : !scalars
    1941              :  integer :: ia,ia0,ib,ierr,ig1,ig2,ig3,ir1,ir2,ir3,is1,is2,jj,js,ka,kb,kd,kg,my_comm_atom,newg,newr,ng,nr
    1942              :  logical :: my_atmtab_allocated,paral_atom
    1943              :  real(dp) :: arg,ch,chsq,cos_term,d2derfc,d2gss,d2r,d2rs,dderfc,derfc_arg
    1944              :  real(dp) :: dgss1,dgss2,direct,dr1,dr2,drs1,drs2,eew,eta,fac,fraca1,fraca2
    1945              :  real(dp) :: fraca3,fracb1,fracb2,fracb3,gsq,gsum,r1,r2,r3,recip,reta
    1946              :  real(dp) :: rmagn,rsq,sin_term,sumg,summi,summr,sumr,t1,term
    1947              :  character(len=500) :: message
    1948              : !arrays
    1949              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
    1950           37 :  integer,pointer :: my_atmtab(:)
    1951              :  real(dp) :: d2gm(3,3,6,6),d2ris(3),d2rm(3,3,6,6),dgm(3,3,6),dris(3),drm(3,3,6)
    1952              :  real(dp) :: t2(3),ts2(3),tsec(2),tt(3)
    1953           37 :  real(dp),allocatable :: d2sumg(:,:),d2sumr(:,:),drhoisi(:,:),drhoisr(:,:)
    1954           37 :  real(dp),allocatable :: mpibuf(:)
    1955              : 
    1956              : ! *************************************************************************
    1957              : 
    1958              : !DEBUG
    1959              : !write(std_out,*)' elt_ewald : enter '
    1960              : !stop
    1961              : !ENDDEBUG
    1962              : 
    1963              : !Compute 1st and 2nd derivatives of metric tensor wrt all strain components
    1964              : !and store for use in inner loop below.
    1965              : 
    1966              : !Set up parallelism over atoms
    1967           37 :  paral_atom=(present(comm_atom).and.(my_natom/=natom))
    1968           37 :  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
    1969           37 :  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
    1970           37 :  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
    1971              : 
    1972              : !Loop over 2nd strain index
    1973          259 :  do is2=1,6
    1974          222 :    kg=idx(2*is2-1);kd=idx(2*is2)
    1975          888 :    do jj = 1,3
    1976         2664 :      drm(:,jj,is2)=rprimd(kg,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kg,jj)
    1977         2886 :      dgm(:,jj,is2)=-(gprimd(kg,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kg,jj))
    1978              :    end do
    1979              : 
    1980              : !  Loop over 1st strain index, upper triangle only
    1981         1036 :    do is1=1,is2
    1982              : 
    1983          777 :      ka=idx(2*is1-1);kb=idx(2*is1)
    1984        10101 :      d2rm(:,:,is1,is2)=zero
    1985        10101 :      d2gm(:,:,is1,is2)=zero
    1986         3330 :      do jj = 1,3
    1987         2331 :        if(ka==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
    1988         4440 : &       +rprimd(kb,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(kb,jj)
    1989         2331 :        if(ka==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
    1990         2664 : &       +rprimd(kb,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(kb,jj)
    1991         2331 :        if(kb==kg) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
    1992         3108 : &       +rprimd(ka,:)*rprimd(kd,jj)+rprimd(kd,:)*rprimd(ka,jj)
    1993         2331 :        if(kb==kd) d2rm(:,jj,is1,is2)=d2rm(:,jj,is1,is2)&
    1994         4440 : &       +rprimd(ka,:)*rprimd(kg,jj)+rprimd(kg,:)*rprimd(ka,jj)
    1995              : 
    1996         2331 :        if(ka==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1997         4440 : &       +gprimd(kb,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(kb,jj)
    1998         2331 :        if(ka==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    1999         2664 : &       +gprimd(kb,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(kb,jj)
    2000         2331 :        if(kb==kg) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    2001         3108 : &       +gprimd(ka,:)*gprimd(kd,jj)+gprimd(kd,:)*gprimd(ka,jj)
    2002         2331 :        if(kb==kd) d2gm(:,jj,is1,is2)=d2gm(:,jj,is1,is2)&
    2003         5217 : &       +gprimd(ka,:)*gprimd(kg,jj)+gprimd(kg,:)*gprimd(ka,jj)
    2004              :      end do
    2005              :    end do !is1
    2006              :  end do !is2
    2007              : 
    2008              : !Add up total charge and sum of $charge^2$ in cell
    2009              :  chsq=zero
    2010              :  ch=zero
    2011          131 :  do ia=1,natom
    2012           94 :    ch=ch+zion(typat(ia))
    2013          131 :    chsq=chsq+zion(typat(ia))**2
    2014              :  end do
    2015              : 
    2016              : !Compute eta, the Ewald summation convergence parameter,
    2017              : !for approximately optimized summations:
    2018              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
    2019           37 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
    2020              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
    2021           37 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
    2022              : !Here, a bias is introduced, because G-space summation scales
    2023              : !better than r space summation ! Note : debugging is the most
    2024              : !easier at fixed eta.
    2025              : ! eta=pi*200._dp/33.0_dp*sqrt(1.69_dp*recip/direct)
    2026           37 : eta=1.0_dp
    2027              : 
    2028              : !Conduct reciprocal space summations
    2029           37 :  fac=pi**2/eta ; gsum=zero
    2030          185 :  ABI_MALLOC(d2sumg,(6+3*natom,6))
    2031          111 :  ABI_MALLOC(drhoisr,(3,natom))
    2032           74 :  ABI_MALLOC(drhoisi,(3,natom))
    2033         3283 :  d2sumg(:,:)=zero
    2034              : 
    2035              : !Sum over G space, done shell after shell until all
    2036              : !contributions are too small.
    2037           37 :  ng=0
    2038              :  do
    2039          930 :    ng=ng+1
    2040          930 :    newg=0
    2041              : 
    2042        28672 :    do ig3=-ng,ng
    2043      1174074 :      do ig2=-ng,ng
    2044     57209902 :        do ig1=-ng,ng
    2045              : 
    2046              : !        Exclude shells previously summed over
    2047              :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
    2048     57182160 : &         .or. ng==1 ) then
    2049              : 
    2050              : !          gsq is G dot G = |G|^2
    2051              :            gsq=gmet(1,1)*dble(ig1*ig1)+gmet(2,2)*dble(ig2*ig2)+&
    2052              : &           gmet(3,3)*dble(ig3*ig3)+2._dp*(gmet(2,1)*dble(ig1*ig2)+&
    2053      6546985 : &           gmet(3,1)*dble(ig1*ig3)+gmet(3,2)*dble(ig3*ig2))
    2054              : 
    2055              : !          Skip g=0:
    2056      6546985 :            if (gsq>1.0d-20) then
    2057      6546948 :              arg=fac*gsq
    2058              : 
    2059              : !            Larger arg gives 0 contribution because of exp(-arg)
    2060      6546948 :              if (arg <= 80._dp) then
    2061              : !              When any term contributes then include next shell
    2062      1275492 :                newg=1
    2063      1275492 :                term=exp(-arg)/gsq
    2064      1275492 :                summr = zero
    2065      1275492 :                summi = zero
    2066              : !              Note that if reduced atomic coordinates xred drift outside
    2067              : !              of unit cell (outside [0,1)) it is irrelevant in the following
    2068              : !              term, which only computes a phase.
    2069      5371384 :                do ia=1,natom
    2070      4095892 :                  arg=two_pi*(ig1*xred(1,ia)+ig2*xred(2,ia)+ig3*xred(3,ia))
    2071              : !                Sum real and imaginary parts (avoid complex variables)
    2072      4095892 :                  cos_term=cos(arg)
    2073      4095892 :                  sin_term=sin(arg)
    2074      4095892 :                  summr=summr+zion(typat(ia))*cos_term
    2075      4095892 :                  summi=summi+zion(typat(ia))*sin_term
    2076      4095892 :                  drhoisr(1,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig1)
    2077      4095892 :                  drhoisi(1,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig1)
    2078      4095892 :                  drhoisr(2,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig2)
    2079      4095892 :                  drhoisi(2,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig2)
    2080      4095892 :                  drhoisr(3,ia)=-two_pi*zion(typat(ia))*sin_term*dble(ig3)
    2081      5371384 :                  drhoisi(3,ia)= two_pi*zion(typat(ia))*cos_term*dble(ig3)
    2082              :                end do
    2083              : 
    2084              : !              The following two checks avoid an annoying
    2085              : !              underflow error message
    2086      1275492 :                if (abs(summr)<1.d-16) summr=zero
    2087      1275492 :                if (abs(summi)<1.d-16) summi=zero
    2088              : 
    2089              : !              The product of term and summr**2 or summi**2 below
    2090              : !              can underflow if not for checks above
    2091      1275492 :                t1=term*(summr*summr+summi*summi)
    2092      1275492 :                gsum=gsum+t1
    2093              : !              Loop over 2nd strain index
    2094      8928444 :                do is2=1,6
    2095              :                  dgss2=dgm(1,1,is2)*dble(ig1*ig1)+dgm(2,2,is2)*dble(ig2*ig2)+&
    2096              : &                 dgm(3,3,is2)*dble(ig3*ig3)+2._dp*(dgm(2,1,is2)*dble(ig1*ig2)+&
    2097      7652952 : &                 dgm(3,1,is2)*dble(ig1*ig3)+dgm(3,2,is2)*dble(ig3*ig2))
    2098              : !                Loop over 1st strain index, upper triangle only
    2099     34438284 :                  do is1=1,is2
    2100              :                    dgss1=dgm(1,1,is1)*dble(ig1*ig1)+dgm(2,2,is1)*dble(ig2*ig2)+&
    2101              : &                   dgm(3,3,is1)*dble(ig3*ig3)+2._dp*(dgm(2,1,is1)*dble(ig1*ig2)+&
    2102     26785332 : &                   dgm(3,1,is1)*dble(ig1*ig3)+dgm(3,2,is1)*dble(ig3*ig2))
    2103              : 
    2104              :                    d2gss=d2gm(1,1,is1,is2)*dble(ig1*ig1)+&
    2105              : &                   d2gm(2,2,is1,is2)*dble(ig2*ig2)+&
    2106              : &                   d2gm(3,3,is1,is2)*dble(ig3*ig3)+2._dp*&
    2107              : &                   (d2gm(2,1,is1,is2)*dble(ig1*ig2)+&
    2108              : &                   d2gm(3,1,is1,is2)*dble(ig1*ig3)+&
    2109     26785332 : &                   d2gm(3,2,is1,is2)*dble(ig3*ig2))
    2110              : 
    2111              :                    d2sumg(is1,is2)=d2sumg(is1,is2)+&
    2112              : &                   t1*((fac**2 + 2.0_dp*fac/gsq + 2.0_dp/(gsq**2))*dgss1*dgss2 -&
    2113     26785332 : &                   0.5_dp*(fac + 1.0_dp/gsq)*d2gss)
    2114     26785332 :                    if(is1<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+&
    2115     19132380 : &                   t1*(fac + 1.0_dp/gsq)*dgss2
    2116     26785332 :                    if(is2<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+&
    2117      7652952 : &                   t1*(fac + 1.0_dp/gsq)*dgss1
    2118     34438284 :                    if(is1<=3 .and. is2<=3) d2sumg(is1,is2)=d2sumg(is1,is2)+t1
    2119              : 
    2120              :                  end do !is1
    2121              : 
    2122              : !                Internal strain contributions
    2123     33503796 :                  do ia=1,natom
    2124     24575352 :                    js=7+3*(ia-1)
    2125     98301408 :                    t2(:)=2.0_dp*term*(summr*drhoisr(:,ia)+summi*drhoisi(:,ia))
    2126              :                    d2sumg(js:js+2,is2)=d2sumg(js:js+2,is2)-&
    2127     98301408 : &                   (fac + 1.0_dp/gsq)*dgss2*t2(:)
    2128     69091332 :                    if(is2<=3) d2sumg(js:js+2,is2)=d2sumg(js:js+2,is2)-t2(:)
    2129              :                  end do
    2130              :                end do !is2
    2131              : 
    2132              :              end if ! End condition of not larger than 80.0
    2133              :            end if ! End skip g=0
    2134              :          end if ! End triple loop over G s and associated new shell condition
    2135              :        end do
    2136              :      end do
    2137              :    end do
    2138              : 
    2139              : !  Check if new shell must be calculated
    2140          930 :    if (newg==0) exit
    2141              :  end do !  End the loop on ng (new shells). Note that there is one exit from this loop.
    2142              : 
    2143           37 :  sumg=gsum/(two_pi*ucvol)
    2144         3283 :  d2sumg(:,:)=d2sumg(:,:)/(two_pi*ucvol)
    2145              : 
    2146           37 :  ABI_FREE(drhoisr)
    2147           37 :  ABI_FREE(drhoisi)
    2148              : !Stress tensor is now computed elsewhere (ewald2) hence do not need
    2149              : !length scale gradients (used to compute them here).
    2150              : 
    2151              : !Conduct real space summations
    2152           37 :  reta=sqrt(eta)
    2153           37 :  fac=2._dp*sqrt(eta/pi)
    2154           74 :  ABI_MALLOC(d2sumr,(6+3*natom,6))
    2155         3283 :  sumr=zero;d2sumr(:,:)=zero
    2156              : 
    2157              : !In the following a summation is being conducted over all
    2158              : !unit cells (ir1, ir2, ir3) so it is appropriate to map all
    2159              : !reduced coordinates xred back into [0,1).
    2160              : !
    2161              : !Loop on shells in r-space as was done in g-space
    2162           37 :  nr=0
    2163              :  do
    2164           79 :    nr=nr+1
    2165           79 :    newr=0
    2166              : !
    2167          410 :    do ir3=-nr,nr
    2168         1913 :      do ir2=-nr,nr
    2169         9173 :        do ir1=-nr,nr
    2170         8842 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
    2171              : 
    2172        16773 :            do ia0=1,my_natom
    2173        11058 :              ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2174        11058 :              js=7+3*(ia-1)
    2175              : !            Map reduced coordinate xred(mu,ia) into [0,1)
    2176        11058 :              fraca1=xred(1,ia)-aint(xred(1,ia))+0.5_dp-sign(0.5_dp,xred(1,ia))
    2177        11058 :              fraca2=xred(2,ia)-aint(xred(2,ia))+0.5_dp-sign(0.5_dp,xred(2,ia))
    2178        11058 :              fraca3=xred(3,ia)-aint(xred(3,ia))+0.5_dp-sign(0.5_dp,xred(3,ia))
    2179        48641 :              do ib=1,natom
    2180        30244 :                fracb1=xred(1,ib)-aint(xred(1,ib))+0.5_dp-sign(0.5_dp,xred(1,ib))
    2181        30244 :                fracb2=xred(2,ib)-aint(xred(2,ib))+0.5_dp-sign(0.5_dp,xred(2,ib))
    2182        30244 :                fracb3=xred(3,ib)-aint(xred(3,ib))+0.5_dp-sign(0.5_dp,xred(3,ib))
    2183        30244 :                r1=dble(ir1)+fracb1-fraca1
    2184        30244 :                r2=dble(ir2)+fracb2-fraca2
    2185        30244 :                r3=dble(ir3)+fracb3-fraca3
    2186              :                rsq=rmet(1,1)*r1*r1+rmet(2,2)*r2*r2+rmet(3,3)*r3*r3+&
    2187        30244 : &               2.0_dp*(rmet(2,1)*r2*r1+rmet(3,2)*r3*r2+rmet(3,1)*r1*r3)
    2188              : 
    2189              : !              Avoid zero denominators in 'term':
    2190        41302 :                if (rsq>=1.0d-24) then
    2191              : 
    2192              : !                Note: erfc(8) is about 1.1e-29,
    2193              : !                so do not bother with larger arg.
    2194              : !                Also: exp(-64) is about 1.6e-28,
    2195              : !                so do not bother with larger arg**2 in exp.
    2196        30166 :                  term=zero
    2197        30166 :                  if (eta*rsq<64.0_dp) then
    2198         1380 :                    newr=1
    2199         1380 :                    rmagn=sqrt(rsq)
    2200         1380 :                    arg=reta*rmagn
    2201              : !                  derfc computes the complementary error function
    2202              : !                  dderfc is the derivative of the complementary error function
    2203              : !                  d2derfc is the 2nd derivative of the complementary error function
    2204         1380 :                    dderfc=-fac*exp(-eta*rsq)
    2205         1380 :                    d2derfc=-2._dp*eta*rmagn*dderfc
    2206         1380 :                    derfc_arg = abi_derfc(arg)
    2207         1380 :                    term=derfc_arg/rmagn
    2208         1380 :                    sumr=sumr+zion(typat(ia))*zion(typat(ib))*term
    2209         5520 :                    tt(:)=rmet(:,1)*r1+rmet(:,2)*r2+rmet(:,3)*r3
    2210         5520 :                    dris(:)=tt(:)/rmagn
    2211              : !                  Loop over 2nd strain index
    2212         9660 :                    do is2=1,6
    2213              :                      drs2=drm(1,1,is2)*r1*r1+drm(2,2,is2)*r2*r2+&
    2214              : &                     drm(3,3,is2)*r3*r3+&
    2215              : &                     2.0_dp*(drm(2,1,is2)*r2*r1+drm(3,2,is2)*r3*r2+&
    2216         8280 : &                     drm(3,1,is2)*r1*r3)
    2217         8280 :                      dr2=0.5_dp*drs2/rmagn
    2218              : !                    Loop over 1st strain index, upper triangle only
    2219        37260 :                      do is1=1,is2
    2220              :                        drs1=drm(1,1,is1)*r1*r1+drm(2,2,is1)*r2*r2+&
    2221              : &                       drm(3,3,is1)*r3*r3+&
    2222              : &                       2.0_dp*(drm(2,1,is1)*r2*r1+drm(3,2,is1)*r3*r2+&
    2223        28980 : &                       drm(3,1,is1)*r1*r3)
    2224        28980 :                        dr1=0.5_dp*drs1/rmagn
    2225              :                        d2rs=d2rm(1,1,is1,is2)*r1*r1+d2rm(2,2,is1,is2)*r2*r2+&
    2226              : &                       d2rm(3,3,is1,is2)*r3*r3+&
    2227              : &                       2.0_dp*(d2rm(2,1,is1,is2)*r2*r1+d2rm(3,2,is1,is2)*r3*r2+&
    2228        28980 : &                       d2rm(3,1,is1,is2)*r1*r3)
    2229        28980 :                        d2r=(0.25_dp*d2rs-dr1*dr2)/rmagn
    2230              :                        d2sumr(is1,is2)=d2sumr(is1,is2)+&
    2231              : &                       zion(typat(ia))*zion(typat(ib))*&
    2232              : &                       ((d2derfc-2.0_dp*dderfc/rmagn+2.0_dp*derfc_arg/rsq)*dr1*dr2+&
    2233        37260 : &                       (dderfc-derfc_arg/rmagn)*d2r)/rmagn
    2234              :                      end do !is1
    2235              : !                    Internal strain contribution
    2236        33120 :                      ts2(:)=drm(:,1,is2)*r1+drm(:,2,is2)*r2+drm(:,3,is2)*r3
    2237        33120 :                      d2ris(:)=ts2(:)/rmagn-0.5_dp*drs2*tt(:)/(rsq*rmagn)
    2238              : 
    2239              :                      d2sumr(js:js+2,is2)=d2sumr(js:js+2,is2)-&
    2240              : &                     2.0_dp*zion(typat(ia))*zion(typat(ib))*&
    2241              : &                     ((d2derfc-2.0_dp*dderfc/rmagn+2.0_dp*derfc_arg/rsq)*dr2*dris(:)+&
    2242        34500 : &                     (dderfc-derfc_arg/rmagn)*d2ris(:))/rmagn
    2243              :                    end do !is2
    2244              :                  end if
    2245              :                end if ! End avoid zero denominators in'term'
    2246              : 
    2247              :              end do ! end loop over ib:
    2248              :            end do ! end loop over ia:
    2249              :          end if ! end triple loop over real space points and associated condition of new shell
    2250              :        end do
    2251              :      end do
    2252              :    end do
    2253              : 
    2254              : !  Check if new shell must be calculated
    2255           79 :    if(newr==0) exit
    2256              :  end do !  End loop on nr (new shells). Note that there is an exit within the loop
    2257              : 
    2258              : !In case of parallelism over atoms: communicate
    2259           37 :  if (paral_atom) then
    2260            6 :    call timab(48,1,tsec)
    2261           18 :    ABI_MALLOC(mpibuf,((6+3*natom)*6+1))
    2262           12 :    mpibuf(1:(6+3*natom)*6)=reshape(d2sumr(:,:),shape=(/((6+3*natom)*6)/))
    2263            6 :    mpibuf((6+3*natom)*6+1)=sumr
    2264            6 :    call xmpi_sum(mpibuf,my_comm_atom,ierr)
    2265            6 :    sumr=mpibuf((6+3*natom)*6+1)
    2266           18 :    d2sumr(:,:)=reshape(mpibuf(1:(6+3*natom)*6),shape=(/(6+3*natom),6/))
    2267            6 :    ABI_FREE(mpibuf)
    2268           12 :    call timab(48,2,tsec)
    2269              :  end if
    2270              : 
    2271           37 :  sumr=0.5_dp*sumr
    2272         3283 :  d2sumr(:,:)=0.5_dp*d2sumr(:,:)
    2273           37 :  fac=pi*ch**2/(2.0_dp*eta*ucvol)
    2274              : 
    2275              : !Finally assemble Ewald energy, eew
    2276           37 :  eew=sumg+sumr-chsq*reta/sqrt(pi)-fac
    2277              : 
    2278         3283 :  elteew(:,:)=d2sumg(:,:)+d2sumr(:,:)
    2279              : 
    2280              : !Additional term for all strains diagonal (from "fac" term in eew)
    2281          481 :  elteew(1:3,1:3)=elteew(1:3,1:3)-fac
    2282              : 
    2283              : !Fill in lower triangle
    2284          222 :  do is2=2,6
    2285          777 :    do is1=1,is2-1
    2286          740 :      elteew(is2,is1)=elteew(is1,is2)
    2287              :    end do
    2288              :  end do
    2289              : 
    2290           37 :  ABI_FREE(d2sumg)
    2291           37 :  ABI_FREE(d2sumr)
    2292              : 
    2293              : !Output the final values of ng and nr
    2294           37 :  write(message, '(a,i4,a,i4)' )' elt_ewald : nr and ng are ',nr,' and ',ng
    2295           37 :  call wrtout(std_out,message,'COLL')
    2296              : 
    2297              : !Destroy atom table used for parallelism
    2298           37 :  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
    2299              : 
    2300           74 : end subroutine elt_ewald
    2301              : !!***
    2302              : 
    2303              : !!****f* ABINIT/dfpt_ewald
    2304              : !!
    2305              : !! NAME
    2306              : !! dfpt_ewald
    2307              : !!
    2308              : !! FUNCTION
    2309              : !! Compute ewald contribution to the dynamical matrix, at a given q wavevector.
    2310              : !! Note: the q=0 part should be subtracted, by another call to
    2311              : !! the present routine, with q=0. The present routine correspond
    2312              : !! to the quantity C_bar defined in Eq.(24) or (27) in Phys. Rev. B 55, 10355 (1997) [[cite:Gonze1997a]].
    2313              : !! The two calls correspond to Eq.(23) of the same paper.
    2314              : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
    2315              : !!
    2316              : !! INPUTS
    2317              : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
    2318              : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
    2319              : !! comm_atom=--optional-- MPI communicator over atoms
    2320              : !! icutcoul= type of Coulomb cutoff to apply
    2321              : !! my_natom=number of atoms treated by current processor
    2322              : !! natom=number of atoms in unit cell
    2323              : !! qphon(3)=phonon wavevector (same system of coordinates as the
    2324              : !!          reciprocal lattice vectors)
    2325              : !! rmet(3,3)=metric tensor in real space (length units squared)
    2326              : !! sumg0: if=1, the sum in reciprocal space must include g=0,
    2327              : !!   if=0, this contribution must be skipped (q=0 singularity)
    2328              : !! typat(natom)=integer label of each type of atom (1,2,...)
    2329              : !! ucvol=unit cell volume in (whatever length scale units)**3
    2330              : !! vcutgeo(3)= array to describe the geometry of the Coulomb cutoff
    2331              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
    2332              : !! zion(ntypat)=charge on each type of atom (real number)
    2333              : !!
    2334              : !! OUTPUT
    2335              : !! dyew(2,3,natom,3,natom)= Ewald part of the dynamical matrix,
    2336              : !!    second energy derivative wrt xred(3,natom), Hartrees.
    2337              : !!
    2338              : !! SOURCE
    2339              : 
    2340         1800 : subroutine dfpt_ewald(dyew,gmet,gsqcut,icutcoul,my_natom,natom,ngfft,nkpt,qphon,rcut, &
    2341          900 : &                 rmet,rprimd,sumg0,typat,ucvol,vcutgeo,xred,zion, &
    2342          900 : &                 mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
    2343              : 
    2344              : !Arguments -------------------------------
    2345              : !scalars
    2346              :  integer,intent(in) :: icutcoul,my_natom,natom,nkpt,sumg0
    2347              :  real(dp),intent(in) :: gsqcut,rcut,ucvol
    2348              : !arrays
    2349              :  integer,intent(in) :: ngfft(18),typat(natom)
    2350              :  integer,optional,intent(in) :: comm_atom
    2351              :  integer,optional,target,intent(in) :: mpi_atmtab(:)
    2352              :  real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),rprimd(3,3),vcutgeo(3),xred(3,natom),zion(*)
    2353              :  real(dp),intent(out) :: dyew(2,3,natom,3,natom)
    2354              : 
    2355              : !Local variables -------------------------
    2356              : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
    2357              : !scalars
    2358              :  integer,parameter :: im=2,ng=10,nr=6,re=1
    2359              :  integer :: ia,ia0,ib,ierr,ig,ig1,ig2,ig23,ig3,ii,ing
    2360              :  integer :: ir1,ir2,ir3,mu,my_comm_atom,nh,nu
    2361              :  logical :: my_atmtab_allocated,paral_atom,computeit
    2362              :  real(dp) :: arg,arga,argb,c1i,c1r,da1,da2,da3,derfc_arg
    2363              :  real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
    2364              :  real(dp) :: eta,fac,gdot12,gdot13,gdot23,gsq,gsum,norm1
    2365              :  real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
    2366              :  real(dp) :: reta3m,rmagn,rsq,term,term1,term2
    2367              :  real(dp) :: term3,facg0
    2368              :  character(len=500) :: message
    2369              : !arrays
    2370              :  integer :: id(3)
    2371          900 :  integer, allocatable :: inv_ig(:,:)
    2372              :  real(dp) :: tsec(2)
    2373          900 :  integer,pointer :: my_atmtab(:)
    2374              :  real(dp) :: gpq(3),rq(3)
    2375          900 :  real(dp),allocatable :: gcutoff(:)
    2376              : 
    2377              : ! *************************************************************************
    2378              : 
    2379              : !Set up parallelism over atoms
    2380          900 :  paral_atom=(present(comm_atom).and.(my_natom/=natom))
    2381          900 :  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
    2382          900 :  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
    2383          900 :  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
    2384              : 
    2385              : !Compute eta for approximately optimized summations:
    2386              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
    2387          900 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
    2388              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
    2389          900 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
    2390          900 :  eta=pi*(dble(ng)/dble(nr))*sqrt(1.69_dp*recip/direct)
    2391              : 
    2392              : !Test Ewald s summation
    2393              : !eta=1.2_dp*eta
    2394              : 
    2395              : !Initialize Gcut-off array from m_gtermcutoff
    2396              :  call termcutoff(gcutoff,gsqcut,icutcoul,ngfft,nkpt,rcut,rprimd,vcutgeo,&
    2397          900 : &                qpt=qphon)
    2398              : 
    2399              : !Need a way to reverse mapping the indexes inside termcutoff and Ewald rotines
    2400          900 :  nh=MAX(ngfft(1),ngfft(2),ngfft(3))/2
    2401         2700 :  ABI_MALLOC(inv_ig,(3,-nh:nh))
    2402         3600 :  do ii=1,3
    2403         2700 :    id(ii)=ngfft(ii)/2+2
    2404        50628 :    do ing=1,ngfft(ii)
    2405        47028 :      ig=ing-(ing/id(ii))*ngfft(ii)-1
    2406              :      ! Create reverse mapping
    2407        49728 :      inv_ig(ii, ig) = ing
    2408              :    end do
    2409              :  end do
    2410              : 
    2411              : !Sum terms over g space:
    2412          900 :  fac=pi**2/eta
    2413          900 :  gsum=zero
    2414          900 :  da1=zero
    2415          900 :  da2=zero
    2416          900 :  da3=zero
    2417       180724 :  dyew(:,:,:,:,:)=zero
    2418              :  ii=0
    2419        19800 :  do ig3=-ng,ng
    2420       416700 :    do ig2=-ng,ng
    2421      8750700 :      do ig1=-ng,ng
    2422      8334900 :        ii=ii+1
    2423      8334900 :        gpq(1)=dble(ig1)+qphon(1)
    2424      8334900 :        gpq(2)=dble(ig2)+qphon(2)
    2425      8334900 :        gpq(3)=dble(ig3)+qphon(3)
    2426      8334900 :        gdot12=gmet(2,1)*gpq(1)*gpq(2)
    2427      8334900 :        gdot13=gmet(3,1)*gpq(1)*gpq(3)
    2428      8334900 :        gdot23=gmet(3,2)*gpq(2)*gpq(3)
    2429      8334900 :        dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
    2430      8334900 :        dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
    2431      8334900 :        dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
    2432      8334900 :        gsq=dot1+dot2+dot3
    2433      8334900 :        facg0= zero
    2434      8334900 :        computeit= .true.
    2435              : !      Skip q=0:
    2436      8334900 :        if (gsq<1.0d-20) then
    2437          690 :          computeit= .false.
    2438          690 :          if (sumg0==1) then
    2439              :            write(message,'(5a)')&
    2440            0 : &           'The phonon wavelength should not be zero : ',ch10,&
    2441            0 : &           'there are non-analytical terms that the code cannot handle.',ch10,&
    2442            0 : &           'Action : subtract this wavelength from the input.'
    2443            0 :            ABI_ERROR(message)
    2444              :          end if
    2445              :        else
    2446      8334210 :          if (icutcoul==55.and.(ig1==0 .and. ig2==0 .and. ig3==0).and. sumg0==0) then
    2447              :            facg0= one
    2448              :          end if
    2449              : !        Endif g/=0 :
    2450              :        end if
    2451              : 
    2452       396900 :        if (computeit) then
    2453      8334210 :          arg=fac*gsq
    2454              : !        Larger arg gives 0 contribution:
    2455      8334210 :          if (arg <= 80._dp) then
    2456              : 
    2457              :            ! Apply cutoff
    2458              :            if ((abs(ig1).lt.ngfft(1)/2).and.&
    2459       962086 :            &   (abs(ig2).lt.ngfft(2)/2).and.&
    2460              :            &   (abs(ig3).lt.ngfft(3)/2)) then
    2461              :              ! Use inv_ig to map back to ing indices
    2462       702357 :              ig23=ngfft(1)*(inv_ig(2,ig2)-1 + ngfft(2)*(inv_ig(3,ig3)-1))
    2463       702357 :              ii=inv_ig(1,ig1)+ig23
    2464       702357 :              term=exp(-arg-facg0)/gsq * gcutoff(ii)
    2465       259729 :            else if (icutcoul.ne.3) then
    2466              :              term=zero
    2467              :            else
    2468       259729 :              term=exp(-arg)/gsq
    2469              :            end if
    2470              : 
    2471      3179405 :            do ia0=1,my_natom
    2472      2217319 :              ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2473      2217319 :              arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
    2474      9399142 :              do ib=1,ia
    2475      6219737 :                argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
    2476      6219737 :                arg=arga-argb
    2477      6219737 :                c1r=cos(arg)*term
    2478      6219737 :                c1i=sin(arg)*term
    2479              : 
    2480     27096267 :                do mu=1,3
    2481     62197370 :                  do nu=1,mu
    2482     37318422 :                    dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+gpq(mu)*gpq(nu)*c1r
    2483     55977633 :                    dyew(im,mu,ia,nu,ib)=dyew(im,mu,ia,nu,ib)+gpq(mu)*gpq(nu)*c1i
    2484              :                  end do
    2485              :                end do
    2486              : 
    2487              :              end do
    2488              :            end do
    2489              :          end if
    2490              : !        Endif computeit:
    2491              :        end if
    2492              : !      End triple loop over G s:
    2493              :      end do
    2494              :    end do
    2495              :  end do
    2496              : 
    2497          900 :  ABI_FREE(gcutoff)
    2498          900 :  ABI_FREE(inv_ig)
    2499              : 
    2500              : !End G summation by accounting for some common factors.
    2501              : !(for the charges:see end of routine)
    2502          900 :  norm1=4.0_dp*pi/ucvol
    2503         2654 :  do ia0=1,my_natom
    2504         1754 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2505         6060 :    do ib=1,ia
    2506        15378 :      do mu=1,3
    2507        34060 :        do nu=1,mu
    2508        71526 :          dyew(:,mu,ia,nu,ib)=dyew(:,mu,ia,nu,ib)*norm1
    2509              :        end do
    2510              :      end do
    2511              :    end do
    2512              :  end do
    2513              : 
    2514              : !Do sums over real space:
    2515          900 :  reta=sqrt(eta)
    2516          900 :  reta3m=-eta*reta
    2517          900 :  fac=4._dp/3.0_dp/sqrt(pi)
    2518        12600 :  do ir3=-nr,nr
    2519       164700 :    do ir2=-nr,nr
    2520      2141100 :      do ir1=-nr,nr
    2521      1977300 :        arg=-two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
    2522      1977300 :        c1r=cos(arg)*reta3m
    2523      1977300 :        c1i=sin(arg)*reta3m
    2524      5982938 :        do ia0=1,my_natom
    2525      3853538 :          ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2526     13313820 :          do ib=1,ia
    2527      7482982 :            r1=dble(ir1)+xred(1,ia)-xred(1,ib)
    2528      7482982 :            r2=dble(ir2)+xred(2,ia)-xred(2,ib)
    2529      7482982 :            r3=dble(ir3)+xred(3,ia)-xred(3,ib)
    2530      7482982 :            rdot12=rmet(2,1)*r1*r2
    2531      7482982 :            rdot13=rmet(3,1)*r1*r3
    2532      7482982 :            rdot23=rmet(3,2)*r2*r3
    2533      7482982 :            dotr1=rmet(1,1)*r1**2+rdot12+rdot13
    2534      7482982 :            dotr2=rmet(2,2)*r2**2+rdot12+rdot23
    2535      7482982 :            dotr3=rmet(3,3)*r3**2+rdot13+rdot23
    2536      7482982 :            rsq=dotr1+dotr2+dotr3
    2537      7482982 :            rmagn=sqrt(rsq)
    2538              : !          Avoid zero denominators in term :
    2539     11336520 :            if (rmagn>=1.0d-12) then
    2540      7481228 :              arg=reta*rmagn
    2541      7481228 :              term=zero
    2542      7481228 :              if (arg<8.0_dp) then
    2543              : !              Note: erfc(8) is about 1.1e-29,
    2544              : !              so don t bother with larger arg.
    2545              : !              Also: exp(-64) is about 1.6e-28,
    2546              : !              so don t bother with larger arg**2 in exp.
    2547       883974 :                derfc_arg = abi_derfc(arg)
    2548       883974 :                term=derfc_arg/arg**3
    2549       883974 :                term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
    2550       883974 :                term2=-(term+term1)
    2551       883974 :                term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
    2552       883974 :                rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
    2553       883974 :                rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
    2554       883974 :                rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
    2555      3535896 :                do mu=1,3
    2556      8839740 :                  do nu=1,mu
    2557              :                    dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+&
    2558      5303844 : &                   c1r*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    2559              :                    dyew(im,mu,ia,nu,ib)=dyew(im,mu,ia,nu,ib)+&
    2560      7955766 : &                   c1i*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    2561              :                  end do
    2562              :                end do
    2563              :              end if
    2564              :            else
    2565         1754 :              if (ia/=ib)then
    2566              :                write(message,'(a,a,a,a,a,i5,a,i5,a)')&
    2567            0 : &               'The distance between two atoms vanishes.',ch10,&
    2568            0 : &               'This is not allowed.',ch10,&
    2569            0 : &               'Action: check the input for the atoms number',ia,' and',ib,'.'
    2570            0 :                ABI_ERROR(message)
    2571              :              else
    2572         7016 :                do mu=1,3
    2573        17540 :                  do nu=1,mu
    2574              :                    dyew(re,mu,ia,nu,ib)=dyew(re,mu,ia,nu,ib)+&
    2575        15786 : &                   fac*reta3m*rmet(mu,nu)
    2576              :                  end do
    2577              :                end do
    2578              :              end if
    2579              :            end if
    2580              : 
    2581              :          end do ! End loop over ib:
    2582              :        end do ! End loop over ia:
    2583              :      end do ! End triple loop over real space points:
    2584              :    end do
    2585              :  end do
    2586              : 
    2587              : !Take account of the charges
    2588              : !write(std_out,*)' '
    2589         2654 :  do ia0=1,my_natom
    2590         1754 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2591         6060 :    do ib=1,ia
    2592        15378 :      do mu=1,3
    2593        34060 :        do nu=1,mu
    2594        71526 :          do ii=1,2
    2595              : !          write(std_out,*)dyew(ii,mu,ia,nu,ib)
    2596              :            dyew(ii,mu,ia,nu,ib)=dyew(ii,mu,ia,nu,ib)*&
    2597        61308 : &           zion(typat(ia))*zion(typat(ib))
    2598              :          end do
    2599              :        end do
    2600              :      end do
    2601              :    end do
    2602              :  end do
    2603              : 
    2604              : !Symmetrize with respect to the directions
    2605         2654 :  do ia0=1,my_natom
    2606         1754 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2607         6060 :    do ib=1,ia
    2608        15378 :      do mu=1,3
    2609        34060 :        do nu=1,mu
    2610        20436 :          dyew(re,nu,ia,mu,ib)=dyew(re,mu,ia,nu,ib)
    2611        30654 :          dyew(im,nu,ia,mu,ib)=dyew(im,mu,ia,nu,ib)
    2612              :        end do
    2613              :      end do
    2614              :    end do
    2615              :  end do
    2616              : 
    2617              : !In case of parallelism over atoms: communicate
    2618          900 :  if (paral_atom) then
    2619           44 :    call timab(48,1,tsec)
    2620           44 :    call xmpi_sum(dyew,my_comm_atom,ierr)
    2621           44 :    call timab(48,2,tsec)
    2622              :  end if
    2623              : 
    2624              : !Fill the upper part of the matrix, with the hermitian conjugate
    2625         2776 :  do ia=1,natom
    2626         6586 :    do ib=1,ia
    2627        17116 :      do nu=1,3
    2628        49530 :        do mu=1,3
    2629        34290 :          dyew(re,mu,ib,nu,ia)=dyew(re,mu,ia,nu,ib)
    2630        45720 :          dyew(im,mu,ib,nu,ia)=-dyew(im,mu,ia,nu,ib)
    2631              :        end do
    2632              :      end do
    2633              :    end do
    2634              :  end do
    2635              : 
    2636              : !Destroy atom table used for parallelism
    2637          900 :  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
    2638              : 
    2639          900 : end subroutine dfpt_ewald
    2640              : !!***
    2641              : 
    2642              : !!****f* ABINIT/dfpt_ewalddq
    2643              : !!
    2644              : !! NAME
    2645              : !! dfpt_ewalddq
    2646              : !!
    2647              : !! FUNCTION
    2648              : !! Compute the first q-gradient of Ewald contribution to the dynamical matrix, at a given q wavevector.
    2649              : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
    2650              : !!
    2651              : !! COPYRIGHT
    2652              : !! Copyright (C) 1998-2026 ABINIT group (MR, MS)
    2653              : !!  This file is distributed under the terms of the
    2654              : !!  GNU General Public License, see ~abinit/COPYING
    2655              : !!  or http://www.gnu.org/copyleft/gpl.txt .
    2656              : !!
    2657              : !! INPUTS
    2658              : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
    2659              : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
    2660              : !! comm_atom=--optional-- MPI communicator over atoms
    2661              : !! my_natom=number of atoms treated by current processor
    2662              : !! natom=number of atoms in unit cell
    2663              : !! qphon(3)=phonon wavevector (same system of coordinates as the
    2664              : !!          reciprocal lattice vectors)
    2665              : !! rmet(3,3)=metric tensor in real space (length units squared)
    2666              : !! sumg0: if=1, the sum in reciprocal space must include g=0,
    2667              : !!   if=0, this contribution must be skipped (q=0 singularity)
    2668              : !! typat(natom)=integer label of each type of atom (1,2,...)
    2669              : !! ucvol=unit cell volume in (whatever length scale units)**3
    2670              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
    2671              : !! zion(ntypat)=charge on each type of atom (real number)
    2672              : !!
    2673              : !! OUTPUT
    2674              : !! dyewdq(2,3,natom,3,natom,3)= First q-gradient of Ewald part of the dynamical matrix,
    2675              : !!    second energy derivative wrt xred(3,natom), Hartrees.
    2676              : !!
    2677              : !! SOURCE
    2678              : 
    2679            6 : subroutine dfpt_ewalddq(dyewdq,gmet,my_natom,natom,qphon,rmet,sumg0,typat,ucvol,xred,zion, &
    2680            3 : &                 mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
    2681              : 
    2682              : !Arguments -------------------------------
    2683              : !scalars
    2684              :  integer,intent(in) :: my_natom,natom,sumg0
    2685              :  real(dp),intent(in) :: ucvol
    2686              : !arrays
    2687              :  integer,intent(in) :: typat(natom)
    2688              :  integer,optional,intent(in) :: comm_atom
    2689              :  integer,optional,target,intent(in) :: mpi_atmtab(:)
    2690              :  real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),xred(3,natom),zion(*)
    2691              :  real(dp),intent(out) :: dyewdq(2,3,natom,3,natom,3)
    2692              : 
    2693              : !Local variables -------------------------
    2694              : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
    2695              : !scalars
    2696              :  integer,parameter :: im=2,nng=10,nnr=6,re=1
    2697              :  integer ::ia,ia0,ib,ierr,ig1,ig2,ig3,ii,iq,ir1,ir2,ir3,mu,my_comm_atom,newg,newr,ng,nr,nu
    2698              :  logical :: my_atmtab_allocated,paral_atom
    2699              :  real(dp) :: arg,arga,argb,c1i,c1r,delag,delbg,derfc_arg
    2700              :  real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
    2701              :  real(dp) :: eta,fac,fac2,gdot12,gdot13,gdot23,gsq,gpqdq,gterms,norm1
    2702              :  real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
    2703              :  real(dp) :: reta3m,rmagn,rsq,term,term1,term2,term3
    2704              :  character(len=500) :: message
    2705              : !arrays
    2706              :  real(dp) :: tsec(2)
    2707            3 :  integer,pointer :: my_atmtab(:)
    2708              :  real(dp) :: dakk(3),gpq(3),rq(3)
    2709              : 
    2710              : ! *************************************************************************
    2711              : 
    2712              : !Set up parallelism over atoms
    2713            3 :  paral_atom=(present(comm_atom).and.(my_natom/=natom))
    2714            3 :  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
    2715            3 :  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
    2716            3 :  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
    2717              : 
    2718              : !Compute eta for approximately optimized summations:
    2719              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
    2720            3 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
    2721              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
    2722            3 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
    2723            3 :  eta=pi*(dble(nng)/dble(nnr))*sqrt(1.69_dp*recip/direct)
    2724              : 
    2725              : !Test Ewald s summation
    2726              : !eta=1.2_dp*eta
    2727              : 
    2728              : !Sum over G space, done shell after shell until all
    2729              : !contributions are too small.
    2730            3 :  fac=pi**2.d0/eta
    2731            3 :  fac2=2.d0*fac
    2732         1164 :  dyewdq(:,:,:,:,:,:)=zero
    2733              :  ng=0
    2734              :  do
    2735           18 :    ng=ng+1
    2736           18 :    newg=0
    2737              : 
    2738          162 :    do ig3=-ng,ng
    2739         1524 :      do ig2=-ng,ng
    2740        15762 :        do ig1=-ng,ng
    2741              : 
    2742              : !        Exclude shells previously summed over
    2743              :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
    2744        15618 : &         .or. ng==1 ) then
    2745              : 
    2746         6591 :            gpq(1)=dble(ig1)+qphon(1)
    2747         6591 :            gpq(2)=dble(ig2)+qphon(2)
    2748         6591 :            gpq(3)=dble(ig3)+qphon(3)
    2749         6591 :            gdot12=gmet(2,1)*gpq(1)*gpq(2)
    2750         6591 :            gdot13=gmet(3,1)*gpq(1)*gpq(3)
    2751         6591 :            gdot23=gmet(3,2)*gpq(2)*gpq(3)
    2752         6591 :            dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
    2753         6591 :            dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
    2754         6591 :            dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
    2755         6591 :            gsq=dot1+dot2+dot3
    2756              :   !        Skip q=0:
    2757         6591 :            if (gsq<1.0d-20) then
    2758            3 :              if (sumg0==1) then
    2759              :                write(message,'(3a)')&
    2760            0 :   &             'The G=0 term has no contributions at first order in q: ',ch10,&
    2761            0 :   &             'Action : sumg0=0 '
    2762            0 :                ABI_ERROR(message)
    2763              :              end if
    2764              :            else
    2765         6588 :              arg=fac*gsq
    2766              :   !          Larger arg gives 0 contribution:
    2767         6588 :              if (arg <= 80._dp) then
    2768              : !              When any term contributes then include next shell
    2769         1230 :                newg=1
    2770         1230 :                term=exp(-arg)/gsq
    2771         3690 :                do ia0=1,my_natom
    2772         2460 :                  ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2773         2460 :                  arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
    2774         7380 :                  do ib=1,ia
    2775         3690 :                    argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
    2776         3690 :                    arg=arga-argb
    2777         3690 :                    c1r=cos(arg)*term
    2778         3690 :                    c1i=sin(arg)*term
    2779              : 
    2780        17220 :                    do iq=1,3
    2781        11070 :                      gpqdq=gmet(iq,1)*gpq(1)+gmet(iq,2)*gpq(2)+gmet(iq,3)*gpq(3)
    2782        47970 :                      do mu=1,3
    2783        33210 :                        delag=zero; if(iq==mu) delag=one
    2784       110700 :                        do nu=1,mu
    2785        66420 :                          delbg=zero; if(iq==nu) delbg=one
    2786        66420 :                          term1=delag*gpq(nu)+delbg*gpq(mu)
    2787        66420 :                          term2=gpq(mu)*gpq(nu)*gpqdq
    2788        66420 :                          term3=fac2*term2
    2789        66420 :                          term2=two*term2/gsq
    2790        66420 :                          gterms=term1-term2-term3
    2791        66420 :                          dyewdq(re,mu,ia,nu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)+gterms*c1r
    2792        99630 :                          dyewdq(im,mu,ia,nu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)+gterms*c1i
    2793              :                        end do
    2794              :                      end do
    2795              :                    end do
    2796              : 
    2797              :                  end do
    2798              :                end do
    2799              :              end if
    2800              :   !          Endif g/=0 :
    2801              :            end if
    2802              :          end if
    2803              :   !        End triple loop over G s:
    2804              :        end do
    2805              :      end do
    2806              :    end do
    2807              : 
    2808              : !  Check if new shell must be calculated
    2809           18 :    if (newg==0) exit
    2810              :  end do !  End the loop on ng (new shells). Note that there is one exit from this loop.
    2811              : 
    2812              : !End G summation by accounting for some common factors.
    2813              : !(for the charges:see end of routine)
    2814            3 :  norm1=4.0_dp*pi/ucvol
    2815            9 :  do ia0=1,my_natom
    2816            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2817           18 :    do ib=1,ia
    2818           42 :      do iq=1,3
    2819          117 :        do mu=1,3
    2820          270 :          do nu=1,mu
    2821          567 :            dyewdq(:,mu,ia,nu,ib,iq)=dyewdq(:,mu,ia,nu,ib,iq)*norm1
    2822              :          end do
    2823              :        end do
    2824              :      end do
    2825              :    end do
    2826              :  end do
    2827              : 
    2828              : !Do sums over real space:
    2829            3 :  reta=sqrt(eta)
    2830            3 :  reta3m=-eta*reta
    2831            3 :  fac=4._dp/3.0_dp/sqrt(pi)
    2832            3 :  nr=0
    2833              :  do
    2834           18 :    nr=nr+1
    2835           18 :    newr=0
    2836              : 
    2837          162 :    do ir3=-nr,nr
    2838         1524 :      do ir2=-nr,nr
    2839        15762 :        do ir1=-nr,nr
    2840        15618 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
    2841              : 
    2842         6591 :            arg=two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
    2843         6591 :            c1r=cos(arg)*reta3m
    2844         6591 :            c1i=sin(arg)*reta3m
    2845        19773 :            do ia0=1,my_natom
    2846        13182 :              ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2847        47211 :              do ib=1,ia
    2848        19773 :                r1=dble(ir1)+xred(1,ib)-xred(1,ia)
    2849        19773 :                r2=dble(ir2)+xred(2,ib)-xred(2,ia)
    2850        19773 :                r3=dble(ir3)+xred(3,ib)-xred(3,ia)
    2851        79092 :                dakk(:)=two_pi*(/r1,r2,r3/)
    2852        19773 :                rdot12=rmet(2,1)*r1*r2
    2853        19773 :                rdot13=rmet(3,1)*r1*r3
    2854        19773 :                rdot23=rmet(3,2)*r2*r3
    2855        19773 :                dotr1=rmet(1,1)*r1**2+rdot12+rdot13
    2856        19773 :                dotr2=rmet(2,2)*r2**2+rdot12+rdot23
    2857        19773 :                dotr3=rmet(3,3)*r3**2+rdot13+rdot23
    2858        19773 :                rsq=dotr1+dotr2+dotr3
    2859        19773 :                rmagn=sqrt(rsq)
    2860              : !              Avoid zero denominators in term :
    2861        32955 :                if (rmagn>=1.0d-12) then
    2862        19767 :                  arg=reta*rmagn
    2863        19767 :                  term=zero
    2864        19767 :                  if (arg<8.0_dp) then
    2865              : !                  Note: erfc(8) is about 1.1e-29,
    2866              : !                  so don t bother with larger arg.
    2867              : !                  Also: exp(-64) is about 1.6e-28,
    2868              : !                  so don t bother with larger arg**2 in exp.
    2869         4200 :                    newr=1
    2870         4200 :                    derfc_arg = abi_derfc(arg)
    2871         4200 :                    term=derfc_arg/arg**3
    2872         4200 :                    term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
    2873         4200 :                    term2=-(term+term1)
    2874         4200 :                    term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
    2875         4200 :                    rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
    2876         4200 :                    rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
    2877         4200 :                    rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
    2878        16800 :                    do iq=1,3
    2879        54600 :                      do mu=1,3
    2880              : !                       do nu=1,3
    2881       126000 :                        do nu=1,mu
    2882              :                          dyewdq(re,mu,ia,nu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)-&
    2883        75600 : &                         c1i*dakk(iq)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    2884              :                          dyewdq(im,mu,ia,nu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)+&
    2885       113400 : &                         c1r*dakk(iq)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    2886              :                        end do
    2887              :                      end do
    2888              :                    end do
    2889              :                  end if
    2890              :                else
    2891            6 :                  if (ia/=ib)then
    2892              :                    write(message,'(a,a,a,a,a,i5,a,i5,a)')&
    2893            0 : &                   'The distance between two atoms vanishes.',ch10,&
    2894            0 : &                   'This is not allowed.',ch10,&
    2895            0 : &                   'Action: check the input for the atoms number',ia,' and',ib,'.'
    2896            0 :                    ABI_ERROR(message)
    2897              :                  end if
    2898              :                end if
    2899              : 
    2900              :              end do ! End loop over ib:
    2901              :            end do ! End loop over ia:
    2902              :          end if
    2903              :        end do ! End triple loop over real space points:
    2904              :      end do
    2905              :    end do
    2906              : 
    2907              : !  Check if new shell must be calculated
    2908           18 :    if(newr==0) exit
    2909              :  end do !  End loop on nr (new shells). Note that there is an exit within the loop
    2910              : 
    2911              : !Take account of the charges
    2912              : !write(std_out,*)' '
    2913            9 :  do ia0=1,my_natom
    2914            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2915           18 :    do ib=1,ia
    2916           42 :      do iq=1,3
    2917          117 :        do mu=1,3
    2918          270 :          do nu=1,mu
    2919          567 :            do ii=1,2
    2920              :              dyewdq(ii,mu,ia,nu,ib,iq)=dyewdq(ii,mu,ia,nu,ib,iq)*&
    2921          486 : &             zion(typat(ia))*zion(typat(ib))
    2922              :            end do
    2923              :          end do
    2924              :        end do
    2925              :      end do
    2926              :    end do
    2927              :  end do
    2928              : 
    2929              : !Symmetrize with respect to the directions
    2930            9 :  do ia0=1,my_natom
    2931            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    2932           18 :    do ib=1,ia
    2933           42 :      do iq=1,3
    2934          117 :        do mu=1,3
    2935          270 :          do nu=1,mu
    2936          162 :            dyewdq(re,nu,ia,mu,ib,iq)=dyewdq(re,mu,ia,nu,ib,iq)
    2937          243 :            dyewdq(im,nu,ia,mu,ib,iq)=dyewdq(im,mu,ia,nu,ib,iq)
    2938              :          end do
    2939              :        end do
    2940              :      end do
    2941              :    end do
    2942              :  end do
    2943              : 
    2944              : !In case of parallelism over atoms: communicate
    2945            3 :  if (paral_atom) then
    2946            0 :    call timab(48,1,tsec)
    2947            0 :    call xmpi_sum(dyewdq,my_comm_atom,ierr)
    2948            0 :    call timab(48,2,tsec)
    2949              :  end if
    2950              : 
    2951              : !Fill the upper part of the matrix, with the hermitian conjugate
    2952            9 :  do ia=1,natom
    2953           18 :    do ib=1,ia
    2954           42 :      do iq=1,3
    2955          117 :        do nu=1,3
    2956          351 :          do mu=1,3
    2957          243 :            dyewdq(re,mu,ib,nu,ia,iq)=dyewdq(re,mu,ia,nu,ib,iq)
    2958          324 :            dyewdq(im,mu,ib,nu,ia,iq)=-dyewdq(im,mu,ia,nu,ib,iq)
    2959              :          end do
    2960              :        end do
    2961              :      end do
    2962              :    end do
    2963              :  end do
    2964              : 
    2965              : !Destroy atom table used for parallelism
    2966            3 :  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
    2967              : 
    2968            3 : end subroutine dfpt_ewalddq
    2969              : !!***
    2970              : 
    2971              : !!****f* ABINIT/dfpt_ewalddqdq
    2972              : !!
    2973              : !! NAME
    2974              : !! dfpt_ewalddqdq
    2975              : !!
    2976              : !! FUNCTION
    2977              : !! Compute the second q-gradient of Ewald contribution to the dynamical matrix, at a given q wavevector,
    2978              : !! sumed over the second atomic sublattice.
    2979              : !! If q=0 is asked, sumg0 should be put to 0. Otherwise, it should be put to 1.
    2980              : !!
    2981              : !! COPYRIGHT
    2982              : !! Copyright (C) 1998-2026 ABINIT group (MR, MS)
    2983              : !!  This file is distributed under the terms of the
    2984              : !!  GNU General Public License, see ~abinit/COPYING
    2985              : !!  or http://www.gnu.org/copyleft/gpl.txt .
    2986              : !!
    2987              : !! INPUTS
    2988              : !! gmet(3,3)=metric tensor in reciprocal space (length units **-2)
    2989              : !! mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
    2990              : !! comm_atom=--optional-- MPI communicator over atoms
    2991              : !! my_natom=number of atoms treated by current processor
    2992              : !! natom=number of atoms in unit cell
    2993              : !! qphon(3)=phonon wavevector (same system of coordinates as the
    2994              : !!          reciprocal lattice vectors)
    2995              : !! rmet(3,3)=metric tensor in real space (length units squared)
    2996              : !! sumg0: if=1, the sum in reciprocal space must include g=0,
    2997              : !!   if=0, this contribution must be skipped (q=0 singularity)
    2998              : !! typat(natom)=integer label of each type of atom (1,2,...)
    2999              : !! ucvol=unit cell volume in (whatever length scale units)**3
    3000              : !! xred(3,natom)=relative coords of atoms in unit cell (dimensionless)
    3001              : !! zion(ntypat)=charge on each type of atom (real number)
    3002              : !!
    3003              : !! OUTPUT
    3004              : !! dyewdqdq(2,3,natom,3,3,3)= First q-gradient of Ewald part of the dynamical matrix,
    3005              : !!    sumed over second atomic sublattice.
    3006              : !!
    3007              : !! SOURCE
    3008              : 
    3009            6 : subroutine dfpt_ewalddqdq(dyewdqdq,gmet,my_natom,natom,qphon,rmet,sumg0,typat,ucvol,xred,zion, &
    3010            3 : &                 mpi_atmtab,comm_atom ) ! optional arguments (parallelism))
    3011              : 
    3012              : !Arguments -------------------------------
    3013              : !scalars
    3014              :  integer,intent(in) :: my_natom,natom,sumg0
    3015              :  real(dp),intent(in) :: ucvol
    3016              : !arrays
    3017              :  integer,intent(in) :: typat(natom)
    3018              :  integer,optional,intent(in) :: comm_atom
    3019              :  integer,optional,target,intent(in) :: mpi_atmtab(:)
    3020              :  real(dp),intent(in) :: gmet(3,3),qphon(3),rmet(3,3),xred(3,natom),zion(*)
    3021              :  real(dp),intent(out) :: dyewdqdq(2,3,natom,3,3,3)
    3022              : 
    3023              : !Local variables -------------------------
    3024              : !nr, ng affect convergence of sums (nr=3,ng=5 is not good enough):
    3025              : !scalars
    3026              :  integer,parameter :: im=2,nng=10,nnr=6,re=1
    3027              :  integer :: ia,ia0,ib,ierr,ig1,ig2,ig3,ii,iq1,iq2,ir1,ir2,ir3,mu,my_comm_atom,newg,newr,ng,nr,nu
    3028              :  logical :: my_atmtab_allocated,paral_atom
    3029              :  real(dp) :: arg,arga,argb,c1i,c1r,delad,delag,delbd,delbg,derfc_arg
    3030              :  real(dp) :: direct,dot1,dot2,dot3,dotr1,dotr2,dotr3
    3031              :  real(dp) :: eta,fac,fac2,fac8,fac2sqr,gdot12,gdot13,gdot23,gsq,gsqsq,gpqdq1,gpqdq2,gterms,g0term,norm1
    3032              :  real(dp) :: r1,r2,r3,rdot12,rdot13,rdot23,recip,reta
    3033              :  real(dp) :: reta3m,rmagn,rsq,term,term1,term2,term3
    3034              :  character(len=500) :: message
    3035              : !arrays
    3036            3 :  integer,pointer :: my_atmtab(:)
    3037              :  real(dp) :: dakk(3),gpq(3),rq(3)
    3038              :  real(dp) :: tsec(2)
    3039            3 :  real(dp),allocatable :: work(:,:,:,:,:,:,:)
    3040              : 
    3041              : ! *************************************************************************
    3042              : 
    3043              : !Set up parallelism over atoms
    3044            3 :  paral_atom=(present(comm_atom).and.(my_natom/=natom))
    3045            3 :  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
    3046            3 :  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
    3047            3 :  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
    3048              : 
    3049              : !Compute eta for approximately optimized summations:
    3050              :  direct=rmet(1,1)+rmet(1,2)+rmet(1,3)+rmet(2,1)+&
    3051            3 : & rmet(2,2)+rmet(2,3)+rmet(3,1)+rmet(3,2)+rmet(3,3)
    3052              :  recip=gmet(1,1)+gmet(1,2)+gmet(1,3)+gmet(2,1)+&
    3053            3 : & gmet(2,2)+gmet(2,3)+gmet(3,1)+gmet(3,2)+gmet(3,3)
    3054            3 :  eta=pi*(dble(nng)/dble(nnr))*sqrt(1.69_dp*recip/direct)
    3055              : ! eta=1.0_dp
    3056              : 
    3057              : !Test Ewald s summation
    3058              : !eta=1.2_dp*eta
    3059              : 
    3060              : !Sum terms over g space:
    3061            3 :  fac=pi**2.0_dp/eta
    3062            3 :  fac2=2.0_dp*fac
    3063            3 :  fac8=4.0_dp*fac2
    3064            3 :  fac2sqr=fac2*fac2
    3065           21 :  ABI_MALLOC(work,(2,3,natom,3,natom,3,3))
    3066         3495 :  work(:,:,:,:,:,:,:)=zero
    3067              :  ng=0
    3068              :  do
    3069           18 :    ng=ng+1
    3070           18 :    newg=0
    3071              : 
    3072          162 :    do ig3=-ng,ng
    3073         1524 :      do ig2=-ng,ng
    3074        15762 :        do ig1=-ng,ng
    3075              : 
    3076              : !        Exclude shells previously summed over
    3077              :          if(abs(ig1)==ng .or. abs(ig2)==ng .or. abs(ig3)==ng&
    3078        15618 : &         .or. ng==1 ) then
    3079              : 
    3080         6591 :            gpq(1)=dble(ig1)+qphon(1)
    3081         6591 :            gpq(2)=dble(ig2)+qphon(2)
    3082         6591 :            gpq(3)=dble(ig3)+qphon(3)
    3083         6591 :            gdot12=gmet(2,1)*gpq(1)*gpq(2)
    3084         6591 :            gdot13=gmet(3,1)*gpq(1)*gpq(3)
    3085         6591 :            gdot23=gmet(3,2)*gpq(2)*gpq(3)
    3086         6591 :            dot1=gmet(1,1)*gpq(1)**2+gdot12+gdot13
    3087         6591 :            dot2=gmet(2,2)*gpq(2)**2+gdot12+gdot23
    3088         6591 :            dot3=gmet(3,3)*gpq(3)**2+gdot13+gdot23
    3089         6591 :            gsq=dot1+dot2+dot3
    3090         6591 :            gsqsq=gsq*gsq
    3091              : !          Skip q=0:
    3092         6591 :            if (gsq<1.0d-20) then
    3093              : 
    3094              : !            At second order in q there is a nonvanishing G=0 contribution in the longwave limit
    3095            3 :              if (sumg0==1) then
    3096            9 :                do ia0=1,my_natom
    3097            6 :                  ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3098           18 :                  do ib=1,ia
    3099           42 :                    do iq2=1,3
    3100          117 :                      do iq1=1,3
    3101          351 :                        do mu=1,3
    3102          243 :                          delag=zero; if(iq1==mu) delag=one
    3103          243 :                          delad=zero; if(iq2==mu) delad=one
    3104          810 :                          do nu=1,mu
    3105          486 :                            delbg=zero; if(iq1==nu) delbg=one
    3106          486 :                            delbd=zero; if(iq2==nu) delbd=one
    3107          486 :                            g0term=-fac*(delad*delbg+delbd*delag)
    3108          729 :                            work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+g0term
    3109              :                          end do
    3110              :                        end do
    3111              :                      end do
    3112              :                    end do
    3113              :                  end do
    3114              :                end do
    3115              :              end if
    3116              : 
    3117              :            else
    3118         6588 :              arg=fac*gsq
    3119              : !            Larger arg gives 0 contribution:
    3120         6588 :              if (arg <= 80._dp) then
    3121         1230 :                newg=1
    3122         1230 :                term=exp(-arg)/gsq
    3123         3690 :                do ia0=1,my_natom
    3124         2460 :                  ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3125         2460 :                  arga=two_pi*(gpq(1)*xred(1,ia)+gpq(2)*xred(2,ia)+gpq(3)*xred(3,ia))
    3126         7380 :                  do ib=1,ia
    3127         3690 :                    argb=two_pi*(gpq(1)*xred(1,ib)+gpq(2)*xred(2,ib)+gpq(3)*xred(3,ib))
    3128         3690 :                    arg=arga-argb
    3129         3690 :                    c1r=cos(arg)*term
    3130         3690 :                    c1i=sin(arg)*term
    3131              : 
    3132        17220 :                    do iq2=1,3
    3133        11070 :                      gpqdq2=gmet(iq2,1)*gpq(1)+gmet(iq2,2)*gpq(2)+gmet(iq2,3)*gpq(3)
    3134        47970 :                      do iq1=1,3
    3135        33210 :                        gpqdq1=gmet(iq1,1)*gpq(1)+gmet(iq1,2)*gpq(2)+gmet(iq1,3)*gpq(3)
    3136       143910 :                        do mu=1,3
    3137        99630 :                          delag=zero; if(iq1==mu) delag=one
    3138        99630 :                          delad=zero; if(iq2==mu) delad=one
    3139       332100 :                          do nu=1,mu
    3140       199260 :                            delbg=zero; if(iq1==nu) delbg=one
    3141       199260 :                            delbd=zero; if(iq2==nu) delbd=one
    3142              : 
    3143       199260 :                            term1=gpqdq2*(delag*gpq(nu)+delbg*gpq(mu))
    3144       199260 :                            term1=term1+gpqdq1*(delad*gpq(nu)+delbd*gpq(mu))
    3145       199260 :                            term1=term1+gpq(mu)*gpq(nu)*gmet(iq1,iq2)
    3146       199260 :                            term1=-term1*(fac2+2.0_dp/gsq)
    3147              : 
    3148       199260 :                            term2=delag*delbd + delbg*delad
    3149              : 
    3150       199260 :                            term3=gpqdq1*gpqdq2*gpq(mu)*gpq(nu)
    3151       199260 :                            term3=term3*(fac8/gsq + fac2sqr + 8.0_dp/gsqsq)
    3152              : 
    3153       199260 :                            gterms=term1+term2+term3
    3154       199260 :                            work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+gterms*c1r
    3155       298890 :                            work(im,mu,ia,nu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)+gterms*c1i
    3156              :                          end do
    3157              :                        end do
    3158              :                      end do
    3159              :                    end do
    3160              :                  end do
    3161              :                end do
    3162              :              end if
    3163              : !            Endif g/=0 :
    3164              :            end if
    3165              :          end if
    3166              : !        End triple loop over G s:
    3167              :        end do
    3168              :      end do
    3169              :    end do
    3170              : 
    3171              : !  Check if new shell must be calculated
    3172           18 :    if (newg==0) exit
    3173              :  end do !  End the loop on ng (new shells). Note that there is one exit from this loop.
    3174              : 
    3175              : !End G summation by accounting for some common factors.
    3176              : !(for the charges:see end of routine)
    3177            3 :  norm1=4.0_dp*pi/ucvol
    3178            9 :  do ia0=1,my_natom
    3179            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3180           18 :    do ib=1,ia
    3181           42 :      do iq2=1,3
    3182          117 :        do iq1=1,3
    3183          351 :          do mu=1,3
    3184          810 :            do nu=1,mu
    3185         1701 :              work(:,mu,ia,nu,ib,iq1,iq2)=work(:,mu,ia,nu,ib,iq1,iq2)*norm1
    3186              :            end do
    3187              :          end do
    3188              :        end do
    3189              :      end do
    3190              :    end do
    3191              :  end do
    3192              : 
    3193              : !Do sums over real space:
    3194            3 :  reta=sqrt(eta)
    3195            3 :  reta3m=eta*reta
    3196            3 :  fac=4._dp/3.0_dp/sqrt(pi)
    3197            3 :  nr=0
    3198              :  do
    3199           18 :    nr=nr+1
    3200           18 :    newr=0
    3201              : 
    3202          162 :    do ir3=-nr,nr
    3203         1524 :      do ir2=-nr,nr
    3204        15762 :        do ir1=-nr,nr
    3205        15618 :          if( abs(ir3)==nr .or. abs(ir2)==nr .or. abs(ir1)==nr .or. nr==1 )then
    3206              : 
    3207         6591 :            arg=two_pi*(qphon(1)*ir1+qphon(2)*ir2+qphon(3)*ir3)
    3208         6591 :            c1r=cos(arg)*reta3m
    3209         6591 :            c1i=sin(arg)*reta3m
    3210        19773 :            do ia0=1,my_natom
    3211        13182 :              ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3212        47211 :              do ib=1,ia
    3213        19773 :                r1=dble(ir1)+xred(1,ib)-xred(1,ia)
    3214        19773 :                r2=dble(ir2)+xred(2,ib)-xred(2,ia)
    3215        19773 :                r3=dble(ir3)+xred(3,ib)-xred(3,ia)
    3216        79092 :                dakk(:)=two_pi*(/r1,r2,r3/)
    3217        19773 :                rdot12=rmet(2,1)*r1*r2
    3218        19773 :                rdot13=rmet(3,1)*r1*r3
    3219        19773 :                rdot23=rmet(3,2)*r2*r3
    3220        19773 :                dotr1=rmet(1,1)*r1**2+rdot12+rdot13
    3221        19773 :                dotr2=rmet(2,2)*r2**2+rdot12+rdot23
    3222        19773 :                dotr3=rmet(3,3)*r3**2+rdot13+rdot23
    3223        19773 :                rsq=dotr1+dotr2+dotr3
    3224        19773 :                rmagn=sqrt(rsq)
    3225              : !              Avoid zero denominators in term :
    3226        32955 :                if (rmagn>=1.0d-12) then
    3227        19767 :                  arg=reta*rmagn
    3228        19767 :                  term=zero
    3229        19767 :                  if (arg<8.0_dp) then
    3230              : !                  Note: erfc(8) is about 1.1e-29,
    3231              : !                  so don t bother with larger arg.
    3232              : !                  Also: exp(-64) is about 1.6e-28,
    3233              : !                  so don t bother with larger arg**2 in exp.
    3234         4200 :                    newr=1
    3235         4200 :                    derfc_arg = abi_derfc(arg)
    3236         4200 :                    term=derfc_arg/arg**3
    3237         4200 :                    term1=2.0_dp/sqrt(pi)*exp(-arg**2)/arg**2
    3238         4200 :                    term2=-(term+term1)
    3239         4200 :                    term3=(3*term+term1*(3.0_dp+2.0_dp*arg**2))/rsq
    3240         4200 :                    rq(1)=rmet(1,1)*r1+rmet(1,2)*r2+rmet(1,3)*r3
    3241         4200 :                    rq(2)=rmet(2,1)*r1+rmet(2,2)*r2+rmet(2,3)*r3
    3242         4200 :                    rq(3)=rmet(3,1)*r1+rmet(3,2)*r2+rmet(3,3)*r3
    3243        16800 :                    do iq2=1,3
    3244        54600 :                      do iq1=1,3
    3245       163800 :                        do mu=1,3
    3246              : !                         do nu=1,3
    3247       378000 :                          do nu=1,mu
    3248              :                            work(re,mu,ia,nu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)+&
    3249       226800 : &                           c1r*dakk(iq1)*dakk(iq2)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    3250              :                            work(im,mu,ia,nu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)+&
    3251       340200 : &                           c1i*dakk(iq1)*dakk(iq2)*(rq(mu)*rq(nu)*term3+rmet(mu,nu)*term2)
    3252              :                          end do
    3253              :                        end do
    3254              :                      end do
    3255              :                    end do
    3256              :                  end if
    3257              :                else
    3258            6 :                  if (ia/=ib)then
    3259              :                    write(message,'(a,a,a,a,a,i5,a,i5,a)')&
    3260            0 : &                   'The distance between two atoms vanishes.',ch10,&
    3261            0 : &                   'This is not allowed.',ch10,&
    3262            0 : &                   'Action: check the input for the atoms number',ia,' and',ib,'.'
    3263            0 :                    ABI_ERROR(message)
    3264              :                  end if
    3265              :                end if
    3266              : 
    3267              :              end do ! End loop over ib:
    3268              :            end do ! End loop over ia:
    3269              :          end if
    3270              :        end do ! End triple loop over real space points:
    3271              :      end do
    3272              :    end do
    3273              : 
    3274              : !  Check if new shell must be calculated
    3275           18 :    if(newr==0) exit
    3276              :  end do !  End loop on nr (new shells). Note that there is an exit within the loop
    3277              : 
    3278              : !Take account of the charges
    3279              : !write(std_out,*)' '
    3280            9 :  do ia0=1,my_natom
    3281            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3282           18 :    do ib=1,ia
    3283           42 :      do iq2=1,3
    3284          117 :        do iq1=1,3
    3285          351 :          do mu=1,3
    3286          810 :            do nu=1,mu
    3287         1701 :              do ii=1,2
    3288              :                work(ii,mu,ia,nu,ib,iq1,iq2)=work(ii,mu,ia,nu,ib,iq1,iq2)*&
    3289         1458 : &               zion(typat(ia))*zion(typat(ib))
    3290              :              end do
    3291              :            end do
    3292              :          end do
    3293              :        end do
    3294              :      end do
    3295              :    end do
    3296              :  end do
    3297              : 
    3298              : !Symmetrize with respect to the directions
    3299            9 :  do ia0=1,my_natom
    3300            6 :    ia=ia0;if(paral_atom)ia=my_atmtab(ia0)
    3301           18 :    do ib=1,ia
    3302           42 :      do iq2=1,3
    3303          117 :        do iq1=1,3
    3304          351 :          do mu=1,3
    3305          810 :            do nu=1,mu
    3306          486 :              work(re,nu,ia,mu,ib,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)
    3307          729 :              work(im,nu,ia,mu,ib,iq1,iq2)=work(im,mu,ia,nu,ib,iq1,iq2)
    3308              :            end do
    3309              :          end do
    3310              :        end do
    3311              :      end do
    3312              :    end do
    3313              :  end do
    3314              : 
    3315              : !In case of parallelism over atoms: communicate
    3316            3 :  if (paral_atom) then
    3317            0 :    call timab(48,1,tsec)
    3318            0 :    call xmpi_sum(work,my_comm_atom,ierr)
    3319            0 :    call timab(48,2,tsec)
    3320              :  end if
    3321              : 
    3322              : !Fill the upper part of the matrix, with the hermitian conjugate
    3323            9 :  do ia=1,natom
    3324           18 :    do ib=1,ia
    3325           42 :      do iq2=1,3
    3326          117 :        do iq1=1,3
    3327          351 :          do nu=1,3
    3328         1053 :            do mu=1,3
    3329          729 :              work(re,mu,ib,nu,ia,iq1,iq2)=work(re,mu,ia,nu,ib,iq1,iq2)
    3330          972 :              work(im,mu,ib,nu,ia,iq1,iq2)=-work(im,mu,ia,nu,ib,iq1,iq2)
    3331              :            end do
    3332              :          end do
    3333              :        end do
    3334              :      end do
    3335              :    end do
    3336              :  end do
    3337              : 
    3338              : !Perform the summation over the second atomic sublattice
    3339         1740 :  dyewdqdq(:,:,:,:,:,:)=zero
    3340            9 :  do ia=1,natom
    3341           27 :    do iq2=1,3
    3342           78 :      do iq1=1,3
    3343          234 :        do nu=1,3
    3344          702 :          do mu=1,3
    3345         1620 :            do ib=1,natom
    3346              :              dyewdqdq(re,mu,ia,nu,iq1,iq2)=dyewdqdq(re,mu,ia,nu,iq1,iq2) + &
    3347          972 :            & work(re,mu,ia,nu,ib,iq1,iq2)
    3348              :              dyewdqdq(im,mu,ia,nu,iq1,iq2)=dyewdqdq(im,mu,ia,nu,iq1,iq2) + &
    3349         1458 :            & work(im,mu,ia,nu,ib,iq1,iq2)
    3350              :            end do
    3351              :          end do
    3352              :        end do
    3353              :      end do
    3354              :    end do
    3355              :  end do
    3356            3 :  ABI_FREE(work)
    3357              : 
    3358              : !Destroy atom table used for parallelism
    3359            3 :  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
    3360              : 
    3361            3 : end subroutine dfpt_ewalddqdq
    3362              : !!***
    3363              : 
    3364              : end module m_dfpt_elt
    3365              : !!***
        

Generated by: LCOV version 2.3-1