quantum-espresso/GWW/pw4gww/convergence.f90

2530 lines
92 KiB
Fortran

MODULE convergence_gw
USE kinds, ONLY : DP
SAVE
TYPE vpv
INTEGER :: nr!numer of points
INTEGER(kind=DP), DIMENSION(:), POINTER :: r!points in real space where vPv will be evaluated
!the point is /= 0 if it belongs to this MPI task
!in this case it is the point index on charge grid
REAL(kind=DP), DIMENSION(:,:), POINTER :: vpvr!vpv(:,r) in real space charge grid, real part
REAL(kind=DP), DIMENSION(:,:), POINTER :: vpvr_im!vpv(:,r) in real space charge grid, imaginary part
REAL(kind=DP) :: freq!frequency at which it is calculated, real part
REAL(kind=DP) :: freq_im!frequency at which it is calculated, imaginary part
END type vpv
TYPE gzero
INTEGER :: nr!numer of points
INTEGER(kind=DP), DIMENSION(:), POINTER :: r!points in real space where vPv will be evaluated
!the point is /= 0 if it belongs to this MPI task
!in this case it is the point index on charge grid
REAL(kind=DP), DIMENSION(:,:,:), POINTER :: gf!Green's function (:,nspin,r) in real space charge grid, real part
REAL(kind=DP), DIMENSION(:,:,:), POINTER :: gf_im!Green's function (:,nspin,r) in real space charge grid, imaginary part
REAL(kind=DP) :: freq!frequency at which it is calculated, real part
REAL(kind=DP) :: freq_im!frequency at which it is calculated, imaginary part
END type gzero
TYPE exchange
INTEGER :: nr!numer of points
INTEGER(kind=DP), DIMENSION(:), POINTER :: r!points in real space where vPv will be evaluated
REAL(kind=DP), DIMENSION(:,:,:), POINTER :: x!Exchange function (:,r,nspin) in real space charge grid
END type exchange
TYPE hks
INTEGER :: nr!numer of points
INTEGER(kind=DP), DIMENSION(:), POINTER :: r!points in real space where vPv will be evaluated
REAL(kind=DP), DIMENSION(:,:), POINTER :: h0!Hamiltonian (:,r) in real space charge grid
REAL(kind=DP), DIMENSION(:,:), POINTER :: vxc!V_xc(:,r) in real space charge grid
END type hks
TYPE convergence_tests
INTEGER :: nr!numer of points
INTEGER :: iband!band index, we put iband=0 if no specific band is associated to the data
INTEGER :: ispin!spin index, we put iband=0 if no specific band is associated to the data
INTEGER,DIMENSION(:), POINTER :: r!points in real space where vPv will be evaluated
!the point is /= 0 if it belongs to this MPI task
!in this case it is the point index on charge grid
INTEGER :: r_coord(3)!coordinates in grid space of point, only one point is assumed
COMPLEX(kind=DP), POINTER :: freq(:)!frequencies at which it is calculated
INTEGER :: nf!number of frequencies
TYPE(vpv),POINTER :: wapprox(:)!vPV or also an aproximated W
TYPE(gzero),POINTER :: g0(:)!Green's functions
TYPE(exchange) :: xf!exact exchange
TYPE(hks) :: h0!Hamiltonian KS
REAL(kind=DP), DIMENSION(:), POINTER :: energy!energy (in Ry) calculated at points r
END type convergence_tests
TYPE self_energy
INTEGER :: s_first_state!these two specify the range of KS states
INTEGER :: s_last_state!
INTEGER :: s_first_spin, s_last_spin!!these two specify the range of KS spin
INTEGER :: ngrid!grid points in imaginary frequency
REAL(kind=DP), POINTER :: freq(:)!frequencies (ngrid)
INTEGER :: nr!total number of r points
REAL(kind=DP), POINTER :: psif(:,:,:) !wavefunction at point dimension (nr,s_first_state:s_last_state,s_first_spin,s_last_spin)
COMPLEX(kind=DP), POINTER :: self(:,:,:,:)!self_energy(ngrid,nr,s_first_state:s_last_state,s_first_spin,s_last_spin)
LOGICAL :: l_first!if true, the self_energy has not yet been created
REAL(kind=DP), POINTER :: ene_ks(:,:)!KS expectation values (nbnd,nspin)
REAL(kind=DP), POINTER :: ene_xc(:,:)!DFT-XC expectation values (nbnd,nspin)
REAL(kind=DP), POINTER :: ene_x(:,:)!exact exchnage expectation values (nbnd,nspin)
END TYPE self_energy
INTERFACE free_memory
MODULE PROCEDURE free_vpv
MODULE PROCEDURE free_convergence_tests
MODULE PROCEDURE free_gzero
MODULE PROCEDURE free_exchange
MODULE PROCEDURE free_hks
MODULE PROCEDURE free_self_energy
END INTERFACE free_memory
INTERFACE initialize_memory
MODULE PROCEDURE initialize_memory_gzero
MODULE PROCEDURE initialize_memory_vpv
MODULE PROCEDURE initialize_memory_self_energy
END INTERFACE initialize_memory
CONTAINS
SUBROUTINE initialize_memory_self_energy(se)
IMPLICIT NONE
TYPE(self_energy) ::se
nullify(se%freq,se%psif,se%self,se%ene_ks,se%ene_xc,se%ene_x)
se%l_first=.true.
END SUBROUTINE initialize_memory_self_energy
SUBROUTINE free_self_energy(se)
IMPLICIT NONE
TYPE(self_energy) ::se
if(associated(se%freq)) deallocate(se%freq)
if(associated(se%self)) deallocate(se%self)
if(associated(se%psif)) deallocate(se%psif)
if(associated(se%ene_ks)) deallocate(se%ene_ks)
if(associated(se%ene_xc)) deallocate(se%ene_xc)
if(associated(se%ene_x)) deallocate(se%ene_x)
nullify(se%freq,se%psif,se%self,se%ene_ks,se%ene_xc,se%ene_x)
END SUBROUTINE free_self_energy
SUBROUTINE initialize_memory_gzero(c)
IMPLICIT NONE
TYPE(gzero) :: c
nullify(c%r,c%gf,c%gf_im)
RETURN
END SUBROUTINE initialize_memory_gzero
SUBROUTINE initialize_memory_vpv(c)
IMPLICIT NONE
TYPE(vpv) :: c
nullify(c%r,c%vpvr,c%vpvr_im)
RETURN
END SUBROUTINE initialize_memory_vpv
SUBROUTINE free_hks(c)
IMPLICIT NONE
TYPE(hks) :: c
deallocate(c%r,c%h0,c%vxc)
RETURN
END SUBROUTINE free_hks
SUBROUTINE free_exchange(c)
IMPLICIT NONE
TYPE(exchange) :: c
deallocate(c%r,c%x)
RETURN
END SUBROUTINE free_exchange
SUBROUTINE free_gzero(c)
IMPLICIT NONE
TYPE(gzero) :: c
if(associated(c%r)) deallocate(c%r)
if(associated(c%gf)) deallocate(c%gf)
if(associated(c%gf_im)) deallocate(c%gf_im)
nullify(c%r,c%gf,c%gf_im)
RETURN
END SUBROUTINE free_gzero
SUBROUTINE set_se_energies(se, ene_ks,ene_xc,ene_x)
USE wvfct, ONLY : nbnd
USE lsda_mod, ONLY : nspin
IMPLICIT NONE
TYPE(self_energy), INTENT(out) :: se
REAL(kind=DP), INTENT(in) :: ene_ks(nbnd,nspin)
REAL(kind=DP), INTENT(in) :: ene_xc(nbnd,nspin)
REAL(kind=DP), INTENT(in) :: ene_x(nbnd,nspin)
allocate(se%ene_ks(nbnd,nspin))
allocate(se%ene_xc(nbnd,nspin))
allocate(se%ene_x(nbnd,nspin))
se%ene_ks(1:nbnd,1:nspin)=ene_ks(1:nbnd,1:nspin)
se%ene_xc(1:nbnd,1:nspin)=ene_xc(1:nbnd,1:nspin)
se%ene_x(1:nbnd,1:nspin)=ene_x(1:nbnd,1:nspin)
RETURN
END SUBROUTINE set_se_energies
SUBROUTINE write_self_energy(se, ix_start,iy_start,iz_start,nr_counter)
USE io_global, ONLY :stdout, ionode
USE io_files, ONLY : prefix
IMPLICIT NONE
TYPE(self_energy) ::se !object to be written on disk
INTEGER :: ix_start,iy_start,iz_start! last point coordinates
INTEGER :: nr_counter !last counter position
INTEGER, EXTERNAL :: find_free_unit
INTEGER :: iun, ii,is
if(ionode) then
iun=find_free_unit()
open( unit= iun, file=trim(prefix)//'.easyself', status='unknown', form='unformatted')
write(iun) ix_start,iy_start,iz_start
write(iun) nr_counter
write(iun) se%s_first_state
write(iun) se%s_last_state
write(iun) se%s_first_spin
write(iun) se%s_last_spin
write(iun) se%ngrid
write(iun) se%nr
write(iun) se%l_first
write(iun)se%freq(1:se%ngrid)
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
write(iun) se%psif(1:se%nr,ii,is)
enddo
enddo
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
write(iun) se%self(1:se%ngrid,1:se%nr,ii,is)
enddo
enddo
close(iun)
endif
END SUBROUTINE write_self_energy
SUBROUTINE read_self_energy(se, ix_start,iy_start,iz_start,nr_counter)
USE io_global, ONLY :stdout, ionode, ionode_id
USE io_files, ONLY : prefix
USE mp, ONLY : mp_bcast
USE mp_global, ONLY : world_comm
IMPLICIT NONE
TYPE(self_energy) ::se !object to be read on disk
INTEGER :: ix_start,iy_start,iz_start! last point coordinates
INTEGER :: nr_counter !last counter position
INTEGER, EXTERNAL :: find_free_unit
INTEGER :: iun, ii, is
if(ionode) then
iun=find_free_unit()
open( unit= iun, file=trim(prefix)//'.easyself', status='old', form='unformatted')
read(iun) ix_start,iy_start,iz_start
read(iun) nr_counter
read(iun) se%s_first_state
read(iun) se%s_last_state
read(iun) se%s_first_spin
read(iun) se%s_last_spin
read(iun) se%ngrid
read(iun) se%nr
read(iun) se%l_first
endif
call mp_bcast(ix_start,ionode_id,world_comm)
call mp_bcast(iy_start,ionode_id,world_comm)
call mp_bcast(iz_start,ionode_id,world_comm)
call mp_bcast(nr_counter,ionode_id,world_comm)
call mp_bcast(se%s_first_state,ionode_id,world_comm)
call mp_bcast(se%s_last_state,ionode_id,world_comm)
call mp_bcast(se%s_first_spin,ionode_id,world_comm)
call mp_bcast(se%s_last_spin,ionode_id,world_comm)
call mp_bcast(se%ngrid,ionode_id,world_comm)
call mp_bcast(se%nr,ionode_id,world_comm)
call mp_bcast(se%l_first,ionode_id,world_comm)
allocate(se%freq(se%ngrid))
allocate(se%psif(1:se%nr,se%s_first_state:se%s_last_state,se%s_first_spin:se%s_last_spin))
allocate(se%self(1:se%ngrid,1:se%nr,se%s_first_state:se%s_last_state,se%s_first_spin:se%s_last_spin))
if(ionode) then
read(iun)se%freq(1:se%ngrid)
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
read(iun) se%psif(1:se%nr,ii,is)
enddo
enddo
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
read(iun) se%self(1:se%ngrid,1:se%nr,ii,is)
enddo
enddo
close(iun)
endif
call mp_bcast(se%freq,ionode_id,world_comm)
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
call mp_bcast(se%psif(1:se%nr,ii,is),ionode_id,world_comm)
enddo
enddo
do is=se%s_first_spin,se%s_last_spin
do ii=se%s_first_state,se%s_last_state
call mp_bcast(se%self(1:se%ngrid,1:se%nr,ii,is),ionode_id,world_comm)
enddo
enddo
END SUBROUTINE read_self_energy
SUBROUTINE check_normalisation(v_states, iband)
USE fft_base, ONLY : dfftp, dffts
USE mp, ONLY : mp_sum
USE mp_world, ONLY : world_comm,mpime
USE io_global, ONLY : stdout
USE wannier_gw
IMPLICIT NONE
INTEGER :: iband!band considered for convergence test
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbndv(1))!valence states in real space
INTEGER :: ix,iy,iz, id,nd,ii,ib,jb,nd2
REAL(kind=DP) ::sca
do ib=1,10!iband
do jb=4,4!1,iband
do id=1,30
sca=0.d0
nd=0
nd2=0
do iz=1,dffts%nr3,id
do iy=1,dffts%nr2,id
do ix=1,dffts%nr1,id
if( iz>dffts%nr3p_offset(mpime+1) .and. iz <=( dffts%nr3p_offset(mpime+1)+dffts%my_nr3p)) then
ii=(iz-dffts%nr3p_offset(mpime+1)-1)*dffts%nr2*dffts%nr1+&
(iy-1)*dffts%nr1+ix
if(abs(v_states(ii,jb))> 1.d-0) then
sca=sca+v_states(ii,ib)*v_states(ii,jb)
nd2=nd2+1
endif
nd=nd+1
endif
enddo
enddo
enddo
call mp_sum(nd,world_comm)
call mp_sum(nd2,world_comm)
call mp_sum(sca,world_comm)
sca=sca/dble(nd)
write(stdout,*) 'NORMALIZATION, STEP :',ib,jb,id,nd,nd2,sca
enddo
enddo
enddo
return
END SUBROUTINE check_normalisation
SUBROUTINE start_convergence(ct,iband,ispin,v_states,lmax,nx,ny,nz,nf, freq,ks_wfcs)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2,bg
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE mp_world, ONLY : mpime, nproc,world_comm
USE lanczos
USE io_files, ONLY : prefix, tmp_dir
USE mp_pools, ONLY : intra_pool_comm
USE mp_wave, ONLY : splitwf
USE lsda_mod, ONLY : nspin
USE scf, ONLY : rho,rho_core,rhog_core,scf_type,create_scf_type,destroy_scf_type
IMPLICIT NONE
TYPE(convergence_tests) :: ct!object for convergence tests
INTEGER :: iband!band considered for convergence test
INTEGER :: ispin!spin considered for convergence test
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbnds,nspin)!valence states in real space
LOGICAL, INTENT(in) :: lmax!if true selec the maximu for v_states otherwise x,y,z
INTEGER, INTENT(in) :: nx,ny,nz
INTEGER, INTENT(in) :: nf!number of frequencies
COMPLEX(kind=DP), INTENT(in) :: freq(nf)
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wavefunctions in G space
INTEGER :: ip,ir,imax,iw
REAL(kind=DP) :: charge,charge_max
LOGICAL :: lfound
LOGICAL :: l_old
COMPLEX(kind=DP), ALLOCATABLE :: psi_old(:),psi_old_vpv(:,:,:)
TYPE(lanczos_chain) :: lc(2),lc_vpv(2)
REAL(kind=DP), ALLOCATABLE :: head(:),head1(:),head2(:),head3(:)
INTEGER :: iun,nh
REAL(kind=DP), ALLOCATABLE :: freqh(:)
INTEGER, EXTERNAL :: find_free_unit
REAL(kind=DP) :: omegah
!!!!variables for wings
INTEGER :: n_g, ngm_k
REAL(kind=DP) :: omega_g
INTEGER :: ii, ipol
COMPLEX(kind=DP), ALLOCATABLE :: e_head(:,:,:), e_head_g0(:)
INTEGER :: npwx_g
INTEGER, ALLOCATABLE :: k2g_ig_l2g(:)
REAL(kind=DP), ALLOCATABLE :: freqs_head(:)
COMPLEX(kind=DP), ALLOCATABLE :: wing(:)
TYPE(scf_type) :: aile
REAL(kind=DP) :: alpha
REAL(kind=DP), ALLOCATABLE :: vc(:,:)
REAL(kind=DP) :: broadening
COMPLEX(kind=DP), ALLOCATABLE :: phi_save(:)
call create_scf_type ( aile , .true. )
l_wing=.true.
write(stdout,*) 'Routine calculate_convergence'
if(.not.l_truncated_coulomb .and. l_wing) then
!here reads wings stuff
allocate(k2g_ig_l2g(ngm))
call ktogamma_ig_l2g ( k2g_ig_l2g, at, bg )
if(ionode) then
iun = find_free_unit()
open( unit= iun, file=trim(tmp_dir)//'/_ph0/'//trim(prefix)//'.e_head', status='old',form='unformatted')
read(iun) n_g
read(iun) omega_g
endif
call mp_bcast(n_g, ionode_id,world_comm)
call mp_bcast(omega_g, ionode_id,world_comm)
allocate(freqs_head(n_g+1))
if(ionode) then
read(iun) freqs_head(1:n_g+1)
read(iun) ngm_k
endif
call mp_bcast(freqs_head, ionode_id,world_comm)
call mp_bcast(ngm_k, ionode_id,world_comm)
allocate(e_head_g0(ngm_k))
allocate(e_head(npw, n_g+1,3))
e_head(:,:,:)= (0.d0,0.d0)
do ii=1,n_g+1
do ipol=1,3
e_head_g0(:)=(0.d0,0.d0)
if(ionode) read(iun) e_head_g0(1:ngm_k)
call splitwf(e_head(:, ii,ipol),e_head_g0,npw,k2g_ig_l2g,mpime,nproc,ionode_id,intra_pool_comm)
enddo
enddo
if(ionode) close(iun)
deallocate(e_head_g0)
allocate(wing(npw))
else
allocate(wing(npw))
endif
call initialize_memory(lc(1))
call initialize_memory(lc(2))
call initialize_memory(lc_vpv(1))
call initialize_memory(lc_vpv(2))
allocate(head(nf))
if(.not.l_truncated_coulomb) then
if(ionode) then
allocate(head1(nf),head2(nf),head3(nf))
allocate(freqh(nf))
iun = find_free_unit()
open( unit= iun, file=trim(tmp_dir)//'/_ph0/'//trim(prefix)//'.head', status='old',form='unformatted')
read(iun) nh
read(iun) omegah
read(iun) freqh(1:nh+1)
read(iun) head1(1:nh+1)
read(iun) head2(1:nh+1)
read(iun) head3(1:nh+1)
close(iun)
do iw=1,nf
head(nf-iw+1)=(1.d0/3.d0)*(head1(iw)+head2(iw)+head3(iw))
head(nf-iw+1)=head1(iw)!DEBUG
!if(l_verbose) write(stdout,*) 'HEAD: ', iw, head(nf-iw+1),nf,nh
enddo
deallocate(head1,head2,head3,freqh)
endif
call mp_bcast(head, ionode_id, world_comm)
endif
ct%nr=1
ct%iband=iband
ct%ispin=ispin
allocate(ct%r(1))
ct%r=0
ct%nf=nf
allocate(ct%freq(nf))
ct%freq(1:nf)=freq(1:nf)
allocate(ct%wapprox(nf))
allocate(ct%g0(nf))
if(lmax) then
charge_max=-1.d0
do ip=0,nproc-1
if(mpime==ip) then
imax=0
do ir=1,dffts%nnr
charge=(v_states(ir,ct%iband,ispin))**2.d0
if(charge>charge_max) then
charge_max=charge
imax=ir
ct%r(1)=imax
endif
enddo
if(imax>0) then
lfound=.true.
else
lfound=.false.
endif
call mp_bcast(lfound,ip,world_comm)
call mp_bcast(charge_max,ip,world_comm)
else
call mp_bcast(lfound,ip,world_comm)
call mp_bcast(charge_max,ip,world_comm)
if(lfound) then
ct%r(1)=0
endif
endif
enddo
else
if( nz>dffts%nr3p_offset(mpime+1) .and. nz <=( dffts%nr3p_offset(mpime+1)+dffts%my_nr3p)) then
ct%r(1)=(nz-dffts%nr3p_offset(mpime+1)-1)*dffts%nr2*dffts%nr1+&
(ny-1)*dffts%nr1+nx
endif
ct%iband=0
ct%ispin=0
ct%r_coord(1)=nx
ct%r_coord(2)=ny
ct%r_coord(3)=nz
endif
if(lmax) write(stdout,*) 'MAXIMUM PSI :',ct%iband, sqrt(charge_max)
allocate(psi_old(npw),psi_old_vpv(npw,num_nbndv(1),2))
!call calculate_vpv_complex(ct%wapprox(1),0.d0,0.d0,ct%r,ct%nr,v_states,.true.,1.d-12,.false.,psi_old_vpv)
!call calculate_gzero(ct%g0(1),0.d0,ct%r,ct%nr)
alpha=0.5d0!1.d0 !DEBUG
allocate(phi_save(npw))
do iw=1,ct%nf
if(l_verbose) write(stdout,*) 'IMAGINARY FREQ:',aimag(ct%freq(iw))
if(iw==1) then
l_old=.false.
else
l_old=.true.
endif
if(.not.l_truncated_coulomb .and. l_wing) then
call read_wing ( aile, 1, .true.,1,ct%nf-iw+1 )
wing(1:npw)=(1.d0/3.d0)*(e_head(1:npw,ct%nf-iw+1,1)+e_head(1:npw,ct%nf-iw+1,2)+e_head(1:npw,ct%nf-iw+1,3))
wing(1:npw)=aile%of_g(1:npw,1)!DEBUG
endif
if(aimag(ct%freq(iw))==0.d0) then
broadening = (aimag(ct%freq(iw))+aimag(ct%freq(iw-1)))/4.d0
write(stdout,*) 'DEBUG BROADENIG', broadening
else
broadening =0.d0
endif
call calculate_vpv_complex(ct%wapprox(iw),dble(ct%freq(iw)),aimag(ct%freq(iw))+broadening,ct%r,ct%nr,v_states,.true.,&
& easy_w_thrs,lc_vpv,head(iw),wing, alpha,ks_wfcs, l_old,phi_save)
call calculate_gzero_complex(ct%g0(iw),dble(ct%freq(iw)),aimag(ct%freq(iw))+broadening,ct%r,ct%nr,l_old,psi_old, &
l_easy_lanczos_g, lc,ks_wfcs)
if(broadening /= 0.d0) then
ct%g0(iw)%gf_im=0.d0
endif
enddo
deallocate(phi_save)
deallocate(psi_old)
call calculate_x(ct%xf,ct%r,ct%nr,v_states)
call calculate_hks(ct%h0,ct%r,ct%nr,v_states)
call free_memory(lc(1))
call free_memory(lc(2))
call free_memory(lc_vpv(1))
call free_memory(lc_vpv(2))
deallocate(head)
!deallocate wing part
if(.not.l_truncated_coulomb.and.l_wing) then
deallocate(k2g_ig_l2g,freqs_head)
deallocate(e_head)
endif
deallocate(wing)
!
call destroy_scf_type (aile )
return
END SUBROUTINE start_convergence
SUBROUTINE calculate_convergence(ct,v_states,se,nr_counter)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2,bg
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE io_files, ONLY : prefix, tmp_dir
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE mp_world, ONLY : mpime, nproc,world_comm
USE constants, ONLY : rytoev
USE lsda_mod, ONLY : nspin
USE scf, ONLY : rho,rho_core,rhog_core
IMPLICIT NONE
TYPE(convergence_tests) :: ct!object for convergence tests
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbnds,nspin)!valence states in real space
TYPE(self_energy) ::se !object for collecting calculated self-energies
INTEGER, INTENT(inout):: nr_counter!counter for self_energy
INTEGER :: ir,ii,iw,jw,dw,iww,jww,dww,jj,ix,iy,iz,ipol,is
REAL(kind=DP) :: sca,psif,sca1,sca2,sca3
INTEGER, EXTERNAL :: find_free_unit
INTEGER :: iun,iun1,iun2
REAL(kind=DP), ALLOCATABLE :: vprods(:,:), vprods_im(:,:)
REAL(kind=DP), ALLOCATABLE :: wterms(:,:), wterms_im(:,:)
REAL(kind=DP), ALLOCATABLE :: gwmat_rr(:,:),gwmat_ri(:,:),gwmat_ir(:,:),gwmat_ii(:,:)
CHARACTER(4) :: nfile,nfilex,nfiley,nfilez
CHARACTER(5) :: nfilel,nfilel2
COMPLEX(kind=DP), ALLOCATABLE :: cmat(:,:),sigmac(:)
REAL(kind=DP) emax,freq_im
INTEGER :: ifirst,ilast,kk,ifirst_spin,ilast_spin
INTEGER :: passed,nr_calculate
REAL(kind=DP) :: vpsif, psif_xc,psif_x
INTEGER :: irr
CHARACTER(4) :: nfile_orb
write(stdout,*) 'Routine calculate_convergence'
if(l_whole_s) then
ifirst=1
ilast=num_nbnds
ifirst_spin=1
ilast_spin=nspin
else
if(ct%iband>0) then
ifirst=ct%iband
ilast=ct%iband
ifirst_spin=ct%ispin
ilast_spin=ct%ispin
else
ifirst=s_first_state
ilast=s_last_state
ifirst_spin=s_first_spin
ilast_spin=s_last_spin
endif
endif
if(se%l_first) then
se%s_first_state=ifirst
se%s_last_state=ilast
se%s_first_spin=ifirst_spin
se%s_last_spin=ilast_spin
se%ngrid=2*(ct%nf-1)+1
allocate(se%freq(se%ngrid))
do jj=-ct%nf+1,ct%nf-1
se%freq(jj+ct%nf)= abs(aimag(ct%freq(1)))/dble(ct%nf)*jj
enddo
if(ct%iband>0) then
se%nr=s_last_state-s_first_state+1
else
if(easy_grid_type==1) then
if(easy_psi_thrs==0.d0 .and. easy_grid_param(5)>=10000) then
se%nr=(int((dffts%nr1-easy_grid_param(1)-1)/easy_grid_param(4))+1)* &
&(int((dffts%nr2-easy_grid_param(2)-1)/easy_grid_param(4))+1)*(int((dffts%nr3-easy_grid_param(3)-1)/easy_grid_param(4))+1)
else
nr_calculate=0.d0
do iz=1+easy_grid_param(3),dffts%nr3,easy_grid_param(4)
do iy=1+easy_grid_param(2),dffts%nr2,easy_grid_param(4)
do ix=1+easy_grid_param(1),dffts%nr1,easy_grid_param(4)
passed=0
if(ix<easy_grid_param(5) .and. iy<easy_grid_param(5) .and. iz<easy_grid_param(5)) then
if( iz>dffts%nr3p_offset(mpime+1) .and. iz <=( dffts%nr3p_offset(mpime+1)+dffts%my_nr3p)) then
ii=(iz-dffts%nr3p_offset(mpime+1)-1)*dffts%nr2*dffts%nr1+&
(iy-1)*dffts%nr1+ix
do is=se%s_first_spin,se%s_last_spin
do jj=s_first_state,s_last_state
if(abs(v_states(ii,jj,is))> easy_psi_thrs) passed=1
enddo
enddo
endif
endif
call mp_sum(passed,world_comm)
if(passed>0) nr_calculate=nr_calculate+1
enddo
enddo
enddo
se%nr=nr_calculate
endif
else
se%nr=easy_grid_param(4)
endif
write(stdout,*) 'TOTAL NUMBER OF R POINTS TO BE CALCULATED:', se%nr
endif
allocate(se%psif(se%nr,se%s_first_state:se%s_last_state,se%s_first_spin:se%s_last_spin))
if( easy_grid_type /= 1 ) then
allocate(se%self(se%ngrid,se%nr,se%s_first_state:se%s_last_state,se%s_first_spin:se%s_last_spin))
else
allocate(se%self(1,1,se%s_first_state:se%s_last_state,se%s_first_spin:se%s_last_spin))
endif
se%self=0.d0
se%l_first=.false.
endif
allocate(ct%energy(ct%nr))
do ir=1,ct%nr!NOTE THAT ONLY 1 POINTS HAS BEEN IMPLEMENTED SO FAR
!!!!!THE FOLLOWING PART WAS TO USE AS A CONVERGENCE ESTIMATOR IN GWL
! if(ct%iband>0) then
! sca=0.d0
! sca1=0.d0
! sca2=0.d0
! sca3=0.d0
! do ii=1,dffts%nnr
! sca=sca+ct%g0(1)%gf(ii,ir)*ct%wapprox(1)%vpvr(ii,ir)*v_states(ii,ct%iband)
! sca1=sca1+ct%xf%x(ii,ir)*v_states(ii,ct%iband)
! sca2=sca2+ct%h0%h0(ii,ir)*v_states(ii,ct%iband)
! sca3=sca3+v_states(ii,ct%iband)**2.d0
! enddo
! call mp_sum(sca,world_comm)
! sca=sca/dble((dffts%nr1*dffts%nr2*dffts%nr3))
! call mp_sum(sca1,world_comm)
! sca1=sca1/dble((dffts%nr1*dffts%nr2*dffts%nr3))
! call mp_sum(sca2,world_comm)
! sca2=sca2/dble((dffts%nr1*dffts%nr2*dffts%nr3))
! call mp_sum(sca3,world_comm)
! sca3=sca3/(dffts%nr1*dffts%nr2*dffts%nr3)
!
!
! ct%energy(ir)=sca+sca1
! psif=0.d0
! if(ct%r(ir)/=0) psif=v_states(ct%r(ir),ct%iband)
! call mp_sum(psif,world_comm)
! ct%energy(ir)=ct%energy(ir)/psif
!
! write(stdout,*) 'CONVERGED ENERGY FOR TEST:', sca/psif*rytoev,sca1/psif*rytoev,sca2/psif*rytoev,sca3
! write(stdout,*) ct%energy(ir)*rytoev,psif
! endif
!!!!!!!!!!TILL HERE
if(easy_grid_type==1.or.easy_grid_type==2) then
write(stdout,*) 'POINT NUMBER', nr_counter
endif
do is=ifirst_spin,ilast_spin
do kk=ifirst,ilast
do iw=1,ct%nf
sca=0.d0
sca1=0.d0
do ii=1,dffts%nnr
sca=sca+ct%g0(iw)%gf(ii,is,ir)*v_states(ii,kk,is)
sca1=sca1+ct%g0(iw)%gf_im(ii,is,ir)*v_states(ii,kk,is)
enddo
call mp_sum(sca,world_comm)
sca=sca/dble((dffts%nr1*dffts%nr2*dffts%nr3))
call mp_sum(sca1,world_comm)
sca1=sca1/dble((dffts%nr1*dffts%nr2*dffts%nr3))
psif=0.d0
if(ct%r(ir)/=0) psif=v_states(ct%r(ir),kk,is)
call mp_sum(psif,world_comm)
! if(l_verbose) write(stdout,*) iw, sca/psif*rytoev,sca1/psif*rytoev
enddo
do iw=1,ct%nf
sca=0.d0
sca1=0.d0
do ii=1,dffts%nnr
sca=sca+ct%wapprox(iw)%vpvr(ii,ir)*v_states(ii,kk,is)
sca1=sca1+ct%wapprox(iw)%vpvr_im(ii,ir)*v_states(ii,kk,is)
enddo
call mp_sum(sca,world_comm)
sca=sca/dble((dffts%nr1*dffts%nr2*dffts%nr3))
call mp_sum(sca1,world_comm)
sca1=sca1/dble((dffts%nr1*dffts%nr2*dffts%nr3))
psif=0.d0
if(ct%r(ir)/=0) psif=v_states(ct%r(ir),kk,is)
call mp_sum(psif,world_comm)
!if(l_verbose) write(stdout,*) iw, sca/psif*rytoev,sca1/psif*rytoev
enddo
if(ionode .and. kk==ct%iband .and. l_verbose) then
iun=find_free_unit()
write(nfile,'(4i1)') ct%iband/1000,mod(ct%iband,1000)/100,mod(ct%iband,100)/10,mod(ct%iband,10)
open( unit= iun, file=trim(prefix)//'.convdata.'//nfile, status='unknown')
write(iun,*) ct%nf
do iw=1,ct%nf
write(iun,*) ct%wapprox(iw)%freq
enddo
endif
psif=0.d0
if(ct%r(ir)/=0) psif=v_states(ct%r(ir),kk,is)
call mp_sum(psif,world_comm)
psif_x=0.d0
do irr=1,dffts%nnr
psif_x=psif_x+ct%xf%x(irr,1,is)*v_states(irr,kk,is)
enddo
call mp_sum(psif_x,world_comm)
psif_xc=0.d0
if(ct%r(1)/=0) psif_xc=psif*ct%h0%vxc(ct%r(1),is)
call mp_sum(psif_xc,world_comm)
if(l_whole_s .or. easy_grid_type==1.or.easy_grid_type==2) se%psif(nr_counter,kk,is)=psif
if( easy_grid_type==1.or.easy_grid_type==2) then
write(stdout,*) 'WAVE_FUNCTIONS BAND AND VALUE',kk,psif,0.d0,0.d0
else
write(stdout,*) 'WAVE_FUNCTIONS OF MAX ', ct%iband, ct%ispin, ' in ', kk,psif,0.d0,0.d0
endif
allocate(vprods(dffts%nnr,ct%nf),wterms(dffts%nnr,ct%nf))
allocate(vprods_im(dffts%nnr,ct%nf),wterms_im(dffts%nnr,ct%nf))
allocate(gwmat_rr(ct%nf,ct%nf),gwmat_ri(ct%nf,ct%nf),gwmat_ir(ct%nf,ct%nf),gwmat_ii(ct%nf,ct%nf))
do iw=1,ct%nf
vprods(1:dffts%nnr,iw)=ct%g0(iw)%gf(1:dffts%nnr,is,ir)*v_states(1:dffts%nnr,kk,is)
wterms(1:dffts%nnr,iw)=ct%wapprox(iw)%vpvr(1:dffts%nnr,ir)
vprods_im(1:dffts%nnr,iw)=ct%g0(iw)%gf_im(1:dffts%nnr,is,ir)*v_states(1:dffts%nnr,kk,is)
wterms_im(1:dffts%nnr,iw)=ct%wapprox(iw)%vpvr_im(1:dffts%nnr,ir)
enddo
call DGEMM('T','N',ct%nf,ct%nf,dffts%nnr,1.d0,wterms,dffts%nnr,vprods,dffts%nnr,0.d0,gwmat_rr,ct%nf)
call mp_sum(gwmat_rr, world_comm)
call DGEMM('T','N',ct%nf,ct%nf,dffts%nnr,1.d0,wterms_im,dffts%nnr,vprods,dffts%nnr,0.d0,gwmat_ir,ct%nf)
call mp_sum(gwmat_ir, world_comm)
call DGEMM('T','N',ct%nf,ct%nf,dffts%nnr,1.d0,wterms,dffts%nnr,vprods_im,dffts%nnr,0.d0,gwmat_ri,ct%nf)
call mp_sum(gwmat_ri, world_comm)
call DGEMM('T','N',ct%nf,ct%nf,dffts%nnr,1.d0,wterms_im,dffts%nnr,vprods_im,dffts%nnr,0.d0,gwmat_ii,ct%nf)
call mp_sum(gwmat_ii, world_comm)
allocate(cmat(ct%nf,ct%nf),sigmac(2*ct%nf))
do iw=1,ct%nf
do jw=1,ct%nf
if(easy_grid_type/=1.and.easy_grid_type/=2) then
sca=(gwmat_rr(iw,jw)-gwmat_ii(iw,jw))/dble((dffts%nr1*dffts%nr2*dffts%nr3))/psif
sca1=(gwmat_ir(iw,jw)+gwmat_ri(iw,jw))/dble((dffts%nr1*dffts%nr2*dffts%nr3))/psif
else!if equally spaced grid we do not divide for psif as it can be zero
sca=(gwmat_rr(iw,jw)-gwmat_ii(iw,jw))/dble((dffts%nr1*dffts%nr2*dffts%nr3))
sca1=(gwmat_ir(iw,jw)+gwmat_ri(iw,jw))/dble((dffts%nr1*dffts%nr2*dffts%nr3))
endif
cmat(iw,jw)=cmplx(sca,sca1)
!if(ionode.and. kk==ct%iband .and. l_verbose) write(iun,*) sca,sca1
enddo
write(stdout,*) iw,dble(cmat(iw,ct%nf))
enddo
if(ionode.and. kk==ct%iband .and. l_verbose) close(iun)
sigmac=0.d0
do dw=-ct%nf+1,ct%nf
dww=dw+ct%nf
do jw=-ct%nf+1,ct%nf
iw=dw-jw
if(jw>-ct%nf .and. jw <ct%nf) then
if(jw>-ct%nf .and.jw <= 0) then
jww=jw+ct%nf
elseif(jw>0 .and. jw< ct%nf) then
jww=-jw+ct%nf
endif
if(iw>-ct%nf .and. iw <= 0) then
iww=iw+ct%nf
sigmac(dww)=sigmac(dww)+cmat(jww,iww)
elseif(iw>0 .and. iw< ct%nf) then
iww=-iw+ct%nf
sigmac(dww)=sigmac(dww)+conjg(cmat(jww,iww))
endif
endif
enddo
enddo
emax=abs(aimag(ct%freq(1)))
sigmac=sigmac*(emax*2.d0)/dble(2*ct%nf-1)*(1.d0)/(2.d0*3.1415926d0)
if(easy_grid_type==0) then
!MAXVAL VC case
!sigmac=sigmac*psif*(ene_c)/psifvc!*(-1.d0)
! LONG CASE
!sigmac=(sigmac-psif_xc/psif-psif_x/psif)+se%ene_xc(kk,is)-se%ene_x(kk,is)
endif
if(ionode .and. l_verbose ) then
iun=find_free_unit()
write(nfile,'(4i1)') ct%iband/1000,mod(ct%iband,1000)/100,mod(ct%iband,100)/10,mod(ct%iband,10)
open(unit=iun,file=trim(prefix)//'sigmac.'//nfile//'.dat',status='unknown')
do iw=1,2*ct%nf
write(iun,*) 2.d0*emax/dble(2*ct%nf)*iw-emax,dble(sigmac(iw)),aimag(sigmac(iw))
enddo
close(iun)
endif
!if(l_whole_s .or. easy_grid_type==1.or.easy_grid_type==2) then
if(l_whole_s .or.easy_grid_type==2) then
do jj=-ct%nf+1,ct%nf-1
se%self(jj+ct%nf,nr_counter,kk,is)=sigmac(jj+ct%nf)
enddo
endif
if(ionode) then
if(kk==ct%iband) then
write(nfilel,'(5i1)') &
& ct%iband/10000,mod(ct%iband,10000)/1000,mod(ct%iband,1000)/100,mod(ct%iband,100)/10,mod(ct%iband,10)
if(is==1) then
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im'// nfilel, status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im'// nfilel, status='unknown',form='formatted')
else
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im2'// nfilel, status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im2'// nfilel, status='unknown',form='formatted')
endif
do jj=-ct%nf+1,ct%nf-1
freq_im= emax/dble(ct%nf)*jj
write(iun1,*) freq_im,0.d0,dble(sigmac(jj+ct%nf)),0.d0
write(iun2,*) freq_im,0.d0,aimag(sigmac(jj+ct%nf)),0.d0
enddo
close(iun1)
close(iun2)
else
if(ct%iband>0 ) then
write(nfilel,'(5i1)') &
& ct%iband/10000,mod(ct%iband,10000)/1000,mod(ct%iband,1000)/100,mod(ct%iband,100)/10,mod(ct%iband,10)
write(nfilel2,'(5i1)') &
& kk/10000,mod(kk,10000)/1000,mod(kk,1000)/100,mod(kk,100)/10,mod(kk,10)
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im_off'// nfilel//'_'//nfilel2, &
& status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im_off'// nfilel//'_'//nfilel2, &
& status='unknown',form='formatted')
else
if(l_verbose) then
write(nfilex,'(4i1)') &
& ct%r_coord(1)/1000,mod(ct%r_coord(1),1000)/100,mod(ct%r_coord(1),100)/10, mod(ct%r_coord(1),10)
write(nfiley,'(4i1)') &
& ct%r_coord(2)/1000,mod(ct%r_coord(2),1000)/100,mod(ct%r_coord(2),100)/10, mod(ct%r_coord(2),10)
write(nfilez,'(4i1)') &
& ct%r_coord(3)/1000,mod(ct%r_coord(3),1000)/100,mod(ct%r_coord(3),100)/10, mod(ct%r_coord(3),10)
write(nfilel2,'(5i1)') &
& kk/10000,mod(kk,10000)/1000,mod(kk,1000)/100,mod(kk,100)/10,mod(kk,10)
iun1 = find_free_unit()
write(nfile_orb,'(4i1)') &
& kk/1000,mod(kk,1000)/100,mod(kk,100)/10, mod(kk,10)
if(is==1) then
open( unit=iun1, file=trim(prefix)//'-gwl_orbital_1_'//nfile_orb//'/re_on_im_r_'&
&//nfilex//'_'//nfiley//'_'//nfilez//'__'//nfilel2,status='unknown',form='formatted')
else
open( unit=iun1, file=trim(prefix)//'-gwl_orbital_2_'//nfile_orb//'/re_on_im_r_2'&
&//nfilex//'_'//nfiley//'_'//nfilez//'__'//nfilel2, status='unknown',form='formatted')
endif
iun2 = find_free_unit()
if(is==1) then
open( unit=iun2, file=trim(prefix)//'-gwl_orbital_1_'//nfile_orb//'/im_on_im_r_'&
&//nfilex//'_'//nfiley//'_'//nfilez//'__'//nfilel2, status='unknown',form='formatted')
else
open( unit=iun2, file=trim(prefix)//'-gwl_orbital_2_'//nfile_orb//'/im_on_im_r_2'&
&//nfilex//'_'//nfiley//'_'//nfilez//'__'//nfilel2, status='unknown',form='formatted')
endif
endif
endif
if(.not.(easy_grid_type==1.or.easy_grid_type==2).or.l_verbose) then
do jj=-ct%nf+1,ct%nf-1
freq_im= emax/dble(ct%nf)*jj
write(iun1,*) freq_im,0.d0,dble(sigmac(jj+ct%nf)),0.d0
write(iun2,*) freq_im,0.d0,aimag(sigmac(jj+ct%nf)),0.d0
enddo
close(iun1)
close(iun2)
endif
endif
endif
deallocate(cmat,sigmac)
deallocate(vprods,vprods_im,wterms,wterms_im)
deallocate(gwmat_rr,gwmat_ri,gwmat_ir,gwmat_ii)
enddo
enddo
nr_counter=nr_counter+1
enddo
return
END SUBROUTINE calculate_convergence
SUBROUTINE average_self_energy(se)
USE io_global, ONLY : stdout, ionode, ionode_id
USE io_files, ONLY : prefix, tmp_dir
USE wannier_gw
IMPLICIT NONE
TYPE(self_energy) :: se
INTEGER :: kk,ir,is
COMPLEX(kind=DP), ALLOCATABLE :: self_ave(:)
REAL(kind=DP) :: den
CHARACTER(5) :: nfile
INTEGER :: iun1,iun2
INTEGER, EXTERNAL :: find_free_unit
INTEGER :: nr_calculate
allocate(self_ave(se%ngrid))
do is=se%s_first_spin,se%s_last_spin
do kk=se%s_first_state,se%s_last_state
self_ave=0.d0
den=0.d0
nr_calculate=0
do ir=1,se%nr
if(abs(se%psif(ir,kk,is))>easy_psi_thrs) then
den=den+se%psif(ir,kk,is)**2.d0
self_ave(1:se%ngrid)=self_ave(1:se%ngrid)+se%self(1:se%ngrid,ir,kk,is)*se%psif(ir,kk,is)
nr_calculate=nr_calculate+1
endif
enddo
write(stdout,*) 'Averaging over r points',kk,den,dble(nr_calculate)
if(easy_average_type==0) then
self_ave(1:se%ngrid)=self_ave(1:se%ngrid)/den
else
self_ave(1:se%ngrid)=self_ave(1:se%ngrid)/dble(nr_calculate)
endif
if(ionode) then
write(nfile,'(5i1)') &
& kk/10000,mod(kk,10000)/1000,mod(kk,1000)/100,mod(kk,100)/10,mod(kk,10)
if(is==1) then
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im'// nfile, status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im'// nfile, status='unknown',form='formatted')
else
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im2'// nfile, status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im2'// nfile, status='unknown',form='formatted')
endif
do ir=1,se%ngrid
write(iun1,*) se%freq(ir),0.d0,dble(self_ave(ir)),0.d0
write(iun2,*) se%freq(ir),0.d0,aimag(self_ave(ir)),0.d0
enddo
close(iun1)
close(iun2)
endif
enddo
end do
deallocate(self_ave)
END SUBROUTINE average_self_energy
SUBROUTINE solve_off_diagonal(se)
USE io_global, ONLY : stdout, ionode, ionode_id
USE io_files, ONLY : prefix, tmp_dir
USE wannier_gw
IMPLICIT NONE
TYPE(self_energy),INTENT(inout) :: se!self_energies object
INTEGER :: kk,ir,it
COMPLEX(kind=DP), ALLOCATABLE :: self_diag(:,:)
REAL(kind=DP) :: den
CHARACTER(5) :: nfile
INTEGER :: iun1,iun2
INTEGER, EXTERNAL :: find_free_unit
REAL(kind=DP), ALLOCATABLE :: psi_mat(:,:),sigma_vec(:,:)
REAL(kind=DP), ALLOCATABLE :: sigma_vec_im(:,:)
INTEGER :: nn!matrix dimesion
INTEGER, ALLOCATABLE :: ipiv(:)
INTEGER :: info
write(stdout,*) 'Routine solve_off_diagonal'
nn=s_last_state-s_first_state+1
if(nn /= se%nr) then
call errore('solve_off_diagonal','mismatch bands/points ',1)
endif
allocate(self_diag(se%ngrid,s_first_state:s_last_state))
allocate(psi_mat(nn,nn))
allocate(sigma_vec(nn,nn))
allocate(sigma_vec_im(nn,nn))
allocate(ipiv(nn))
psi_mat=0.d0
do it=1,se%ngrid
do ir=1,nn
do kk=s_first_state,s_last_state
sigma_vec(ir,kk) =dble(se%self(it,ir,kk,1))*se%psif(ir,kk,1)
sigma_vec_im(ir,kk) =aimag(se%self(it,ir,kk,1))*se%psif(ir,kk,1)
enddo
enddo
psi_mat(1:nn,1:nn)=se%psif(1:nn,s_first_state:s_last_state,1)
call DGESV(nn,nn,psi_mat,nn,ipiv,sigma_vec,nn,info)!psi_mat changed in exit
if(info/=0) then
call errore('solve_off_diagonal','DGESV error:',info)
endif
psi_mat(1:nn,1:nn)=se%psif(1:nn,s_first_state:s_last_state,1)
call DGESV(nn,nn,psi_mat,nn,ipiv,sigma_vec_im,nn,info)!psi_mat changed in exit
if(info/=0) then
call errore('solve_off_diagonal','DGESV error:',info)
endif
do kk=se%s_first_state,se%s_last_state
self_diag(it,kk)=cmplx(sigma_vec(kk-s_first_state+1,kk-s_first_state+1),&
sigma_vec_im(kk-s_first_state+1,kk-s_first_state+1))
write(stdout,*) 'VECTOR',it,kk,sigma_vec(:,kk)
write(stdout,*) 'VECTOR IM',it,kk,sigma_vec_im(:,kk)
enddo
enddo
if(ionode) then
do kk=se%s_first_state,se%s_last_state
write(nfile,'(5i1)') &
& kk/10000,mod(kk,10000)/1000,mod(kk,1000)/100,mod(kk,100)/10,mod(kk,10)
iun1 = find_free_unit()
open( unit=iun1, file=trim(prefix)//'-'//'re_on_im'// nfile, status='unknown',form='formatted')
iun2 = find_free_unit()
open( unit=iun2, file=trim(prefix)//'-'//'im_on_im'// nfile, status='unknown',form='formatted')
do it=1,se%ngrid
write(iun1,*) se%freq(it),0.d0,dble(self_diag(it,kk)),0.d0
write(iun2,*) se%freq(it),0.d0,aimag(self_diag(it,kk)),0.d0
enddo
close(iun1)
close(iun2)
enddo
endif
deallocate(psi_mat,sigma_vec)
deallocate(sigma_vec_im)
deallocate(ipiv,self_diag)
END SUBROUTINE solve_off_diagonal
SUBROUTINE free_convergence_tests(ct)
IMPLICIT NONE
TYPE(convergence_tests) :: ct
INTEGER :: iw
do iw=1,ct%nf
call free_memory(ct%wapprox(iw))
call free_memory(ct%g0(iw))
enddo
deallocate(ct%r)
deallocate(ct%energy)
CALL free_memory(ct%xf)
CALL free_memory(ct%h0)
deallocate(ct%wapprox)
deallocate(ct%g0)
RETURN
END SUBROUTINE free_convergence_tests
SUBROUTINE free_vpv(c)
IMPLICIT NONE
TYPE(vpv) :: c
if(associated(c%r)) deallocate(c%r)
if(associated(c%vpvr)) deallocate(c%vpvr)
if(associated(c%vpvr_im)) deallocate(c%vpvr_im)
nullify(c%r,c%vpvr,c%vpvr_im)
RETURN
END SUBROUTINE free_vpv
SUBROUTINE calculate_gzero(g0,freq,r,nr)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE becmod, ONLY : becp,allocate_bec_type,deallocate_bec_type
USE uspp, ONLY : vkb, nkb, okvan
USE g_psi_mod, ONLY : h_diag, s_diag
USE uspp_init, ONLY : init_us_2
IMPLICIT NONE
TYPE(gzero) :: g0!green's function to be created and initialised
REAL(kind=DP) :: freq!frequency to be calculated now just 0 implemented
INTEGER :: r(nr)!list of r points
INTEGER :: nr!number of r points
INTEGER :: ir,ii,jj,ig,iv
COMPLEX(kind=DP), ALLOCATABLE :: psi_g(:,:),psi_g2(:,:)
INTEGER :: kter
LOGICAL :: lconv_root,lfirst
REAL(kind=DP) :: anorm
EXTERNAL :: hpsi_pw4gww2,cg_psi_pw4gww
REAL(kind=DP), PARAMETER :: ethr=1d-10
REAL(kind=DP), ALLOCATABLE :: et0(:,:)
g0%freq=freq
g0%nr=nr
allocate(g0%r(nr))
g0%r(1:nr)=r(1:nr)
allocate(g0%gf(dffts%nnr,1,nr))
allocate(et0(1,1))
et0(1,1)=+(et(num_nbndv(1)+1,1)+et(num_nbndv(1),1))/2.d0
call allocate_bec_type ( nkb, 1, becp)
IF ( nkb > 0 ) CALL init_us_2( npw, igk_k(1,1), xk(1,1), vkb )
allocate (h_diag(npw, 1),s_diag(npw,1))
allocate(psi_g2(npw,1),psi_g(npw,1))
do ig = 1, npw
g2kin (ig) = ( g (1,ig)**2 + g (2,ig)**2 + g (3,ig)**2 ) * tpiba2
enddo
h_diag=0.d0
do ig = 1, npw
h_diag(ig,1)=g2kin(ig)
enddo
!loop on points
do ir=1,nr
psic(1:dfftp%nnr)=0.d0
if(g0%r(ir) /= 0) psic(g0%r(ir))=1.d0*dble((dffts%nr1*dffts%nr2*dffts%nr3))
CALL fwfft ('Wave', psic, dffts)
psi_g(1:npw,1) = psic(dffts%nl(igk_k(1:npw,1)))
psi_g2(1:npw,1)=psi_g(1:npw,1)
call cgsolve_all_gamma (hpsi_pw4gww2,cg_psi_pw4gww,et0,psi_g,psi_g2, &
h_diag,npw,npw,ethr,1,kter,lconv_root,anorm,1,1)
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = psi_g2(1:npw,1)
psic(dffts%nlm(1:npw)) = CONJG( psi_g2(1:npw,1) )
CALL invfft ('Wave', psic, dffts)
g0%gf(1:dffts%nnr,1,ir)= DBLE(psic(1:dffts%nnr))
enddo
deallocate(h_diag,s_diag,psi_g2,et0,psi_g)
call deallocate_bec_type(becp)
return
END SUBROUTINE calculate_gzero
SUBROUTINE calculate_gzero_complex(g0,freq,freq_im,r,nr,l_old,psi_old,l_lanczos,lc,ks_wfcs)
!lanczos AND multiple R points NOT IMPLEMENTED YET
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE mp_global, ONLY : world_comm
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE becmod, ONLY : becp,allocate_bec_type,deallocate_bec_type
USE uspp, ONLY : vkb, nkb, okvan
USE g_psi_mod, ONLY : h_diag, s_diag
USE lanczos
USE lsda_mod, ONLY : nspin, current_spin
USE uspp_init, ONLY : init_us_2
IMPLICIT NONE
TYPE(gzero) :: g0!green's function to be created and initialised
REAL(kind=DP) :: freq!frequency to be calculated real part
REAL(kind=DP) :: freq_im!frequency to be calculated imaginary part
INTEGER :: r(nr)!list of r points
INTEGER :: nr!number of r points
LOGICAL :: l_old!if true in psi_old a previous trial solution is given
COMPLEX(kind=DP) :: psi_old(npw) !in input: previous solution, in output: this solution in G space
LOGICAL :: l_lanczos!if true useus lanczos algorithm for matrix inversion
TYPE(lanczos_chain) :: lc(2)
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wavefunctions in G space
INTEGER :: ir,ii,jj,ig,iv
COMPLEX(kind=DP), ALLOCATABLE :: psi_g(:,:),psi_g2(:,:),psi_g1(:,:),psi_g3(:,:)
INTEGER :: kter
LOGICAL :: lconv_root,lfirst
REAL(kind=DP) :: anorm
EXTERNAL :: hpsi_pw4gww2,cg_psi_pw4gww_square,hpsi_square
REAL(kind=DP), PARAMETER :: ethr=1d-12!DEBUG ERA 10
REAL(kind=DP), ALLOCATABLE :: et_fermi(:,:),et_zero(:,:),et_freq(:),et_freq_set(:)
COMPLEX(kind=DP) :: freqc
INTEGER :: is
REAL(kind=DP) :: sca1,sca2
REAL(kind=DP) :: smearing=0.0d0
call start_clock('gzero_complex')
g0%nr=nr
allocate(g0%r(nr))
g0%r(1:nr)=r(1:nr)
allocate(g0%gf(dffts%nnr,nspin,nr))
allocate(g0%gf_im(dffts%nnr,nspin,nr))
g0%freq=freq
g0%freq_im=freq_im
freqc=cmplx(freq,freq_im)
allocate(et_fermi(1,1),et_zero(1,1),et_freq(2),et_freq_set(2))
et_zero=0.d0
call allocate_bec_type ( nkb, 1, becp)
IF ( nkb > 0 ) CALL init_us_2( npw, igk_k(1,1), xk(1,1), vkb )
allocate (h_diag(npw, 1),s_diag(npw,1))
allocate(psi_g2(npw,1),psi_g(npw,1),psi_g1(npw,1),psi_g3(npw,1))
do ig = 1, npw
g2kin (ig) = ( g (1,ig)**2 + g (2,ig)**2 + g (3,ig)**2 ) * tpiba2
enddo
do is=1,nspin
current_spin=is
et_fermi(1,1)=(et(num_nbndv(is)+1,is)+et(num_nbndv(is),is))/2.d0
!DEBUG INIZIO
!et_fermi(1,1)=(et(num_nbndv(1)+1,1)+et(num_nbndv(1),1))/2.d0
! write(stdout,*) 'DEBUG FERMI ENERGY', et_fermi(1,1)*13.606, num_nbndv(is),is
!DEBUG FINE
do ig = 1, npw
h_diag(ig,1)=1.d0*(g2kin(ig)-(freq+et_fermi(1,1)))**2.d0+freq_im**2.d0
enddo
!loop on points
!set frequencies
et_freq(1)=g0%freq+et_fermi(1,1)+smearing
et_freq(2)=g0%freq_im
et_freq_set(1)=et_fermi(1,1)
et_freq_set(2)=0.d0
call hpsi_square( npw,psi_g,psi_g1,et_freq,-1,2)
call hpsi_square( npw,psi_g,psi_g1,et_freq,-1,2)
!call hpsi_square( npw,psi_g,psi_g1,et_freq,-2,2)!DEBUG
do ir=1,nr
psic(1:dfftp%nnr)=0.d0
if(g0%r(ir) /= 0) psic(g0%r(ir))=1.d0!*dble((dffts%nr1*dffts%nr2*dffts%nr3))
CALL fwfft ('Wave', psic, dffts)
psi_g(1:npw,1) = psic(dffts%nl(igk_k(1:npw,1)))
!call pv_operator(psi_g(1,1),is,ks_wfcs,.true.)
if(lc(is)%l_first .and. l_lanczos) then
!call create_lanczos_chain(lc,hpsi_pw4gww2,1,n_self_lanczos,psi_g(1:npw,1),.true.,et_freq_set,0)
call create_krylov(lc(is),hpsi_pw4gww2,1,n_self_lanczos,psi_g(1,1),et_freq_set,is)!,ks_wfcs)
lc(is)%l_first=.false.
endif
if(l_lanczos) then
!call solve_lanczos(lc,psi_g,freqc,psi_g2,psi_g3,.false.,psi_g,psi_g,hpsi_pw4gww2,et_freq_set)
call solve_krylov(lc(is),psi_g,freqc,psi_g2,psi_g3)
else
!first calculate the real part
call h_psi( npw, npw, 1, psi_g, psi_g1 )
!call pv_operator(psi_g1(1,1),is,ks_wfcs,.true.)
psi_g1(1:npw,1)=psi_g1(1:npw,1)-(freq+et_fermi(1,1))*psi_g(1:npw,1)
if(.not. l_old) then
psi_g2(1:npw,1)=psi_g1(1:npw,1)
else
psi_g2(1:npw,1)=psi_old(1:npw)
endif
call cgsolve_all_gamma(hpsi_square,cg_psi_pw4gww_square,et_zero,psi_g1,psi_g2, &
h_diag,npw,npw,ethr,1,kter,lconv_root,anorm,1,1)
endif
!check for quality of solution
!call h_psi( npw, npw, 1, psi_g2, psi_g3 )
!psi_g3(1:npw,1)=psi_g3(1:npw,1)-(freq+et_fermi(1,1))*psi_g2(1:npw,1)
!psi_g3(1:npw,1)=psi_g3(1:npw,1)-psi_g(1:npw,1)
!sca1=0.d0
!do ig=1,npw
! sca1=sca1+2.0*dble(psi_g3(ig,1)*conjg(psi_g3(ig,1)))
!enddo
!if(gstart==2) sca1=sca1 -dble(psi_g3(1,1)*conjg(psi_g3(1,1)))
!call mp_sum(sca1,world_comm)
!sca2=0.d0
!do ig=1,npw
! sca2=sca2+2.0*dble(psi_g(ig,1)*conjg(psi_g(ig,1)))
!enddo
!if(gstart==2) sca2=sca2 -dble(psi_g(1,1)*conjg(psi_g(1,1)))
!call mp_sum(sca2,world_comm)
!write(stdout,*) 'SOLUTION QUALITY', sca1,sca2,sca1/sca2
!!
!call pc_operator2(psi_g2,is,ks_wfcs,.true.)
psi_old(1:npw)=psi_g2(1:npw,1)
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = psi_g2(1:npw,1)
psic(dffts%nlm(1:npw)) = CONJG( psi_g2(1:npw,1) )
CALL invfft ('Wave', psic, dffts)
g0%gf(1:dffts%nnr,is,ir)= DBLE(psic(1:dffts%nnr))*dble((dffts%nr1*dffts%nr2*dffts%nr3))
!then the imaginary part
if(.not.l_lanczos) then
psi_g1(1:npw,1)=freq_im*psi_g(1:npw,1)
psi_g3(1:npw,1)=psi_g1(1:npw,1)
call cgsolve_all_gamma(hpsi_square,cg_psi_pw4gww_square,et_zero,psi_g1,psi_g3, &
h_diag,npw,npw,ethr,1,kter,lconv_root,anorm,1,1)
endif
!call pc_operator2(psi_g3,is,ks_wfcs,.true.)
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = psi_g3(1:npw,1)
psic(dffts%nlm(1:npw)) = CONJG( psi_g3(1:npw,1) )
CALL invfft ('Wave', psic, dffts)
g0%gf_im(1:dffts%nnr,is,ir)= DBLE(psic(1:dffts%nnr))*dble((dffts%nr1*dffts%nr2*dffts%nr3))
enddo
enddo
!DEBUG INIZIO
! g0%gf_im(1:dffts%nnr,2,1)= g0%gf_im(1:dffts%nnr,1,1)
! g0%gf(1:dffts%nnr,2,1)= g0%gf(1:dffts%nnr,1,1)
!DEBUG FINE
deallocate(h_diag,s_diag,psi_g2,et_fermi,psi_g,psi_g1,psi_g3)
deallocate(et_zero,et_freq,et_freq_set)
call deallocate_bec_type(becp)
call stop_clock('gzero_complex')
return
END SUBROUTINE calculate_gzero_complex
SUBROUTINE calculate_vpv_complex(c,freq,freq_im,r,nr,v_states,l_w,thrs,lc,&
& head, wing, alpha,ks_wfcs, l_save,phi_save)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE becmod, ONLY : becp,allocate_bec_type,deallocate_bec_type
USE uspp, ONLY : vkb, nkb, okvan
USE g_psi_mod, ONLY : h_diag, s_diag
USE mp_world, ONLY : world_comm
USE lanczos
USE lsda_mod, ONLY : nspin, current_spin
USE io_files, ONLY : prefix, diropn
USE gvecw, ONLY : ecutwfc
USE uspp_init, ONLY : init_us_2
IMPLICIT NONE
TYPE(vpv) :: c!vpv structure to be created and initialised
REAL(kind=DP) :: freq!frequency to be calculated now just 0 implemenmted , real part
REAL(kind=DP) :: freq_im!frequency to be calculated now just 0 implemenmted, imaginary part
INTEGER :: r(nr)!list of r points
INTEGER :: nr!number of r points
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbnds,nspin)!valence states in real space
LOGICAL :: l_w!if true calculate W
REAL(kind=DP) :: thrs!threshold for W calculations, now only for imaginary frequencies
TYPE(lanczos_chain) :: lc(2) !structure for lanczos chains
REAL(kind=DP) :: head! in case of extended systems, the head of the RPA symm. diel. matrix
COMPLEX(kind=DP) :: wing(npw)!wing of the symmetric irriducible dielectric matrix
REAL(kind=DP) :: alpha !initial parameter for Richardson algorithm
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wave functions in real space
COMPLEX(kind=DP), INTENT(inout) :: phi_save(npw)!previous solutionn to the problem
LOGICAL, INTENT(in) :: l_save!if true in phi_save previous solution to the problem
INTEGER :: ir,ii,jj,ig,iv
REAL(kind=DP), ALLOCATABLE :: fac(:)
REAL(kind=DP):: qq
COMPLEX(kind=DP), ALLOCATABLE :: verre(:),verre0(:)
INTEGER :: numv(2)
COMPLEX(kind=DP), ALLOCATABLE :: psi_g2(:,:,:),psi_g1(:,:),psi_g3(:,:),psi_g4(:,:,:),psi_g5(:,:)
REAL(kind=DP), ALLOCATABLE :: psi_r(:,:),psi_v(:),psi_v0(:)
COMPLEX(kind=DP), ALLOCATABLE :: psi_g(:,:,:)
INTEGER :: kter
LOGICAL :: lconv_root,lfirst
REAL(kind=DP) :: anorm
EXTERNAL :: hpsi_square,cg_psi_pw4gww_square,hpsi_pw4gww
COMPLEX(kind=DP), ALLOCATABLE :: opsi(:)
REAL(kind=DP), PARAMETER :: ethr=1d-10
REAL(kind=DP) et_freq(2)
INTEGER :: it
INTEGER :: max_iter=50!maximum number of iterations (15)
REAL(kind=DP) :: sca
COMPLEX(kind=DP) :: freqc
COMPLEX(kind=DP), ALLOCATABLE :: verreg(:,:,:)
REAL(kind=DP) :: erre,erre2
REAL(kind=DP), ALLOCATABLE :: et_scissor(:,:)
REAL(kind=DP) :: scissor_w=0.d0!DEBUG ATTENZIONE ERA 0.d0
REAL(kind=DP) :: wing_fact
COMPLEX(kind=DP), ALLOCATABLE :: phi0(:),phi1(:)
REAL(kind=DP) :: previous_norm=10.d0
REAL(kind=DP) :: testa(3)
REAL(kind=DP), ALLOCATABLE :: norms(:,:),norms_lan(:,:)
TYPE(lanczos_chain) :: lc_save(2)
REAL(kind=DP) :: energy0, energy1, energy,energy_old,mod_force, mod_force_old
COMPLEX(kind=DP), ALLOCATABLE :: force(:),phi_old(:)
COMPLEX(kind=DP), ALLOCATABLE :: psi_g_phi(:,:)
REAL(kind=DP) :: alpha_old,par_a,par_b=1.d0,par_c=1.d0, alpha_new
LOGICAL :: l_updated
COMPLEX(kind=DP), ALLOCATABLE :: h_diag2(:,:), s_diag2(:,:)
INTEGER :: is
LOGICAL :: l_update_basis_w, l_restart
COMPLEX(kind=DP), ALLOCATABLE :: p_basis(:,:)
INTEGER :: iungprod
LOGICAL :: exst
INTEGER, EXTERNAL :: find_free_unit
REAL(kind=DP), ALLOCATABLE :: pbr(:),wpbr(:)
INTEGER :: ifreq, ngm_max
REAL(kind=DP), ALLOCATABLE :: omat(:,:)
if(freq_im<0.2d0) then
l_update_basis_w=.false.
max_iter=100
else
l_update_basis_w=.false.
endif
l_restart=.false.
l_wing=.true.
previous_norm=10.d0
energy_old=10.d10
mod_force_old=10.d0
alpha_old=alpha
l_updated=.false.
call start_clock('vpv_complex')
call initialize_memory(lc_save(1))
call initialize_memory(lc_save(2))
if(.not.lc(1)%l_first) call copy(lc(1),lc_save(1))
if(.not.lc(2)%l_first .and. nspin==2) call copy(lc(2),lc_save(2))
numv(1)=num_nbndv(1)
if(nspin==2) numv(2)=num_nbndv(2)
allocate(norms(numv(1),nspin),norms_lan(numv(1),nspin))
allocate(force(npw),phi_old(npw))
freqc=cmplx(freq,freq_im)
c%freq=freq
c%freq_im=freq_im
allocate(c%r(nr))
c%r(1:nr)=r(1:nr)
allocate(c%vpvr(dffts%nnr,nr))
allocate(c%vpvr_im(dffts%nnr,nr))
if(.not.l_w) max_iter=1
allocate(phi0(npw),phi1(npw))
allocate(psi_g_phi(npw,numv(1)))
c%vpvr_im=0.d0
et_freq(1)=freq
et_freq(2)=freq_im
!allocate
allocate(fac(ngm))
if(l_truncated_coulomb) then
do ig=1,ngm
qq = g(1,ig)**2.d0 + g(2,ig)**2.d0 + g(3,ig)**2.d0
if (qq > 1.d-8) then
fac(ig)=(e2*fpi/(tpiba2*qq))*(1.d0-dcos(dsqrt(qq)*truncation_radius*tpiba))
else
fac(ig)=e2*fpi*(truncation_radius**2.d0/2.d0)
endif
enddo
if(gstart==2) fac(1)=0.d0
fac(:)=fac(:)/omega
else
fac(1:npw)=vg_q(1:npw)
endif
if(.not.l_truncated_coulomb .and. l_wing) then
wing(gstart:npw)=wing(gstart:npw)*sqrt( fac(gstart:npw)*omega/e2/fpi)
endif
allocate(verre(npw),verre0(npw))
allocate(verreg(npw,numv(1),nspin))
call allocate_bec_type ( nkb, numv(1), becp)
IF ( nkb > 0 ) CALL init_us_2( npw, igk_k(1,1), xk(1,1), vkb )
allocate (h_diag(npw, numv(1)),s_diag(npw,numv(1)))
allocate(psi_g2(npw,numv(1),nspin))
do ig = 1, npw
g2kin (ig) = ( g (1,ig)**2 + g (2,ig)**2 + g (3,ig)**2 ) * tpiba2
enddo
h_diag=0.d0
do iv = 1, numv(1)
do ig = 1, npw
h_diag(ig,iv)=(g2kin(ig)-(freq+et(iv,1)))**2.d0+freq_im**2.d0
enddo
enddo
allocate(psi_r(dffts%nnr,2),psi_v(dffts%nnr),psi_v0(dffts%nnr))
allocate(psi_g(npw,numv(1),nspin),psi_g1(npw,numv(1)),psi_g3(npw,numv(1)))
allocate(opsi(npw))
allocate(psi_g4(npw,numv(1),nspin),psi_g5(npw,numv(1)))
if(nspin==2) then
allocate(h_diag2(npw, numv(2)),s_diag2(npw,numv(2)))
h_diag2=0.d0
do iv = 1, numv(2)
do ig = 1, npw
h_diag2(ig,iv)=(g2kin(ig)-(freq+et(iv,2)))**2.d0+freq_im**2.d0
enddo
enddo
endif
allocate(et_scissor(numv(1),1))
et_scissor(1:numv(1),1)=et(1:numv(1),1)-scissor_w
!loop on points
do ir=1,nr
it=0
do while(it < max_iter)
it=it+1
!first real part
!product with v
if(it==1) alpha=1.0
if(it==1.or.l_easy_update_basis_w) then
psic(1:dfftp%nnr)=0.d0
if(c%r(ir) /= 0) psic(c%r(ir))=1.!*dble((dffts%nr1*dffts%nr2*dffts%nr3))
CALL fwfft ('Wave', psic, dffts)
verre(1:npw) = psic(dffts%nl(igk_k(1:npw,1)))
if(l_easy_dielectric_constant) verre(gstart:npw)=0.d0
if(gstart==2) then
erre=verre(1)
wing_fact=sqrt(fac(1))
else
erre=0.d0
wing_fact=0.d0
endif
call mp_sum(erre, world_comm)
call mp_sum(wing_fact, world_comm)
verre0(1:npw)=verre(1:npw)
verre(1:npw)=sqrt(fac(1:npw))*verre(1:npw)
do is=1,nspin
do iv=1,numv(is)
verreg(1:npw,iv,is)=verre(1:npw)
enddo
enddo
if(it==1) then
if(.not.l_save) then
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = verre(1:npw)
psic(dffts%nlm(1:npw)) = CONJG( verre(1:npw))
phi0(1:npw)=verre0(1:npw)
else
phi0(1:npw)=phi_save(1:npw)
endif
else
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = phi0(1:npw)*sqrt(fac(1:npw))
psic(dffts%nlm(1:npw)) = CONJG( phi0(1:npw)*sqrt(fac(1:npw)) )
endif
CALL invfft ('Wave', psic, dffts)
psi_v0(1:dffts%nnr)= DBLE(psic(1:dffts%nnr))
endif
if(lc(1)%l_first.or. (l_easy_update_basis_w.and.it>1) .or. (l_update_basis_w .and. it==1) ) then!DEBUG ERA 1
psi_v(1:dffts%nnr)=psi_v0(1:dffts%nnr)
do is=1,nspin
do iv=1,numv(is),2
!!product with psi_v
if(iv/=numv(1)) then
psi_r(1:dffts%nnr,1)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv,is)
psi_r(1:dffts%nnr,2)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv+1,is)
else
psi_r(1:dffts%nnr,1)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv,is)
endif
!!fourier transfrm to G
if(iv/=numv(is)) then
psic(1:dffts%nnr)=cmplx(psi_r(1:dffts%nnr,1),psi_r(1:dffts%nnr,2))
else
psic(1:dffts%nnr)=cmplx(psi_r(1:dffts%nnr,1),0.d0)
endif
CALL fwfft ('Wave', psic, dffts)
if(iv/=numv(is)) then
psi_g(1:npw,iv,is)=0.5d0*(psic(dffts%nl(1:npw))+conjg(psic(dffts%nlm(1:npw))))
psi_g(1:npw,iv+1,is)=(0.d0,-0.5d0)*(psic(dffts%nl(1:npw))-conjg(psic(dffts%nlm(1:npw))))
if(gstart==2) psi_g(1,iv,is)=dble(psi_g(1,iv,is))
if(gstart==2) psi_g(1,iv+1,is)=dble(psi_g(1,iv+1,is))
else
psi_g(1:npw,iv,is)=psic(dffts%nl(1:npw))
if(gstart==2) psi_g(1,iv,is)=dble(psi_g(1,iv,is))
endif
!!project on conduction manifold
call start_clock('opsi_pc')
if(iv/=numv(is)) then
call pc_operator2(psi_g(:,iv,is),is,ks_wfcs,.true.)!DEBUG ERA FALSE
call pc_operator2(psi_g(:,iv+1,is),is,ks_wfcs,.true.)
else
call pc_operator2(psi_g(:,iv,is),is,ks_wfcs,.true.)
endif
call stop_clock('opsi_pc')
enddo
enddo
norms=0.d0
do is=1,nspin
do iv=1,numv(is)
do ig=1,npw
norms(iv,is)=norms(iv,is)+2.d0*dble(conjg(psi_g(ig,iv,is))*psi_g(ig,iv,is))
enddo
if(gstart==2) norms(iv,is)=norms(iv,is)-dble(conjg(psi_g(1,iv,is))*psi_g(1,iv,is))
enddo
enddo
call mp_sum(norms,world_comm)
if(it>1) then
do is=1,nspin
do iv=1,numv(is)
verreg(1:npw,iv,is)=phi0(1:npw)*sqrt(fac(1:npw))
enddo
if(gstart==2) verreg(1,:,is)=0.d0
call norms_lanczos(lc(is),verreg(1,1,is),norms_lan(1,is))
enddo
endif
!if required start lanczos chains
! if(it>1 .and. l_verbose) write(stdout,*) 'SCARTO MAX', &
! &maxval(abs(norms(1:numv(1),1)-norms_lan(1:numv(1),1))/norms(1:numv(1),1)),alpha
! if(it>1 .and. l_verbose .and. nspin==2) write(stdout,*) 'SCARTO MAX2', &
! &maxval(abs(norms(1:numv(2),2)-norms_lan(1:numv(2),2))/norms(1:numv(2),2)),alpha
if(it==1 ) then
call start_clock('vpv_lanczos')
do is=1,nspin
et_scissor(1:numv(is),1)=et(1:numv(is),is)-scissor_w
current_spin=is
evc(1:npw, 1:numv(is))=ks_wfcs(1:npw,1:numv(is),is)
call free_memory(lc(is))
!
call create_krylov(lc(is),hpsi_pw4gww,numv(is),n_pola_lanczos,psi_g(1,1,is),et_scissor,is)!,ks_wfcs)
call product_chain(lc(is),v_states(1,1,is),0)
lc(is)%l_first=.false.
if(it==1) call copy(lc(is),lc_save(is))
enddo
call stop_clock('vpv_lanczos')
else
do is=1,nspin
evc(1:npw, 1:numv(is))=ks_wfcs(1:npw,1:numv(is),is)
current_spin=is
et_scissor(1:numv(is),1)=et(1:numv(is),is)-scissor_w
if((maxval(abs(norms(1:numv(is),is)-norms_lan(1:numv(is),is))/norms(1:numv(is),is)) > easy_w_update_lanczos &
&.and. maxval (lc(is)%ns_chain) > 5*n_pola_lanczos) .or. l_update_basis_w) then
!ATTENZIONE ERA 5
call free_memory(lc(is))
call create_krylov(lc(is),hpsi_pw4gww,numv(is),n_pola_lanczos,psi_g(1,1,is),et_scissor,is)!,ks_wfcs)
call product_chain(lc(is),v_states(1,1,is),0)
lc(is)%l_first=.false.
elseif(.not.l_updated) then
do iv=1,numv(is)
if(abs(norms(iv,is)-norms_lan(iv,is))/norms(iv,is) > easy_w_update_lanczos) then
! if( l_verbose) write(stdout,*) 'UPDATING LANCZOS', iv,is!DEBUG_NO
call update_krylov(lc(is),hpsi_pw4gww,psi_g(1,1,is),et_scissor, 2,iv,is,ks_wfcs)
call product_chain_krylov(lc(is),v_states(1,1,is),2,iv)
endif
enddo
endif
enddo
endif
elseif (l_easy_update_basis_w.and.it==1) then
!call copy(lc_save,lc)
endif
call start_clock('vpv_lanczos')
do is=1,nspin
do iv=1,numv(is)
verreg(1:npw,iv,is)=phi0(1:npw)*sqrt(fac(1:npw))
enddo
if(gstart==2 ) verreg(1,:,is)=0.d0!ATTENZIONE
enddo
!call product_wfc(v_states,numv,psi_g,psi_g_phi)
do is=1,nspin
if(lc(1)%l_krylov) then
call solve_krylov(lc(is),verreg(1,1,is),freqc,psi_g2(1,1,is),psi_g4(1,1,is))
else
! call solve_lanczos(lc(is),verreg(1,1,is),freqc,psi_g2,psi_g4,.false.,psi_g,psi_g_phi,hpsi_pw4gww,et_scissor)
endif
if(gstart==2) psi_g2(1,1:numv(1),is)=0.d0
enddo
if(nspin==1) then
psi_g2=4.d0*psi_g2
else
psi_g2=2.d0*psi_g2
endif
psi_g4=0.d0
call stop_clock('vpv_lanczos')
if(gstart==2) phi0(1)=dble(phi0(1))
phi1(1:npw)=alpha*(-phi0(1:npw)+verre(1:npw))
energy0=0.d0
do ig=1,npw
energy0=energy0+2.d0*dble(conjg(phi0(ig)*verre(ig)))
enddo
if(gstart==2) energy0=energy0-dble(conjg(phi0(1)*verre(1)))
call mp_sum(energy0,world_comm)
energy0=energy0*2.d0
do is=1,nspin
do iv=1,numv(is)
phi1(1:npw)=phi1(1:npw)+alpha*(-sqrt(fac(1:npw))*psi_g2(1:npw,iv,is))
enddo
enddo
if(gstart==2 .and. l_truncated_coulomb) phi1(1)=0.d0
if(.not.l_truncated_coulomb.and.l_wing) then
!add wing term
if(gstart==2) then
wing_fact=phi0(1)
else
wing_fact=0.
endif
erre2=0.d0
do ig=gstart,npw
erre2=erre2+2.d0*dble(conjg(wing(ig))*phi0(ig))
enddo
call mp_sum(wing_fact,world_comm)
call mp_sum(erre2,world_comm)
phi1(gstart:npw)=phi1(gstart:npw)-wing(gstart:npw)*wing_fact*alpha
if(gstart==2) phi1(1)=phi1(1)+phi0(1)*(-head)*alpha!OK
if(gstart==2) phi1(1)=phi1(1)-erre2*alpha
if(gstart==2) then
testa(1)=phi1(1)+phi0(1)
testa(2)=verre(1)
testa(3)=phi0(1)
else
testa=0.d0
endif
call mp_sum(testa,world_comm)
! if(l_verbose) write(stdout,*)' TESTA', testa(1:3),head,erre2,wing_fact!DEBUG_NO
endif
force(1:npw)=phi1(1:npw)/alpha
phi1(1:npw)=phi1(1:npw)+phi0(1:npw)
mod_force=0.d0
do ig=1,npw
mod_force=mod_force+2.d0*dble(conjg(force(ig))*(force(ig)))
enddo
if(gstart==2) mod_force=mod_force-dble(conjg(force(1))*(force(1)))
call mp_sum(mod_force,world_comm)
energy1=0.d0
do ig=1,npw
energy1=energy1+2.d0*dble(conjg(phi0(ig))*(-(force(ig)+verre(ig))))
enddo
if(gstart==2) energy1=energy1-dble(conjg(phi0(1))*(-(force(1)+verre(1))))
call mp_sum(energy1,world_comm)
!energy=-energy0+energy1
energy=energy1
! if(l_verbose) write(stdout,*) 'ENERGIA :',energy0,energy1,energy!DEBUG_NO
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = phi1(1:npw)*sqrt(fac(1:npw))-verre(1:npw)*sqrt(fac(1:npw))
psic(dffts%nlm(1:npw)) = CONJG( phi1(1:npw)*sqrt(fac(1:npw))-verre(1:npw)*sqrt(fac(1:npw)))
CALL invfft ('Wave', psic, dffts)
c%vpvr(1:dffts%nnr,ir)= DBLE(psic(1:dffts%nnr))
!now imaginary part
!TO BE DONE
c%vpvr_im(1:dffts%nnr,ir)=0.d0
sca=0.d0
do ig=1,npw
sca=sca+2.d0*dble((phi0(ig)-phi1(ig))*conjg(phi0(ig)-phi1(ig)))
enddo
if(gstart==2) sca=sca-dble((phi0(1)-phi1(1))*conjg(phi0(1)-phi1(1)))
call mp_sum(sca,world_comm)
sca=sca*dble((dffts%nr1*dffts%nr2*dffts%nr3))
! if(l_verbose) write(stdout,*) 'Convergence criteria:', mod_force,it,alpha!DEBUG_NO
if(mod_force< thrs) then
if(l_verbose) write(stdout,*) 'Converged with interations :', it
write(stdout,*) 'Converged with interations :', it, mod_force
phi_save(1:npw)=phi1(1:npw)
exit
!elseif(mod_force>mod_force_old .or. abs(mod_force_old-mod_force)/mod_force_old < 0.1) then
elseif(mod_force>mod_force_old) then
if(l_verbose) write(stdout,*) 'ALPHA UPDATE'
!elseif(energy>1d10) then
alpha=alpha*easy_w_update_alpha
phi0(1:npw)=phi_old(1:npw)
l_updated=.true.
mod_force_old=10.d10
energy_old=10.d0
!DEBUG INIZIO
! phi_old(1:npw)=phi0(1:npw)
! phi0(1:npw)=phi1(1:npw)
!DEBUG FINE
! (sca>previous_norm) then
!
! alpha=alpha/2.d0
! it=0!START FROM BEGINNING
! previous_norm=10.0
! if(l_verbose) write(stdout,*) 'NEW ALPHA FOR RICHARDSON', alpha
! elseif((previous_norm-sca)/previous_norm<0.25) then
! write(stdout,*) 'START ANEW 1'
! alpha=alpha/2.d0
! it=0
! previous_norm=10.0
! if(l_verbose) write(stdout,*) 'NEW ALPHA FOR RICHARDSON', alpha
else
l_updated=.false.
if(energy_old<1d0) then
par_a=energy_old
par_b=-mod_force_old*2.d0
par_c=(energy-par_a-par_b*alpha_old)/alpha_old**2.d0
! if(l_verbose) write(stdout,*) 'NEW ALPHA FROM MINIMIZATION', -par_b/(2.d0*par_c)!DEBUG_NO
endif
previous_norm=sca
mod_force_old=mod_force
alpha_old=alpha
phi_old(1:npw)=phi0(1:npw)
phi0(1:npw)=phi1(1:npw)
alpha_new= -par_b/(2.d0*par_c)
if(energy_old<1d0 .and. alpha_new > 0.1d0 .and. alpha_new < 2.d0 .and. mod_force>1d-14) alpha=alpha_new !DEBUG
energy_old=energy
endif
!if(l_verbose.and. .not.l_truncated_coulomb ) write(stdout,*) 'costante dielettrica',it, 1./( testa(1)/testa(2)),alpha
if(it==max_iter .and. .not.l_restart) then
if(l_verbose) write(stdout,*) 'NOT CONVERGED, RETRYING:', freq_im
l_update_basis_w=.true.
it=0
previous_norm=10.d0
energy_old=10.d10
mod_force_old=10.d0
alpha_old=alpha
l_updated=.false.
l_restart=.true.
endif
enddo
if(it==max_iter) write(stdout,*) 'NOT CONVERGED:' ,it,mod_force
if(l_easy_dielectric_constant .and. .not.l_truncated_coulomb) then
write(stdout,*) 'COSTANTE DIELETTRICA',1./( testa(1)/testa(2))
endif
c%vpvr(1:dffts%nnr,ir)= c%vpvr(1:dffts%nnr,ir)*dble((dffts%nr1*dffts%nr2*dffts%nr3))
c%vpvr_im(1:dffts%nnr,ir)= c%vpvr_im(1:dffts%nnr,ir)*dble((dffts%nr1*dffts%nr2*dffts%nr3))
!add head term
if(.not.l_truncated_coulomb.and.(.not.l_wing)) then
psic(:)=(0.d0,0.d0)
if(gstart==2) psic(dffts%nl(1)) = fac(1)*erre*(1.d0/(head+1.d0)-1.d0)
if(gstart==2) write(stdout,*) 'DEBUG PSIC', fac(1)*erre*(1.d0/(head+1.d0)-1.d0)
if(l_verbose) write(stdout,* ) 'HEAD ', head
CALL invfft ('Wave', psic, dffts)
c%vpvr(1:dffts%nnr,ir)= c%vpvr(1:dffts%nnr,ir)+ &
& DBLE(psic(1:dffts%nnr))*dble((dffts%nr1*dffts%nr2*dffts%nr3))
endif
enddo
!call copy(lc_save,lc)
deallocate(h_diag,s_diag,opsi)
deallocate(fac,verre,verre0,psi_g2,psi_r,psi_g,psi_v,psi_v0,psi_g1,psi_g3)
deallocate(psi_g4,psi_g5)
call deallocate_bec_type(becp)
deallocate(verreg)
deallocate(phi0,phi1)
deallocate(norms,norms_lan)
call free_memory(lc_save(1))
call free_memory(lc_save(2))
deallocate(force,phi_old)
deallocate(psi_g_phi)
deallocate(et_scissor)
if(nspin==2) then
deallocate(h_diag2,s_diag2)
endif
call stop_clock('vpv_complex')
return
END SUBROUTINE calculate_vpv_complex
SUBROUTINE calculate_x(xf,r,nr,v_states)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE becmod, ONLY : becp,allocate_bec_type,deallocate_bec_type
USE uspp, ONLY : vkb, nkb, okvan
USE g_psi_mod, ONLY : h_diag, s_diag
USE lsda_mod, ONLY : lsda, nspin,current_spin,isk
IMPLICIT NONE
TYPE(exchange) :: xf!exchange structure to be created and initialised
INTEGER :: r(nr)!list of r points
INTEGER :: nr!number of r points
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbnds,nspin)!valence states in real space
REAL(kind=DP), ALLOCATABLE :: fac(:)
REAL(kind=DP):: qq
INTEGER :: ir,ii,jj,ig,iv,is
REAL(kind=DP), ALLOCATABLE :: psi_r(:,:),psi_v(:)
COMPLEX(kind=DP), ALLOCATABLE :: psi_g(:,:)
INTEGER :: numv
xf%nr=nr
allocate(xf%r(nr))
xf%r(1:nr)=r(1:nr)
allocate(xf%x(dffts%nnr,nr,nspin))
xf%x=0.d0
allocate(fac(ngm))
allocate(psi_r(dffts%nnr,2),psi_v(dffts%nnr))
allocate(psi_g(npw,num_nbndv(1)))
if(l_truncated_coulomb) then
do ig=1,ngm
qq = g(1,ig)**2.d0 + g(2,ig)**2.d0 + g(3,ig)**2.d0
if (qq > 1.d-8) then
fac(ig)=(e2*fpi/(tpiba2*qq))*(1.d0-dcos(dsqrt(qq)*truncation_radius*tpiba))
else
fac(ig)=e2*fpi*(truncation_radius**2.d0/2.d0)
endif
enddo
fac(:)=fac(:)/omega
else
fac(:)=0.d0
fac(1:npw)=vg_q(1:npw)
endif
do is=1,nspin
numv=num_nbndv(is)
do ir=1,nr
!product with v
psi_v(1:dfftp%nnr)=0.d0
if(xf%r(ir) /= 0) psi_v(xf%r(ir))=1.d0!*dble((dffts%nr1*dffts%nr2*dffts%nr3))
do iv=1,numv,2
!!product with psi_v
if(iv/=numv) then
psi_r(1:dffts%nnr,1)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv,is)
psi_r(1:dffts%nnr,2)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv+1,is)
else
psi_r(1:dffts%nnr,1)=psi_v(1:dffts%nnr)*v_states(1:dffts%nnr, iv,is)
endif
!!fourier transfrm to G
if(iv/=numv) then
psic(1:dffts%nnr)=cmplx(psi_r(1:dffts%nnr,1),psi_r(1:dffts%nnr,2))
else
psic(1:dffts%nnr)=cmplx(psi_r(1:dffts%nnr,1),0.d0)
endif
CALL fwfft ('Wave', psic, dffts)
if(iv/=numv) then
psi_g(1:npw,iv)=0.5d0*(psic(dffts%nl(1:npw))+conjg(psic(dffts%nlm(1:npw))))
psi_g(1:npw,iv+1)=(0.d0,-0.5d0)*(psic(dffts%nl(1:npw))-conjg(psic(dffts%nlm(1:npw))))
if(gstart==2) psi_g(1,iv)=dble(psi_g(1,iv))
if(gstart==2) psi_g(1,iv+1)=dble(psi_g(1,iv+1))
else
psi_g(1:npw,iv)=psic(dffts%nl(1:npw))
if(gstart==2) psi_g(1,iv)=dble(psi_g(1,iv))
endif
enddo
do iv=1,numv
psi_g(1:npw,iv)=fac(1:npw)*psi_g(1:npw,iv)
enddo
do iv=1,numv,2
!!fourier transform to R space
psic(:)=(0.d0,0.d0)
if(iv/=numv) then
psic(dffts%nl(1:npw)) = psi_g(1:npw,iv)+(0.d0,1.d0)*psi_g(1:npw,iv+1)
psic(dffts%nlm(1:npw)) = CONJG( psi_g(1:npw,iv) )+(0.d0,1.d0)*conjg(psi_g(1:npw,iv+1))
else
psic(dffts%nl(1:npw)) = psi_g(1:npw,iv)
psic(dffts%nlm(1:npw)) = CONJG( psi_g(1:npw,iv) )
endif
CALL invfft ('Wave', psic, dffts)
if(iv/=numv) then
psi_r(:,1)= DBLE(psic(:))
psi_r(:,2)= dimag(psic(:))
else
psi_r(:,1)= DBLE(psic(:))
endif
!!product with psi_v
if(iv/=numv) then
psi_r(1:dffts%nnr,1)=psi_r(1:dffts%nnr,1)*v_states(1:dffts%nnr,iv,is)
psi_r(1:dffts%nnr,2)=psi_r(1:dffts%nnr,2)*v_states(1:dffts%nnr,iv+1,is)
xf%x(1:dffts%nnr,ir,is)=xf%x(1:dffts%nnr,ir,is)+psi_r(1:dffts%nnr,1)+psi_r(1:dffts%nnr,2)
else
psi_r(1:dffts%nnr,1)=psi_r(1:dffts%nnr,1)*v_states(1:dffts%nnr,iv,is)
xf%x(1:dffts%nnr,ir,is)=xf%x(1:dffts%nnr,ir,is)+psi_r(1:dffts%nnr,1)
endif
enddo
enddo
enddo
deallocate(fac,psi_r,psi_v,psi_g)
RETURN
END SUBROUTINE calculate_x
SUBROUTINE calculate_hks(h0,r,nr,v_states)
USE constants, ONLY : e2, pi, tpi, fpi
USE cell_base, ONLY: at, alat, tpiba, omega, tpiba2
USE fft_base, ONLY : dfftp, dffts
USE fft_interfaces, ONLY : fwfft, invfft
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE io_global, ONLY : stdout, ionode, ionode_id
USE wannier_gw
USE wavefunctions, ONLY : evc, psic
USE wvfct, ONLY : g2kin, npwx, npw, nbnd, et
USE gvect
USE klist, ONLY : igk_k,xk
USE becmod, ONLY : becp,allocate_bec_type,deallocate_bec_type
USE uspp, ONLY : vkb, nkb, okvan
USE g_psi_mod, ONLY : h_diag, s_diag
USE scf, ONLY : rho, vltot, vrs, rho_core,rhog_core, scf_type
USE lsda_mod, ONLY : nspin
USE uspp_init, ONLY : init_us_2
IMPLICIT NONE
TYPE(hks) :: h0!Hamiltonian function to be created and initialised
INTEGER :: r(nr)!list of r points
INTEGER :: nr!number of r points
REAL(kind=DP), INTENT(in) :: v_states(dffts%nnr,num_nbndv(1))
INTEGER :: ir,ii,jj,ig,iv
COMPLEX(kind=DP), ALLOCATABLE :: psi_g(:,:),psi_g2(:,:)
INTEGER :: kter
LOGICAL :: lconv_root,lfirst
REAL(kind=DP) :: anorm
EXTERNAL :: hpsi_pw4gww2,cg_psi_pw4gww
REAL(kind=DP), PARAMETER :: ethr=1d-10
REAL(kind=DP) :: etxc,vtxc,ehart, charge
REAL(kind=DP), ALLOCATABLE :: rho_fake_core(:)
REAL(kind=DP), ALLOCATABLE :: vr(:,:)
allocate(vr(dfftp%nnr,nspin))
h0%nr=nr
allocate(h0%r(nr))
h0%r(1:nr)=r(1:nr)
allocate(h0%h0(dffts%nnr,nr))
allocate(h0%vxc(dffts%nnr,nspin))
call allocate_bec_type ( nkb, 1, becp)
IF ( nkb > 0 ) CALL init_us_2( npw, igk_k(1,1), xk(1,1), vkb )
allocate (h_diag(npw, 1),s_diag(npw,1))
allocate(psi_g2(npw,1),psi_g(npw,1))
do ig = 1, npw
g2kin (ig) = ( g (1,ig)**2 + g (2,ig)**2 + g (3,ig)**2 ) * tpiba2
enddo
h_diag=0.d0
do ig = 1, npw
h_diag(ig,1)=g2kin(ig)
enddo
!loop on points
do ir=1,nr
psic(1:dfftp%nnr)=0.d0
if(h0%r(ir) /= 0) psic(h0%r(ir))=1.d0!*dble((dffts%nr1*dffts%nr2*dffts%nr3))
!psic(1:dfftp%nnr)=v_states(1:dfftp%nnr,num_nbndv(1))
CALL fwfft ('Wave', psic, dffts)
psi_g(1:npw,1) = psic(dffts%nl(igk_k(1:npw,1)))
call h_psi( npw, npw, 1, psi_g, psi_g2 )
psic(:)=(0.d0,0.d0)
psic(dffts%nl(1:npw)) = psi_g2(1:npw,1)
psic(dffts%nlm(1:npw)) = CONJG( psi_g2(1:npw,1) )
CALL invfft ('Wave', psic, dffts)
h0%h0(1:dffts%nnr,ir)= DBLE(psic(1:dffts%nnr))
allocate(rho_fake_core(dfftp%nnr))
rho_fake_core(:)=0.d0
CALL v_xc( rho, rho_core, rhog_core, etxc, vtxc, vr )
h0%vxc(1:dffts%nnr,1:nspin)=vr(1:dffts%nnr,1:nspin)
deallocate(rho_fake_core)
enddo
deallocate(h_diag,s_diag,psi_g2,psi_g)
call deallocate_bec_type(becp)
deallocate(vr)
return
END SUBROUTINE calculate_hks
subroutine pv_operator(state,ispin,ks_wfcs, l_all)
!this operator project the wavefunction state on the valence
!subspace, the valence wavefunction are in evc
USE io_global, ONLY : stdout
USE kinds, ONLY : DP
USE gvect
USE wvfct, ONLY : npwx, npw, nbnd
USE wavefunctions, ONLY : evc, psic
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE mp_world, ONLY : world_comm
USE wannier_gw, ONLY : num_nbndv,num_nbnds
USE lsda_mod, ONLy :nspin
implicit none
COMPLEX(kind=DP), INTENT(inout) :: state(npw)!state to be projected
INTEGER, INTENT(in) :: ispin!spin channel
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wavefunctions
LOGICAL, INTENT(in) :: l_all! if true project over the entire KS manifold
INTEGER :: iv,ig
REAL(kind=DP), ALLOCATABLE :: prod(:)
INTEGER :: num_proj
if(num_nbndv(ispin)==0) return
if(l_all) then
num_proj=num_nbndv(ispin)
else
num_proj=nbnd
endif
allocate(prod(num_proj))
call dgemm('T','N', num_proj,1,2*npw,2.d0,ks_wfcs(1,1,ispin),2*npwx,state,2*npw,&
& 0.d0,prod,num_proj)
do iv=1,num_proj
if(gstart==2) prod(iv)=prod(iv)-dble(conjg(ks_wfcs(1,iv,ispin))*state(1))
enddo
call mp_sum(prod, world_comm)
call dgemm('N','N',2*npw,1,num_proj,1.d0,ks_wfcs(1,1,ispin),2*npwx,prod,&
&num_proj,0.d0,state,2*npw)
deallocate(prod)
return
end subroutine pv_operator
subroutine pc_operator2(state,ispin,ks_wfcs, l_all)
!this operator project the wavefunction state on the conduction
!subspace, the valence wavefunction are in evc
!ONLY FOR GAMMA POINT NOW!!!!
USE io_global, ONLY : stdout
USE kinds, ONLY : DP
USE gvect
USE wvfct, ONLY : npwx, npw, nbnd
USE wavefunctions, ONLY : evc, psic
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE mp_world, ONLY : world_comm
USE wannier_gw, ONLY : num_nbndv,num_nbnds
USE lsda_mod, ONLy :nspin
implicit none
COMPLEX(kind=DP), INTENT(inout) :: state(npw)!state to be projected
INTEGER, INTENT(in) :: ispin!spin channel
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wavefunctions
LOGICAL, INTENT(in) :: l_all! if true project over the entire KS manifold
INTEGER :: iv,ig
REAL(kind=DP), ALLOCATABLE :: prod(:)
INTEGER :: num_proj
if(num_nbndv(ispin)==0) return
if(l_all) then
num_proj=num_nbndv(ispin)
else
num_proj=nbnd
endif
allocate(prod(num_proj))
call dgemm('T','N', num_proj,1,2*npw,2.d0,ks_wfcs(1,1,ispin),2*npwx,state,2*npw,&
& 0.d0,prod,num_proj)
do iv=1,num_proj
if(gstart==2) prod(iv)=prod(iv)-dble(conjg(ks_wfcs(1,iv,ispin))*state(1))
enddo
call mp_sum(prod, world_comm)
call dgemm('N','N',2*npw,1,num_proj,-1.d0,ks_wfcs(1,1,ispin),2*npwx,prod,&
&num_proj,1.d0,state,2*npw)
deallocate(prod)
return
end subroutine pc_operator2
subroutine hpsi_pw4gww_krylov( ndim,psi,ppsi,et,is,numv,ks_wfcs)
! ch_psi_all (n, h, ah, e, ik, m)
USE kinds, ONLY : DP
USE wvfct, ONLY : npwx, npw, nbnd
USE mp, ONLY : mp_sum, mp_barrier, mp_bcast
USE mp_world, ONLY : mpime, nproc
USE lsda_mod, ONLY : nspin
implicit none
INTEGER, INTENT(in) :: ndim !leading dimension of psi and psip
INTEGER, INTENT(in) :: numv!number of bands
INTEGER, INTENT(in) ::is!spin index
COMPLEX(kind=DP), INTENT(inout) :: psi(ndim,numv)
COMPLEX(kind=DP), INTENT(out) :: ppsi(ndim,numv)
REAL(kind=DP) :: et(numv)
COMPLEX(kind=DP), INTENT(in) :: ks_wfcs(npw,nbnd,nspin)!KS wavefunctions
COMPLEX(kind=DP), ALLOCATABLE :: psi_save(:,:)
INTEGER :: iv
!apply h_psi
do iv=1,numv
call pc_operator2(psi(1,iv),is,ks_wfcs,.false.)
enddo
call h_psi( ndim, npw, numv, psi, ppsi )
do iv=1,numv
ppsi(1:npw,iv)=ppsi(1:npw,iv)-et(iv)*psi(1:npw,iv)
enddo
do iv=1,numv
call pc_operator2(ppsi(1,iv),is,ks_wfcs,.false.)
enddo
return
end subroutine hpsi_pw4gww_krylov
END MODULE convergence_gw
SUBROUTINE read_wing ( rho, nspin, gamma_only,ipol,iw )
!
USE scf, ONLY : scf_type
USE noncollin_module, ONLY : noncolin, domag
USE gvect, ONLY : ig_l2g
USE io_files, ONLY : seqopn, prefix, tmp_dir, postfix
USE io_global, ONLY : ionode, ionode_id, stdout
USE mp_bands, ONLY : root_bgrp, intra_bgrp_comm
USE mp_images, ONLY : intra_image_comm
USE mp, ONLY : mp_bcast, mp_sum
USE kinds, ONLY : DP
USE io_files, ONLY : create_directory
USE io_base, ONLY : write_rhog, read_rhog
!
IMPLICIT NONE
TYPE(scf_type), INTENT(INOUT) :: rho
INTEGER, INTENT(IN) :: nspin
LOGICAL, INTENT(IN) :: gamma_only
INTEGER, INTENT(IN) :: ipol!direction
INTEGER, INTENT(IN) :: iw !frequency
!
CHARACTER(LEN=256) :: dirname
LOGICAL :: lexist
INTEGER :: nspin_, iunocc, iunpaw, ierr
INTEGER, EXTERNAL :: find_free_unit
CHARACTER(5) :: nfile
CHARACTER :: npol
write(nfile,'(5i1)') &
& iw/10000,mod(iw,10000)/1000,mod(iw,1000)/100,mod(iw,100)/10,mod(iw,10)
write(npol,'(1i1)') ipol
dirname = TRIM(tmp_dir)//'/_ph0/' // TRIM(prefix) // postfix
! in the following case do not read or write polarization
IF ( noncolin .AND. .NOT.domag ) THEN
nspin_=1
ELSE
nspin_=nspin
ENDIF
! read charge density
CALL read_rhog(TRIM(dirname) // "wing_" // npol // "_" //nfile , &
root_bgrp, intra_bgrp_comm, &
ig_l2g, nspin_, rho%of_g, gamma_only )
IF ( nspin > nspin_) rho%of_r(:,nspin_+1:nspin) = (0.0_dp, 0.0_dp)
!
RETURN
END SUBROUTINE read_wing