TABLE OF CONTENTS
ABINIT/mknucdipmom_k [ Functions ]
NAME
mknucdipmom_k
FUNCTION
compute Hamiltonian in reciprocal space due to array of nuclear dipole moments, at a given k point
COPYRIGHT
Copyright (C) 1998-2018 ABINIT group 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
gmet(3,3)=metric for reciprocal space vectors kg(3,npw)=reduced planewave coordinates at current k point kpt(3)=current k point, reduced coordinates natom=number of atoms in cell nucdipmom(3,natom)=nuclear dipole moment vectors, at each atom npw=number of planewaves rprimd(3,3)=real space translation vectors ucvol=unit cell volume xred(3,natom)=location of atoms in unit cell, in reduced coordinates
OUTPUT
nucdipmom_k(npw*(npw+1)/2) = nuclear dipole moment Hamiltonian matrix, in lower diagonal Hermitian packed storage, at current k point
SIDE EFFECTS
NOTES
PARENTS
vtorho
CHILDREN
SOURCE
42 #if defined HAVE_CONFIG_H 43 #include "config.h" 44 #endif 45 46 #include "abi_common.h" 47 48 49 subroutine mknucdipmom_k(gmet,kg,kpt,natom,nucdipmom,nucdipmom_k,npw,rprimd,ucvol,xred) 50 51 use defs_basis 52 use m_profiling_abi 53 54 !This section has been created automatically by the script Abilint (TD). 55 !Do not modify the following lines by hand. 56 #undef ABI_FUNC 57 #define ABI_FUNC 'mknucdipmom_k' 58 !End of the abilint section 59 60 implicit none 61 62 !Arguments ------------------------------------ 63 !scalars 64 integer,intent(in) :: natom,npw 65 real(dp),intent(in) :: ucvol 66 67 !arrays 68 integer,intent(in) :: kg(3,npw) 69 real(dp),intent(in) :: gmet(3,3),kpt(3),nucdipmom(3,natom),rprimd(3,3),xred(3,natom) 70 complex(dpc),intent(out) :: nucdipmom_k(npw*(npw+1)/2) 71 72 !Local variables------------------------------- 73 !scalars 74 integer :: atom_nd_tot,col,iatom,ndp_index,row 75 real(dp) :: crossfac,dg2,permeability,phasefac 76 complex(dpc) :: cpermfac,cphasefac 77 !arrays 78 integer :: atom_nd(natom) 79 real(dp) :: cprod(3),cprod_cart(3),dgp_red(3), gpk_red(3) 80 81 ! ************************************************************************* 82 ! 83 84 ! magnetic permeability mu_0/four_pi in atomic units 85 ! this constant is also used in m_pawdij.F90/pawdijnd, if you change it here, 86 ! change it there also for consistency 87 permeability=5.325135453D-5 88 ! will need 4*pi*i*(\mu_0/four\pi) 89 cpermfac = CMPLX(zero,four_pi*permeability) 90 91 ! make list of atoms with non-zero nuclear magnetic dipoles 92 atom_nd_tot = 0 93 do iatom = 1, natom 94 if(any(abs(nucdipmom(:,iatom))>tol8)) then 95 atom_nd_tot = atom_nd_tot + 1 96 atom_nd(atom_nd_tot) = iatom 97 end if 98 end do 99 100 ndp_index = 0 101 do col=1,npw ! enumerate plane waves G 102 ! form k + G at this k point for current plane wave (this is the ket |k+G> ) 103 ! in reduced coordinates 104 gpk_red(1)=dble(kg(1,col))+kpt(1) 105 gpk_red(2)=dble(kg(2,col))+kpt(2) 106 gpk_red(3)=dble(kg(3,col))+kpt(3) 107 108 do row=col,npw ! enumerate lower diagonal from 1 to G 109 ! index of the current matrix element, in lower triangular packed storage 110 ! "packed sequentially, column by column" 111 ndp_index = ndp_index + 1 112 nucdipmom_k(ndp_index) = czero 113 114 ! form G-G' = \Delta G at this k pt (this is the bra <k+G'| ) 115 ! in reduced coordinates 116 dgp_red(1)=dble(kg(1,col)-kg(1,row)) 117 dgp_red(2)=dble(kg(2,col)-kg(2,row)) 118 dgp_red(3)=dble(kg(3,col)-kg(3,row)) 119 120 ! compute |\Delta G|^2 121 ! must use gmet metric because G's are in reduced coords in reciprocal space 122 dg2 = DOT_PRODUCT(dgp_red,MATMUL(gmet,dgp_red)) 123 ! if \Delta G = 0, Hamiltonian term is zero and move on to next one 124 if (abs(dg2)<tol8) then 125 nucdipmom_k(ndp_index)=czero 126 cycle 127 end if 128 129 ! compute cross product \Delta G \times (k + G) 130 ! notice that \Delta G and (k + G) are in reduced coords in reciprocal space 131 cprod(1) = dgp_red(2)*gpk_red(3) - dgp_red(3)*gpk_red(2) 132 cprod(2) = dgp_red(3)*gpk_red(1) - dgp_red(1)*gpk_red(3) 133 cprod(3) = dgp_red(1)*gpk_red(2) - dgp_red(2)*gpk_red(1) 134 135 ! proper cross product must account for reduced coords as follows: 136 ! gprimd*dgp \times gprimd*gpk = (det gprimd)*(gprimd^{-1,T})*(dgp \times gpk) 137 ! = rprimd * (dgp \times gpk)/ucvol 138 ! final vector also includes the division by |\Delta G|^2 139 cprod_cart = MATMUL(rprimd,cprod)/(ucvol*dg2) 140 141 ! loop over the atoms with non-zero nuclear dipoles 142 ! phase factors exp(i*\Delta G*I) where I is ion position, 143 ! might be retrievable from ph1d, need to check 144 do iatom = 1, atom_nd_tot 145 phasefac = two_pi*DOT_PRODUCT(dgp_red,xred(:,atom_nd(iatom))) 146 cphasefac = CMPLX(cos(phasefac),sin(phasefac)) 147 crossfac = DOT_PRODUCT(nucdipmom(:,iatom),cprod_cart) 148 nucdipmom_k(ndp_index) = nucdipmom_k(ndp_index) + cpermfac*cphasefac*crossfac 149 end do ! end loop over atoms with nonzero dipoles 150 151 end do ! end loop over G' = G to npw 152 153 end do ! end loop over G = 1 to npw 154 155 end subroutine mknucdipmom_k