voronoi12.f Source File


Source Code

c***********************************************************************
      SUBROUTINE VORONOI12(
     >  NVEC,RVEC,NVERTMAX,NFACED,WEIGHT0,WEIGHT,TOLVDIST,TOLAREA,TOLHS,
     <  RMT,ROUT,VOLUME,NFACE,A3,B3,C3,D3,NVERT,XVERT,YVERT,ZVERT,
     <  VCENTER)
c Given a cluster of atomic positions at RVEC(3,NVEC), this subroutine
c returns information about the Voronoi cell around the origin. It is
c supposed, of course, that the origin corresponds to an atomic position
c which is not included in the RVEC(3,N). The information returned is:
c
c RMT: Muffin-tin radius (radius of inscribed sphere centered at the 
c      origin).
c
c ROUT: Radius of circumscribed sphere centered at the origin.
c
c VOLUME: Volume of the Voronoi cell. 
c
c NFACE: Number of faces of the cell.
c
c A3(NFACE),B3(NFACE),C3(NFACE),D3(NFACE): Coefficients defining the
c faces via A3*x+B3*y+C3*z=D3. The arrays are filled in the first
c NFACE positions with the information, the rest can be garbage.
c
c NVERT(NFACE): Number of vertices corresponting to each face.
c
c XVERT(NVERTMAX,NFACE),YVERT(NVERTMAX,NFACE),ZVERT(NVERTMAX,NFACE): 
c Coordinates of theese vertices.
c
c The Voronoi construction performed here allows for different than
c 50%/50% bisections. For this, each atomic site, positioned say at
c vector r(i), is assigned a weight w(i). Then a point r in space
c belongs to the cell i if, for all j, 
c |r-r(i)|**2 - w(i) < |r-r(j)|**2 - w(j).    (1)
c The points for which the inequality becomes an equality is the 
c bisector, and it can be easily shown that it is a plane perpendicular
c to the vector r(j)-r(i).
c One can parametrize the segment connecting r(i) and r(j) using a
c parameter t, 0 < t < 1. For t=0 we are at r(i), for t=1 at r(j), and
c in-between we have a linear dependence of the distance from r(i) with
c t. I.e., the position vector is r = r(i)*(1-t) + r(j)*t.
c The point where the bisector cuts this segment will then be at
c t=(1/2)*( (w(i)-w(j))/dist**2 + 1 )         (2)
c where dist is the distance of the two points. As a special case we see
c that, for w(i)=w(j), the bisector will be in the middle, else the
c atomic site with the bigger weight gains more space.
c
c The above procedure is guaranteed to divide space into tesselating 
c (:=space-filling) convex polyhedra (one of their sides could be at 
c infinity in special cases). The convexity of the polyhedra is 
c guaranteed by the constuction, i.e. as mutual cut of half-spaces, and
c the property of tesselation is guaranteed by the fact that every point
c in space is assigned to some atom.
c
c However, this procedure might place the polyhedron in such a way that
c its own atomic site is not contained in it. This can happen if there
c is a big enough difference in the weights, whence, from eq.(2) above,
c t can become <0 or >1 (then the bisector has passed one of the two
c points). This cannot be allowed in a KKR calculation, and therefore
c each time it is checked that this is not the case. If such a case
c occurs, a different set of weights must be chosen.
c
c
c Uses subroutines NORMALPLANE, POLYHEDRON, and function DISTPLANE.
      implicit none
c#@# KKRtags: VORONOI geometry
c Input:
      INTEGER  NVEC,NVERTMAX,NFACED
      REAL*8   RVEC(3,NFACED)
      REAL*8   WEIGHT0,WEIGHT(NFACED)  ! Weight of central atom, 
c                          !   and of all others (dimensioned as RVEC). 
      REAL*8  TOLVDIST              ! Max. tolerance for distance of two vertices
      REAL*8  TOLAREA               ! Max. tolerance for area of polygon face
      REAL*8  TOLHS                 ! Tolerance for halfspace routine
c Output:
      INTEGER NFACE
      INTEGER NVERT(*)
      REAL*8              VOLUME,VCENTER(3)
      REAL*8              A3(NFACED),B3(NFACED),C3(NFACED),D3(NFACED)
      REAL*8              XVERT(NVERTMAX,NFACED),YVERT(NVERTMAX,NFACED),
     &                    ZVERT(NVERTMAX,NFACED)
      REAL*8              RMT,ROUT
c Inside:
      INTEGER IVEC,IFACE,IVERT,I,NVERTTOT
      INTEGER NPLANE
      REAL*8           X1,Y1,Z1,X2,Y2,Z2,X3,Y3,Z3,TETRVOL,RSQ,TAU
      REAL*8           FACEAREA(NFACED),TRIANGLEAREA   
      REAL*8           TEMP
      REAL*8           DISTPLANE          ! Function used.
      INTEGER ISORT(NFACED),POS,INEW    ! Index for sorting
      REAL*8 RSORT(4,NFACED)              ! Aux. function for sorting
      REAL*8 ATMP(NFACED),BTMP(NFACED),CTMP(NFACED),DTMP(NFACED) ! For sorting
      REAL*8 XVTMP(NVERTMAX,NFACED),YVTMP(NVERTMAX,NFACED)       ! For sorting
      REAL*8 ZVTMP(NVERTMAX,NFACED)                              ! For sorting
      INTEGER NVTMP(NFACED)                                      ! For sorting
      INTEGER NPANEL
      LOGICAL TEST  ! test options

c---------------------------------------------------------------
c Check that the origin is not included in RVEC.
      DO IVEC = 1,NVEC
         IF (DABS(RVEC(1,IVEC))+DABS(RVEC(2,IVEC))+DABS(RVEC(3,IVEC))
     &                                               .LT.1.D-12) THEN
            WRITE(*,*) 'VORONOI: Vector',IVEC,'is zero.'
            STOP 'VORONOI'
         ENDIF
      ENDDO
c---------------------------------------------------------------
c Define the planes as normal to the vectors RVEC, passing from t as
c in eq. (2) above:
      DO IVEC = 1,NVEC
         RSQ = RVEC(1,IVEC) * RVEC(1,IVEC)
     &       + RVEC(2,IVEC) * RVEC(2,IVEC)
     &       + RVEC(3,IVEC) * RVEC(3,IVEC)
         TAU = 0.5D0*((WEIGHT0-WEIGHT(IVEC))/RSQ + 1.D0)
         CALL NORMALPLANE0(
     >                    RVEC(1,IVEC),RVEC(2,IVEC),RVEC(3,IVEC),TAU,
     <                    A3(IVEC),B3(IVEC),C3(IVEC),D3(IVEC))
      ENDDO
c---------------------------------------------------------------
c Find the Voronoi polyhedron.
      NPLANE = NVEC
      IF (TEST('verb1   ')) WRITE(*,*) 'Entering POLYHEDRON08'
      CALL POLYHEDRON08(
     >                  NPLANE,NVERTMAX,NFACED,TOLVDIST,TOLAREA,
     X                  TOLHS,A3,B3,C3,D3,
     <                  NFACE,NVERT,XVERT,YVERT,ZVERT)
      IF (TEST('verb1   ')) WRITE(*,*) 'Exited POLYHEDRON08'

c---------------------------------------------------------------
c Calculate the volume as sum of the volumes of all tetrahedra 
c connecting the origin to the faces. Use for each tetrahedron
c volume = det((r0-r1),(r0-r2),(r0-r3))/6, where r0 is here the
c origin and r1,r2,r3 the vectors of the 3 other vertices.
c Algorithm requires that the face is a convex polygon with the 
c vertices ordered (doesn't matter if they are clock- or anticlockwise).
      VOLUME = 0.d0
      VCENTER(1) = 0.d0
      VCENTER(2) = 0.d0
      VCENTER(3) = 0.d0
      DO IFACE = 1,NFACE
         X1 = XVERT(1,IFACE)
         Y1 = YVERT(1,IFACE)
         Z1 = ZVERT(1,IFACE)
         FACEAREA(IFACE) = 0.d0
         DO IVERT = 2,NVERT(IFACE)-1
            X2 = XVERT(IVERT,IFACE)
            Y2 = YVERT(IVERT,IFACE)
            Z2 = ZVERT(IVERT,IFACE)
            X3 = XVERT(IVERT+1,IFACE)
            Y3 = YVERT(IVERT+1,IFACE)
            Z3 = ZVERT(IVERT+1,IFACE)
            TETRVOL = X1*(Y2*Z3-Y3*Z2)+X2*(Y3*Z1-Y1*Z3)+X3*(Y1*Z2-Y2*Z1)
            VCENTER(1) = VCENTER(1) + 0.25d0*DABS(TETRVOL)*(X1+X2+X3)
            VCENTER(2) = VCENTER(2) + 0.25d0*DABS(TETRVOL)*(Y1+Y2+Y3)
            VCENTER(3) = VCENTER(3) + 0.25d0*DABS(TETRVOL)*(Z1+Z2+Z3)
            VOLUME = VOLUME + DABS(TETRVOL)
            TRIANGLEAREA = 0.5d0 * DSQRT(
     &           ( X1*Y2 + X2*Y3 + X3*Y1 - Y2*X3 - Y3*X1 - Y1*X2)**2
     &         + ( Y1*Z2 + Y2*Z3 + Y3*Z1 - Z2*Y3 - Z3*Y1 - Z1*Y2)**2
     &         + ( Z1*X2 + Z2*X3 + Z3*X1 - X2*Z3 - X3*Z1 - X1*Z2)**2 )
! wrong           TRIANGLEAREA = 0.5d0 * DABS(
!     &           (X2-X1)*(X3-X1)+(Y2-Y1)*(Y3-Y1)+(Z2-Z1)*(Z3-Z1) )
            FACEAREA(IFACE) = FACEAREA(IFACE)+ TRIANGLEAREA
         ENDDO
      ENDDO
      VOLUME = VOLUME/6.D0
      VCENTER(1) = VCENTER(1)/VOLUME
      VCENTER(2) = VCENTER(2)/VOLUME
      VCENTER(3) = VCENTER(3)/VOLUME

      WRITE(6,*) ' Polyhedron properties '

      WRITE(6,*) ' Number of faces : ',nface

      IF (TEST('verb0   ')) THEN
      DO IFACE=1,NFACE
         WRITE(6,201) IFACE,NVERT(IFACE),FACEAREA(IFACE)
 201     FORMAT(' Face ',I4,'   has ',I4,' vertices ','; Area= ',E12.4)  
         DO IVERT=1,NVERT(IFACE)
            WRITE(*,9000) IVERT,XVERT(IVERT,IFACE),YVERT(IVERT,IFACE)
     &                ,ZVERT(IVERT,IFACE)
         ENDDO
         WRITE(*,9010) A3(IFACE),B3(IFACE),C3(IFACE),D3(IFACE)
      END DO 
      ENDIF

      WRITE(6,*) 'The Volume is : ',VOLUME

 9000 FORMAT(I5,4E16.8)
 9010 FORMAT(' Face coefficients:',4E16.8)
c---------------------------------------------------------------
c Find RMT:
      RMT = DISTPLANE(A3(1),B3(1),C3(1),D3(1))
      DO IFACE = 2,NFACE
         TEMP = DISTPLANE(A3(IFACE),B3(IFACE),C3(IFACE),D3(IFACE))
         IF (TEMP.LT.RMT) RMT = TEMP
      ENDDO
c Fint ROUT:
      ROUT = 0.D0
      DO IFACE = 1,NFACE
         DO IVERT = 1,NVERT(IFACE)
            TEMP = XVERT(IVERT,IFACE)*XVERT(IVERT,IFACE) 
     &           + YVERT(IVERT,IFACE)*YVERT(IVERT,IFACE)
     &           + ZVERT(IVERT,IFACE)*ZVERT(IVERT,IFACE)
            IF (TEMP.GT.ROUT) ROUT = TEMP
         ENDDO
      ENDDO
      ROUT = DSQRT(ROUT)
      WRITE(*,9020) RMT,ROUT,RMT*100/ROUT
 9020 FORMAT('Voronoi subroutine: RMT=',E16.8,'; ROUT=',E16.8,
     &       '; RATIO=',F12.2,' %')
c---------------------------------------------------------------
c Sort faces:
      DO IFACE = 1,NFACE
         RSORT(1,IFACE) = 
     &        DISTPLANE(A3(IFACE),B3(IFACE),C3(IFACE),D3(IFACE))
         RSORT(2,IFACE) = C3(IFACE) 
         RSORT(3,IFACE) = B3(IFACE) 
         RSORT(4,IFACE) = A3(IFACE) 
      ENDDO
!      CALL DSORT(RSORT,ISORT,NFACE,POS)

      CALL DSORT_NCOMP(RSORT,4,.FALSE.,ISORT,NFACE,POS)
c     Rearrange using a temporary array
      ATMP(:) = A3(:)
      BTMP(:) = B3(:)
      CTMP(:) = C3(:)
      DTMP(:) = D3(:)
      XVTMP(:,:) = XVERT(:,:)
      YVTMP(:,:) = YVERT(:,:)
      ZVTMP(:,:) = ZVERT(:,:)
      NVTMP(1:NFACE) = NVERT(1:NFACE)
      DO IFACE = 1,NFACE
         INEW = ISORT(IFACE)
         A3(INEW) = ATMP(IFACE)
         B3(INEW) = BTMP(IFACE)
         C3(INEW) = CTMP(IFACE)
         D3(INEW) = DTMP(IFACE)
         XVERT(:,INEW) = XVTMP(:,IFACE)
         YVERT(:,INEW) = YVTMP(:,IFACE)
         ZVERT(:,INEW) = ZVTMP(:,IFACE)
         NVERT(INEW) = NVTMP(IFACE)
      ENDDO
c---------------------------------------------------------------


      RETURN
      END