TABLE OF CONTENTS


ABINIT/make_efg_ion [ Functions ]

[ Top ] [ Functions ]

NAME

 make_efg_ion

FUNCTION

 compute the electric field gradient due to ionic cores

COPYRIGHT

 Copyright (C) 2005-2018 ABINIT group (JJ)
 This file is distributed under the terms of the
 GNU General Public License, see ~ABINIT/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

INPUTS

 natom, number of atoms in the unit cell
 nsym=number of symmetries in space group
 ntypat, the number of types of atoms in the unit cell
 rprimd(3,3), the matrix giving the transformation from crystal to cartesian coordinates
 symrel(3,3,nsym)=symmetry operators in terms of action on primitive translations
 tnons(3,nsym) = nonsymmorphic translations
 typat(natom), the type of each atom in the unit cell
 ucvol, the volume of the unit cell in atomic units
 xred(3,natom) the location of each atom in the cell in crystallographic coordinates
 zion(ntypat) the net charge on each type of atom

OUTPUT

 efg(3,3,natom), the 3x3 efg tensors at each atomic site

SIDE EFFECTS

NOTES

 This routine computes the electric field gradient, specifically the components
 $\partial^2 V/\partial x_\alpha \partial x_\beta$ of the potential generated by the ionic cores,
 at each atomic site in the unit cell.
 Key references:
 Profeta, Mauri, and Pickard, ``Accurate first principles prediction of $^{17}$O NMR parameters in
 SiO$_2$: Assignment of the zeolite ferrierite spectrum'', J. Am. Chem. Soc. 125, 541--548 (2003);
 A. Honma, ``Dipolar lattice-sums with applications to the exciton bands of anthracene crystal and
 the crystal field due to point charges'', J. Phys. Soc. Jpn. 42, 1129--1135 (1977);
 and Kresse and Joubert, ``From ultrasoft pseudopotentials to the projector augmented wave method'',
 Phys. Rev. B. 59, 1758--1775 (1999). In Kresse and Joubert's notation, the ionic cores are $n_{Zc}$;
 these charges are given by the net core charges on the pseudoatoms. Due to otherwise slow convergence,
 the sum over atoms is carried out by an Ewald method as detailed in the Honma reference, specifically
 his Eq. 4.8.

PARENTS

      calc_efg

CHILDREN

      matpointsym,matr3inv,xred2xcart

SOURCE

 55 #if defined HAVE_CONFIG_H
 56 #include "config.h"
 57 #endif
 58 
 59 #include "abi_common.h"
 60 
 61 subroutine make_efg_ion(efg,natom,nsym,ntypat,rprimd,symrel,tnons,typat,ucvol,xred,zion)
 62 
 63  use defs_basis
 64  use m_profiling_abi
 65 
 66  use m_geometry,       only : xred2xcart
 67  use m_special_funcs,  only : abi_derfc
 68 
 69 !This section has been created automatically by the script Abilint (TD).
 70 !Do not modify the following lines by hand.
 71 #undef ABI_FUNC
 72 #define ABI_FUNC 'make_efg_ion'
 73  use interfaces_32_util
 74  use interfaces_45_geomoptim
 75 !End of the abilint section
 76 
 77  implicit none
 78 
 79 !Arguments ------------------------------------
 80 !scalars
 81  integer,intent(in) :: natom,nsym,ntypat
 82  real(dp) :: ucvol
 83 !arrays
 84  integer,intent(in) :: symrel(3,3,nsym),typat(natom)
 85  real(dp),intent(in) :: rprimd(3,3),tnons(3,nsym)
 86  real(dp),intent(in) :: zion(ntypat)
 87  real(dp),intent(inout) :: xred(3,natom)
 88  real(dp),intent(out) :: efg(3,3,natom)
 89 !Local variables-------------------------------
 90 !scalars
 91  integer :: iatom,ishell,ii,jatom,jj,nshell,sx,sy,sz
 92  real(dp) :: cph,dampfac,derfc_karg,derivs,gsq,karg
 93  real(dp) :: lenrho,phase,qk,rlkcut,trace,xi0
 94  real(dp) :: glkcut
 95 !arrays
 96  real(dp) :: cvec(3),gvec(3),gpl(3),gprimd(3,3)
 97  real(dp) :: rhok(3),rhored(3),rpl(3)
 98  real(dp),allocatable :: efg_g(:,:,:),efg_r(:,:,:)
 99  real(dp),allocatable :: xcart(:,:)
100 
101 ! ************************************************************************
102 
103 !DEBUG
104 !write(std_out,*)' make_efg_ion : enter'
105 !ENDDEBUG
106 
107  ABI_ALLOCATE(efg_g,(3,3,natom))
108  ABI_ALLOCATE(efg_r,(3,3,natom))
109  ABI_ALLOCATE(xcart,(3,natom))
110  efg(:,:,:) = zero ! final efg tensor
111  efg_g(:,:,:) = zero ! part of tensor accumulated in G space
112  efg_r(:,:,:) = zero ! part of tensor accumulated in R space
113 
114  call xred2xcart(natom,rprimd,xcart,xred) ! get atomic locations in cartesian coords
115 
116  do ii = 1, 3 ! generate the lengths of the unit cell edges in atomic units
117    rpl(ii) = sqrt(rprimd(1,ii)**2+rprimd(2,ii)**2+rprimd(3,ii)**2)
118  end do
119  xi0 = sqrt(pi/(maxval(rpl)*minval(rpl))) ! this estimate for xi0 is from Honma's paper
120 
121  call matr3inv(rprimd,gprimd) ! gprimd holds the inverse transpose of rprimd
122 !remember ordering: rprimd( (x_comp,y_comp,z_comp), (edge 1, edge 2, edge 3) )
123 !while gprimd( (edge 1, edge 2, edge 3),(x_comp, y_comp, z_comp) )
124  do ii = 1, 3 ! generate the lengths of the reciprocal cell edges
125    gpl(ii) = sqrt(gprimd(ii,1)**2+gprimd(ii,2)**2+gprimd(ii,3)**2)
126  end do
127 
128 !go out enough shells such that g**2/4*xi0**2 is of order 30
129  nshell = int(anint(sqrt(30.0)*xi0/(pi*minval(gpl))))
130  glkcut = (0.95*nshell*two*pi*minval(gpl))**2
131 
132  do ishell = 0, nshell ! loop over shells
133    do sx = -ishell, ishell
134      do sy = -ishell, ishell
135        do sz = -ishell, ishell
136          if ( .not. (sx==0 .and. sy==0 .and. sz==0) ) then ! avoid origin
137 !          constrain to be on shell surface, not interior
138            if ( abs(sx)==ishell .or. abs(sy)==ishell .or. abs(sz)==ishell ) then
139              cvec(1)=sx;cvec(2)=sy;cvec(3)=sz
140 !            make the g vector in cartesian coords
141              gvec(:) = zero
142              do ii = 1, 3
143                do jj = 1, 3
144                  gvec(ii) = gvec(ii) + gprimd(ii,jj)*cvec(jj)*two*pi
145                end do
146              end do
147              gsq = dot_product(gvec,gvec)
148              if(gsq < glkcut) then
149                dampfac = exp(-gsq/(4.0*xi0*xi0)) ! see Honma eq. 4.8
150                do iatom = 1, natom
151                  do jatom = 1, natom
152                    qk = zion(typat(jatom)) ! charge on neighbor atom
153                    rhok = xcart(:,jatom)-xcart(:,iatom)
154                    phase = dot_product(gvec,rhok)
155                    cph = cos(phase)
156                    do ii = 1, 3
157                      do jj = 1, 3
158                        derivs = -3.0*gvec(ii)*gvec(jj)/gsq
159                        if (ii == jj) derivs = 1.0 + derivs
160                        efg_g(ii,jj,iatom) = efg_g(ii,jj,iatom) + &
161 &                       qk*cph*derivs*dampfac
162                      end do ! end loop over jj
163                    end do ! end loop over ii
164                  end do ! end loop over jatom
165                end do ! end loop over iatom
166              end if ! constrain to gsq < glkcut
167            end if ! end selection on shell edge
168          end if ! end avoidance of origin
169        end do ! end loop over sz
170      end do ! end loop over sy
171    end do ! end loop over sx
172  end do ! end loop over ishell
173 
174 !sum in real space begins here
175 
176 !go out enough shells such that (r*xi0)**2 is of order 30
177  nshell = int(anint(sqrt(30.)/(minval(rpl)*xi0)))
178  rlkcut = nshell*minval(rpl)*0.95
179 !
180 !go out enough shells so that rlkcut is of order 30 bohr
181 !nshell=int(anint(30.0/minval(rpl)))
182 !rlkcut = 0.95*nshell*minval(rpl)
183 
184  do ishell = 0, nshell ! total set of cells to loop over
185    do sx = -ishell, ishell ! loop over all cells in each dimension
186      do sy = -ishell, ishell
187        do sz = -ishell, ishell
188 !        constrain to shell surface, not interior
189          if ( abs(sx)==ishell .or. abs(sy)==ishell .or. abs(sz)==ishell ) then
190            do jatom = 1, natom ! loop over atoms in shell cell
191              do iatom = 1, natom ! loop over atoms in central unit cell
192                if (.NOT. (jatom == iatom .AND. sx == 0 .AND. sy == 0 .AND. sz == 0)) then ! avoid self term
193                  qk = zion(typat(jatom)) ! charge on each neighbor atom
194 !                ! rhored is the vector in crystal coords from neighbor to target
195                  rhored(1) = xred(1,jatom) + sx - xred(1,iatom)
196                  rhored(2) = xred(2,jatom) + sy - xred(2,iatom)
197                  rhored(3) = xred(3,jatom) + sz - xred(3,iatom)
198 !                !  rhok is rhored in cartesian coords
199                  rhok(1) = rprimd(1,1)*rhored(1)+rprimd(1,2)*rhored(2)+rprimd(1,3)*rhored(3)
200                  rhok(2) = rprimd(2,1)*rhored(1)+rprimd(2,2)*rhored(2)+rprimd(2,3)*rhored(3)
201                  rhok(3) = rprimd(3,1)*rhored(1)+rprimd(3,2)*rhored(2)+rprimd(3,3)*rhored(3)
202                  trace = dot_product(rhok,rhok)
203                  lenrho = sqrt(trace)
204                  if (lenrho < rlkcut) then ! this restriction is critical as it ensures
205 !                  ! that we sum over a sphere of atoms in real space
206 !                  ! no matter what shape the unit cell has
207                    karg = xi0*lenrho
208                    derfc_karg = abi_derfc(karg)
209 !                  see Honma eq. 2.10 for derivation of the following damping factor
210                    dampfac = (1.0+3.0/(2.0*karg*karg))*exp(-karg*karg)+3.0*sqrt(pi)*derfc_karg/(4.0*karg**3)
211                    do ii = 1, 3 ! loop over tensor elements
212                      do jj = 1, 3 ! loop over tensor elements
213                        derivs = -3.0*rhok(ii)*rhok(jj)/trace
214                        if(ii == jj) derivs = derivs + 1.0 ! see Honma eq 4.8 re: sign
215 !                      accumulate real space tensor element,
216 !                      weighted by charge of neighbor and Ewald damping factor
217                        efg_r(ii,jj,iatom) = efg_r(ii,jj,iatom) + qk*derivs*dampfac
218                      end do ! end loop over jj in efg(ii,jj,iatom)
219                    end do ! end loop over ii in efg(ii,jj,iatom)
220                  end if ! end if statement restricting to a sphere of radius rlkcut
221                end if ! end if statement avoiding the self atom term
222              end do ! end loop over i atoms in cell
223            end do ! end loop over j atoms in cell
224          end if ! end selection on outer shell of cells only
225        end do ! end loop over sz cells
226      end do ! end loop over sy cells
227    end do ! end loop over sx cells
228  end do ! end loop over shells
229 
230 !now combine the g-space and r-space parts, properly weighted (see Honma)
231  do iatom = 1, natom
232    do ii = 1, 3
233      do jj = 1, 3
234        efg(ii,jj,iatom) = four_pi*efg_g(ii,jj,iatom)/(three*ucvol)-&
235 &       four*xi0**3*efg_r(ii,jj,iatom)/(three*sqrt(pi))
236 !      note extra factor of two: compare Honma eq. 4.6
237      end do
238    end do
239  end do
240 
241 ! symmetrize tensor at each atomic site using point symmetry operations
242  do iatom = 1, natom
243    call matpointsym(iatom,efg(:,:,iatom),natom,nsym,rprimd,symrel,tnons,xred)
244  end do
245 
246  ABI_DEALLOCATE(efg_g)
247  ABI_DEALLOCATE(efg_r)
248  ABI_DEALLOCATE(xcart)
249 
250 !DEBUG
251 !write(std_out,*)' make_efg_ion : exit '
252 !stop
253 !ENDDEBUG
254 
255  end subroutine make_efg_ion