quantum-espresso/XSpectra/xspectra.f90

3680 lines
119 KiB
Fortran

!
! Copyright (C) 2001-2009 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 X_Spectra
USE kinds, ONLY : DP
USE constants, ONLY : rytoev,pi,fpi
USE io_global, ONLY : stdout,ionode,ionode_id ! Modules/io_global.f90
USE io_files, ONLY : prefix, tmp_dir
USE parser, ONLY : read_line
USE cell_base, ONLY : bg, at, celldm
USE parameters, ONLY : ntypx,lmaxx,lqmax
USE ions_base, ONLY : nat, ntyp => nsp, ityp, tau
USE ktetra, ONLY : nk1, nk2, nk3, k1, k2, k3, ltetra, ntetra, tetra
USE wvfct, ONLY : npwx,nbnd,npw,igk,et! et(nbnd,nkstot)
USE radial_grids, ONLY : ndmx
USE atom, ONLY : rgrid
USE becmod, ONLY : becp
USE uspp, ONLY : vkb, nkb, okvan
USE xspectra
USE ener, ONLY : ef, ef_up, ef_dw !Fermi energy
USE symm_base, ONLY : nsym,s
USE paw_gipaw, ONLY : read_recon, &
paw_vkb, & ! |p> projectors
paw_becp, & ! product of projectors and wf.
paw_nkb, & ! total number of beta functions, with st.fact.
paw_lmaxkb, &
paw_recon
USE klist, ONLY : &
nkstot, & ! total number of k-points
nks, & ! number of k-points for local pool
nelec,nelup,neldw, & !number of electrons
xk, & ! k-points coordinates
wk , & ! k-points weight
npk, &
degauss,lgauss,ngauss, &
two_fermi_energies
USE lsda_mod, ONLY : nspin,lsda,isk,current_spin
USE noncollin_module, ONLY : noncolin
USE mp, ONLY : mp_bcast, mp_sum !parallelization
USE mp_global, ONLY : intra_pool_comm, nproc, npool, mp_startup
USE control_flags, ONLY : gamma_only
USE environment, ONLY : environment_start
USE cut_valence_green, ONLY :&
cut_ierror, & ! convergence tolerance for one step in the integral
cut_stepu , & ! integration initial step, upper side
cut_stepl , & ! integration initial step, lower side
cut_startt, & ! integration start value of the t variable
cut_tinf , & ! maximum value of the lower integration boundary
cut_tsup , & ! minimum value of the upper integration boudary
cut_desmooth,& ! size of the interval near the fermi energy in which cross section is smoothed
cut_nmemu,& ! size of the memory of the values of the green function, upper side
cut_nmeml,& ! size of the memory of the values of the green function, lower side
cut_occ_states ! true if you want tou remove occupied states from the spectrum
USE control_flags, ONLY : twfcollect
!<CG>
USE gamma_variable_mod, ONLY : gamma_lines, gamma_tab, gamma_points, gamma_mode, gamma_file
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm, init_xspectra_paw_nhm
!</CG>
IMPLICIT NONE
!
! ... local variables
!
LOGICAL terminator, show_status, wf_collect
INTEGER :: nargs,iiarg,ierr,ios,il,ibnd,ibnd_up,ibnd_dw,xm_r,nc_r,ncomp_max
INTEGER :: iargc
INTEGER nt,nb,na,i,j,k,nrest,nline
INTEGER, ALLOCATABLE :: ncalcv(:,:)
INTEGER, ALLOCATABLE ::&
paw_iltonhb(:,:,:) ! corresp l, projector, type <--> cumulative over all the species
REAL (DP) ehomo, elumo,norm, core_energy
REAL(KIND=DP) :: core_wfn(ndmx)
REAL(dp), ALLOCATABLE:: a(:,:,:),b(:,:,:),xnorm(:,:) !lanczos vectors
REAL (DP), EXTERNAL :: efermig,efermit
REAL(DP) :: rc(ntypx,0:lmaxx),r_paw(0:lmaxx)
LOGICAL :: vloc_set
CHARACTER (LEN=256) :: input_file, filerecon(ntypx),filecore
CHARACTER(LEN=256) :: outdir
CHARACTER(LEN=25) :: calculation
CHARACTER(LEN=4) :: verbosity
CHARACTER(LEN=10) :: dummy_char
REAL(dp) :: gamma_energy(2), gamma_value(2)
REAL(dp) :: auxrpol(3,2)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Namelists Definition
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
namelist / input_xspectra / &
calculation,& ! calulation type : xanes...
verbosity, & ! high/low
prefix, & ! prefix of the pwscf output files
outdir, & ! directory tmp_dir or where the files are
xiabs,&
xkvec,&
xepsilon,&
xcoordcrys,&
ef_r,&
xonly_plot,&
xread_wf,&
x_save_file,&
xniter,&
xerror,&
xcheck_conv, &
show_status, &
nelup,neldw, &
wf_collect,&
U_projection_type,&
time_limit,&
restart_mode
namelist / plot / &
xnepoint,&
xgamma,&
xemax,&
xemin,&
cut_occ_states,&
terminator,&
gamma_mode,&
gamma_file,&
gamma_energy,&
gamma_value
namelist / pseudos /&
filerecon,&
filecore,&
r_paw
namelist / cut_occ /&
cut_ierror, cut_stepu, cut_stepl, cut_startt, cut_tinf, cut_tsup,&
cut_desmooth, cut_nmemu, cut_nmeml
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! initialising MPI environment, clocks, a few other things
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#ifdef __PARA
CALL mp_startup ( )
#endif
CALL environment_start ( 'XSPECTRA' )
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Default values for namelists
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! Set default values for namelist:
!
calculation='xanes'
prefix=''
verbosity='low'
x_save_file='xanes.sav'
CALL get_env( 'ESPRESSO_TMPDIR', outdir )
IF ( TRIM( outdir ) == ' ' ) outdir = './'
xnepoint=100
xniter=50
xcheck_conv=5
xonly_plot=.FALSE.
xread_wf=.FALSE.
xemin=0.d0
xemax=10.d0
xgamma=0.1d0
xerror=1.d-2
xiabs=1 !identify the adsorbing atom
DO i=2,3
xkvec(i)=0.d0
xepsilon(i)=0.d0
ENDDO
xkvec(1)=1.d0
xepsilon(1)=1.d0
xcoordcrys=.true.
ef_r=0.d0
cut_occ_states=.FALSE.
terminator=.false.
show_status=.false.
wf_collect=.false.
gamma_mode='constant'
gamma_file='gamma.dat'
U_projection_type='atomic'
! default values for cutting the occupied states (paste_fermi function)
cut_ierror=1.d-7
cut_stepu=1.d-2
cut_stepl=1.d-3
cut_startt=1.d0
cut_tinf=1.d-6
cut_tsup=100.d0
cut_desmooth=1.d-2
cut_nmemu=100000
cut_nmeml=100000
! Set default values for other variables
filecore='Core.wfc'
restart_mode='from_scratch'
time_limit=1.d8
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Check if the input is from file or from stdin
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! ... Input from file ?
!
IF ( ionode ) THEN
nargs = iargc()
! nargs = command_argument_count() ! if iargc does not work
!
DO iiarg = 1, ( nargs - 1 )
!
CALL getarg( iiarg, input_file )
IF ( TRIM( input_file ) == '-input' .OR. &
TRIM( input_file ) == '-inp' .OR. &
TRIM( input_file ) == '-in' ) THEN
!
CALL getarg( ( iiarg + 1 ) , input_file )
OPEN ( UNIT = 5, FILE = input_file, FORM = 'FORMATTED', &
STATUS = 'OLD', IOSTAT = ierr )
CALL errore( 'iosys', 'input file ' // TRIM( input_file ) // &
& ' not found' , ierr )
!
END IF
!
END DO
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Reading namelists
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
READ(5, input_xspectra, err = 200, iostat = ios)
200 CALL errore ('input_xspectra', 'reading input_xspectra namelist', abs (ios) )
READ(5, plot, err = 300, iostat = ios)
300 CALL errore ('plot', 'reading plot namelist', abs (ios) )
READ(5, pseudos, err = 400, iostat = ios)
400 CALL errore ('pseudos', 'reading pseudos namelist', abs (ios) )
READ(5, cut_occ, err = 500, iostat = ios)
500 CALL errore ('cut_occ', 'reading cut_occ namelist', abs (ios) )
tmp_dir = TRIM(outdir)
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Variables broadcasting
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
CALL mp_bcast( calculation, ionode_id)
CALL mp_bcast( tmp_dir, ionode_id )
CALL mp_bcast( prefix, ionode_id )
CALL mp_bcast( outdir, ionode_id )
CALL mp_bcast( xnepoint, ionode_id )
CALL mp_bcast( xniter, ionode_id )
CALL mp_bcast( xcheck_conv, ionode_id )
CALL mp_bcast( xang_mom, ionode_id )
CALL mp_bcast( xgamma, ionode_id )
CALL mp_bcast( xerror, ionode_id )
CALL mp_bcast( xemin, ionode_id )
CALL mp_bcast( xemax, ionode_id )
CALL mp_bcast( show_status, ionode_id)
CALL mp_bcast( xkvec, ionode_id )
CALL mp_bcast( xepsilon, ionode_id )
CALL mp_bcast( xonly_plot, ionode_id )
CALL mp_bcast( filerecon, ionode_id )
CALL mp_bcast( filecore, ionode_id )
CALL mp_bcast( xiabs, ionode_id )
CALL mp_bcast( r_paw, ionode_id )
CALL mp_bcast( xread_wf, ionode_id )
CALL mp_bcast( x_save_file, ionode_id )
CALL mp_bcast( xcoordcrys, ionode_id )
CALL mp_bcast( ef_r, ionode_id )
CALL mp_bcast( cut_occ_states, ionode_id )
CALL mp_bcast( terminator, ionode_id )
CALL mp_bcast( wf_collect, ionode_id )
CALL mp_bcast( twfcollect, ionode_id )
CALL mp_bcast( U_projection_type, ionode_id )
CALL mp_bcast( gamma_mode, ionode_id )
CALL mp_bcast( gamma_energy, ionode_id )
CALL mp_bcast( gamma_value, ionode_id )
CALL mp_bcast( cut_ierror, ionode_id )
CALL mp_bcast( cut_stepu, ionode_id )
CALL mp_bcast( cut_stepl, ionode_id )
CALL mp_bcast( cut_startt, ionode_id )
CALL mp_bcast( cut_tinf, ionode_id )
CALL mp_bcast( cut_tsup, ionode_id )
CALL mp_bcast( cut_desmooth, ionode_id )
CALL mp_bcast( cut_nmemu, ionode_id )
CALL mp_bcast( cut_nmeml, ionode_id )
! restart
CALL mp_bcast( time_limit, ionode_id )
CALL mp_bcast( restart_mode, ionode_id )
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Writing the status of the code (working features and things to do)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(show_status) CALL WRITE_status_of_the_code
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Initialising clocks
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
IF(TRIM(ADJUSTL(calculation)).EQ.'xanes_dipole') THEN
n_lanczos=1
xang_mom=1 !so it is not necessary to specify xang_mom
calculation='xanes'
ELSEIF(TRIM(ADJUSTL(calculation)).EQ.'xanes_quadrupole') THEN
n_lanczos=1
xang_mom=2 !so it is not necessary to specify xang_mom
calculation='xanes'
ENDIF
CALL start_clock( calculation )
!CALL stop_clock( code )
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! check on wfcollect
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(xread_wf.AND.wf_collect) THEN
CALL errore ('main','incompatibility xread_wf and wf_collect',1)
ENDIF
twfcollect=wf_collect
! $$$$$$$$$ notstart if on xonlyplot $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(.NOT.xonly_plot) THEN
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! read pwscf structural and k-points infos, also ditributes across the pools
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
CALL read_file_xspectra(xread_wf)
IF(xread_wf) THEN
WRITE(stdout,*) ' '
IF (okvan) THEN
WRITE(stdout,*) 'Approx. ram memory needed per proc in MB = ',(16.0*4.0*npwx*npool)/(nproc*1000000.0)
ELSE
WRITE(stdout,*) 'Approx. ram memory needed per proc in MB = ', (16.0*3.0*npwx*npool)/(nproc*1000000.0)
ENDIF
WRITE(stdout,*)
ENDIF
WRITE(stdout,*) 'k-points : nkstot=', nkstot
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! WRITE out crystal structure, kpoints list etc.
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
WRITE(stdout,*) '-------------- Crystal Structure ------------ '
WRITE(stdout,*) 'celldm(1:6)'
WRITE(stdout,'(3f14.8)') (celldm(i),i=1,3)
WRITE(stdout,'(3f14.8)') (celldm(i),i=4,6)
WRITE(stdout,*) 'direct lattice vectors'
DO i=1,3
WRITE(stdout,'(3f14.8)') (at(i,j),j=1,3)
ENDDO
WRITE(stdout,*) 'reciprocal lattice vectors'
DO i=1,3
WRITE(stdout,'(3f14.8)') (bg(i,j),j=1,3)
ENDDO
WRITE(stdout,*) 'nks=',nks,' nkstot=',nkstot
WRITE(stdout,*) ' ----k-point list [units 2*pi/celldm(1)], weight---------'
DO i=1,nkstot
WRITE(stdout,'(1i6,4f14.8)') i,(xk(j,i) , j=1,3),wk(i)
ENDDO
WRITE(stdout,*) '-------------------------------------------------'
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! normalize xkvec and xepsilon
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(xcoordcrys) CALL cryst_to_cart(1,xepsilon,at,1)
IF(xang_mom.EQ.2) THEN
IF(xcoordcrys) CALL cryst_to_cart(1,xkvec,at,1)
norm=DSQRT(xkvec(1)**2+xkvec(2)**2+xkvec(3)**2)
DO i=1,3
xkvec(i)=xkvec(i)/norm
ENDDO
ENDIF
norm=DSQRT(xepsilon(1)**2+xepsilon(2)**2+xepsilon(3)**2)
DO i=1,3
xepsilon(i)=xepsilon(i)/norm
ENDDO
! check orthogonality
WRITE (stdout,*) '--- Polarisation and k vector [cartesian coordinates]----'
WRITE (stdout,'(a,1x,3(f10.8, 1x))') 'xepsilon(:)=', (xepsilon(i),i=1,3)
WRITE (stdout,'(a,1x,3(f10.8, 1x))') 'xkvec(:)=', (xkvec(i),i=1,3)
IF(xang_mom.EQ.2) THEN
IF ((abs(xkvec(1)*xepsilon(1)+xkvec(2)*xepsilon(2)+xkvec(3)*xepsilon(3))).ge.1.0d-6) THEN
WRITE(stdout,*) 'WARNING, xkvec and xepsilon are not orthogonal'
WRITE(stdout,*) 'scalar product=',xkvec(1)*xepsilon(1)+xkvec(2)*xepsilon(2)+xkvec(3)*xepsilon(3)
ENDIF
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! is the type associated to xiabs existing ?
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
i=0
DO na=1,nat
IF(ityp(na).EQ.xiabs) i=i+1
ENDDO
IF(i.NE.1) THEN
CALL errore( 'main program', 'Wrong xiabs!!!',i)
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Reads reconstruction files
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
CALL read_core_abs(filecore,core_wfn)
IF ( .NOT. paw_recon(xiabs)%gipaw_data_in_upf_file ) &
CALL read_recon ( filerecon(xiabs), xiabs, paw_recon(xiabs) ) !*apsi
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Reads potentials and so on from post processing
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(.NOT.twfcollect) CALL openfil_pp
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Assign paw radii to species (this will become soon obsolete)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! read recon should be parallelized
!
DO nt=1,ntyp
IF ((.NOT.paw_recon(nt)%gipaw_data_in_upf_file).AND.( paw_recon(nt)%paw_nbeta.NE.0))&
CALL errore( 'xspectra, paw_recon', 'paw_nbeta not null',1)
DO j=1,paw_recon(nt)%paw_nbeta
il=paw_recon(nt)%psphi(j)%label%l
IF(xiabs.EQ.nt.AND.DABS(r_paw(il)).lt.1.d-6) THEN
!*apsi if(r(kkbeta(nt),nt).GT.1.d-3) THEN
!*apsi rc(nt,il)= r(kkbeta(nt),nt)
!*apsi ELSE
!*apsi WRITE(stdout,*) 'Warning-no-kkbeta r_paw(',il,')=1.0'
!*apsi rc(nt,il)=1.0
!*apsi ENDIF
!<CG> to be verified
IF (paw_recon(nt)%psphi(j)%label%rc > 1.d-3) THEN
WRITE(stdout,*) 'warning, r_paw(', il,' ) set to ', &
paw_recon(nt)%psphi(j)%label%rc
rc(nt, il)= paw_recon(nt)%psphi(j)%label%rc*3.0/2.0
ELSE
WRITE(stdout,*) 'Warning, no rc'
WRITE(stdout,*) 'warning, r_paw(', il,' ) set to 1.5'
rc(nt, il)= 1.5d0
ENDIF
!</CG>
ELSEIF(xiabs.EQ.nt.AND.DABS(r_paw(il)).GT.1.d-6) THEN
rc(nt,il)=r_paw(il)
ELSEIF(nt.NE.xiabs) THEN
!*apsi IF(r(kkbeta(nt),nt).GT.1.d-3) THEN
!*apsi rc(nt,il)=r(kkbeta(nt),nt)
!*apsi ELSE
!*apsi rc(nt,il)=1.0
!*apsi ENDIF
!<CG> to be verified
IF(paw_recon(nt)%psphi(j)%label%rc.GT.1.d-3) THEN
rc(nt,il)=paw_recon(nt)%psphi(j)%label%rc*3.0/2.0
ELSE
rc(nt,il)=1.5
ENDIF
!<CG>
ENDIF
ENDDO
ENDDO
!<CG>
DO nt=1,ntyp
DO j = 1,paw_recon(nt)%paw_nbeta
paw_recon(nt)%psphi(j)%label%rc = rc(nt,paw_recon(nt)%psphi(j)%label%l)
paw_recon(nt)%aephi(j)%label%rc = rc(nt,paw_recon(nt)%aephi(j)%label%l)
ENDDO
ENDDO
!</CG>
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! write band energies if xread_wf=true
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(xread_wf.AND.TRIM(verbosity).EQ.'high') THEN
WRITE(stdout,*) '------- Band energies read from file -----------'
DO i=1,nkstot
WRITE(stdout,'("k=[",3f14.8,"] spin=",1i2)') &
xk(1,i),xk(2,i),xk(3,i),isk(i)
WRITE(stdout, '(8f9.4)') (et(j,i)*13.605,j=1,nbnd)
ENDDO
WRITE(stdout,*) '------------------------------------------------'
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Calculate the Fermi level if possible
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
WRITE(stdout,*)
WRITE(stdout,*) '=========================================================='
IF(TRIM(calculation).EQ.'fermi_level'.AND..NOT.xread_wf) THEN
WRITE(stdout,*) 'Impossible to calculate the Fermi level'
WRITE(stdout,*) ' without reading wavefunctions (xread_wf=.true.)'
CALL errore( 'main program', &
'xread_wf incompatible with calculation type', 1 )
ENDIF
IF(.NOT.xread_wf) THEN !Fermi level must be read from input
ef=ef_r
WRITE( stdout,*)
WRITE( stdout,'(">> Fermi level from input (Ryd)=",1f14.8)') ef
ENDIF
IF(TRIM(calculation).EQ.'fermi_level') THEN
IF(ltetra.OR.lgauss) THEN
WRITE( stdout,*)
WRITE( stdout,*) 'Metallic case'
WRITE( stdout,*)
CALL errore('input','Read fermi level from scf/nscf output',1)
ELSE
WRITE(stdout,*)
WRITE(stdout,*) 'Insulating case:'
WRITE(stdout,*)
! SPINLESS CASE
IF ( nspin.EQ.1) THEN
ibnd = NINT (nelec) / 2
ef = MAXVAL ( et( ibnd , 1:nkstot) )
WRITE( stdout, '(">> Fermi level (Ryd) = ",1f14.8)') ef
!SPIN POLARIZED CALCULATION
ELSEIF(nspin.EQ.2) THEN
ibnd = NINT( nelec )
IF(nelup.EQ.0.OR.nelup.EQ.0) THEN
WRITE(stdout,*) 'WARNING, nelup=0 or neldw=0'
ENDIF
WRITE(stdout,*) 'nel=',nelec,' nelup=',nelup, 'neldw=',neldw
ibnd_up = NINT( nelup )
ibnd_dw = NINT( neldw )
IF ( ibnd_up == 0 ) THEN
!
ef = MAXVAL( et(ibnd_dw,1:nkstot/2) )
ef_dw = ef
WRITE( stdout,&
'(">> Fermi level down (Ryd)= ",1f14.8)')&
ef_dw
!
ELSE IF ( ibnd_dw == 0 ) THEN
!
ef = MAXVAL( et(ibnd_up,1:nkstot/2) )
ef_up = ef
WRITE( stdout,&
'(">> Fermi level up (Ryd)= ",1f14.8)')&
ef_up
!
ELSE
!
WRITE(stdout,*) 'nkstot=',nkstot
ef = MAX( MAXVAL( et(ibnd_up,1:nkstot/2) ), &
MAXVAL( et(ibnd_dw,nkstot/2+1:nkstot) ) )
ef_up = MAXVAL( et(ibnd_up,1:nkstot/2) )
ef_dw = MAXVAL( et(ibnd_dw,nkstot/2+1:nkstot) )
WRITE( stdout,&
'(">> Fermi level up (Ryd)= ",1f14.8,&
&" Fermi level down (Ryd)= ",1f14.8)') &
ef_up,ef_dw
!
END IF
WRITE( stdout,'(">> Fermi level (Ryd)=",1f14.8)') ef
END IF
ENDIF
WRITE( stdout,*)
WRITE (stdout,*) &
'============================================================'
CALL stop_pp
ENDIF
! CALL mp_bcast( ef, ionode_id ) !Why should I need this ?
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Allocation of variables for paw projectors
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! CG : becp allocated in the xanes_dipole and xanes_quadrupole subroutines
! call allocate_bec_type ( nkb, nbnd, becp )
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Initialise Vanderbilt and Paw projectors
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!-----------
! CALL init_us_1 ! CG
!<CG>
CALL init_gipaw_1
!</CG>
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Definition of a particular indexation to avoid Mickael Profeta's crazy indexation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! <CG>
CALL init_xspectra_paw_nhm
!<\CG>
ALLOCATE (paw_iltonhb(0:paw_lmaxkb,xspectra_paw_nhm, ntyp))
CALL define_index_arrays(paw_iltonhb)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Allocate paw projectors
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
ALLOCATE (paw_vkb( npwx, paw_nkb))
ALLOCATE (paw_becp(paw_nkb, nbnd))
ELSEIF(xonly_plot) THEN !$$$$$$$$$$$$$$$$$$ xonly_plot if structure
! Fermi level read from file
ef=ef_r
WRITE( stdout,*)
WRITE( stdout,'(">> Fermi level read from file (Ryd)=",1f14.8)') ef
WRITE( stdout,*)
ENDIF !$$$$$$$$$$$$$$$$$$ xonly_plot if structure
!<CG>
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! $ Computing gamma tabulated values
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!<MCB> THIS MUST BE CHANGED
IF (TRIM(gamma_mode).EQ.'file') THEN
CALL read_gamma_file
ELSEIF (TRIM(gamma_mode).EQ.'variable') THEN
gamma_lines=2
ALLOCATE(gamma_points(2,2))
gamma_points(1,1)=gamma_energy(1)
gamma_points(2,1)=gamma_energy(2)
gamma_points(1,2)=gamma_value(1)
gamma_points(2,2)=gamma_value(2)
ENDIF
IF ((TRIM(gamma_mode).EQ.'file').OR.(TRIM(gamma_mode).EQ.'variable')) THEN
ALLOCATE( gamma_tab(xnepoint))
CALL initialize_gamma_tab
DEALLOCATE(gamma_points)
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!</CG>
xnitermax=xniter
IF(xonly_plot) THEN
CALL read_header_save_file(x_save_file)
nks = nkstot
WRITE(6,*) 'nks=',nks
IF(lsda) THEN
isk(1:nkstot/2)=1
isk(nkstot/2+1:nkstot)=2
wk(1:nkstot)=2.d0/nkstot
ELSEIF(.NOT.lsda) THEN
isk(1:nkstot)=1
wk(1:nkstot)=2.d0/nkstot
ENDIF
CALL divide_et_impera( xk, wk, isk, lsda, nkstot, nks )
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Verification of paw relations between pseudo partial waves and projector (radial parts)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(.NOT.xonly_plot.AND.TRIM(verbosity).EQ.'high') CALL check_paw_projectors(xiabs)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Allocate and initialise lanczosvectors
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
ALLOCATE(a(xnitermax,n_lanczos,nks))
ALLOCATE(b(xnitermax,n_lanczos,nks))
ALLOCATE(xnorm(n_lanczos,nks))
ALLOCATE(ncalcv(n_lanczos,nks))
a(:,:,:)=0.d0
b(:,:,:)=0.d0
xnorm(:,:)=0.d0
ncalcv(:,:)=0
! for restart
ALLOCATE(calculated(n_lanczos,nks))
calculated(:,:)=0
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! And now we go... XANES CALCULATION
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! IF (okvan) THEN
! WRITE(stdout,*) 'Ultrasoft not implemented'
! CALL stop_pp
! ENDIF
IF(TRIM(calculation).EQ.'xanes') THEN
IF(.NOT.xonly_plot) THEN
IF(TRIM(ADJUSTL(restart_mode)).eq.'restart') THEN
CALL read_header_save_file(x_save_file)
CALL read_save_file(a,b,xnorm,ncalcv,x_save_file,core_energy)
ENDIF
IF(xang_mom.EQ.1) THEN
save_file_version=1
save_file_kind='xanes_dipole'
CALL xanes_dipole(a,b,ncalcv,xnorm,core_wfn,paw_iltonhb,terminator,verbosity)
! open save file and write everything
CALL write_save_file(a,b,xnorm,ncalcv,x_save_file)
ELSEIF(xang_mom.EQ.2) THEN
save_file_version=1
save_file_kind='xanes_quadrupole'
CALL xanes_quadrupole(a,b,ncalcv,xnorm,core_wfn,paw_iltonhb,terminator,verbosity)
CALL write_save_file(a,b,xnorm,ncalcv,x_save_file)
ENDIF
ELSE
CALL read_save_file(a,b,xnorm,ncalcv,x_save_file,core_energy)
ENDIF
IF (TRIM(save_file_kind).eq.'unfinished') CALL stop_pp
IF(xang_mom.EQ.1) THEN
CALL plot_xanes_dipole(a,b,xnorm,ncalcv,terminator,core_energy)
ELSEIF(xang_mom.EQ.2) THEN
CALL plot_xanes_quadrupole(a,b,xnorm,ncalcv,terminator,core_energy)
ENDIF
ELSEIF(TRIM(calculation).EQ.'rxes') THEN
CALL errore( 'Main', 'rxes Not yet implemented',1)
ELSEIF(TRIM(calculation).EQ.'bethe_salpeter') THEN
CALL errore( 'Main', 'bethe_salpeter Not yet implemented',1)
ELSEIF(TRIM(calculation).EQ.'hpsi') THEN
CALL verify_hpsi
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Deallocation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! IF(.NOT.xonly_plot) THEN
! call deallocate_bec_type ( becp )
! ENDIF
DEALLOCATE(a)
DEALLOCATE(b)
DEALLOCATE(xnorm)
DEALLOCATE(ncalcv)
WRITE (stdout,*) 'End program ', TRIM(calculation)
CALL stop_clock( calculation )
CALL print_clock( calculation )
CALL stop_pp
END program X_Spectra
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Dipolar Calculation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
SUBROUTINE xanes_dipole(a,b,ncalcv,xnorm,core_wfn,paw_iltonhb,terminator,verbosity)
USE constants, ONLY : fpi
USE io_files, ONLY : nd_nmbr, prefix, tmp_dir, &
nwordwfc, iunwfc
USE io_global, ONLY : stdout ! Modules/io_global.f90
USE kinds, ONLY : DP
USE parameters, ONLY : ntypx
USE radial_grids, ONLY : ndmx
USE ions_base, ONLY : nat, ntyp => nsp, ityp
USE wvfct, ONLY : npwx, nbndx, nbnd, npw, igk, g2kin, et,&
current_k
USE lsda_mod, ONLY : nspin,lsda,isk,current_spin
USE cell_base, ONLY: tpiba2, bg
USE wavefunctions_module, ONLY: evc
USE klist, ONLY : &
nkstot, & ! total number of k-points
nks, & ! number of k-points per pool
xk, & ! k-points coordinates
wk ! k-points weight
USE gvect, ONLY: g,ngm,ecutwfc,ngl,nrxx
!,ig_l2g(ngm),ngm_l,ngm_g
USE paw_gipaw, ONLY : &
paw_vkb, & ! |p> projectors
paw_becp, & ! product of projectors and wf.
paw_nkb, & ! total number of beta functions, with st.fact.
paw_lmaxkb,paw_recon
USE becmod, ONLY : becp, allocate_bec_type, deallocate_bec_type !CG
USE scf, ONLY : vltot, vrs, v, kedtau
USE gsmooth, ONLY : doublegrid, nrxxs ! CG
USE mp_global, ONLY : intra_pool_comm, root_pool, world_comm
USE mp, ONLY : mp_sum, mp_bcast, mp_barrier !CG
USE io_global, ONLY : ionode
USE xspectra, ONLY : xiabs, xanes_dip, xang_mom, xniter,&
xnitermax, xepsilon,time_limit,calculated,&
save_file_kind
USE atom, ONLY : rgrid, msh
! use atom, ONLY : &
! mesh, &!mesh(ntypx) number of mesh points
! msh , &!msh(ntypx)the point at rcut=end of radial integration
! r
USE radin_mod
USE uspp, ONLY : vkb, nkb, okvan !CG
USE ldaU, ONLY : lda_plus_u
!<CG>
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm
!</CG>
IMPLICIT NONE
REAL(dp) core_wfn(ndmx)
REAL(dp) a(xnitermax,1,nks),b(xnitermax,1,nks)
REAL (dp) xnorm(1,nks)
INTEGER :: is,ik,iabso,nr,ip,jp,l,j,icrd,ip_l,nrc,nt,na
INTEGER :: ipx,ipx_0,ipy,ipz,nline,nrest,npw_partial
INTEGER :: ncalcv(1,nks)
INTEGER :: paw_iltonhb(0:paw_lmaxkb,xspectra_paw_nhm, ntyp)
REAL (dp) pref,prefb,v_of_0,xnorm_partial
REAL (dp) norm
REAL (dp), ALLOCATABLE :: aux(:)
COMPLEX(KIND=DP), EXTERNAL :: zdotc
COMPLEX(dp), ALLOCATABLE :: paw_vkb_cplx(:,:)
LOGICAL :: terminator
REAL(dp) :: normps
CHARACTER(LEN=4) :: verbosity
EXTERNAL zdscal
LOGICAL :: recalc
COMPLEX(dp), ALLOCATABLE :: psiwfc(:), spsiwfc(:)
REAL(DP), EXTERNAL :: get_clock
REAL(dp) :: timenow=0
INTEGER :: nunfinished=0
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Constant Definitions
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
pref=SQRT(3.d0/2.d0)
prefb=SQRT(3.d0)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Variable allocation and initialization
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
ALLOCATE(aux(rgrid(xiabs)%mesh)) !allocation too big, it needs only up to msh
ALLOCATE (paw_vkb_cplx( npwx, paw_nkb))
ALLOCATE(xanes_dip(paw_recon(xiabs)%paw_nl(xang_mom)))
ALLOCATE(psiwfc(npwx))
xanes_dip(:)=0.d0
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Radial Dipole Matrix element
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! I compute the radial part,
! <\phi_n|r|\psi_i>=int r^3 \phi_n \psi_i dr.
! Here only ps and ae wavefunctions from XX.recon
!
WRITE( stdout,*) 'Calculation dipole matrix element'
WRITE( stdout,*) 'There are ',paw_recon(xiabs)%paw_nl(xang_mom),' projectors/channel'
WRITE( stdout,*) 'for angular moment ',xang_mom,' and atom type ',xiabs
! I check that the core wf is correctly normalized
nr=msh(xiabs) ! extended up to all the NON ZERO points in the mesh.
IF(TRIM(verbosity).EQ.'high') THEN
aux(1:nr)=core_wfn(1:nr)*core_wfn(1:nr)
WRITE (stdout,'(" norm of core wfc =",1f14.8)') SQRT(para_radin(aux(1:nr),rgrid(xiabs)%r(1:nr),nr))
ENDIF
! and I calculate the radial integral
ip_l=0
DO ip=1,paw_recon(xiabs)%paw_nbeta
! IF(psphi(xiabs,ip)%label%l.EQ.xang_mom) THEN
IF(paw_recon(xiabs)%aephi(ip)%label%l.EQ.xang_mom) THEN
nrc=paw_recon(xiabs)%aephi(ip)%label%nrc
ip_l=ip_l+1
! here below, recall that psi is r*psi and you have a Jacobian=r^2
aux(1:nrc)=rgrid(xiabs)%r(1:nrc)*paw_recon(xiabs)%aephi(ip)%psi(1:nrc)*core_wfn(1:nrc)
! here we have to integrate only inside the augmentation region.
xanes_dip(ip_l)=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
ENDIF
ENDDO
WRITE(6,*) '----------------------------------------------------------------'
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom) !
WRITE( stdout,'("dipole radial matrix element proj. (",i2,")=",f14.8)') ip,xanes_dip(ip)
ENDDO
WRITE(6,*) '----------------------------------------------------------------'
DEALLOCATE(aux)
!
! We count the projectors for all the atoms
!
ipx_0=0
IF(xiabs.NE.1) THEN
DO nt=1, xiabs-1
DO na=1, nat
IF (ityp(na).EQ.nt) THEN
ipx_0=ipx_0+paw_recon(nt)%paw_nh
ENDIF
ENDDO
ENDDO
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Beginning the loop over the k-points
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!*apsi call set_vrs(vrs,vltot,vr,nrxx,nspin,doublegrid)
!<CG>
CALL set_vrs(vrs,vltot,v%of_r,kedtau, v%kin_r,nrxx,nspin,doublegrid)
!</CG>
! CALL newd ! CG
IF (lda_plus_u) CALL init_xanes_ldau
DO ik=1,nks
IF (calculated(1,ik).EQ.1) CYCLE
timenow=get_clock( 'xanes' )
CALL mp_bcast(timenow,root_pool, intra_pool_comm)
IF( timenow.GT.time_limit) THEN
nunfinished=1
EXIT
ENDIF
WRITE(stdout,*)
WRITE(stdout,*) 'Starting k-point : ', ik
WRITE( stdout,'(" total cpu time spent up to now is ",F9.2," secs")') timenow
current_k=ik
IF(lsda) current_spin=isk(ik)
!gk_sort sort k-points and exit kinetic energies
CALL gk_sort(xk (1,ik),ngm,g,ecutwfc/tpiba2,npw,igk,g2kin) !CHECK
g2kin=g2kin*tpiba2 !CHECK
npw_partial = npw
CALL mp_sum( npw_partial, intra_pool_comm )
IF(xniter.ge.npw_partial) THEN
xniter = npw_partial
WRITE(stdout,*) 'Hilbert space is saturated'
WRITE(stdout,*) 'xniter is set equal to ',npw_partial
WRITE(stdout,*) 'Hint: Increase Kinetic Energy cutoff in your SCF simulation'
ENDIF
!<CG>
CALL init_gipaw_2(npw,igk,xk(1,ik),paw_vkb)
!</CG>
CALL init_us_2(npw,igk,xk(1,ik),vkb)
! initialise (not orthogonalized) atomic wfc if lda_plus_u=T
IF (lda_plus_u) CALL init_xanes_ldau_2(ik)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Angular Matrix element
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! Here I define human projectors
!
! paw_vkb(1:npw,ipx) are real spherical harmonics. The real spherical harmonics are
! defined as
!
! y_{l,2m} =[Y_{l,m}+(-1)^m Y_{l,-m}]/SQRT(2)
! y_{l,2m+1}=[Y_{l,m}-(-1)^m Y_{l,-m}]/(i*SQRT(2))
!
! (remember Y_{l,m}=(-1)^m Y_{l,-m)^* )
!
! The complex spherical harmonics can be written has a function of the real
! ones as :
!
! Y_{l,m} = [y_{l,2m}+iy_{l,2m+1}]/SQRT(2)
! Y_{l,-m} = (-1)^m [y_{l,2m}-iy_{l,2m+1}]/SQRT(2)
!
! The paw_vkb_cplx are the Y_{l,m} so the usual spherical harmonics
!
! rotational invariance has been checked
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom)
ipx=ipx_0+paw_iltonhb(xang_mom,ip,xiabs)
paw_vkb_cplx(1:npw,ipx)= paw_vkb(1:npw,ipx) !m=0
paw_vkb_cplx(1:npw,ipx+1)= &
(paw_vkb(1:npw,ipx+1)+(0.d0,1.d0)*paw_vkb(1:npw,ipx+2))/SQRT(2.0) !m=+1
paw_vkb_cplx(1:npw,ipx+2)=- &
(paw_vkb(1:npw,ipx+1)-(0.d0,1.d0)*paw_vkb(1:npw,ipx+2))/SQRT(2.0) !m=-1
ENDDO
psiwfc(1:npw)=(0.d0,0.d0)
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom)
ipx=ipx_0+paw_iltonhb(xang_mom,ip,xiabs)
! WARNING, storage of spherical harmonics is the following:
! given Y_{l,m}=P_{lm}exp(im\phi) one has
! counter
! l, m=0 -------> Y_{l,0} 1 z
! l, m=+1 -------> Y_{l,1}+Y_{l,-1} or cos(m\phi) 2
! l, m=-1 -------> Y_{l,1}-Y_{l,-1} or sin(m\phi) 3
! .....
! l, m=+l -------> Y_{l,1}+Y_{l,-1} or cos(m\phi) 2*l
! l, m=-l -------> Y_{l,1}-Y_{l,-1} or sin(m\phi) 2*l+1
psiwfc(1:npw)=psiwfc(1:npw)&
+( &
pref*paw_vkb_cplx(1:npw,ipx+2)*(xepsilon(1)+(0.d0,1.d0)*xepsilon(2))&
+ pref*paw_vkb_cplx(1:npw,ipx+1)*(-xepsilon(1)+(0.d0,1.d0)*xepsilon(2))&
+prefb*paw_vkb_cplx(1:npw,ipx)*xepsilon(3) &
)*xanes_dip(ip)/SQRT(fpi)
ENDDO
psiwfc(1:npw)=psiwfc(1:npw)*SQRT(fpi)/3.0
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Starting Lanczos
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! I normalize the wavefunction psiwfc(1:npw)
!
!<CG>
CALL allocate_bec_type(nkb,1,becp)
IF (okvan) THEN
ALLOCATE(spsiwfc(npwx))
spsiwfc(:)=(0.d0,0.d0)
recalc=.true.
CALL sm1_psi(recalc,npwx, npw, 1, psiwfc, spsiwfc)
xnorm_partial=zdotc(npw,psiwfc,1,spsiwfc,1)
DEALLOCATE(spsiwfc)
ELSE
xnorm_partial=zdotc(npw,psiwfc,1,psiwfc,1)
ENDIF
!</CG>
CALL mp_sum( xnorm_partial, intra_pool_comm )
xnorm(1,ik)=SQRT(xnorm_partial)
WRITE( stdout,*) 'norm initial vector=',xnorm(1,ik)
norm=1.d0/xnorm(1,ik)
CALL zdscal(npw,norm,psiwfc,1)
!
! Then I call the lanczos routine
!
WRITE(stdout,*) 'Starting lanczos'
IF (okvan) THEN
CALL lanczos_uspp(a(:,1,ik),b(:,1,ik),psiwfc,ncalcv(1,ik), terminator)
ELSE
CALL lanczos(a(:,1,ik),b(:,1,ik),psiwfc,ncalcv(1,ik), terminator)
ENDIF
!
! Then I write small report of the lanczos results
!
IF(TRIM(verbosity).EQ.'high') THEN
WRITE( stdout,*) '-----------------------------------------'
WRITE( stdout,*) 'k-point number =',ik
WRITE( stdout,*) 'k-point coordinate, isk'
WRITE( stdout,'(3f12.6,1i2)') xk(1,ik),xk(2,ik),xk(3,ik),isk(ik)
WRITE( stdout,*) 'Norm of the initial vector =',xnorm(1,ik)
WRITE( stdout,*) 'Number of iterations =',ncalcv(1,ik)
! nline=ncalcv(icrd,ik)/6
! nrest=ncalcv(icrd,ik)-nline*6
! WRITE( stdout,*) 'a vectors:'
! DO ip=1,nline
! WRITE( stdout,"(6(f10.6,3x))") (a((ip-1)*6+j,icrd,ik),j=1,6)
! ENDDO
! WRITE( stdout,"(6(f10.6,3x))") (a(nline*6+j,icrd,ik),j=1,nrest)
! WRITE( stdout,*) 'b vectors:'
! DO ip=1,nline
! WRITE( stdout,"(6(f10.6,3x))") (b((ip-1)*6+j,icrd,ik),j=1,6)
! ENDDO
! WRITE( stdout,"(6(f10.6,3x))") (b(nline*6+j,icrd,ik),j=1,nrest)
WRITE( stdout,*) '-----------------------------------------'
ENDIF
CALL deallocate_bec_type ( becp ) ! CG
calculated(1,ik)=1
ENDDO !on k points
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Array deallocation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
CALL mp_barrier(world_comm)
CALL mp_sum(nunfinished, world_comm)
IF (nunfinished >= 1) THEN
save_file_kind='unfinished'
write(stdout,*) 'calculation not finished'
ENDIF
DEALLOCATE(psiwfc)
DEALLOCATE(xanes_dip)
DEALLOCATE (paw_vkb_cplx)
END SUBROUTINE xanes_dipole
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Quadrupolar Calculation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
SUBROUTINE xanes_quadrupole(a,b,ncalcv,xnorm,core_wfn,paw_iltonhb,terminator,verbosity)
USE io_files, ONLY : nd_nmbr, prefix, tmp_dir, &
nwordwfc, iunwfc
USE io_global, ONLY : stdout ! Modules/io_global.f90
USE kinds, ONLY : DP
USE constants, ONLY : pi
USE parameters, ONLY : ntypx
USE radial_grids, ONLY : ndmx
USE ions_base, ONLY : nat, ntyp => nsp, ityp
USE wvfct, ONLY : npwx,nbndx,nbnd,npw,igk,&
g2kin,et, current_k
! ,igk_l2g
USE lsda_mod, ONLY : nspin,lsda,isk,current_spin
USE cell_base, ONLY: tpiba2, bg
USE wavefunctions_module, ONLY: evc
USE klist, ONLY : &
nkstot, & ! total number of k-points
nks, & ! number of k-points per pool
xk, & ! k-points coordinates
wk ! k-points weight
USE gvect, ONLY: g,ngm,ecutwfc,ngl,nrxx
!,ig_l2g(ngm),ngm_l,ngm_g
USE paw_gipaw, ONLY : &
paw_vkb, & ! |p> projectors
paw_becp, & ! product of projectors and wf.
paw_nkb, & ! total number of beta functions, with st.fact.
paw_lmaxkb, &
paw_recon
USE becmod, ONLY:becp, allocate_bec_type, deallocate_bec_type ! CG
USE scf, ONLY: vltot,v,vrs, kedtau !CG
USE gsmooth, ONLY : doublegrid
USE mp_global, ONLY : intra_pool_comm, root_pool, world_comm ! CG
USE mp, ONLY : mp_sum,mp_barrier, mp_bcast !CG
USE xspectra, ONLY: xiabs,xanes_qua,xang_mom,xniter,xnitermax,xkvec,xepsilon,&
save_file_kind, calculated, time_limit
USE atom, ONLY : rgrid, msh
! use atom, ONLY : &
! mesh, &!mesh(ntypx) number of mesh points
! msh , &!msh(ntypx)the point at rcut=end of radial integration
! r
USE radin_mod
USE uspp, ONLY : vkb, nkb, okvan !CG
USE ldaU, ONLY : lda_plus_u
!<CG>
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm
!</CG>
IMPLICIT NONE
REAL(dp) core_wfn(ndmx)
REAL(dp) a(xnitermax,1,nks),b(xnitermax,1,nks)
REAL (dp) xnorm(1,nks)
INTEGER is,ik,iabso,nr,ip,jp,l,j, ip_l,nrc,nt,na,ipx_0
INTEGER ipx,ipy,ipz,nline,nrest,npw_partial,icrd
INTEGER ncalcv(1,nks)
INTEGER paw_iltonhb(0:paw_lmaxkb,xspectra_paw_nhm, ntyp) !CG
REAL (dp) pref,prefb,v_of_0,xnorm_partial
REAL (dp) norm,prefm2,prefm1,prefm0
REAL (dp), ALLOCATABLE :: aux(:)
COMPLEX(KIND=dp), ALLOCATABLE :: psi(:)
COMPLEX(KIND=DP), EXTERNAL :: zdotc
COMPLEX(dp), ALLOCATABLE :: paw_vkb_cplx(:,:)
LOGICAL terminator
REAL(dp) :: normps
EXTERNAL zdscal
COMPLEX(dp), ALLOCATABLE :: psiwfc(:), spsiwfc(:)
LOGICAL :: recalc
CHARACTER(LEN=4) :: verbosity
REAL(DP), EXTERNAL :: get_clock
REAL(DP) :: timenow=0
INTEGER :: nunfinished=0
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Constant Definitions
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
prefm2=SQRT(3.0/40.0)/3.0
prefm1=prefm2
prefm0=2.0*SQRT(1.0/40.0)/3.0
pref=SQRT(2.d0)
prefb=1.0/pref
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Variable allocation and initialization
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
ALLOCATE(aux(rgrid(xiabs)%mesh))!overdimensionated, necessary only up to msh
ALLOCATE(psi(npwx))
ALLOCATE (paw_vkb_cplx( npwx, paw_nkb))
ALLOCATE(xanes_qua(paw_recon(xiabs)%paw_nl(xang_mom)))
ALLOCATE(psiwfc(npwx))
xanes_qua(:)=0.d0
psi(:)=(0.d0)
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Radial Quadrupole Matrix element
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!
! First of all I build the quadrupole matrix element (radial part).
! Namely I compute the radial part,
! <\phi_n|r|\psi_i>=int r^3 \phi_n \psi_i dr.
! Here only ps and ae wavefunctions from XX.recon
!
WRITE( stdout,*) 'Calculation Quadrupole matrix element'
WRITE( stdout,*) 'There are ',paw_recon(xiabs)%paw_nl(xang_mom),' projectors/channel'
WRITE( stdout,*) 'xang_mom=',xang_mom,' xiabs=',xiabs
! I check that the fondamental orthogonality condition of paw is satisfied:
! nr=mesh(xiabs) ! extended up to all the points in the mesh.
nr=msh(xiabs) ! extended up to all the NON ZERO points in the mesh.
! I check that the core wf is correctly normalized
IF(TRIM(verbosity).EQ.'high') THEN
aux(1:nr)=core_wfn(1:nr)*core_wfn(1:nr)
WRITE (stdout,'("norm of core wfc =",1f14.8)') SQRT(para_radin(aux(1:nr),rgrid(xiabs)%r(1:nr),nr))
ENDIF
! and I calculate the radial integral
ip_l=0
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.EQ.xang_mom) THEN
nrc=paw_recon(xiabs)%aephi(ip)%label%nrc
ip_l=ip_l+1
! here below, recall that psi is r*psi and you have a Jacobian=r^2
! aux(1:nr)=r(1:nr,xiabs)*r(1:nr,xiabs)* &
! psphi(xiabs,ip)%psi(1:nr)*core_wfn(1:nr)
aux(1:nrc)=rgrid(xiabs)%r(1:nrc)*rgrid(xiabs)%r(1:nrc)*&
paw_recon(xiabs)%aephi(ip)%psi(1:nrc)*core_wfn(1:nrc)
! here we have to integrate only inside the augmentation region.
xanes_qua(ip_l)=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
ENDIF
ENDDO
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom) !
WRITE( stdout,*) 'XANES quadrupole matrix element proj',ip,': ',xanes_qua(ip)
ENDDO
DEALLOCATE(aux)
DEALLOCATE(psi)
!
! We count the projectors for all the atoms
!
ipx_0=0
IF(xiabs.NE.1) THEN
DO nt=1, xiabs-1
DO na=1, nat
IF (ityp(na).EQ.nt) THEN
ipx_0=ipx_0+paw_recon(nt)%paw_nh
ENDIF
ENDDO
ENDDO
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Beginning the loop over the k-points
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
!*apsi call set_vrs(vrs,vltot,vr,nrxx,nspin,doublegrid)
! CALL set_vrs(vrs,vltot,v%of_r,nrxx,nspin,doublegrid)
! CALL newd
!<CG>
! set_vrs (vrs, vltot, vr, kedtau, kedtaur,nrxx, nspin, doublegrid)
CALL set_vrs(vrs,vltot,v%of_r,kedtau, v%kin_r,nrxx,nspin,doublegrid)
!</CG>
IF (lda_plus_u) CALL init_xanes_ldau
DO ik=1,nks
IF (calculated(1,ik).EQ.1) CYCLE
timenow=get_clock( 'xanes' )
CALL mp_bcast(timenow,root_pool, intra_pool_comm)
IF( timenow.GT.time_limit) THEN
nunfinished=1
EXIT
ENDIF
WRITE(stdout,*)
WRITE(stdout,*) 'Starting k-point : ', ik
WRITE( stdout,'(" total cpu time spent up to now is ",F9.2," secs")') timenow
current_k=ik
IF(lsda) current_spin=isk(ik)
!gk_sort sort k-points and exit kinetic energies
CALL gk_sort(xk (1,ik),ngm,g,ecutwfc/tpiba2,npw,igk,g2kin) !CHECK
g2kin=g2kin*tpiba2 !CHECK
npw_partial = npw
CALL mp_sum( npw_partial, intra_pool_comm )
IF(xniter.ge.npw_partial) THEN
xniter = npw_partial
WRITE(stdout,*) 'Hilbert space is saturated'
WRITE(stdout,*) 'xniter is set equal to ',npw_partial
WRITE(stdout,*) 'Hint: Increase Kinetic Energy cutoff in your SCF simulation'
! CALL stop_pp
ENDIF
!<CG>
CALL init_gipaw_2(npw,igk,xk(1,ik),paw_vkb)
!</CG>
CALL init_us_2(npw,igk,xk(1,ik),vkb)
! initialise orthogonalized atomic wfc if lda_plus_u=T
IF (lda_plus_u) CALL init_xanes_ldau_2(ik)
!
! Here I define human projectors
!
! paw_vkb(1:npw,ipx) are real spherical harmonics. The real spherical harmonics are
! defined as
!
! y_{l,2m} =[(-)^{m} Y_{l,m}+Y_{l,-m}]/SQRT(2)
! y_{l,2m+1}=[(-)^{m} Y_{l,m}-Y_{l,-m}]/(i*SQRT(2))
!
! The complex spherical harmonics can be written has a function of the real
! ones as :
!
! Y_{l,m} = [y_{l,2m}+iy_{l,2m+1}]/SQRT(2)
! Y_{l,-m} = (-)^m [y_{l,2m}-iy_{l,2m+1}]/SQRT(2)
!
! The paw_vkb_cplx are the Y_{l,m}, so the usual spherical harmonics
!
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom)
ipx=ipx_0+paw_iltonhb(xang_mom,ip,xiabs)
paw_vkb_cplx(1:npw,ipx)= paw_vkb(1:npw,ipx) !m=0
paw_vkb_cplx(1:npw,ipx+1)= &
(paw_vkb(1:npw,ipx+1)+(0.d0,1.d0)*paw_vkb(1:npw,ipx+2))/SQRT(2.0) !m=+1
paw_vkb_cplx(1:npw,ipx+2)= &
-(paw_vkb(1:npw,ipx+1)-(0.d0,1.d0)*paw_vkb(1:npw,ipx+2))/SQRT(2.0) !m=-1
paw_vkb_cplx(1:npw,ipx+3)= &
(paw_vkb(1:npw,ipx+3)+(0.d0,1.d0)*paw_vkb(1:npw,ipx+4))/SQRT(2.0) !m=+2
paw_vkb_cplx(1:npw,ipx+4)= &
(paw_vkb(1:npw,ipx+3)-(0.d0,1.d0)*paw_vkb(1:npw,ipx+4))/SQRT(2.0) !m=-2
ENDDO
! WARNING, storage of spherical harmonics is the following:
! given Y_{l,m}=P_{lm}exp(im\phi) one has
! counter
! l, m=0 -------> Y_{l,0} 1 z
! l, m=+1 -------> Y_{l,1}+Y_{l,-1} or cos(m\phi) 2
! l, m=-1 -------> Y_{l,1}-Y_{l,-1} or sin(m\phi) 3
! .....
! l, m=+l -------> Y_{l,1}+Y_{l,-1} or cos(m\phi) 2*l
! l, m=-l -------> Y_{l,1}-Y_{l,-1} or sin(m\phi) 2*l+1
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Angular Matrix element
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
psiwfc(:)=(0.d0,0.d0)
DO ip=1,paw_recon(xiabs)%paw_nl(xang_mom)
ipx=ipx_0+paw_iltonhb(xang_mom,ip,xiabs)
psiwfc(1:npw)=psiwfc(1:npw)+prefm2*&
(xepsilon(1)-(0.d0,1.d0)*xepsilon(2))*&
(xkvec(1)-(0.d0,1.d0)*xkvec(2))*&
xanes_qua(ip)*&
paw_vkb_cplx(1:npw,ipx+3)
psiwfc(1:npw)=psiwfc(1:npw)+prefm2*&
(xepsilon(1)+(0.d0,1.d0)*xepsilon(2))*&
(xkvec(1)+(0.d0,1.d0)*xkvec(2))*&
xanes_qua(ip)*&
paw_vkb_cplx(1:npw,ipx+4)
psiwfc(1:npw)=psiwfc(1:npw)-prefm1*( &
(xepsilon(1)-(0.d0,1.d0)*xepsilon(2))* &
xkvec(3)+ &
(xkvec(1)-(0.d0,1.d0)*xkvec(2))* &
xepsilon(3) )* &
xanes_qua(ip)*&
paw_vkb_cplx(1:npw,ipx+1)
psiwfc(1:npw)=psiwfc(1:npw)+prefm1*( &
(xepsilon(1)+(0.d0,1.d0)*xepsilon(2))* &
xkvec(3)+ &
(xkvec(1)+(0.d0,1.d0)*xkvec(2))* &
xepsilon(3) )* &
xanes_qua(ip)*&
paw_vkb_cplx(1:npw,ipx+2)
psiwfc(1:npw)=psiwfc(1:npw)+prefm0*( &
pref*xkvec(3)*xepsilon(3)-&
prefb*(xepsilon(1)*xkvec(1)+xepsilon(2)*xkvec(2)))*&
xanes_qua(ip)*&
paw_vkb_cplx(1:npw,ipx)
ENDDO
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Starting Lanczos
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
CALL allocate_bec_type(nkb,1, becp) ! CG
!<CG>
IF (okvan) THEN
ALLOCATE(spsiwfc(npwx))
spsiwfc(:)=(0.d0,0.d0)
recalc=.true.
CALL sm1_psi(recalc,npwx, npw, 1, psiwfc, spsiwfc)
xnorm_partial=zdotc(npw,psiwfc,1,spsiwfc,1)
DEALLOCATE(spsiwfc)
ELSE
xnorm_partial=zdotc(npw,psiwfc,1,psiwfc,1)
ENDIF
!</CG>
!
! I normalize the wavefunction pwswfc(1:npw)
!
CALL mp_sum( xnorm_partial, intra_pool_comm )
xnorm(1,ik)=SQRT(xnorm_partial)
WRITE( stdout,*) 'norm initial vector=',xnorm(1,ik)
norm=1.d0/xnorm(1,ik)
CALL zdscal(npw,norm,psiwfc,1)
!
! Then I call the lanczos routine
!
IF (okvan) THEN
CALL lanczos_uspp(a(:,1,ik),b(:,1,ik),psiwfc,ncalcv(1,ik), terminator)
ELSE
CALL lanczos(a(:,1,ik),b(:,1,ik),psiwfc,ncalcv(1,ik), terminator)
ENDIF
!
! Then I write small report of the lanczos results
!
IF(TRIM(verbosity).EQ.'high') THEN
WRITE( stdout,*) '-----------------------------------------'
WRITE( stdout,*) 'k-point number =',ik
WRITE( stdout,*) 'Norm of the initial vector =',xnorm(1,ik)
WRITE( stdout,*) 'Number of iterations =',ncalcv(1,ik)
WRITE( stdout,*) 'k-point coordinate, isk'
WRITE( stdout,'(3f12.6,1i2)') xk(1,ik),xk(2,ik),xk(3,ik),isk(ik)
! nline=ncalcv(1,ik)/6
! nrest=ncalcv(1,ik)-nline*6
! WRITE( stdout,*) 'a vectors:'
! DO ip=1,nline
! WRITE( stdout,"(6(f10.6,3x))") (a((ip-1)*6+j,1,ik),j=1,6)
! ENDDO
! WRITE( stdout,"(6(f10.6,3x))") (a(nline*6+j,1,ik),j=1,nrest)
! WRITE( stdout,*) 'b vectors:'
! DO ip=1,nline
! WRITE( stdout,"(6(f10.6,3x))") (b((ip-1)*6+j,1,ik),j=1,6)
! ENDDO
! WRITE( stdout,"(6(f10.6,3x))") (b(nline*6+j,1,ik),j=1,nrest)
WRITE( stdout,*) '-----------------------------------------'
ENDIF
CALL deallocate_bec_type (becp) ! CG
calculated(1,ik)=1
ENDDO !en loop over k points
CALL mp_barrier(world_comm)
CALL mp_sum(nunfinished, world_comm)
IF (nunfinished >= 1) THEN
save_file_kind='unfinished'
write(stdout,*) 'calculation not finished'
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Array deallocation
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
DEALLOCATE(psiwfc)
DEALLOCATE (paw_vkb_cplx)
DEALLOCATE(xanes_qua)
END SUBROUTINE xanes_quadrupole
!<CG>
SUBROUTINE lanczos (a,b,psi,ncalcv, terminator)
USE kinds, ONLY : DP
USE constants, ONLY : rytoev
USE wvfct, ONLY: npwx,nbndx, nbnd,npw,igk,g2kin
!USE wavefunctions_module, ONLY : psic
USE becmod, ONLY:becp
USE gsmooth, ONLY : nls, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, nrxxs
USE uspp, ONLY : vkb, nkb
USE cell_base, ONLY:omega
USE xspectra, ONLY : xniter, xnepoint, xcheck_conv,xnitermax,xemin,xemax,xgamma,xerror
USE mp_global, ONLY : intra_pool_comm
USE mp, ONLY : mp_sum
USE io_global, ONLY : stdout
IMPLICIT NONE
! INPUT
INTEGER ncalcv
REAL(dp) :: a(xnitermax),b(xnitermax)
COMPLEX(KIND=DP) :: psi(npwx)
LOGICAL terminator
!INTERNAL
LOGICAL converge
LOGICAL iconv
INTEGER ibnd,j,i,m
REAL(KIND=dp) norm,error,xemin_ryd,xemax_ryd,xgamma_ryd
COMPLEX(KIND=dp):: ac,bc
REAL(KIND=dp), ALLOCATABLE :: comp(:)
COMPLEX(KIND=dp), ALLOCATABLE :: hpsi(:),u(:)
REAL (KIND=dp) :: ddot
COMPLEX(KIND=DP) :: zdotc
EXTERNAL zdotc,ddot
External h_psi
ALLOCATE(hpsi(npwx))
ALLOCATE(u(npwx))
ALLOCATE(comp(xnepoint))
hpsi(:)=(0.d0,0.d0)
u(:)=(0.d0,0.d0)
a(:)=0.d0
b(:)=0.d0
xemax_ryd=xemax/rytoev
xemin_ryd=xemin/rytoev
xgamma_ryd=xgamma/rytoev
iconv=.false.
! ------------------------ 1st iteration --------------------------
!
! -- computes H*Psi (|u0>=|Psi>)
CALL h_psi( npwx, npw,1, psi, hpsi )
! -- computes a_(1)=<Psi|HPsi>
a(1)=dble(zdotc(npw,psi,1,hpsi,1))
CALL mp_sum(a(1), intra_pool_comm)
ac=-a(1)*(1.d0,0.d0)
!
! -- computes t3=H*Psi-a_1*Psi
CALL zaxpy(npw,ac,psi,1,hpsi,1)
!
! -- computes the norm of t3
b(1) = zdotc(npw,hpsi,1,hpsi,1)
CALL mp_sum( b(1), intra_pool_comm )
b(1) = SQRT( b(1) )
!
! -- computes the vector |u1>
CALL zdscal(npw,1.d0/b(1),hpsi,1)
!
! -- saves |u1>
u(1:npw)=hpsi(1:npw)
hpsi(:)=(0.d0,0.d0)
!
! -------------------------- Next iterations -----------------------
!
comp(:)=0.d0
comp(1)=1.d0
DO i=2,xniter
!From here below we have:
! u=psi_j
! hpsi=empty
! psi=psi_j-1
CALL h_psi( npwx, npw, 1, u, hpsi )
!
! I compute hpsi=hpsi-b_{j-1}*psi_{j-1} (j is actually i-1)
bc=-b(i-1)*(1.d0,0.d0)
CALL zaxpy(npw,bc,psi,1,hpsi,1)
!
! computes a(i)=<t2|t3>=<t2|H|t2>
a(i)=REAL(zdotc(npw,hpsi,1,u,1),dp)
CALL mp_sum( a(i), intra_pool_comm )
!
! computes t3=t3-a(i)*t2
!
ac=-a(i)*(1.d0,0.d0)
CALL zaxpy(npw,ac,u,1,hpsi,1)
!
! computes b(i) the norm of t3
!
b(i)=REAL(zdotc(npw,hpsi,1,hpsi,1),dp)
CALL mp_sum( b(i), intra_pool_comm )
b(i) = SQRT( b(i) )
!
! saves initial vector in t1 (t1 = t2)
psi(1:npw)=u(1:npw)
!
! computes vector t3/norm(t3) and saves it in t2
CALL zdscal(npw,1.d0/b(i),hpsi,1)
u(1:npw)=hpsi(1:npw)
hpsi(1:npw)=(0.d0,0.d0)
!
! I should gather all the ncalcv,error at the end and write only
! then.
!
IF(mod(i,xcheck_conv).EQ.0) THEN
IF(converge(a,b,i,comp,error,xemin_ryd,xemax_ryd,xgamma_ryd,xnepoint,xerror,terminator)) THEN
WRITE( stdout,*) 'CONVERGED at iter ',i,' with error=',error
ncalcv=i
iconv=.true.
EXIT
ELSE
WRITE( stdout,*) 'Estimated error at iter ',i,' is ', error
ENDIF
ENDIF
ENDDO
IF(.NOT.iconv) THEN
WRITE( stdout,*) 'XANES not converged after', i-1, ' iterations'
WRITE( stdout,*) 'Estimated final error after ',i-1,'iterations is ', &
converge(a,b,i-1,comp,error,xemin_ryd,xemax_ryd,xgamma_ryd,xnepoint,xerror,terminator)
ncalcv=i-1
ENDIF
DEALLOCATE(hpsi)
DEALLOCATE(u)
DEALLOCATE(comp)
END SUBROUTINE lanczos
!<CG>
SUBROUTINE lanczos_uspp (a,b,psi,ncalcv, terminator)
USE kinds, ONLY : DP
USE wvfct, ONLY: npwx,nbndx, nbnd,npw,igk,g2kin
!USE wavefunctions_module, ONLY : psic
USE becmod, ONLY: becp, calbec
USE gsmooth, ONLY : nls, nr1s, nr2s, nr3s, nrx1s, nrx2s, nrx3s, nrxxs
USE uspp, ONLY : vkb, nkb
USE cell_base, ONLY:omega
USE xspectra, ONLY : xniter, xnepoint,xcheck_conv,xnitermax,xemin,xemax,xgamma,xerror
USE mp_global, ONLY : intra_pool_comm
USE mp, ONLY : mp_sum
USE io_global, ONLY : stdout
IMPLICIT NONE
! INPUT
INTEGER ncalcv
REAL(dp) :: a(xnitermax),b(xnitermax)
COMPLEX(KIND=DP) :: psi(npwx)
LOGICAL terminator
!INTERNAL
LOGICAL converge
LOGICAL iconv
INTEGER ibnd,j,i,m
REAL(KIND=dp) norm,error,xemin_ryd,xemax_ryd,ryd2eV,xgamma_ryd
parameter(ryd2ev = 13.6058d0)
COMPLEX(KIND=dp):: ac,bc
REAL(KIND=dp), ALLOCATABLE :: comp(:)
COMPLEX(KIND=dp), ALLOCATABLE :: u(:), v1(:), v2(:), v3(:)
REAL (KIND=dp) :: ddot
COMPLEX(KIND=DP) :: zdotc
EXTERNAL zdotc,ddot
External h_psi
LOGICAL recalc
COMPLEX(KIND=DP) :: vecteuraux1(npwx,1), vecteuraux2(npwx,1)
ALLOCATE(v1(npwx))
ALLOCATE(u(npwx))
ALLOCATE(comp(xnepoint))
ALLOCATE(v2(npwx))
ALLOCATE(v3(npwx))
v1(:)=(0.d0,0.d0)
v2(:)=(0.d0,0.d0)
u(:)=(0.d0,0.d0)
a(:)=0.d0
b(:)=0.d0
xemax_ryd=xemax/Ryd2eV
xemin_ryd=xemin/Ryd2eV
xgamma_ryd=xgamma/Ryd2eV
iconv=.false.
! ------------------------ 1st iteration --------------------------
!
recalc=.true.
CALL sm1_psi(recalc,npwx, npw, 1, psi, v1) ! -- computes v1= S^-1 psi
CALL h_psi( npwx, npw,1, v1, u ) ! -- computes u = H v1
! -- computes a_(1)=<v1|u>
a(1)=dble(zdotc(npw,v1,1,u,1))
CALL mp_sum(a(1), intra_pool_comm)
ac=-a(1)*(1.d0,0.d0)
!
! -- computes u= S^-1 (u-a_1*psi)
CALL zaxpy(npw,ac,psi,1,u,1) ! -- computes u=u-a_1*psi
recalc=.false.
CALL sm1_psi(recalc,npwx, npw, 1, u,v1 ) ! -- computes u=S^-1 u
!
! -- computes the norm
b(1) = zdotc(npw,u,1,v1,1) ! -- computes b_1 =sqrt(<u|v1>)
CALL mp_sum( b(1), intra_pool_comm )
b(1) = SQRT( b(1) )
!
! -- computes the vector |u1>
CALL zdscal(npw,1.d0/b(1),u,1) ! -- computes u=u/b1
CALL zdscal(npw,1.d0/b(1),v1,1) ! -- computes v1=v1/b1
!
!
! -------------------------- Next iterations -----------------------
!
comp(:)=0.d0
comp(1)=1.d0
DO i=2,xniter
CALL h_psi( npwx, npw,1, v1,v2) ! -- computes v2= H v1
a(i)=REAL(zdotc(npw,v1,1,v2,1),dp) ! -- computes a_i=<v1|v2>
CALL mp_sum( a(i), intra_pool_comm )
!
! I compute hpsi=hpsi-b_{j-1}*psi_{j-1} (j is actually i-1)
bc=-b(i-1)*(1.d0,0.d0)
CALL zaxpy(npw,bc,psi,1,v2,1) ! -- computes v2=v2-b_{i-1}*psi
ac=-a(i)*(1.d0,0.d0)
CALL zaxpy(npw,ac,u,1,v2,1) ! -- computes v2=v2-a_i*u
v1(:)=(0.d0,0.d0)
recalc=.false.
CALL sm1_psi(recalc,npwx, npw, 1,v2 ,v1 ) ! computes v1= S^-1 v2
b(i)=REAL(zdotc(npw,v2,1,v1,1),dp) ! -- computes b_i=sqrt(<v2|v1>)
CALL mp_sum( b(i), intra_pool_comm )
b(i) = SQRT( b(i) )
!
! saves initial vector in t1 (t1 = t2)
psi(1:npwx)=u(1:npwx) ! Psi -> u
!
CALL zdscal(npw,1.d0/b(i),v2,1) ! -- computes v2=v2/b_i
CALL zdscal(npw,1.d0/b(i),v1,1) ! -- computes v1=v1/b_i
u(1:npwx)=v2(1:npwx) ! v2 -> u
!
! I should gather all the ncalcv,error at the end and write only
! then.
!
IF(mod(i,xcheck_conv).EQ.0) THEN
IF(converge(a,b,i,comp,error,xemin_ryd,xemax_ryd,xgamma_ryd,xnepoint,xerror,terminator)) THEN
WRITE( stdout,*) 'CONVERGED at iter ',i,' with error=',error
ncalcv=i
iconv=.true.
EXIT
ELSE
WRITE( stdout,*) 'Estimated error at iter ',i,' is ', error
ENDIF
ENDIF
ENDDO
IF(.NOT.iconv) THEN
WRITE( stdout,*) 'XANES not converged after', i-1, ' iterations'
WRITE( stdout,*) 'Estimated final error after ',i-1,'iterations is ', &
converge(a,b,i-1,comp,error,xemin_ryd,xemax_ryd,xgamma_ryd,xnepoint,xerror,terminator)
ncalcv=i-1
ENDIF
DEALLOCATE(v1,v2,u)
DEALLOCATE(comp)
END SUBROUTINE lanczos_uspp
!</CG>
LOGICAL FUNCTION converge(a,b,m,comp,estimated_error,xemin,xemax,xgamma,xnepoint,xerror,use_term)
USE kinds, ONLY : dp
USE xspectra, ONLY : xnitermax
IMPLICIT NONE
!
! INPUT:
! -----
!
INTEGER :: xnepoint
REAL(dp) :: xemin,xemax,xgamma,xerror
!
! INPUT / OUTPUT:
! ----------------
!
REAL(dp) :: a(xnitermax),b(xnitermax)
INTEGER :: m ! number of calculated vectors
REAL(dp) :: comp(xnepoint)
REAL(dp) :: estimated_error
!
! ---------------------- local variables ------------------------------
!
REAL(dp) :: deltae,tmp,area,e,err
REAL(dp) :: continued_fraction
INTEGER :: n
LOGICAL :: use_term
!
deltae = (xemax-xemin) / xnepoint
err = 0.d0
area = 0.d0
n = 0
e = xemin
DO n = 1, xnepoint
e = e + deltae
tmp = continued_fraction(a,b,e,xgamma,m,use_term)
err = err + abs(comp(n)-tmp)
area = area + abs(tmp)
comp(n) = tmp
ENDDO
err = err / area
estimated_error = err
IF(err < xerror) THEN
converge = .true.
ELSE
converge = .false.
ENDIF
END FUNCTION converge
!
! ------------------------------------------------------------------------
!
FUNCTION continued_fraction(a,b,e,gamma,m, term)
USE kinds, ONLY : dp
USE xspectra, ONLY : xnitermax, xcheck_conv
USE io_global, ONLY : stdout
IMPLICIT NONE
! computes the continued fraction.
!
! INPUT:
! -----
!
REAL(dp) :: continued_fraction
INTEGER :: m
REAL(dp) :: a(xnitermax)
REAL(dp) :: b(xnitermax)
REAL(dp) :: gamma
REAL(dp) :: e
LOGICAL :: term
!
! ---------------------- local variables ------------------------------
!
INTEGER :: i, p,q
COMPLEX(dp) :: res ,lastterm ! intermediate variable
REAL(dp) :: aa, bb
q=xcheck_conv/2
IF (term) THEN
aa=0.0
bb=0.0
DO p=1, q
aa=aa+a(m-p)
bb=bb+b(m-p)
ENDDO
aa=aa/q
bb=bb/q
res=lastterm(aa-e,bb*bb,gamma)
ELSE
res = CMPLX(a(m)-e,gamma,kind=DP)
ENDIF
DO i = 1, m -1
res = CMPLX(a(m-i)-e, -gamma,kind=DP) -b(m-i)*b(m-i)/res
ENDDO
continued_fraction = AIMAG(1/res)
END FUNCTION continued_fraction
!
SUBROUTINE read_core_abs_paratec(filename,core_wfn,xiabs)
USE io_global, ONLY : stdout
USE kinds, ONLY : DP
USE ions_base, ONLY : ityp,nat
USE radial_grids, ONLY : ndmx
USE atom, ONLY : rgrid, msh
! USE atom, ONLY : mesh, msh, r !mesh(ntypx) number of mesh points
USE splinelib
IMPLICIT NONE
INTEGER, INTENT ( IN ) :: xiabs
LOGICAL :: core_found
INTEGER :: i,icounter, iostatus,na, jtyp, j
CHARACTER (LEN=80) :: filename
REAL(KIND=dp):: x(ndmx),d1
REAL(KIND=dp):: core_wfn_para(ndmx),core_wfn(*)
CHARACTER (LEN=90)::dummy_str
REAL(dp), ALLOCATABLE :: xdata(:), tab(:), tab_d2y(:)
core_found=.FALSE.
open(unit=33,file=filename,form='formatted',status='old')
rewind(33)
DO
READ(33,'(a)',iostat = iostatus) dummy_str
IF ( iostatus /= 0 ) EXIT
IF ( index ( dummy_str, "core wavefunctions" ) /= 0 ) THEN
core_found=.TRUE.
READ(33,'(a)') dummy_str
IF ( dummy_str(1:7) /= "#n=1l=0" ) THEN
CALL errore ( "read_core_abs_paratec", "missing 1s state", 0 )
ENDIF
icounter=0
DO
READ(33,'(a)') dummy_str
IF ( dummy_str(1:1) == "#" .OR. dummy_str(1:1) == "&" ) THEN
EXIT
ELSE
icounter=icounter+1
IF(icounter.GT.ndmx) &
CALL errore ( "read_core_abs_paratec", "ndmx too small", 0 )
READ(dummy_str,*) x(icounter),core_wfn_para(icounter)
ENDIF
ENDDO
ENDIF
ENDDO
IF(.NOT.core_found) &
CALL errore ( "read_core_abs_paratec", "no core state(s) found", 0 )
close(33)
jtyp=0
DO na=1,nat
IF(ityp(na).EQ.xiabs) jtyp=jtyp+1
ENDDO
! Interpolate to the grid of the pseudo potential
ALLOCATE( xdata(icounter), tab(icounter), tab_d2y(icounter) )
xdata = x ( 1:icounter )
tab = core_wfn_para ( 1:icounter )
! initialize spline interpolation; for 3.x, x >= 1
d1 = (tab(2) - tab(1)) / (xdata(2) - xdata(1))
CALL spline(xdata, tab, 0.d0, d1, tab_d2y)
! CALL spline(xdata, tab, tab_d2y)
DO j = 1, msh(jtyp)
core_wfn(j) = splint(xdata, tab, tab_d2y, rgrid(jtyp)%r(j))
ENDDO
DEALLOCATE( xdata, tab, tab_d2y )
END SUBROUTINE read_core_abs_paratec
SUBROUTINE read_core_abs(filename,core_wfn)
USE kinds, ONLY : DP
USE atom, ONLY : rgrid
!USE atom, ONLY : mesh !mesh(ntypx) number of mesh points
USE xspectra, ONLY : xiabs
IMPLICIT NONE
INTEGER :: i
CHARACTER (LEN=80) :: filename
REAL(KIND=dp):: x
REAL(KIND=dp):: core_wfn(*)
WRITE(6,*) 'xmesh=',rgrid(xiabs)%mesh
open(unit=33,file=filename,form='formatted',status='old')
rewind(33)
READ(33,*)
DO i=1, rgrid(xiabs)%mesh
! read(33,'(2f16.8)') x,core_wfn(i)
READ(33 ,*) x,core_wfn(i)
ENDDO
close(33)
END SUBROUTINE read_core_abs
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Continuum fraction and plotting dipolar part
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
SUBROUTINE plot_xanes_dipole(a,b,xnorm,ncalcv, terminator, core_energy)
USE kinds, ONLY : DP
USE constants, ONLY : rytoev, pi
USE xspectra, ONLY : xang_mom,xemax,xemin,xiabs,xnepoint,xgamma,xonly_plot
!*apsi USE uspp_param, ONLY : psd !psd(ntypx) label for the atoms
USE klist, ONLY : nelec, &
nkstot, & ! total number of k-points
nks, & ! number of k-points per pool
xk, & ! k-points coordinates
wk ! k-points weight
USE ener, ONLY : ef
USE io_global, ONLY : stdout,ionode
USE mp_global, ONLY : intra_pool_comm, inter_pool_comm !CG
USE xspectra, ONLY : xnitermax,xkvec,xepsilon
USE cut_valence_green, ONLY : cut_occ_states, cut_desmooth, memu, meml, cut_nmemu, cut_nmeml
USE lsda_mod, ONLY : nspin,isk
!<CG>
USE mp, ONLY : mp_sum
USE uspp_param, ONLY : upf
USE gamma_variable_mod , ONLY : gamma_tab, gamma_mode
!</CG>
IMPLICIT NONE
LOGICAL terminator
INTEGER iestart
INTEGER ncalcv(1,nks)
REAL(dp) a(xnitermax,1,nks),b(xnitermax,1,nks)
REAL (dp) xnorm(1,nks)
REAL(KIND=dp) alpha2,core_energy
INTEGER :: i,ik,n,icoord !loops
INTEGER :: lmax
REAL (dp) :: mygetK,e_1s,energy,de,mod_xgamma,xemax_ryd,xemin_ryd,xgamma_ryd
REAL (dp) :: tmp_var
REAL (dp) :: Intensity_coord(1,xnepoint,nspin)
! , Intensity_tot(xnepoint)
REAL(dp) :: continued_fraction, paste_fermi, desmooth,t1,t2,f1,f2,df1,df2,poly(4) !CG
LOGICAL :: first
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! constant and initialization
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(xonly_plot) THEN
e_1s=core_energy !the K-edge in eV.
ELSE
!<CG>
e_1s=mygetK(upf(xiabs)%psd) !mygetK gets the K-edge in eV.
!</CG>
ENDIF
e_1s=e_1s/rytoeV !This is in Rydberg
alpha2=4.d0*pi/137.04
desmooth=cut_desmooth/rytoev ! This is in rydberg
!
! small output
!
WRITE( stdout,"(/'CALCULATION XANES SPECTRA')")
WRITE( stdout,"('---------------------')")
WRITE( stdout,"(/' Final state angular momentum:',1x,i3)") xang_mom
IF (TRIM(gamma_mode).EQ.'constant') WRITE( stdout,"(' Broadening parameter (in eV):',1x,g20.12)") xgamma !check
WRITE( stdout,"(' Nb of energy points:',1x,i5)") xnepoint
WRITE( stdout,"(' Maximum energy (in eV):',1x,g20.12)") xemax !check
WRITE( stdout,"(' Minimum energy (in eV):',1x,g20.12)") xemin !check
WRITE( stdout,"(' Binding energy of the 1s level (in eV):',1x,g20.12)") -e_1s*rytoeV
IF( ionode ) THEN
open (unit=277,file='xanes.dat',form='formatted',status='unknown')
rewind(277)
WRITE(277,"('# final state angular momentum:',1x,i3)") xang_mom
IF (TRIM(gamma_mode).EQ.'constant') WRITE(277,"('# broadening parameter (in eV):',1x,g20.12)") xgamma !
WRITE(277,"('# absorbing atom type:',i4)") xiabs
IF(nspin.GT.1) THEN
WRITE(277,"('# Energy (eV) sigmatot sigmaup sigmadown ')")
ELSE
WRITE(277,"('# Energy (eV) sigma')")
ENDIF
ENDIF
!
! I convert in Rydberg most of the relevant quantities
!
xemax_ryd=xemax/rytoeV+ef
xemin_ryd=xemin/rytoeV+ef
xgamma_ryd=xgamma/rytoeV
WRITE(stdout,*) 'xemin(ryd)=',xemin_ryd
WRITE(stdout,*) 'xemax(ryd)=',xemax_ryd
IF (TRIM(gamma_mode).EQ.'constant') THEN
WRITE(stdout,*) 'gamma in rydberg=',xgamma_ryd
ELSE
WRITE(stdout,*) 'nonconstant gamma'
ENDIF
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Continuum fraction
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Intensity_coord(:,:,:)=0.d0
de = (xemax_ryd-xemin_ryd) / REAL(xnepoint-1)
IF (TRIM(gamma_mode).EQ.'constant') THEN
IF(cut_occ_states) THEN
ALLOCATE(memu(cut_nmemu,2))
ALLOCATE(meml(cut_nmeml,2))
iestart=(ef-xemin_ryd)/de
DO ik=1,nks
first=.true. ! to erase the memory of paste_fermi
!<CG>
t1=ef-desmooth
f1=paste_fermi(t1,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=paste_fermi(t1-de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=(f1-df1)/de
t2=ef+desmooth
f2=continued_fraction(a(1,1,ik),b(1,1,ik),t2,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=continued_fraction(a(1,1,ik),b(1,1,ik),t2+de,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2+de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=(df2-f2)/de
CALL determine_polycut(t1,t2,f1,f2,df1,df2,poly) ! calculates interpolation polynome
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
IF ((energy-ef<desmooth).AND.(energy-ef>-desmooth)) THEN ! interpolation
tmp_var=poly(1)+poly(2)*energy+poly(3)*energy**2+poly(4)*energy**3
tmp_var=tmp_var*xnorm(1,ik)*xnorm(1,ik)
!</CG>
ELSE
tmp_var=0.d0
IF (n>iestart) THEN
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1,terminator)* &
xnorm(1,ik)*xnorm(1,ik)
ENDIF
tmp_var = tmp_var + paste_fermi(energy,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first) &
*xnorm(1,ik)*xnorm(1,ik)
ENDIF
! Intensity_tot(n)=Intensity_tot(n)+tmp_var*wk(ik)
Intensity_coord(1,n,isk(ik)) = Intensity_coord(1,n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
DEALLOCATE(memu)
DEALLOCATE(meml)
ELSE
DO ik=1,nks
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1, terminator)* &
xnorm(1,ik)*xnorm(1,ik)
Intensity_coord(1,n,isk(ik)) = Intensity_coord(1,n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
ENDIF
ELSE ! nonconstant gamma
IF(cut_occ_states) THEN
ALLOCATE(memu(cut_nmemu,2))
ALLOCATE(meml(cut_nmeml,2))
iestart=(ef-xemin_ryd)/de
DO ik=1,nks
first=.true. ! to erase the memory of paste_fermi
xgamma_ryd=gamma_tab(iestart)
t1=ef-desmooth
f1=paste_fermi(t1,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=paste_fermi(t1-de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=(f1-df1)/de
t2=ef+desmooth
f2=continued_fraction(a(1,1,ik),b(1,1,ik),t2,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=continued_fraction(a(1,1,ik),b(1,1,ik),t2+de,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2+de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=(df2-f2)/de
CALL determine_polycut(t1,t2,f1,f2,df1,df2,poly)
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
xgamma_ryd=gamma_tab(n)
IF ((energy-ef<desmooth).AND.(energy-ef>-desmooth)) THEN ! interpolation
tmp_var=poly(1)+poly(2)*energy+poly(3)*energy**2+poly(4)*energy**3
tmp_var=tmp_var*xnorm(1,ik)*xnorm(1,ik)
ELSE
tmp_var=0.d0
IF (n>iestart) THEN
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1,terminator)* &
xnorm(1,ik)*xnorm(1,ik)
ENDIF
tmp_var = tmp_var + paste_fermi(energy,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first) &
*xnorm(1,ik)*xnorm(1,ik)
ENDIF
! Intensity_tot(n)=Intensity_tot(n)+tmp_var*wk(ik)
Intensity_coord(1,n,isk(ik)) = Intensity_coord(1,n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
DEALLOCATE(memu)
DEALLOCATE(meml)
ELSE
DO ik=1,nks
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
xgamma_ryd=gamma_tab(n)
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1, terminator)* &
xnorm(1,ik)*xnorm(1,ik)
Intensity_coord(1,n,isk(ik)) = Intensity_coord(1,n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
ENDIF
ENDIF ! gamma_mode
! CALL poolreduce( nspin*xnepoint, Intensity_coord )
!<CG> replaces poolreduce
#ifdef __PARA
CALL mp_sum ( Intensity_coord, inter_pool_comm )
#endif
!</CG>
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Plotting xanes spectrum
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(ionode) THEN
IF(nspin.EQ.1) THEN
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
Intensity_coord(:,n,:)=Intensity_coord(:,n,:)*(energy+e_1s)*alpha2 !
WRITE(277,'(2f14.8)') (energy-ef)*rytoeV, Intensity_coord(1,n,1)
ENDDO
ELSEIF(nspin.EQ.2) THEN
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
Intensity_coord(:,n,:)=Intensity_coord(:,n,:)*(energy+e_1s)*alpha2 !
WRITE(277,'(4f14.8)') (energy-ef)*rytoev, &
Intensity_coord(1,n,1)+Intensity_coord(1,n,2),&
Intensity_coord(1,n,1),Intensity_coord(1,n,2)
ENDDO
ENDIF
close(277)
ENDIF
END SUBROUTINE plot_xanes_dipole
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Continuum fraction and plotting quadrupolar part
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
SUBROUTINE plot_xanes_quadrupole(a,b,xnorm,ncalcv, terminator,core_energy)
USE kinds, ONLY : DP
USE constants, ONLY: pi, rytoev
USE xspectra, ONLY : xang_mom,xemax,xemin,xiabs,xnepoint,xgamma,xonly_plot
!*apsi USE uspp_param, ONLY : psd !psd(ntypx) label for the atoms
USE klist, ONLY : nelec, &
nkstot, & ! total number of k-points
nks, & ! number of k-points per pool
xk, & ! k-points coordinates
wk ! k-points weight
USE ener, ONLY : ef
USE io_global, ONLY : stdout,ionode
USE mp_global, ONLY : intra_pool_comm, inter_pool_comm
USE xspectra, ONLY : xnitermax,xepsilon
USE cut_valence_green , ONLY : cut_occ_states, cut_desmooth, cut_nmemu, cut_nmeml, memu, meml
USE lsda_mod, ONLY : nspin,isk
!<CG>
USE mp, ONLY : mp_sum
USE uspp_param, ONLY : upf
USE gamma_variable_mod, ONLY : gamma_tab, gamma_mode
!</CG>
IMPLICIT NONE
LOGICAL terminator
INTEGER iestart
INTEGER ncalcv(1,nks)
REAL(dp) a(xnitermax,1,nks),b(xnitermax,1,nks)
REAL (dp) xnorm(1,nks)
REAL(KIND=dp) alpha2,constantqua
INTEGER :: i,ik,n,icoord !loops
INTEGER :: lmax
REAL (dp) :: mygetK,e_1s,energy,de,mod_xgamma,xemax_ryd,xemin_ryd,xgamma_ryd
REAL (dp) :: tmp_var,core_energy
REAL (dp) :: Intensity_tot(xnepoint,nspin)
REAL(dp) :: continued_fraction, paste_fermi, desmooth,t1,t2,f1,f2,df1,df2,poly(4)
LOGICAL :: first
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! constant and initialization
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
constantqua=pi/(137.04*137.04*137.04)
IF(xonly_plot) THEN
e_1s=core_energy !the K-edge in eV.
ELSE
!<CG>
e_1s=mygetK(upf(xiabs)%psd) !mygetK gets the K-edge in eV.
!</CG>
ENDIF
e_1s=e_1s/rytoeV !This is in Rydberg
desmooth=cut_desmooth/rytoev ! This is in rydberg
alpha2=4.d0*pi/137.04
!
! small output
!
WRITE( stdout,"(/'CALCULATION XANES SPECTRA')")
WRITE( stdout,"('---------------------')")
WRITE( stdout,"(/' Final state angular momentum:',1x,i3)") xang_mom
IF (TRIM(gamma_mode).EQ.'constant') WRITE( stdout,"(' Broadening parameter (in eV):',1x,g20.12)") xgamma !check
WRITE( stdout,"(' Nb of energy points:',1x,i5)") xnepoint
WRITE( stdout,"(' Maximum energy (in eV):',1x,g20.12)") xemax !check
WRITE( stdout,"(' Minimum energy (in eV):',1x,g20.12)") xemin !check
WRITE( stdout,"(' Binding energy of the 1s level (in eV):',1x,g20.12)") -e_1s*rytoev
IF( ionode ) THEN
open (unit=277,file='xanes.dat',form='formatted',status='unknown')
rewind(277)
WRITE(277,"('# final state angular momentum:',1x,i3)") xang_mom
IF (TRIM(gamma_mode).EQ.'constant') WRITE(277,"('# broadening parameter (in eV):',1x,g20.12)") xgamma
WRITE(277,"('# absorbing atom type:',i4)") xiabs
IF(nspin.EQ.1) THEN
WRITE(277,"('# Energy (eV) sigmatot')")
ELSEIF(nspin.EQ.2) THEN
WRITE(277,"('# Energy (eV) sigmatot, sigmaup, sigmadown')")
ENDIF
ENDIF
!
! I convert in Rydberg most of the relevant quantities
!
xemax_ryd=xemax/rytoev+ef
xemin_ryd=xemin/rytoev+ef
xgamma_ryd=xgamma/rytoev
WRITE(stdout,*) 'xemin(ryd)=',xemin_ryd
WRITE(stdout,*) 'xemax(ryd)=',xemax_ryd
IF (TRIM(gamma_mode).EQ.'constant') THEN
WRITE(stdout,*) 'gamma in rydberg=',xgamma_ryd
ELSE
WRITE(stdout,*) 'gamma from file'
ENDIF
! WRITE(stdout,*) 'terminator=', terminator
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Continuum fraction
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Intensity_tot(:,:)=0.d0
de = (xemax_ryd-xemin_ryd) / REAL(xnepoint-1)
IF (TRIM(gamma_mode).EQ.'constant') THEN
IF(cut_occ_states) THEN
ALLOCATE(memu(cut_nmemu,2))
ALLOCATE(meml(cut_nmeml,2))
DO ik=1,nks
iestart=(ef-xemin_ryd)/de
first=.true.
!<CG>
t1=ef-desmooth
f1=paste_fermi(t1,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=paste_fermi(t1-de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=(f1-df1)/de
t2=ef+desmooth
f2=continued_fraction(a(1,1,ik),b(1,1,ik),t2,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=continued_fraction(a(1,1,ik),b(1,1,ik),t2+de,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2+de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=(df2-f2)/de
CALL determine_polycut(t1,t2,f1,f2,df1,df2,poly)
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
IF ((energy-ef<desmooth).AND.(energy-ef>-desmooth)) THEN !interpolation
tmp_var=poly(1)+poly(2)*energy+poly(3)*energy**2+poly(4)*energy**3
tmp_var=tmp_var*xnorm(1,ik)*xnorm(1,ik)
!</CG>
ELSE
tmp_var=0.d0
IF (n>iestart) THEN
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1,terminator)* &
xnorm(1,ik)*xnorm(1,ik)
ENDIF
tmp_var=tmp_var+paste_fermi(energy,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)&
*xnorm(1,ik)*xnorm(1,ik)
ENDIF
Intensity_tot(n,isk(ik))=Intensity_tot(n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
DEALLOCATE(memu)
DEALLOCATE(meml)
ELSE
! WRITE(stdout,*) 'in plor_
DO ik=1,nks
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1, terminator)* &
xnorm(1,ik)*xnorm(1,ik)
Intensity_tot(n,isk(ik))=Intensity_tot(n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
ENDIF
ELSE ! nonconstant gamma
IF(cut_occ_states) THEN
ALLOCATE(memu(cut_nmemu,2))
ALLOCATE(meml(cut_nmeml,2))
DO ik=1,nks
iestart=(ef-xemin_ryd)/de
first=.true.
!<CG>
xgamma_ryd=gamma_tab(iestart)
t1=ef-desmooth
f1=paste_fermi(t1,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=paste_fermi(t1-de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df1=(f1-df1)/de
t2=ef+desmooth
f2=continued_fraction(a(1,1,ik),b(1,1,ik),t2,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=continued_fraction(a(1,1,ik),b(1,1,ik),t2+de,xgamma_ryd,ncalcv(1,ik)-1,terminator)&
+paste_fermi(t2+de,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)
df2=(df2-f2)/de
CALL determine_polycut(t1,t2,f1,f2,df1,df2,poly)
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
xgamma_ryd=gamma_tab(n)
IF ((energy-ef<desmooth).AND.(energy-ef>-desmooth)) THEN !interpolation
tmp_var=poly(1)+poly(2)*energy+poly(3)*energy**2+poly(4)*energy**3
tmp_var=tmp_var*xnorm(1,ik)*xnorm(1,ik)
!</CG>
ELSE
tmp_var=0.d0
IF (n>iestart) THEN
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1,terminator)* &
xnorm(1,ik)*xnorm(1,ik)
ENDIF
tmp_var=tmp_var+paste_fermi(energy,ef,a(1,1,ik),b(1,1,ik),xgamma_ryd,ncalcv(1,ik)-1,terminator, first)&
*xnorm(1,ik)*xnorm(1,ik)
ENDIF
Intensity_tot(n,isk(ik))=Intensity_tot(n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
DEALLOCATE(memu)
DEALLOCATE(meml)
ELSE
! WRITE(stdout,*) 'in plor_
DO ik=1,nks
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
xgamma_ryd=gamma_tab(n)
tmp_var= &
continued_fraction(a(1,1,ik),b(1,1,ik),energy,xgamma_ryd,ncalcv(1,ik)-1, terminator)* &
xnorm(1,ik)*xnorm(1,ik)
Intensity_tot(n,isk(ik))=Intensity_tot(n,isk(ik))+tmp_var*wk(ik)
ENDDO
ENDDO
ENDIF
ENDIF ! gammma_mode
! CALL poolreduce( nspin*xnepoint, Intensity_tot )
!<CG> replaces poolreduce
#ifdef __PARA
CALL mp_sum ( Intensity_tot, inter_pool_comm )
#endif
!</CG>
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! Plotting xanes spectrum
! $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
IF(ionode) THEN
IF(nspin.EQ.1) THEN
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
Intensity_tot(n,:)=Intensity_tot(n,:)*(energy+e_1s)*(energy+e_1s)*(energy+e_1s)*constantqua !normalized
WRITE(277,'(2f14.8)') (energy-ef)*rytoev,Intensity_tot(n,:)
ENDDO
ELSEIF(nspin.EQ.2) THEN
DO n=1,xnepoint
energy=xemin_ryd+de*(n-1)
Intensity_tot(n,:)=Intensity_tot(n,:)*(energy+e_1s)*(energy+e_1s)*(energy+e_1s)*constantqua !normalized
WRITE(277,'(4f14.8)') (energy-ef)*rytoev,Intensity_tot(n,1)+Intensity_tot(n,2),&
Intensity_tot(n,1),Intensity_tot(n,2)
ENDDO
ENDIF
close(277)
ENDIF
END SUBROUTINE plot_xanes_quadrupole
SUBROUTINE define_index_arrays(paw_iltonhb)
USE paw_gipaw, ONLY : paw_lmaxkb, paw_recon
USE ions_base, ONLY : ntyp => nsp
USE parameters, ONLY : lmaxx
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm ! CG
! Arguments
INTEGER paw_iltonhb(0:paw_lmaxkb,xspectra_paw_nhm,ntyp) ! CG
! Local
INTEGER nt,ih,nb,l
INTEGER ip_per_l(0:lmaxx)
DO nt = 1, ntyp
ih = 1
ip_per_l(:)=0
DO nb = 1, paw_recon(nt)%paw_nbeta
l = paw_recon(nt)%aephi(nb)%label%l
ip_per_l(l)=ip_per_l(l)+1
paw_iltonhb(l,ip_per_l(l),nt)= ih
ih=ih+2*l+1
ENDDO
ENDDO
END SUBROUTINE define_index_arrays
FUNCTION lastterm(a,b,g)
USE kinds, ONLY : dp
IMPLICIT NONE
REAL(dp) :: a,b, g,y1,y2,z1,z2,r
COMPLEX(dp) :: lastterm
y1 =a*a-g*g-4*b
y2=-2*a*g
r=SQRT(y1*y1+y2*y2)/2
IF (g<0) THEN
z1=a/2+0.5*SIGN(SQRT(y1/2+r),y2)
z2=-g/2+SQRT(-y1/2+r)/2
ELSE
z1=a/2-0.5*SIGN(SQRT(y1/2+r),y2)
z2=-g/2-SQRT(-y1/2+r)/2
ENDIF
lastterm=CMPLX(z1,z2,kind=DP)
END FUNCTION lastterm
FUNCTION paste_fermi(e,ef,a,b,gamma,m,term, first)
USE kinds, ONLY : dp
USE xspectra, ONLY : xnitermax, xcheck_conv
USE cut_valence_green, ONLY :&
cut_ierror,cut_stepu, cut_stepl,&
cut_startt,cut_tinf, cut_tsup, cut_nmemu, cut_nmeml, memu, meml
IMPLICIT NONE
REAL(dp) :: paste_fermi
INTEGER :: m
REAL(dp) :: a(xnitermax)
REAL(dp) :: b(xnitermax)
REAL(dp) :: gamma
REAL(dp) :: e,ef
LOGICAL :: term
COMPLEX(dp) :: green,y,dy,c1,c2, e1, e2
REAL(dp) ::twopi, t,dt, t1, ta, tb
INTEGER, save :: n1
INTEGER, save :: n2
INTEGER :: nn1,nn2
LOGICAL :: first
IF (first) THEN
memu(:,:)=(0.d0,0.d0)
meml(:,:)=(0.d0,0.d0)
n1=0
n2=0
first=.false.
ENDIF
dy=cut_ierror+1.0
y=0.d0
twopi=6.28318530
nn1=1
nn2=1
t1=0.5773502692
t=cut_startt
DO WHILE ((abs(dy)>cut_ierror).OR.(t<cut_tsup))
dt=cut_stepu*t
ta=t+dt*(1-t1)/2
tb=t+dt*(1+t1)/2
e1=CMPLX(ef,ta,kind=DP)
e2=CMPLX(ef,tb,kind=DP)
IF (nn1>n1) THEN
c1=green(a,b,e1,m,term)
c2=green(a,b,e2,m,term)
IF (nn1<cut_nmemu) THEN
memu(nn1,1)=c1
memu(nn1,2)=c2
n1=nn1
ENDIF
ELSE
c1=memu(nn1,1)
c2=memu(nn1,2)
ENDIF
dy=(dt/2)*(c1/CMPLX(ef-e,ta-gamma,kind=DP)+CONJG(c1)/CMPLX(ef-e,-ta-gamma,kind=DP)&
+c2/CMPLX(ef-e,tb-gamma,kind=DP)+CONJG(c2)/CMPLX(ef-e,-tb-gamma,kind=DP))
y=y+dy
t=t+dt
nn1=nn1+1
ENDDO
t=cut_startt
dy=cut_ierror+1
DO WHILE((abs(dy)>cut_ierror).OR.(t>cut_tinf))
dt=cut_stepl*t
ta=t-dt*(1-t1)/2
tb=t-dt*(1+t1)/2
e1=CMPLX(ef,ta,kind=DP)
e2=CMPLX(ef,tb,kind=DP)
IF (nn2>n2) THEN
c1=green(a,b,e1,m,term)
c2=green(a,b,e2,m,term)
IF (nn2<cut_nmeml) THEN
meml(nn2,1)=c1
meml(nn2,2)=c2
n2=nn2
ENDIF
ELSE
c1=meml(nn2,1)
c2=meml(nn2,2)
ENDIF
dy=(dt/2)*(c1/CMPLX(ef-e,ta-gamma,kind=DP)+CONJG(c1)/CMPLX(ef-e,-ta-gamma,kind=DP)&
+c2/CMPLX(ef-e,tb-gamma,kind=DP)+CONJG(c2)/CMPLX(ef-e,-tb-gamma,kind=DP))
y=y+dy
t=t-dt
nn2=nn2+1
ENDDO
paste_fermi=AIMAG(y)/twopi
END FUNCTION paste_fermi
FUNCTION green(a,b,e,m, term)
USE kinds, ONLY : dp
USE xspectra, ONLY : xnitermax, xcheck_conv
IMPLICIT NONE
COMPLEX(dp) :: green
INTEGER :: m
REAL(dp) :: a(xnitermax)
REAL(dp) :: b(xnitermax)
COMPLEX(dp) :: e
LOGICAL :: term
INTEGER :: i, p,q
COMPLEX(dp) :: res ,lastterm
REAL(dp) :: aa, bb
q=xcheck_conv/2
IF (term) THEN
aa=0.0
bb=0.0
DO p=1, q
aa=aa+a(m-p)
bb=bb+b(m-p)
ENDDO
aa=aa/q
bb=bb/q
res=lastterm(aa-REAL(e),bb*bb,AIMAG(e))
ELSE
res = CMPLX(a(m)-REAL(e),AIMAG(e),kind=DP)
ENDIF
DO i = 1, m -1
res = a(m-i)-e -b(m-i)*b(m-i)/res
ENDDO
green = 1/res
END FUNCTION green
SUBROUTINE check_paw_projectors(xiabs)
USE kinds, ONLY : DP
USE constants, ONLY : pi
USE paw_gipaw, ONLY : &
paw_lmaxkb, &
paw_recon
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm
USE atom, ONLY : rgrid, msh
! USE atom, ONLY : &
! mesh, &!mesh(ntypx) number of mesh points
! msh , &!msh(ntypx)the point at rcut=end of radial integration
! r, rab
USE ions_base, ONLY : ntyp => nsp
USE io_global, ONLY : stdout
USE radin_mod
IMPLICIT NONE
INTEGER xiabs
! internal
INTEGER :: nr,nrc,ip,jp,lmax,l,ip_l,jtyp,n1,n2,nrs,ndm,ih,jh
REAL(dp) :: overlap,rexx,overlap2
REAL (dp), ALLOCATABLE :: aux(:),f(:,:)
REAL(dp) , ALLOCATABLE :: s(:,:),e(:),v(:,:)
ALLOCATE(aux(rgrid(xiabs)%mesh)) !allocation too big, it needs only up to msh
ALLOCATE(f(rgrid(xiabs)%mesh,2)) !allocation too big, it needs only up to msh
WRITE(stdout,*) '---- PAW projectors from reconstruction files -----'
WRITE(stdout,*)
WRITE(stdout,*) 'atom type, total number of projectors'
DO jtyp=1,ntyp
WRITE (stdout,'(2i4)') jtyp,paw_recon(jtyp)%paw_nbeta
ENDDO
WRITE(stdout,*)
!
! I calculate maximum l
!
lmax=0
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.GT.lmax) &
lmax = paw_recon(xiabs)%psphi(ip)%label%l
ENDDO
WRITE(stdout,*) 'atom type, l, number of projectors per ang. mom.'
DO jtyp=1,ntyp
DO l=0,lmax
WRITE(stdout,'(3i4)') jtyp,l,paw_recon(jtyp)%paw_nl(l)
ENDDO
ENDDO
! We calculate the overlaps between partial waves and projectors
! to see if they are equal to the croneker delta.
nr=msh(xiabs) ! extended up to all the NON ZERO points in the mesh.
WRITE(stdout,*) '---- Overlaps between partial waves and projectors (radial) -----'
WRITE(stdout,*)
WRITE(stdout,*) '<tilde{phi} l,n|tilde{p} l,nn>=delta_{n,nn}'
WRITE(stdout,*)
DO ip=1,paw_recon(xiabs)%paw_nbeta
DO jp=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.EQ.paw_recon(xiabs)%psphi(jp)%label%l) THEN
nrc=Count(rgrid(xiabs)%r(1:nr).le.paw_recon(xiabs)%psphi(ip)%label%rc)
IF(nrc.GT.nr) THEN
WRITE(stdout,*) 'nrc=',nrc,' > ',nr,' = nr'
CALL errore ( "nrc > nr", "xanes_dipole", 0 )
ENDIF
aux(1:nrc)=paw_recon(xiabs)%psphi(ip)%psi(1:nrc)*paw_recon(xiabs)%paw_betar(1:nrc,jp)
aux(nrc+1:nr)=0.d0
WRITE(stdout,'("<tilde{phi}_",2i2,10X,"|tilde{p}_",2i2,">=",1f14.8)') &
ip,paw_recon(xiabs)%psphi(ip)%label%l,jp, &
paw_recon(xiabs)%psphi(jp)%label%l, &
para_radin(aux(1:nr),rgrid(xiabs)%r(1:nr),nr)
ENDIF
ENDDO
ENDDO
WRITE(stdout,*)
!
!
!
WRITE(stdout,*) '---- Check normalization pseudo,ae wf and projectors -----------'
WRITE(stdout,*) '---- (radial part only, integral up to r_c) -----------'
WRITE(stdout,*)
WRITE(stdout,*) 'l, n, |proj|^2, |pswf|^2 , |aewf|^2'
WRITE(stdout,*)
DO l=0,lmax
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.EQ.l) THEN
nrc=Count(rgrid(xiabs)%r(1:nr).le.paw_recon(xiabs)%psphi(ip)%label%rc)
aux(1:nrc) = paw_recon(xiabs)%paw_betar(1:nrc,ip) &
* paw_recon(xiabs)%paw_betar(1:nrc,ip)
overlap=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
aux(1:nrc)=paw_recon(xiabs)%aephi(ip)%psi(1:nrc)*paw_recon(xiabs)%aephi(ip)%psi(1:nrc)
overlap2=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
aux(1:nrc)=paw_recon(xiabs)%psphi(ip)%psi(1:nrc)*paw_recon(xiabs)%psphi(ip)%psi(1:nrc)
rexx=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
WRITE(stdout,'(2i4,3f14.8)')l,ip,overlap,overlap2,rexx
ENDIF
ENDDO
ENDDO
WRITE(stdout,*)
goto 323
WRITE(stdout,*) '---- <phi|chi>= \sum_nl <phi |phi_l><p_l| chi>_nrc --------'
WRITE(stdout,*) 'WARNING : this test assumes a form of the phi/chi function'
! DO l=0,lmax
DO l=1,1
ip_l=0
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(ip_l.EQ.0.AND.paw_recon(xiabs)%psphi(ip)%label%l.EQ.l) ip_l=ip
ENDDO
f(:,:)=0.d0
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.EQ.l) THEN
f(1:nr,1)=f(1:nr,1)+paw_recon(xiabs)%psphi(ip)%psi(1:nr)/REAL(ip,dp)
f(1:nr,2)=f(1:nr,2)+1.123*paw_recon(xiabs)%psphi(ip)%psi(1:nr)/REAL(ip,dp)
ENDIF
ENDDO
rexx=0.d0
DO ip=1,paw_recon(xiabs)%paw_nbeta
IF(paw_recon(xiabs)%psphi(ip)%label%l.EQ.l) THEN
nrc=Count(rgrid(xiabs)%r(1:nr).le.paw_recon(xiabs)%psphi(ip)%label%rc)
IF(nrc.GT.nr) THEN
WRITE(stdout,*) 'nrc=',nrc,' > ',nr,' = nr'
CALL errore ( "nrc > nr", "xanes_dipole", 0 )
ENDIF
aux(1:nrc)=f(1:nrc,1)*paw_recon(xiabs)%paw_betar(1:nrc,ip)
overlap=para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
aux(1:nrc)=f(1:nrc,2)*paw_recon(xiabs)%psphi(ip)%psi(1:nrc)
overlap=overlap*para_radin(aux(1:nrc),rgrid(xiabs)%r(1:nrc),nrc)
WRITE(stdout,'("overlap(l=",1i2,",n=",1i2,")= ",1f14.8)')l,ip,overlap
rexx=rexx+overlap
ENDIF
ENDDO
aux(1:nr)=f(1:nr,1)*f(1:nr,2)
WRITE(stdout,'("sum/overlap=",1f14.8)') rexx/para_radin(aux,rgrid(xiabs)%r(1:nr),nrc)
WRITE(stdout,'("sum projectors=",1f14.8," overlap=",1f14.8)') rexx,para_radin(aux,rgrid(xiabs)%r(1:nr),nrc)
WRITE(stdout,*)'---+++++----'
ENDDO
! aux(1:nrc)=paw_recon(xiabs)%psphi(ip)%psi(1:nrc)*paw_recon(xiabs)%paw_betar(1:nrc,jp)
!
!
!
! ENDIF
! ENDDO
WRITE(stdout,*)
WRITE(stdout,*) '================================================================'
323 continue
!
! Check linear dependence of projectors
!
WRITE(stdout,*) '================================================================'
WRITE(stdout,*) ' Checking linear dipendence of projectors '
WRITE(stdout,*)
DEALLOCATE(aux)
ndm = MAXVAL (msh(1:ntyp))
ALLOCATE(aux(ndm))
DO l=0,paw_lmaxkb
IF (paw_recon(xiabs)%paw_nl(l)>0) THEN
ALLOCATE (s(paw_recon(xiabs)%paw_nl(l),paw_recon(xiabs)%paw_nl(l)))
ALLOCATE (e(paw_recon(xiabs)%paw_nl(l)),v(paw_recon(xiabs)%paw_nl(l),paw_recon(xiabs)%paw_nl(l)))
DO ih=1,paw_recon(xiabs)%paw_nl(l)
n1=paw_recon(xiabs)%paw_iltonh(l,ih)
nrc=paw_recon(xiabs)%psphi(n1)%label%nrc
nrs=paw_recon(xiabs)%psphi(n1)%label%nrs
DO jh=1,paw_recon(xiabs)%paw_nl(l)
n2=paw_recon(xiabs)%paw_iltonh(l,jh)
CALL step_f(aux,paw_recon(xiabs)%psphi(n1)%psi(1:msh(xiabs)) * &
paw_recon(xiabs)%psphi(n2)%psi(1:msh(xiabs)), &
rgrid(xiabs)%r(1:msh(xiabs)),nrs,nrc, 1.d0, msh(xiabs) )
CALL simpson ( msh(xiabs), aux, rgrid(xiabs)%rab(1), s(ih,jh))
ENDDO
ENDDO
WRITE(stdout,'("atom type=",1i4)') xiabs
WRITE(stdout,'("number of projectors projector =",1i4," angular momentum=",1i4)') &
paw_recon(xiabs)%paw_nl(l),l
DO ih=1,paw_recon(xiabs)%paw_nl(l)
WRITE(stdout,'(10f14.8)') (s(ih,jh),jh=1,paw_recon(xiabs)%paw_nl(l))
ENDDO
WRITE(stdout,*) 'Eigenvalues S matrix:'
WRITE(stdout,*)
IF(paw_recon(xiabs)%paw_nl(l).EQ.1) THEN
WRITE(stdout,'(1i4,1f14.8)') 1,s(1,1)
ELSE
CALL rdiagh(paw_recon(xiabs)%paw_nl(l),s,paw_recon(xiabs)%paw_nl(l) , e, v )
DO ih=1,paw_recon(xiabs)%paw_nl(l)
WRITE(stdout,'(1i4,1f14.8)') ih,e(ih)
ENDDO
ENDIF
WRITE(stdout,*)
DEALLOCATE(s,e,v)
ENDIF
ENDDO
WRITE(stdout,*) '================================================================'
DEALLOCATE(aux,f)
END SUBROUTINE check_paw_projectors
SUBROUTINE read_save_file(a,b,xnorm,ncalcv,x_save_file,core_energy)
USE kinds, ONLY : DP
USE klist, ONLY : nks,nkstot
USE xspectra, ONLY : xnitermax,xang_mom,xiabs,&
n_lanczos, save_file_version, save_file_kind, calculated
USE io_global, ONLY : stdout,ionode
USE lsda_mod, ONLY : nspin,lsda
IMPLICIT NONE
CHARACTER(LEN=256) :: x_save_file
INTEGER :: ierr,nkstot_r
INTEGER :: xm_r,nc_r,ncomp_max
INTEGER ncalcv(n_lanczos,nks)
REAL(dp) core_energy
REAL(dp) a(xnitermax,n_lanczos,nks),b(xnitermax,n_lanczos,nks)
REAL (dp) xnorm(n_lanczos,nks)
INTEGER, ALLOCATABLE :: ncalcv_all(:,:)
REAL(dp), ALLOCATABLE :: a_all(:,:),b_all(:,:),xnorm_all(:,:),aux(:,:)
REAL(dp) xkvec_r(3)
REAL(dp) :: xepsilon_r(3)
INTEGER i,j,k,ncalcv_max
INTEGER :: calculated_all(n_lanczos,nkstot)
ALLOCATE(a_all(xnitermax,nkstot))
ALLOCATE(b_all(xnitermax,nkstot))
ALLOCATE(xnorm_all(n_lanczos,nkstot))
ALLOCATE(ncalcv_all(n_lanczos,nkstot))
ALLOCATE(aux(xnitermax,nks))
a(:,:,:)=0.d0
b(:,:,:)=0.d0
xnorm(:,:)=0.d0
ncalcv(:,:)=0
calculated_all(:,:)=0
OPEN ( UNIT = 10, FILE = x_save_file, FORM = 'FORMATTED', &
STATUS = 'UNKNOWN', IOSTAT = ierr )
CALL errore( 'iosys', 'x_save_file ' // TRIM( x_save_file ) // &
& ' not found' , ierr )
REWIND(10)
IF (save_file_version.eq.0) then
WRITE(stdout,*) 'save file version : old'
ELSEIF(save_file_version.eq.1) then
WRITE(stdout,*) 'save file version : 1'
DO i=1,6
READ(10,*)
ENDDO
ENDIF
READ(10,*) lsda,nspin
READ(10,*) xm_r,nkstot_r,xnitermax
IF(xm_r.NE.xang_mom) THEN
WRITE(stdout,*) 'xm_r=',xm_r
CALL errore('read_save_file','xm_r is different from xang_mom=',xang_mom)
ENDIF
READ(10,*) ncalcv_max
IF(ncalcv_max.GT.xnitermax) THEN
WRITE(stdout,*) 'ncalcv_max=',ncalcv_max
CALL errore('read_save_file','ncalcv_max is grater than xnitermax=',xnitermax)
ENDIF
READ(10,*) core_energy
READ(10,*) (xkvec_r(i),i=1,3)
WRITE(stdout,*) '---------------------------------------------------------'
WRITE(stdout,*) 'xkvec read from savefile'
WRITE(stdout,*) (xkvec_r(i),i=1,3)
READ(10,*) (xepsilon_r(i),i=1,3)
WRITE(stdout,*) 'xepsilon read from file'
WRITE(stdout,*) (xepsilon_r(i),i=1,3)
WRITE(stdout,*) '---------------------------------------------------------'
write(stdout,*) 'n_lanczos=', n_lanczos
DO i=1, n_lanczos
IF (TRIM(save_file_kind).eq.'unfinished') THEN
READ(10,*) (calculated_all(i,j),j=1,nkstot)
ENDIF
READ(10,*) (xnorm_all(i,j),j=1,nkstot)
READ(10,*) (ncalcv_all(i,j),j=1,nkstot)
READ(10,*) ((a_all(j,k),j=1,ncalcv_max),k=1,nkstot)
READ(10,*) ((b_all(j,k),j=1,ncalcv_max),k=1,nkstot)
#ifdef __PARA
CALL poolscatter(xnitermax,nkstot,a_all,nks,aux)
a(1:xnitermax,i,1:nks)=aux(1:xnitermax,1:nks)
CALL poolscatter(xnitermax,nkstot,b_all,nks,aux)
b(1:xnitermax,i,1:nks)=aux(1:xnitermax,1:nks)
#else
a(1:xnitermax,i,1:nkstot)=a_all(1:ncalcv_max,1:nkstot)
b(1:xnitermax,i,1:nkstot)=b_all(1:ncalcv_max,1:nkstot)
#endif
ENDDO
close(10)
#ifdef __PARA
CALL poolscatter(n_lanczos,nkstot,xnorm_all,nks,xnorm)
CALL ipoolscatter(n_lanczos,nkstot,ncalcv_all,nks,ncalcv)
CALL ipoolscatter(n_lanczos,nkstot,calculated_all,nks,calculated)
#else
IF(nks.NE.nkstot) THEN
CALL errore('read_save_file','nks\=nkstot',1)
ENDIF
xnorm(1:n_lanczos,1:nkstot)=xnorm_all(1:n_lanczos,1:nkstot)
ncalcv(1:n_lanczos,1:nkstot)=ncalcv_all(1:n_lanczos,1:nkstot)
calculated(1:n_lanczos,1:nkstot)=calculated_all(1:n_lanczos,1:nkstot)
#endif
DEALLOCATE(a_all)
DEALLOCATE(b_all)
DEALLOCATE(xnorm_all)
DEALLOCATE(ncalcv_all)
DEALLOCATE(aux)
END SUBROUTINE read_save_file
SUBROUTINE read_header_save_file(x_save_file)
USE kinds, ONLY : DP
USE klist, ONLY : nkstot
USE lsda_mod, ONLY : nspin,lsda
USE xspectra, ONLY : save_file_version, save_file_kind, n_lanczos
USE io_global, ONLY : stdout
IMPLICIT NONE
CHARACTER(LEN=256) :: x_save_file
INTEGER :: ierr,nkstot_r
INTEGER :: xm_r
CHARACTER :: c
OPEN ( UNIT = 10, FILE = x_save_file, FORM = 'FORMATTED', &
STATUS = 'UNKNOWN', IOSTAT = ierr )
CALL errore( 'iosys', 'x_save_file ' // TRIM( x_save_file ) // &
& ' not found' , ierr )
REWIND(10)
READ(10, '(a1)') c
REWIND(10)
IF (c == '#') then
READ(10, '(20x,i8)') save_file_version
READ(10, '(20x,a32)') save_file_kind
READ(10,*)
READ(10,'(27x,i4)') n_lanczos
READ(10,*)
READ(10,*)
ELSE
save_file_version=0
save_file_kind='xanes_old'
n_lanczos=1
ENDIF
READ(10,*) lsda,nspin
READ(10,*) xm_r,nkstot_r
nkstot=nkstot_r
CLOSE(10)
RETURN
END SUBROUTINE read_header_save_file
SUBROUTINE write_save_file(a,b,xnorm,ncalcv,x_save_file)
USE kinds, ONLY : DP
USE klist, ONLY : nks,nkstot
USE xspectra, ONLY : xnitermax,xang_mom,xkvec,xepsilon,xiabs,&
save_file_version, save_file_kind, n_lanczos, calculated
USE io_global, ONLY : ionode
!*apsi USE uspp_param, ONLY : psd
USE lsda_mod, ONLY : nspin,lsda
USE uspp_param, ONLY : upf
IMPLICIT NONE
CHARACTER(LEN=256) :: x_save_file
INTEGER :: ierr
INTEGER ncalcv(n_lanczos,nks)
REAL(dp) a(xnitermax,n_lanczos,nks),b(xnitermax,n_lanczos,nks)
REAL (dp) xnorm(n_lanczos,nks)
INTEGER, ALLOCATABLE :: ncalcv_all(:,:)
REAL(dp), ALLOCATABLE :: a_all(:,:),b_all(:,:),xnorm_all(:,:)
REAL (dp) :: mygetK
INTEGER i,j,k,ncalcv_max
CHARACTER(LEN=8) :: dte
INTEGER :: calculated_all(n_lanczos,nkstot)
IF (ionode) CALL DATE_AND_TIME(date=dte)
ALLOCATE(a_all(xnitermax,nkstot))
ALLOCATE(b_all(xnitermax,nkstot))
ALLOCATE(xnorm_all(n_lanczos,nkstot))
ALLOCATE(ncalcv_all(n_lanczos,nkstot))
ncalcv_all(:,:)=0
xnorm_all(:,:)=0.d0
ncalcv_all(1:n_lanczos,1:nks)=ncalcv(1:n_lanczos,1:nks)
xnorm_all(1:n_lanczos,1:nks)=xnorm(1:n_lanczos,1:nks)
calculated_all(1:n_lanczos,1:nks)=calculated(1:n_lanczos,1:nks)
#ifdef __PARA
CALL poolrecover(xnorm_all,n_lanczos,nkstot,nks)
CALL ipoolrecover(ncalcv_all,n_lanczos,nkstot,nks)
CALL ipoolrecover(calculated_all,n_lanczos,nkstot,nks)
#endif
ncalcv_max=0
DO j=1, n_lanczos
DO i=1,nkstot
IF(ncalcv_all(j,i).GT.ncalcv_max) ncalcv_max=ncalcv_all(j,i)
ENDDO
ENDDO
IF ( ionode ) THEN
OPEN ( UNIT = 10, FILE = x_save_file, FORM = 'FORMATTED', &
STATUS = 'UNKNOWN', IOSTAT = ierr )
REWIND(10)
WRITE(10, '(a20,i8)') '# save_file_version=',save_file_version
WRITE(10, '(a20,a32)') '# save_file_kind =',save_file_kind
WRITE(10,'(a7,a8)') '# date=', dte
WRITE(10,'(a27,i4)') '# number of lanczos stored=',n_lanczos
WRITE(10,'(a1)') '#'
WRITE(10,'(a1)') '#'
WRITE(10,*) lsda,nspin
WRITE(10,*) xang_mom,nkstot,xnitermax
WRITE(10,*) ncalcv_max
WRITE(10,*) mygetK(upf(xiabs)%psd)
WRITE(10,*) (xkvec(i),i=1,3)
WRITE(10,*) (xepsilon(i),i=1,3)
ENDIF
DO i=1, n_lanczos
a_all(:,:)=0.d0
b_all(:,:)=0.d0
a_all(1:xnitermax,1:nks)= a(1:xnitermax,i,1:nks)
b_all(1:xnitermax,1:nks)= b(1:xnitermax,i,1:nks)
#ifdef __PARA
CALL poolrecover(a_all,xnitermax,nkstot,nks)
CALL poolrecover(b_all,xnitermax,nkstot,nks)
#endif
IF ( ionode) THEN
IF (TRIM(save_file_kind).EQ.'unfinished') THEN
WRITE(10,*) (calculated_all(i,j),j=1,nkstot)
ENDIF
WRITE(10,*) (xnorm_all(i,j),j=1,nkstot)
WRITE(10,*) (ncalcv_all(i,j),j=1,nkstot)
WRITE(10,*) ((a_all(j,k),j=1,ncalcv_max),k=1,nkstot)
WRITE(10,*) ((b_all(j,k),j=1,ncalcv_max),k=1,nkstot)
ENDIF
ENDDO
close(10)
DEALLOCATE(a_all)
DEALLOCATE(b_all)
DEALLOCATE(xnorm_all)
DEALLOCATE(ncalcv_all)
END SUBROUTINE write_save_file
SUBROUTINE write_status_of_the_code
USE io_global, ONLY : stdout
IMPLICIT NONE
WRITE (stdout,*) '======= Working features (22/04/2009) ==========='
WRITE (stdout,*) 'xanes works both in dipolar and quadrupolar part,'
WRITE (stdout,*) 'spin polarized works'
WRITE (stdout,*) 'DFT+U implemented, validated'
WRITE (stdout,*) 'ultrasoft pseudo works'
WRITE (stdout,*) 'cut occupied states working, improved'
WRITE (stdout,*) 'terminator working'
WRITE (stdout,*) 'Multiprojectors TM+USPP working (MCB,CG)'
WRITE (stdout,*) 'new save file format, with version numbering'
WRITE (stdout,*) 'time limit implemented, with restart, seems to work'
WRITE (stdout,*) 'DFT+U tested ONLY for non ortho wfc, but implemented'
WRITE (stdout,*) '======= TO DO ==========='
WRITE (stdout,*) 'Bethe-Salpeter [CG] '
WRITE (stdout,*) 'RXES [DC] o [CG]'
WRITE (stdout,*) '================================================='
END SUBROUTINE write_status_of_the_code
!<CG>
SUBROUTINE verify_hpsi
USE io_files, ONLY : nd_nmbr, prefix, tmp_dir, &
nwordwfc, iunwfc
USE io_global, ONLY : stdout ! Modules/io_global.f90
USE kinds, ONLY : DP
USE parameters, ONLY : ntypx
USE radial_grids, ONLY : ndmx
USE ions_base, ONLY : nat, ntyp => nsp, ityp
USE wvfct, ONLY : npwx, nbndx, nbnd, npw, igk, g2kin, et,&
current_k
USE lsda_mod, ONLY : nspin,lsda,isk,current_spin
USE cell_base, ONLY: tpiba2, bg
USE wavefunctions_module, ONLY: evc
USE klist, ONLY : &
nkstot, & ! total number of k-points
nks, & ! number of k-points per pool
xk, & ! k-points coordinates
wk ! k-points weight
USE gvect, ONLY: g,ngm,ecutwfc,ngl,nrxx
USE paw_gipaw, ONLY : &
paw_vkb, & ! |p> projectors
paw_becp, & ! product of projectors and wf.
paw_nkb, & ! total number of beta functions, with st.fact.
paw_lmaxkb,paw_recon
USE becmod, ONLY : becp, calbec, allocate_bec_type, deallocate_bec_type !CG
USE scf, ONLY : vltot, vrs, v, kedtau !CG
USE gsmooth, ONLY : doublegrid, nrxxs !CG
USE mp_global, ONLY : intra_pool_comm, mpime,my_pool_id, npool
USE mp, ONLY : mp_sum
USE xspectra, ONLY : xiabs, xanes_dip, xang_mom, xniter, xnitermax, xepsilon
USE atom, ONLY : rgrid, msh
USE radin_mod
USE uspp, ONLY : vkb, nkb, okvan
USE ldaU, ONLY : lda_plus_u
USE xspectra_paw_variables, ONLY : xspectra_paw_nhm
USE wavefunctions_module, ONLY: evc
USE uspp_param, ONLY : upf
IMPLICIT NONE
INTEGER :: is,ik,iabso,nr,ip,jp,l,j,icrd,ip_l,nrc,nt,na,i
INTEGER :: ipx,ipx_0,ipy,ipz,nline,nrest,npw_partial
REAL (dp) v_of_0
REAL (dp) norm
COMPLEX(KIND=DP) :: zdotc
COMPLEX(dp), ALLOCATABLE :: paw_vkb_cplx(:,:)
REAL(dp) :: normps
EXTERNAL zdotc
EXTERNAL zdscal
COMPLEX(dp), ALLOCATABLE :: psiwfc(:)
INTEGER :: ipw
COMPLEX(dp) :: prodscal, hevc(npwx), vecteur(npwx), prodscal_part, normtemp
INTEGER :: indice, numk, nkppool, ind2, rest, mpimea, mpimeb
LOGICAL :: exst, opnd
CHARACTER ( LEN=32) :: filehpsi, filenumber
REAL(dp) :: maxdiff
COMPLEX (dp) :: vecteuraux(npwx,1), vecteuraux2(npwx,1), sm1spsi(npwx)
COMPLEX(dp) :: psi_h_psi, psi_psi, psi_s_psi, psi_sm1s_psi
REAL(dp) :: difference
CALL set_vrs(vrs,vltot,v%of_r,kedtau, v%kin_r,nrxx,nspin,doublegrid)
IF (lda_plus_u) CALL init_xanes_ldau
mpimea=mpime
filenumber=''
DO j=1, 3
mpimeb=mod(mpimea,10)
filenumber=char(mpimeb+48)//filenumber
mpimea=mpimea/10
ENDDO
filehpsi='hpsi_'//TRIM(filenumber)//'.out'
open(unit=1000+mpime,file=filehpsi,form='formatted',status='unknown')
rewind(1000+mpime)
maxdiff=0.d0
DO ik=1,nks
current_k=ik
IF(lsda) current_spin=isk(ik)
!gk_sort sort k-points and exit kinetic energies
CALL gk_sort(xk (1,ik),ngm,g,ecutwfc/tpiba2,npw,igk,g2kin) !CHECK
g2kin=g2kin*tpiba2 !CHECK
npw_partial = npw
CALL mp_sum( npw_partial, intra_pool_comm )
CALL init_gipaw_2(npw,igk,xk(1,ik),paw_vkb)
CALL init_us_2(npw,igk,xk(1,ik),vkb)
IF (lda_plus_u) CALL init_xanes_ldau_2(ik)
CALL allocate_bec_type(nkb,1,becp)
WRITE(1000+mpime,*) 'lda_plus_u=', lda_plus_u
WRITE(1000+mpime,*) 'mypoolid=', my_pool_id,' ik=', ik
WRITE(1000+mpime,*) 'npool=', npool, ' nkstot=', nkstot
WRITE(1000+mpime,*) 'nwordwfc=', nwordwfc, ' iunwfc=', iunwfc
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! open saved eigenvectors
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
inquire (unit = iunwfc, opened = opnd)
IF (.NOT.opnd) CALL diropn( iunwfc, 'wfc', nwordwfc, exst )
CALL davcio( evc, nwordwfc, iunwfc, ik, -1 )
numk=0
nkppool=nkstot/npool
rest=nkstot-nkppool*npool
DO indice=0, my_pool_id-1
numk=numk+nkppool
IF (indice<rest) numk=numk+1
ENDDO
numk=numk+ik
WRITE(1000+mpime,*) 'npw=', npw, 'npwx=', npwx
!WRITE(1000+mpime,*) 'ns(1,1,1,1)=', ns(1,1,1,1)
!WRITE(1000+mpime,*) 'natomwfc=', natomwfc
!WRITE(1000+mpime,*) 'swfcatom=', ((swfcatom(ind2, indice), ind2=1,3), indice=1, natomwfc)
DO indice=1, nbnd
! calculating <psi | psi>
psi_psi=zdotc(npw,evc(:,indice),1,evc(:,indice),1)
CALL mp_sum( psi_psi, intra_pool_comm )
! calculating <psi | H | psi >
hevc(:)=(0.d0,0.d0)
CALL h_psi( npwx, npw,1, evc(:,indice), hevc )
psi_h_psi=zdotc(npw,evc(:,indice),1,hevc,1)
CALL mp_sum( psi_h_psi, intra_pool_comm )
difference=abs(psi_h_psi-et(indice,numk)*psi_psi)
! calculating <psi | S | psi > if ultrasoft
IF (okvan) THEN
becp%k(:,:)=0.d0
vecteuraux(:,1)=evc(:,indice)
CALL calbec(npw,vkb,vecteuraux,becp,1)
CALL s_psi( npwx,npw, 1, vecteuraux,vecteuraux2)
vecteur(:)=vecteuraux2(:,1)
psi_s_psi=zdotc(npw,evc(:,indice),1,vecteur,1)
CALL mp_sum( psi_s_psi, intra_pool_comm )
CALL sm1_psi(.true.,npwx, npw, 1, vecteuraux2, vecteuraux)
sm1spsi(:)=vecteuraux(:,1)
psi_sm1s_psi=zdotc(npw,evc(:,indice),1,sm1spsi,1)
CALL mp_sum( psi_sm1s_psi, intra_pool_comm )
ENDIF
! printing the result
IF (okvan) THEN
difference=abs(psi_h_psi-et(indice,numk)*psi_s_psi)
WRITE(1000+mpime,*) 'k-point', ik, 'absolute k =', numk
WRITE(1000+mpime,*) 'bande : ', indice
WRITE(1000+mpime,*) 'current spin=', current_spin
WRITE(1000+mpime,*) 'et(bande,ik)=', et(indice, numk)
WRITE(1000+mpime,*) '|<psi|psi>|=',abs(psi_psi)
WRITE(1000+mpime,*) '|<psi|S|psi>|=',abs(psi_s_psi)
WRITE(1000+mpime,*) '|<psi|S^-1*S|psi>|=',abs(psi_sm1s_psi)
WRITE(1000+mpime,*) '|<psi|H|psi>|=',abs(psi_h_psi)
WRITE(1000+mpime,*) '|<psi|H|psi>-E*<psi|psi>|=',abs(psi_h_psi-et(indice,numk)*psi_psi)
WRITE(1000+mpime,*) '|<psi|H|psi>-E*<psi|S|psi>|=', difference
ELSE
difference=abs(psi_h_psi-et(indice,numk)*psi_psi)
WRITE(1000+mpime,*) 'k-point', ik, 'absolute k =', numk
WRITE(1000+mpime,*) 'bande : ', indice
WRITE(1000+mpime,*) 'current spin=', current_spin
WRITE(1000+mpime,*) 'et(bande,ik)=', et(indice, numk)
WRITE(1000+mpime,*) '|<psi|psi>|=',abs(psi_psi)
WRITE(1000+mpime,*) '|<psi|H|psi>|=',abs(psi_h_psi)
WRITE(1000+mpime,*) '|<psi|H|psi>-E*<psi|psi>|=', difference
ENDIF
IF (difference > maxdiff) maxdiff=difference
IF (difference > 1.d-4) WRITE(1000+mpime,*) 'warning : difference too big'
WRITE(1000+mpime,*) ' '
ENDDO
WRITE(1000+mpime,*) '--------------------- END ------------------ '
CALL deallocate_bec_type(becp)
ENDDO !on k points
close(1000+mpime)
WRITE(stdout,*) '> h_psi test : maximum difference on master node is ', maxdiff
END SUBROUTINE verify_hpsi
SUBROUTINE read_gamma_file
USE gamma_variable_mod
IMPLICIT NONE
INTEGER :: nl, ierr, i
open (unit=21, file=gamma_file, form='formatted',status='unknown', iostat=ierr)
CALL errore ('io ', 'gamma file '//TRIM(gamma_file)//' not found', abs (ierr) )
rewind(21)
nl=0
DO
READ (21,'(a1)',iostat=ierr)
IF (ierr.NE.0) EXIT
nl=nl+1
ENDDO
close(21)
gamma_lines=nl
ALLOCATE(gamma_points(nl,2))
open (unit=21, file=gamma_file, form='formatted',status='unknown', iostat=ierr)
rewind(21)
DO i=1,nl
READ(21,*) gamma_points(i,1), gamma_points(i,2)
ENDDO
close(21)
END SUBROUTINE read_gamma_file
SUBROUTINE initialize_gamma_tab
USE xspectra, ONLY : xemin, xemax, xnepoint
USE kinds, ONLY :dp
USE io_global, ONLY : stdout
USE gamma_variable_mod
IMPLICIT NONE
REAL(dp) :: e,x,y,dx
INTEGER :: i,j,n
REAL (dp), parameter :: ryd2ev = 13.6058d0
dx=(xemax-xemin)/dfloat(xnepoint)
DO n=1, xnepoint
x=xemin+(n-1)*dx
i=1
DO j=1, gamma_lines
IF(x>gamma_points(j,1)) i=i+1
ENDDO
IF (i.EQ.1) THEN
y=gamma_points(1,2)
ELSEIF (i.EQ.(gamma_lines+1)) THEN
y=gamma_points(gamma_lines,2)
ELSE
y=(gamma_points(i-1,2)*(gamma_points(i,1)-x)+gamma_points(i,2)*(x-gamma_points(i-1,1)))&
/(gamma_points(i,1)-gamma_points(i-1,1))
ENDIF
gamma_tab(n)=y/ryd2ev
ENDDO
END SUBROUTINE initialize_gamma_tab
SUBROUTINE determine_polycut(t1,t2,f1,f2,df1,df2,poly)
! calculates the interpolation polynome betwenn 2 points
USE kinds, ONLY : dp
IMPLICIT NONE
REAL(dp) :: t1,t2,f1,f2,df1,df2,poly(4)
poly(4)=((t2-t1)*(df2+df1)-2*(f2-f1))/((t2-t1)**3)
poly(3)=(df2-df1)/(2*(t2-t1))-1.5d0*(t2+t1)*((t2-t1)*(df2+df1)-2*(f2-f1))/((t2-t1)**3)
poly(2)=df1-2*t1*poly(3)-3*t1*t1*poly(4)
poly(1)=f1-poly(2)*t1-poly(3)*t1**2-poly(4)*t1**3
END SUBROUTINE determine_polycut
!</CG>