Initial release (previously developed against tag QE-3-1-1 in directory

NMR_new).


git-svn-id: http://qeforge.qe-forge.org/svn/q-e/trunk/espresso@3662 c92efa57-630b-4861-b058-cf58834340f0
This commit is contained in:
seitsonen 2007-01-15 11:29:24 +00:00
parent d9a096994a
commit f926db4ce1
21 changed files with 4564 additions and 0 deletions

107
GIPAW/Makefile Normal file
View File

@ -0,0 +1,107 @@
# Makefile for NMR_new
include ../make.sys
NMROBJS = \
nmr_module.o \
magn_main.o \
stop_code.o \
apply_p.o \
apply_vel.o \
greenfunction.o \
h_psiq.o \
ch_psi_all.o \
sym_cart_tensor.o \
symmetrize_field.o \
test_sum_rule.o \
compute_u_kq.o \
suscept_crystal.o \
j_para.o \
biot_savart.o \
compute_sigma_bare.o \
init_us_2_no_phase.o \
init_paw_2_no_phase.o \
g_tensor_crystal.o \
write_tensor_field.o
MODULES = \
../Modules/atom.o \
../Modules/autopilot.o \
../Modules/basic_algebra_routines.o \
../Modules/bfgs_module.o \
../Modules/berry_phase.o \
../Modules/cell_base.o \
../Modules/check_stop.o \
../Modules/clocks.o \
../Modules/constants.o \
../Modules/constraints_module.o \
../Modules/control_flags.o \
../Modules/electrons_base.o \
../Modules/fft_base.o \
../Modules/fft_scalar.o \
../Modules/fft_types.o \
../Modules/functionals.o \
../Modules/input_parameters.o \
../Modules/io_files.o \
../Modules/io_global.o \
../Modules/ions_base.o \
../Modules/ions_nose.o \
../Modules/kind.o \
../Modules/metadyn_base.o \
../Modules/metadyn_io.o \
../Modules/metadyn_vars.o \
../Modules/mp_global.o \
../Modules/mp_wave.o \
../Modules/mp.o \
../Modules/parallel_include.o \
../Modules/parameters.o \
../Modules/parser.o \
../Modules/path_base.o \
../Modules/path_formats.o \
../Modules/path_variables.o \
../Modules/path_opt_routines.o \
../Modules/path_io_routines.o \
../Modules/path_reparametrisation.o \
../Modules/printout_base.o \
../Modules/pseudo_types.o \
../Modules/ptoolkit.o \
../Modules/random_numbers.o \
../Modules/read_cards.o \
../Modules/read_namelists.o \
../Modules/read_uspp.o \
../Modules/read_upf.o \
../Modules/recvec.o \
../Modules/splinelib.o \
../Modules/stick_base.o \
../Modules/shmem_include.o \
../Modules/task_groups.o \
../Modules/timestep.o \
../Modules/uspp.o \
../Modules/version.o \
../Modules/wavefunctions.o \
../Modules/wave_base.o \
../Modules/xml_io_base.o
PWOBJS = ../PW/libpw.a
PHOBJS = ../PH/libph.a
TLDEPS=bindir ph pw mods libs libiotk
all : tldeps magn.x
magn.x : $(NMROBJS) $(PWOBJS) $(PHOBJS) $(LIBOBJS)
$(MPIF90) $(LDFLAGS) -o $@ \
$(NMROBJS) $(MODULES) $(PHOBJS) $(PWOBJS) $(LIBOBJS) $(LIBS)
- ( cd ../bin; ln -fs ../NMR_new/$@ . )
tldeps:
test -n "$(TLDEPS)" && ( cd .. ; $(MAKE) $(MFLAGS) $(TLDEPS) || exit 1) || :
clean :
- /bin/rm -f magn.x *.o *~ *.F90 *.d *.mod *.i work.pc
include make.depend
# DO NOT DELETE

45
GIPAW/apply_p.f90 Normal file
View File

@ -0,0 +1,45 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE apply_p(psi, p_psi, ik, ipol, q)
!-----------------------------------------------------------------------
!
! ... Apply the kinetic part of the velocity operator
! ... |p_psi> = (G+k+q/2)_{ipol} |psi>
!
USE kinds, ONLY : DP
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE pwcom
USE nmr_module
!-- parameters ---------------------------------------------------------
IMPLICIT none
INTEGER, INTENT(IN) :: ik ! k-point
INTEGER, INTENT(IN) :: ipol ! cartesian direction (1..3)
REAL(DP), INTENT(IN) :: q(3)
COMPLEX(DP), INTENT(IN) :: psi(npwx,nbnd)
COMPLEX(DP), INTENT(OUT) :: p_psi(npwx,nbnd)
!-- local variables ----------------------------------------------------
REAL(DP) :: gk
INTEGER :: ig, ibnd
call start_clock('apply_p')
do ibnd = 1, nbnd_occ(ik)
do ig = 1, npw
gk = xk(ipol,ik) + g(ipol,igk(ig)) + q(ipol)
p_psi(ig,ibnd) = gk * tpiba * psi(ig,ibnd)
enddo
enddo
call stop_clock('apply_p')
END SUBROUTINE apply_p

293
GIPAW/apply_vel.f90 Normal file
View File

@ -0,0 +1,293 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE apply_vel(psi, vel_psi, ik, ipol, q)
!-----------------------------------------------------------------------
!
! ... Apply the velocity operator
! ... v = p + dV^{NL}_{k+q,k}/dk
! ...
! ... Here we use Hartree atomic units, so that:
! ... V^{NL} => V^{NL} * ryd_to_hartree
!-----------------------------------------------------------------------
USE kinds, ONLY : DP
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE becmod, ONLY : becp
USE pwcom
USE nmr_module
!-- paramters ----------------------------------------------------------
IMPLICIT NONE
INTEGER, INTENT(IN) :: ipol ! cartesian direction (1..3)
INTEGER, INTENT(IN) :: ik ! k-point
COMPLEX(DP), INTENT(IN) :: psi(npwx,nbnd)
COMPLEX(DP), INTENT(OUT) :: vel_psi(npwx,nbnd)
REAL(DP), INTENT(IN) :: q(3)
!-- local variables ----------------------------------------------------
real(dp), parameter :: ryd_to_hartree = 0.5d0
complex(dp), allocatable :: aux(:,:), vkb_save(:,:)
real(dp) :: dk, dxk(3)
integer :: isign
logical :: q_is_zero
! first apply p
call apply_p(psi, vel_psi, ik, ipol, q)
call start_clock('apply_vel')
! set dk
dk = q_nmr/2.d0
! if no projectors, return
if (nkb == 0) return
! check if |q| is zero
q_is_zero = .false.
if (sqrt(q(1)*q(1)+q(2)*q(2)+q(3)*q(3)) < 1d-8) q_is_zero = .true.
! allocate temporary arrays, save old NL-potential
allocate(aux(npwx,nbnd), vkb_save(npwx,nkb))
vkb_save = vkb
#if 1
!====================================================================
! compute (1/2|dk|) ( V^{NL}_{k+dk+q,k+dk} |psi> -
! V^{NL}_{k-dk+q,k-dk} |psi> )
!====================================================================
do isign = -1,1,2
dxk(:) = xk(:,ik)
dxk(ipol) = dxk(ipol) + isign * dk ! k + dk
! compute <\beta(k \pm dk)| and project on |psi>
call init_us_2_no_phase(npw, igk, dxk, vkb)
call ccalbec (nkb, npwx, npw, nbnd_occ(ik), becp, vkb, psi)
! |q|!=0 => compute |\beta(k \pm dk + q)>
if (.not. q_is_zero) then
dxk(:) = dxk(:) + q(:)
call init_us_2_no_phase(npw, igk, dxk, vkb)
endif
! apply |\beta(k \pm dk+q)>D<\beta(k \pm dk)| to |psi>
aux = (0.d0,0.d0)
call add_vuspsi(npwx, npw, nbnd_occ(ik), psi, aux)
vel_psi = vel_psi + dble(isign) * ryd_to_hartree * aux/(2.d0*dk*tpiba)
enddo
#else
do isign = -1,1,2
! compute <\beta(k)| and project on |psi>
call init_us_2_no_phase(npw, igk, xk(1,ik), vkb)
call ccalbec (nkb, npwx, npw, nbnd_occ(ik), becp, vkb, psi)
dxk(ipol) = xk(ipol,ik) + isign * dk ! k + dk
call init_us_2_no_phase(npw, igk, dxk, vkb)
! apply |\beta(k \pm dk+q)>D<\beta(k)| to |psi>
aux = (0.d0,0.d0)
call add_vuspsi(npwx, npw, nbnd_occ(ik), psi, aux)
vel_psi = vel_psi + 0.5*dble(isign) * ryd_to_hartree * aux/(2.d0*dk*tpiba)
! compute <\beta(k \pm dk)| and project on |psi>
dxk(:) = xk(:,ik)
dxk(ipol) = dxk(ipol) + isign * dk ! k + dk
call init_us_2_no_phase(npw, igk, xk(1,ik), vkb)
call ccalbec (nkb, npwx, npw, nbnd_occ(ik), becp, vkb, psi)
dxk(:) = xk(:,ik)
call init_us_2_no_phase(npw, igk, dxk, vkb)
! apply |\beta(k+q)>D<\beta(k \pm dk)| to |psi>
aux = (0.d0,0.d0)
call add_vuspsi(npwx, npw, nbnd_occ(ik), psi, aux)
vel_psi = vel_psi + 0.5*dble(isign) * ryd_to_hartree * aux/(2.d0*dk*tpiba)
enddo
#endif
! restore NL-potential at k
vkb = vkb_save
! free memory
deallocate(aux, vkb_save)
call stop_clock('apply_vel')
END SUBROUTINE apply_vel
! Here are some previous and testing version of the subroutine
! it looks like that the analytic derivative has some troubles.
!
! The numerical one (that computes just |dbeta/dk>) is just fine
! but is is more involved that the routine above.
#if 0
real(DP), allocatable :: gk (:,:)
complex(DP), allocatable :: ps2(:,:,:), dvkb (:,:), dvkb1 (:,:), &
work (:,:), becp2(:,:), becp1(:,:), aux(:,:), vkb_save(:,:)
complex(DP), external :: ZDOTC
integer :: ig, na, ibnd, ikb, jkb, nt, ih, jh, ijkb0
integer :: isign
real(DP) :: axis(3)
do ibnd = 1, nbnd_occ(ik)
print*, ibnd
print '(2(F12.6,2X))', vel_psi(1:5,ibnd)
print*
enddo
!!!vl_psi = 0.d0
! this is the old routine, applying |beta><dbeta/dk| + |dbeta/dk><beta|
! compute (k+G)/|k+G|
allocate (gk(3,npwx))
do ig = 1, npw
gk (1, ig) = (xk (1, ik) + g (1, igk (ig) ) ) * tpiba
gk (2, ig) = (xk (2, ik) + g (2, igk (ig) ) ) * tpiba
gk (3, ig) = (xk (3, ik) + g (3, igk (ig) ) ) * tpiba
g2kin (ig) = gk (1, ig) **2 + gk (2, ig) **2 + gk (3, ig) **2
if (g2kin (ig) < 1.0d-10) then
gk (1, ig) = 0.d0
gk (2, ig) = 0.d0
gk (3, ig) = 0.d0
else
gk (1, ig) = gk (1, ig) / sqrt (g2kin (ig) )
gk (2, ig) = gk (2, ig) / sqrt (g2kin (ig) )
gk (3, ig) = gk (3, ig) / sqrt (g2kin (ig) )
endif
enddo
! allocate variable for the derivative of the beta's
allocate(dvkb(npwx,nkb), dvkb1(npwx,nkb))
dvkb = (0.d0,0.d0)
dvkb1 = (0.d0,0.d0)
work = (0.d0,0.d0)
! and this is the contribution from nonlocal pseudopotentials
axis = 0.d0; axis(ipol) = 1.d0
!!!call gen_us_dy (ik, at (1, ipol), dvkb1)
call gen_us_dy (ik, axis(1), dvkb1)
call gen_us_dj (ik, dvkb)
print*, dvkb1(2,:)
jkb = 0
do nt = 1, ntyp
do na = 1, nat
if (nt == ityp (na)) then
do ikb = 1, nh (nt)
jkb = jkb + 1
do ig = 1, npw
!!!work (ig,jkb) = dvkb1 (ig, jkb) + dvkb (ig, jkb) * &
!!! (at (1, ipol) * gk (1, ig) + &
!!! at (2, ipol) * gk (2, ig) + &
!!! at (3, ipol) * gk (3, ig) )
work (ig,jkb) = dvkb1 (ig, jkb) + dvkb (ig, jkb) * gk(ipol,ig)
enddo
enddo
endif
enddo
enddo
work(1,3) = (0.d0,-0.133684d0)
jkb = 3
write(98,'(2F12.6,2X))') work(:,jkb)
print*
! this was the previous numerical derivative
!allocate(dvkb(npwx,nkb), dvkb1(npwx,nkb))
dvkb = (0.d0,0.d0)
dvkb1 = (0.d0,0.d0)
work = (0.d0,0.d0)
vel_psi = 0.d0
! compute it by finite differences
work = (0.d0,0.d0)
dxk(:) = xk(:,ik); dxk(ipol) = dxk(ipol) + dk
call init_us_2(npw,igk,dxk,work)
dxk(:) = xk(:,ik); dxk(ipol) = dxk(ipol) - dk
call init_us_2(npw,igk,dxk,dvkb)
work(:,:) = work(:,:) - dvkb(:,:)
work = 0.5d0 * work / (dk * tpiba)
write(99,'(2F12.6,2X))') work(:,jkb)
print*
allocate( becp2(nkb,nbnd), becp1(nkb,nbnd))
becp2(:,:) = (0.d0,0.d0)
becp1(:,:) = (0.d0,0.d0)
call ccalbec (nkb, npwx, npw, nbnd, becp2, work, psi)
call init_us_2(npw,igk,xk(1,ik),vkb)
call ccalbec (nkb, npwx, npw, nbnd, becp1, vkb, psi)
ijkb0 = 0
allocate (ps2 ( nkb, nbnd, 2))
ps2(:,:,:)=(0.d0,0.d0)
do nt = 1, ntyp
do na = 1, nat
if (nt == ityp (na)) then
do ih = 1, nh (nt)
ikb = ijkb0 + ih
do jh = 1, nh (nt)
jkb = ijkb0 + jh
do ibnd = 1, nbnd_occ(ik)
!! CHECK factor (-1.d0,0.d0)
!!!ps2(ikb,ibnd,1) = ps2(ikb,ibnd,1)+ becp2(jkb,ibnd)* &
!!! (-1.d0,0.d0) * (deeq(ih,jh,na,current_spin) &
!!! -et(ibnd,ik)*qq(ih,jh,nt))
!!!ps2(ikb,ibnd,2) = ps2(ikb,ibnd,2) +becp1(jkb,ibnd,ik) * &
!!! (-1.d0,0.d0) * (deeq(ih,jh,na,current_spin)&
!!! -et(ibnd,ik)*qq(ih,jh,nt))
ps2(ikb,ibnd,1) = ps2(ikb,ibnd,1) + becp2(jkb,ibnd)* &
(1.d0,0.d0) * deeq(ih,jh,na,current_spin)
ps2(ikb,ibnd,2) = ps2(ikb,ibnd,2) + becp1(jkb,ibnd) * &
(1.d0,0.d0) * deeq(ih,jh,na,current_spin)
enddo
enddo
enddo
ijkb0=ijkb0+nh(nt)
end if
end do
end do
if (ikb /= nkb .OR. jkb /= nkb) call errore ('apply_vel', 'unexpected error',1)
!print*, 'ps2(:,:,1)='
!print*, ps2(:,:,1)
!print*, 'ps2(:,:,2)='
!print*, ps2(:,:,2)
CALL ZGEMM( 'N', 'N', npw, nbnd_occ(ik), nkb, &
(1.d0,0.d0), vkb(1,1), npwx, ps2(1,1,1), nkb, (1.d0,0.d0), &
vel_psi(1,1), npwx )
CALL ZGEMM( 'N', 'N', npw, nbnd_occ(ik), nkb, &
(1.d0,0.d0), work(1,1), npwx, ps2(1,1,2), nkb, (1.d0,0.d0), &
vel_psi(1,1), npwx )
do ibnd = 1, nbnd_occ(ik)
print*, ibnd
print '(2(F12.6,2X))', vel_psi(1:5,ibnd)
print*
enddo
STOP
deallocate (ps2)
deallocate (gk)
#endif

95
GIPAW/biot_savart.f90 Normal file
View File

@ -0,0 +1,95 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE biot_savart(jpol)
!-----------------------------------------------------------------------
!
! ... Compute the induced magentic field via the Biot-Savart law
! ... B_ind(r) = (1/c) \int d^3r' j(r') (r-r')/|r-r'|
! ... which in reciprocal space reads:
! ... B_ind(G) = (4\pi/c) (i G \times j(G))/G^2
! ... the G=0 is not computed here and is given by chi_bare
USE kinds, ONLY : DP
USE constants, ONLY : fpi
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE gvect, ONLY : ngm, gstart, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nl, nlm, g, gg, ecutwfc, gcutm
USE pwcom
USE nmr_module
!-- parameters ---------------------------------------------------------
IMPLICIT none
INTEGER, INTENT(IN) :: jpol
!-- local variables ----------------------------------------------------
COMPLEX(DP), allocatable :: aux(:), j_of_g(:,:)
REAL(DP) :: gk
complex(dp) :: fact
INTEGER :: ig, ipol, ispin
call start_clock('biot_savart')
! allocate memory
allocate(aux(nrxxs), j_of_g(1:ngm,3))
! transform current to reciprocal space
j_of_g(:,:) = 0.d0
do ispin = 1, nspin
do ipol = 1, 3
aux(1:nrxxs) = j_bare(1:nrxxs,ipol,jpol,ispin)
call cft3s(aux, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, -1)
j_of_g(1:ngm,ipol) = j_of_g(1:ngm,ipol) + aux(nl(1:ngm))
enddo
enddo
! compute induced field in reciprocal space
do ig = gstart, ngm
fact = (0.d0,1.d0) * (fpi/c) / (gg(ig) * tpiba)
b_ind(ig,1,jpol) = fact * (g(2,ig)*j_of_g(ig,3) - g(3,ig)*j_of_g(ig,2))
b_ind(ig,2,jpol) = fact * (g(3,ig)*j_of_g(ig,1) - g(1,ig)*j_of_g(ig,3))
b_ind(ig,3,jpol) = fact * (g(1,ig)*j_of_g(ig,2) - g(2,ig)*j_of_g(ig,1))
enddo
! transform induced field in real space
do ipol = 1, 3
aux = (0.d0,0.d0)
aux(nl(1:ngm)) = b_ind(1:ngm,ipol,jpol)
call cft3s(aux, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 1)
b_ind_r(1:nrxxs,ipol,jpol) = real(aux(1:nrxxs))
enddo
deallocate(aux, j_of_g)
call stop_clock('biot_savart')
END SUBROUTINE biot_savart
SUBROUTINE field_to_reciprocal_space
USE kinds, ONLY : DP
USE gvect, ONLY : ngm, gstart, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nl, nlm, g, gg, ecutwfc, gcutm
USE pwcom
USE nmr_module
IMPLICIT NONE
complex(dp), allocatable :: aux(:)
integer :: ipol, jpol
allocate(aux(nrxxs))
b_ind(:,:,:) = 0.d0
do ipol = 1, 3
do jpol = 1, 3
aux(1:nrxxs) = b_ind_r(1:nrxxs,ipol,jpol)
call cft3s(aux, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, -1)
b_ind(1:ngm,ipol,jpol) = aux(nl(1:ngm))
enddo
enddo
deallocate(aux)
END SUBROUTINE field_to_reciprocal_space

107
GIPAW/ch_psi_all.f90 Normal file
View File

@ -0,0 +1,107 @@
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
subroutine ch_psi_all (n, h, ah, e, ik, m)
!-----------------------------------------------------------------------
!
! This routine applies the operator ( H - \epsilon S + alpha_pv P_v)
! to a vector h. The result is given in Ah.
!
#include "f_defs.h"
use pwcom
use becmod
USE kinds, only : DP
USE nmr_module
implicit none
integer :: n, m, ik
! input: the dimension of h
! input: the number of bands
! input: the k point
real(DP) :: e (m)
! input: the eigenvalue
complex(DP) :: h (npwx, m), ah (npwx, m)
! input: the vector
! output: the operator applied to the vector
!
! local variables
!
integer :: ibnd, ikq, ig
! counter on bands
! the point k+q
! counter on G vetors
complex(DP), allocatable :: ps (:,:), hpsi (:,:), spsi (:,:)
! scalar products
! the product of the Hamiltonian and h
! the product of the S matrix and h
call start_clock ('ch_psi')
allocate (ps ( nbnd , m))
allocate (hpsi( npwx , m))
allocate (spsi( npwx , m))
hpsi (:,:) = (0.d0, 0.d0)
spsi (:,:) = (0.d0, 0.d0)
!
! compute the product of the hamiltonian with the h vector
!
call h_psiq (npwx, n, m, h, hpsi, spsi)
call start_clock ('last')
!
! then we compute the operator H-epsilon S
!
do ibnd = 1, m
do ig = 1, n
ah (ig, ibnd) = hpsi (ig, ibnd) - e (ibnd) * spsi (ig, ibnd)
enddo
enddo
!
! Here we compute the projector in the valence band
!
!!!if (lgamma) then
ikq = ik
!!!else
!!! ikq = 2 * ik
!!!endif
ps (:,:) = (0.d0, 0.d0)
call ZGEMM ('C', 'N', nbnd_occ (ikq) , m, n, (1.d0, 0.d0) , evq, &
npwx, spsi, npwx, (0.d0, 0.d0) , ps, nbnd)
ps (:,:) = ps(:,:) * alpha_pv
#ifdef __PARA
call reduce (2 * nbnd * m, ps)
#endif
hpsi (:,:) = (0.d0, 0.d0)
call ZGEMM ('N', 'N', n, m, nbnd_occ (ikq) , (1.d0, 0.d0) , evq, &
npwx, ps, nbnd, (1.d0, 0.d0) , hpsi, npwx)
spsi(:,:) = hpsi(:,:)
!
! And apply S again
!
call ccalbec (nkb, npwx, n, m, becp, vkb, hpsi)
call s_psi (npwx, n, m, hpsi, spsi)
do ibnd = 1, m
do ig = 1, n
ah (ig, ibnd) = ah (ig, ibnd) + spsi (ig, ibnd)
enddo
enddo
deallocate (spsi)
deallocate (hpsi)
deallocate (ps)
call stop_clock ('last')
call stop_clock ('ch_psi')
return
end subroutine ch_psi_all

View File

@ -0,0 +1,178 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE compute_sigma_bare(chi_bare, sigma_bare)
!-----------------------------------------------------------------------
!
! ... Compute the bare contribution to the chemical shift at the
! ... position of the nuclei, given the induced field
USE kinds, ONLY : DP
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE gvect, ONLY : ngm, gstart, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nl, nlm, g, gg, ecutwfc, gcutm
USE ions_base, ONLY : nat, tau, atm, ityp
USE io_global, ONLY : stdout
USE symme, ONLY : s, nsym, irt
USE pwcom
USE nmr_module
! Arguments
REAL(DP), INTENT(IN) :: chi_bare(3,3)
real(dp), intent(out) :: sigma_bare(3,3,nat)
! Local
integer :: na, ig
real(dp) :: macroscopic_shape(3,3)
real(dp) :: arg, tr_sigma
complex(dp) :: tmp_sigma(3,3)
macroscopic_shape(:,:) = 2.0_dp/3.0_dp
! like in paratec:
macroscopic_shape(:,:) = 0.0_dp
do na = 1, 3
macroscopic_shape(na,na) = 2.0_dp/3.0_dp
enddo
write(stdout,'(5X,''NMR chemical bare shifts in ppm:'')')
write(stdout,*)
do na = 1, nat
tmp_sigma(:,:) = 0.0_dp
do ig = gstart, ngm
arg = (g(1,ig)*tau(1,na) + g(2,ig)*tau(2,na) + g(3,ig)*tau(3,na)) * tpi
tmp_sigma(:,:) = tmp_sigma(:,:) &
+ b_ind(ig,:,:) * cmplx(cos(arg),sin(arg))
enddo
#if 1
! this is the G = 0 term
if (gstart == 2) then
tmp_sigma(:,:) = tmp_sigma(:,:) &
- (4.0_dp*pi) * macroscopic_shape(:,:) * chi_bare(:,:) !*TMPTMPTMP
end if
#endif
sigma_bare(:,:,na) = real(tmp_sigma(:,:))
enddo
#ifdef __PARA
call reduce(9*na, sigma_bare)
#endif
#if 0
! symmetrize tensors ??
do na = 1, nat
call trntns (sigma_bare(1,1,na), at, bg, -1)
enddo
call symz(sigma_bare, nsym, s, nat, irt)
do na = 1, nat
call trntns (sigma_bare(1,1,na), at, bg, 1)
enddo
#endif
do na = 1, nat
tr_sigma = (sigma_bare(1,1,na)+sigma_bare(2,2,na)+sigma_bare(3,3,na))/3.0_dp
write(stdout,'(5X,''Atom'',I3,2X,A3,'' pos: ('',3(F10.6),&
'') sigma: '',F14.4)') na, atm(ityp(na)), tau(:,na), tr_sigma*1e6_dp
write(stdout, tens_fmt) sigma_bare(:,:,na) * 1e6_dp
enddo
end subroutine compute_sigma_bare
!-----------------------------------------------------------------------
SUBROUTINE compute_sigma_diamagnetic( sigma_diamagnetic )
!-----------------------------------------------------------------------
!
! ... Compute the diamagnetic contribution to the chemical shift at the
! ... position of the nuclei, given the induced field
USE kinds, ONLY : DP
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE gvect, ONLY : ngm, gstart, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nl, nlm, g, gg, ecutwfc, gcutm
USE ions_base, ONLY : nat, tau, atm, ityp
USE io_global, ONLY : stdout
USE symme, ONLY : s, nsym, irt
USE pwcom
USE nmr_module
! Arguments
real(dp), intent(inout) :: sigma_diamagnetic(3,3,nat)
! Local
integer :: na
real(dp) :: tr_sigma
write(stdout,'(5X,''NMR chemical diamagnetic shifts in ppm:'')')
write(stdout,*)
! symmetrize tensors
do na = 1, nat
call trntns (sigma_diamagnetic(1,1,na), at, bg, -1)
enddo
call symz(sigma_diamagnetic, nsym, s, nat, irt)
do na = 1, nat
call trntns (sigma_diamagnetic(1,1,na), at, bg, 1)
enddo
do na = 1, nat
tr_sigma = (sigma_diamagnetic(1,1,na)+sigma_diamagnetic(2,2,na) &
+sigma_diamagnetic(3,3,na))/3.0_dp
write(stdout,'(5X,''Atom'',I3,2X,A3,'' pos: ('',3(F10.6),&
'') sigma: '',F14.4)') na, atm(ityp(na)), tau(:,na), tr_sigma*1e6_dp
write(stdout, tens_fmt) sigma_diamagnetic(:,:,na) * 1e6_dp
enddo
end subroutine compute_sigma_diamagnetic
!-----------------------------------------------------------------------
SUBROUTINE compute_sigma_paramagnetic( sigma_paramagnetic )
!-----------------------------------------------------------------------
!
! ... Compute the paramagnetic contribution to the chemical shift at the
! ... position of the nuclei, given the induced field
USE kinds, ONLY : DP
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk
USE gvect, ONLY : ngm, gstart, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nl, nlm, g, gg, ecutwfc, gcutm
USE ions_base, ONLY : nat, tau, atm, ityp
USE io_global, ONLY : stdout
USE symme, ONLY : s, nsym, irt
USE pwcom
USE nmr_module
! Arguments
real(dp), intent(inout) :: sigma_paramagnetic(3,3,nat)
! Local
integer :: na
real(dp) :: tr_sigma
write(stdout,'(5X,''NMR chemical paramagnetic shifts in ppm:'')')
write(stdout,*)
! symmetrize tensors
do na = 1, nat
call trntns (sigma_paramagnetic(1,1,na), at, bg, -1)
enddo
call symz(sigma_paramagnetic, nsym, s, nat, irt)
do na = 1, nat
call trntns (sigma_paramagnetic(1,1,na), at, bg, 1)
enddo
do na = 1, nat
tr_sigma = (sigma_paramagnetic(1,1,na)+sigma_paramagnetic(2,2,na) &
+sigma_paramagnetic(3,3,na))/3.0_dp
write(stdout,'(5X,''Atom'',I3,2X,A3,'' pos: ('',3(F10.6),&
'') sigma: '',F14.4)') na, atm(ityp(na)), tau(:,na), tr_sigma*1e6_dp
write(stdout, tens_fmt) sigma_paramagnetic(:,:,na) * 1e6_dp
enddo
end subroutine compute_sigma_paramagnetic

186
GIPAW/compute_u_kq.f90 Normal file
View File

@ -0,0 +1,186 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE compute_u_kq(ik, q)
!-----------------------------------------------------------------------
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE io_files, ONLY : nwordwfc, iunwfc
USE cell_base, ONLY : at, bg, omega, tpiba, tpiba2
USE wavefunctions_module, ONLY : evc
USE klist, ONLY : nkstot, xk
USE wvfct, ONLY : nbnd, nbndx, npwx, npw, igk, g2kin, current_k, btype
USE nmr_module
USE gvect, only: g,ngm,ecutwfc,ngl,nrxx, nr1, nr2, nr3, nrx1, nrx2, nrx3
USE uspp, ONLY : nkb, vkb, okvan
USE pwcom, ONLY : et
USE becmod, ONLY : becp
USE lsda_mod, ONLY : current_spin, lsda, isk
USE g_psi_mod, ONLY : h_diag, s_diag
USE scf, ONLY : vrs, vltot, vr
USE complex_diis_module
IMPLICIT NONE
INTEGER, INTENT(IN) :: ik
REAL(DP), INTENT(IN) :: q(3)
real(dp), allocatable :: etq(:)
real(dp) :: xk_plus_q(3)
integer :: ig, ntry, iter, notconv
real(dp) :: v_of_0
real(dp) :: avg_iter, dav_iter, cg_iter, ethr
integer :: diis_iter
logical :: lrot
integer, parameter :: max_cg_iter = 200
integer, parameter :: isolve = 0
integer, parameter :: david = 4
complex(dp) :: ZDOTC
CALL start_clock( 'u_kq' )
v_of_0 = SUM( vltot(1:nrxx) ) / DBLE( nr1 * nr2 * nr3 )
CALL reduce( 1, v_of_0 )
call gk_sort(xk(1,ik),ngm,g,ecutwfc/tpiba2,npw,igk,g2kin)
current_k = ik
if (lsda) current_spin = isk(ik)
xk_plus_q(:) = xk(:,ik) + q(:)
call init_us_2(npw,igk,xk_plus_q,vkb)
! ... read in wavefunctions from the SCF calculation at k
! ... and use it as a starting guess
CALL davcio( evc, nwordwfc, iunwfc, ik, -1 )
call ccalbec (nkb, npwx, npw, nbnd, becp, vkb, evc)
!g2kin(1:npw) = ( ( xk(1,ik) + g(1,igk(1:npw)) )**2 + &
! ( xk(2,ik) + g(2,igk(1:npw)) )**2 + &
! ( xk(3,ik) + g(3,igk(1:npw)) )**2 ) * tpiba2
!call h_psi(npwx, npw, nbnd, evc, evq)
!print*, ZDOTC(npw, evc(1,1), 1, evq(1,1), 1)*13.605692d0
!print*, ZDOTC(npw, evc(1,2), 1, evq(1,2), 1)*13.605692d0
! initial guess
evq = evc
! ... sets the kinetic energy
g2kin(1:npw) = ( ( xk_plus_q(1) + g(1,igk(1:npw)) )**2 + &
( xk_plus_q(2) + g(2,igk(1:npw)) )**2 + &
( xk_plus_q(3) + g(3,igk(1:npw)) )**2 ) * tpiba2
ALLOCATE( h_diag( npwx ) )
ALLOCATE( s_diag( npwx ) )
ALLOCATE(btype( nbnd, nkstot ) )
nbndx = nbnd
IF ( isolve == 0 ) nbndx = david * nbnd
btype(:,:) = 1
iter = 1
allocate(etq(1:nbndx))
ethr = conv_threshold
!====================================================================
! Diagonalize
!====================================================================
IF ( isolve == 1 ) THEN
! ... Conjugate-Gradient diagonalization
! ... h_diag is the precondition matrix
!!!call errore('compute_u_kq','CG not working properly?',-1)
h_diag = 1.D0
FORALL( ig = 1 : npw )
h_diag(ig) = 1.D0 + g2kin(ig) + SQRT( 1.D0 + ( g2kin(ig) - 1.D0 )**2 )
END FORALL
ntry = 0
CG_loop : DO
IF ( ntry > 0 ) THEN
CALL cinitcgg( npwx, npw, nbnd, nbnd, evq, evq, etq )
avg_iter = avg_iter + 1.D0
END IF
CALL ccgdiagg( npwx, npw, nbnd, evq, etq, btype(1,ik), &
h_diag, ethr, max_cg_iter, .true., &
notconv, cg_iter )
avg_iter = avg_iter + cg_iter
ntry = ntry + 1
print*, etq(:)*13.605692d0
! ... exit condition
IF ( test_exit_cond() ) EXIT CG_loop
END DO CG_loop
ELSE IF ( isolve == 2 ) THEN
! ... RMM-DIIS method
call errore('compute_u_kq','DIIS not working properly?',-1)
h_diag(1:npw) = g2kin(1:npw) + v_of_0
CALL usnldiag( h_diag, s_diag )
ntry = 0
RMMDIIS_loop: DO
CALL cdiisg( npw, npwx, nbnd, evq, etq, &
btype(1,ik), notconv, diis_iter, iter )
avg_iter = avg_iter + diis_iter
ntry = ntry + 1
! ... exit condition
IF ( test_exit_cond() ) EXIT RMMDIIS_loop
END DO RMMDIIS_loop
ELSE IF (isolve == 0) THEN
! ... Davidson diagonalization
! ... h_diag are the diagonal matrix elements of the
! ... hamiltonian used in g_psi to evaluate the correction
! ... to the trial eigenvectors
h_diag(1:npw) = g2kin(1:npw) + v_of_0
CALL usnldiag( h_diag, s_diag )
ntry = 0
david_loop: DO
lrot = ( iter == 1 )
CALL cegterg( npw, npwx, nbnd, nbndx, evq, ethr, &
okvan, etq, btype(1,ik), notconv, &
lrot, dav_iter )
avg_iter = avg_iter + dav_iter
ntry = ntry + 1
! ... exit condition
IF ( test_exit_cond() ) EXIT david_loop
END DO david_loop
!!!print '(4F8.4)', etq(1:nbnd)*13.605692d0
ELSE
call errore('compute_u_kq', 'diagonalization method?', -1)
END IF
IF ( notconv > MAX( 5, nbnd / 4 ) ) THEN
CALL errore( 'compute_u_kq', 'too many bands are not converged', 1 )
END IF
call stop_clock('u_kq')
DEALLOCATE( h_diag )
DEALLOCATE( s_diag )
DEALLOCATE(btype )
CONTAINS
FUNCTION test_exit_cond()
IMPLICIT NONE
LOGICAL :: test_exit_cond
test_exit_cond = ( ntry > 100 ) .OR. ( notconv <= 0 )
END FUNCTION test_exit_cond
END SUBROUTINE compute_u_kq

924
GIPAW/g_tensor_crystal.f90 Normal file
View File

@ -0,0 +1,924 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE g_tensor_crystal
!-----------------------------------------------------------------------
!
! ... Compute the "bare" susceptibility as in Eq.(64-65) of
! ... PRB 63, 245101 (2001)
! ... add more comments
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE io_files, ONLY : nwordwfc, iunwfc
USE cell_base, ONLY : at, bg, omega, tpiba, tpiba2
USE wavefunctions_module, ONLY : evc
USE klist, ONLY : nks, nkstot, wk, xk, nelec
USE wvfct, ONLY : nbnd, npwx, npw, igk, wg, g2kin, &
current_k
USE lsda_mod, ONLY : current_spin, lsda, isk, nspin
USE becmod, ONLY : becp
USE symme, ONLY : nsym, s, ftau
USE scf, ONLY : vr, vltot, rho
USE gvect, ONLY : ngm, nr1, nr2, nr3, nrx1, nrx2, &
nrx3, nrxx, nlm, g
USE mp_global, ONLY : my_pool_id
USE pwcom
USE nmr_module
!<apsi>
USE paw, ONLY: paw_vkb, paw_becp, paw_nkb, aephi, &
psphi, paw_nh, paw_nhtol, &
paw_nhtom, paw_indv, paw_nbeta
USE ions_base, ONLY : nat
!</apsi>
!-- local variables ----------------------------------------------------
IMPLICIT NONE
complex(dp), allocatable, dimension(:,:,:) :: p_evc, vel_evc, g_vel_evc
complex(dp), allocatable :: aux(:,:)
! Q tensor of eq. (65) (pGv => HH in Paratec, vGv => VV in Paratec)
real(dp) :: q_pGv(3,3,-1:1), q_vGv(3,3,-1:1)
! F tensor of eq. (64)
real(dp) :: f_pGv(3,3,-1:1), f_vGv(3,3,-1:1)
! chi_bare tensor of eq. (64)
real(dp) :: chi_bare_pGv(3,3), chi_bare_vGv(3,3)
! f-sum rule
real(dp) :: f_sum(3,3)
real(dp) :: q(3), braket, delta_rmc, gipaw_delta_rmc, rmc_gipaw
integer :: ia, ib, ik, ipol, jpol, i, ibnd, isign, ispin
complex(dp), external :: ZDOTC
integer :: s_maj, s_min
real(dp) :: e_hartree, charge, s_weight, rho_diff, d_omega
real(dp), allocatable :: grad_vr(:,:), v_local(:,:)
real(dp), allocatable :: grad_vh(:,:), vh(:)
real(dp), dimension ( 3, 3 ) :: delta_g_rmc, delta_g_bare, delta_g_soo, &
delta_g_soo_2, delta_g_paramagn, delta_g_diamagn, delta_g_total, &
delta_g_rmc_gipaw
real(dp) :: g_e = 2.0023192778_DP, g_prime, units_Ry2Ha = 0.5_DP
logical :: tevaluate_chi, tcalculate_correct_delta_g_soo
real(dp) :: diamagnetic_corr_tensor(3,3)
real(dp) :: paramagnetic_corr_tensor(3,3)
real(dp) :: sigma_paramagnetic(3,3)
!-----------------------------------------------------------------------
!<apsi> TMPTMPTMP Until the reconstruction has been implemented
delta_g_paramagn = 0.0_DP
delta_g_diamagn = 0.0_DP
!</apsi>
g_prime = 2 * ( g_e - 1 )
!<apsi> TMPTMPTMP Move to input or make it default?
tcalculate_correct_delta_g_soo = .true.
!</apsi>
if ( tcalculate_correct_delta_g_soo ) then
tevaluate_chi = .true.
else
tevaluate_chi = .false.
end if
! Select majority and minority spin components
rho_diff = SUM ( rho ( :, 1 ) - rho ( :, nspin ) )
if ( rho_diff > +1.0e-3 ) then
s_maj = 1
s_min = nspin
else if ( rho_diff < -1.0e-3 ) then
s_maj = nspin
s_min = 1
else
write ( stdout, * ) "WARNING: rho_diff zero!"
end if
! allocate memory
allocate ( p_evc(npwx,nbnd,3), vel_evc(npwx,nbnd,3), &
aux(npwx,nbnd), g_vel_evc(npwx,nbnd,3) )
! zero the Q tensors
q_pGv(:,:,:) = 0.0_dp
q_vGv(:,:,:) = 0.0_dp
! zero the current and the field
j_bare(:,:,:,:) = (0.0_dp,0.0_dp)
b_ind(:,:,:) = (0.0_dp,0.0_dp)
delta_rmc = 0.0_DP
gipaw_delta_rmc = 0.0_DP
write(stdout, '(5X,''Computing the magnetic susceptibility'')')
!====================================================================
! loop over k-points
!====================================================================
do ik = 1, nks
#ifdef __PARA
if (my_pool_id == 0) &
write(*, '(5X,''k-point #'',I5,'' of '',I5,'' (my_pool_id='',I3)') &
ik, nks, my_pool_id
#else
write(*, '(5X,''k-point #'',I5,'' of '',I5)') ik, nks
#endif
current_k = ik
current_spin = isk(ik)
if ( current_spin == s_maj ) then
s_weight = +1
else
s_weight = -1
end if
! initialize at k-point k
call gk_sort(xk(1,ik), ngm, g, ecutwfc/tpiba2, npw, igk, g2kin)
g2kin(:) = g2kin(:) * tpiba2
call init_us_2(npw,igk,xk(1,ik),vkb)
! read wfcs from file and compute becp
call davcio (evc, nwordwfc, iunwfc, ik, -1)
call ccalbec (nkb, npwx, npw, nbnd, becp, vkb, evc)
!<apsi>
call init_paw_2_no_phase (npw, igk, xk (1, ik), paw_vkb)
call ccalbec (paw_nkb, npwx, npw, nbnd, paw_becp, paw_vkb, evc)
diamagnetic_corr_tensor = 0.0
call diamagnetic_correction ( diamagnetic_corr_tensor )
delta_g_diamagn = delta_g_diamagn + s_weight * diamagnetic_corr_tensor
!</apsi>
! this is the case q = 0 (like the case of the f-sum rule)
q(:) = 0.0_dp
!!!write(*,'(''q='',3(F12.4))') q
call compute_u_kq(ik, q)
evc = evq
do ibnd = 1, nbnd_occ(ik)
delta_rmc = delta_rmc - s_weight &
* wg(ibnd,ik) * SUM ( g2kin(:) * conjg(evc(:,ibnd)) * evc(:,ibnd) )
end do
CALL relativistic_mass_correction ( rmc_gipaw )
write(6,*) "CCC: ", rmc_gipaw
gipaw_delta_rmc = gipaw_delta_rmc - s_weight * rmc_gipaw
! compute p_k|evc>, v_k|evc> and G_k v_{k,k}|evc>
call apply_operators
!------------------------------------------------------------------
! f-sum rule (pGv term only)
!------------------------------------------------------------------
do ia = 1, 3
do ib = 1, 3
do ibnd = 1, nbnd_occ(ik)
braket = 2.0_dp*real(ZDOTC(npw, p_evc(1,ibnd,ia), 1, &
g_vel_evc(1,ibnd,ib), 1), DP)
f_sum(ia,ib) = f_sum(ia,ib) + wg(ibnd,ik) * braket
enddo
enddo
enddo
#ifdef __PARA
call reduce(9, f_sum)
#endif
!------------------------------------------------------------------
! pGv and vGv contribution to chi_{bare}
!------------------------------------------------------------------
if ( tevaluate_chi ) then
do i = 1, 3
call add_to_tensor(q_pGv(:,:,0), p_evc, g_vel_evc)
call add_to_tensor(q_vGv(:,:,0), vel_evc, g_vel_evc)
enddo
end if
!------------------------------------------------------------------
! loop over -q and +q
!------------------------------------------------------------------
do isign = -1, 1, 2
! loop over cartesian directions
do i = 1, 3
if (iverbosity > 10) then
write(stdout,*) " QQQ: ", i * isign
end if
! set the q vector
q(:) = 0.0_dp
q(i) = real(isign,dp) * q_nmr
!!!write(*,'(''q='',3(F12.4))') q
! compute the wfcs at k+q
call compute_u_kq(ik, q)
! compute p_k|evc>, v_k|evc> and G_{k+q} v_{k+q,k}|evc>
call apply_operators
!<apsi>
call init_paw_2_no_phase (npw, igk, xk(:,ik)+q(:), paw_vkb)
call paramagnetic_correction ( paramagnetic_corr_tensor )
paramagnetic_corr_tensor = paramagnetic_corr_tensor * s_weight
call add_to_sigma_para ( paramagnetic_corr_tensor, delta_g_paramagn )
!</apsi>
if ( tevaluate_chi ) then
! pGv and vGv contribution to chi_bare
call add_to_tensor(q_pGv(:,:,isign), p_evc, g_vel_evc)
call add_to_tensor(q_vGv(:,:,isign), vel_evc, g_vel_evc)
end if
! now the j_bare term
call add_to_current(j_bare(:,:,:,current_spin), evc, g_vel_evc)
enddo ! i
enddo ! isign
enddo ! ik
! TODO: put a lot of poolreduce here
#ifdef __PARA
call poolreduce(9, f_sum)
call poolreduce(9, q_pGv)
call poolreduce(9, q_vGv)
! TODO: non working yet in parallel!!!
#endif
!====================================================================
! print out results
!====================================================================
write(stdout,'(5X,''End of magnetic susceptibility calculation'',/)')
! f-sum rule
if (iverbosity > 0) then
write(stdout, '(5X,''f-sum rule:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') f_sum
endif
call sym_cart_tensor(f_sum)
write(stdout, '(5X,''f-sum rule (symmetrized):'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') f_sum
!--------------------------------------------------------------------
! now get the current, induced field and delta_g
!--------------------------------------------------------------------
chi_bare_pGv(:,:) = chi_bare_pGv(:,:) / omega
j_bare(:,:,:,:) = j_bare(:,:,:,:) / (2.0_dp * q_nmr * tpiba * c * omega)
! either you symmetrize the current ...
do ispin = 1, nspin
call symmetrize_field(j_bare(:,:,:,ispin),1)
end do
!
! calculate the susceptibility
!
! F_{ij} = (2 - \delta_{ij}) Q_{ij}
if ( tevaluate_chi ) then
do ipol = 1, 3
do jpol = 1, 3
f_pGv(ipol,jpol,:) = 2.0_dp*q_pGv(ipol,jpol,:)
if (ipol == jpol) f_pGv(ipol,jpol,:) = q_pGv(ipol,jpol,:)
f_vGv(ipol,jpol,:) = 2.0_dp*q_vGv(ipol,jpol,:)
if (ipol == jpol) f_vGv(ipol,jpol,:) = q_vGv(ipol,jpol,:)
enddo
enddo
! compute chi_bare both pGv and vGv terms
chi_bare_pGv(:,:) = f_pGv(:,:,1) - 2.0_dp*f_pGv(:,:,0) + f_pGv(:,:,-1)
chi_bare_pGv(:,:) = -0.50_dp * chi_bare_pGv(:,:) / (c * q_nmr * tpiba)**2
if (iverbosity > 0) then
write(stdout, '(5X,''chi_bare pGv (HH) in paratec units:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_pGv(:,:) * c**2
endif
call sym_cart_tensor(chi_bare_pGv)
if (iverbosity > 0) then
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_pGv(:,:) * c**2
endif
chi_bare_vGv(:,:) = f_vGv(:,:,1) - 2.0_dp*f_vGv(:,:,0) + f_vGv(:,:,-1)
chi_bare_vGv(:,:) = -0.50_dp * chi_bare_vGv(:,:) / (c * q_nmr * tpiba)**2
if (iverbosity > 0) then
write(stdout, '(5X,''chi_bare vGv (VV) in paratec units:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_vGv(:,:) * c**2
endif
call sym_cart_tensor(chi_bare_vGv)
if (iverbosity > 0) then
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_vGv(:,:) * c**2
endif
end if
! compute induced field
do ipol = 1, 3
call biot_savart(ipol)
enddo
! compute chemical shifts
!call compute_sigma_bare(chi_bare_pGv)
d_omega = omega / REAL ( nr1 * nr2 * nr3, DP )
!
! ***************** spin-orbit-bare *******************
!
! <apsi> TMPTMPTMP PLEASE CHECK FOR VANDERBILT/HARD GRIDS
allocate ( grad_vr ( 3, nrxx ), v_local ( nrxx, nspin ) )
do ispin = 1, nspin
v_local(:,ispin) = vltot(:) + vr(:,ispin)
end do
call gradient ( nrx1, nrx2, nrx3, nr1, nr2, nr3, nrxx, v_local, &
ngm, g, nl, alat, grad_vr )
grad_vr = grad_vr * units_Ry2Ha
deallocate ( v_local )
! </apsi>
do ipol = 1, 3
delta_g_bare ( ipol, 1 ) = SUM ( &
( j_bare(:,2,ipol,s_maj)-j_bare(:,2,ipol,s_min)) * grad_vr ( 3, : ) &
-(j_bare(:,3,ipol,s_maj)-j_bare(:,3,ipol,s_min)) * grad_vr ( 2, : ) )
delta_g_bare ( ipol, 2 ) = SUM ( &
( j_bare(:,3,ipol,s_maj)-j_bare(:,3,ipol,s_min)) * grad_vr ( 1, : ) &
-(j_bare(:,1,ipol,s_maj)-j_bare(:,1,ipol,s_min)) * grad_vr ( 3, : ) )
delta_g_bare ( ipol, 3 ) = SUM ( &
( j_bare(:,1,ipol,s_maj)-j_bare(:,1,ipol,s_min)) * grad_vr ( 2, : ) &
-(j_bare(:,2,ipol,s_maj)-j_bare(:,2,ipol,s_min)) * grad_vr ( 1, : ) )
end do
deallocate ( grad_vr )
#ifdef __PARA
call reduce(9, delta_g_bare)
#endif
delta_g_bare = delta_g_bare * d_omega
delta_g_bare = - delta_g_bare * g_prime / 2.0_dp / c * 1.0e6
!
! ***************** spin-other-orbit *******************
!
! This is the form used in the implementation in 'paratec'
! calculate the spin-other-orbit term a'la paratec:
! int_r j_up(r) x v_h[n_unpaired] d^3r
allocate ( grad_vh ( 3, nrxx ), vh ( nrxx ) )
call v_h( rho(:,s_maj)-rho(:,s_min), nr1, nr2, nr3, nrx1, nrx2, nrx3, nrxx, &
nl, ngm, gg, gstart, 1, alat, omega, e_hartree, charge, vh )
call gradient ( nrx1, nrx2, nrx3, nr1, nr2, nr3, nrxx, vh, &
ngm, g, nl, alat, grad_vh )
grad_vh = grad_vh * units_Ry2Ha
deallocate ( vh )
! -2*j_bare_dw(r) because of the self-interaction correction:
! j_bare(r) - [j_bare_up(r)-j_bare_dw(r)] = -2*j_bare_dw(r)
do ipol = 1, 3
delta_g_soo ( ipol, 1 ) = 2 * SUM &
( j_bare(:,2,ipol,s_min) * grad_vh ( 3, : ) &
- j_bare(:,3,ipol,s_min) * grad_vh ( 2, : ) )
delta_g_soo ( ipol, 2 ) = 2 * SUM &
( j_bare(:,3,ipol,s_min) * grad_vh ( 1, : ) &
- j_bare(:,1,ipol,s_min) * grad_vh ( 3, : ) )
delta_g_soo ( ipol, 3 ) = 2 * SUM &
( j_bare(:,1,ipol,s_min) * grad_vh ( 2, : ) &
- j_bare(:,2,ipol,s_min) * grad_vh ( 1, : ) )
end do
deallocate ( grad_vh )
#ifdef __PARA
call reduce ( 9, delta_g_soo )
#endif
delta_g_soo = delta_g_soo * d_omega
delta_g_soo = delta_g_soo * 2 / c * 1.0e6
! This is obtained using the equation (7) of Pickard et Mauri, PRL 88/086043
if ( tcalculate_correct_delta_g_soo ) then
!<apsi> The G=0 term is still not yet in
!</apsi>
do jpol = 1, 3
do ipol = 1, 3
delta_g_soo_2 ( ipol, jpol ) = SUM ( b_ind_r(:,ipol,jpol) &
* ( rho(:,s_maj)-rho(:,s_min) ) )
end do
end do
end if
delta_g_soo_2 = delta_g_soo_2 * d_omega
delta_g_soo_2 = delta_g_soo_2 * 2 * 1.0e6
!
! ***************** relativistic-mass-correction *******************
!
delta_rmc = delta_rmc / c ** 2 * g_e * units_Ry2Ha * 1.0e6
delta_g_rmc = 0.0_DP
do i = 1, 3
delta_g_rmc(i,i) = delta_rmc
end do
!
! ***************** relativistic-mass-correction gipaw *******************
!
write(6,*) "RMC: ", gipaw_delta_rmc, 1e6 / c ** 2
gipaw_delta_rmc = gipaw_delta_rmc / c ** 2 * g_e * units_Ry2Ha * 1e6
delta_g_rmc_gipaw = 0.0_DP
do i = 1, 3
delta_g_rmc_gipaw(i,i) = gipaw_delta_rmc
end do
!
! ***************** diamagnetic reconstruction *******************
!
! symmetrize tensors
!call trntns (delta_g_diamagn, at, bg, -1)
!call symz(delta_g_diamagn, nsym, s, 1, irt)
!call trntns (delta_g_diamagn, at, bg, 1)
delta_g_diamagn(:,:) = delta_g_diamagn(:,:) &
* g_prime / 4 * units_Ry2Ha * 1e6
!
! ***************** paramagnetic reconstruction *******************
!
! symmetrize tensors
!call trntns (delta_g_paramagn, at, bg, -1)
!call symz(delta_g_paramagn, nsym, s, 1, irt)
!call trntns (delta_g_paramagn, at, bg, 1)
delta_g_paramagn(:,:) = delta_g_paramagn(:,:) * g_prime / 2 * 1e6 &
* units_Ry2Ha
!
! ***************** total delta_g *******************
!
delta_g_total = delta_g_rmc + delta_g_rmc_gipaw + delta_g_bare &
+ delta_g_diamagn + delta_g_paramagn + delta_g_soo
write (stdout,*)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - relativistic-mass-correction'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_rmc(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - relativistic-mass-correction gipaw'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_rmc_gipaw(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - spin-orbit-bare'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_bare(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - spin-orbit diamagnetic correction (GIPAW)'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_diamagn(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - spin-orbit paramagnetic correction (GIPAW)'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_paramagn(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - spin-other-orbit'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_soo(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - spin-other-orbit, version 2'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_soo_2(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
write (stdout,*) 'Delta g - total'
write (stdout,*)
write ( stdout, '(3(5X,3(F12.6,2X)/))' ) delta_g_total(:,:)
write (stdout,*) '**********************************************'
write (stdout,*)
deallocate(p_evc, vel_evc, aux, g_vel_evc, j_bare, b_ind)
CONTAINS
!====================================================================
! compute p_k|evc>, v_k|evc> and G_k v_{k+q,k}|evc>
!====================================================================
SUBROUTINE apply_operators
implicit none
integer ipol
do ipol = 1, 3
call apply_p(evc, p_evc(1,1,ipol), ik, ipol, q)
call apply_vel(evc, vel_evc(1,1,ipol), ik, ipol, q)
! necessary because aux is overwritten by subroutine greenfunction
aux(:,:) = vel_evc(:,:,ipol)
call greenfunction(ik, aux, g_vel_evc(1,1,ipol), q)
enddo
END SUBROUTINE apply_operators
!====================================================================
! add contribution the Q tensors
! Q_{\alpha,\beta} += <(e_i \times ul)_\alpha | (e_i \times ur)_\beta>
!====================================================================
SUBROUTINE add_to_tensor(qt, ul, ur)
implicit none
real(dp), intent(inout) :: qt(3,3)
complex(dp), intent(in) :: ul(npwx,nbnd,3), ur(npwx,nbnd,3)
real(dp) :: braket
integer :: ibnd, ia, ib, comp_ia, comp_ib, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
do ia = 1, 3 ! ia = alpha
comp_ia = ind(ia,i)
if (mult(ia,i) == 0) cycle
do ib = 1, 3 ! ib = beta
comp_ib = ind(ib,i)
if (mult(ib,i) == 0) cycle
do ibnd = 1, nbnd_occ(ik)
braket = real(ZDOTC(npw, ul(1,ibnd,comp_ia), 1, &
ur(1,ibnd,comp_ib), 1), DP)
qt(ia,ib) = qt(ia,ib) + wg(ibnd,ik) * &
braket * mult(ia,i) * mult(ib,i)
enddo ! ibnd
enddo ! ib
enddo ! ia
#ifdef __PARA
call reduce(9, qt)
#endif
END SUBROUTINE add_to_tensor
!====================================================================
! add contribution the the current
! j(r)_{\alpha,\beta} += <ul|J(r)|(B\times e_i \cdot ur)>
!====================================================================
SUBROUTINE add_to_current(j, ul, ur)
implicit none
real(dp), intent(inout) :: j(nrxxs,3,3)
complex(dp), intent(in) :: ul(npwx,nbnd), ur(npwx,nbnd,3)
real(dp) :: fact
integer :: ibdir, icomp, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
! loop over B direction
do ibdir = 1, 3
if (i == ibdir) cycle
icomp = ind(ibdir, i)
fact = real(mult(ibdir,i)*isign)
call j_para(fact, ul(1,1), ur(1,1,icomp), ik, q, j(1,1,ibdir))
enddo
END SUBROUTINE add_to_current
!====================================================================
! ...
!====================================================================
SUBROUTINE relativistic_mass_correction ( rmc_gipaw )
USE atom, ONLY : r, rab
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE nmr_module, ONLY : c
implicit none
! Arguments
real(dp), intent(inout):: rmc_gipaw
integer :: l1, m1, lm1, l2, m2, lm2, ih, ikb, nbs1, jh, jkb, nbs2
integer :: nt, ibnd, na, lm, nrc, ijkb0
complex(dp) :: efg_corr
complex(dp) :: bec_product
efg_corr = 0.0_dp
do ibnd = 1, nbnd
ijkb0 = 0
do nt = 1, ntyp
do na = 1, nat
if (ityp (na) .eq.nt) then
do ih = 1, paw_nh (nt)
ikb = ijkb0 + ih
nbs1=paw_indv(ih,nt)
l1=paw_nhtol(ih,nt)
m1=paw_nhtom(ih,nt)
lm1=m1+l1**2
do jh = 1, paw_nh (nt)
jkb = ijkb0 + jh
nbs2=paw_indv(jh,nt)
l2=paw_nhtol(jh,nt)
m2=paw_nhtom(jh,nt)
lm2=m2+l2**2
IF ( l1 /= l2 ) CYCLE
IF ( m1 /= m2 ) CYCLE
bec_product = paw_becp(jkb,ibnd) &
* CONJG(paw_becp(ikb,ibnd))
efg_corr = efg_corr &
+ bec_product &
* radial_integral_rmc(nbs1,nbs2,nt) &
* wg(ibnd,ik)
enddo
enddo
ijkb0 = ijkb0 + paw_nh (nt)
endif
enddo
enddo
enddo
rmc_gipaw = REAL ( efg_corr, dp )
END SUBROUTINE relativistic_mass_correction
!====================================================================
! ...
!====================================================================
SUBROUTINE diamagnetic_correction ( diamagnetic_tensor )
USE atom, ONLY : r, rab
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE nmr_module, ONLY : c
implicit none
! Arguments
real(dp), intent(inout):: diamagnetic_tensor(3,3)
integer :: l1, m1, lm1, l2, m2, lm2, ih, ikb, nbs1, jh, jkb, nbs2
integer :: nt, ibnd, na, lm, nrc, ijkb0
complex(dp) , allocatable :: efg_corr(:)
complex(dp) :: bec_product
allocate ( efg_corr ( lmaxx**2 ) )
efg_corr = 0.0_dp
do ibnd = 1, nbnd
ijkb0 = 0
do nt = 1, ntyp
do na = 1, nat
if (ityp (na) .eq.nt) then
do ih = 1, paw_nh (nt)
ikb = ijkb0 + ih
nbs1=paw_indv(ih,nt)
l1=paw_nhtol(ih,nt)
m1=paw_nhtom(ih,nt)
lm1=m1+l1**2
do jh = 1, paw_nh (nt)
jkb = ijkb0 + jh
nbs2=paw_indv(jh,nt)
l2=paw_nhtol(jh,nt)
m2=paw_nhtom(jh,nt)
lm2=m2+l2**2
bec_product = paw_becp(jkb,ibnd) &
* CONJG(paw_becp(ikb,ibnd))
!<apsi> s/non-trace-zero component
! 2/3 to separate the non-trace vanishing component
! 1/(2c^2) from the equation (59) in PM-PRB
IF ( l1 == l2 .AND. m1 == m2 ) THEN
diamagnetic_tensor(1,1) &
= diamagnetic_tensor(1,1) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic_so(nbs1,nbs2,nt) &
* wg(ibnd,ik) / c**2
diamagnetic_tensor(2,2) &
= diamagnetic_tensor(2,2) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic_so(nbs1,nbs2,nt) &
* wg(ibnd,ik) / c**2
diamagnetic_tensor(3,3) &
= diamagnetic_tensor(3,3) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic_so(nbs1,nbs2,nt) &
* wg(ibnd,ik) / c**2
END IF
! 2/3 to separate the non-trace vanishing component
do lm = 5, 9
efg_corr(lm) = efg_corr(lm) &
+ bec_product / 3.0_dp &
* radial_integral_diamagnetic_so(nbs1,nbs2,nt) &
* ap(lm,lm1,lm2) * wg(ibnd,ik) / c**2
enddo
enddo
enddo
ijkb0 = ijkb0 + paw_nh (nt)
endif
enddo
enddo
enddo
write(6,'("CCC1",5F14.8)') efg_corr(5:9)
!
! transform in cartesian coordinates
!
efg_corr(5:9) = - sqrt(4.0_dp * pi/5.0_dp) * efg_corr(5:9)
diamagnetic_tensor(1,1) = diamagnetic_tensor(1,1) &
+ sqrt(3.0_dp) * efg_corr(8) - efg_corr(5)
diamagnetic_tensor(2,2) = diamagnetic_tensor(2,2) &
- sqrt(3.0_dp) * efg_corr(8) - efg_corr(5)
diamagnetic_tensor(3,3) = diamagnetic_tensor(3,3) &
+ efg_corr(5) * 2.0_dp
diamagnetic_tensor(1,2) = diamagnetic_tensor(1,2) &
+ efg_corr(9) * sqrt(3.0_dp)
diamagnetic_tensor(2,1) = diamagnetic_tensor(1,2)
diamagnetic_tensor(1,3) = diamagnetic_tensor(1,3) &
- efg_corr(6) * sqrt(3.0_dp)
diamagnetic_tensor(3,1) = diamagnetic_tensor(1,3)
diamagnetic_tensor(2,3) = diamagnetic_tensor(2,3) &
- efg_corr(7) * sqrt(3.0_dp)
diamagnetic_tensor(3,2) = diamagnetic_tensor(2,3)
! efg_corr(5) = 3z^2-1
! efg_corr(6) = -xz
! efg_corr(7) = -yz
! efg_corr(8) = x^2-y^2
! efg_corr(9) = xy
deallocate ( efg_corr )
END SUBROUTINE diamagnetic_correction
!====================================================================
! ...
!====================================================================
SUBROUTINE paramagnetic_correction ( paramagnetic_tensor )
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE nmr_module, ONLY : c
implicit none
! Arguments
real(dp), intent(inout):: paramagnetic_tensor(3,3)
integer :: l1, m1, lm1, l2, m2, lm2, ih, ikb, nbs1, jh, jkb, nbs2
integer :: nt, ibnd, na, lm, j, ijkb0, ipol
complex(dp) :: bec_product
complex(dp) , allocatable :: efg_corr(:)
integer, parameter :: ng_ = 27, lmax2_ = 16
integer :: mg, i1, i2, i3
real(DP) :: g_ (3, ng_), gg_ (ng_)
real(DP) :: ylm_ (ng_,lmax2_)
!--------------------------------------------------------------------------
allocate (efg_corr(3))
!
! calculation of the reconstruction part
!
do ipol = 1, 3
if ( ipol == i ) cycle !TESTTESTTEST
call ccalbec (paw_nkb, npwx, npw, nbnd, paw_becp2, paw_vkb, &
g_vel_evc(1,1,ipol))
efg_corr = 0.0_dp
do ibnd = 1, nbnd
ijkb0 = 0
do nt = 1, ntyp
do na = 1, nat
if (ityp (na) .eq.nt) then
do ih = 1, paw_nh (nt)
ikb = ijkb0 + ih
nbs1=paw_indv(ih,nt)
l1=paw_nhtol(ih,nt)
m1=paw_nhtom(ih,nt)
lm1=m1+l1**2
do jh = 1, paw_nh (nt)
jkb = ijkb0 + jh
nbs2=paw_indv(jh,nt)
l2=paw_nhtol(jh,nt)
m2=paw_nhtom(jh,nt)
lm2=m2+l2**2
if ( l1 /= l2 ) cycle
bec_product = CONJG(paw_becp(ikb,ibnd)) &
* paw_becp2(jkb,ibnd)
efg_corr(1) = efg_corr(1) &
+ bec_product &
* radial_integral_paramagnetic_so(nbs1,nbs2,nt) &
* lx ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
efg_corr(2) = efg_corr(2) &
+ bec_product &
* radial_integral_paramagnetic_so(nbs1,nbs2,nt) &
* ly ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
efg_corr(3) = efg_corr(3) &
+ bec_product &
* radial_integral_paramagnetic_so(nbs1,nbs2,nt) &
* lz ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
if (lz(lm1,lm2)/=0.and.ibnd==1.and.l1==-1) then
write(6,*) "ZZZ3: ", &
ibnd, lm1, lm2, &
bec_product, &
radial_integral_paramagnetic_so(nbs1,nbs2,nt)
end if
enddo
enddo
ijkb0 = ijkb0 + paw_nh (nt)
endif
enddo
enddo
enddo
paramagnetic_tensor ( :, ipol ) = REAL ( efg_corr, dp )
write(6,'("DDD1",2I3,3(F16.7,2X)') &
ipol, i*isign, REAL ( efg_corr(1:3) ) * 1e6
! stop
end do
deallocate(efg_corr)
END SUBROUTINE paramagnetic_correction
!====================================================================
! ...
!====================================================================
SUBROUTINE add_to_sigma_para( paramagnetic_correction, sigma_paramagnetic )
implicit none
real(dp), intent(in) :: paramagnetic_correction(3,3)
real(dp), intent(inout) :: sigma_paramagnetic(3,3)
real(dp) :: fact
integer :: ibdir, icomp, ipol, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
! loop over B direction
do ibdir = 1, 3
if (i == ibdir) cycle
icomp = ind(ibdir, i)
fact = real(mult(ibdir,i)*isign)
do ipol = 1, 3
sigma_paramagnetic ( ipol, icomp ) &
= sigma_paramagnetic ( ipol, icomp ) &
+ fact * paramagnetic_correction ( ipol, ibdir ) &
/ ( 2 * q_nmr * tpiba )
! Do iq=1, 3 ! loop over all q-points
! ...
! Do iperm0 =1,-1,-2
! b0 = Mod(iq+iperm0+2,3) +1 ! gives different b0 for iperm0
! p0 = Mod(iq-iperm0+2,3) +1 ! gives p0 = abs(q x b0)
! ...
! Call take_nonloc_deriv_kq_k(p0,k_gspace, rk(1),u_k(1,i),&
! ...
! para_corr_shift_tot(b0,:,:,:) = para_corr_shift_tot(b0,:,:,:)-&
! Real(iperm0,dp)*Real(iqsign,dp)*para_corr_shift*&
! kpoints%w(irk)/qmag/dtwo/Real(crys%nspin,dp)
end do
enddo
END SUBROUTINE add_to_sigma_para
END SUBROUTINE g_tensor_crystal

144
GIPAW/greenfunction.f90 Normal file
View File

@ -0,0 +1,144 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE greenfunction(ik, psi, g_psi, q)
!-----------------------------------------------------------------------
!
! ... Apply the Green function operator
! ... (formula here)
! ... We use Hartree atomic units; since G is the inverse of an
! ... energy: G => G / ryd_to_hartree
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE becmod, ONLY : becp
USE wavefunctions_module, ONLY : evc
USE pwcom
USE nmr_module
!-- parameters ---------------------------------------------------------
IMPLICIT none
INTEGER, INTENT(IN) :: ik
COMPLEX(DP), INTENT(INOUT) :: psi(npwx,nbnd) ! psi is changed on output!!!
COMPLEX(DP), INTENT(OUT) :: g_psi(npwx,nbnd)
REAL(DP) :: q(3)
!-- local variables ----------------------------------------------------
real(dp), parameter :: ryd_to_hartree = 0.5d0
complex(dp), allocatable :: ps(:,:), work (:,:)
real(dp), allocatable :: h_diag (:,:), eprec (:)
real(dp) :: anorm, thresh, gk(3), dxk(3)
integer :: ibnd, ig, lter
logical :: conv_root, q_is_zero
complex(dp), external :: ZDOTC
external ch_psi_all, cg_psi
call start_clock ('greenf')
! allocate memory
allocate (work(npwx, MAX(nkb,1)), ps(nbnd,nbnd), h_diag(npwx,nbnd), &
eprec(nbnd))
! check if |q| is zero
q_is_zero = .false.
if (sqrt(q(1)*q(1)+q(2)*q(2)+q(3)*q(3)) < 1d-8) q_is_zero = .true.
if (q_is_zero) evq = evc
!====================================================================
! apply -Q_{k+q} to the r.h.s.
!====================================================================
! project on <evq|: ps(i,j) = <evq(i)|psi(j)>
ps = (0.d0,0.d0)
CALL ZGEMM('C', 'N', nbnd_occ (ik), nbnd_occ (ik), npw, &
(1.d0,0.d0), evq(1,1), npwx, psi(1,1), npwx, (0.d0,0.d0), &
ps(1,1), nbnd)
#ifdef __PARA
call reduce (2 * nbnd * nbnd_occ (ik), ps(1,1))
#endif
!! this is the case with overlap (ultrasoft)
!! g_psi is used as work space to store S|evc>
!!
!!CALL ccalbec (nkb, npwx, npw, nbnd_occ(ik), becp, vkb, evc)
!!CALL s_psi (npwx, npw, nbnd_occ(ik), evc, g_psi)
!! |psi> = -(|psi> - S|evc><evc|psi>)
!!
!!CALL ZGEMM( 'N', 'N', npw, nbnd_occ(ik), nbnd_occ(ik), &
!! (1.d0,0.d0), g_psi(1,1), npwx, ps(1,1), nbnd, (-1.d0,0.d0), &
!! psi(1,1), npwx )
! |psi> = -(1 - |evq><evq|) |psi>
CALL ZGEMM('N', 'N', npw, nbnd_occ(ik), nbnd_occ(ik), &
(1.d0,0.d0), evq(1,1), npwx, ps(1,1), nbnd, (-1.d0,0.d0), &
psi(1,1), npwx)
!====================================================================
! solve the linear system (apply G_{k+q})
!====================================================================
! convergence treshold
!thresh = 1d-12
thresh = sqrt(conv_threshold) ! sqrt(of that of PARATEC)
! preconditioning of the linear system
do ibnd = 1, nbnd_occ (ik)
conv_root = .true.
do ig = 1, npw
work (ig,1) = g2kin (ig) * evc (ig, ibnd)
enddo
eprec (ibnd) = 1.35d0 * ZDOTC (npw, evq (1, ibnd), 1, work, 1)
enddo
#ifdef __PARA
call reduce (nbnd_occ (ik), eprec)
#endif
do ibnd = 1, nbnd_occ (ik)
do ig = 1, npw
h_diag (ig, ibnd) = 1.d0 / max (1.0d0, g2kin (ig) / eprec (ibnd) )
enddo
enddo
! use the hamiltonian at k+q
do ig = 1, npw
gk(1) = (xk(1,ik) + g(1,igk(ig)) + q(1)) * tpiba
gk(2) = (xk(2,ik) + g(2,igk(ig)) + q(2)) * tpiba
gk(3) = (xk(3,ik) + g(3,igk(ig)) + q(3)) * tpiba
g2kin (ig) = gk(1)**2 + gk(2)**2 + gk(3)**2
enddo
if (.not. q_is_zero) then
dxk = xk(:,ik) + q
call init_us_2(npw, igk, dxk, vkb)
call ccalbec (nkb, npwx, npw, nbnd, becp, vkb, psi)
endif
! initial guess
g_psi(:,:) = (0.d0, 0.d0)
! solve linear system
call cgsolve_all (ch_psi_all, cg_psi, et(1,ik), psi, g_psi, &
h_diag, npwx, npw, thresh, ik, lter, conv_root, anorm, &
nbnd_occ(ik) )
!!write(stdout, '(5X,''cgsolve_all converged in '',I3,'' iterations'')') &
!! lter
if (.not.conv_root) WRITE( stdout, '(5x,"ik",i4," ibnd",i4, &
& " linter: root not converged ",e10.3)') &
ik, ibnd, anorm
! convert to Hartree
g_psi(:,:) = g_psi(:,:) / ryd_to_hartree
call flush_unit( stdout )
call stop_clock('greenf')
! free memory
deallocate (work, h_diag, eprec, ps)
END SUBROUTINE greenfunction

102
GIPAW/h_psiq.f90 Normal file
View File

@ -0,0 +1,102 @@
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!-----------------------------------------------------------------------
subroutine h_psiq (lda, n, m, psi, hpsi, spsi)
!-----------------------------------------------------------------------
!
! This routine computes the product of the Hamiltonian
! and of the S matrix with a m wavefunctions contained
! in psi. It first computes the bec matrix of these
! wavefunctions and then with the routines hus_1psi and
! s_psi computes for each band the required products
!
use pwcom
USE wavefunctions_module, ONLY: psic
USE becmod, ONLY: becp
USE kinds, only : DP
use nmr_module
implicit none
!
! Here the local variables
!
integer :: ibnd
! counter on bands
integer :: lda, n, m
! input: the leading dimension of the array psi
! input: the real dimension of psi
! input: the number of psi to compute
integer :: j
! do loop index
complex(DP) :: psi (lda, m), hpsi (lda, m), spsi (lda, m)
! input: the functions where to apply H and S
! output: H times psi
! output: S times psi (Us PP's only)
call start_clock ('h_psiq')
call start_clock ('init')
call ccalbec (nkb, npwx, n, m, becp, vkb, psi)
!
! Here we apply the kinetic energy (k+G)^2 psi
!
do ibnd = 1, m
do j = 1, n
hpsi (j, ibnd) = g2kin (j) * psi (j, ibnd)
enddo
enddo
call stop_clock ('init')
!
! the local potential V_Loc psi. First the psi in real space
!
do ibnd = 1, m
call start_clock ('firstfft')
psic(:) = (0.d0, 0.d0)
!do j = 1, n
! psic (nls(igk(j))) = psi (j, ibnd)
!enddo
psic (nls(igk(1:n))) = psi(1:n, ibnd)
call cft3s (psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 2)
call stop_clock ('firstfft')
!
! and then the product with the potential vrs = (vltot+vr) on the smoo
!
!do j = 1, nrxxs
! psic (j) = psic (j) * vrs (j, current_spin)
!enddo
psic (1:nrxxs) = psic (1:nrxxs) * vrs (1:nrxxs, current_spin)
!
! back to reciprocal space
!
call start_clock ('secondfft')
call cft3s (psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, - 2)
!
! addition to the total product
!
!do j = 1, n
! hpsi (j, ibnd) = hpsi (j, ibnd) + psic (nls(igk(j)))
!enddo
hpsi (1:n, ibnd) = hpsi (1:n, ibnd) + psic (nls(igk(1:n)))
call stop_clock ('secondfft')
enddo
!
! Here the product with the non local potential V_NL psi
!
call add_vuspsi (lda, n, m, psi, hpsi)
call s_psi (lda, n, m, psi, spsi)
call stop_clock ('h_psiq')
return
end subroutine h_psiq

View File

@ -0,0 +1,161 @@
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!
!----------------------------------------------------------------------
subroutine init_paw_2_no_phase (npw_, igk_, q_, vkb_)
!----------------------------------------------------------------------
!
! Calculates paw_beta functions (paw projectors), with
! structure factor, for all atoms, in reciprocal space
!
USE kinds , ONLY : dp
USE constants , ONLY : tpi
USE wvfct , ONLY : npwx
USE cell_base , ONLY : tpiba
USE ions_base, ONLY : nat, ntyp => nsp, ityp, tau
USE gvect , ONLY : eigts1, eigts2, eigts3, g, ig1, ig2, ig3
USE us, ONLY : nqxq, dq
USE paw, ONLY : paw_nkb, paw_lmaxkb, paw_nhm, paw_nh, paw_nhtol, &
paw_nhtom, paw_indv, paw_tab, paw_nbeta, &
paw_tab_d2y
USE splinelib
!
implicit none
!
integer :: npw_, igk_ (npw_)
! input: number of PW's
! input: indices of q+G
real(DP) :: q_(3)
! input: q vector
complex(DP) :: vkb_ (npwx, paw_nkb)
! output: beta functions
!
! Local variables
!
integer :: i0,i1,i2,i3, ig, l, lm, na, nt, nb, ih, jkb
real(DP) :: px, ux, vx, wx, arg
real(DP), allocatable :: gk (:,:), qg (:), vq (:), ylm (:,:), vkb1(:,:)
complex(DP) :: phase, pref
complex(DP), allocatable :: sk(:)
!<apsi>
integer :: startq, lastq, iq
real(DP), allocatable :: xdata(:)
!</apsi>
!
!
if (paw_lmaxkb.lt.0) return
call start_clock ('init_paw_2')
allocate (vkb1( npw_,paw_nhm))
allocate ( sk( npw_))
allocate ( qg( npw_))
allocate ( vq( npw_))
allocate ( ylm( npw_, (paw_lmaxkb + 1) **2))
allocate ( gk( 3, npw_))
!
do ig = 1, npw_
gk (1,ig) = q_(1) + g(1, igk_(ig) )
gk (2,ig) = q_(2) + g(2, igk_(ig) )
gk (3,ig) = q_(3) + g(3, igk_(ig) )
qg (ig) = gk(1, ig)**2 + gk(2, ig)**2 + gk(3, ig)**2
enddo
!
call ylmr2 ((paw_lmaxkb+1)**2, npw_, gk, qg, ylm)
!
! set now qg=|q+G| in atomic units
!
do ig = 1, npw_
qg(ig) = sqrt(qg(ig))*tpiba
enddo
!<ceres>
call divide (nqxq, startq, lastq)
startq = 1 !*TMPTMPTMP
lastq = nqxq
allocate(xdata(lastq-startq+1))
do iq = startq, lastq
xdata(iq) = (iq - 1) * dq
enddo
!</ceres>
jkb = 0
do nt = 1, ntyp
! calculate beta in G-space using an interpolation table
do nb = 1, paw_nbeta (nt)
do ig = 1, npw_
!<ceres>
!px = qg (ig) / dq - int (qg (ig) / dq)
!ux = 1.d0 - px
!vx = 2.d0 - px
!wx = 3.d0 - px
!i0 = qg (ig) / dq + 1
!i1 = i0 + 1
!i2 = i0 + 2
!i3 = i0 + 3
!vq (ig) = paw_tab (i0, nb, nt) * ux * vx * wx / 6.d0 + &
! paw_tab (i1, nb, nt) * px * vx * wx / 2.d0 - &
! paw_tab (i2, nb, nt) * px * ux * wx / 2.d0 + &
! paw_tab (i3, nb, nt) * px * ux * vx / 6.d0
vq(ig) = splint(xdata, paw_tab(:,nb,nt), paw_tab_d2y(:,nb,nt), qg(ig))
!</ceres>
enddo
! add spherical harmonic part
do ih = 1, paw_nh (nt)
if (nb.eq.paw_indv (ih, nt) ) then
l = paw_nhtol (ih, nt)
lm = l * l + paw_nhtom (ih, nt)
do ig = 1, npw_
vkb1 (ig,ih) = ylm (ig, lm) * vq (ig)
enddo
endif
enddo
enddo
!
! vkb1 contains all betas including angular part for type nt
! now add the structure factor and factor (-i)^l
!
do na = 1, nat
! ordering: first all betas for atoms of type 1
! then all betas for atoms of type 2 and so on
if (ityp (na) .eq.nt) then
arg = (q_(1) * tau (1, na) + &
q_(2) * tau (2, na) + &
q_(3) * tau (3, na) ) * tpi
phase = CMPLX (cos (arg), - sin (arg) )
do ig = 1, npw_
sk (ig) = eigts1 (ig1(igk_(ig)), na) * &
eigts2 (ig2(igk_(ig)), na) * &
eigts3 (ig3(igk_(ig)), na)
enddo
do ih = 1, paw_nh(nt)
jkb = jkb + 1
pref = (0.d0, -1.d0) ** paw_nhtol (ih, nt) ! * phase
do ig = 1, npw_
vkb_(ig, jkb) = vkb1 (ig,ih) * sk (ig) * pref
enddo
enddo
endif
enddo
enddo
deallocate (gk)
deallocate (ylm)
deallocate (vq)
deallocate (qg)
deallocate (sk)
deallocate (vkb1)
call stop_clock ('init_paw_2')
return
end subroutine init_paw_2_no_phase

View File

@ -0,0 +1,172 @@
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
! for the time being, don't use splines, till it is implemented
! also in PW
#undef SPLINES
#define SPLINES
!----------------------------------------------------------------------
subroutine init_us_2_no_phase (npw_, igk_, q_, vkb_)
!----------------------------------------------------------------------
!
! Calculates beta functions (Kleinman-Bylander projectors), with
! structure factor, for all atoms, in reciprocal space
!
USE kinds, ONLY : DP
USE ions_base, ONLY : nat, ntyp => nsp, ityp, tau
USE cell_base, ONLY : tpiba
USE constants, ONLY : tpi
USE gvect, ONLY : eigts1, eigts2, eigts3, ig1, ig2, ig3, g
USE wvfct, ONLY : npw, npwx, igk
#ifdef SPLINES
USE us, ONLY : nqxq, dq, tab, tab_d2y
USE splinelib
#else
USE us, ONLY : nqxq, dq, tab
#endif
USE uspp, ONLY : nkb, vkb, nhtol, nhtolm, indv
USE uspp_param, ONLY : lmaxkb, nbeta, nhm, nh
!
implicit none
!
integer :: npw_, igk_ (npw_)
! input: number of PW's
! input: indices of q+G
real(DP) :: q_(3)
! input: q vector
complex(DP) :: vkb_ (npwx, nkb)
! output: beta functions
!
! Local variables
!
integer :: i0,i1,i2,i3, ig, l, lm, na, nt, nb, ih, jkb, iq
integer :: startq, lastq
real(DP) :: px, ux, vx, wx, arg
real(DP), allocatable :: gk (:,:), qg (:), vq (:), ylm (:,:), vkb1(:,:)
complex(DP) :: phase, pref
complex(DP), allocatable :: sk(:)
real(DP), allocatable :: xdata(:)
!
!
if (lmaxkb.lt.0) return
call start_clock ('init_us_2')
allocate (vkb1( npw_,nhm))
allocate ( sk( npw_))
allocate ( qg( npw_))
allocate ( vq( npw_))
allocate ( ylm( npw_, (lmaxkb + 1) **2))
allocate ( gk( 3, npw_))
!
do ig = 1, npw_
gk (1,ig) = q_(1) + g(1, igk_(ig) )
gk (2,ig) = q_(2) + g(2, igk_(ig) )
gk (3,ig) = q_(3) + g(3, igk_(ig) )
qg (ig) = gk(1, ig)**2 + gk(2, ig)**2 + gk(3, ig)**2
enddo
!
call ylmr2 ((lmaxkb+1)**2, npw_, gk, qg, ylm)
!
! set now qg=|q+G| in atomic units
!
do ig = 1, npw_
qg(ig) = sqrt(qg(ig))*tpiba
enddo
#ifdef SPLINES
!<ceres>
startq = 1
lastq = nqxq
call divide (nqxq, startq, lastq)
allocate(xdata(lastq-startq+1))
do iq = startq, lastq
xdata(iq) = (iq - 1) * dq
enddo
!</ceres>
#endif
jkb = 0
do nt = 1, ntyp
! calculate beta in G-space using an interpolation table
do nb = 1, nbeta (nt)
do ig = 1, npw_
#ifdef SPLINES
vq(ig) = splint(xdata, tab(:,nb,nt), tab_d2y(:,nb,nt), qg(ig))
#else
px = qg (ig) / dq - int (qg (ig) / dq)
ux = 1.d0 - px
vx = 2.d0 - px
wx = 3.d0 - px
i0 = INT( qg (ig) / dq ) + 1
i1 = i0 + 1
i2 = i0 + 2
i3 = i0 + 3
!*apsi TMPTMPTMP
if ( i3 > size(tab,1) ) then
vq(ig) = 0.0_dp
else
vq (ig) = tab (i0, nb, nt) * ux * vx * wx / 6.d0 + &
tab (i1, nb, nt) * px * vx * wx / 2.d0 - &
tab (i2, nb, nt) * px * ux * wx / 2.d0 + &
tab (i3, nb, nt) * px * ux * vx / 6.d0
end if
#endif
enddo
! add spherical harmonic part
do ih = 1, nh (nt)
if (nb.eq.indv (ih, nt) ) then
l = nhtol (ih, nt)
lm =nhtolm (ih, nt)
do ig = 1, npw_
vkb1 (ig,ih) = ylm (ig, lm) * vq (ig)
enddo
endif
enddo
enddo
!
! vkb1 contains all betas including angular part for type nt
! now add the structure factor and factor (-i)^l
!
do na = 1, nat
! ordering: first all betas for atoms of type 1
! then all betas for atoms of type 2 and so on
if (ityp (na) .eq.nt) then
!arg = (q_(1) * tau (1, na) + &
! q_(2) * tau (2, na) + &
! q_(3) * tau (3, na) ) * tpi
!phase = CMPLX (cos (arg), - sin (arg) )
do ig = 1, npw_
sk (ig) = eigts1 (ig1(igk_(ig)), na) * &
eigts2 (ig2(igk_(ig)), na) * &
eigts3 (ig3(igk_(ig)), na)
enddo
do ih = 1, nh (nt)
jkb = jkb + 1
pref = (0.d0, -1.d0) **nhtol (ih, nt)! * phase
do ig = 1, npw_
vkb_(ig, jkb) = vkb1 (ig,ih) * sk (ig) * pref
enddo
enddo
endif
enddo
enddo
deallocate (gk)
deallocate (ylm)
deallocate (vq)
deallocate (qg)
deallocate (sk)
deallocate (vkb1)
call stop_clock ('init_us_2')
return
end subroutine init_us_2_no_phase

93
GIPAW/j_para.f90 Normal file
View File

@ -0,0 +1,93 @@
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE j_para(fact, psi_n, psi_m, ik, q, j)
!-----------------------------------------------------------------------
!
! ... Compute the paramgnetic current between two states:
! ... j_para(r') = (1/2) fact <psi_n| { p_k|r'><r'| + |r'><r'|p_{k+q} } |psi_m>
! ... the result is added to j and is returned in real space
!
USE kinds, ONLY : DP
USE klist, ONLY : xk
USE wvfct, ONLY : nbnd, npwx, npw, igk, wg
USE pwcom
USE nmr_module
!-- parameters ---------------------------------------------------------
IMPLICIT none
INTEGER, INTENT(IN) :: ik ! k-point
REAL(DP), INTENT(IN) :: fact ! multiplication factor
REAL(DP), INTENT(IN) :: q(3)
COMPLEX(DP), INTENT(IN) :: psi_n(npwx,nbnd), psi_m(npwx,nbnd)
REAL(DP), INTENT(INOUT) :: j(nrxxs,3)
!-- local variables ----------------------------------------------------
COMPLEX(DP), allocatable :: p_psic(:), psic(:), aux(:)
REAL(DP) :: gk
INTEGER :: ig, ipol, ibnd
call start_clock('j_para')
! allocate real space wavefunctions
allocate(p_psic(nrxxs), psic(nrxxs), aux(npwx))
! loop over cartesian components
do ipol = 1, 3
! loop over bands
do ibnd = 1, nbnd_occ(ik)
! apply p_k on the left
do ig = 1, npw
gk = xk(ipol,ik) + g(ipol,igk(ig))
aux(ig) = gk * tpiba * psi_n(ig,ibnd)
enddo
! transform to real space
p_psic(:) = (0.d0,0.d0)
p_psic(nls(igk(1:npw))) = aux(1:npw)
call cft3s(p_psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 2)
psic(:) = (0.d0,0.d0)
psic(nls(igk(1:npw))) = psi_m(1:npw,ibnd)
call cft3s(psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 2)
! add to the current
j(1:nrxxs,ipol) = j(1:nrxxs,ipol) + 0.5d0 * fact * wg(ibnd,ik) * &
aimag(conjg(p_psic(1:nrxxs)) * psic(1:nrxxs))
! apply p_{k+q} on the right
do ig = 1, npw
gk = xk(ipol,ik) + g(ipol,igk(ig)) + q(ipol)
aux(ig) = gk * tpiba * psi_m(ig,ibnd)
enddo
! transform to real space
p_psic(:) = (0.d0,0.d0)
p_psic(nls(igk(1:npw))) = aux(1:npw)
call cft3s(p_psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 2)
psic(:) = (0.d0,0.d0)
psic(nls(igk(1:npw))) = psi_n(1:npw,ibnd)
call cft3s(psic, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, 2)
! add to the current
j(1:nrxxs,ipol) = j(1:nrxxs,ipol) + 0.5d0 * fact * wg(ibnd,ik) * &
aimag(conjg(psic(1:nrxxs)) * p_psic(1:nrxxs))
enddo ! ibnd
enddo ! ipol
! free memory
deallocate(p_psic, psic, aux)
call stop_clock('j_para')
END SUBROUTINE j_para

102
GIPAW/magn_main.f90 Normal file
View File

@ -0,0 +1,102 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
PROGRAM magn_main
!-----------------------------------------------------------------------
!
! ... This is the main driver of the magnetic resposne program.
! ... It controls the initialization routines.
! ... Features: NMR chemical shifts
!... EPR g-tensor
! ... Ported to Espresso by:
! ... D. Ceresoli, A. P. Seitsonen, U. Gerstamnn and F. Mauri
! ...
! ... References (NMR):
! ... F. Mauri and S. G. Louie Phys. Rev. Lett. 76, 4246 (1996)
! ... F. Mauri, B. G. Pfrommer, S. G. Louie, Phys. Rev. Lett. 77, 5300 (1996)
! ... T. Gregor, F. Mauri, and R. Car, J. Chem. Phys. 111, 1815 (1999)
! ... C. J. Pickard and F. Mauri, Phys. Rev. B 63, 245101 (2001)
! ... C. J. Pickard and F. Mauri, Phys. Rev. Lett. 91, 196401 (2003)
! ...
! ... References (g-tensor):
! ... C. J. Pickard and F. Mauri, Phys. Rev. Lett. 88, 086403 (2002)
! ...
USE kinds, ONLY : DP
USE io_global, ONLY : stdout, ionode, ionode_id
USE wvfct, ONLY : gamma_only
USE io_files, ONLY : prefix, tmp_dir, nd_nmbr
USE klist, ONLY : nks
USE mp, ONLY : mp_bcast
USE cell_base, ONLY : tpiba
USE nmr_module
USE global_version, ONLY : version_number
!<apsi>
use paw, ONLY : read_recon, read_recon_paratec
USE mp, ONLY : mp_barrier !*TMPTMPTMP
!</apsi>
!------------------------------------------------------------------------
IMPLICIT NONE
CHARACTER (LEN=9) :: code = 'MAGN'
!------------------------------------------------------------------------
CALL init_clocks( .TRUE. )
CALL start_clock( 'MAGN' )
! ... and begin with the initialization part
CALL startup( nd_nmbr, code, version_number )
CALL nmr_readin()
! read ground state wavefunctions
call read_file
call openfil
if (gamma_only) call errore('MAGN_main', 'gamma_only == .true.', 1)
!<apsi>
! Read in qe format
IF ( read_recon_in_paratec_fmt ) THEN
! Read in paratec format
CALL read_recon_paratec ( file_reconstruction )
ELSE
CALL read_recon ( file_reconstruction )
END IF
!</apsi>
! write(0,*) "QQQ2: ", aephi(1,1)%psi(5), psphi(1,1)%psi(5)
CALL nmr_allocate()
CALL nmr_setup()
CALL nmr_summary()
CALL nmr_openfil()
CALL print_clock( 'MAGN' )
! convert q_nmr in units of tpiba
q_nmr = q_nmr / tpiba
! calculation
select case(trim(job))
case('nmr')
call suscept_crystal
case('g_tensor')
call g_tensor_crystal
case('f-sum')
call test_f_sum_rule
case default
call errore('magn_main', 'wrong or undefined job in input', 1)
end select
! print timings and stop the code
CALL print_clock_nmr()
CALL stop_code( .TRUE. )
STOP
END PROGRAM magn_main

692
GIPAW/nmr_module.f90 Normal file
View File

@ -0,0 +1,692 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
MODULE nmr_module
!-----------------------------------------------------------------------
!
! ... This module contains the variables used for NMR calculations
!
USE kinds, ONLY : DP
USE constants, ONLY : a0_to_cm => bohr_radius_cm
USE parameters, ONLY: npk, ntypx, lmaxx
IMPLICIT NONE
SAVE
! speed of light in atomic units: c = 1/alpha
REAL(DP), PARAMETER :: c = 137.03599911d0
! avogadro number
REAL(DP), PARAMETER :: avogadro = 6.022142d23
! number of occupied bands at each k-point
INTEGER :: nbnd_occ(npk)
! alpha shift of the projector on the valence wfcs
REAL(DP) :: alpha_pv
! eigenvalues and eigenfunctions at k+q
COMPLEX(DP), ALLOCATABLE :: evq(:,:)
! induced current (bare term) and induced magnetic field
REAL(DP), ALLOCATABLE :: j_bare(:,:,:,:), b_ind_r(:,:,:)
! induced magnetic field in reciprocal space
COMPLEX(DP), ALLOCATABLE :: b_ind(:,:,:)
! convergence threshold for diagonalizationa and greenfunction
REAL(DP) :: conv_threshold
! q for the perturbation (in bohrradius^{-1})
REAL(DP) :: q_nmr
! verbosity
INTEGER :: iverbosity
! job: nmr, g_tensor
CHARACTER(80) :: job
! format for a rank-2 tensor
CHARACTER(*), PARAMETER :: tens_fmt = '(3(5X,3(F14.4,2X)/))'
! for plotting the induced current and induced field
CHARACTER(80) :: filcurr, filfield
!<apsi>
CHARACTER(256) :: file_reconstruction ( ntypx )
LOGICAL :: read_recon_in_paratec_fmt
REAL(dp) :: rc(ntypx,0:lmaxx)
COMPLEX(dp), ALLOCATABLE :: paw_becp2 ( :, : )
REAL(dp), ALLOCATABLE, DIMENSION ( :, : ) :: lx, ly, lz
REAL(dp), ALLOCATABLE :: radial_integral_paramagnetic(:,:,:)
REAL(dp), ALLOCATABLE :: radial_integral_diamagnetic(:,:,:)
REAL(dp), ALLOCATABLE :: radial_integral_paramagnetic_so(:,:,:)
REAL(dp), ALLOCATABLE :: radial_integral_diamagnetic_so(:,:,:)
REAL(dp), ALLOCATABLE :: radial_integral_rmc(:,:,:)
!<apsi>
CONTAINS
!-----------------------------------------------------------------------
! Read in the nmr input file.
! Format: &inputmagn
! prefix = '...' prefix of SCF calculation
! tmp_dir = '...' scratch directory
! job = 'nmr' or 'g_tensor'
! conv_threshold = 1d-14
! q_nmr = 0.01d0
! filcurr = '...'
! filfield = '...'
! iverbosity = 0
! /
!-----------------------------------------------------------------------
SUBROUTINE nmr_readin()
USE io_files, ONLY : nd_nmbr, prefix, tmp_dir
USE io_global, ONLY : ionode
IMPLICIT NONE
INTEGER :: ios
NAMELIST /inputmagn/ job, prefix, tmp_dir, conv_threshold, &
q_nmr, iverbosity, filcurr, filfield, &
read_recon_in_paratec_fmt, &
file_reconstruction
if ( .not. ionode ) goto 400
job = ''
prefix = 'pwscf'
tmp_dir = './scratch/'
conv_threshold = 1d-14
q_nmr = 0.01d0
iverbosity = 0
filcurr = ''
filfield = ''
read_recon_in_paratec_fmt = .FALSE.
file_reconstruction ( : ) = " "
read( 5, inputmagn, err = 200, iostat = ios )
200 call errore( 'nmr_readin', 'reading inputmagn namelist', abs( ios ) )
400 continue
call nmr_bcast_input
END SUBROUTINE nmr_readin
!-----------------------------------------------------------------------
! Broadcast input data to all processors
!-----------------------------------------------------------------------
SUBROUTINE nmr_bcast_input
#ifdef __PARA
#include "f_defs.h"
USE mp, ONLY : mp_bcast
USE io_files, ONLY : prefix, tmp_dir
implicit none
integer :: root = 0
call mp_bcast(job, root)
call mp_bcast(prefix, root)
call mp_bcast(tmp_dir, root)
call mp_bcast(conv_threshold, root)
call mp_bcast(q_nmr, root)
call mp_bcast(iverbosity, root)
call mp_bcast(filcurr, root)
call mp_bcast(filfield, root)
call mp_bcast(read_recon_in_paratec_fmt, root)
call mp_bcast(file_reconstruction, root)
#endif
END SUBROUTINE nmr_bcast_input
!-----------------------------------------------------------------------
! Allocate memory for NMR
!-----------------------------------------------------------------------
SUBROUTINE nmr_allocate
USE becmod, ONLY : becp
USE lsda_mod, ONLY : nspin, lsda
USE pwcom
!<apsi>
USE paw, only: paw_vkb, paw_becp, paw_nkb
!</apsi>
IMPLICIT NONE
allocate(evq(npwx,nbnd))
allocate(becp(nkb,nbnd))
allocate(j_bare(nrxxs,3,3,nspin), b_ind_r(nrxxs,3,3), b_ind(ngm,3,3))
END SUBROUTINE nmr_allocate
!-----------------------------------------------------------------------
! Print a short summary of the calculation
!-----------------------------------------------------------------------
SUBROUTINE nmr_summary
USE io_global, ONLY : stdout
IMPLICIT NONE
CALL flush_unit( stdout )
END SUBROUTINE nmr_summary
!-----------------------------------------------------------------------
! Open files needed for NMR
!-----------------------------------------------------------------------
SUBROUTINE nmr_openfil
USE wvfct, ONLY : npwx
USE uspp, ONLY : nkb
IMPLICIT NONE
END SUBROUTINE nmr_openfil
!-----------------------------------------------------------------------
! Print timings
!-----------------------------------------------------------------------
SUBROUTINE print_clock_nmr
USE io_global, ONLY : stdout
IMPLICIT NONE
WRITE( stdout, * )
call print_clock ('MAGN')
WRITE( stdout, * ) ' INITIALIZATION: '
call print_clock ('nmr_setup')
WRITE( stdout, * )
call print_clock ('greenf')
call print_clock ('cgsolve')
call print_clock ('ch_psi')
call print_clock ('h_psiq')
WRITE( stdout, * )
call print_clock ('u_kq')
call print_clock ('h_psi')
WRITE( stdout, * )
call print_clock ('apply_p')
call print_clock ('apply_vel')
WRITE( stdout, * )
call print_clock ('j_para')
call print_clock ('biot_savart')
call print_clock ('c_sigma')
WRITE( stdout, * )
WRITE( stdout, * ) ' General routines'
call print_clock ('ccalbec')
call print_clock ('cft3')
call print_clock ('cft3s')
call print_clock ('cinterpolate')
call print_clock ('davcio')
call print_clock ('write_rec')
WRITE( stdout, * )
#ifdef __PARA
WRITE( stdout, * ) ' Parallel routines'
call print_clock ('reduce')
call print_clock ('poolreduce')
#endif
END SUBROUTINE print_clock_nmr
!-----------------------------------------------------------------------
! NMR setup
!-----------------------------------------------------------------------
SUBROUTINE nmr_setup
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE ions_base, ONLY : tau, nat, ntyp => nsp
USE atom, ONLY : nlcc
USE wvfct, ONLY : nbnd, et, wg, npwx
USE lsda_mod, ONLY : nspin, lsda
USE scf, ONLY : vr, vrs, vltot, rho, rho_core
USE gvect, ONLY : nrxx, ngm
USE gsmooth, ONLY : doublegrid
USE klist, ONLY : xk, degauss, ngauss, nks, nelec
USE constants, ONLY : degspin, pi
!<apsi>
USE paw, ONLY : paw_nbeta, aephi, psphi, paw_vkb, &
paw_becp, paw_nkb, vloc_present, &
gipaw_ae_vloc, gipaw_ps_vloc
USE atom, ONLY : r, rab
!</apsi>
IMPLICIT none
integer :: ik, nt, ibnd
logical :: nlcc_any
real(dp) :: emin, emax
!<apsi>
integer :: il, lm, l, m, lm1, lm2, m1, m2, abs_m1, abs_m2
integer :: sign_m1, sign_m2, il1, il2, l1, l2, j, kkpsi, nrc
real(dp) :: alpha_lm, beta_lm
integer, allocatable :: lm2l ( : ), lm2m ( : ), kkpsi_max
real(dp), allocatable :: work(:), kinetic_aephi(:), kinetic_psphi(:)
real(dp), allocatable :: aephi_dvloc_dr(:), psphi_dvloc_dr(:)
!</apsi>
real(dp) :: mysum1 ( 3, lmaxx ) !TMPTMPTMP
real(dp) :: mysum2 ( 3, 1:lmaxx ) !TMPTMPTMP
call start_clock ('nmr_setup')
! initialize pseudopotentials
call init_us_1
!<apsi>
! initialize paw
do nt=1,ntyp
do il = 1,paw_nbeta(nt)
IF ( psphi(nt,il)%label%rc < -0.99_dp ) THEN
rc(nt,psphi(nt,il)%label%l) = 1.6_dp
rc(nt,aephi(nt,il)%label%l) = 1.6_dp
psphi(nt,il)%label%rc = rc(nt,psphi(nt,il)%label%l)
aephi(nt,il)%label%rc = rc(nt,aephi(nt,il)%label%l)
ELSE
rc(nt,psphi(nt,il)%label%l) = psphi(nt,il)%label%rc
rc(nt,aephi(nt,il)%label%l) = aephi(nt,il)%label%rc
END IF
enddo
enddo
call init_paw_1
allocate (paw_vkb( npwx, paw_nkb))
allocate (paw_becp(paw_nkb, nbnd))
allocate (paw_becp2(paw_nkb, nbnd))
!<apsi>
allocate ( radial_integral_diamagnetic(paw_nkb,paw_nkb,ntypx) )
allocate ( radial_integral_paramagnetic(paw_nkb,paw_nkb,ntypx) )
allocate ( radial_integral_diamagnetic_so(paw_nkb,paw_nkb,ntypx) )
allocate ( radial_integral_paramagnetic_so(paw_nkb,paw_nkb,ntypx) )
allocate ( radial_integral_rmc(paw_nkb,paw_nkb,ntypx) )
radial_integral_diamagnetic = 0.0_dp
radial_integral_paramagnetic = 0.0_dp
radial_integral_diamagnetic_so = 0.0_dp
radial_integral_paramagnetic_so = 0.0_dp
radial_integral_rmc = 0.0_dp
do nt=1, ntyp
do il1=1, paw_nbeta(nt)
l1 = psphi(nt,il1)%label%l
kkpsi = aephi(nt,il1)%kkpsi
nrc = psphi(nt,il1)%label%nrc
write(0,*) "ZZZtmptmptmp: ", kkpsi, nrc
allocate ( work(kkpsi) )
do il2 = 1, paw_nbeta(nt)
l2 = psphi(nt,il2)%label%l
IF ( l1 /= l2 ) CYCLE
!
! NMR shielding, diamagnetic
!
!work = 0.0_dp
do j = 1, nrc
work(j) = (aephi(nt,il1)%psi(j)*aephi(nt,il2)%psi(j)-&
psphi(nt,il1)%psi(j)*psphi(nt,il2)%psi(j))/r(j,nt)
enddo
!work(1) = 0.0_dp
CALL simpson( nrc, work, rab(:nrc,nt), &
radial_integral_diamagnetic(il1,il2,nt) )
!
! NMR shielding, paramagnetic
!
! calculate radial integration on atom site
! <aephi|1/r^3|aephi>-<psphi|1/r^3|psphi>
!
!work(1) = 0.0_dp
do j = 1, nrc
work(j) = &
( aephi(nt,il1)%psi(j) * aephi(nt,il2)%psi(j) &
- psphi(nt,il1)%psi(j) * psphi(nt,il2)%psi(j) ) &
/ r(j,nt) ** 3
end do
!work(1) = 0.0_dp
call simpson( nrc, work, rab(:,nt), &
radial_integral_paramagnetic(il1,il2,nt) )
write(stdout,*) "WWW1: ", l2, il1, il2, &
radial_integral_paramagnetic(il1,il2,nt) / c**2 * 1e6 * 4
! Calculate the radial integral only if the radial potential
! is present
IF ( .NOT. vloc_present ( nt ) ) CYCLE
!
! g tensor, relativistic mass correction
!
ALLOCATE ( kinetic_aephi ( kkpsi ), kinetic_psphi ( kkpsi ) )
CALL radial_kinetic_energy ( l2, r(:nrc,nt), &
aephi(nt,il2)%psi(:nrc), kinetic_aephi(:nrc) )
CALL radial_kinetic_energy ( l2, r(:nrc,nt), &
psphi(nt,il2)%psi(:nrc), kinetic_psphi(:nrc) )
do j = 1, nrc
work(j) = ( aephi(nt,il1)%psi(j) * kinetic_aephi(j) &
- psphi(nt,il1)%psi(j) * kinetic_psphi(j) )
end do
DEALLOCATE ( kinetic_aephi, kinetic_psphi )
!work(1) = 0.0_dp
CALL simpson ( nrc, work, rab(:,nt), &
radial_integral_rmc(il1,il2,nt) )
write(stdout,*) "WWW2: ", l2, il1, il2, &
radial_integral_rmc(il1,il2,nt)
ALLOCATE ( aephi_dvloc_dr ( nrc ), psphi_dvloc_dr ( nrc ) )
CALL radial_derivative ( r(:nrc,nt), &
gipaw_ae_vloc ( :nrc, nt ), &
aephi_dvloc_dr ( :nrc ) )
CALL radial_derivative ( r(:nrc,nt), &
gipaw_ps_vloc ( :nrc, nt ), &
psphi_dvloc_dr ( :nrc ) )
!
! g tensor, diamagnetic
!
do j = 1, nrc
work(j) = ( aephi(nt,il1)%psi(j) * aephi_dvloc_dr(j) &
* aephi(nt,il2)%psi(j) - psphi(nt,il1)%psi(j) &
* psphi_dvloc_dr(j) * psphi(nt,il2)%psi(j) ) &
* r(j,nt)
end do
!work(1) = 0.0_dp
call simpson( nrc, work, rab(:,nt), &
radial_integral_diamagnetic_so(il1,il2,nt) )
write(stdout,*) "WWW3: ", l2, il1, il2, &
radial_integral_diamagnetic_so(il1,il2,nt) / c
!
! g tensor, paramagnetic
!
!work(1) = 0.0_dp
do j = 1, nrc
work(j) = ( aephi(nt,il1)%psi(j) * aephi_dvloc_dr(j) &
* aephi(nt,il2)%psi(j) - psphi(nt,il1)%psi(j) &
* psphi_dvloc_dr(j) * psphi(nt,il2)%psi(j) ) &
/ r(j,nt)
end do
if ( l1 == 0 ) then
do j = 1, nrc
write(90,*) r(j,nt), work(j)*r(j,nt)**2
end do
write(90,*) ""
end if
!work(1) = 0.0_dp
call simpson( nrc,work,rab(:,nt), &
radial_integral_paramagnetic_so(il1,il2,nt) )
write(stdout,*) "WWW4: ", l2, il1, il2, &
radial_integral_paramagnetic_so(il1,il2,nt) / c
DEALLOCATE ( aephi_dvloc_dr, psphi_dvloc_dr )
enddo
DEALLOCATE ( work )
enddo
enddo
!</apsi>
! terms for paramagnetic
!<apsi>
allocate ( lx ( lmaxx**2, lmaxx**2 ) )
allocate ( ly ( lmaxx**2, lmaxx**2 ) )
allocate ( lz ( lmaxx**2, lmaxx**2 ) )
allocate ( lm2l ( lmaxx**2 ), lm2m ( lmaxx**2 ) )
lm = 0
do l = 0, lmaxx - 1
do m = 0, l
lm = lm + 1
lm2l ( lm ) = l
lm2m ( lm ) = m
if ( m /= 0 ) then
lm = lm + 1
lm2l ( lm ) = l
lm2m ( lm ) = - m
end if
end do
end do
lx = 0.0_dp
ly = 0.0_dp
lz = 0.0_dp
do lm2 = 1, lmaxx**2
do lm1 = 1, lmaxx**2
if ( lm2l ( lm1 ) /= lm2l ( lm2 ) ) cycle
l = lm2l ( lm1 )
m1 = lm2m ( lm1 )
m2 = lm2m ( lm2 )
! L_x, L_y
if ( m2 == 0 ) then
if ( m1 == -1 ) then
lx ( lm1, lm2 ) = - sqrt(real(l*(l+1),dp)) / sqrt(2.0_dp)
else if ( m1 == +1 ) then
ly ( lm1, lm2 ) = + sqrt(real(l*(l+1),dp)) / sqrt(2.0_dp)
end if
else if ( m1 == 0 ) then
if ( m2 == -1 ) then
lx ( lm1, lm2 ) = + sqrt(real(l*(l+1),dp)) / sqrt(2.0_dp)
else if ( m2 == +1 ) then
ly ( lm1, lm2 ) = - sqrt(real(l*(l+1),dp)) / sqrt(2.0_dp)
end if
else
abs_m1 = abs ( m1 )
abs_m2 = abs ( m2 )
sign_m1 = sign ( 1, m1 )
sign_m2 = sign ( 1, m2 )
alpha_lm = sqrt(real(l*(l+1)-abs_m2*(abs_m2+1),dp))
beta_lm = sqrt(real(l*(l+1)-abs_m2*(abs_m2-1),dp))
if ( abs_m1 == abs_m2 + 1 ) then
lx ( lm1, lm2 ) =-( sign_m2 - sign_m1 ) * alpha_lm / 4.0_dp
ly ( lm1, lm2 ) = ( sign_m2 + sign_m1 ) * alpha_lm / 4.0_dp &
/ sign_m2
else if ( abs_m1 == abs_m2 - 1 ) then
lx ( lm1, lm2 ) =-( sign_m2 - sign_m1 ) * beta_lm / 4.0_dp
ly ( lm1, lm2 ) =-( sign_m2 + sign_m1 ) * beta_lm / 4.0_dp &
/ sign_m2
end if
end if
! L_z
if ( m1 == - m2 ) then
lz ( lm1, lm2 ) = - m2
end if
end do
end do
write(stdout,'(A)') "lx:"
write(stdout,'(9F8.5)') lx
write(stdout,'(A)') "ly:"
write(stdout,'(9F8.5)') ly
write(stdout,'(A)') "lz:"
write(stdout,'(9F8.5)') lz
! Checks
mysum1 = 0
mysum2 = 0
do lm2 = 1, lmaxx**2
do lm1 = 1, lmaxx**2
if ( lm2l ( lm1 ) /= lm2l ( lm2 ) ) cycle
l = lm2l ( lm2 )
mysum1(1,l+1) = mysum1(1,l+1) + lx(lm1,lm2)
mysum2(1,l+1) = mysum2(1,l+1) + lx(lm1,lm2)**2
mysum1(2,l+1) = mysum1(2,l+1) + ly(lm1,lm2)
mysum2(2,l+1) = mysum2(2,l+1) + ly(lm1,lm2)**2
mysum1(3,l+1) = mysum1(3,l+1) + lz(lm1,lm2)
mysum2(3,l+1) = mysum2(3,l+1) + lz(lm1,lm2)**2
end do
end do
write(stdout,'(A,9F8.4)') "DDD1x: ", mysum1(1,:)
write(stdout,'(A,9F8.4)') "DDD1y: ", mysum1(2,:)
write(stdout,'(A,9F8.4)') "DDD1z: ", mysum1(3,:)
write(stdout,'(A,9F8.4)') "DDD2x: ", mysum2(1,:)
write(stdout,'(A,9F8.4)') "DDD2y: ", mysum2(2,:)
write(stdout,'(A,9F8.4)') "DDD2z: ", mysum2(3,:)
deallocate ( lm2l, lm2m )
!
! calculate radial integration on atom site
! <aephi|1/r^3|aephi>-<psphi|1/r^3|psphi>
!
! allocate ( radial_integral_paramagnetic(paw_nkb,paw_nkb,ntypx) )
! radial_integral_paramagnetic = 0.0_dp
! do nt=1,ntyp
! do il1=1,paw_nbeta(nt)
! l1 = psphi(nt,il1)%label%l
! kkpsi = aephi(nt,il1)%kkpsi
! allocate ( work(kkpsi) )
! nrc = psphi(nt,il1)%label%nrc
! do il2=1,paw_nbeta(nt)
! l2 = psphi(nt,il2)%label%l
! IF ( l1 /= l2 ) CYCLE
! work=0.0_dp
! do j = 1, nrc
! work(j) = (aephi(nt,il1)%psi(j)*aephi(nt,il2)%psi(j)-&
! psphi(nt,il1)%psi(j)*psphi(nt,il2)%psi(j))/r(j,nt)**3
! enddo
!
! !work(1) = 0.0_dp
! call simpson( nrc,work,rab(:,nt), &
! radial_integral_paramagnetic(il1,il2,nt) )
!
! if ( il1 == 1 .and. il2 == 1 ) then
! write(stdout,*) "WWW: ", il1, il2, &
! radial_integral_paramagnetic(il1,il2,nt) / c**2 * 1e6 * 4
! end if
!
! enddo
!
! deallocate(work)
! enddo
! enddo
!</apsi>
! stop "DONE"
! computes the total local potential (external+scf) on the smooth grid
call set_vrs (vrs, vltot, vr, nrxx, nspin, doublegrid)
! compute the D for the pseudopotentials
call newd
! set non linear core correction stuff
nlcc_any = .false.
do nt = 1, ntyp
nlcc_any = nlcc_any.or.nlcc (nt)
enddo
!!if (nlcc_any) allocate (drc( ngm, ntyp))
!! setup all gradient correction stuff
!!call setup_dgc
! computes the number of occupied bands for each k point
nbnd_occ (:) = 0
do ik = 1, nks
do ibnd = 1, nbnd
if ( wg(ibnd,ik) > 1e-6 ) then
nbnd_occ(ik) = ibnd
end if
end do
end do
! computes alpha_pv
emin = et (1, 1)
do ik = 1, nks
do ibnd = 1, nbnd
emin = min (emin, et (ibnd, ik) )
enddo
enddo
#ifdef __PARA
! find the minimum across pools
call poolextreme (emin, -1)
#endif
if (degauss.ne.0.d0) then
call errore('nmr_setup', 'implemented only for insulators', -1)
else
emax = et (1, 1)
do ik = 1, nks
do ibnd = 1, nbnd
emax = max (emax, et (ibnd, ik) )
enddo
enddo
#ifdef __PARA
! find the maximum across pools
call poolextreme (emax, + 1)
#endif
alpha_pv = 2.d0 * (emax - emin)
endif
! avoid zero value for alpha_pv
alpha_pv = max (alpha_pv, 1.0d-2)
call stop_clock('nmr_setup')
CONTAINS
SUBROUTINE radial_kinetic_energy ( l, rdata, ydata, kin_ydata )
USE splinelib
INTEGER, INTENT ( IN ) :: l
REAL(dp), INTENT ( IN ) :: rdata ( : ), ydata ( : )
REAL(dp), INTENT ( OUT ) :: kin_ydata ( : )
REAL(dp) :: d1
d1 = ( ydata(2) - ydata(1) ) / ( rdata(2) - rdata(1) )
CALL spline ( rdata, ydata, 0.d0, d1, kin_ydata )
kin_ydata = - kin_ydata + l*(l+1) * ydata / rdata ** 2
END SUBROUTINE radial_kinetic_energy
SUBROUTINE radial_derivative ( rdata, ydata, dydata_dr )
USE splinelib
! ydata passed as y * r
REAL(dp), INTENT ( IN ) :: rdata ( : ), ydata ( : )
REAL(dp), INTENT ( OUT ) :: dydata_dr ( : )
INTEGER :: j
REAL(dp) :: d1, tab_d2y ( SIZE ( ydata ) )
d1 = ( ydata(2) - ydata(1) ) / ( rdata(2) - rdata(1) )
CALL spline ( rdata, ydata, 0.d0, d1, tab_d2y )
DO j = 1, SIZE ( ydata )
dydata_dr ( j ) = &
( splint_deriv ( rdata, ydata, tab_d2y, rdata ( j ) ) &
- ydata ( j ) / rdata ( j ) ) / rdata ( j )
END DO
END SUBROUTINE radial_derivative
END SUBROUTINE nmr_setup
!-----------------------------------------------------------------------
END MODULE nmr_module
!-----------------------------------------------------------------------

46
GIPAW/stop_code.f90 Normal file
View File

@ -0,0 +1,46 @@
!
! Copyright (C) 2001-2004 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
SUBROUTINE stop_code( flag )
!----------------------------------------------------------------------------
!
! ... Synchronize processes before stopping.
!
USE kinds, ONLY : DP
USE mp, ONLY : mp_end, mp_barrier
!
USE parallel_include
!
IMPLICIT NONE
!
LOGICAL :: flag
!
!
CALL mp_barrier()
!
CALL mp_end()
!
#if defined (__T3E)
!
! ... set streambuffers off
!
CALL set_d_stream( 0 )
!
#endif
!
IF ( flag ) THEN
!
STOP
!
ELSE
!
STOP 1
!
ENDIF
!
END SUBROUTINE stop_code

649
GIPAW/suscept_crystal.f90 Normal file
View File

@ -0,0 +1,649 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE suscept_crystal
!-----------------------------------------------------------------------
!
! ... Compute the "bare" susceptibility as in Eq.(64-65) of
! ... PRB 63, 245101 (2001)
! ... add more comments
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE io_files, ONLY : nwordwfc, iunwfc
USE cell_base, ONLY : at, bg, omega, tpiba, tpiba2
USE wavefunctions_module, ONLY : evc
USE klist, ONLY : nks, nkstot, wk, xk, nelec
USE wvfct, ONLY : nbnd, npwx, npw, igk, wg, g2kin, &
current_k
USE lsda_mod, ONLY : current_spin, lsda, isk
USE becmod, ONLY : becp
USE symme, ONLY : nsym, s, ftau
USE mp_global, ONLY : my_pool_id, npool, me_pool, root_pool
USE pwcom
USE nmr_module
!<apsi>
USE paw, ONLY: paw_vkb, paw_becp, paw_nkb, aephi, &
psphi, paw_nh, paw_nhtol, &
paw_nhtom, paw_indv, paw_nbeta
USE ions_base, ONLY : nat
!</apsi>
!-- local variables ----------------------------------------------------
IMPLICIT NONE
complex(dp), allocatable, dimension(:,:,:) :: p_evc, vel_evc, g_vel_evc
complex(dp), allocatable :: aux(:,:)
! Q tensor of eq. (65) (pGv => HH in Paratec, vGv => VV in Paratec)
real(dp) :: q_pGv(3,3,-1:1), q_vGv(3,3,-1:1)
! F tensor of eq. (64)
real(dp) :: f_pGv(3,3,-1:1), f_vGv(3,3,-1:1)
! chi_bare tensor of eq. (64)
real(dp) :: chi_bare_pGv(3,3), chi_bare_vGv(3,3)
! f-sum rule
real(dp) :: f_sum(3,3)
integer :: ia, ib, ik, ipol, jpol, i, ibnd, isign
real(dp) :: tmp(3,3), q(3), braket, sigma_bare(3,3,nat)
real(dp) :: diamagnetic_corr_tensor(3,3,nat)
real(dp) :: paramagnetic_corr_tensor(3,3,nat)
real(dp) :: sigma_diamagnetic(3,3,nat)
real(dp) :: sigma_paramagnetic(3,3,nat)
complex(dp), external :: ZDOTC
!-----------------------------------------------------------------------
! allocate memory
allocate ( p_evc(npwx,nbnd,3), vel_evc(npwx,nbnd,3), &
aux(npwx,nbnd), g_vel_evc(npwx,nbnd,3) )
! zero the Q tensors
q_pGv(:,:,:) = 0.0_dp
q_vGv(:,:,:) = 0.0_dp
! zero the current and the field
j_bare(:,:,:,:) = (0.0_dp,0.0_dp)
b_ind(:,:,:) = (0.0_dp,0.0_dp)
sigma_diamagnetic = 0.0_dp
sigma_paramagnetic = 0.0_dp
write(stdout, '(5X,''Computing the magnetic susceptibility'')')
!====================================================================
! loop over k-points
!====================================================================
do ik = 1, nks
#ifdef __PARA
if (me_pool == root_pool) &
write(*, '(5X,''k-point #'',I5,'' of '',I5,6X,''pool #'',I3)') &
ik, nks, my_pool_id+1
#else
write(stdout, '(5X,''k-point #'',I5,'' of '',I5)') ik, nks
#endif
current_k = ik
current_spin = isk(ik)
! initialize at k-point k
call gk_sort(xk(1,ik), ngm, g, ecutwfc/tpiba2, npw, igk, g2kin)
g2kin(:) = g2kin(:) * tpiba2
call init_us_2(npw,igk,xk(1,ik),vkb)
! read wfcs from file and compute becp
call davcio (evc, nwordwfc, iunwfc, ik, -1)
call ccalbec (nkb, npwx, npw, nbnd, becp, vkb, evc)
!<apsi>
call init_paw_2_no_phase (npw, igk, xk (1, ik), paw_vkb)
call ccalbec (paw_nkb, npwx, npw, nbnd, paw_becp, paw_vkb, evc)
diamagnetic_corr_tensor = 0.0
call diamagnetic_correction ( diamagnetic_corr_tensor )
sigma_diamagnetic = sigma_diamagnetic + diamagnetic_corr_tensor
!</apsi>
! this is the case q = 0 (like the case of the f-sum rule)
q(:) = 0.0_dp
!!!write(*,'(''q='',3(F12.4))') q
call compute_u_kq(ik, q)
evc = evq
! compute p_k|evc>, v_k|evc> and G_k v_{k,k}|evc>
call apply_operators
!------------------------------------------------------------------
! f-sum rule (pGv term only)
!------------------------------------------------------------------
do ia = 1, 3
do ib = 1, 3
do ibnd = 1, nbnd_occ(ik)
braket = 2.0_dp*real(ZDOTC(npw, p_evc(1,ibnd,ia), 1, &
g_vel_evc(1,ibnd,ib), 1), DP)
f_sum(ia,ib) = f_sum(ia,ib) + wg(ibnd,ik) * braket
enddo
enddo
enddo
!------------------------------------------------------------------
! pGv and vGv contribution to chi_{bare}
!------------------------------------------------------------------
do i = 1, 3
call add_to_tensor(q_pGv(:,:,0), p_evc, g_vel_evc)
call add_to_tensor(q_vGv(:,:,0), vel_evc, g_vel_evc)
enddo
!------------------------------------------------------------------
! loop over -q and +q
!------------------------------------------------------------------
do isign = -1, 1, 2
! loop over cartesian directions
do i = 1, 3
! set the q vector
q(:) = 0.0_dp
q(i) = dble(isign) * q_nmr
!!!write(*,'(''q='',3(F12.4))') q
! compute the wfcs at k+q
call compute_u_kq(ik, q)
! compute p_k|evc>, v_k|evc> and G_{k+q} v_{k+q,k}|evc>
call apply_operators
!<apsi>
call init_paw_2_no_phase (npw, igk, xk(:,ik)+q(:), paw_vkb)
call paramagnetic_correction ( paramagnetic_corr_tensor )
call add_to_sigma_para ( paramagnetic_corr_tensor, sigma_paramagnetic )
!</apsi>
! pGv and vGv contribution to chi_bare
call add_to_tensor(q_pGv(:,:,isign), p_evc, g_vel_evc)
call add_to_tensor(q_vGv(:,:,isign), vel_evc, g_vel_evc)
! now the j_bare term
call add_to_current(j_bare(:,:,:,current_spin), evc, g_vel_evc)
enddo ! i
enddo ! isign
enddo ! ik
#ifdef __PARA
! reduce over G-vectors
call reduce(9, f_sum)
call reduce(3*9, q_pGv)
call reduce(3*9, q_vGv)
#endif
#ifdef __PARA
! reduce over k-points
call poolreduce(9, f_sum)
call poolreduce(3*9, q_pGv)
call poolreduce(3*9, q_vGv)
call poolreduce(nrxxs*nspin*9, j_bare)
call poolreduce(9*nat, sigma_diamagnetic)
call poolreduce(9*nat, sigma_paramagnetic)
#endif
!====================================================================
! print out results
!====================================================================
write(stdout,'(5X,''End of magnetic susceptibility calculation'')')
write(stdout,*)
! f-sum rule
if (iverbosity > 0) then
write(stdout, '(5X,''f-sum rule:'')')
write(stdout, tens_fmt) f_sum
endif
call sym_cart_tensor(f_sum)
write(stdout, '(5X,''f-sum rule (symmetrized):'')')
write(stdout, tens_fmt) f_sum
! F_{ij} = (2 - \delta_{ij}) Q_{ij}
do ipol = 1, 3
do jpol = 1, 3
f_pGv(ipol,jpol,:) = 2.0_dp*q_pGv(ipol,jpol,:)
if (ipol == jpol) f_pGv(ipol,jpol,:) = q_pGv(ipol,jpol,:)
f_vGv(ipol,jpol,:) = 2.0_dp*q_vGv(ipol,jpol,:)
if (ipol == jpol) f_vGv(ipol,jpol,:) = q_vGv(ipol,jpol,:)
enddo
enddo
! compute chi_bare both pGv and vGv terms
chi_bare_pGv(:,:) = f_pGv(:,:,1) - 2.0_dp*f_pGv(:,:,0) + f_pGv(:,:,-1)
chi_bare_pGv(:,:) = -0.5_dp * chi_bare_pGv(:,:) / (c * q_nmr * tpiba)**2
if (iverbosity > 0) then
write(stdout, '(5X,''chi_bare pGv (HH) in paratec units:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_pGv(:,:) * c**2
endif
call sym_cart_tensor(chi_bare_pGv)
if (iverbosity > 0) then
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_pGv(:,:) * c**2
endif
chi_bare_vGv(:,:) = f_vGv(:,:,1) - 2.0_dp*f_vGv(:,:,0) + f_vGv(:,:,-1)
chi_bare_vGv(:,:) = -0.5_dp * chi_bare_vGv(:,:) / (c * q_nmr * tpiba)**2
if (iverbosity > 0) then
write(stdout, '(5X,''chi_bare vGv (VV) in paratec units:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_vGv(:,:) * c**2
endif
call sym_cart_tensor(chi_bare_vGv)
if (iverbosity > 0) then
write(stdout, '(3(5X,3(F12.6,2X)/))') chi_bare_vGv(:,:) * c**2
endif
! convert from atomic units to 10^{-6} cm^3 / mol
tmp(:,:) = chi_bare_pGv(:,:) * 1e6_dp * a0_to_cm**3.0_dp * avogadro
write(stdout, '(5X,''chi_bare pGv (HH) in 10^{-6} cm^3/mol:'')')
write(stdout, tens_fmt) tmp(:,:)
tmp(:,:) = chi_bare_vGv(:,:) * 1e6_dp * a0_to_cm**3.0_dp * avogadro
write(stdout, '(5X,''chi_bare vGv (VV) in 10^{-6} cm^3/mol:'')')
write(stdout, tens_fmt) tmp(:,:)
!--------------------------------------------------------------------
! now get the current, induced field and chemical shifts
!--------------------------------------------------------------------
chi_bare_pGv(:,:) = chi_bare_pGv(:,:) / omega
j_bare(:,:,:,:) = j_bare(:,:,:,:) / (2.0_dp * q_nmr * tpiba * c * omega)
!nsym = 1
! either you symmetrize the current ...
do i = 1, nspin
#ifdef __PARA
call psymmetrize_field(j_bare(:,:,:,i),1)
#else
call symmetrize_field(j_bare(:,:,:,i),1)
#endif
enddo
! compute induced field
do ipol = 1, 3
call biot_savart(ipol)
enddo
do i = 1, nspin
if (trim(filcurr) /= '') &
call write_tensor_field(filcurr, i, j_bare(1,1,1,i))
enddo
if (trim(filfield) /= '') &
call write_tensor_field(filfield, 0, b_ind_r)
! ... or you symmetrize the induced field
!call symmetrize_field(b_ind_r,0)
!call field_to_reciprocal_space
! compute chemical shifts
call compute_sigma_bare(chi_bare_pGv, sigma_bare)
call compute_sigma_diamagnetic( sigma_diamagnetic )
call compute_sigma_paramagnetic( sigma_paramagnetic )
deallocate(p_evc, vel_evc, aux, g_vel_evc, j_bare, b_ind)
CONTAINS
!====================================================================
! compute p_k|evc>, v_k|evc> and G_k v_{k+q,k}|evc>
!====================================================================
SUBROUTINE apply_operators
implicit none
integer ipol
do ipol = 1, 3
call apply_p(evc, p_evc(1,1,ipol), ik, ipol, q)
call apply_vel(evc, vel_evc(1,1,ipol), ik, ipol, q)
! necessary because aux is overwritten by subroutine greenfunction
aux(:,:) = vel_evc(:,:,ipol)
call greenfunction(ik, aux, g_vel_evc(1,1,ipol), q)
enddo
END SUBROUTINE apply_operators
!====================================================================
! add contribution the Q tensors
! Q_{\alpha,\beta} += <(e_i \times ul)_\alpha | (e_i \times ur)_\beta>
!====================================================================
SUBROUTINE add_to_tensor(qt, ul, ur)
implicit none
real(dp), intent(inout) :: qt(3,3)
complex(dp), intent(in) :: ul(npwx,nbnd,3), ur(npwx,nbnd,3)
real(dp) :: braket
integer :: ibnd, ia, ib, comp_ia, comp_ib, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
do ia = 1, 3 ! ia = alpha
comp_ia = ind(ia,i)
if (mult(ia,i) == 0) cycle
do ib = 1, 3 ! ib = beta
comp_ib = ind(ib,i)
if (mult(ib,i) == 0) cycle
do ibnd = 1, nbnd_occ(ik)
braket = real(ZDOTC(npw, ul(1,ibnd,comp_ia), 1, &
ur(1,ibnd,comp_ib), 1), DP)
qt(ia,ib) = qt(ia,ib) + wg(ibnd,ik) * &
braket * mult(ia,i) * mult(ib,i)
enddo ! ibnd
enddo ! ib
enddo ! ia
!#ifdef __PARA
! call reduce(9, qt)
!#endif
END SUBROUTINE add_to_tensor
!====================================================================
! add contribution the the current
! j(r)_{\alpha,\beta} += <ul|J(r)|(B\times e_i \cdot ur)>
!====================================================================
SUBROUTINE add_to_current(j, ul, ur)
implicit none
real(dp), intent(inout) :: j(nrxxs,3,3)
complex(dp), intent(in) :: ul(npwx,nbnd), ur(npwx,nbnd,3)
real(dp) :: braket, fact
integer :: ibdir, icomp, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
! loop over B direction
do ibdir = 1, 3
if (i == ibdir) cycle
icomp = ind(ibdir, i)
fact = real(mult(ibdir,i)*isign)
call j_para(fact, ul(1,1), ur(1,1,icomp), ik, q, j(1,1,ibdir))
enddo
END SUBROUTINE add_to_current
!====================================================================
! ...
!====================================================================
SUBROUTINE diamagnetic_correction ( diamagnetic_tensor )
USE atom, ONLY : r, rab
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE nmr_module, ONLY : c
implicit none
! Arguments
real(dp), intent(inout):: diamagnetic_tensor(3,3,nat)
integer :: l1, m1, lm1, l2, m2, lm2, ih, ikb, nbs1, jh, jkb, nbs2
integer :: nt, ibnd, na, lm, nrc, ijkb0
complex(dp) , allocatable :: efg_corr(:,:)
complex(dp) :: bec_product
allocate (efg_corr(lmaxx**2,nat))
efg_corr = 0.0_dp
! rc=1.60_dp
! nrc=count(r(1:msh(1),1).le.rc)
!
! calculate radial integration on atom site
! <aephi|1/r^3|aephi>-<psphi|1/r^3|psphi>
!
!
! calculation of the reconstruction part
!
do ibnd = 1, nbnd
ijkb0 = 0
do nt = 1, ntyp
do na = 1, nat
if (ityp (na) .eq.nt) then
do ih = 1, paw_nh (nt)
ikb = ijkb0 + ih
nbs1=paw_indv(ih,nt)
l1=paw_nhtol(ih,nt)
m1=paw_nhtom(ih,nt)
lm1=m1+l1**2
do jh = 1, paw_nh (nt)
jkb = ijkb0 + jh
nbs2=paw_indv(jh,nt)
l2=paw_nhtol(jh,nt)
m2=paw_nhtom(jh,nt)
lm2=m2+l2**2
bec_product = paw_becp(jkb,ibnd) &
* CONJG(paw_becp(ikb,ibnd))
!<apsi> s/non-trace-zero component
! 2/3 to separate the non-trace vanishing component
! 1/(2c^2) from the equation (59) in PM-PRB
IF ( l1 == l2 .AND. m1 == m2 ) THEN
diamagnetic_tensor(1,1,na) &
= diamagnetic_tensor(1,1,na) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic(nbs1,nbs2,nt) &
* wg(ibnd,ik) / (2.0_dp*c**2)
diamagnetic_tensor(2,2,na) &
= diamagnetic_tensor(2,2,na) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic(nbs1,nbs2,nt) &
* wg(ibnd,ik) / (2.0_dp*c**2)
diamagnetic_tensor(3,3,na) &
= diamagnetic_tensor(3,3,na) &
+ 2.0_dp / 3.0_dp * bec_product &
* radial_integral_diamagnetic(nbs1,nbs2,nt) &
* wg(ibnd,ik) / (2.0_dp*c**2)
END IF
! 2/3 to separate the non-trace vanishing component
do lm = 5, 9
efg_corr(lm,na) = efg_corr(lm,na) &
+ bec_product / 3.0_dp &
* radial_integral_diamagnetic(nbs1,nbs2,nt) &
* ap(lm,lm1,lm2) * wg(ibnd,ik) / (2.0_dp*c**2)
enddo
enddo
enddo
ijkb0 = ijkb0 + paw_nh (nt)
endif
enddo
enddo
enddo
! write(6,'("DDD1",5F14.8)') efg_corr(5:9,1)
! write(6,'("DDD2",5F14.8)') efg_corr(5:9,2)
!
! transform in cartesian coordinates
!
efg_corr(5:9,:nat) = - sqrt(4.0_dp * pi/5.0_dp) * efg_corr(5:9,:nat)
diamagnetic_tensor(1,1,:) = diamagnetic_tensor(1,1,:) &
+ sqrt(3.0_dp) * efg_corr(8,:) - efg_corr(5,:)
diamagnetic_tensor(2,2,:) = diamagnetic_tensor(2,2,:) &
- sqrt(3.0_dp) * efg_corr(8,:) - efg_corr(5,:)
diamagnetic_tensor(3,3,:) = diamagnetic_tensor(3,3,:) &
+ efg_corr(5,:) * 2.0_dp
diamagnetic_tensor(1,2,:) = diamagnetic_tensor(1,2,:) &
+ efg_corr(9,:) * sqrt(3.0_dp)
diamagnetic_tensor(2,1,:) = diamagnetic_tensor(1,2,:)
diamagnetic_tensor(1,3,:) = diamagnetic_tensor(1,3,:) &
- efg_corr(6,:) * sqrt(3.0_dp)
diamagnetic_tensor(3,1,:) = diamagnetic_tensor(1,3,:)
diamagnetic_tensor(2,3,:) = diamagnetic_tensor(2,3,:) &
- efg_corr(7,:) * sqrt(3.0_dp)
diamagnetic_tensor(3,2,:) = diamagnetic_tensor(2,3,:)
! efg_corr(5,:) = 3z^2-1
! efg_corr(6,:) = -xz
! efg_corr(7,:) = -yz
! efg_corr(8,:) = x^2-y^2
! efg_corr(9,:) = xy
deallocate ( efg_corr )
END SUBROUTINE diamagnetic_correction
!====================================================================
! ...
!====================================================================
SUBROUTINE paramagnetic_correction ( paramagnetic_tensor )
USE ions_base, ONLY : nat, ityp, ntyp => nsp
USE nmr_module, ONLY : c
implicit none
! Arguments
real(dp), intent(inout):: paramagnetic_tensor(3,3,nat)
integer :: l1, m1, lm1, l2, m2, lm2, ih, ikb, nbs1, jh, jkb, nbs2
integer :: nt, ibnd, na, lm, j, ijkb0, ipol
complex(dp) :: bec_product
complex(dp) , allocatable :: efg_corr(:,:)
integer, parameter :: ng_ = 27, lmax2_ = 16
integer :: mg, i1, i2, i3
real(DP) :: g_ (3, ng_), gg_ (ng_)
real(DP) :: ylm_ (ng_,lmax2_)
!--------------------------------------------------------------------------
allocate (efg_corr(3,nat))
!
! calculation of the reconstruction part
!
do ipol = 1, 3
if ( ipol == i ) cycle !TESTTESTTEST
call ccalbec (paw_nkb, npwx, npw, nbnd, paw_becp2, paw_vkb, &
g_vel_evc(1,1,ipol))
efg_corr = 0.0_dp
do ibnd = 1, nbnd
ijkb0 = 0
do nt = 1, ntyp
do na = 1, nat
if (ityp (na) .eq.nt) then
do ih = 1, paw_nh (nt)
ikb = ijkb0 + ih
nbs1=paw_indv(ih,nt)
l1=paw_nhtol(ih,nt)
m1=paw_nhtom(ih,nt)
lm1=m1+l1**2
do jh = 1, paw_nh (nt)
jkb = ijkb0 + jh
nbs2=paw_indv(jh,nt)
l2=paw_nhtol(jh,nt)
m2=paw_nhtom(jh,nt)
lm2=m2+l2**2
if ( l1 /= l2 ) cycle
bec_product = CONJG(paw_becp(ikb,ibnd)) &
* paw_becp2(jkb,ibnd)
efg_corr(1,na) = efg_corr(1,na) &
+ bec_product &
* radial_integral_paramagnetic(nbs1,nbs2,nt) &
* lx ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
efg_corr(2,na) = efg_corr(2,na) &
+ bec_product &
* radial_integral_paramagnetic(nbs1,nbs2,nt) &
* ly ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
efg_corr(3,na) = efg_corr(3,na) &
+ bec_product &
* radial_integral_paramagnetic(nbs1,nbs2,nt) &
* lz ( lm1, lm2 ) * wg(ibnd,ik) / c ** 2
enddo
enddo
ijkb0 = ijkb0 + paw_nh (nt)
endif
enddo
enddo
enddo
paramagnetic_tensor ( :, ipol, : ) = REAL ( efg_corr, dp )
write(6,'("DDD1",2I3,3(F16.7,2X)') &
ipol, i*isign, REAL ( efg_corr(1:3,1) ) * 1e6
!write(6,'("DDD2",2I3,3(F16.7,2X)') &
! ipol, i*isign, REAL ( efg_corr(1:3,2) ) * 1e6
end do
deallocate(efg_corr)
END SUBROUTINE paramagnetic_correction
!====================================================================
! ...
!====================================================================
SUBROUTINE add_to_sigma_para( paramagnetic_correction, sigma_paramagnetic )
implicit none
real(dp), intent(in) :: paramagnetic_correction(3,3,nat)
real(dp), intent(inout) :: sigma_paramagnetic(3,3,nat)
real(dp) :: fact
integer :: ibdir, icomp, ipol, ind(3,3), mult(3,3)
! index for the cross product
ind(:,1) = (/ 1, 3, 2/); mult(:,1) = (/ 0,-1, 1 /)
ind(:,2) = (/ 3, 2, 1/); mult(:,2) = (/ 1, 0,-1 /)
ind(:,3) = (/ 2, 1, 3/); mult(:,3) = (/-1, 1, 0 /)
! loop over B direction
do ibdir = 1, 3
if (i == ibdir) cycle
icomp = ind(ibdir, i)
fact = real(mult(ibdir,i)*isign)
do ipol = 1, 3
sigma_paramagnetic ( ipol, icomp, : ) &
= sigma_paramagnetic ( ipol, icomp, : ) &
+ fact * paramagnetic_correction ( ipol, ibdir, : ) &
/ ( 2 * q_nmr * tpiba )
! Do iq=1, 3 ! loop over all q-points
! ...
! Do iperm0 =1,-1,-2
! b0 = Mod(iq+iperm0+2,3) +1 ! gives different b0 for iperm0
! p0 = Mod(iq-iperm0+2,3) +1 ! gives p0 = abs(q x b0)
! ...
! Call take_nonloc_deriv_kq_k(p0,k_gspace, rk(1),u_k(1,i),&
! ...
! para_corr_shift_tot(b0,:,:,:) = para_corr_shift_tot(b0,:,:,:)-&
! Real(iperm0,dp)*Real(iqsign,dp)*para_corr_shift*&
! kpoints%w(irk)/qmag/dtwo/Real(crys%nspin,dp)
end do
enddo
END SUBROUTINE add_to_sigma_para
END SUBROUTINE suscept_crystal

30
GIPAW/sym_cart_tensor.f90 Normal file
View File

@ -0,0 +1,30 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!-----------------------------------------------------------------------
SUBROUTINE sym_cart_tensor(tens)
!-----------------------------------------------------------------------
!
! ... symmetrize a rank-2 tensor in cartesian coordinates
!
USE kinds, ONLY : DP
USE cell_base, ONLY : at, bg
USE symme, ONLY : s, nsym
IMPLICIT NONE
REAL(DP), INTENT(INOUT) :: tens(3,3)
! cartesian to crystal
call trntns (tens, at, bg, -1)
! symmetrize
call symtns (tens, nsym, s)
! crystal to cartesian
call trntns (tens, at, bg, 1)
END SUBROUTINE sym_cart_tensor

195
GIPAW/symmetrize_field.f90 Normal file
View File

@ -0,0 +1,195 @@
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE symmetrize_field(field, iflag)
!-----------------------------------------------------------------------
!
! symmetrize a tensor field (e.g. current or induced magnetic field)
! iflag = 0 => tensor (e.g. induced B field)
! iflag = 1 => pseudo-tensor (e.g. induced current)
!
! don't use nrxxs: in the parallel case nrx1s*nrx2s*nrx3s /= nrxxs
!
USE kinds, ONLY : DP
USE symme, ONLY : s, nsym
USE cell_base, ONLY : at, bg
USE pwcom
USE nmr_module
!-- parameters ------------------------------------------------------
IMPLICIT NONE
REAL(DP), INTENT(INOUT) :: field(nrx1s*nrx2s*nrx3s,3,3)
INTEGER :: iflag
!-- local variables ----------------------------------------------------
complex(dp), allocatable :: aux(:)
real(dp) :: tmp(3,3)
integer :: i, ipol, jpol
! if no symmetries, return
if (nsym.eq.1) return
! cartesian to crystal
do i = 1, nrx1s*nrx2s*nrx3s
tmp(:,:) = field(i,:,:)
call trntns (tmp, at, bg, -1)
field(i,:,:) = tmp(:,:)
enddo
! symmetrize
call syme2(field, iflag)
! crystal to cartesian
do i = 1, nrx1s*nrx2s*nrx3s
tmp(:,:) = field(i,:,:)
call trntns (tmp, at, bg, 1)
field(i,:,:) = tmp(:,:)
enddo
END SUBROUTINE symmetrize_field
!-----------------------------------------------------------------------
SUBROUTINE psymmetrize_field(field, iflag)
!-----------------------------------------------------------------------
!
! symmetrize a tensor field (e.g. current or induced magnetic field)
! (parallel version)
! iflag = 0 => tensor (e.g. induced B field)
! iflag = 1 => pseudo-tensor (e.g. induced current)
!
USE kinds, ONLY : DP
USE pfft, ONLY : nxx
USE mp_global, ONLY : me_pool
USE pwcom
USE nmr_module
!-- parameters ------------------------------------------------------
IMPLICIT NONE
REAL(DP), INTENT(INOUT) :: field(nxx,3,3)
INTEGER :: iflag
!-- local variables ----------------------------------------------------
real(dp), allocatable :: aux(:,:,:)
integer :: i, j
! if no symmetries, return
if (nsym.eq.1) return
allocate( aux(nrx1s*nrx2s*nrx3s,3,3) )
do i = 1, 3
do j = 1, 3
call gather(field(1,i,j), aux(1,i,j))
enddo
enddo
if ( me_pool == 0 ) call symmetrize_field(aux, iflag)
do i = 1, 3
do j = 1, 3
call scatter(aux(1,i,j), field(1,i,j))
enddo
enddo
deallocate(aux)
END SUBROUTINE psymmetrize_field
!
! Copyright (C) 2001 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!#include "f_defs.h"
!---------------------------------------------------------------------
subroutine syme2 (dvsym, iflag)
!-------------------------------------------------------------------
!
!
use kinds, only : DP
use pwcom
implicit none
real(DP) :: dvsym (nrx1, nrx2, nrx3, 3, 3)
real(DP), allocatable :: aux (:,:,:,:,:)
! the function to symmetrize
! auxiliary space
integer :: ix, jx, kx, ri, rj, rk, irot, ip, jp, lp, mp, iflag
! define a real-space point on the grid
! the rotated points
! counter on symmetries
! counter on polarizations
real(dp) :: det(48), sc(3,3), d
if (nsym.eq.1) return
allocate (aux(nrx1 , nrx2 , nrx3 , 3, 3))
call DCOPY (nrx1 * nrx2 * nrx3 * 9, dvsym, 1, aux, 1)
! compute determinants of transformation matrixes
do irot = 1, nsym
if (iflag == 1) then ! pseudo-tensor
sc(:,:) = dble(s(:,:,irot))
! crystal to cartesian
call trntns (sc, at, bg, 1)
d = sc(1,1)*sc(2,2)*sc(3,3) + &
sc(1,2)*sc(2,3)*sc(3,1) + &
sc(1,3)*sc(2,1)*sc(3,2) - &
sc(1,3)*sc(2,2)*sc(3,1) - &
sc(1,2)*sc(2,1)*sc(3,3) - &
sc(1,1)*sc(2,3)*sc(3,2)
det(irot) = sign(1.d0,d)
else ! tensor
det(irot) = 1.d0
endif
enddo
dvsym (:,:,:,:,:) = 0.d0
!
! symmmetrize
!
do kx = 1, nr3
do jx = 1, nr2
do ix = 1, nr1
do irot = 1, nsym
call ruotaijk(s (1, 1, irot), ftau (1, irot), ix, jx, kx, &
nr1, nr2, nr3, ri, rj, rk)
!
! ruotaijk finds the rotated of ix,jx,kx with the inverse of S
!
do ip = 1, 3
do jp = 1, 3
do lp = 1, 3
do mp = 1, 3
dvsym (ix, jx, kx, ip, jp) = &
dvsym (ix, jx, kx, ip, jp) + det(irot)*&
DBLE (s (ip, lp, irot))* &
DBLE (s (jp, mp, irot))* &
aux (ri, rj, rk, lp, mp)
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
call DSCAL (nrx1 * nrx2 * nrx3 * 9, 1.d0 / DBLE (nsym), dvsym , 1)
deallocate (aux)
return
end subroutine syme2

113
GIPAW/test_sum_rule.f90 Normal file
View File

@ -0,0 +1,113 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE test_f_sum_rule
!-----------------------------------------------------------------------
!
! ... Test the f-sum rule
! ... 2/N_k sum_k sum_n^{occ}
! ... <u_{nk}| p_{k,\alpha} G_k v_{k,\beta} | u_{nk}> =
! ... = -N_{el} \delta_{\alpha,\beta}
! ...
! ... where: p_k = -i\nabla + k and v_k = -i [r, H_k]
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE io_files, ONLY : nwordwfc, iunwfc
USE cell_base, ONLY : at, bg, omega, tpiba, tpiba2
USE wavefunctions_module, ONLY : evc
USE klist, ONLY : nks, nkstot, wk, xk, nelec
USE wvfct, ONLY : nbnd, npwx, npw, igk, wg, g2kin, &
current_k
USE lsda_mod, ONLY : current_spin, lsda, isk
USE becmod, ONLY : becp
USE pwcom
USE nmr_module
!-- local variables ----------------------------------------------------
IMPLICIT NONE
complex(dp), allocatable, dimension(:,:,:) :: p_evc, vel_evc, g_vel_evc
real(dp) :: f_sum(3,3), f_sum_k(3,3), q(3)
integer :: ik, ipol, jpol, ibnd, ig
complex(dp), external :: ZDOTC
! allocate memory
allocate ( p_evc(npwx,nbnd,3), &
vel_evc(npwx,nbnd,3), &
g_vel_evc(npwx,nbnd,3) )
! zero the f-sum
f_sum(:,:) = 0.d0
q(:) = 0.d0
write(stdout, '(5X,''Computing the f-sum rule'')')
!====================================================================
! loop over k-points
!====================================================================
do ik = 1, nks
current_k = ik
current_spin = isk(ik)
! initialize at k-point k
call gk_sort(xk(1,ik), ngm, g, ecutwfc/tpiba2, npw, igk, g2kin)
g2kin(:) = g2kin(:) * tpiba2
call init_us_2(npw,igk,xk(1,ik),vkb)
! read wfcs from file and compute becp
CALL davcio (evc, nwordwfc, iunwfc, ik, -1)
call ccalbec (nkb, npwx, npw, nbnd, becp, vkb, evc)
!q = 0.d0; q(1) = 0.0d0
!write(stdout, '(5X,''computing wfcs at k + q'')')
!call compute_u_kq(ik, q)
!evc = evq
! compute p_k|evc>, v_k|evc> and G_k v_k|evc>
do ipol = 1, 3
call apply_p(evc, p_evc(1,1,ipol), ik, ipol, q)
call apply_vel(evc, vel_evc(1,1,ipol), ik, ipol, q)
call greenfunction(ik, vel_evc(1,1,ipol), g_vel_evc(1,1,ipol), q)
enddo
! k-point contribution to the f-sum rule
f_sum_k = 0.0
! loop over cartesian directions
do jpol = 1, 3
do ipol = 1, 3
do ibnd = 1, nbnd_occ (ik)
f_sum_k(ipol,jpol) = f_sum_k(ipol,jpol) + wg(ibnd,ik) * &
2.d0 * real(ZDOTC(npw, p_evc(1,ibnd,ipol), 1, &
g_vel_evc(1,ibnd,jpol), 1))
enddo
enddo ! ipol
enddo ! jpol
write(stdout, '(5X,''f-sum rule (ik='',I5,''):'')') ik
write(stdout, '(3(5X,3(F12.6,2X)/))') f_sum_k
f_sum(:,:) = f_sum(:,:) + f_sum_k(:,:)
enddo ! ik
#ifdef __PARA
call reduce(9, f_sum)
call poolreduce(9, f_sum)
#endif
write(stdout, '(5X,''f-sum rule:'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') f_sum(:,:)
call sym_cart_tensor(f_sum)
write(stdout, '(5X,''f-sum rule (symmetrized):'')')
write(stdout, '(3(5X,3(F12.6,2X)/))') f_sum
deallocate(p_evc, vel_evc, g_vel_evc)
END SUBROUTINE test_f_sum_rule

View File

@ -0,0 +1,130 @@
!
! Copyright (C) 2001-2005 Quantum-ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
#include "f_defs.h"
!-----------------------------------------------------------------------
SUBROUTINE write_tensor_field(name, ispin, field)
!-----------------------------------------------------------------------
!
! ... write the tensor field in xcrysden format
!
USE kinds, ONLY : DP
USE io_global, ONLY : stdout
USE mp_global, ONLY : me_pool
USE cell_base, ONLY : at, bg, alat
USE ions_base, ONLY : nat, tau, atm, ityp
USE pwcom
USE nmr_module
!--------------------------------------------------------------------
character*(*) name
integer :: ispin
real(dp) :: field(nrx1,nrx2,nrx3,3)
!--------------------------------------------------------------------
integer, parameter :: ounit = 48
character*80 :: fname
integer :: ios, ipol
if (me_pool /= 0) return
do ipol = 1, 3
! form the name of the output file
if (ispin == 0) fname = trim(name)//'_'
if (ispin == 1) fname = trim(name)//'_UP_'
if (ispin == 2) fname = trim(name)//'_DW_'
if (ipol == 1) fname = trim(fname)//'X.xsf'
if (ipol == 2) fname = trim(fname)//'Y.xsf'
if (ipol == 3) fname = trim(fname)//'Z.xsf'
write(stdout, '(5X,''write_tensor_field: '',A40)') fname
open(unit=ounit, file=fname, iostat=ios, form='formatted', &
status='unknown')
if (ios /= 0) &
call errore('write_tensor_field', 'error opening '//fname, ounit)
call xsf_struct (alat, at, nat, tau, atm, ityp, nr1*nr2*nr3, ounit)
call xsf_vector_3d(field(1,1,1,ipol), &
nr1, nr2, nr3, nrx1, nrx2, nrx3, at, bg, alat, ounit)
close(unit=48)
enddo
end subroutine write_tensor_field
!
! Copyright (C) 2003 Tone Kokalj
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
! This file holds XSF (=Xcrysden Structure File) utilities.
! Routines written by Tone Kokalj on Mon Jan 27 18:51:17 CET 2003
!
! -------------------------------------------------------------------
! this routine writes the crystal structure in XSF format
! -------------------------------------------------------------------
subroutine xsf_struct (alat, at, nat, tau, atm, ityp, nr, ounit)
USE kinds, only : DP
implicit none
integer :: nat, ityp (nat), nr, ounit
character(len=3) :: atm(*)
real(DP) :: alat, tau (3, nat), at (3, 3)
! --
integer :: i, j, n
real(DP) :: at1 (3, 3)
! convert lattice vectors to ANGSTROM units ...
do i=1,3
do j=1,3
at1(j,i) = at(j,i)*alat*0.529177d0
enddo
enddo
write(ounit,*) 'CRYSTAL'
write(ounit,*) 'PRIMVEC'
write(ounit,'(2(3F15.9/),3f15.9)') at1
write(ounit,*) 'PRIMCOORD'
write(ounit,*) nat + nr, 1
do n=1,nat
! positions are in Angstroms
write(ounit,'(a3,3x,3f15.9)') atm(ityp(n)), &
tau(1,n)*alat*0.529177d0, &
tau(2,n)*alat*0.529177d0, &
tau(3,n)*alat*0.529177d0
enddo
return
end subroutine xsf_struct
! -------------------------------------------------------------------
! this routine writes a 3D vector field
! -------------------------------------------------------------------
subroutine xsf_vector_3d(v, nr1, nr2, nr3, nrx1, nrx2, nrx3, &
at, bg, alat, ounit)
USE kinds, only : DP
implicit none
integer :: nrx1, nrx2, nrx3, nr1, nr2, nr3, ounit
real(DP) :: at(3,3), bg(3,3), x(3), alat, v(nrx1,nrx2,nrx3,3)
integer :: i1, i2, i3
do i1 = 1, nr1
do i2 = 1, nr2
do i3 = 1, nr3
! coordinate in angstrom
x(1) = dble(i1)/dble(nr1)
x(2) = dble(i2)/dble(nr2)
x(3) = dble(i3)/dble(nr3)
! crystal to cartesian
call trnvect (x, at, bg, 1)
x = x * alat * 0.529177d0
write(ounit,'(''X '',3x,3f15.9,2x,3e12.4)') x, v(i1,i2,i3,1:3)
enddo
enddo
enddo
end subroutine xsf_vector_3d