LCOV - code coverage report
Current view: top level - src/67_common - m_nucprop.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.1 % 308 299
Test Date: 2026-11-11 11:17:02 Functions: 100.0 % 4 4
Branches: 73.8 % 432 319

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_nucprop
       2                 :             : !! NAME
       3                 :             : !!  m_nucprop
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  routines used to compute properties at the nuclear sites, including
       7                 :             : !!  electric field gradient and Fermi contact
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !! Copyright (C) 1998-2026 ABINIT group (MT, JWZ)
      11                 :             : !!  This file is distributed under the terms of the
      12                 :             : !!  GNU General Public License, see ~abinit/COPYING
      13                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      14                 :             : !!
      15                 :             : !! SOURCE
      16                 :             : 
      17                 :             : #if defined HAVE_CONFIG_H
      18                 :             : #include "config.h"
      19                 :             : #endif
      20                 :             : 
      21                 :             : #include "abi_common.h"
      22                 :             : 
      23                 :             : module m_nucprop
      24                 :             : 
      25                 :             :   use defs_basis
      26                 :             :   use m_abicore
      27                 :             :   use m_errors
      28                 :             : 
      29                 :             :   use defs_abitypes, only : MPI_type
      30                 :             :   use m_mpinfo,   only : ptabs_fourdp
      31                 :             :   use m_xmpi, only : xmpi_comm_self, xmpi_sum
      32                 :             :   use m_geometry,       only : xred2xcart
      33                 :             :   use m_linalg_interfaces, only: dsyev
      34                 :             :   use m_paw_an,      only : paw_an_type
      35                 :             :   use m_pawang,      only : pawang_type
      36                 :             :   use m_pawrad,     only : pawrad_type
      37                 :             :   use m_pawtab,     only : pawtab_type
      38                 :             :   use m_pawrhoij,   only : pawrhoij_type
      39                 :             :   use m_paw_nmr,    only : make_efg_onsite,make_fc_paw
      40                 :             :   use m_paral_atom, only : get_my_atmtab,free_my_atmtab
      41                 :             :   use m_special_funcs,  only : abi_derfc
      42                 :             :   use m_matrix,         only : matr3inv
      43                 :             :   use m_symtk,         only : matpointsym
      44                 :             :   use m_fft,           only : fourdp
      45                 :             : 
      46                 :             :   implicit none
      47                 :             : 
      48                 :             :   private
      49                 :             : !!***
      50                 :             : 
      51                 :             :   public :: calc_efg
      52                 :             :   public :: calc_fc
      53                 :             :   public :: make_efg_ion
      54                 :             :   public :: make_efg_el
      55                 :             : !!***
      56                 :             : 
      57                 :             : contains
      58                 :             : 
      59                 :             : !!****f* ABINIT/calc_efg
      60                 :             : !! NAME
      61                 :             : !! calc_efg
      62                 :             : !!
      63                 :             : !! FUNCTION
      64                 :             : !! calculation and output of electric field gradient tensor at each atomic site
      65                 :             : !!
      66                 :             : !! INPUTS
      67                 :             : !!  mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
      68                 :             : !!  comm_atom=--optional-- MPI communicator over atoms
      69                 :             : !!  mpi_enreg=information about MPI parallelization
      70                 :             : !!  my_natom=number of atoms treated by current processor
      71                 :             : !!  natom=number of atoms in cell.
      72                 :             : !!  nfft=number of points on fft grid
      73                 :             : !!  ngfft(18)=details of fft
      74                 :             : !!  nhat(nfft,nspden)=compensation charge density
      75                 :             : !!  nspden=number of spin densities
      76                 :             : !!  nsym=number of symmetries in space group
      77                 :             : !!  ntypat=number of atom types
      78                 :             : !!  nucefg=1 to print summary output, 2 for detailed output
      79                 :             : !!  ptcharge(ntypat)=user input charges on atoms to make simple point charge calc
      80                 :             : !!  paw_an(my_natom) <type(paw_an_type)>=paw arrays given on angular mesh
      81                 :             : !!  pawang <type(pawang_type)>=paw angular mesh and related data
      82                 :             : !!  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
      83                 :             : !!  pawrhoij(my_natom) <type(pawrhoij_type)>= paw rhoij occupancies and related data
      84                 :             : !!  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
      85                 :             : !!  quadmom(ntypat)=quadrupole moments in barns of different atomic nuclei
      86                 :             : !!  rhor(nfft,nspden)=electron density on grid (strictly $\tilde{n}+\hat{n}$)
      87                 :             : !!  rprimd(3,3)=matrix relating cartesian coordinates to crystal coordinates
      88                 :             : !!  symrel(3,3,nsym)=symmetry operators in terms of action on primitive translations
      89                 :             : !!  tnons(3,nsym)=nonsymmorphic translations
      90                 :             : !!  typat(natom)=type (integer) for each atom
      91                 :             : !!  ucvol=unit cell volume in Bohr^3
      92                 :             : !!  usepaw=1 if we are using PAW formalism, 0 else
      93                 :             : !!  xred(3,natom)=vectors locating each atom in the unit cell, in crystal coords
      94                 :             : !!  zion(ntypat)=net core charge on each type of atom
      95                 :             : !!
      96                 :             : !! OUTPUT
      97                 :             : !!  (only writing, printing)
      98                 :             : !!
      99                 :             : !! SOURCE
     100                 :             : 
     101                 :          18 :   subroutine calc_efg(efg,mpi_enreg,my_natom,natom,nfft,ngfft,nhat,nspden,nsym,nucefg,ntypat,&
     102                 :           9 :                       paw_an,pawang,pawrad,pawrhoij,pawtab,&
     103                 :           9 :                       ptcharge,quadmom,rhor,rprimd,symrel,tnons,typat,ucvol,usepaw,xred,zion,&
     104   [ +  -  -  +  :           9 :                       mpi_atmtab,comm_atom) ! optional arguments (parallelism)
                   -  - ]
     105                 :             : 
     106                 :             :     !Arguments ------------------------------------
     107                 :             :     !scalars
     108                 :             :     integer,intent(in) :: my_natom,natom,nfft,nspden,nsym,nucefg,ntypat,usepaw
     109                 :             :     integer,optional,intent(in) :: comm_atom
     110                 :             :     real(dp),intent(in) :: ucvol
     111                 :             :     type(MPI_type),intent(in) :: mpi_enreg
     112                 :             :     type(pawang_type),intent(in) :: pawang
     113                 :             :     !arrays
     114                 :             :     integer,intent(in) :: ngfft(18),symrel(3,3,nsym),typat(natom)
     115                 :             :     integer,optional,target,intent(in) :: mpi_atmtab(:)
     116                 :             :     real(dp),intent(in) :: nhat(nfft,nspden),ptcharge(ntypat)
     117                 :             :     real(dp),intent(in) :: quadmom(ntypat),rhor(nfft,nspden),rprimd(3,3)
     118                 :             :     real(dp),intent(in) :: tnons(3,nsym),zion(ntypat)
     119                 :             :     real(dp),intent(inout) :: xred(3,natom)
     120                 :             :     real(dp),intent(out) :: efg(3,3,natom)
     121                 :             :     type(paw_an_type),intent(in) :: paw_an(my_natom)
     122                 :             :     type(pawrad_type),intent(in) :: pawrad(ntypat)
     123                 :             :     type(pawrhoij_type),intent(in) :: pawrhoij(my_natom)
     124                 :             :     type(pawtab_type),intent(in) :: pawtab(ntypat)
     125                 :             : 
     126                 :             :     !Local variables-------------------------------
     127                 :             :     !scalars
     128                 :             :     integer :: ii,INFO,LDA,LWORK,N,iatom,my_comm_atom
     129                 :             :     logical :: my_atmtab_allocated,paral_atom
     130                 :             :     real(dp) :: cq,efgsi21,eta,vxx,vyy,vzz
     131                 :             :     character(len=500) :: message
     132                 :             :     !arrays
     133                 :           9 :     integer,pointer :: my_atmtab(:)
     134                 :             :     real(dp) :: eigval(3),matr(3,3),work(8)
     135                 :           9 :     real(dp),allocatable :: efg_el(:,:,:),efg_ion(:,:,:),efg_paw(:,:,:)
     136                 :           9 :     real(dp),allocatable :: efg_point_charge(:,:,:)
     137                 :             : 
     138                 :             :     ! ************************************************************************
     139                 :             : 
     140                 :             :     !Compatibility tests
     141                 :           9 :     if (usepaw /= 1) then
     142                 :           0 :        message = ' usepaw /= 1 but EFG calculation requires PAW '
     143                 :           0 :        ABI_ERROR(message)
     144                 :             :     end if
     145                 :             : 
     146                 :           9 :     efgsi21=efg_si*1.0E-21 ! efg_si is electric field gradient in SI units, defined in
     147                 :             :                            ! defs_basis. Multiply by 10E-21 for nice printing below.
     148                 :             :                            ! 1 EFG in au is 9.725E21 volts/m^2
     149                 :             : 
     150                 :             :     !Set up parallelism over atoms
     151   [ +  -  +  - ]:           9 :     paral_atom=(present(comm_atom).and.(my_natom/=natom))
     152         [ -  + ]:           9 :     nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
     153         [ +  - ]:           9 :     my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
     154                 :           9 :     call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
     155                 :             : 
     156   [ -  +  +  -  :          27 :     ABI_MALLOC(efg_el,(3,3,natom))
          +  -  +  -  -  
                +  -  + ]
     157   [ -  +  +  -  :          18 :     ABI_MALLOC(efg_ion,(3,3,natom))
             -  +  -  + ]
     158   [ -  +  +  -  :          18 :     ABI_MALLOC(efg_paw,(3,3,natom))
             -  +  -  + ]
     159   [ -  +  +  -  :          18 :     ABI_MALLOC(efg_point_charge,(3,3,natom))
             -  +  +  - ]
     160   [ +  +  +  +  :         542 :     efg_el(:,:,:) = zero
                   +  + ]
     161   [ +  +  +  +  :         542 :     efg_ion(:,:,:) = zero
                   +  + ]
     162   [ +  +  +  +  :         542 :     efg_paw(:,:,:) = zero
                   +  + ]
     163   [ +  +  +  +  :         542 :     efg_point_charge(:,:,:) = zero
                   +  + ]
     164                 :             : 
     165                 :           9 :     call make_efg_el(efg_el,mpi_enreg,natom,nfft,ngfft,nhat,nspden,nsym,rhor,rprimd,symrel,tnons,xred)
     166                 :             : 
     167                 :           9 :     call make_efg_ion(efg_ion,natom,nsym,ntypat,rprimd,symrel,tnons,typat,ucvol,xred,zion)
     168                 :             : 
     169         [ -  + ]:           9 :     if (paral_atom) then
     170                 :             :        call make_efg_onsite(efg_paw,my_natom,natom,nsym,ntypat,paw_an,pawang,pawrhoij,pawrad,pawtab,&
     171                 :           0 :             &   rprimd,symrel,tnons,xred,comm_atom=my_comm_atom,mpi_atmtab=my_atmtab)
     172                 :             :     else
     173                 :             :        call make_efg_onsite(efg_paw,my_natom,natom,nsym,ntypat,paw_an,pawang,pawrhoij,pawrad,pawtab,&
     174                 :           9 :             &   rprimd,symrel,tnons,xred)
     175                 :             :     end if
     176                 :             : 
     177                 :             :     !calculate efg due to pure point charges, as input in variable ptcharge(ntypat)
     178                 :             :     !note here all atoms of the same type will have the same valence; in the future this
     179                 :             :     !could be made more flexible by having ptcharge(natom) but that will require a slightly
     180                 :             :     !different version than the existing make_efg_ion routine
     181         [ +  + ]:           9 :     if(nucefg > 2) then
     182                 :           1 :        call make_efg_ion(efg_point_charge,natom,nsym,ntypat,rprimd,symrel,tnons,typat,ucvol,xred,ptcharge)
     183                 :             :     end if
     184                 :             : 
     185   [ +  +  +  +  :         542 :     efg(:,:,:) = efg_el(:,:,:) + efg_ion(:,:,:) + efg_paw(:,:,:)
                   +  + ]
     186                 :             : 
     187                 :           9 :     write(message,'(a,a,a)' ) ch10,' Electric Field Gradient Calculation ',ch10
     188                 :           9 :     call wrtout(ab_out,message,'COLL')
     189                 :             : 
     190                 :           9 :     LDA=3; LWORK=8;N=3 ! these parameters are needed for the LAPACK dsyev routine
     191         [ +  + ]:          50 :     do iatom = 1, natom
     192   [ +  +  +  + ]:         533 :        matr(:,:) = efg(:,:,iatom)
     193                 :          41 :        call dsyev('V','U',N,matr,LDA,eigval,work,LWORK,INFO) ! get eigenvalues and eigenvectors
     194         [ +  + ]:          41 :        if (eigval(3) > abs(eigval(1)) ) then ! In NMR, the convention is that whatever component is
     195                 :             :           !    largest in magnitude is called Vzz, next comes Vxx, then Vyy
     196                 :          16 :           vzz = eigval(3)
     197                 :          16 :           vxx = eigval(1)
     198                 :          16 :           vyy = eigval(2)
     199                 :             :        else
     200                 :          25 :           vzz = eigval(1)
     201                 :          25 :           vxx = eigval(3)
     202                 :          25 :           vyy = eigval(2)
     203                 :             :        end if
     204                 :             :        ! Cq = vzz*(eQ)/h, where Q is the nuclear quad moment in barns (10E-28 m2)
     205                 :             :        ! Multiply Q by 1E-8 * Ang_Bohr**2 to get nuclear moment in Bohr^2
     206                 :             :        ! resulting vzz*(eQ) is energy in Ha (recall e = 1 in au)
     207                 :             :        ! then convert to MHz with Ha_THz*1.E6
     208                 :             :        ! resulting factors are Ang_Bohr**2*Ha_THz*1.0D-2
     209                 :          41 :        cq = vzz*quadmom(typat(iatom))*Ang_Bohr**2*Ha_THz*1.0D-2
     210         [ +  + ]:          41 :        if (abs(cq) > tol8) then
     211                 :          29 :          eta = abs(vxx-vyy)/abs(vzz)
     212                 :             :        else
     213                 :          12 :          cq = zero
     214                 :          12 :          eta = zero ! if Cq is small then eta is meaningless
     215                 :             :        end if
     216                 :             : 
     217                 :          41 :        write(message,'(a,a,i4,a,i4)')ch10,'   atom : ',iatom,'   typat : ',typat(iatom)
     218                 :          41 :        call wrtout(ab_out,message,'COLL')
     219         [ +  - ]:          41 :        if (nucefg > 1) then
     220                 :          41 :          write(message,'(2a,f9.4,a,f9.4,a,f9.4)') ch10,'   Nuclear quad. mom. (barns) : ',quadmom(typat(iatom)),&
     221                 :          82 :            & '   Cq (MHz) : ',cq,'   eta : ',eta
     222                 :          41 :          call wrtout(ab_out,message,'COLL')
     223                 :             :        end if
     224                 :             : 
     225                 :             :        ! for printing and test portability, it's better to simply set very small eigvals to zero
     226         [ +  + ]:         164 :        do ii=1,3
     227         [ +  + ]:         164 :          if (abs(eigval(ii))<tol8) eigval(ii)=zero
     228                 :             :        end do
     229                 :          41 :        write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      efg eigval (au) : ',eigval(1),' ; (1.0E+21 V/m^2) : ',eigval(1)*efgsi21,ch10,&
     230                 :          82 :             &     '-         eigvec : ',matr(1,1),matr(2,1),matr(3,1)
     231                 :          41 :        call wrtout(ab_out,message,'COLL')
     232                 :          41 :        write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      efg eigval (au) : ',eigval(2),' ; (1.0E+21 V/m^2) : ',eigval(2)*efgsi21,ch10,&
     233                 :          82 :             &     '-         eigvec : ',matr(1,2),matr(2,2),matr(3,2)
     234                 :          41 :        call wrtout(ab_out,message,'COLL')
     235                 :          41 :        write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      efg eigval (au) : ',eigval(3),' ; (1.0E+21 V/m^2) : ',eigval(3)*efgsi21,ch10,&
     236                 :          82 :             &     '-         eigvec : ',matr(1,3),matr(2,3),matr(3,3)
     237                 :          41 :        call wrtout(ab_out,message,'COLL')
     238                 :          41 :        write(message,'(a,a,3f13.6)')ch10,'      total efg : ',efg(1,1,iatom),efg(1,2,iatom),efg(1,3,iatom)
     239                 :          41 :        call wrtout(ab_out,message,'COLL')
     240                 :          41 :        write(message,'(a,3f13.6)')'      total efg : ',efg(2,1,iatom),efg(2,2,iatom),efg(2,3,iatom)
     241                 :          41 :        call wrtout(ab_out,message,'COLL')
     242                 :          41 :        write(message,'(a,3f13.6,a)')'      total efg : ',efg(3,1,iatom),efg(3,2,iatom),efg(3,3,iatom),ch10
     243                 :          41 :        call wrtout(ab_out,message,'COLL')
     244                 :          41 :        write(message,'(a,a,3f13.6)')ch10,'      efg_el : ',efg_el(1,1,iatom),efg_el(1,2,iatom),efg_el(1,3,iatom)
     245                 :          41 :        call wrtout(ab_out,message,'COLL')
     246                 :          41 :        write(message,'(a,3f13.6)')'      efg_el : ',efg_el(2,1,iatom),efg_el(2,2,iatom),efg_el(2,3,iatom)
     247                 :          41 :        call wrtout(ab_out,message,'COLL')
     248                 :          41 :        write(message,'(a,3f13.6,a)')'      efg_el : ',efg_el(3,1,iatom),efg_el(3,2,iatom),efg_el(3,3,iatom),ch10
     249                 :          41 :        call wrtout(ab_out,message,'COLL')
     250                 :          41 :        write(message,'(a,3f13.6)')'      efg_ion : ',efg_ion(1,1,iatom),efg_ion(1,2,iatom),efg_ion(1,3,iatom)
     251                 :          41 :        call wrtout(ab_out,message,'COLL')
     252                 :          41 :        write(message,'(a,3f13.6)')'      efg_ion : ',efg_ion(2,1,iatom),efg_ion(2,2,iatom),efg_ion(2,3,iatom)
     253                 :          41 :        call wrtout(ab_out,message,'COLL')
     254                 :          41 :        write(message,'(a,3f13.6,a)')'      efg_ion : ',efg_ion(3,1,iatom),efg_ion(3,2,iatom),efg_ion(3,3,iatom),ch10
     255                 :          41 :        call wrtout(ab_out,message,'COLL')
     256                 :          41 :        write(message,'(a,3f13.6)')'      efg_paw : ',efg_paw(1,1,iatom),efg_paw(1,2,iatom),efg_paw(1,3,iatom)
     257                 :          41 :        call wrtout(ab_out,message,'COLL')
     258                 :          41 :        write(message,'(a,3f13.6)')'      efg_paw : ',efg_paw(2,1,iatom),efg_paw(2,2,iatom),efg_paw(2,3,iatom)
     259                 :          41 :        call wrtout(ab_out,message,'COLL')
     260                 :          41 :        write(message,'(a,3f13.6,a)')'      efg_paw : ',efg_paw(3,1,iatom),efg_paw(3,2,iatom),efg_paw(3,3,iatom),ch10
     261                 :          41 :        call wrtout(ab_out,message,'COLL')
     262         [ +  + ]:          50 :        if (nucefg > 2) then ! write output of pure pointcharge calculation
     263   [ +  +  +  + ]:          78 :           matr(:,:) = efg_point_charge(:,:,iatom)
     264                 :           6 :           call dsyev('V','U',N,matr,LDA,eigval,work,LWORK,INFO) ! get eigenvalues and eigenvectors
     265         [ -  + ]:           6 :           if (eigval(3) > abs(eigval(1)) ) then ! In NMR, the convention is that whatever component is
     266                 :             :              !      largest in magnitude is called Vzz, next comes Vxx, then Vyy
     267                 :           0 :              vzz = eigval(3)
     268                 :           0 :              vxx = eigval(1)
     269                 :           0 :              vyy = eigval(2)
     270                 :             :           else
     271                 :           6 :              vzz = eigval(1)
     272                 :           6 :              vxx = eigval(3)
     273                 :           6 :              vyy = eigval(2)
     274                 :             :           end if
     275                 :           6 :           cq = vzz*quadmom(typat(iatom))*Ang_Bohr**2*Ha_THz*1.0D-2
     276         [ +  + ]:           6 :           if (abs(cq) > tol8) then
     277                 :           4 :             eta = abs(vxx-vyy)/abs(vzz)
     278                 :             :           else
     279                 :           2 :             eta = zero ! if Cq is small then eta is meaningless
     280                 :             :           end if
     281                 :           6 :           write(message,'(a,f9.4,a,f9.4)') '  Point charge Cq = ',cq,' MHz     eta = ',eta
     282                 :           6 :           call wrtout(ab_out,message,'COLL')
     283                 :           6 :           write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      point charge eigval (au) : ',&
     284                 :           6 :             & eigval(1),' ; (1.0E+21 V/m^2) : ',eigval(1)*efgsi21,ch10,&
     285                 :          12 :                &     '-         eigvec : ',matr(1,1),matr(2,1),matr(3,1)
     286                 :           6 :           call wrtout(ab_out,message,'COLL')
     287                 :           6 :           write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      point charge eigval (au) : ',&
     288                 :           6 :             & eigval(2),' ; (1.0E+21 V/m^2) : ',eigval(2)*efgsi21,ch10,&
     289                 :          12 :                &     '-         eigvec : ',matr(1,2),matr(2,2),matr(3,2)
     290                 :           6 :           call wrtout(ab_out,message,'COLL')
     291                 :           6 :           write(message,'(2a,f13.6,a,f16.8,a,a,3f13.6)')ch10,'      point charge eigval (au) : ',&
     292                 :           6 :             & eigval(3),' ; (1.0E+21 V/m^2) : ',eigval(3)*efgsi21,ch10,&
     293                 :          12 :                &     '-         eigvec : ',matr(1,3),matr(2,3),matr(3,3)
     294                 :           6 :           call wrtout(ab_out,message,'COLL')
     295                 :           6 :           write(message,'(a,a,3f13.6)')ch10,'      point charge efg : ',efg_point_charge(1,1,iatom),&
     296                 :          12 :                &     efg_point_charge(1,2,iatom),efg_point_charge(1,3,iatom)
     297                 :           6 :           call wrtout(ab_out,message,'COLL')
     298                 :           6 :           write(message,'(a,3f13.6)')'      point charge efg : ',efg_point_charge(2,1,iatom),&
     299                 :          12 :                &     efg_point_charge(2,2,iatom),efg_point_charge(2,3,iatom)
     300                 :           6 :           call wrtout(ab_out,message,'COLL')
     301                 :           6 :           write(message,'(a,3f13.6,a)')'      point charge efg : ',efg_point_charge(3,1,iatom),&
     302                 :          12 :                &     efg_point_charge(3,2,iatom),efg_point_charge(3,3,iatom),ch10
     303                 :           6 :           call wrtout(ab_out,message,'COLL')
     304                 :             :        end if
     305                 :             :     end do
     306                 :           9 :     write(message,'(3a)')ch10,ch10,ch10
     307                 :           9 :     call wrtout(ab_out,message,'COLL')
     308                 :             : 
     309         [ -  + ]:           9 :     ABI_FREE(efg_el)
     310         [ -  + ]:           9 :     ABI_FREE(efg_ion)
     311         [ -  + ]:           9 :     ABI_FREE(efg_paw)
     312         [ -  + ]:           9 :     ABI_FREE(efg_point_charge)
     313                 :             : 
     314                 :             :     !Destroy atom table used for parallelism
     315                 :           9 :     call free_my_atmtab(my_atmtab,my_atmtab_allocated)
     316                 :             : 
     317                 :             :     !DEBUG
     318                 :             :     !write(std_out,*)' calc_efg : exit '
     319                 :             :     !stop
     320                 :             :     !ENDDEBUG
     321                 :             : 
     322         [ -  + ]:           9 :   end subroutine calc_efg
     323                 :             : !!***
     324                 :             : 
     325                 :             : !!***
     326                 :             : !!****f* ABINIT/calc_fc
     327                 :             : !! NAME
     328                 :             : !! calc_fc
     329                 :             : !!
     330                 :             : !! FUNCTION
     331                 :             : !! calculation and output of Fermi-contact term at each atomic site
     332                 :             : !!
     333                 :             : !! INPUTS
     334                 :             : !!  mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
     335                 :             : !!  comm_atom=--optional-- MPI communicator over atoms
     336                 :             : !!  my_natom=number of atoms treated by current processor
     337                 :             : !!  natom=number of atoms in cell.
     338                 :             : !!  nspden=number of spin density components
     339                 :             : !!  ntypat=number of atom types
     340                 :             : !!  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
     341                 :             : !!  pawrhoij(natom) <type(pawrhoij_type)>= paw rhoij occupancies and related data
     342                 :             : !!  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
     343                 :             : !!  typat(natom)=type (integer) for each atom
     344                 :             : !!  usepaw=1 if PAW is activated
     345                 :             : !!
     346                 :             : !! OUTPUT
     347                 :             : !!  (only writing, printing)
     348                 :             : !!
     349                 :             : !! SIDE EFFECTS
     350                 :             : !!
     351                 :             : !!
     352                 :             : !! NOTES
     353                 :             : !!
     354                 :             : !! SOURCE
     355                 :             : 
     356                 :          10 :   subroutine calc_fc(my_natom,natom,nspden,ntypat,pawrad,pawrhoij,pawtab,typat,usepaw,&
     357   [ +  -  -  +  :           5 :        &                  mpi_atmtab,comm_atom) ! optional arguments (parallelism)
                   -  - ]
     358                 :             : 
     359                 :             :     !Arguments ------------------------------------
     360                 :             :     !scalars
     361                 :             :     integer,intent(in) :: my_natom,natom,nspden,ntypat,usepaw
     362                 :             :     integer,optional,intent(in) :: comm_atom
     363                 :             :     !arrays
     364                 :             :     integer,intent(in) :: typat(natom)
     365                 :             :     integer,optional,target,intent(in) :: mpi_atmtab(:)
     366                 :             :     type(pawrad_type),intent(in) :: pawrad(ntypat)
     367                 :             :     type(pawrhoij_type),intent(in) :: pawrhoij(my_natom)
     368                 :             :     type(pawtab_type),intent(in) :: pawtab(ntypat)
     369                 :             : 
     370                 :             :     !Local variables-------------------------------
     371                 :             :     !scalars
     372                 :             :     integer :: iatom,my_comm_atom
     373                 :             :     logical :: my_atmtab_allocated,paral_atom
     374                 :             :     character(len=500) :: message
     375                 :             :     !arrays
     376                 :           5 :     integer,pointer :: my_atmtab(:)
     377                 :           5 :     real(dp),allocatable :: fc(:,:)
     378                 :             : 
     379                 :             : !***********************************************************************
     380                 :             : 
     381                 :             :     !Compatibility tests
     382                 :           5 :     if (usepaw /= 1) then
     383                 :           0 :        message = ' usepaw /= 1 but Fermi-contact calculation requires PAW '
     384                 :           0 :        ABI_ERROR(message)
     385                 :             :     end if
     386                 :             : 
     387                 :             :     !Set up parallelism over atoms
     388   [ +  -  +  - ]:           5 :     paral_atom=(present(comm_atom).and.(my_natom/=natom))
     389         [ -  + ]:           5 :     nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
     390         [ +  - ]:           5 :     my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
     391                 :           5 :     call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
     392                 :             : 
     393                 :             :     !Initialization
     394   [ -  +  +  -  :          20 :     ABI_MALLOC(fc,(nspden,natom))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     395                 :             : 
     396                 :             :     !Computation
     397         [ -  + ]:           5 :     if (paral_atom) then
     398                 :             :        call make_fc_paw(fc,my_natom,natom,nspden,ntypat,pawrhoij,pawrad,pawtab,&
     399                 :           0 :             &   comm_atom=my_comm_atom,mpi_atmtab=my_atmtab)
     400                 :             :     else
     401                 :           5 :        call make_fc_paw(fc,my_natom,natom,nspden,ntypat,pawrhoij,pawrad,pawtab)
     402                 :             :     end if
     403                 :             : 
     404                 :             :     !Printing
     405                 :           5 :     write(message,'(a,a,a)' ) ch10,' Fermi-contact Term Calculation ',ch10
     406                 :           5 :     call wrtout(ab_out,message,'COLL')
     407                 :             : 
     408         [ +  + ]:          26 :     do iatom = 1, natom
     409         [ +  + ]:          26 :        if (nspden == 2) then
     410                 :           1 :           write(message,'(a,i3,a,i3,a,f12.4)') ' Atom ',iatom,', typat ',typat(iatom),': FC total = ',&
     411                 :           2 :                &     fc(1,iatom)+fc(2,iatom)
     412                 :           1 :           call wrtout(ab_out,message,'COLL')
     413                 :           1 :           write(message,'(a,i3,a,i3,a,f12.4)') ' Atom ',iatom,', typat ',typat(iatom),': FC up - down = ',&
     414                 :           2 :                &     fc(1,iatom)-fc(2,iatom)
     415                 :           1 :           call wrtout(ab_out,message,'COLL')
     416                 :             :        else
     417                 :          20 :           write(message,'(a,i3,a,i3,a,f12.4)') ' Atom ',iatom,', typat ',typat(iatom),': FC = ',&
     418                 :          40 :                &     fc(1,iatom)
     419                 :          20 :           call wrtout(ab_out,message,'COLL')
     420                 :             :        end if
     421                 :             :     end do
     422                 :             : 
     423                 :           5 :     write(message,'(3a)')ch10,ch10,ch10
     424                 :           5 :     call wrtout(ab_out,message,'COLL')
     425                 :             : 
     426                 :             :     !Memory deallocation
     427         [ -  + ]:           5 :     ABI_FREE(fc)
     428                 :             : 
     429                 :             :     !Destroy atom table used for parallelism
     430                 :           5 :     call free_my_atmtab(my_atmtab,my_atmtab_allocated)
     431                 :             : 
     432         [ -  + ]:           5 :   end subroutine calc_fc
     433                 :             : !!***
     434                 :             : 
     435                 :             : !!****f* ABINIT/make_efg_ion
     436                 :             : !! NAME
     437                 :             : !! make_efg_ion
     438                 :             : !!
     439                 :             : !! FUNCTION
     440                 :             : !! compute the electric field gradient due to ionic cores
     441                 :             : !!
     442                 :             : !! INPUTS
     443                 :             : !! natom, number of atoms in the unit cell
     444                 :             : !! nsym=number of symmetries in space group
     445                 :             : !! ntypat, the number of types of atoms in the unit cell
     446                 :             : !! rprimd(3,3), the matrix giving the transformation from crystal to cartesian coordinates
     447                 :             : !! symrel(3,3,nsym)=symmetry operators in terms of action on primitive translations
     448                 :             : !! tnons(3,nsym) = nonsymmorphic translations
     449                 :             : !! typat(natom), the type of each atom in the unit cell
     450                 :             : !! ucvol, the volume of the unit cell in atomic units
     451                 :             : !! xred(3,natom) the location of each atom in the cell in crystallographic coordinates
     452                 :             : !! zion(ntypat) the net charge on each type of atom
     453                 :             : !!
     454                 :             : !! OUTPUT
     455                 :             : !! efg(3,3,natom), the 3x3 efg tensors at each atomic site
     456                 :             : !!
     457                 :             : !! SIDE EFFECTS
     458                 :             : !!
     459                 :             : !! NOTES
     460                 :             : !! This routine computes the electric field gradient, specifically the components
     461                 :             : !! $\partial^2 V/\partial x_\alpha \partial x_\beta$ of the potential generated by the ionic cores,
     462                 :             : !! at each atomic site in the unit cell.
     463                 :             : !! Key references:
     464                 :             : !! Profeta, Mauri, and Pickard, ``Accurate first principles prediction of $^{17}$O NMR parameters in
     465                 :             : !! SiO$_2$: Assignment of the zeolite ferrierite spectrum'', J. Am. Chem. Soc. 125, 541--548 (2003) [[cite:Profeta2003]];
     466                 :             : !! A. Honma, ``Dipolar lattice-sums with applications to the exciton bands of anthracene crystal and
     467                 :             : !! the crystal field due to point charges'', J. Phys. Soc. Jpn. 42, 1129--1135 (1977) [[cite:Honma1977]];
     468                 :             : !! and Kresse and Joubert, ``From ultrasoft pseudopotentials to the projector augmented wave method'',
     469                 :             : !! Phys. Rev. B. 59, 1758--1775 (1999) [[cite:Kresse1999]]. In Kresse and Joubert's notation, the ionic cores are $n_{Zc}$;
     470                 :             : !! these charges are given by the net core charges on the pseudoatoms. Due to otherwise slow convergence,
     471                 :             : !! the sum over atoms is carried out by an Ewald method as detailed in the Honma reference, specifically
     472                 :             : !! his Eq. 4.8.
     473                 :             : !!
     474                 :             : !! SOURCE
     475                 :             : 
     476                 :          10 : subroutine make_efg_ion(efg,natom,nsym,ntypat,rprimd,symrel,tnons,typat,ucvol,xred,zion)
     477                 :             : 
     478                 :             :   !Arguments ------------------------------------
     479                 :             :   !scalars
     480                 :             :   integer,intent(in) :: natom,nsym,ntypat
     481                 :             :   real(dp) :: ucvol
     482                 :             :   !arrays
     483                 :             :   integer,intent(in) :: symrel(3,3,nsym),typat(natom)
     484                 :             :   real(dp),intent(in) :: rprimd(3,3),tnons(3,nsym)
     485                 :             :   real(dp),intent(in) :: zion(ntypat)
     486                 :             :   real(dp),intent(inout) :: xred(3,natom)
     487                 :             :   real(dp),intent(out) :: efg(3,3,natom)
     488                 :             :   !Local variables-------------------------------
     489                 :             :   !scalars
     490                 :             :   integer :: iatom,ishell,ii,jatom,jj,nshell,sx,sy,sz
     491                 :             :   real(dp) :: cph,dampfac,derfc_karg,derivs,gsq,karg
     492                 :             :   real(dp) :: lenrho,phase,qk,rlkcut,trace,xi0
     493                 :             :   real(dp) :: glkcut
     494                 :             :   !arrays
     495                 :             :   real(dp) :: cvec(3),gvec(3),gpl(3),gprimd(3,3)
     496                 :             :   real(dp) :: rhok(3),rhored(3),rpl(3)
     497                 :          10 :   real(dp),allocatable :: efg_g(:,:,:),efg_r(:,:,:)
     498                 :          10 :   real(dp),allocatable :: xcart(:,:)
     499                 :             : 
     500                 :             :   ! ************************************************************************
     501                 :             : 
     502                 :             :   !DEBUG
     503                 :             :   !write(std_out,*)' make_efg_ion : enter'
     504                 :             :   !ENDDEBUG
     505                 :             : 
     506   [ -  +  +  -  :          30 :   ABI_MALLOC(efg_g,(3,3,natom))
          +  -  +  -  -  
                +  -  + ]
     507   [ -  +  +  -  :          20 :   ABI_MALLOC(efg_r,(3,3,natom))
             -  +  -  + ]
     508   [ -  +  +  -  :          30 :   ABI_MALLOC(xcart,(3,natom))
          +  -  +  -  -  
                +  -  + ]
     509   [ +  +  +  +  :         621 :   efg(:,:,:) = zero ! final efg tensor
                   +  + ]
     510   [ +  +  +  +  :         621 :   efg_g(:,:,:) = zero ! part of tensor accumulated in G space
                   +  + ]
     511   [ +  +  +  +  :         621 :   efg_r(:,:,:) = zero ! part of tensor accumulated in R space
                   +  + ]
     512                 :             : 
     513                 :          10 :   call xred2xcart(natom,rprimd,xcart,xred) ! get atomic locations in cartesian coords
     514                 :             : 
     515         [ +  + ]:          40 :   do ii = 1, 3 ! generate the lengths of the unit cell edges in atomic units
     516                 :          40 :      rpl(ii) = sqrt(rprimd(1,ii)**2+rprimd(2,ii)**2+rprimd(3,ii)**2)
     517                 :             :   end do
     518   [ -  +  +  -  :          90 :   xi0 = sqrt(pi/(maxval(rpl)*minval(rpl))) ! this estimate for xi0 is from Honma's paper
          +  +  -  +  +  
                -  +  + ]
     519                 :             : 
     520                 :          10 :   call matr3inv(rprimd,gprimd) ! gprimd holds the inverse transpose of rprimd
     521                 :             :   !remember ordering: rprimd( (x_comp,y_comp,z_comp), (edge 1, edge 2, edge 3) )
     522                 :             :   !while gprimd( (edge 1, edge 2, edge 3),(x_comp, y_comp, z_comp) )
     523         [ +  + ]:          40 :   do ii = 1, 3 ! generate the lengths of the reciprocal cell edges
     524                 :          40 :      gpl(ii) = sqrt(gprimd(ii,1)**2+gprimd(ii,2)**2+gprimd(ii,3)**2)
     525                 :             :   end do
     526                 :             : 
     527                 :             :   !go out enough shells such that g**2/4*xi0**2 is of order 30
     528   [ -  +  +  -  :          50 :   nshell = int(anint(sqrt(30.0)*xi0/(pi*minval(gpl))))
                   +  + ]
     529   [ -  +  +  -  :          50 :   glkcut = (0.95*nshell*two*pi*minval(gpl))**2
                   +  + ]
     530                 :             : 
     531         [ +  + ]:          56 :   do ishell = 0, nshell ! loop over shells
     532         [ +  + ]:         270 :      do sx = -ishell, ishell
     533         [ +  + ]:        1586 :         do sy = -ishell, ishell
     534         [ +  + ]:       10874 :            do sz = -ishell, ishell
     535         [ +  + ]:       10660 :               if ( .not. (sx==0 .and. sy==0 .and. sz==0) ) then ! avoid origin
     536                 :             :                  !          constrain to be on shell surface, not interior
     537   [ +  +  +  +  :        9288 :                  if ( abs(sx)==ishell .or. abs(sy)==ishell .or. abs(sz)==ishell ) then
                   +  + ]
     538                 :        5736 :                     cvec(1)=sx;cvec(2)=sy;cvec(3)=sz
     539                 :             :                     !            make the g vector in cartesian coords
     540                 :        5736 :                     gvec(:) = zero
     541         [ +  + ]:       22944 :                     do ii = 1, 3
     542         [ +  + ]:       74568 :                        do jj = 1, 3
     543                 :       68832 :                           gvec(ii) = gvec(ii) + gprimd(ii,jj)*cvec(jj)*two*pi
     544                 :             :                        end do
     545                 :             :                     end do
     546         [ +  + ]:       22944 :                     gsq = dot_product(gvec,gvec)
     547         [ +  + ]:        5736 :                     if(gsq < glkcut) then
     548                 :        1200 :                        dampfac = exp(-gsq/(4.0*xi0*xi0)) ! see Honma eq. 4.8
     549         [ +  + ]:        7364 :                        do iatom = 1, natom
     550         [ +  + ]:       42576 :                           do jatom = 1, natom
     551                 :       35212 :                              qk = zion(typat(jatom)) ! charge on neighbor atom
     552         [ +  + ]:      140848 :                              rhok = xcart(:,jatom)-xcart(:,iatom)
     553         [ +  + ]:      140848 :                              phase = dot_product(gvec,rhok)
     554                 :       35212 :                              cph = cos(phase)
     555         [ +  + ]:      147012 :                              do ii = 1, 3
     556         [ +  + ]:      457756 :                                 do jj = 1, 3
     557                 :      316908 :                                    derivs = -3.0*gvec(ii)*gvec(jj)/gsq
     558         [ +  + ]:      316908 :                                    if (ii == jj) derivs = 1.0 + derivs
     559                 :             :                                    efg_g(ii,jj,iatom) = efg_g(ii,jj,iatom) + &
     560                 :      422544 :                                         &                       qk*cph*derivs*dampfac
     561                 :             :                                 end do ! end loop over jj
     562                 :             :                              end do ! end loop over ii
     563                 :             :                           end do ! end loop over jatom
     564                 :             :                        end do ! end loop over iatom
     565                 :             :                     end if ! constrain to gsq < glkcut
     566                 :             :                  end if ! end selection on shell edge
     567                 :             :               end if ! end avoidance of origin
     568                 :             :            end do ! end loop over sz
     569                 :             :         end do ! end loop over sy
     570                 :             :      end do ! end loop over sx
     571                 :             :   end do ! end loop over ishell
     572                 :             : 
     573                 :             :   !sum in real space begins here
     574                 :             : 
     575                 :             :   !go out enough shells such that (r*xi0)**2 is of order 30
     576   [ -  +  +  -  :          50 :   nshell = int(anint(sqrt(30.)/(minval(rpl)*xi0)))
                   +  + ]
     577   [ -  +  +  -  :          50 :   rlkcut = nshell*minval(rpl)*0.95
                   +  + ]
     578                 :             : !
     579                 :             :   !go out enough shells so that rlkcut is of order 30 bohr
     580                 :             :   !nshell=int(anint(30.0/minval(rpl)))
     581                 :             :   !rlkcut = 0.95*nshell*minval(rpl)
     582                 :             : 
     583         [ +  + ]:          56 :   do ishell = 0, nshell ! total set of cells to loop over
     584         [ +  + ]:         270 :      do sx = -ishell, ishell ! loop over all cells in each dimension
     585         [ +  + ]:        1586 :         do sy = -ishell, ishell
     586         [ +  + ]:       10874 :            do sz = -ishell, ishell
     587                 :             :               !        constrain to shell surface, not interior
     588   [ +  +  +  +  :       10660 :               if ( abs(sx)==ishell .or. abs(sy)==ishell .or. abs(sz)==ishell ) then
                   +  + ]
     589         [ +  + ]:       35763 :                  do jatom = 1, natom ! loop over atoms in shell cell
     590         [ +  + ]:      212250 :                     do iatom = 1, natom ! loop over atoms in central unit cell
     591   [ +  +  +  + ]:      202916 :                        if (.NOT. (jatom == iatom .AND. sx == 0 .AND. sy == 0 .AND. sz == 0)) then ! avoid self term
     592                 :      172852 :                           qk = zion(typat(jatom)) ! charge on each neighbor atom
     593                 :             :                           !                ! rhored is the vector in crystal coords from neighbor to target
     594                 :      172852 :                           rhored(1) = xred(1,jatom) + sx - xred(1,iatom)
     595                 :      172852 :                           rhored(2) = xred(2,jatom) + sy - xred(2,iatom)
     596                 :      172852 :                           rhored(3) = xred(3,jatom) + sz - xred(3,iatom)
     597                 :             :                           !                !  rhok is rhored in cartesian coords
     598                 :      172852 :                           rhok(1) = rprimd(1,1)*rhored(1)+rprimd(1,2)*rhored(2)+rprimd(1,3)*rhored(3)
     599                 :      172852 :                           rhok(2) = rprimd(2,1)*rhored(1)+rprimd(2,2)*rhored(2)+rprimd(2,3)*rhored(3)
     600                 :      172852 :                           rhok(3) = rprimd(3,1)*rhored(1)+rprimd(3,2)*rhored(2)+rprimd(3,3)*rhored(3)
     601         [ +  + ]:      691408 :                           trace = dot_product(rhok,rhok)
     602                 :      172852 :                           lenrho = sqrt(trace)
     603         [ +  + ]:      172852 :                           if (lenrho < rlkcut) then ! this restriction is critical as it ensures
     604                 :             :                              !                  ! that we sum over a sphere of atoms in real space
     605                 :             :                              !                  ! no matter what shape the unit cell has
     606                 :       24896 :                              karg = xi0*lenrho
     607                 :       24896 :                              derfc_karg = abi_derfc(karg)
     608                 :             :                              !                  see Honma eq. 2.10 for derivation of the following damping factor
     609                 :       24896 :                              dampfac = (1.0+3.0/(2.0*karg*karg))*exp(-karg*karg)+3.0*sqrt(pi)*derfc_karg/(4.0*karg**3)
     610         [ +  + ]:       99584 :                              do ii = 1, 3 ! loop over tensor elements
     611         [ +  + ]:      323648 :                                 do jj = 1, 3 ! loop over tensor elements
     612                 :      224064 :                                    derivs = -3.0*rhok(ii)*rhok(jj)/trace
     613         [ +  + ]:      224064 :                                    if(ii == jj) derivs = derivs + 1.0 ! see Honma eq 4.8 re: sign
     614                 :             :                                    !                      accumulate real space tensor element,
     615                 :             :                                    !                      weighted by charge of neighbor and Ewald damping factor
     616                 :      298752 :                                    efg_r(ii,jj,iatom) = efg_r(ii,jj,iatom) + qk*derivs*dampfac
     617                 :             :                                 end do ! end loop over jj in efg(ii,jj,iatom)
     618                 :             :                              end do ! end loop over ii in efg(ii,jj,iatom)
     619                 :             :                           end if ! end if statement restricting to a sphere of radius rlkcut
     620                 :             :                        end if ! end if statement avoiding the self atom term
     621                 :             :                     end do ! end loop over i atoms in cell
     622                 :             :                  end do ! end loop over j atoms in cell
     623                 :             :               end if ! end selection on outer shell of cells only
     624                 :             :            end do ! end loop over sz cells
     625                 :             :         end do ! end loop over sy cells
     626                 :             :      end do ! end loop over sx cells
     627                 :             :   end do ! end loop over shells
     628                 :             : 
     629                 :             :   !now combine the g-space and r-space parts, properly weighted (see Honma)
     630         [ +  + ]:          57 :   do iatom = 1, natom
     631         [ +  + ]:         198 :      do ii = 1, 3
     632         [ +  + ]:         611 :         do jj = 1, 3
     633                 :             :            efg(ii,jj,iatom) = four_pi*efg_g(ii,jj,iatom)/(three*ucvol)-&
     634                 :         564 :                 &       four*xi0**3*efg_r(ii,jj,iatom)/(three*sqrt(pi))
     635                 :             :            !      note extra factor of two: compare Honma eq. 4.6
     636                 :             :         end do
     637                 :             :      end do
     638                 :             :   end do
     639                 :             : 
     640                 :             :   ! symmetrize tensor at each atomic site using point symmetry operations
     641         [ +  + ]:          57 :   do iatom = 1, natom
     642                 :          57 :      call matpointsym(iatom,efg(:,:,iatom),natom,nsym,rprimd,symrel,tnons,xred)
     643                 :             :   end do
     644                 :             : 
     645         [ -  + ]:          10 :   ABI_FREE(efg_g)
     646         [ -  + ]:          10 :   ABI_FREE(efg_r)
     647         [ -  + ]:          10 :   ABI_FREE(xcart)
     648                 :             : 
     649                 :             :   !DEBUG
     650                 :             :   !write(std_out,*)' make_efg_ion : exit '
     651                 :             :   !stop
     652                 :             :   !ENDDEBUG
     653                 :             : 
     654                 :          10 : end subroutine make_efg_ion
     655                 :             : !!***
     656                 :             : 
     657                 :             : !!****f* ABINIT/make_efg_el
     658                 :             : !! NAME
     659                 :             : !! make_efg_el
     660                 :             : !!
     661                 :             : !! FUNCTION
     662                 :             : !! compute the electric field gradient due to electron density
     663                 :             : !!
     664                 :             : !! INPUTS
     665                 :             : !! mpi_enreg=information about MPI parallelization
     666                 :             : !! natom, number of atoms in unit cell
     667                 :             : !! nfft,ngfft(18), number of FFT points and details of FFT
     668                 :             : !! nhat(nfft,nspden) compensation charge density
     669                 :             : !! nspden, number of spin components
     670                 :             : !! nsym=number of symmetries in space group
     671                 :             : !! rhor(nfft,nspden), valence electron density, here $\tilde{n} + \hat{n}$
     672                 :             : !! rprimd(3,3), conversion from crystal coordinates to cartesian coordinates
     673                 :             : !! symrel(3,3,nsym)=symmetry operators in terms of action on primitive translations
     674                 :             : !! tnons(3,nsym) = nonsymmorphic translations
     675                 :             : !! xred(3,natom), location of atoms in crystal coordinates.
     676                 :             : !!
     677                 :             : !! OUTPUT
     678                 :             : !! efg(3,3,natom), the 3x3 efg tensor at each atomic site due to rhor
     679                 :             : !!
     680                 :             : !! NOTES
     681                 :             : !! This routine computes the electric field gradient, specifically the components
     682                 :             : !! $\partial^2 V/\partial x_\alpha \partial x_\beta$ of the potential generated by the valence
     683                 :             : !! electrons, at each atomic site in the unit cell. Key references: Kresse and Joubert, ``From
     684                 :             : !! ultrasoft pseudopotentials to the projector augmented wave method'', Phys. Rev. B. 59, 1758--1775 (1999) [[cite:Kresse1999]],
     685                 :             : !! and Profeta, Mauri, and Pickard, ``Accurate first principles prediction of $^{17}$O NMR parameters in
     686                 :             : !! SiO$_2$: Assignment of the zeolite ferrierite spectrum'', J. Am. Chem. Soc. 125, 541--548 (2003) [[cite:Profeta2003]]. This
     687                 :             : !! routine computes the second derivatives of the potential generated by $\tilde{n}$ (see Kresse and Joubert
     688                 :             : !! for notation, Fourier-transforming the density, doing the sum in G space, and then transforming back at
     689                 :             : !! each atomic site. The final formula is
     690                 :             : !! \begin{displaymath}
     691                 :             : !! \frac{\partial^2 V}{\partial x_\alpha\partial x_\beta} = -4\pi^2\sum_G (G_\alpha G_\beta - \delta_{\alpha,\beta}G^2/3)
     692                 :             : !! \left(\frac{\tilde{n}(G)}{\pi G^2}\right)e^{2\pi i G\cdot R}
     693                 :             : !! \end{displaymath}
     694                 :             : !!
     695                 :             : !!
     696                 :             : !! SOURCE
     697                 :             : 
     698                 :           9 : subroutine make_efg_el(efg,mpi_enreg,natom,nfft,ngfft,nhat,nspden,nsym,rhor,rprimd,symrel,tnons,xred)
     699                 :             : 
     700                 :             :   !Arguments ------------------------------------
     701                 :             :   !scalars
     702                 :             :   integer,intent(in) :: natom,nfft,nspden,nsym
     703                 :             :   type(MPI_type),intent(in) :: mpi_enreg
     704                 :             :   !arrays
     705                 :             :   integer,intent(in) :: ngfft(18),symrel(3,3,nsym)
     706                 :             :   real(dp),intent(in) :: nhat(nfft,nspden),rhor(nfft,nspden),rprimd(3,3),tnons(3,nsym),xred(3,natom)
     707                 :             :   real(dp),intent(out) :: efg(3,3,natom)
     708                 :             : 
     709                 :             :   !Local variables-------------------------------
     710                 :             :   !scalars
     711                 :             :   integer :: cplex,fftdir,fofg_index,iatom,i1,i2,i2_local,i23,i3,id1,id2,id3
     712                 :             :   integer :: ierr,ig,ig2,ig3,ii,ii1,ing,jj
     713                 :             :   integer :: me_fft,n1,n2,n3,nproc_fft,tim_fourdp
     714                 :             :   real(dp) :: cph,derivs,phase,sph,trace
     715                 :             :   ! type(MPI_type) :: mpi_enreg_seq
     716                 :             :   !arrays
     717                 :             :   integer :: id(3)
     718                 :           9 :   integer, contiguous, pointer :: fftn2_distrib(:),ffti2_local(:)
     719                 :           9 :   integer, contiguous, pointer :: fftn3_distrib(:),ffti3_local(:)
     720                 :             :   real(dp) :: gprimd(3,3),gqred(3),gvec(3),ratom(3)
     721                 :           9 :   real(dp),allocatable :: fofg(:,:),fofr(:),gq(:,:),xcart(:,:)
     722                 :             : 
     723                 :             :   ! ************************************************************************
     724                 :             : 
     725                 :             :   !DEBUG
     726                 :             :   !write(std_out,*)' make_efg_el : enter'
     727                 :             :   !ENDDEBUG
     728                 :             : 
     729   [ +  -  +  -  :          27 :   ABI_MALLOC(fofg,(2,nfft))
          +  -  -  +  -  
                      + ]
     730   [ -  +  +  -  :          27 :   ABI_MALLOC(fofr,(nfft))
          +  -  +  -  -  
                +  -  + ]
     731   [ -  +  +  -  :          27 :   ABI_MALLOC(xcart,(3,natom))
          +  -  +  -  -  
                +  -  + ]
     732                 :             : 
     733   [ +  +  +  +  :         542 :   efg(:,:,:) = zero
                   +  + ]
     734                 :           9 :   call xred2xcart(natom,rprimd,xcart,xred) ! get atomic locations in cartesian coords
     735                 :           9 :   call matr3inv(rprimd,gprimd)
     736                 :             : 
     737                 :           9 :   tim_fourdp = 0 ! timing code, not using
     738                 :           9 :   fftdir = -1 ! FT from R to G
     739                 :           9 :   cplex = 1 ! fofr is real
     740                 :             :   !here we are only interested in the valence pseudo charge density, which is rhor(:,1)-nhat(:,1)
     741                 :             :   !regardless of the value of nspden. This may change in the future depending on
     742                 :             :   !developments with noncollinear magnetization and so forth. Such a change will
     743                 :             :   !require an additional loop over nspden.
     744                 :             :   !Multiply by -1 to convert the electron particle density to the charge density
     745         [ +  + ]:      644537 :   fofr(:) = -(rhor(:,1)-nhat(:,1))
     746                 :             : 
     747                 :             :   ! Get the distrib associated with this fft_grid  See hartre.F90 for another example where
     748                 :             :   ! this is done
     749                 :           9 :   n1=ngfft(1); n2=ngfft(2); n3=ngfft(3)
     750                 :           9 :   nproc_fft = mpi_enreg%nproc_fft; me_fft = mpi_enreg%me_fft
     751                 :           9 :   call ptabs_fourdp(mpi_enreg,n2,n3,fftn2_distrib,ffti2_local,fftn3_distrib,ffti3_local)
     752                 :             : 
     753                 :           9 :   call fourdp(cplex,fofg,fofr,fftdir,mpi_enreg,nfft,1,ngfft,tim_fourdp) ! construct charge density in G space
     754                 :             : 
     755                 :             :   ! the following loops over G vectors has been copied from hartre.F90 in order to be compatible with
     756                 :             :   ! possible FFT parallelism
     757                 :             : 
     758                 :             :   ! In order to speed the routine, precompute the components of g
     759                 :             :   ! Also check if the booked space was large enough...
     760   [ -  +  +  -  :          27 :   ABI_MALLOC(gq,(3,max(n1,n2,n3)))
          +  -  +  -  -  
                +  -  + ]
     761         [ +  + ]:          36 :   do ii=1,3
     762                 :          27 :      id(ii)=ngfft(ii)/2+2
     763         [ +  + ]:        1084 :      do ing=1,ngfft(ii)
     764                 :        1048 :         ig=ing-(ing/id(ii))*ngfft(ii)-1
     765                 :        1075 :         gq(ii,ing)=ig
     766                 :             :      end do
     767                 :             :   end do
     768                 :           9 :   id1=n1/2+2;id2=n2/2+2;id3=n3/2+2
     769                 :             : 
     770                 :             :   ! Triple loop on each dimension
     771         [ +  + ]:         309 :   do i3=1,n3
     772                 :         300 :      ig3=i3-(i3/id3)*n3-1
     773                 :         300 :      gqred(3) = gq(3,i3)
     774                 :             : 
     775         [ +  + ]:       13853 :      do i2=1,n2
     776                 :       13544 :         ig2=i2-(i2/id2)*n2-1
     777         [ +  - ]:       13844 :         if (fftn2_distrib(i2) == me_fft) then
     778                 :             : 
     779                 :       13544 :            gqred(2) = gq(2,i2)
     780                 :       13544 :            i2_local = ffti2_local(i2)
     781                 :       13544 :            i23=n1*(i2_local-1 +(n2/nproc_fft)*(i3-1))
     782                 :             :            ! Do the test that eliminates the Gamma point outside of the inner loop
     783                 :       13544 :            ii1=1
     784         [ +  + ]:       13544 :            if(i23==0 .and. ig2==0 .and. ig3==0) ii1=2
     785                 :             : 
     786                 :             :            ! Final inner loop on the first dimension (note the lower limit)
     787         [ +  + ]:      658063 :            do i1=ii1,n1
     788                 :             :               !         gs=gs2+ gq(1,i1)*(gq(1,i1)*gmet(1,1)+gqg2p3)
     789                 :      644519 :               gqred(1) = gq(1,i1)
     790   [ +  +  +  + ]:     8378747 :               gvec(1:3) = MATMUL(gprimd,gqred)
     791                 :      644519 :               fofg_index=i1+i23
     792         [ +  + ]:     2578076 :               trace = dot_product(gvec,gvec)
     793         [ +  + ]:     2591620 :               do ii = 1, 3 ! sum over components of efg tensor
     794         [ +  + ]:     8378747 :                  do jj = 1, 3 ! sum over components of efg tensor
     795                 :     5800671 :                     derivs = gvec(ii)*gvec(jj) ! This term is $G_\alpha G_\beta$
     796         [ +  + ]:     5800671 :                     if (ii == jj) derivs = derivs - trace/three
     797         [ +  + ]:    34391427 :                     do iatom = 1, natom ! sum over atoms in unit cell
     798         [ +  + ]:   106628796 :                        ratom(:) = xcart(:,iatom) ! extract location of atom iatom
     799         [ +  + ]:   106628796 :                        phase = two_pi*dot_product(gvec,ratom) ! argument of $e^{2\pi i G\cdot R}$
     800                 :    26657199 :                        cph = cos(phase)
     801                 :    26657199 :                        sph = sin(phase)
     802                 :             :                        efg(ii,jj,iatom) = efg(ii,jj,iatom) - &
     803                 :    32457870 :                             &               four_pi*derivs*(fofg(1,fofg_index)*cph-fofg(2,fofg_index)*sph)/trace ! real part of efg tensor
     804                 :             :                     end do ! end loop over atoms in cell
     805                 :             :                  end do ! end loop over jj in V_ij
     806                 :             :               end do ! end loop over ii in V_ij
     807                 :             :            end do ! End loop on i1
     808                 :             :         end if
     809                 :             :      end do ! End loop on i2
     810                 :             :   end do ! End loop on i3
     811                 :             : 
     812                 :           9 :   call xmpi_sum(efg,mpi_enreg%comm_fft,ierr)
     813                 :             : 
     814                 :             :   ! symmetrize tensor at each atomic site using point symmetry operations
     815         [ +  + ]:          50 :   do iatom = 1, natom
     816                 :          50 :      call matpointsym(iatom,efg(:,:,iatom),natom,nsym,rprimd,symrel,tnons,xred)
     817                 :             :   end do
     818                 :             : 
     819         [ -  + ]:           9 :   ABI_FREE(fofg)
     820         [ -  + ]:           9 :   ABI_FREE(fofr)
     821         [ -  + ]:           9 :   ABI_FREE(xcart)
     822         [ -  + ]:           9 :   ABI_FREE(gq)
     823                 :             : 
     824                 :             :   !DEBUG
     825                 :             :   !write(std_out,*)' make_efg_el : exit '
     826                 :             :   !stop
     827                 :             :   !ENDDEBUG
     828                 :             : 
     829         [ -  + ]:           9 : end subroutine make_efg_el
     830                 :             : !!***
     831                 :             : 
     832                 :             : end module m_nucprop
     833                 :             : !!***
        

Generated by: LCOV version 2.3-1