shellgen2k.f90 Source File


Source Code

!-----------------------------------------------------------------------------------------!
! Copyright (c) 2018 Peter Grünberg Institut, Forschungszentrum Jülich, Germany           !
! This file is part of Jülich KKR code and available as free software under the conditions!
! of the MIT license as expressed in the LICENSE.md file in more detail.                  !
!-----------------------------------------------------------------------------------------!

!------------------------------------------------------------------------------------
!> Summary: Determines the number of different atomic pairs in a cluster by symmetry considerations
!> Author: 
!> Determines the number of different atomic pairs in a cluster by symmetry considerations
!> assigning a "shell" pointer (used to set up the GF matrix), to each representative pair.
!------------------------------------------------------------------------------------
module mod_shellgen2k
  use mod_datatypes, only: dp
  private dp

contains

  !-------------------------------------------------------------------------------
  !> Summary: Determines the number of different atomic pairs in a cluster by symmetry considerations
  !> Author:
  !> Category: geometry, input-output, KKRhost
  !> Deprecated: False 
  !> Determines the number of different atomic pairs in a cluster by symmetry considerations
  !> assigning a "shell" pointer (used to set up the GF matrix), to each representative pair.
  !-------------------------------------------------------------------------------
  subroutine shellgen2k(icc,natom,rcls,atom,nofgij,iofgij,jofgij,nrot,rsymat,       &
    isymindex,rotname,nshell,ratom,nsh1,nsh2,ish,jsh,ijtabsym,ijtabsh,ijtabcalc,    &
    iprint,nsheld,natomd)
    ! **********************************************************************
    ! *    Determines the number of different atomic pairs in a cluster by *
    ! * symmetry considerations, assigning a "shell" pointer (used to set  *
    ! * up the GF matrix), to each representative pair.                    *
    ! *                                                                    *
    ! * NATOM       number of atoms in the cluster                         *
    ! * RCLS(3,*)   atom positions in the cluster                          *
    ! * ATOM(*)     corresponding site index in the unit cell              *
    ! * NROT        actual number of symmetry operations                   *
    ! * RSYMAT      symmetry operation matrices                            *
    ! * ISYMINDEX   symmetry operation pointer                             *
    ! * NSHELD      dimension parameter ( max number of different shells)  *
    ! * IJTABCALC   flag to calculate the pair (I,J) - 1/0 for YES/NO      *
    ! *             (e.g. for impurity calc IJTABCALC(I,J) = 1 - delta_ij) *
    ! * NOFGIJ      total number of ij pairs (equals number of non-zero    *
    ! *             IJTABCALC elements                                     *
    ! * IOFGIJ      cluster indices i for pair ij                          *
    ! * JOFGIJ                      j for pair ij                          *
    ! *                                                                    *
    ! * NSHELL(0)   number of different shells (ij pairs)                  *
    ! * NSHELL(NS)  number of equivalent pairs in shell NS                 *
    ! * NSH1(NS),                                                          *
    ! * NSH2(NS)    site indices i,j of shell (representative pair) NS     *
    ! * ISH/JSH     cluster indices i,j of all NSHELL(NS) equivalent pairs *
    ! described by shell NS                                  *
    ! * IJTABSH     the index of the representative shell NS for G_ij      *
    ! * IJTABSYM    the index of the symmetry operation which brings G(NS) *
    ! *             into G_ij                                              *
    ! * RATOM(3,NS) diference vector R_i(NS) - R_j(NS)                     *
    ! *                                                                    *
    ! **********************************************************************
    use mod_constants, only: nsymaxd 
    use mod_runoptions, only: calc_exchange_couplings
    implicit none
    ! ..
    ! .. Scalar arguments
    integer, intent(inout) :: icc
    integer, intent(in) :: natom
    integer, intent(in) :: nofgij
    integer, intent(in) :: nrot
    integer, intent(in) :: iprint
    integer, intent(in) :: nsheld
    integer, intent(in) :: natomd

    ! ..
    ! .. Array arguments
    integer, dimension(natom**2),  intent(in) :: ijtabcalc !! Linear pointer, specifying whether the block (i,j) has to be calculated needs set up for ICC=-1, not used for ICC=1
    integer, dimension(natomd),  intent(in) :: atom
    integer, dimension(nsymaxd), intent(in) :: isymindex
    integer, dimension(nofgij),  intent(in) :: iofgij
    integer, dimension(nofgij),  intent(in) :: jofgij
    integer, dimension(natom**2), intent(out) :: ijtabsym
    integer, dimension(natom**2), intent(out) :: ijtabsh
    integer, dimension(nsheld, 2*nsymaxd), intent(out) :: ish
    integer, dimension(nsheld, 2*nsymaxd), intent(out) :: jsh
    integer, dimension(nsheld), intent(inout) :: nsh1
    integer, dimension(nsheld), intent(inout) :: nsh2
    integer, dimension(0:nsheld), intent(inout) :: nshell
    
    real (kind=dp), dimension(3, natomd), intent(in) :: rcls
    real (kind=dp), dimension(64, 3, 3), intent(in) :: rsymat
    real (kind=dp), dimension(3, nsheld), intent(inout) :: ratom

    character (len=10), dimension(64), intent(in) :: rotname
    ! ..
    ! .. Local scalars
    integer :: ai, aj, i, j, k, ns, nsnew, nsgen, id, isym, ii, ij, igij
    real (kind=dp) :: r1, small
    logical :: lfound
    ! ..
    ! .. Local arrays
    real (kind=dp) :: ri(3), rj(3)
    integer, allocatable :: nsh1i(:), nsh2i(:), nshelli(:)
    real (kind=dp), allocatable :: ratomi(:, :)
    ! ..
    ! .. Data statements
    data small/1.0e-10_dp/
    ! ..

    ! OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OUTPUT
    write (1337, 120)
    if (iprint>1) call printijtab(natom, natom**2, ijtabcalc)
    ! OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OUTPUT

    if (nofgij<=0) then
      write (6, '(A)') '      ICC set to 0'
      write (6, '(A)') '         maybe you should check your input?'
      icc = 0                      ! Bauer Long 2011-10-11
      return
    end if
    allocate (nsh1i(nsheld), nsh2i(nsheld), nshelli(nsheld), stat=ns)
    if (ns/=0) stop '   < shellgen2k > allocate NSHELLI arrays'
    allocate (ratomi(3,nsheld), stat=ns)
    if (ns/=0) stop '   < shellgen2k > allocate RATOMI array'
    ! ======================================================================
    ! --> initialise number of shells found for this cluster, setup the
    ! working arrays NSH1I,NSH2I,NSHELLI,RATOMI and set the number of
    ! new found shells (NSNEW) to zero

    do i = 1, nshell(0)
      nsh1i(i) = nsh1(i)
      nsh2i(i) = nsh2(i)
      nshelli(i) = nshell(i)
      do j = 1, 3
        ratomi(j, i) = ratom(j, i)
      end do
    end do
    nsnew = 0

    ! **********************************************************************
    ! loop over I,J-pairs in cluster
    do igij = 1, nofgij

      ! --> search for a symmetric equivalent pair of atoms, LFOUND takes
      ! on the value false/true if this equivalent pair is found

      i = iofgij(igij)
      j = jofgij(igij)
      ! take only those shells that have atom in them
      if (i/=0 .or. j/=0) then
        ai = atom(i)
        aj = atom(j)

        lfound = .false.
        nsgen = nshell(0) + nsnew

        ! RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
        do id = 1, nrot
          isym = isymindex(id)
          ! ----------------------------------------------------------------------
          do ii = 1, 3
            ri(ii) = rsymat(isym, ii, 1)*rcls(1, i) + rsymat(isym, ii, 2)*rcls(2, i) + rsymat(isym, ii, 3)*rcls(3, i)

            rj(ii) = rsymat(isym, ii, 1)*rcls(1, j) + rsymat(isym, ii, 2)*rcls(2, j) + rsymat(isym, ii, 3)*rcls(3, j)
          end do
          ! ----------------------------------------------------------------------
          ! --> search for an equivalent pair within the already generated
          ! shells (1..NSHELL(0)+NSNEW)
          ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
          ns = 0
          do while ((.not. lfound) .and. (ns<nsgen))
            ns = ns + 1
            ! ----------------------------------------------------------------------
            ! IF ( ( AI.EQ.NSH1I(NS) .AND. AJ.EQ.NSH2I(NS) ).OR.
            ! &              ( AI.EQ.NSH2I(NS) .AND. AJ.EQ.NSH1I(NS) )  ) THEN
            ! Commented out by Phivos Mavropoulos 31 Oct 2008. The problem is that
            ! if (I,J) and (J,I)
            ! are assigned to the same shell, then G(I,J) should be transposed to
            ! obtain G(J,I).
            ! However, this transposition is not performed in account in kkr1b
            ! (subr. tbxccpljij).
            ! There, only the real-space rotations (DSYMLL) are performed to
            ! generate each pair GF from the
            ! representative pair, but the transposition is forgotten. Thus there
            ! are two ways to resolve this:
            ! Either flag the pairs to be transposed, which is is a little faster
            ! but complicated
            ! to program, or do not consider the (I,J) and (J,I) pairs as
            ! belonging to the same shell,
            ! which is done now:
            if ((ai==nsh1i(ns) .and. aj==nsh2i(ns))) then

              r1 = (ri(1)-rj(1)+ratomi(1,ns))**2 + (ri(2)-rj(2)+ratomi(2,ns))**2 + (ri(3)-rj(3)+ratomi(3,ns))**2

              if (r1<small) then
                lfound = .true.
                nshelli(ns) = nshelli(ns) + 1
                ! this check is only used for jij mode since otherwise ish/jsh arrays are not used anywhere
                if (calc_exchange_couplings) then
                  if (nshelli(ns)>2*nsymaxd) stop 'dimension error in shellgen2k: nshelli > 2*nsymaxd'
                  if (ns<=nshell(0)) write (1337, 130) ai, (rcls(ii,i), ii=1, 3), aj, (rcls(ii,j), ii=1, 3), ns
                  ish(ns, nshelli(ns)) = i
                  jsh(ns, nshelli(ns)) = j
                end if
              end if

            end if
            ! ----------------------------------------------------------------------
          end do                   ! while loop ns = 1..nsgen while .not.lfound
          ! ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        end do                     ! id=1, nrot
        ! RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR

        ! --> if the rotation and the representative pair (shell) that
        ! identify a pair of atoms was found LFOUND=.TRUE. and
        ! the search for a different pair of atoms starts; otherwise
        ! the pair (I,J) requires a new shell

        if (.not. lfound) then
          nsnew = nsnew + 1
          if (nsnew+nshell(0)>nsheld) then
            write (6, 110) 'global', 'NSHELD', nsnew + nshell(0)
            stop
          end if

          nsh1i(nshell(0)+nsnew) = ai
          nsh2i(nshell(0)+nsnew) = aj
          nshelli(nshell(0)+nsnew) = 1
          if (calc_exchange_couplings) then
            ! ish and jsh only needed fot Jij mode
            ish(nshell(0)+nsnew, 1) = i
            jsh(nshell(0)+nsnew, 1) = j
          end if
          do ii = 1, 3
            ratomi(ii, nshell(0)+nsnew) = rcls(ii, j) - rcls(ii, i)
          end do
        end if                     ! .not. lfound

      end if                       ! (i/=0 .or. j/=0) then

    end do                         ! igij = 1, nofgij
    ! **********************************************************************

    ! --> test number of shells

    if (nsnew+nshell(0)>nsheld) then
      write (6, 110) 'global', 'NSHELD', nsnew + nshell(0)
      stop
    end if

    ! --> update the argument arrays

    do i = 1, nshell(0) + nsnew
      nsh1(i) = nsh1i(i)
      nsh2(i) = nsh2i(i)
      nshell(i) = nshelli(i)
      do j = 1, 3
        ratom(j, i) = ratomi(j, i)
      end do
    end do

    nshell(0) = nshell(0) + nsnew
    deallocate (nsh1i, nsh2i, nshelli, ratomi, stat=ns)
    if (ns/=0) stop '   < shellgen2k > deallocate arrays'

    ! **********************************************************************

    ! --> scan once again the shells to find the corresponding symmetry
    ! index bringing GS(1..NSHELL(0)) to Gij.
    ! Setup the tables IJTABSH  assigning (I,J) --> NS
    ! IJTABSYM assigning (I,J) --> ISYM
    ! G_ij = D^\dagger(ISYM) * G(NS) * D(ISYM)

    ! **********************************************************************
    do i = 1, natom
      ai = (i-1)*natom
      do j = 1, natom
        ij = ai + j
        ijtabsh(ij) = 0
        ijtabsym(ij) = 0
      end do
    end do
    ! **********************************************************************
    do i = 1, natom
      ai = atom(i)
      do j = 1, natom
        aj = atom(j)
        ! =======================================================================
        do ii = 1, nshell(0)
          ! -----------------------------------------------------------------------
          if ( ai==nsh1(ii) .and. aj==nsh2(ii) ) then
            do id = 1, nrot
              isym = isymindex(id)

              do k = 1, 3
                ri(k) = rsymat(isym, k, 1)*ratom(1, ii) + rsymat(isym, k, 2)*ratom(2, ii) + rsymat(isym, k, 3)*ratom(3, ii)
              end do

                r1 = (rcls(1,j)-rcls(1,i)-ri(1))**2 + (rcls(2,j)-rcls(2,i)-ri(2))**2 + (rcls(3,j)-rcls(3,i)-ri(3))**2

                if (r1<small) then
                  ij = (i-1)*natom + j
                  ijtabsh(ij) = ii
                  ijtabsym(ij) = id
                  go to 100
                end if
            end do!id
          end if!ai==nsh1(ii) .and. aj==nsh2(ii)
          ! -----------------------------------------------------------------------
100       continue
        end do!ii
        ! =======================================================================
      end do
    end do
    ! ***********************************************************************
    if (iprint<=0) return

    ! OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OUTPUT
    write (1337, 140) 'assigned shells and symmetries'
    do i = 1, natom
      ai = (i-1)*natom
      do j = 1, natom
        ij = ai + j
        if (ijtabcalc(ij)>0) write (1337, 150) i, j, ijtabsh(ij), ijtabsym(ij), rotname(ijtabsym(ij))
      end do
    end do
    write (1337, 160)
    ! OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OUTPUT

110 format (6x, 'Dimension ERROR: please increase the ', a, ' parameter', /, 6x, a, ' to a value >=', i5, /)
120 format (9x, '< SHELLGEN2K > : assigning representative pairs', ' (shells) ', /, 26x, 'for the off-diagonal elements Gij', /)
130 format (9x, 'INFO: For the atomic sites   I=', i3, ' :', 3f10.6, /, 9x, 29x, 'J=', i3, ' :', 3f10.6, /, 9x, 6x, 'an already generated equivalent shell (', i3, ') was found', /)
140 format (13x, 30('-'), /, 13x, a, /, 13x, 30('-'), /, 13x, ' I ', 1x, ' J ', ' | ', 'shell', 4x, 'isym', /, 13x, 30('-'))
150 format (13x, i3, 1x, i3, ' | ', 1x, i4, 4x, i2, 2x, a10)
160 format (13x, 30('-'), /)
  end subroutine shellgen2k        ! SUBROUTINE SHELLGEN

  !-------------------------------------------------------------------------------
  !> Summary: Print the pointer indicating if a block of the Greens function has to be calculated
  !> Author: 
  !> Category: geometry, input-output, KKRhost
  !> Deprecated: False 
  !> Print the pointer indicating if a block of the Greens function has to be calculated
  !-------------------------------------------------------------------------------
  subroutine printijtab(natom, nofgij, ijtab)
    implicit none
    ! ..
    integer, intent(in) :: natom !! Number of atoms in the cluster
    integer, intent(in) :: nofgij
    integer, dimension(nofgij), intent(in) :: ijtab !! Linear pointer, specifying whether the block (i,j) has to be calculated needs set up for ICC=-1, not used for ICC=1
    ! ..
    integer :: i, j, ij
    integer :: lgmax
    ! ..
    lgmax = 59
    write (1337, 100, advance='no') '  searched for pairs marked with 1 in the table below'
    do j = 1, min(natom+3, lgmax)
      write (1337, '("-")', advance='no')
    end do
    write (1337, *)
    do i = 1, natom
      write (1337, '(14X,I3," | ")', advance='no') i
      ij = (i-1)*natom
      do j = 1, natom
        write (1337, '(I1)', advance='no') ijtab(ij+j)
      end do
      write (1337, *)
    end do
    write (1337, '(13X,6("-"))', advance='no')
    do j = 1, min(natom+3, lgmax)
      write (1337, '("-")', advance='no')
    end do
    write (1337, '(/)')
    ! ...........................................
100 format (13x, 65('-'), /, 18x, a, /, 13x, 65('-'), /, 13x, '   J |', /, 13x, 'I    | 1..NATCLUS', /, 13x, 6('-'))
  end subroutine printijtab

end module mod_shellgen2k