mirror of https://gitlab.com/QEF/q-e.git
Spectra manipulation tool
This small tool allows to 1) Remove states below a certain energy from the spectrum In large gap insulator it should work as the usual cut_occupied_states option but it is much much faster In metals/semimetals the normal and more time consuming option cut_occupied_states=.true. used in XSpectra should work better. The procedure use here can sometimes work for metals but care is needed. 2) For L23 edges, this code generates the full L23 spectrum from the L2 edge only. The L3 edge is obtained multiplying by two the L2 (branching ration 2.0) and shifting it by the spin-orbit splitting between 2p1/2 and 2p3/2. Thus the spectrum in input must be the L2 edge. Instruction on how to use it are in the header of the file i.e. cat spectra_manipulation.f90 |more More functions to be added in the next days. MCB git-svn-id: http://qeforge.qe-forge.org/svn/q-e/trunk/espresso@11704 c92efa57-630b-4861-b058-cf58834340f0
This commit is contained in:
parent
d0fd9a36c3
commit
f3f6c913c0
|
@ -38,6 +38,8 @@ GIPAWOBJS=./paw_gipaw.o \
|
|||
./init_gipaw_1.o \
|
||||
./init_gipaw_2.o
|
||||
|
||||
MANIP_XS_OBJ=./gaunt_mod.o
|
||||
|
||||
QEMODS = ../../Modules/libqemod.a
|
||||
PWOBJS = ../../PW/src/libpw.a
|
||||
|
||||
|
@ -46,13 +48,18 @@ LIBOBJS = ../../iotk/src/libiotk.a ../../flib/flib.a \
|
|||
|
||||
TLDEPS = bindir libs pw
|
||||
|
||||
all : tldeps xspectra.x
|
||||
all : tldeps xspectra.x spectra_manipulation.x
|
||||
|
||||
xspectra.x : xspectra.o $(XOBJS) $(GIPAWOBJS) $(QEMODS) $(PWOBJS)
|
||||
$(MPIF90) -o $@ xspectra.o $(XOBJS) $(GIPAWOBJS) \
|
||||
$(PWOBJS) $(QEMODS) $(LDFLAGS) $(LIBOBJS) $(LIBS)
|
||||
- ( cd ../../bin ; ln -fs ../XSpectra/src/$@ . )
|
||||
|
||||
spectra_manipulation.x : spectra_manipulation.o $(MANIP_XS_OBJ) $(QEMODS) $(PWOBJS)
|
||||
$(MPIF90) -o $@ spectra_manipulation.o $(MANIP_XS_OBJ) $(PWOBJS) $(QEMODS) \
|
||||
$(LDFLAGS) $(LIBOBJS) $(LIBS)
|
||||
- ( cd ../../bin ; ln -fs ../XSpectra/src/$@ . )
|
||||
|
||||
tldeps :
|
||||
test -n "$(TLDEPS)" && ( cd ../.. ; $(MAKE) $(MFLAGS) $(TLDEPS) || exit 1) || :
|
||||
|
||||
|
|
|
@ -148,6 +148,8 @@ select_nl_init.o : ../../Modules/io_global.o
|
|||
select_nl_init.o : ../../Modules/kind.o
|
||||
set_xspectra_namelists_defaults.o : ../../Modules/io_files.o
|
||||
set_xspectra_namelists_defaults.o : xspectra_mod.o
|
||||
spectra_manipulation.o : ../../Modules/kind.o
|
||||
spectra_manipulation.o : gaunt_mod.o
|
||||
stdout_routines.o : ../../Modules/constants.o
|
||||
stdout_routines.o : ../../Modules/io_files.o
|
||||
stdout_routines.o : ../../Modules/io_global.o
|
||||
|
|
|
@ -0,0 +1,333 @@
|
|||
!
|
||||
! Spectra manipulation tool by Matteo Calandra, Agust 2015
|
||||
!
|
||||
! This small code allows to
|
||||
!
|
||||
! 1) Remove states below a certain energy from the spectrum
|
||||
! In large gap insulator it should work as the usual
|
||||
! cut_occupied_states option but it is much much faster
|
||||
! In metals/semimetals the normal and more time consuming
|
||||
! option cut_occupied_states=.true. used in XSpectra
|
||||
! should work better. The procedure use here can sometimes
|
||||
! work for metals but care is needed.
|
||||
!
|
||||
! 2) For L23 edges, this code generates the full L23 spectrum from
|
||||
! the L2 edge only. the L3 edge is obtained multiplying by two the
|
||||
! L2 and shifting it by the spin-orbit splitting between 2p1/2
|
||||
! and 2p3/2. Thus the spectrum in input must be the L2 edge.
|
||||
!
|
||||
! How to use:
|
||||
!
|
||||
! 1) Use in single processor, no parallelization
|
||||
!
|
||||
! 2) Input file description:
|
||||
!
|
||||
! case (i): removal of occupied states from the spectrum
|
||||
!
|
||||
! &input_manip
|
||||
! cross_section_file='xanes.dat',
|
||||
! option='cut_occ_states',
|
||||
! xe0=13.0,
|
||||
! shift_spectrum=.false.,
|
||||
! &end
|
||||
!
|
||||
! if shift_spectrum=.true. the spectrum is shifted in xe0
|
||||
!
|
||||
! case (ii): removal of occupied states from the spectrum
|
||||
!
|
||||
! &input_manip
|
||||
! cross_section_file='xanes.dat',
|
||||
! option='add_L2_L3',
|
||||
! element='Cu',
|
||||
! &end
|
||||
!
|
||||
! element is used to read the spin orbit splitting 2p1/2, 2p3/2
|
||||
!
|
||||
! The cross_section_file is the xanes.dat file with the cross section.
|
||||
!
|
||||
!----------------------------------------------------------------------------
|
||||
Program manip_spectra
|
||||
USE kinds, ONLY : DP
|
||||
USE edge_energy, ONLY: getE
|
||||
IMPLICIT NONE
|
||||
! Input
|
||||
LOGICAL :: shift_spectrum
|
||||
REAL(kind=dp) :: xe0
|
||||
CHARACTER (LEN=255) :: cross_section_file, option
|
||||
CHARACTER (LEN=2) :: element
|
||||
|
||||
! Other variables
|
||||
|
||||
LOGICAL :: found
|
||||
INTEGER :: i
|
||||
INTEGER :: nargs, iiarg, iargc, ierr, ios
|
||||
INTEGER :: nenergy, istart
|
||||
REAL(kind=dp) :: el2, el3, so_splitting
|
||||
REAL(kind=DP), ALLOCATABLE :: cross_section_in(:), energy_in(:)
|
||||
REAL(kind=DP), ALLOCATABLE :: cross_section_out(:), energy_out(:)
|
||||
REAL(kind=DP), ALLOCATABLE :: cross_section_L3(:), energy_L3(:)
|
||||
|
||||
CHARACTER (LEN=256) :: input_file
|
||||
|
||||
namelist / input_manip / &
|
||||
cross_section_file, &
|
||||
option, &
|
||||
xe0, &
|
||||
shift_spectrum, &
|
||||
element
|
||||
|
||||
!
|
||||
! Defaults
|
||||
!
|
||||
|
||||
cross_section_file=' '
|
||||
option=' '
|
||||
xe0=0
|
||||
shift_spectrum=.false.
|
||||
|
||||
!
|
||||
! Read namelist
|
||||
!
|
||||
|
||||
nargs = iargc()
|
||||
found = .FALSE.
|
||||
input_file = ' '
|
||||
|
||||
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' .OR. &
|
||||
TRIM( input_file ) == '-i' ) THEN
|
||||
!
|
||||
CALL getarg( ( iiarg + 1 ) , input_file )
|
||||
found = .TRUE.
|
||||
EXIT
|
||||
ENDIF
|
||||
!
|
||||
ENDDO
|
||||
|
||||
IF (found) THEN
|
||||
OPEN ( UNIT = 5, FILE = input_file, FORM = 'FORMATTED', &
|
||||
STATUS = 'OLD', IOSTAT = ierr )
|
||||
IF ( ierr > 0 ) THEN
|
||||
CALL errore('iosys', ' input file ' // TRIM( input_file ) // &
|
||||
& ' not found' , ierr )
|
||||
! WRITE (stdout, '(/,5x,"*** STOP: input file ",A," not found ***",/)' ) &
|
||||
! TRIM( input_file )
|
||||
ENDIF
|
||||
ELSE
|
||||
ierr = -1
|
||||
END IF
|
||||
|
||||
|
||||
READ(5, input_manip, err = 200, iostat = ios)
|
||||
200 CALL errore ('input_xspectra', 'reading input_xspectra namelist', abs (ios) )
|
||||
|
||||
!
|
||||
! Check input
|
||||
!
|
||||
|
||||
IF( TRIM(ADJUSTL(option)).ne.'cut_occ_states'.AND.TRIM(ADJUSTL(option)).ne.'add_L2_L3') then
|
||||
write(6,*) 'Option not recognized'
|
||||
write(6,*) 'Program is stopped'
|
||||
stop
|
||||
ENDIF
|
||||
|
||||
|
||||
!
|
||||
! Read the cross section
|
||||
!
|
||||
|
||||
cross_section_file=TRIM(ADJUSTL(cross_section_file))
|
||||
OPEN (unit=277,file=cross_section_file,form='formatted',status='unknown')
|
||||
rewind(277)
|
||||
|
||||
call how_many_lines_in_cs_file(277, nenergy)
|
||||
|
||||
allocate(cross_section_in(nenergy))
|
||||
allocate(energy_in(nenergy))
|
||||
|
||||
|
||||
read(277,*)
|
||||
read(277,*)
|
||||
read(277,*)
|
||||
read(277,*)
|
||||
|
||||
do i=1,nenergy
|
||||
read(277,*) energy_in(i), cross_section_in(i)
|
||||
enddo
|
||||
|
||||
close(277)
|
||||
|
||||
|
||||
|
||||
IF(option.eq.'cut_occ_states') then
|
||||
allocate(cross_section_out(nenergy))
|
||||
allocate(energy_out(nenergy))
|
||||
call removal_of_occupied_states(nenergy, energy_in, cross_section_in, xe0, shift_spectrum, &
|
||||
energy_out, cross_section_out)
|
||||
OPEN (unit=20,file=trim(adjustl(cross_section_file))//'.cut',form='formatted',status='unknown')
|
||||
rewind(20)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
|
||||
do i=1,nenergy
|
||||
write(20,*) energy_out(i), cross_section_out(i)
|
||||
enddo
|
||||
close(20)
|
||||
deallocate(cross_section_out)
|
||||
deallocate(energy_out)
|
||||
ELSEIF(option.eq.'add_L2_L3') then
|
||||
allocate(cross_section_L3(nenergy))
|
||||
allocate(energy_L3(nenergy))
|
||||
|
||||
cross_section_L3=2.d0*cross_section_in
|
||||
|
||||
el2=getE(element,'L2')
|
||||
el3=getE(element,'L3')
|
||||
so_splitting=el2-el3
|
||||
|
||||
write(6,*) 'Energy of L2 edge (eV) = ',el2
|
||||
write(6,*) 'Energy of L3 edge (eV) = ',el3
|
||||
|
||||
|
||||
energy_L3=energy_in+so_splitting
|
||||
|
||||
if(energy_L3(1).gt.energy_in(nenergy)) then
|
||||
|
||||
OPEN (unit=20,file=trim(adjustl(cross_section_file))//'.L23',&
|
||||
form='formatted',status='unknown')
|
||||
|
||||
rewind(20)
|
||||
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
|
||||
do i=1,nenergy
|
||||
write(20,*) energy_in(i), cross_section_in(i)
|
||||
enddo
|
||||
do i=1,nenergy
|
||||
write(20,*) energy_L3(i), cross_section_L3(i)
|
||||
enddo
|
||||
|
||||
close(20)
|
||||
|
||||
else
|
||||
|
||||
allocate(cross_section_out(nenergy))
|
||||
|
||||
cross_section_out=0.d0
|
||||
|
||||
!
|
||||
! determine the first overlap point
|
||||
!
|
||||
|
||||
do i=1,nenergy-1
|
||||
if(energy_in(i).lt.energy_L3(1).and.energy_in(i+1).gt.energy_L3(1)) istart=i
|
||||
enddo
|
||||
|
||||
do i=1,istart
|
||||
cross_section_out(i)=cross_section_in(i)
|
||||
enddo
|
||||
do i=istart+1, nenergy
|
||||
cross_section_out(i)=cross_section_in(i)+cross_section_L3(i-istart)
|
||||
enddo
|
||||
|
||||
OPEN (unit=20,file=trim(adjustl(cross_section_file))//'.L23',&
|
||||
form='formatted',status='unknown')
|
||||
|
||||
rewind(20)
|
||||
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
write(20,*)
|
||||
|
||||
do i=1,nenergy
|
||||
write(20,*) energy_in(i), cross_section_out(i)
|
||||
enddo
|
||||
|
||||
close(20)
|
||||
|
||||
deallocate(cross_section_out)
|
||||
endif
|
||||
deallocate(cross_section_L3)
|
||||
deallocate(energy_L3)
|
||||
|
||||
ENDIF
|
||||
|
||||
|
||||
deallocate(cross_section_in)
|
||||
deallocate(energy_in)
|
||||
|
||||
|
||||
end Program manip_spectra
|
||||
|
||||
subroutine how_many_lines_in_cs_file( iun, nlines )
|
||||
IMPLICIT NONE
|
||||
INTEGER :: iun, nlines
|
||||
!
|
||||
character(256) :: line
|
||||
integer :: ios
|
||||
|
||||
rewind(iun)
|
||||
!
|
||||
! Read the small header
|
||||
!
|
||||
read(iun,*)
|
||||
read(iun,*)
|
||||
read(iun,*)
|
||||
read(iun,*)
|
||||
|
||||
nlines=0
|
||||
|
||||
!
|
||||
! Count the lines.
|
||||
!
|
||||
do
|
||||
|
||||
read ( iun, '(a)', iostat = ios ) line
|
||||
|
||||
if ( ios /= 0 ) then
|
||||
exit
|
||||
end if
|
||||
|
||||
|
||||
nlines = nlines + 1
|
||||
|
||||
end do
|
||||
|
||||
rewind(iun)
|
||||
|
||||
end subroutine how_many_lines_in_cs_file
|
||||
|
||||
subroutine removal_of_occupied_states(nenergy, energy_in, cross_section_in, xe0, shift_spectrum, &
|
||||
energy_out, cross_section_out)
|
||||
USE kinds, ONLY : DP
|
||||
IMPLICIT NONE
|
||||
LOGICAL :: shift_spectrum
|
||||
INTEGER :: nenergy
|
||||
REAL(kind=dp) :: xe0
|
||||
REAL(kind=dp) :: energy_in(nenergy), cross_section_in(nenergy)
|
||||
REAL(kind=dp) :: energy_out(nenergy), cross_section_out(nenergy)
|
||||
!
|
||||
INTEGER :: i
|
||||
|
||||
energy_out=energy_in
|
||||
cross_section_out=0.d0
|
||||
|
||||
do i=1,nenergy
|
||||
if(energy_in(i).ge.xe0) cross_section_out(i)=cross_section_in(i)
|
||||
enddo
|
||||
|
||||
if(shift_spectrum) energy_out=energy_out-xe0
|
||||
|
||||
RETURN
|
||||
end subroutine removal_of_occupied_states
|
||||
|
Loading…
Reference in New Issue