On Sun, 26 Jun 2005, xianghjun wrote:

| Dear Andrei Postnikov,
|  I have tried rho2xsf, and it works well.
| Now I want to plot the Fermi surface using Xcrysden.
| I learn that you have a program named ene2bxsf to do this job.
| Would you please send a copy of ene2bxsf to me?
| Thanks a lot.
| 
| Best regards,
| xianghjun

Dear Xianghjun,

please find in the attachment a code to calculate Fermi surface file
in Xcrysden. I did not check it extensively, but it seems to work
also with the version 1.4 (that with an additional option 
to plot several sheets of the Fermi surface in the same plot).
Please let me know if you encounter any problems.

Be sure that you use many enough k-points without shifting.

Good luck,

Andrei
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, Mar 2005
C             [EMAIL PROTECTED]
C
      program ene2bxsf
      implicit none
      integer MKP,MNB
      parameter (MKP=8000,MNB=500)
      integer ii1,ii2,ii3,io1
      parameter (ii1=11,ii2=12,ii3=13,io1=14)
      integer ii,jj,nbands,nbmin,nbmax,nkp,ikp,ndum,iis,
     .        mdiv1,mdiv2,mdiv3,ndiv(3,MKP),ind,irrek(MKP),nspin,is,
     .        iband,iik,idiv1,idiv2,idiv3,itry1,itry2,itry3,ib,
     .        homo(2),lumo(2),ik,in2,in3
      character inpfil*60,outfil*60,syslab*30,suffix*6
      real*8 cell(3,3),efermi,twopi,rcell(3,3),small,relmin(3),
     .       relk(3,MKP),kkp(3),eneb(MNB,2),enek(MKP),dum
      equivalence (eneb,enek)
      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 (nbands.gt.MNB) then
        write (6,*) '  nbands=',nbands,' .gt. MNB=',MNB
        stop
      endif
      if (nspin.ne.1.and.nspin.ne.2) then
        write (6,*) 'A problem encountered: nspin=',nspin
        stop
      endif
      if (nkp.gt.MKP) then
        write (6,*) '  nkp=',nkp,' .gt. MKP=',MKP
        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
      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
      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     write (6,*) ' cell:'
C     do ii=1,3
C       write(6,'(3f15.6)')  (cell(ii,jj),jj=1,3)
C     enddo
C     write (6,*) ' rcell:'
C     do ii=1,3
C       write(6,'(3f15.6)')  (rcell(ii,jj),jj=1,3)
C     enddo

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
      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
C       write(6,'(i5,3f15.6)')  ikp,(relk(jj,ikp),jj=1,3)
      enddo
      close (ii3)
C     write (6,*) '  relmin=',relmin
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.
      mdiv1=1.d0/relmin(1)+small
      mdiv2=1.d0/relmin(2)+small
      mdiv3=1.d0/relmin(3)+small
      write (6,*) '  mdiv1,2,3=',mdiv1,mdiv2,mdiv3
      if ((mdiv1+1)*(mdiv2+1)*(mdiv3+1).gt.MKP) then
        write (6,*) ' MKP needs to be at least ',
     .              (mdiv1+1)*(mdiv2+1)*(mdiv3+1)
        stop
      endif
C --- decifer all k-point coordinates as ndiv(ii,ikp)/mdiv_ii
      do ikp=1,nkp
        do ii=1,3
          if (relk(ii,ikp).ge.0.d0) then
            ndiv(ii,ikp)=relk(ii,ikp)/relmin(ii)+small
          else   
            ndiv(ii,ikp)=(relk(ii,ikp)+1.d0)/relmin(ii)+small
          endif  
        enddo
C       write(6,203) ikp, ndiv(1,ikp),mdiv1,
C    .                    ndiv(2,ikp),mdiv2,
C    .                    ndiv(3,ikp),mdiv3
  203   format('   ikp=',i4,':  (',3(i3,'/',i3,3x),' )')
      enddo
C --- attribute irreducible k-points to k-points on the grid:
      ind=0
      do idiv3 = 0,mdiv3
      do idiv2 = 0,mdiv2
      do idiv1 = 0,mdiv1
        ind = ind + 1      !  global address on the mesh
        itry1=mod(idiv1,mdiv1)
        itry2=mod(idiv2,mdiv2)
        itry3=mod(idiv3,mdiv3)
C       write (6,302) idiv1,idiv2,idiv3,itry1,itry2,itry3
  302 format ('  Search idiv1,2,3=',3i5,'  itry1,2,3=',3i5)
        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
C         write (6,*) ' Found: ikp=',ikp
          goto 14
   12   enddo
C ---   haven't find anything; try inversion:
        itry1=mod(mdiv1-idiv1,mdiv1)
        itry2=mod(mdiv2-idiv2,mdiv2)
        itry3=mod(mdiv3-idiv3,mdiv3)
C       write (6,303) itry1,itry2,itry3
  303 format (' ---  try inversed:   itry1,2,3=',3i5)
        do 13 ikp=1,nkp
C         write (6,*) ' ikp:',ikp,'  ndiv=',(ndiv(ii,ikp),ii=1,3)
          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
C         write (6,*) ' Found: ikp=',ikp
          goto 14
   13   enddo
C ---   haven't try anything with inversion as well;
        write (6,*) ' No irreducible k-point found ',
     .              ' for k-grid point (',idiv1,'/',mdiv1,',   ',
     .             idiv2,'/',mdiv2,',   ',idiv3,'/',mdiv3,'  ) .'
        write (6,*) ' Are you sure your k-grid was without shift?'
        stop
   14   continue
      enddo
      enddo
      enddo

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)")    mdiv1+1, mdiv2+1, mdiv3+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,(mdiv1+1)*(mdiv2+1)*(mdiv3+1))
        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
      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 ...........................................................

Reply via email to