LCOV - code coverage report
Current view: top level - src/56_xc - m_mkcore.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 84.7 % 515 436
Test Date: 2026-09-19 17:42:43 Functions: 85.7 % 7 6

            Line data    Source code
       1              : !!****m* ABINIT/m_mkcore
       2              : !! NAME
       3              : !!  m_mkcore
       4              : !!
       5              : !! FUNCTION
       6              : !!  Routines related to non-linear core correction.
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, TRangel, MT)
      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_mkcore
      23              : 
      24              :  use defs_basis
      25              :  use m_abicore
      26              :  use m_xmpi
      27              :  use m_errors
      28              :  use m_linalg_interfaces
      29              : 
      30              :  use defs_abitypes, only : mpi_type
      31              :  use m_geometry,    only : strconv
      32              :  use m_time,        only : timab
      33              :  use m_mpinfo,      only : ptabs_fourdp
      34              :  use m_sort,        only : sort_dp
      35              :  use m_pawrad,      only : pawrad_type, pawrad_init, pawrad_free
      36              :  use m_pawtab,      only : pawtab_type
      37              :  use m_paw_numeric, only : paw_splint
      38              : 
      39              :  implicit none
      40              : 
      41              :  private
      42              : !!***
      43              : 
      44              :  public :: mkcore
      45              :  public :: mkcore_alt
      46              :  public :: dfpt_mkcore       ! Derivative of the core electron density with respect to one specific atom displacement
      47              : !!***
      48              : 
      49              : contains
      50              : !!***
      51              : 
      52              : !!****f* ABINIT/mkcore
      53              : !! NAME
      54              : !! mkcore
      55              : !!
      56              : !! FUNCTION
      57              : !! Optionally compute:
      58              : !!  (1) pseudo core electron density throughout unit cell
      59              : !!  (2) pseudo-core contribution to forces
      60              : !!  (3) pseudo-core contribution to stress tensor
      61              : !!  (4) pseudo-core contrib. to frozen-wf part the dynamical matrix (part 2)
      62              : !!
      63              : !! INPUTS
      64              : !!  natom=number of atoms in cell.
      65              : !!  nfft=(effective) number of FFT grid points (for this processor)
      66              : !!  nspden=number of spin-density components
      67              : !!  ntypat=number of types of atoms in cell.
      68              : !!  n1,n2,n3=fft grid dimensions.
      69              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
      70              : !!  option: 1 for computing xccc3d (core charge density),
      71              : !!   2 for computing core charge contribution to $d(E_{xc})/d(tau)$,
      72              : !!   3 for computing core charge contribution to stress tensor corstr,
      73              : !!   4 for contribution to frozen-wavefunction part of dynamical matrix
      74              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
      75              : !!  typat(natom)=integer type for each atom in cell
      76              : !!  ucvol=unit cell volume (bohr**3).
      77              : !!  vxc(nfft,nspden)=exchange-correlation potential (hartree) in real
      78              : !!   space--only used when option=2,3, or 4,  else ignored
      79              : !!  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
      80              : !!  xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
      81              : !!   for each type of atom, from psp
      82              : !!  xred(3,natom)=reduced coordinates for atoms in unit cell
      83              : !!
      84              : !! OUTPUT
      85              : !!  corstr(6)=core charge contribution to stress tensor, only if option=3
      86              : !!  dyfrx2(3,3,natom)=non-linear xc core correction part of the
      87              : !!    frozen-wavefunction part of the dynamical matrix, only for option=4
      88              : !!  grxc(3,natom)=d(Exc)/d(xred), hartree (only computed when option=2, else
      89              : !!   ignored)
      90              : !!
      91              : !! SIDE EFFECTS
      92              : !!  xccc3d(n1*n2*n3)=3D core electron density for XC core correction, bohr^-3
      93              : !!   (computed and returned when option=1, needed as input when option=3)
      94              : !!
      95              : !! NOTES
      96              : !! Note that this routine is tightly connected to the dfpt_mkcore.f routine
      97              : !!
      98              : !! SOURCE
      99              : 
     100         9509 : subroutine mkcore(corstr,dyfrx2,grxc,mpi_enreg,natom,nfft,nspden,ntypat,n1,n1xccc,&
     101         9509 : & n2,n3,option,rprimd,typat,ucvol,vxc,xcccrc,xccc1d,xccc3d,xred)
     102              : 
     103              : !Arguments ------------------------------------
     104              : !scalars
     105              :  integer,intent(in) :: n1,n1xccc,n2,n3,natom,nfft,nspden,ntypat,option
     106              :  real(dp),intent(in) :: ucvol
     107              :  type(mpi_type),intent(in) :: mpi_enreg
     108              : !arrays
     109              :  integer,intent(in) :: typat(natom)
     110              :  real(dp),intent(in) :: rprimd(3,3),vxc(nfft,nspden),xccc1d(n1xccc,6,ntypat)
     111              :  real(dp),intent(in) :: xcccrc(ntypat),xred(3,natom)
     112              :  real(dp),intent(inout) :: xccc3d(nfft)
     113              :  real(dp),intent(out) :: corstr(6),dyfrx2(3,3,natom)
     114              :  real(dp),intent(inout) :: grxc(3,natom)
     115              : 
     116              : !Local variables-------------------------------
     117              : !scalars
     118              :  integer :: i1,i2,i3,iatom,ier,ifft,ishift,ishift1,ishift2
     119              :  integer :: ishift3,itypat,ixp,jj,me_fft,mrange,mu,nfftot,nu
     120              :  real(dp) :: dd,delta,delta2div6,deltam1,diff,difmag,difmag2
     121              :  real(dp) :: difmag2_fact,difmag2_part,fact,func,grxc1,grxc2,grxc3,range,range2
     122              :  real(dp) :: rangem1,rdiff1,rdiff2,rdiff3,strdia,t1,t2,t3,term,term1,term2
     123              :  character(len=500) :: message
     124              : !arrays
     125              :  integer :: igrid(3),irange(3),ngfft(3)
     126         9509 :  integer, contiguous, pointer :: fftn2_distrib(:),ffti2_local(:)
     127         9509 :  integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
     128         9509 :  integer,allocatable :: ii(:,:)
     129              :  real(dp) :: yy,aa,bb,cc
     130              :  real(dp) :: corfra(3,3),lencp(3),rmet(3,3),scale(3),tau(3),tsec(2),tt(3)
     131         9509 :  real(dp),allocatable :: rrdiff(:,:),work(:,:,:)
     132              : !************************************************************************
     133              : 
     134         9509 :  call timab(12,1,tsec)
     135              : 
     136              : !Make sure option is acceptable
     137         9509 :  if (option<0.or.option>4) then
     138              :    write(message, '(a,i12,a,a,a)' )&
     139            0 :     'option=',option,' is not allowed.',ch10,&
     140            0 :     'Must be 1, 2, 3 or 4.'
     141            0 :    ABI_BUG(message)
     142              :  end if
     143              : 
     144              : !Zero out only the appropriate array according to option:
     145              : !others are dummies with no storage
     146              : 
     147         9509 :  if (option==1) then
     148              : !  Zero out array to permit accumulation over atom types below:
     149     49390449 :    xccc3d(:)=zero
     150         6148 :  else if (option==2) then
     151              : !  Zero out gradient of Exc array
     152        63261 :    grxc(:,:)=zero
     153         2055 :  else if (option==3) then
     154              : !  Zero out locally defined stress array
     155         9509 :    corfra(:,:)=zero
     156         9509 :    strdia=zero
     157          246 :  else if (option==4) then
     158              : !  Zero out fr-wf part of the dynamical matrix
     159         7175 :    dyfrx2(:,:,:)=zero
     160              :  else
     161            0 :    ABI_BUG(" Can't be here! (bad option)")
     162              :  end if
     163              : 
     164              : !Compute lengths of cross products for pairs of primitive
     165              : !translation vectors (used in setting index search range below)
     166              :  lencp(1)=cross_mkcore(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
     167         9509 : & rprimd(1,3),rprimd(2,3),rprimd(3,3))
     168              :  lencp(2)=cross_mkcore(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
     169         9509 : & rprimd(1,1),rprimd(2,1),rprimd(3,1))
     170              :  lencp(3)=cross_mkcore(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
     171         9509 : & rprimd(1,2),rprimd(2,2),rprimd(3,2))
     172              : 
     173              : !Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
     174              : !(recall ucvol=R1.(R2xR3))
     175        38036 :  scale(:)=ucvol/lencp(:)
     176              : 
     177              : !Compute metric tensor in real space rmet
     178        38036 :  do nu=1,3
     179       123617 :    rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+rprimd(3,:)*rprimd(3,nu)
     180              :  end do
     181              : 
     182         9509 :  ngfft(1)=n1
     183         9509 :  ngfft(2)=n2
     184         9509 :  ngfft(3)=n3
     185         9509 :  nfftot=n1*n2*n3
     186         9509 :  me_fft = mpi_enreg%me_fft
     187              : 
     188              :  ! Get the distrib associated with this fft_grid
     189         9509 :  call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
     190              : 
     191         9509 :  delta=one/(n1xccc-1)
     192         9509 :  deltam1=n1xccc-1
     193         9509 :  delta2div6=delta**2/6.0d0
     194              : 
     195         9509 :  if (option>=2) then
     196        30740 :    ABI_MALLOC(work,(n1,n2,n3))
     197              : !  For spin-polarization, replace vxc by (1/2)*(vxc(up)+vxc(down))
     198              : !  For non-collinear magnetism, replace vxc by (1/2)*(vxc^{11}+vxc^{22})
     199         6148 :    if (nspden>=2) then
     200              :      ifft=1
     201        24804 :      do i3=1,n3
     202        24804 :        if(me_fft==fftn3_distrib(i3)) then
     203       573400 :          do i2=1,n2
     204     14211550 :            do i1=1,n1
     205     13638150 :              work(i1,i2,i3)=half*(vxc(ifft,1)+vxc(ifft,2))
     206     14187781 :              ifft=ifft+1
     207              :            end do
     208              :          end do
     209              :        end if
     210              :      end do
     211              :    else
     212              :      ifft=1
     213       130122 :      do i3=1,n3
     214       130122 :        if(me_fft==fftn3_distrib(i3)) then
     215      3440853 :          do i2=1,n2
     216    126830547 :            do i1=1,n1
     217    123389694 :              work(i1,i2,i3)=vxc(ifft,1)
     218    126706338 :              ifft=ifft+1
     219              :            end do
     220              :          end do
     221              :        end if
     222              :      end do
     223              : !    call DCOPY(nfft,vxc,1,work,1)
     224              :    end if
     225              :  end if
     226              : 
     227              : !Loop over atoms in unit cell
     228        43644 :  do iatom=1,natom
     229              : 
     230        34135 :    if(option==2)then
     231        14792 :      grxc1=zero
     232        14792 :      grxc2=zero
     233        14792 :      grxc3=zero
     234              :    end if
     235              : 
     236              : !  Set search range (density cuts off perfectly beyond range)
     237        34135 :    itypat=typat(iatom)
     238        34135 :    range=xcccrc(itypat)
     239              : 
     240              : !  Skip loop if this atom has no core charge
     241        34135 :    if (abs(range)<1.d-16) cycle
     242              : 
     243        31789 :    range2=range**2
     244        31789 :    rangem1=one/range
     245              : 
     246              : !  Consider each component in turn : compute range
     247       127156 :    do mu=1,3
     248              : 
     249              : !    Convert reduced coord of given atom to [0,1)
     250        95367 :      tau(mu)=mod(xred(mu,iatom)+one-aint(xred(mu,iatom)),one)
     251              : 
     252              : !    Use tau to find nearest grid point along R(mu)
     253              : !    (igrid=0 is the origin; shift by 1 to agree with usual index)
     254        95367 :      igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
     255              : 
     256              : !    Use range to compute an index range along R(mu)
     257              : !    (add 1 to make sure it covers full range)
     258       127156 :      irange(mu)=1+nint((range/scale(mu))*dble(ngfft(mu)))
     259              : 
     260              :    end do
     261              : 
     262              : !  Allocate arrays that depends on the range
     263       127156 :    mrange=maxval(irange(1:3))
     264       127156 :    ABI_MALLOC(ii,(2*mrange+1,3))
     265        95367 :    ABI_MALLOC(rrdiff,(2*mrange+1,3))
     266              : 
     267              : !  Set up counters that explore the relevant range
     268              : !  of points around the atom
     269       127156 :    do mu=1,3
     270        95367 :      ishift=0
     271      2919937 :      do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
     272      2792781 :        ishift=ishift+1
     273      2792781 :        ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
     274      2888148 :        rrdiff(ishift,mu)=dble(ixp)/dble(ngfft(mu))-tau(mu)
     275              :      end do
     276              :    end do
     277              : 
     278              : !  Conduct triple loop over restricted range of grid points for iatom
     279       953024 :    do ishift3=1,1+2*irange(3)
     280              : !    map back to [1,ngfft(3)] for usual fortran index in unit cell
     281       921235 :      i3=ii(ishift3,3)
     282       921235 :      if(fftn3_distrib(i3)/=mpi_enreg%me_fft) cycle
     283              : !    find vector from atom location to grid point (reduced)
     284       912745 :      rdiff3=rrdiff(ishift3,3)
     285              : 
     286     32795547 :      do ishift2=1,1+2*irange(2)
     287     31851013 :        i2=ii(ishift2,2)
     288     31851013 :        rdiff2=rrdiff(ishift2,2)
     289              : !      Prepare the computation of difmag2
     290              :        difmag2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2&
     291     31851013 : &       +2.0d0*rmet(3,2)*rdiff3*rdiff2
     292     31851013 :        difmag2_fact=2.0d0*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
     293              : 
     294   1402719161 :        do ishift1=1,1+2*irange(1)
     295   1369946913 :          rdiff1=rrdiff(ishift1,1)
     296              : 
     297              : !        Compute (rgrid-tau-Rprim)**2
     298   1369946913 :          difmag2= difmag2_part+rdiff1*(difmag2_fact+rmet(1,1)*rdiff1)
     299              : 
     300              : !        Only accept contribution inside defined range
     301   1401797926 :          if (difmag2<range2-tol12) then
     302              : 
     303              : !          Prepare computation of core charge function and derivative,
     304              : !          using splines
     305    498513981 :            i1=ii(ishift1,1)
     306    498513981 :            difmag=sqrt(difmag2)
     307    498513981 :            yy=difmag*rangem1
     308              : 
     309              : !          Compute index of yy over 1 to n1xccc scale
     310    498513981 :            jj=1+int(yy*(n1xccc-1))
     311    498513981 :            diff=yy-(jj-1)*delta
     312              : 
     313              : !          Will evaluate spline fit (p. 86 Numerical Recipes, Press et al;
     314              : !          NOTE error in book for sign of "aa" term in derivative;
     315              : !          also see splfit routine).
     316    498513981 :            bb = diff*deltam1
     317    498513981 :            aa = one-bb
     318    498513981 :            cc = aa*(aa**2-one)*delta2div6
     319    498513981 :            dd = bb*(bb**2-one)*delta2div6
     320              : 
     321              : 
     322              : !          Test first for option 2, the most frequently used
     323    498513981 :            if (option==2) then
     324              : 
     325              : !            Accumulate contributions to Exc gradients
     326              : 
     327    167786929 :              if (difmag>1.0d-10) then
     328              : 
     329              : !              Evaluate spline fit of 1st der of core charge density
     330              : !              from xccc1d(:,2,:) and (:,4,:)
     331              :                func=aa*xccc1d(jj,2,itypat)+bb*xccc1d(jj+1,2,itypat) +&
     332    167784009 : &               cc*xccc1d(jj,4,itypat)+dd*xccc1d(jj+1,4,itypat)
     333    167784009 :                term=work(i1,i2,i3)*func/difmag
     334    167784009 :                grxc1=grxc1+rdiff1*term
     335    167784009 :                grxc2=grxc2+rdiff2*term
     336    167784009 :                grxc3=grxc3+rdiff3*term
     337              :              end if
     338              : 
     339    330727052 :            else if (option==1) then
     340              : 
     341              : !            Evaluate spline fit of core charge density
     342              : !            from xccc1d(:,1,:) and (:,3,:)
     343              :              func=aa*xccc1d(jj,1,itypat)+bb*xccc1d(jj+1,1,itypat) +&
     344    216671601 : &             cc*xccc1d(jj,3,itypat)+dd*xccc1d(jj+1,3,itypat)
     345              : 
     346              : !            Accumulate contributions to core electron density
     347              : !            throughout unit cell
     348    216671601 :              ifft=i1+n1*(i2-1+n2*(ffti3_local(i3)-1))
     349    216671601 :              xccc3d(ifft)=xccc3d(ifft)+func
     350              : 
     351    114055451 :            else if (option==3) then
     352              : 
     353              : !            Accumulate contributions to stress tensor
     354              : !            in reduced coordinates
     355              : 
     356     92318265 :              if (difmag>1.0d-10) then
     357              : 
     358              : !              Evaluate spline fit of 1st der of core charge density
     359              : !              from xccc1d(:,2,:) and (:,4,:)
     360              :                func=aa*xccc1d(jj,2,itypat)+bb*xccc1d(jj+1,2,itypat) +&
     361     92316670 : &               cc*xccc1d(jj,4,itypat)+dd*xccc1d(jj+1,4,itypat)
     362     92316670 :                term=work(i1,i2,i3)*func*rangem1/difmag/dble(n1*n2*n3)
     363              : !              Write out the 6 symmetric components
     364     92316670 :                corfra(1,1)=corfra(1,1)+term*rdiff1**2
     365     92316670 :                corfra(2,2)=corfra(2,2)+term*rdiff2**2
     366     92316670 :                corfra(3,3)=corfra(3,3)+term*rdiff3**2
     367     92316670 :                corfra(3,2)=corfra(3,2)+term*rdiff3*rdiff2
     368     92316670 :                corfra(3,1)=corfra(3,1)+term*rdiff3*rdiff1
     369     92316670 :                corfra(2,1)=corfra(2,1)+term*rdiff2*rdiff1
     370              : !              (the above still needs to be transformed to cartesian coords)
     371              : 
     372              :              end if
     373              : 
     374              : !            Also compute a diagonal term
     375              : !            Evaluate spline fit of core charge density
     376              : !            from xccc1d(:,1,:) and (:,3,:)
     377              :              func=aa*xccc1d(jj,1,itypat)+bb*xccc1d(jj+1,1,itypat) +&
     378     92318265 : &             cc*xccc1d(jj,3,itypat)+dd*xccc1d(jj+1,3,itypat)
     379     92318265 :              strdia=strdia+work(i1,i2,i3)*func
     380              : 
     381     21737186 :            else if (option==4) then
     382              : 
     383              : !            Compute frozen-wf contribution to Dynamical matrix
     384              : 
     385     21737186 :              tt(1)=rmet(1,1)*rdiff1+rmet(1,2)*rdiff2+rmet(1,3)*rdiff3
     386     21737186 :              tt(2)=rmet(2,1)*rdiff1+rmet(2,2)*rdiff2+rmet(2,3)*rdiff3
     387     21737186 :              tt(3)=rmet(3,1)*rdiff1+rmet(3,2)*rdiff2+rmet(3,3)*rdiff3
     388              : 
     389     21737186 :              if (difmag>1.d-10) then
     390              : 
     391              : !              Accumulate contributions to dynamical matrix
     392     21736924 :                term=(ucvol/dble(nfftot))*work(i1,i2,i3)*rangem1/difmag
     393              : !              Evaluate spline fit of 1st der of core charge density
     394              : !              from xccc1d(:,2,:) and (:,4,:)
     395              :                func=aa*xccc1d(jj,2,itypat)+bb*xccc1d(jj+1,2,itypat) +&
     396     21736924 : &               cc*xccc1d(jj,4,itypat)+dd*xccc1d(jj+1,4,itypat)
     397     21736924 :                term1=term*func
     398              : !              Evaluate spline fit of 2nd der of core charge density
     399              : !              from xccc1d(:,3,:) and (:,5,:)
     400              :                func=aa*xccc1d(jj,3,itypat)+bb*xccc1d(jj+1,3,itypat) +&
     401     21736924 : &               cc*xccc1d(jj,5,itypat)+dd*xccc1d(jj+1,5,itypat)
     402     21736924 :                term2=term*func*rangem1/difmag
     403     86947696 :                do mu=1,3
     404    282580012 :                  do nu=1,3
     405              :                    dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)&
     406              : &                   +(term2-term1/difmag**2)*tt(mu)*tt(nu)&
     407    260843088 : &                   +term1*rmet(mu,nu)
     408              :                  end do
     409              :                end do
     410              : 
     411              :              else
     412              : 
     413              : !              There is a contribution from difmag=zero !
     414              : !              Evaluate spline fit of 2nd der of core charge density
     415              : !              from xccc1d(:,3,:) and (:,5,:)
     416              :                func=aa*xccc1d(jj,3,itypat)+bb*xccc1d(jj+1,3,itypat) +&
     417          262 : &               cc*xccc1d(jj,5,itypat)+dd*xccc1d(jj+1,5,itypat)
     418          262 :                term=(ucvol/dble(nfftot))*work(i1,i2,i3)*func*rangem1**2
     419         1048 :                do mu=1,3
     420         3406 :                  do nu=1,3
     421         3144 :                    dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)+term*rmet(mu,nu)
     422              :                  end do
     423              :                end do
     424              : 
     425              : !              End of condition not to be precisely on the point (difmag=zero)
     426              :              end if
     427              : 
     428              : !            If option is not 1, 2, 3, or 4.
     429              :            else
     430            0 :              ABI_BUG("Can't be here in mkcore")
     431              : !            End of choice of option
     432              :            end if
     433              : 
     434              :          end if ! End of condition on the range
     435              :        end do ! End loop on ishift1
     436              :      end do ! End loop on ishift2
     437              :    end do ! End loop on ishift3
     438              : 
     439        31789 :    ABI_FREE(ii)
     440        31789 :    ABI_FREE(rrdiff)
     441              : 
     442        41298 :    if(option==2)then
     443        13381 :      fact=-(ucvol/dble(nfftot))/range
     444        13381 :      grxc(1,iatom)=grxc1*fact
     445        13381 :      grxc(2,iatom)=grxc2*fact
     446        13381 :      grxc(3,iatom)=grxc3*fact
     447              :    end if
     448              : 
     449              :  end do !  End big loop on atoms
     450              : 
     451         9509 :  if (option==2) then
     452              : 
     453              : !  Apply rmet as needed to get reduced coordinate gradients
     454        18885 :    do iatom=1,natom
     455        14792 :      t1=grxc(1,iatom)
     456        14792 :      t2=grxc(2,iatom)
     457        14792 :      t3=grxc(3,iatom)
     458        63261 :      grxc(:,iatom)=rmet(:,1)*t1+rmet(:,2)*t2+rmet(:,3)*t3
     459              : 
     460              :    end do
     461              :  end if
     462              : 
     463         9509 :  if (option==3) then
     464              : 
     465              : !  Transform stress tensor from full storage mode to symmetric storage mode
     466         1809 :    corstr(1)=corfra(1,1)
     467         1809 :    corstr(2)=corfra(2,2)
     468         1809 :    corstr(3)=corfra(3,3)
     469         1809 :    corstr(4)=corfra(3,2)
     470         1809 :    corstr(5)=corfra(3,1)
     471         1809 :    corstr(6)=corfra(2,1)
     472              : 
     473              : !  Transform stress tensor from reduced coordinates to cartesian coordinates
     474         1809 :    call strconv(corstr,rprimd,corstr)
     475              : 
     476              : !  Compute diagonal contribution to stress tensor (need input xccc3d)
     477              : !  strdia = (1/N) Sum(r) [mu_xc_avg(r) * rho_core(r)]
     478         1809 :    ifft=0 ; strdia=zero
     479        41324 :    do i3=1,n3
     480        41324 :      if(me_fft==fftn3_distrib(i3)) then
     481       944282 :        do i2=1,n2
     482     27526212 :          do i1=1,n1
     483     26581930 :            ifft=ifft+1
     484     27487097 :            strdia=strdia+work(i1,i2,i3)*xccc3d(ifft)
     485              :          end do
     486              :        end do
     487              :      end if
     488              :    end do
     489         1809 :    strdia=strdia/dble(nfftot)
     490              : !  strdia=DDOT(nfft,work,1,xccc3d,1)/dble(nfftot)
     491              : 
     492              : !  Add diagonal term to stress tensor
     493         1809 :    corstr(1)=corstr(1)+strdia
     494         1809 :    corstr(2)=corstr(2)+strdia
     495         1809 :    corstr(3)=corstr(3)+strdia
     496              :  end if
     497              : 
     498         9509 :  if(option>=2)  then
     499         6148 :    ABI_FREE(work)
     500              :  end if
     501              : 
     502         9509 :  if(mpi_enreg%nproc_fft > 1) then
     503           72 :    call timab(539,1,tsec)
     504           72 :    if(option==2) then
     505           24 :      call xmpi_sum(grxc,mpi_enreg%comm_fft,ier)
     506              :    end if
     507           72 :    if(option==3) then
     508           24 :      call xmpi_sum(corstr,mpi_enreg%comm_fft,ier)
     509              :    end if
     510           72 :    if(option==4) then
     511            0 :      call xmpi_sum(dyfrx2,mpi_enreg%comm_fft,ier)
     512              :    end if
     513           72 :    call timab(539,2,tsec)
     514              :  end if
     515              : 
     516        19018 :  call timab(12,2,tsec)
     517              : 
     518              :  contains
     519              : !!***
     520              : 
     521              : !!****f* ABINIT/cross_mkcore
     522              : !! NAME
     523              : !!  cross_mkcore
     524              : !!
     525              : !! FUNCTION
     526              : !!  Define magnitude of cross product of two vectors
     527              : !!
     528              : !! SOURCE
     529              : 
     530        28527 :    function cross_mkcore(xx,yy,zz,aa,bb,cc)
     531              : 
     532              :    real(dp) :: cross_mkcore
     533              :    real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
     534              : ! *************************************************************************
     535        28527 :    cross_mkcore=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
     536        28527 :  end function cross_mkcore
     537              : 
     538              : end subroutine mkcore
     539              : !!***
     540              : 
     541              : !--------------------------------------------------------------------------------------
     542              : 
     543              : !!****f* ABINIT/mkcore_alt
     544              : !! NAME
     545              : !! mkcore_alt
     546              : !!
     547              : !! FUNCTION
     548              : !! Optionally compute:
     549              : !!  (1) pseudo core electron density throughout unit cell
     550              : !!  (2) pseudo-core contribution to forces
     551              : !!  (3) pseudo-core contribution to stress tensor
     552              : !!  (4) pseudo-core contrib. to frozen-wf part the dynamical matrix (part 2)
     553              : !! This routine is an alternative to mkcore, to be used for PAW and/or WVL.
     554              : !!
     555              : !! INPUTS
     556              : !!  atindx1(natom)=index table for atoms, inverse of atindx
     557              : !!  icoulomb= periodic treatment of Hartree potential: 0=periodic, 1=free BC, 2=surface BC
     558              : !!  mpi_enreg=information about MPI parallelization
     559              : !!  natom=number of atoms in cell.
     560              : !!  nfft=(effective) number of FFT grid points (for this processor)
     561              : !!  nspden=number of spin-density components
     562              : !!  ntypat=number of types of atoms in cell
     563              : !!  n1,n2,n3=fft grid dimensions.
     564              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
     565              : !!  option: 1 for computing core charge density
     566              : !!          2 for computing core charge contribution to forces
     567              : !!          3 for computing core charge contribution to stress tensor
     568              : !!          4 for computing contribution to frozen-wf part of dynamical matrix
     569              : !!  pawrad(ntypat*usepaw) <type(pawrad_type)>=paw radial mesh and related data
     570              : !!  pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
     571              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
     572              : !!  ucvol=unit cell volume (bohr**3)
     573              : !!  usepaw=flag for PAW method
     574              : !!  vxc(nfft,nspden)=exchange-correlation potential (hartree) in real space
     575              : !!  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
     576              : !!  xccc1d(n1xccc,6,ntypat)=1D core charge function and 5 derivatives for each atom type
     577              : !!  xred(3,natom)=reduced coordinates for atoms in unit cell
     578              : !!  [usekden]= --optional-- if TRUE, output the kinetic energy density instead of the density
     579              : !!
     580              : !! OUTPUT
     581              : !!  === if option==1 ===
     582              : !!  xccc3d(n1*n2*n3)=3D core electron density for XC core correction (bohr^-3)
     583              : !!  === if option==2 ===
     584              : !!  grxc(3,natom)=core charge contribution to forces
     585              : !!  === if option==3 ===
     586              : !!  corstr(6)=core charge contribution to stress tensor
     587              : !!  === if option==4 ===
     588              : !!  dyfrx2(3,3,natom)=non-linear xc core correction part of the
     589              : !!    frozen-wavefunction part of the dynamical matrix
     590              : !!
     591              : !! SIDE EFFECTS
     592              : !!  xccc3d(n1*n2*n3)=3D core electron (event. kinetic energy) density for XC core correction (bohr^-3)
     593              : !!   (computed and returned when option=1, needed as input when option=3)
     594              : !!
     595              : !! NOTES
     596              : !!  Based on mkcore.F90
     597              : !!
     598              : !! SOURCE
     599              : 
     600           92 : subroutine mkcore_alt(atindx1,corstr,dyfrx2,grxc,icoulomb,mpi_enreg,natom,nfft,nspden,&
     601           92 : &          nattyp,ntypat,n1,n1xccc,n2,n3,option,rprimd,ucvol,vxc,xcccrc,xccc1d,&
     602           46 : &          xccc3d,xred,pawrad,pawtab,usepaw,&
     603              : &          usekden) ! optional argument
     604              : 
     605              : !Arguments ------------------------------------
     606              : !scalars
     607              :  integer,intent(in) :: icoulomb,n1,n1xccc,n2,n3,natom,nfft,nspden,ntypat,option,usepaw
     608              :  logical,intent(in),optional :: usekden
     609              :  real(dp),intent(in) :: ucvol
     610              :  type(mpi_type),intent(in) :: mpi_enreg
     611              :  type(pawrad_type),intent(in) :: pawrad(:)
     612              :  type(pawtab_type),target,intent(in) :: pawtab(:)
     613              : !arrays
     614              :  integer,intent(in) :: atindx1(natom),nattyp(ntypat)
     615              :  real(dp),intent(in) :: rprimd(3,3),xccc1d(n1xccc,6,ntypat)
     616              :  real(dp),intent(in) :: xcccrc(ntypat),xred(3,natom)
     617              :  real(dp),intent(in),target :: vxc(nfft,nspden)
     618              :  real(dp),intent(out) :: corstr(6),grxc(3,natom),dyfrx2(3,3,natom)
     619              :  real(dp),intent(inout) :: xccc3d(nfft)
     620              : 
     621              : !Local variables-------------------------------
     622              : !scalars
     623              :  integer :: i1,i2,i3,iat,iatm,iatom,ier,ipts
     624              :  integer :: ishift,ishift1,ishift2,ishift3
     625              :  integer :: itypat,ixp,jj,jpts,me_fft,mrange,msz,mu
     626              :  integer :: nfftot,npts,npts12,nu
     627              :  logical :: letsgo,usekden_
     628              :  real(dp) :: aa,bb,cc,dd,delta,delta2div6,deltam1
     629              :  real(dp) :: diff,difmag,fact,range,range2
     630              :  real(dp) :: rangem1,rdiff1,rdiff2,rdiff3
     631              :  real(dp) :: rnorm2,rnorm2_fact,rnorm2_part
     632              :  real(dp) :: strdia,t1,t2,t3,term,term1,term2,yy
     633              :  character(len=1) :: geocode
     634              :  character(len=500) :: message
     635           46 :  type(pawrad_type) :: core_mesh
     636              : !arrays
     637              :  integer :: igrid(3),irange(3),ishiftmax(3),ngfft(3)
     638           46 :  integer,allocatable :: ii(:,:),iindex(:),indx1(:),indx2(:)
     639           46 :  integer, contiguous, pointer :: fftn2_distrib(:),ffti2_local(:)
     640           46 :  integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
     641              :  logical :: per(3)
     642              :  real(dp) :: corfra(3,3),corgr(3),lencp(3),rmet(3,3)
     643              :  real(dp) :: scale(3),tau(3),tsec(2),tt(3)
     644           46 :  real(dp),allocatable :: dtcore(:),d2tcore(:),rnorm(:)
     645           46 :  real(dp),allocatable :: rrdiff(:,:),tcore(:)
     646           46 :  real(dp),allocatable,target :: tcoretau(:,:) ! only needed in PAW case.
     647           46 :  real(dp), contiguous, pointer :: corespl(:,:),vxc_eff(:)
     648              : !************************************************************************
     649              : 
     650           46 :  call timab(12,1,tsec)
     651              : 
     652              : !Make sure options are acceptable
     653           46 :  if (option<0.or.option>4) then
     654              :    write(message, '(a,i12,a,a,a)' )&
     655            0 :     'option=',option,' is not allowed.',ch10,&
     656            0 :     'Must be 1, 2, 3 or 4.'
     657            0 :    ABI_BUG(message)
     658              :  end if
     659              : 
     660           46 :  usekden_=.false.;if (present(usekden)) usekden_=usekden
     661           46 :  if (usekden_) then
     662           46 :    message='usekden=1 mkcore_alt not yet in production. You have been warned! May not work with PAW or NC'
     663           46 :    ABI_WARNING(message)
     664              :  end if
     665              : 
     666              : 
     667              : !Zero out only the appropriate array according to option:
     668           46 :  if (option==1) then
     669      2003084 :    xccc3d(:)=zero
     670            6 :  else if (option==2) then
     671           23 :    grxc(:,:)=zero
     672            3 :  else if (option==3) then
     673           46 :    corfra(:,:)=zero
     674           46 :    strdia=zero
     675            0 :  else if (option==4) then
     676            0 :    dyfrx2(:,:,:)=zero
     677              :  end if
     678              : 
     679              : !Conditions for periodicity in the three directions
     680           46 :  geocode='P'
     681           46 :  if (icoulomb==1) geocode='F'
     682           46 :  if (icoulomb==2) geocode='S'
     683           46 :  per(1)=(geocode /= 'F')
     684           46 :  per(2)=(geocode == 'P')
     685           46 :  per(3)=(geocode /= 'F')
     686              : 
     687              : !Compute lengths of cross products for pairs of primitive
     688              : !translation vectors (used in setting index search range below)
     689              :  lencp(1)=cross_mkcore_alt(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
     690           46 : & rprimd(1,3),rprimd(2,3),rprimd(3,3))
     691              :  lencp(2)=cross_mkcore_alt(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
     692           46 : & rprimd(1,1),rprimd(2,1),rprimd(3,1))
     693              :  lencp(3)=cross_mkcore_alt(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
     694           46 : & rprimd(1,2),rprimd(2,2),rprimd(3,2))
     695              : 
     696              : !Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
     697              : !(recall ucvol=R1.(R2xR3))
     698          184 :  scale(:)=ucvol/lencp(:)
     699              : 
     700              : !Compute metric tensor in real space rmet
     701          184 :  do nu=1,3
     702          598 :    rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+rprimd(3,:)*rprimd(3,nu)
     703              :  end do
     704              : 
     705              : !Get the distrib associated with this fft_grid
     706           46 :  ngfft(1)=n1;ngfft(2)=n2;ngfft(3)=n3
     707           46 :  nfftot=n1*n2*n3 ; me_fft=mpi_enreg%me_fft
     708           46 :  call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
     709              : 
     710           46 :  delta=one/(n1xccc-1)
     711           46 :  deltam1=n1xccc-1
     712           46 :  delta2div6=delta**2/6.0_dp
     713              : 
     714           46 :  if (option>=2) then
     715              : !  For spin-polarization, replace vxc by (1/2)*(vxc(up)+vxc(down))
     716              : !  For non-collinear magnetism, replace vxc by (1/2)*(vxc^{11}+vxc^{22})
     717            6 :    if (nspden>=2) then
     718            0 :      ABI_MALLOC(vxc_eff,(nfft))
     719            0 :      do jj=1,nfft
     720            0 :        vxc_eff(jj)=half*(vxc(jj,1)+vxc(jj,2))
     721              :      end do
     722              :    else
     723            6 :      vxc_eff => vxc(1:nfft,1)
     724              :    end if
     725              :  end if
     726              : 
     727              : !Loop over atom types
     728           46 :  iatm=0
     729          100 :  do itypat=1,ntypat
     730              : 
     731              : !  Set search range (density cuts off perfectly beyond range)
     732           54 :    range=xcccrc(itypat);if (usepaw==1) range=pawtab(itypat)%rcore
     733              : 
     734              : !  Skip loop if this type has no core charge
     735           54 :    if (abs(range)<1.d-16) cycle
     736              : 
     737           15 :    range2=range**2 ; rangem1=one/range
     738              : 
     739              : 
     740              : !  PAW: select core density type and create mesh
     741           15 :    if (usepaw==1) then
     742            0 :      if (usekden_) then
     743            0 :        msz=pawtab(itypat)%coretau_mesh_size
     744            0 :        ABI_MALLOC(tcoretau,(msz,1))
     745            0 :        tcoretau(:,1)=pawtab(itypat)%coretau(:)
     746            0 :        corespl => tcoretau
     747              :      else
     748            0 :        msz=pawtab(itypat)%core_mesh_size
     749            0 :        corespl => pawtab(itypat)%tcoredens
     750              :      end if
     751              :      call pawrad_init(core_mesh,mesh_size=msz,&
     752              : &     mesh_type=pawrad(itypat)%mesh_type,&
     753            0 : &     rstep=pawrad(itypat)%rstep,lstep=pawrad(itypat)%lstep)
     754              :    end if
     755              : 
     756              : !  Loop over atoms of the type
     757           30 :    do iat=1,nattyp(itypat)
     758           15 :      iatm=iatm+1;iatom=atindx1(iatm)
     759              : 
     760           15 :      if(option==2) corgr(:)=zero
     761              : 
     762              : !    Consider each component in turn : compute range
     763           60 :      do mu=1,3
     764              : !      Convert reduced coord of given atom to [0,1)
     765           45 :        tau(mu)=mod(xred(mu,iatom)+one-aint(xred(mu,iatom)),one)
     766              : !      Use tau to find nearest grid point along R(mu)
     767              : !      (igrid=0 is the origin; shift by 1 to agree with usual index)
     768           45 :        igrid(mu)=nint(tau(mu)*real(ngfft(mu),dp))
     769              : !      Use range to compute an index range along R(mu)
     770              : !      (add 1 to make sure it covers full range)
     771           60 :        irange(mu)=1+nint((range/scale(mu))*real(ngfft(mu),dp))
     772              :      end do
     773              : 
     774              : !    Allocate arrays that depends on the range
     775           60 :      mrange=maxval(irange(1:3))
     776           60 :      ABI_MALLOC(ii,(2*mrange+1,3))
     777           45 :      ABI_MALLOC(rrdiff,(2*mrange+1,3))
     778              : 
     779              : !    Set up counters that explore the relevant range of points around the atom
     780           15 :      if (geocode=='P') then
     781              : !      Fully periodic version
     782           60 :        do mu=1,3
     783           45 :          ishift=0
     784         2790 :          do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
     785         2745 :            ishift=ishift+1
     786         2745 :            ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
     787         2790 :            rrdiff(ishift,mu)=real(ixp,dp)/real(ngfft(mu),dp)-tau(mu)
     788              :          end do
     789           60 :          ishiftmax(mu)=ishift
     790              :        end do
     791              :      else
     792              : !      Free or surface conditions
     793            0 :        do mu=1,3
     794            0 :          ishift=0
     795            0 :          do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
     796            0 :            call indpos_mkcore_alt(per(mu),ixp,ngfft(mu),jj,letsgo)
     797            0 :            if (letsgo) then
     798            0 :              ishift=ishift+1;ii(ishift,mu)=1+jj
     799            0 :              rrdiff(ishift,mu)=real(ixp,dp)/real(ngfft(mu),dp)-tau(mu)
     800              :            end if
     801              :          end do
     802            0 :          ishiftmax(mu)=ishift
     803              :        end do
     804              :      end if
     805           15 :      npts12=ishiftmax(1)*ishiftmax(2)
     806           45 :      ABI_MALLOC(indx1,(npts12))
     807           30 :      ABI_MALLOC(indx2,(npts12))
     808           30 :      ABI_MALLOC(iindex,(npts12))
     809           45 :      ABI_MALLOC(rnorm,(npts12))
     810           15 :      if (option==1.or.option==3) then
     811           20 :        ABI_MALLOC(tcore,(npts12))
     812              :      end if
     813           15 :      if (option>=2) then
     814           20 :        ABI_MALLOC(dtcore,(npts12))
     815              :      end if
     816           15 :      if (option==4) then
     817            0 :        ABI_MALLOC(d2tcore,(npts12))
     818              :      end if
     819              : 
     820              : !    Conduct loop over restricted range of grid points for iatom
     821          930 :      do ishift3=1,ishiftmax(3)
     822          915 :        i3=ii(ishift3,3)
     823          915 :        rdiff3=rrdiff(ishift3,3)
     824              : 
     825          915 :        if(fftn3_distrib(i3)/=mpi_enreg%me_fft) cycle
     826              : 
     827              : !      Select the vectors located around the current atom
     828              : !        TR: all of the following  could be done inside or
     829              : !        outside the loops (i2,i1,i3).
     830              : !        Outside: the memory consumption increases.
     831              : !        Inside: the time of calculation increases.
     832              : !        Here, I choose to do it here, somewhere in the middle.
     833          915 :        npts=0
     834        58698 :        do ishift2=1,ishiftmax(2)
     835        57783 :          i2=ii(ishift2,2) ; rdiff2=rrdiff(ishift2,2)
     836              :          rnorm2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2 &
     837        57783 : &         +2.0d0*rmet(3,2)*rdiff3*rdiff2
     838        57783 :          rnorm2_fact=2.0d0*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
     839      3832485 :          do ishift1=1,ishiftmax(1)
     840      3773787 :            i1=ii(ishift1,1) ; rdiff1=rrdiff(ishift1,1)
     841      3773787 :            rnorm2=rnorm2_part+rdiff1*(rnorm2_fact+rmet(1,1)*rdiff1)
     842              : !          Only accept contributions inside defined range
     843      3831570 :            if (rnorm2<range2-tol12) then
     844      1315515 :              npts=npts+1 ; iindex(npts)=npts
     845      1315515 :              indx1(npts)=ishift1;indx2(npts)=ishift2
     846      1315515 :              rnorm(npts)=sqrt(rnorm2)
     847              :            end if
     848              :          end do
     849              :        end do
     850          915 :        if (npts==0) cycle
     851          873 :        if (npts>npts12) then
     852            0 :          message='npts>npts12!'
     853            0 :          ABI_BUG(message)
     854              :        end if
     855              : 
     856              : !      Evaluate core density (and derivatives) on the set of selected points
     857          873 :        if (usepaw==1) then
     858              : !        PAW: use splint routine
     859            0 :          call sort_dp(npts,rnorm(1:npts),iindex(1:npts),tol16)
     860            0 :          if (option==1.or.option==3) then
     861              : !          Evaluate fit of core density
     862              :            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
     863              : &           corespl(:,1),corespl(:,3),&
     864            0 : &           npts,rnorm(1:npts),tcore(1:npts))
     865              :          end if
     866            0 :          if (option>=2) then
     867              : !          Evaluate fit of 1-der of core density
     868              :            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
     869              : &           corespl(:,2),corespl(:,4),&
     870            0 : &           npts,rnorm(1:npts),dtcore(1:npts))
     871              :          end if
     872            0 :          if (option==4) then
     873              : !          Evaluate fit of 2nd-der of core density
     874              :            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
     875              : &           corespl(:,3),corespl(:,5),&
     876            0 : &           npts,rnorm(1:npts),d2tcore(1:npts))
     877              :          end if
     878              :        else
     879              : !        Norm-conserving PP:
     880              : !          Evaluate spline fit with method from Numerical Recipes
     881              : !          (p. 86 Numerical Recipes, Press et al;
     882              : !          NOTE error in book for sign of "aa" term in derivative)
     883      1316388 :          do ipts=1,npts
     884      1315515 :            yy=rnorm(ipts)*rangem1
     885      1315515 :            jj=1+int(yy*(n1xccc-1))
     886      1315515 :            diff=yy-(jj-1)*delta
     887      1315515 :            bb = diff*deltam1 ; aa = one-bb
     888      1315515 :            cc = aa*(aa**2-one)*delta2div6
     889      1315515 :            dd = bb*(bb**2-one)*delta2div6
     890      1315515 :            if (option==1.or.option==3) then
     891              :              tcore(ipts)=aa*xccc1d(jj,1,itypat)+bb*xccc1d(jj+1,1,itypat) +&
     892       877010 : &             cc*xccc1d(jj,3,itypat)+dd*xccc1d(jj+1,3,itypat)
     893              :            end if
     894      1315515 :            if (option>=2) then
     895              :              dtcore(ipts)=aa*xccc1d(jj,2,itypat)+bb*xccc1d(jj+1,2,itypat) +&
     896       877010 : &             cc*xccc1d(jj,4,itypat)+dd*xccc1d(jj+1,4,itypat)
     897              :            end if
     898      1316388 :            if (option==4) then
     899              :              d2tcore(ipts)=aa*xccc1d(jj,3,itypat)+bb*xccc1d(jj+1,3,itypat) +&
     900            0 : &             cc*xccc1d(jj,5,itypat)+dd*xccc1d(jj+1,5,itypat)
     901              :            end if
     902              :          end do
     903              :        end if
     904              : 
     905              : !      Now, perform the loop over selected grid points
     906      1316403 :        do ipts=1,npts
     907      1315515 :          ishift1=indx1(iindex(ipts))
     908      1315515 :          ishift2=indx2(iindex(ipts))
     909      1315515 :          difmag=rnorm(ipts)
     910              : 
     911      1315515 :          rdiff1=rrdiff(ishift1,1);rdiff2=rrdiff(ishift2,2)
     912      1315515 :          jpts=ii(ishift1,1)+n1*(ii(ishift2,2)-1+n2*(ffti3_local(i3)-1))
     913              : 
     914              : !        === Evaluate charge density
     915      1316430 :          if (option==1) then
     916       438505 :            xccc3d(jpts)=xccc3d(jpts)+tcore(ipts)
     917              : 
     918              : !        === Accumulate contributions to forces
     919       877010 :          else if (option==2) then
     920       438505 :            if (difmag>tol10) then
     921       438500 :              term=vxc_eff(jpts)*dtcore(ipts)/difmag
     922       438500 :              corgr(1)=corgr(1)+rdiff1*term
     923       438500 :              corgr(2)=corgr(2)+rdiff2*term
     924       438500 :              corgr(3)=corgr(3)+rdiff3*term
     925              :            end if
     926              : 
     927              : !        === Accumulate contributions to stress tensor (in red. coordinates)
     928       438505 :          else if (option==3) then
     929       438505 :            if (difmag>tol10) then
     930       438500 :              term=vxc_eff(jpts)*dtcore(ipts)*rangem1/difmag/real(nfftot,dp)
     931              : !            Write out the 6 symmetric components
     932       438500 :              corfra(1,1)=corfra(1,1)+term*rdiff1*rdiff1
     933       438500 :              corfra(2,2)=corfra(2,2)+term*rdiff2*rdiff2
     934       438500 :              corfra(3,3)=corfra(3,3)+term*rdiff3*rdiff3
     935       438500 :              corfra(3,2)=corfra(3,2)+term*rdiff3*rdiff2
     936       438500 :              corfra(3,1)=corfra(3,1)+term*rdiff3*rdiff1
     937       438500 :              corfra(2,1)=corfra(2,1)+term*rdiff2*rdiff1
     938              : !            (the above still needs to be transformed to cartesian coords)
     939              :            end if
     940              : !          Also compute a diagonal term
     941       438505 :            strdia=strdia+vxc_eff(jpts)*tcore(ipts)
     942              : 
     943              : !        === Compute frozen-wf contribution to Dynamical matrix
     944            0 :          else if (option==4) then
     945            0 :            tt(1)=rmet(1,1)*rdiff1+rmet(1,2)*rdiff2+rmet(1,3)*rdiff3
     946            0 :            tt(2)=rmet(2,1)*rdiff1+rmet(2,2)*rdiff2+rmet(2,3)*rdiff3
     947            0 :            tt(3)=rmet(3,1)*rdiff1+rmet(3,2)*rdiff2+rmet(3,3)*rdiff3
     948            0 :            if (difmag>tol10) then
     949            0 :              term=(ucvol/real(nfftot,dp))*vxc_eff(jpts)*rangem1/difmag
     950            0 :              term1=term*tcore(ipts)
     951            0 :              term2=term*d2tcore(ipts)*rangem1/difmag
     952            0 :              do mu=1,3
     953            0 :                do nu=1,3
     954              :                  dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)&
     955              : &                 +(term2-term1/difmag**2)*tt(mu)*tt(nu)&
     956            0 : &                 +term1*rmet(mu,nu)
     957              :                end do
     958              :              end do
     959              :            else
     960              : !            There is a contribution from difmag=zero !
     961            0 :              term=(ucvol/real(nfftot,dp))*vxc_eff(jpts)*d2tcore(ipts)*rangem1**2
     962            0 :              do mu=1,3
     963            0 :                do nu=1,3
     964            0 :                  dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)+term*rmet(mu,nu)
     965              :                end do
     966              :              end do
     967              :            end if
     968              :          end if ! Choice of option
     969              : 
     970              :        end do ! Loop on ipts (ishift1, ishift2)
     971              : 
     972              :      end do ! Loop on ishift3
     973              : 
     974           15 :      ABI_FREE(ii)
     975           15 :      ABI_FREE(rrdiff)
     976           15 :      ABI_FREE(indx1)
     977           15 :      ABI_FREE(indx2)
     978           15 :      ABI_FREE(iindex)
     979           15 :      ABI_FREE(rnorm)
     980           15 :      if (allocated(tcore)) then
     981           10 :        ABI_FREE(tcore)
     982              :      end if
     983           15 :      if (allocated(tcoretau)) then
     984            0 :        ABI_FREE(tcoretau)
     985              :      end if
     986           15 :      if (allocated(dtcore)) then
     987           10 :        ABI_FREE(dtcore)
     988              :      end if
     989           15 :      if (allocated(d2tcore)) then
     990            0 :        ABI_FREE(d2tcore)
     991              :      end if
     992              : 
     993           30 :      if (option==2) then
     994            5 :        fact=-(ucvol/real(nfftot,dp))/range
     995           20 :        grxc(:,iatom)=corgr(:)*fact
     996              :      end if
     997              : 
     998              : !  End loop on atoms
     999              :    end do
    1000              : 
    1001           61 :    if (usepaw==1) then
    1002            0 :      call pawrad_free(core_mesh)
    1003              :    end if
    1004              : 
    1005              : !End loop over atom types
    1006              :  end do
    1007              : 
    1008           46 :  if(option>=2.and.nspden>=2)  then
    1009            0 :    ABI_FREE(vxc_eff)
    1010              :  end if
    1011              : 
    1012              : !Forces: translate into reduced coordinates
    1013           46 :  if (option==2) then
    1014            8 :    do iatom=1,natom
    1015            5 :      t1=grxc(1,iatom);t2=grxc(2,iatom);t3=grxc(3,iatom)
    1016           23 :      grxc(:,iatom)=rmet(:,1)*t1+rmet(:,2)*t2+rmet(:,3)*t3
    1017              :    end do
    1018              :  end if
    1019              : 
    1020              : !Stress tensor: symmetrize, translate into cartesian coord., add diagonal part
    1021           46 :  if (option==3) then
    1022            3 :    corstr(1)=corfra(1,1) ; corstr(2)=corfra(2,2)
    1023            3 :    corstr(3)=corfra(3,3) ; corstr(4)=corfra(3,2)
    1024            3 :    corstr(5)=corfra(3,1) ; corstr(6)=corfra(2,1)
    1025            3 :    call strconv(corstr,rprimd,corstr)
    1026            3 :    corstr(1)=corstr(1)+strdia/real(nfftot,dp)
    1027            3 :    corstr(2)=corstr(2)+strdia/real(nfftot,dp)
    1028            3 :    corstr(3)=corstr(3)+strdia/real(nfftot,dp)
    1029              :  end if
    1030              : 
    1031              : !If needed sum over MPI processes
    1032           46 :  if(mpi_enreg%nproc_fft>1) then
    1033            0 :    call timab(539,1,tsec)
    1034            0 :    if (option==2) then
    1035            0 :      call xmpi_sum(grxc,mpi_enreg%comm_fft,ier)
    1036              :    end if
    1037            0 :    if (option==3) then
    1038            0 :      call xmpi_sum(corstr,mpi_enreg%comm_fft,ier)
    1039              :    end if
    1040            0 :    if (option==4) then
    1041            0 :      call xmpi_sum(dyfrx2,mpi_enreg%comm_fft,ier)
    1042              :    end if
    1043            0 :    call timab(539,2,tsec)
    1044              :  end if
    1045              : 
    1046           92 :  call timab(12,2,tsec)
    1047              : 
    1048              :  contains
    1049              : !!***
    1050              : 
    1051              : !--------------------------------------------------------------
    1052              : 
    1053              : !!****f* ABINIT/cross_mkcore_alt
    1054              : !! NAME
    1055              : !!  cross_mkcore_alt
    1056              : !!
    1057              : !! FUNCTION
    1058              : !!  Define magnitude of cross product of two vectors
    1059              : !!
    1060              : !! SOURCE
    1061              : 
    1062          138 :    function cross_mkcore_alt(xx,yy,zz,aa,bb,cc)
    1063              : 
    1064              :     real(dp) :: cross_mkcore_alt
    1065              :     real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
    1066              : ! *************************************************************************
    1067          138 :    cross_mkcore_alt=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
    1068          138 :  end function cross_mkcore_alt
    1069              : !!***
    1070              : 
    1071              : !--------------------------------------------------------------
    1072              : 
    1073              : !!****f* ABINIT/indpos_mkcore_alt
    1074              : !! NAME
    1075              : !!  indpos_mkcore_alt
    1076              : !!
    1077              : !! FUNCTION
    1078              : !!  Find the grid index of a given position in the cell according to the BC
    1079              : !!  Determine also whether the index is inside or outside the box for free BC
    1080              : !!
    1081              : !! SOURCE
    1082              : 
    1083            0 :    subroutine indpos_mkcore_alt(periodic,ii,nn,jj,inside)
    1084              : !    Find the grid index of a given position in the cell according to the BC
    1085              : !    Determine also whether the index is inside or outside the box for free BC
    1086              :     integer, intent(in) :: ii,nn
    1087              :     integer, intent(out) :: jj
    1088              :     logical, intent(in) :: periodic
    1089              :     logical, intent(out) :: inside
    1090              : ! *************************************************************************
    1091            0 :    if (periodic) then
    1092            0 :      inside=.true. ; jj=modulo(ii-1,nn)+1
    1093              :    else
    1094            0 :      jj=ii ; inside=(ii>=1.and.ii<=nn)
    1095              :    end if
    1096            0 :  end subroutine indpos_mkcore_alt
    1097              : 
    1098              : end subroutine mkcore_alt
    1099              : !!***
    1100              : 
    1101              : !!****f* ABINIT/dfpt_mkcore
    1102              : !! NAME
    1103              : !! dfpt_mkcore
    1104              : !!
    1105              : !! FUNCTION
    1106              : !! Compute the derivative of the core electron density
    1107              : !! with respect to one specific atom displacement
    1108              : !! In case of derivative with respect to k or
    1109              : !! electric (magnetic) field perturbation, the 1st-order core electron density
    1110              : !! vanishes.
    1111              : !!
    1112              : !! INPUTS
    1113              : !!  cplex: if 1, real space 1-order functions on FFT grid are REAL,
    1114              : !!    if 2, COMPLEX
    1115              : !!  idir=direction of atomic displacement (=1,2 or 3 : displacement of
    1116              : !!    atom ipert along the 1st, 2nd or 3rd axis) or cartesian coordinate
    1117              : !!    pair for strain perturbation
    1118              : !!  ipert=number of the atom being displaced or natom+3,4 for strain
    1119              : !!    perturbation
    1120              : !!  natom=number of atoms in cell.
    1121              : !!  ntypat=number of types of atoms in cell.
    1122              : !!  n1,n2,n3=fft grid dimensions.
    1123              : !!  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
    1124              : !!  qphon(3)=wavevector of the phonon
    1125              : !!  rprimd(3,3)=dimensional primitive translation vectors (bohr)
    1126              : !!  typat(natom)=integer type for each atom in cell
    1127              : !!  ucvol=unit cell volume (bohr**3).
    1128              : !!  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
    1129              : !!  xccc1d(n1xccc,6,ntypat)=1D core charge function and five derivatives,
    1130              : !!   for each type of atom, from psp
    1131              : !!  xred(3,natom)=reduced coordinates for atoms in unit cell
    1132              : !!
    1133              : !! OUTPUT
    1134              : !!  xccc3d1(cplex*n1*n2*n3)=3D core electron density for XC core correction, bohr^-3
    1135              : !!
    1136              : !! NOTES
    1137              : !! Note that this routine is tightly connected to the mkcore.f routine
    1138              : !!
    1139              : !! SOURCE
    1140              : 
    1141        14692 : subroutine dfpt_mkcore(cplex,idir,ipert,natom,ntypat,n1,n1xccc,&
    1142        14692 : & n2,n3,qphon,rprimd,typat,ucvol,xcccrc,xccc1d,xccc3d1,xred)
    1143              : 
    1144              : !Arguments ------------------------------------
    1145              : !scalars
    1146              :  integer,intent(in) :: cplex,idir,ipert,n1,n1xccc,n2,n3,natom,ntypat
    1147              :  real(dp),intent(in) :: ucvol
    1148              : !arrays
    1149              :  integer,intent(in) :: typat(natom)
    1150              :  real(dp),intent(in) :: qphon(3),rprimd(3,3),xccc1d(n1xccc,6,ntypat)
    1151              :  real(dp),intent(in) :: xcccrc(ntypat),xred(3,natom)
    1152              :  real(dp),intent(out) :: xccc3d1(cplex*n1*n2*n3)
    1153              : 
    1154              : !Local variables-------------------------------
    1155              : !scalars
    1156              :  integer,parameter :: mshift=401
    1157              :  integer :: i1,i2,i3,iatom,ifft,ishift,ishift1,ishift2,ishift3,istr
    1158              :  integer :: ixp,jj,ka,kb,mrange,mu,nu
    1159              :  real(dp) :: aa,bb,cc,dd,delta,delta2div6,deltam1,diff,difmag
    1160              :  real(dp) :: difmag2,difmag2_fact,difmag2_part,func,phase,phi,phr,prod
    1161              :  real(dp) :: range,range2,rangem1,rdiff1,rdiff2,rdiff3,term
    1162              :  real(dp) :: yy
    1163              :  character(len=500) :: message
    1164              : !arrays
    1165              :  integer,save :: idx(12)=(/1,1,2,2,3,3,3,2,3,1,2,1/)
    1166              :  integer :: igrid(3),irange(3),ngfft(3)
    1167        14692 :  integer,allocatable :: ii(:,:)
    1168              :  real(dp) :: drmetds(3,3),lencp(3),rmet(3,3),scale(3),tau(3)
    1169        14692 :  real(dp),allocatable :: rrdiff(:,:)
    1170              : ! *************************************************************************
    1171              : 
    1172              : ! if( ipert<1 .or. ipert> natom+7) then
    1173              : !   write(message,'(a,i0,a,a,a,i0,a)')&
    1174              : !&   ' The argument ipert must be between 1 and natom+7=',natom+7,',',ch10,&
    1175              : !&   ' while it is ipert=',ipert,'.'
    1176              : !   ABI_BUG(message)
    1177              : ! end if
    1178              : 
    1179        14692 :  if( (ipert==natom+3 .or. ipert==natom+4) .and. cplex/=1) then
    1180              :    write(message,'(3a,i4,a)')&
    1181            0 : &   'The argument cplex must be 1 for strain perturbationh',ch10,&
    1182            0 : &   'while it is cplex=',cplex,'.'
    1183            0 :    ABI_BUG(message)
    1184              :  end if
    1185              : 
    1186              : !Zero out array
    1187    274243017 :  xccc3d1(:)=0.0_dp
    1188              : 
    1189              : !For a non-linear XC core correction, the perturbation must be phonon-type or strain type
    1190        14692 :  if(ipert<=natom .or. ipert==natom+3 .or. ipert==natom+4) then
    1191              : 
    1192        14347 :    if( idir<1 .or. idir> 3) then
    1193              :      write(message,'(a,a,a,i4,a)')&
    1194            0 : &     'The argument idir must be between 1 and 3,',ch10,&
    1195            0 : &     'while it is idir=',idir,'.'
    1196            0 :      ABI_BUG(message)
    1197              :    end if
    1198              : 
    1199              : !  Compute lengths of cross products for pairs of primitive
    1200              : !  translation vectors (used in setting index search range below)
    1201              :    lencp(1)=cross_mk(rprimd(1,2),rprimd(2,2),rprimd(3,2),&
    1202        14347 : &   rprimd(1,3),rprimd(2,3),rprimd(3,3))
    1203              :    lencp(2)=cross_mk(rprimd(1,3),rprimd(2,3),rprimd(3,3),&
    1204        14347 : &   rprimd(1,1),rprimd(2,1),rprimd(3,1))
    1205              :    lencp(3)=cross_mk(rprimd(1,1),rprimd(2,1),rprimd(3,1),&
    1206        14347 : &   rprimd(1,2),rprimd(2,2),rprimd(3,2))
    1207              : 
    1208              : !  Compute factor R1.(R2xR3)/|R2xR3| etc for 1, 2, 3
    1209              : !  (recall ucvol=R1.(R2xR3))
    1210        57388 :    scale(:)=ucvol/lencp(:)
    1211              : 
    1212              : !  Compute metric tensor in real space rmet
    1213        57388 :    do nu=1,3
    1214              :      rmet(:,nu)=rprimd(1,:)*rprimd(1,nu)+rprimd(2,:)*rprimd(2,nu)+&
    1215       186511 : &     rprimd(3,:)*rprimd(3,nu)
    1216              :    end do
    1217              : 
    1218              : !  Section to be executed only for strain perturbation
    1219              : !  Compute derivative of metric tensor wrt strain component istr
    1220        14347 :    if(ipert==natom+3 .or. ipert==natom+4) then
    1221          502 :      istr=idir + 3*(ipert-natom-3)
    1222              : 
    1223          502 :      ka=idx(2*istr-1);kb=idx(2*istr)
    1224         2008 :      do jj = 1,3
    1225         6526 :        drmetds(:,jj)=(rprimd(ka,:)*rprimd(kb,jj)+rprimd(kb,:)*rprimd(ka,jj))
    1226              :      end do
    1227              : !    For historical reasons:
    1228        20371 :      drmetds(:,:)=0.5_dp*drmetds(:,:)
    1229              : 
    1230              : !    end of strain perturbation section
    1231              :    end if
    1232              : 
    1233        14347 :    ngfft(1)=n1
    1234        14347 :    ngfft(2)=n2
    1235        14347 :    ngfft(3)=n3
    1236              : 
    1237        14347 :    delta=1.0_dp/(n1xccc-1)
    1238        14347 :    deltam1=n1xccc-1
    1239        14347 :    delta2div6=delta**2/6.0_dp
    1240              : 
    1241              : !  Loop over atoms in unit cell
    1242              : !  Note that we cycle immediately for all except the displaced atom
    1243              : !  for such a perturbation.  The loop is executed over all the
    1244              : !  atoms for a strain peturbation.
    1245        56095 :    do iatom=1,natom
    1246        41748 :      if(ipert<=natom .and. iatom/=ipert) cycle
    1247              : !    Set search range (density cuts off perfectly beyond range)
    1248              : !    Cycle if no range.
    1249        14878 :      range=0.0_dp
    1250        14878 :      range=xcccrc(typat(iatom))
    1251        14878 :      if(range<1.d-16) cycle
    1252              : 
    1253        13644 :      range2=range**2
    1254        13644 :      rangem1=1.0_dp/range
    1255              : 
    1256              : !    compute mrange for ii(:,3), rrdiff(:,3), inserted by MM (2005/12/06)
    1257              : !    Consider each component in turn : compute range
    1258        54576 :      do mu=1,3
    1259              : 
    1260              : !      Convert reduced coord of given atom to [0,1)
    1261        40932 :        tau(mu)=mod(xred(mu,iatom)+1._dp-aint(xred(mu,iatom)),1._dp)
    1262              : 
    1263              : !      Use tau to find nearest grid point along R(mu)
    1264              : !      (igrid=0 is the origin; shift by 1 to agree with usual index)
    1265        40932 :        igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
    1266              : 
    1267              : !      Use range to compute an index range along R(mu)
    1268              : !      (add 1 to make sure it covers full range)
    1269        54576 :        irange(mu)=1+nint((range/scale(mu))*dble(ngfft(mu)))
    1270              : 
    1271              :      end do
    1272              : 
    1273              : !    Allocate arrays that depends on the range
    1274        54576 :      mrange=maxval(irange(1:3))
    1275        54576 :      ABI_MALLOC(ii,(2*mrange+1,3))
    1276        40932 :      ABI_MALLOC(rrdiff,(2*mrange+1,3))
    1277              : 
    1278              : !    Consider each component in turn
    1279        54576 :      do mu=1,3
    1280              : 
    1281              : !      temporarily suppressed by MM (2005/12/02)
    1282              : !      Convert reduced coord of given atom to [0,1)
    1283              : !      tau(mu)=mod(xred(mu,iatom)+1._dp-aint(xred(mu,iatom)),1._dp)
    1284              : 
    1285              : !      Use tau to find nearest grid point along R(mu)
    1286              : !      (igrid=0 is the origin; shift by 1 to agree with usual index)
    1287              : !      igrid(mu)=nint(tau(mu)*dble(ngfft(mu)))
    1288              : 
    1289              : !      Use range to compute an index range along R(mu)
    1290              : !      (add 1 to make sure it covers full range)
    1291              : !      irange(mu)=1+nint((range/scale(mu))*dble(ngfft(mu)))
    1292              : 
    1293              : !      Check that the largest range is smallest than the maximum
    1294              : !      allowed one
    1295              : !      if(2*irange(mu)+1 > mshift)then
    1296              : !      write(message, '(a,a,a,a,i6,a)' ) ch10,&
    1297              : !      &    ' dfpt_mkcore : BUG -',ch10,&
    1298              : !      &    '  The range around atom',iatom,' is too large.'
    1299              : !      ABI_BUG(message)
    1300              : !      end if
    1301              : 
    1302              : !      Set up a counter that explore the relevant range
    1303              : !      of points around the atom
    1304        40932 :        ishift=0
    1305      1688176 :        do ixp=igrid(mu)-irange(mu),igrid(mu)+irange(mu)
    1306      1633600 :          ishift=ishift+1
    1307      1633600 :          ii(ishift,mu)=1+mod(ngfft(mu)+mod(ixp,ngfft(mu)),ngfft(mu))
    1308      1674532 :          rrdiff(ishift,mu)=dble(ixp)/dble(ngfft(mu))-tau(mu)
    1309              :        end do
    1310              : 
    1311              : !      End loop on mu
    1312              :      end do
    1313              : 
    1314              : !    Conduct triple loop over restricted range of grid points for iatom
    1315              : 
    1316       545288 :      do ishift3=1,1+2*irange(3)
    1317              : !      map back to [1,ngfft(3)] for usual fortran index in unit cell
    1318       531644 :        i3=ii(ishift3,3)
    1319              : !      find vector from atom location to grid point (reduced)
    1320       531644 :        rdiff3=rrdiff(ishift3,3)
    1321              : 
    1322     28801076 :        do ishift2=1,1+2*irange(2)
    1323     28255788 :          i2=ii(ishift2,2)
    1324     28255788 :          rdiff2=rrdiff(ishift2,2)
    1325              : !        Prepare the computation of difmag2
    1326              :          difmag2_part=rmet(3,3)*rdiff3**2+rmet(2,2)*rdiff2**2&
    1327     28255788 : &         +2.0_dp*rmet(3,2)*rdiff3*rdiff2
    1328     28255788 :          difmag2_fact=2.0_dp*(rmet(3,1)*rdiff3+rmet(2,1)*rdiff2)
    1329              : 
    1330   1914049192 :          do ishift1=1,1+2*irange(1)
    1331   1885261760 :            rdiff1=rrdiff(ishift1,1)
    1332              : 
    1333              : !          Compute (rgrid-tau-Rprim)**2
    1334   1885261760 :            difmag2= difmag2_part+rdiff1*(difmag2_fact+rmet(1,1)*rdiff1)
    1335              : 
    1336              : !          Only accept contribution inside defined range
    1337   1913517548 :            if (difmag2<range2) then
    1338              : 
    1339              : !            Prepare computation of core charge function and derivative,
    1340              : !            using splines
    1341    677162857 :              difmag=sqrt(difmag2)
    1342    677162857 :              if (difmag>=1.0d-10) then
    1343    677154932 :                i1=ii(ishift1,1)
    1344    677154932 :                yy=difmag*rangem1
    1345              : 
    1346              : !              Compute index of yy over 1 to n1xccc scale
    1347    677154932 :                jj=1+int(yy*(n1xccc-1))
    1348    677154932 :                diff=yy-(jj-1)*delta
    1349              : 
    1350              : !              Will evaluate spline fit (p. 86 Numerical Recipes, Press et al;
    1351              : !              NOTE error in book for sign of "aa" term in derivative;
    1352              : !              also see splfit routine).
    1353    677154932 :                bb = diff*deltam1
    1354    677154932 :                aa = 1.0_dp-bb
    1355    677154932 :                cc = aa*(aa**2-1.0_dp)*delta2div6
    1356    677154932 :                dd = bb*(bb**2-1.0_dp)*delta2div6
    1357              : 
    1358              : !              Evaluate spline fit of 1st der of core charge density
    1359              : !              from xccc1d(:,2,:) and (:,4,:)
    1360              :                func=aa*xccc1d(jj,2,typat(iatom))+bb*xccc1d(jj+1,2,typat(iatom)) +&
    1361    677154932 : &               cc*xccc1d(jj,4,typat(iatom))+dd* xccc1d(jj+1,4,typat(iatom))
    1362              : 
    1363    677154932 :                if(ipert<=natom) then
    1364              :                  phase=2*pi*(qphon(1)*(rdiff1+xred(1,iatom))  &
    1365              : &                 +qphon(2)*(rdiff2+xred(2,iatom))  &
    1366    664960548 : &                 +qphon(3)*(rdiff3+xred(3,iatom)))
    1367    664960548 :                  prod=rmet(idir,1)*rdiff1+rmet(idir,2)*rdiff2+rmet(idir,3)*rdiff3
    1368              : 
    1369    664960548 :                  term=-func*rangem1/difmag*prod
    1370    664960548 :                  ifft=i1+n1*(i2-1+n2*(i3-1))
    1371    664960548 :                  phr=cos(phase)
    1372    664960548 :                  if(cplex==1)then
    1373    252397494 :                    xccc3d1(ifft)=xccc3d1(ifft)+term*phr
    1374              :                  else
    1375    412563054 :                    phi=sin(phase)
    1376    412563054 :                    xccc3d1(2*ifft-1)=xccc3d1(2*ifft-1)+term*phr
    1377    412563054 :                    xccc3d1(2*ifft  )=xccc3d1(2*ifft  )-term*phi
    1378              :                  end if
    1379              :                else
    1380              :                  prod=&
    1381              : &                 (rdiff1*(drmetds(1,1)*rdiff1+drmetds(1,2)*rdiff2+drmetds(1,3)*rdiff3)&
    1382              : &                 +rdiff2*(drmetds(2,1)*rdiff1+drmetds(2,2)*rdiff2+drmetds(2,3)*rdiff3)&
    1383     12194384 : &                 +rdiff3*(drmetds(3,1)*rdiff1+drmetds(3,2)*rdiff2+drmetds(3,3)*rdiff3))
    1384     12194384 :                  term=prod*func*rangem1/difmag
    1385              : 
    1386     12194384 :                  ifft=i1+n1*(i2-1+n2*(i3-1))
    1387     12194384 :                  xccc3d1(ifft)=xccc3d1(ifft)+term
    1388              : 
    1389              :                end if
    1390              : 
    1391              : !              End of the condition for the distance not to vanish
    1392              :              end if
    1393              : 
    1394              : !            End of condition to be inside the range
    1395              :            end if
    1396              : 
    1397              : !          End loop on ishift1
    1398              :          end do
    1399              : 
    1400              : !        End loop on ishift2
    1401              :        end do
    1402              : 
    1403              : !      End loop on ishift3
    1404              :      end do
    1405              : 
    1406        13644 :      ABI_FREE(ii)
    1407        56440 :      ABI_FREE(rrdiff)
    1408              : !    End loop on atoms
    1409              :    end do
    1410              : 
    1411              : !  End of the condition ipert corresponds to a phonon type perturbation
    1412              : !  or strain type perturbation
    1413              :  end if
    1414              : 
    1415              :  contains
    1416              : 
    1417        43041 :    function cross_mk(xx,yy,zz,aa,bb,cc)
    1418              : 
    1419              :    real(dp) :: cross_mk
    1420              :    real(dp),intent(in) :: xx,yy,zz,aa,bb,cc
    1421        43041 :    cross_mk=sqrt((yy*cc-zz*bb)**2+(zz*aa-xx*cc)**2+(xx*bb-yy*aa)**2)
    1422        43041 :  end function cross_mk
    1423              : 
    1424              : end subroutine dfpt_mkcore
    1425              : !!***
    1426              : 
    1427              : end module m_mkcore
    1428              : !!***
        

Generated by: LCOV version 2.3-1