On Mon, 4 Jul 2005, xianghjun wrote:
| Dear Andrei Postnikov,
| I tried ene2bxsf, sometimes it works well, for example for factitial SCC Fe,
| however ene2bxsf fails for BCC Fe, as an example in siesta.
Dear H.J. Xiang,
thank you for your hint. It was indeed a not clean enough piece of code
which shoot for bcc lattice. Please try the updated version
of eig2bxsf attached to this mail.
Just one note of caution. In the Siesta example of Fe you use,
the lattice vectors are
0.50000 0.500000 0.500000
0.50000 -0.500000 0.500000
0.50000 0.500000 -0.500000
- this is of course legal for a band structure calculation,
and even results in a Fermi surface,
which is however weirdly folded and not quite of cubic symmetry.
If you take more conventional and symmetric lattice vectors
-0.50000 0.500000 0.500000
0.50000 -0.500000 0.500000
0.50000 0.500000 -0.500000
the Fermi surface will be nice and cubic-symmetric. (However, I don't
remember what the true Fe Fermi surface is like, so you better check it).
Good luck, and again let me know in case of any problems.
Andrei
+-- Dr. habil. Andrei Postnikov ----- Tel. +49-541-969.2377 -- Fax .2351 ---+
| Institut fuer Festkoerperforschung - FZ Juelich, D-52425 Juelich, Germany |
+-- [EMAIL PROTECTED] --------- http://www.home.uni-osnabrueck.de/apostnik/ --+
C
C ene2bxsf, a script to make the band-XSF file (for plotting
C the Fermi surface) from siesta KP and EIG files.
C The k-mesh must be generated without shift
C (requirement of the BXSF format).
C
C Written by Andrei Postnikov, Jul 2005 Vers_0.1
C [EMAIL PROTECTED]
C
program ene2bxsf
implicit none
integer ii1,ii2,ii3,io1
parameter (ii1=11,ii2=12,ii3=13,io1=14)
integer ii,jj,nbands,nbmin,nbmax,nkp,ikp,ndum,iis,mdiv(3),ind,
. nspin,is,iband,iik,idiv1,idiv2,idiv3,itry1,itry2,itry3,
. ib,mkp,homo(2),lumo(2),ik,in2,in3,ialloc
character inpfil*60,outfil*60,syslab*30,suffix*6
real*8 cell(3,3),efermi,twopi,rcell(3,3),small,relmin(3),
. kkp(3),dum
real*8, allocatable :: relk(:,:), eneb(:,:), enek(:)
integer, allocatable :: ndiv(:,:),irrek(:)
parameter (small=1.0d-04)
C
C string manipulation functions in Fortran used below:
C len_trim(string): returns the length of string
C without trailing blank characters,
C char(integer) : returns the character in the specified position
C of computer's ASCII table, i.e. char(49)=1
C
twopi = 8.d0*atan(1.d0)
write (6,701)
701 format(" Specify SystemLabel (or 'siesta' if none): ",$)
read (5,*) syslab
C --- open .XV and .EIG :
inpfil = syslab(1:len_trim(syslab))//'.XV'
open (ii1,file=inpfil,form='formatted',status='old',err=801)
write (6,*) 'Found and opened: ',inpfil
inpfil = syslab(1:len_trim(syslab))//'.EIG'
open (ii2,file=inpfil,form='formatted',status='old',err=801)
write (6,*) 'Found and opened: ',inpfil
C --- read Fermi energy and total number of bands from .EIG :
read (ii2,*) efermi
read (ii2,*) nbands, nspin, nkp
if (nspin.ne.1.and.nspin.ne.2) then
write (6,*) 'A problem encountered: nspin=',nspin
stop
endif
C --- finds bands crossing the Fermi energy:
do is=1,nspin
homo(is)=0 ! higest (partially?) occupied band
lumo(is)=nbands+1 ! lowest (partially?) unoccupied band
enddo
write (6,*) ' nkp=',nkp,' nbands=',nbands
allocate (eneb(nbands,nspin),STAT=ialloc)
if (ialloc.ne.0) then
write (6,*) ' Fails to allocate space for nbands=',
. nbands,', nspin=',nspin
stop
endif
do ik=1,nkp
read (ii2,"(i5,10f12.5,/,(5x,10f12.5))") iik, ! written in
. ((eneb(ib,is),ib=1,nbands),is=1,min(nspin,2)) ! ioeif.f
if (iik.ne.ik) then
write (6,*) ' iik=',iik,'.ne. ik=',ik,' for spin ',is
stop
endif
do is=1,nspin
do ib=1,nbands
if (eneb(ib,is).lt.efermi.and.ib.gt.homo(is)) homo(is) = ib
if (eneb(ib,is).gt.efermi.and.ib.lt.lumo(is)) lumo(is) = ib
enddo
enddo
enddo
deallocate (eneb)
do is=1,nspin
write (6,*) ' is=',is,' homo, lumo=',homo(is),lumo(is)
if (homo(is).lt.lumo(is)) write (6,201) is, homo(is),lumo(is)
enddo
C --- read cell vectors from .XV, convert to Ang, find reciprocal:
do ii=1,3
read (ii1,*,end=803,err=803) (cell(ii,jj),jj=1,3)
enddo
close (ii1)
call inver3(cell,rcell)
C --- open .KP as old:
inpfil = syslab(1:len_trim(syslab))//'.KP'
open (ii3,file=inpfil,form='formatted',status='old',err=801)
write (6,*) 'Found and opened: ',inpfil
C --- read k-points from the .KP file and recover their fractional
C coordinates in terms of reciprocal vectors:
read (ii3,*) nkp
relmin(:)=1.d0/small
allocate (relk(3,nkp))
if (ialloc.ne.0) then
write (6,*) ' Fails to allocate space for relk(3,',nkp,')'
stop
endif
do ikp=1,nkp
read (ii3,*) iik,(kkp(jj),jj=1,3)
if (iik.ne.ikp) then
write (6,*) ' a mess in KP list: read in iik=',iik,
. ', but expected ikp=',ikp
stop
endif
C --- find relative coordinates of k-point:
do ii=1,3
relk(ii,ikp)=( cell(ii,1)*kkp(1) +
+ cell(ii,2)*kkp(2) +
+ cell(ii,3)*kkp(3) )/twopi
if (abs(relk(ii,ikp)).lt.relmin(ii).and.
. abs(relk(ii,ikp)).gt.small)
. relmin(ii)=abs(relk(ii,ikp))
enddo
enddo
close (ii3)
C --- relmin(ii) is now the smallest relative coordinate of k points
C along the reciprocal vector (ii). Good chance that its inverse
C is number of divisions.
mdiv(:)=1.d0/relmin(:)+small
write (6,*) ' No. of divisions seems to be ',mdiv
mkp = (mdiv(1)+1)*(mdiv(2)+1)*(mdiv(3)+1)
write (6,*) ' Full No. of k-points on general grid:', mkp
allocate (ndiv(3,mkp),STAT=ialloc)
allocate (irrek(mkp), STAT=ialloc)
if (ialloc.ne.0) then
write (6,*) ' Fails to allocate space for mkp=',mkp
stop
endif
C --- decifer all k-point coordinates as ndiv(ii,ikp)/mdiv(ii)
do ikp=1,nkp
ndiv(:,ikp)=modulo(floor(relk(:,ikp)/relmin(:)+small),mdiv(:))
enddo
C --- attribute irreducible k-points to k-points on the grid:
ind=0
do idiv3 = 0,mdiv(3)
do idiv2 = 0,mdiv(2)
do idiv1 = 0,mdiv(1)
ind = ind + 1 ! global address on the mesh
itry1=mod(idiv1,mdiv(1))
itry2=mod(idiv2,mdiv(2))
itry3=mod(idiv3,mdiv(3))
do 12 ikp=1,nkp
if (ndiv(1,ikp).ne.itry1) goto 12
if (ndiv(2,ikp).ne.itry2) goto 12
if (ndiv(3,ikp).ne.itry3) goto 12
irrek(ind) = ikp
goto 14
12 enddo
C --- haven't find anything; try inversion:
itry1=mod(mdiv(1)-idiv1,mdiv(1))
itry2=mod(mdiv(2)-idiv2,mdiv(2))
itry3=mod(mdiv(3)-idiv3,mdiv(3))
do 13 ikp=1,nkp
if (ndiv(1,ikp).ne.itry1) goto 13
if (ndiv(2,ikp).ne.itry2) goto 13
if (ndiv(3,ikp).ne.itry3) goto 13
irrek(ind) = ikp
goto 14
13 enddo
C --- haven't try anything with inversion as well;
write (6,304) idiv1,mdiv(1),idiv2,mdiv(2),idiv3,mdiv(3)
304 format(' No irreducible k-point found for k-grid point (',
. i4,'/',i4,', ',i4,'/',i4,', ',i4,'/',i4,' )')
write (6,*) ' Are you sure your k-grid was without shift?'
stop
14 continue
enddo
enddo
enddo
allocate (enek(nkp), STAT=ialloc)
if (ialloc.ne.0) then
write (6,*) ' Fails to allocate space for enek(1:',nkp,')'
stop
endif
C --- The writing sequence (into two BXSF files if two spins)
do is=1,nspin
if (nspin.eq.1) then
outfil = syslab(1:len_trim(syslab))//'.BXSF'
else
outfil =
. syslab(1:len_trim(syslab))//'_spin_'//char(48+is)//'.BXSF'
endif
open (io1,file=outfil,form='formatted',status='new',err=802)
write (6,*) 'Opened as new: ',outfil
write (io1, "(a10)") 'BEGIN_INFO'
write (io1, "(a5)") ' # '
write (io1, "(a33)") ' # Band-XCRYSDEN-Structure-File'
write (io1, "(a5)") ' # '
write (io1, "(a16,f10.4)") ' Fermi energy: ',efermi
write (io1, "(a8,/)") 'END_INFO'
write (io1, "(a23)") 'BEGIN_BLOCK_BANDGRID_3D'
write (io1, *) ' ',syslab(1:len_trim(syslab))
write (io1, "(a19,a1)") ' BANDGRID_3D_spin_',char(48+is)
write (io1, "(i5)") homo(is)-lumo(is)+1 ! No. of bands
write (io1, "(3i5)") mdiv(1)+1, mdiv(2)+1, mdiv(3)+1
write (io1, "(3f16.8)") 0.0, 0.0, 0.0
write (io1, "(3f16.8)") (rcell(jj,1)*twopi,jj=1,3)
write (io1, "(3f16.8)") (rcell(jj,2)*twopi,jj=1,3)
write (io1, "(3f16.8)") (rcell(jj,3)*twopi,jj=1,3)
do iband=lumo(is),homo(is)
write (io1, '(a7,i5)') ' BAND:',iband
C --- again read band energies of the needed band and spin from .ENE
C and write them in the correct order into .BXSF
rewind (ii2)
read (ii2,*) dum
read (ii2,*) ndum, ndum, ndum
C --- read in all energy values over all k points for the given spin band:
do ik=1,nkp
read (ii2,"(i5,10f12.5,/,(5x,10f12.5))") iik,
. ((dum,ib=1,nbands),iis=1,is-1), ! dummy read prev. spin, if any
. (dum,ib=1,iband-1),enek(ik),(dum,ib=iband+1,nbands),
. ((dum,ib=1,nbands),iis=is+1,nspin) ! dummy read next spin, if any
enddo
C --- write into .BXSF file:
write (io1, "(7f11.5)")
. (enek(irrek(ii)),ii=1,mkp)
enddo ! do iband=lumo(is),homo(is)
write (io1, '(a17)') ' END_BANDGRID_3D'
write (io1, '(a21)') 'END_BLOCK_BANDGRID_3D'
close (io1)
enddo ! do is=1,ispin
deallocate (enek)
deallocate (relk)
deallocate (ndiv)
deallocate (irrek)
close (ii2)
stop
201 format (' spin',i2,': band gap between bands ',i5,' and ',i5)
204 format (3f12.7)
205 format (1p,6e13.6)
C 205 format (1p,8e10.3)
206 format (' For is=',i1,': ',a3,'. grid value =',1p,e12.5,
. ' at ix,iy,iz=',3i4)
801 write (6,*) ' Error opening file ',
. inpfil(1:len_trim(inpfil)),' as old formatted'
stop
802 write (6,*) ' Error opening file ',
. outfil(1:len_trim(outfil)),' as new formatted'
stop
803 write (6,*) ' End/Error reading XV for cell vector ',ii
stop
end
C -----------------------------------
C
subroutine inver3(a,b)
C
C Inverts a 3x3 matrix
implicit none
integer i
double precision a(3,3), b(3,3), c
b(1,1) = a(2,2)*a(3,3) - a(3,2)*a(2,3)
b(1,2) = a(3,2)*a(1,3) - a(1,2)*a(3,3)
b(1,3) = a(1,2)*a(2,3) - a(2,2)*a(1,3)
b(2,1) = a(2,3)*a(3,1) - a(3,3)*a(2,1)
b(2,2) = a(3,3)*a(1,1) - a(1,3)*a(3,1)
b(2,3) = a(1,3)*a(2,1) - a(2,3)*a(1,1)
b(3,1) = a(2,1)*a(3,2) - a(3,1)*a(2,2)
b(3,2) = a(3,1)*a(1,2) - a(1,1)*a(3,2)
b(3,3) = a(1,1)*a(2,2) - a(2,1)*a(1,2)
do i = 1, 3
c=1.d0/(a(1,i)*b(i,1) + a(2,i)*b(i,2) + a(3,i)*b(i,3) )
b(i,1)=b(i,1)*c
b(i,2)=b(i,2)*c
b(i,3)=b(i,3)*c
enddo
end
C
C ...........................................................