clsgenimp12.f Source File


Source Code

c ************************************************************************
      SUBROUTINE CLSGENIMP12(
     >        NUMIMP,RIMPURITY,NKILLATOM,RKILL,
     >        CLS,NCLS,NACLS,ATOM,RCLS,
     >        BRAVAIS,RECBV,NAEZ,RBASIS,RCUTZ,RCUTXY,
     <        CLSIMP,NCLSIMP,NACLSIMP,ATOMIMP,RCLSIMP,RMTHLFIMP)
      implicit none
c#@# KKRtags: VORONOI KKRimp geometry
c ************************************************************************
c This subroutine is used to create the clusters around each atom 
c where in order to prepare the shape functions and produce povray 
c input files. (Based on clsgen99.f)
c
c STRATEGY : 
c Calculate the cluster of each atom by the lattice
c parameters avaliable. Sort the atoms in a unique way :big r, big z, big y
c compare the positions with the previous clusters to see if there is 
c a difference. If not keep only previous clusters and make indexing if
c a new cluster is found then check dimensions and continue for the new
c atom.  
c
c
      include 'inc.geometry'    
c
c
c     .. arguments
c
c
      
      INTEGER
     +     CLS(*),                  ! sort of cluster around atom
     +     NACLS(*),                ! number of atoms in cluster
     +     ATOM(NACLSD,*)           ! Index to atom in elem/cell at site in cluster
c Input:
      INTEGER NAEZ                    ! number of host-basis atoms
      INTEGER NUMIMP                  ! Number of impurity atoms
      INTEGER NKILLATOM               ! Number of host-sites to be "killed"
      INTEGER NCLS                    ! number of different host clusters
c 
      REAL*8 BRAVAIS(3,3),RECBV(3,3)  ! Bravais vectors of real and reciprocal lattice
      REAL*8 RBASIS(3,*)              ! Positions of host-basis atoms
      REAL*8 RIMPURITY(3,*)           ! positions of impurity sites
      REAL*8 RCLS(3,NACLSD,*)         ! real space position of atom in host cluster
      REAL*8 RKILL(3,*)               ! Positions of sites to be "killed"
      REAL*8 RCUTXY,RCUTZ             ! Cutoff radius of cluster
      
c
c Output:
      INTEGER NCLSIMP                     ! Number of inequivalent clusters
      INTEGER NACLSIMP(*)                 ! Number of sites in each cluster
      INTEGER CLSIMP(*)                   ! Type of cluster of each atom
      INTEGER ATOMIMP(NACLSD,*)           ! Index to atom in elem/cell at site in cluster
      REAL*8 RCLSIMP(3,NACLSD,*)          ! real space position of atom in imp. cluster
      REAL*8 RMTHLFIMP(NIMPD)             ! Muffin tin radius by bisection to nearest neighbour
c
c Local:
      INTEGER IATOM(NACLSD),ATOM1(NACLSD) ! Atom-index in cluster 
      INTEGER ISORT(NACLSD)           ! Auxiliary array for sorting clusters
      INTEGER NIMPCLS ! Number of atoms in impurity cluster
      INTEGER IIMP,JIMP,IBASIS,JKILL,JVEC,IX,NB1,NB2,NB3,ICLS,JCLS,POS
     +     ,IA,IN,IB,IAT,I1
      INTEGER NEAREST                 ! Nearest found host-basis to certain imp-atom
      REAL*8 RG(3,NACLSD),RS1(NACLSD)             ! Auxiliary array for sorting clusters
      REAL*8 RSORT(NACLSD)            ! Parameter for sorting sites in cluster
      REAL*8 RLATT(3)                 ! Lattice vector
      REAL*8 RNEAREST(3)              ! Position of nearest host-atom to imp-atom
      REAL*8 RCURRENT(3)              ! Position of a site.
      REAL*8 DISTSQ,DISTMINSQ         ! Distance**2 between atoms
      REAL*8 TOLIMP                   ! If imp. atom is closer than this to host atom, 
                                      ! it is considered to replace it
      

      LOGICAL LACCEPT,LFOUND ! Accept-flag,Found-flag
c
      REAL*8 EPSSHL,DELTA(3),RCLS1(3,NACLSD)
      REAL*8 RCUT2,RCUTXY2,R2
c
      LOGICAL  L2DIM,CLUSTCOMP_VORONOI
      CHARACTER*256 UIO
      INTEGER IER
c
c
      LOGICAL TEST,OPT
      EXTERNAL DSORT,CLUSTCOMP_VORONOI,IOINPUT
      INTRINSIC MIN,SQRT
c
      DATA     EPSSHL   / 1.0D-4 /
      DATA     TOLIMP   / 1.D-6  / 


      WRITE(6,*) 
     &     '>>> CLSGENIMP_KKRFLEX: generation of cluster coordinates'

c  Cutoffs for max. cluster radius
      RCUTXY2 = (RCUTXY+EPSSHL)*(RCUTXY+EPSSHL)
      RCUT2   = (RCUTZ+EPSSHL)*(RCUTZ+EPSSHL)
      RCUT2 = MAX(RCUTXY2,RCUT2)

c Initialize number of non-equivalent impurity clusters.
      NCLSIMP = 0

      CALL IoInput('TOLIMP          ',UIO,1,7,IER)
      IF (IER.EQ.0) READ (UNIT=UIO,FMT=*) TOLIMP
      ! Default is set by data-statement above.

c
c Strategy:
c Loop over impurities
c   1  Find a near crystal point to impurity (preferably the nearest)
c   2  Span cluster of all impurities
c   3  Span host-cluster around this crystal point
c   -  Exclude common points of host and impurity
c   -  Exclude "killed atoms".
c   4  Center cluster around impurity.
c End loop over impurities
c

      DO 999 IIMP = 1,NUMIMP   ! Loop over impurities

c 1  Find closest lattice point to impurity. 
c Use reciprocal lattice vectors (remember they are given in units 2 pi/a).
c   
      NB1 = NINT( RIMPURITY(1,IIMP)*RECBV(1,1) + 
     &            RIMPURITY(2,IIMP)*RECBV(2,1) + 
     &            RIMPURITY(3,IIMP)*RECBV(3,1)   )
      NB2 = NINT( RIMPURITY(1,IIMP)*RECBV(1,2) + 
     &            RIMPURITY(2,IIMP)*RECBV(2,2) + 
     &            RIMPURITY(3,IIMP)*RECBV(3,2)   )
      NB3 = NINT( RIMPURITY(1,IIMP)*RECBV(1,3) + 
     &            RIMPURITY(2,IIMP)*RECBV(2,3) + 
     &            RIMPURITY(3,IIMP)*RECBV(3,3)   )
      DO IX = 1,3
         RLATT(IX) = NB1 * BRAVAIS(IX,1) + 
     &               NB2 * BRAVAIS(IX,2) + NB3 * BRAVAIS(IX,3)
         DELTA(IX) = RIMPURITY(IX,IIMP) - RLATT(IX)
      ENDDO
c
c The closest lattice point is RLATTT = NB1 * Bravais1 + NB2 * Bravais2 + NB3 * Bravais3.
c The impurity position relative to this point is DELTA.
c Now find nearest basis vector relative to this lattice point.
c
      NEAREST = 1
      DISTMINSQ = 1.D10
      DO IBASIS = 1,NAEZ
         DISTSQ = (DELTA(1) - RBASIS(1,IBASIS))**2 + 
     &            (DELTA(2) - RBASIS(2,IBASIS))**2 +
     &            (DELTA(3) - RBASIS(3,IBASIS))**2
         IF (DISTSQ.LT.DISTMINSQ) THEN
            NEAREST = IBASIS
            DISTMINSQ = DISTSQ
         ENDIF
      ENDDO

      RNEAREST(:) = RLATT(:) + RBASIS(:,NEAREST)
c
c
c 2  Span impurity-cluster around impurity.
c
      NIMPCLS = 1 ! Initialize number of sites in cluster
      RCLS1(:,1) = RIMPURITY(:,IIMP) ! First vector is always the site itself.

      DO JIMP = 1,NUMIMP  ! Loop over (other) impurities
         LACCEPT = .TRUE.
         DISTSQ = (RIMPURITY(1,IIMP) - RIMPURITY(1,JIMP))**2 +
     &            (RIMPURITY(2,IIMP) - RIMPURITY(2,JIMP))**2 +
     &            (RIMPURITY(3,IIMP) - RIMPURITY(3,JIMP))**2
         IF (DISTSQ.GT.RCUT2) LACCEPT = .FALSE. ! Impurity site is considered to be too far away
         IF (IIMP.EQ.JIMP) LACCEPT = .FALSE.    ! Avoid self
         IF (LACCEPT) THEN
            NIMPCLS = NIMPCLS + 1                   ! Add to cluster one more site...
            RCLS1(:,NIMPCLS) = RIMPURITY(:,JIMP)    ! ... and its coordinates
            ATOM1(NIMPCLS) = NAEZ + JIMP            ! Index to store what kind of atoms are in the cluster.
                                                    ! (value between 1 and NAEZ refers to host)
         ENDIF
      ENDDO
c
c 3  Span host-cluster around impurity excluding common atoms with impurity-cluster and killed atoms.
c
      DO JVEC = 1,NACLS(CLS(NEAREST))    ! Loop over cluster-sites of nearest host-atom
                                         ! Remember, CLS(I) is the cluster-index of basis-atom I.
         RCURRENT(:) = RNEAREST(:) + RCLS(:,JVEC,CLS(NEAREST))  ! RCLS is the "reduced" position w.resp.
                                                                ! to cluster-center. For JVEC=1, RCLS=(0,0,0).
         LACCEPT = .TRUE.

C        Check if host atom is identical with any of the impurities
         DO JIMP = 1,NUMIMP       ! Loop over impurity atoms 
            DISTSQ = (RCURRENT(1) - RIMPURITY(1,JIMP))**2 +
     &               (RCURRENT(2) - RIMPURITY(2,JIMP))**2 +
     &               (RCURRENT(3) - RIMPURITY(3,JIMP))**2
            IF (DISTSQ.LT.TOLIMP) LACCEPT = .FALSE. ! Host site is considered identical with impurity site
         ENDDO

C        Check if host atom is identical with any of the killed atoms
         DO JKILL = 1,NKILLATOM    ! Loop over killed atoms 
            DISTSQ = (RCURRENT(1) - RKILL(1,JKILL))**2 +
     &               (RCURRENT(2) - RKILL(2,JKILL))**2 +
     &               (RCURRENT(3) - RKILL(3,JKILL))**2
            IF (DISTSQ.LT.1.D-8) LACCEPT = .FALSE. ! Host site is considered identical with killed site
         ENDDO

c        Check if host atom is too far from current impurity.
         DISTSQ = (RCURRENT(1) - RIMPURITY(1,IIMP))**2 +
     &            (RCURRENT(2) - RIMPURITY(2,IIMP))**2 +
     &            (RCURRENT(3) - RIMPURITY(3,IIMP))**2
         IF (DISTSQ.GT.RCUT2) LACCEPT = .FALSE. ! Host site is considered too far away


         IF (LACCEPT) THEN
            NIMPCLS = NIMPCLS + 1
            RCLS1(:,NIMPCLS) = RCURRENT(:)
            ATOM1(NIMPCLS) = ATOM(JVEC,NEAREST)    ! Index to store what kind of atoms are in the cluster.
         ENDIF

      ENDDO

c Now the impurity IIMP has a cluster of NIMPCLS sites around it, with positions at RCLS1.
c Store number of sites in array NACLSIMP.
      NACLSIMP(IIMP) = NIMPCLS
c 4   Center cluster around impurity (coordinate shift)
      DO JVEC = 1,NIMPCLS
         RCLS1(:,JVEC) = RCLS1(:,JVEC) - RIMPURITY(:,IIMP)
      ENDDO

c-------------------------------------------------------------------------------------
c sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort 
c Sort cluster sites according to: radius, then z, then y, then x.
      DO IA = 1,NIMPCLS
         RSORT(IA) = SQRT(RCLS1(1,IA)**2+RCLS1(2,IA)**2+RCLS1(3,IA)**2)
         RSORT(IA) = 100000000.D0*RSORT(IA)+
     &                  100000.D0*RCLS1(3,IA)+
     &                     100.D0*RCLS1(2,IA)+
     &                      0.1D0*RCLS1(1,IA)
      ENDDO      
C     

      CALL DSORT(RSORT,ISORT,NIMPCLS,POS)
c     Rearange exchange IA with IB
c     Map temporarily to another array         
      DO IA = 1,NIMPCLS       
         RG(:,IA) = RCLS1(:,IA)
         IATOM(IA) = ATOM1(IA)
         RS1(IA) = RSORT(IA)
      END DO    
c     Now use correct order
      DO IA = 1,NIMPCLS
         IB = ISORT(IA)
         RCLS1(:,IA) = RG(:,IB)
         ATOM1(IA) = IATOM(IB)
         RSORT(IA) = RS1(IB)
      END DO


c sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort sort  
c-------------------------------------------------------------------------------------
c
c Store array ATOM1. The I'th site of cluster around IIMP contains atom-type ATOMIMP(I,IIMP).
c Remember, the indexing contains first all host-basis atoms, then all impurity atoms.
      ATOMIMP(:,IIMP) = ATOM1(:)


c-------------------------------------------------------------------------------------
c    Now compare new cluster to previously found and keep only if different.

      LFOUND = .FALSE.
      DO ICLS = 1,NCLS                     ! First check host-clusters
         IF ( CLUSTCOMP_VORONOI(RCLS,ICLS,NACLS(ICLS),RCLS1,NIMPCLS) ) 
     &      THEN
            CLSIMP(IIMP) = ICLS            ! Impurity IIMP is mapped to host cluster index
            LFOUND = .TRUE.
         ENDIF
      ENDDO

      IF (.NOT.LFOUND) THEN                ! Now check impurity clusters
         DO ICLS = 1,NCLSIMP
            IF ( CLUSTCOMP_VORONOI(RCLSIMP,ICLS,
     &              NACLSIMP(ICLS),RCLS1,NIMPCLS) ) THEN  ! Cluster has been found before
               CLSIMP(IIMP) = ICLS + NCLS ! Impurity IIMP is mapped to imp. cluster index
               LFOUND = .TRUE.                
         ENDIF
      ENDDO
      ENDIF

      IF (.NOT.LFOUND) THEN                ! New cluster
         NCLSIMP = NCLSIMP + 1             ! Number of new clusters due to imp.
         CLSIMP(IIMP) = NCLSIMP + NCLS     ! Impurity IIMP is mapped to cluster index;
                                           ! plus NCLS to have a unified indexing of clusters
         NACLSIMP(NCLSIMP) = NIMPCLS       ! Number of atoms in this cluster
         RCLSIMP(:,:,NCLSIMP) = RCLS1(:,:) ! Positions in cluster
      END IF

c     All different clusters have been found
c-------------------------------------------------------------------------------------



 999  ENDDO                     ! IIMP = 1,NUMIMP     ! Loop over impurities


c Write out some info.
      WRITE(*,*) '>>>>>>> Info from clsgenimp_kkrflex'
      DO IIMP = 1,NUMIMP
         WRITE(*,*) 
     &        'Impurity ',IIMP,' has cluster ',CLSIMP(IIMP),
     &        ' with ',NACLSIMP(IIMP),' sites.'
      ENDDO


c Compare impurity clusters with host clusters for chek reasons.

      DO ICLS = 1,NCLSIMP       ! Loop over impurity clusters
         DO JCLS = 1,NCLS       ! Loop over host clusters
            IF ( CLUSTCOMP_VORONOI(RCLSIMP,ICLS,NACLSIMP(ICLS),
     &                     RCLS(1,1,JCLS),NACLS(JCLS))    ) 
     &           WRITE(*,*) 'Impurity cluster ',ICLS,
     &           ' is geometrically identical with host cluster ',JCLS
         ENDDO                  ! JCLS = 1,NCLS
      ENDDO                     ! ICLS = 1,NCLSIMP


c Now the cluster vectors are contained in the array RCLSIMP
c and the number of sites in the cluster in NACLSIMP.

! Find the muffin-tin of each atom by bisection of the distance to the
! nearest atom
      DO IIMP = 1,NUMIMP
         DISTMINSQ = 1.D100
         ICLS = CLSIMP(IIMP)
         DO JVEC = 2,NACLSIMP(ICLS)
            R2 = RCLSIMP(1,JVEC,ICLS)**2 + RCLSIMP(2,JVEC,ICLS)**2 + 
     &                                     RCLSIMP(3,JVEC,ICLS)**2
            IF (R2.LT.DISTMINSQ) DISTMINSQ = R2
         ENDDO
         RMTHLFIMP(IIMP) = DSQRT(DISTMINSQ)/2.D0
      ENDDO

      WRITE(6,*) ' Sub clsgen99  exiting <<<<<<<<<<<<<'

c ------------------------------------------------------------------------


c
c ------------------------------------------------------------------------

 1000   format(' cluster around atom     ',10I4/,
     +         ' number atoms in cluster ',10I4)
 1001   format(I4,2I5,3F8.2,I6,4f7.2)
 1002   format(' cocls : naez =',I3,' (x,y,z)= ',3F10.4)
 1010   format(12x,I6,3F10.4)
 1020   format('  Nr  naez kaoez     x       y       z',
     +         '  ezoa  RR(1)  RR(2)  RR(3)      R')
 1030   FORMAT(3I8)
 1040   FORMAT('Cu  ',3D24.16,2I8,F18.12)
 1050   FORMAT(3F12.7,'  scaling factor')
 1060   FORMAT(I4,3F12.7,'  center',/,(I4,3f12.7))
 1070   FORMAT(I4,3F12.7,'  center of gravity')
 1080   FORMAT('contains ',I4,'  atoms.')
 9005   FORMAT(I4)
 9010   FORMAT(('# Z     ',20F4.0))
 9020   FORMAT(('# KAOEZ ',20I4))
 9030   FORMAT(F12.7,6x,'ALAT')
 9040   FORMAT('> cluster ',I4,' at atom ',I4,
     +       ' of type ',I4,'.')
 9050   FORMAT('      **** COUPLING MATRIX ****',I3,' x ',I3)
 9060   FORMAT(I4,1X,200I1)
 9080   FORMAT(I6,3F15.6)
 9090   FORMAT('The Number of layers is each Principal Layer = ',
     &                I5)
 8000   format('sphere { ')
 8010   format ('<',F10.5,',',F10.5,',',F10.5,'> ,')
 8011   format ('<',F10.5,',',F10.5,',',F10.5,'> ')
 8020   format (F10.5)
 8030   format(' texture { ')
 8040   format('  pigment { color ',A24,' } } } ')
 8050   format('  pigment { color ',A24,'  } ')
c
 8500  format('cylinder { ')
 8502  format(F10.5)
 8503  format(' texture { pigment { color Red }}}')
c
 8099   format('polygon { ' /
     &    I5 ,',')
 8102  format('pigment { color rgb <1, 0, 0> transmit .95 } }')
 8200  format('camera {' /
     & '   location < 4 , 3, -4 > ' /
     & '   look_at < 0, 0, -1 > }')
 8201  format('#include "colors.inc" ' /
     &      ' background {color White }')
 8202  format(' light_source { < 5, 3, -10 > color White }')
 8203  format(' light_source { < 4, 8, 10 > color Red }')
 8600  format('finish{ ambient 0 '/
     &        '        diffuse 0 '/
     &        '        reflection 0.25 '/
     &        '        roughness 0.001 }}')
c             'interior{ior 1.33} }' )
      RETURN
      END