symtaumat.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: Find the symmetry matrices DROT that act on `t`, `tau`
!> Author:
!> Find the symmetry matrices DROT that act on `t`, `tau`
!>
!> * `KREL=0`: for real spherical harmonics
!> * `KREL=1`: for relativistic represntation
!>  
!> The `NSYM` allowed symmetry operations are indicated by `ISYMINDEX` in the table `ROTMAT`.
!> For `KREL=1`, `SYMUNITARY=T/F` indicates unitary/antiunitary symmetry operation.
!> 
!> The routine determines first the Euler angles correponding to a symmetry operation. 
!> Reflections are decomposed into inversion + rotation for this reason
!------------------------------------------------------------------------------------
module mod_symtaumat
  use :: mod_datatypes, only: dp
  private :: dp

contains

  !-------------------------------------------------------------------------------
  !> Summary: Find the symmetry matrices DROT that act on `t`, `tau`
  !> Author:
  !> Category: single-site, k-points, KKRhost
  !> Deprecated: False 
  !> Find the symmetry matrices DROT that act on `t`, `tau`
  !>
  !> * `KREL=0`: for real spherical harmonics
  !> * `KREL=1`: for relativistic represntation
  !>  
  !> The `NSYM` allowed symmetry operations are indicated by `ISYMINDEX` in the table `ROTMAT`.
  !> For `KREL=1`, `SYMUNITARY=T/F` indicates unitary/antiunitary symmetry operation.
  !> 
  !> The routine determines first the Euler angles correponding to a symmetry operation. 
  !> Reflections are decomposed into inversion + rotation for this reason
  !-------------------------------------------------------------------------------
  subroutine symtaumat(rotname,rotmat,drot,nsym,isymindex,symunitary,nqmax,nkmmax,  &
    nq,nl,krel,iprint,nsymaxd)

    use :: mod_calcrotmat
    use :: mod_checkrmat
    use :: mod_cinit
    use :: mod_cmatstr
    use :: mod_ddet33
    use :: mod_taustruct
    use :: mod_errortrap
    use :: mod_constants, only: ci,cone,czero,pi
    implicit none

    ! Dummy arguments
    integer :: iprint, krel, nkmmax, nl, nq, nqmax, nsym, nsymaxd
    complex (kind=dp) :: drot(nkmmax, nkmmax, 48)
    integer :: isymindex(nsymaxd)
    real (kind=dp) :: rotmat(64, 3, 3)
    character (len=10) :: rotname(64)
    logical :: symunitary(48)

    ! Local variables
    real (kind=dp) :: a, b, co1, co2, co3, det, fact(0:100), si1, si2, si3, sk
    real (kind=dp) symeulang(3, 48), tet1, tet2, tet3, rj, rmj
    complex (kind=dp) :: dinv(nkmmax, nkmmax), dtim(nkmmax, nkmmax)
    complex (kind=dp) rc(nkmmax, nkmmax), w1(nkmmax, nkmmax), w2(nkmmax, nkmmax)
    logical :: equal
    integer :: i, i1, i2, ind0q(nqmax), invflag(48), iq, irel, ireleff, isym, itop
    integer :: j, k, l, loop, m, n, nk, nkeff, nkm, nlm, nok, ns
    real (kind=dp) :: rmat(3, 3)
    real (kind=dp) :: w

    equal(a, b) = (abs(a-b)<1e-7_dp)

    write (1337, 110)

    irel = krel*3
    nk = (1-krel)*nl + krel*(2*nl-1)
    nkm = (1+krel)*nl**2

    ! -----------------------------------------------------------------------
    fact(0) = 1.0e0_dp
    do i = 1, 100
      fact(i) = fact(i-1)*real(i, kind=dp)
    end do
    ! -----------------------------------------------------------------------

    ind0q(1) = 0
    do iq = 2, nq
      ind0q(iq) = ind0q(iq-1) + nkm
    end do

    ! ----------------------------------------------------------------------
    ! RC  transforms from  REAL to  COMPLEX (L,M,S) - representation
    ! |LC> = sum[LR] |LR> * RC(LR,LC)
    ! ----------------------------------------------------------------------
    if (krel==0) then
      nlm = nkm

      call cinit(nkmmax*nkmmax, rc)

      w = 1.0e0_dp/sqrt(2.0e0_dp)

      do l = 0, (nl-1)
        do m = -l, l
          i = l*(l+1) + m + 1
          j = l*(l+1) - m + 1

          if (m<0) then
            rc(i, i) = -ci*w
            rc(j, i) = w
          end if
          if (m==0) then
            rc(i, i) = cone
          end if
          if (m>0) then
            rc(i, i) = w*(-1.0e0_dp)**m
            rc(j, i) = ci*w*(-1.0e0_dp)**m
          end if
        end do
      end do
    end if

    ! =======================================================================
    ! The routine determines first the Euler angles correponding
    ! to a symmetry operation. Reflections are decomposed into
    ! inversion + rotation for this reason.
    ! =======================================================================

    do isym = 1, nsym

      do i1 = 1, 3
        do i2 = 1, 3
          rmat(i1, i2) = rotmat(isymindex(isym), i1, i2)
        end do
      end do

      det = ddet33(rmat)

      invflag(isym) = 0
      if (det<0e0_dp) then
        call dscal(9, -1.0e0_dp, rmat, 1)
        invflag(isym) = 1
      end if

      ! ----------------------------------------------------------------------
      co2 = rmat(3, 3)
      tet2 = acos(co2)
      loop = 0
100   continue
      if (loop==1) tet2 = -tet2
      si2 = sin(tet2)

      if (equal(co2,1.0e0_dp)) then
        tet1 = acos(rmat(1,1))
        if (.not. equal(rmat(1,2),sin(tet1))) then
          tet1 = -tet1
          if (.not. equal(rmat(1,2),sin(tet1))) write (1337, *) '>>>>>>>>>>>>>>> STRANGE 1'
        end if
        tet2 = 0e0_dp
        tet3 = 0e0_dp
      else if (equal(co2,-1e0_dp)) then
        tet1 = acos(-rmat(1,1))
        if (.not. equal(rmat(1,2),-sin(tet1))) then
          tet1 = -tet1
          if (.not. equal(rmat(1,2),-sin(tet1))) write (1337, *) '>>>>>>>>>>>>>>> STRANGE 2'
        end if
        tet2 = pi
        tet3 = 0e0_dp
      else
        tet1 = acos(rmat(3,1)/si2)
        if (.not. equal(rmat(3,2),si2*sin(tet1))) then
          tet1 = -tet1
          if (.not. equal(rmat(3,2),si2*sin(tet1))) write (1337, *) '>>>>>>>>>>>>>>> STRANGE 3'
        end if

        tet3 = acos(-rmat(1,3)/si2)
        if (.not. equal(rmat(2,3),si2*sin(tet3))) then
          tet3 = -tet3
          if (.not. equal(rmat(2,3),si2*sin(tet3))) write (1337, *) '>>>>>>>>>>>>>>> STRANGE 4'
        end if

      end if

      co1 = cos(tet1)
      si1 = sin(tet1)
      co2 = cos(tet2)
      si2 = sin(tet2)
      co3 = cos(tet3)
      si3 = sin(tet3)

      nok = 0
      do i1 = 1, 3
        do i2 = 1, 3
          if (checkrmat(rmat,co1,si1,co2,si2,co3,si3,i1,i2)) then
            nok = nok + 1
          else if (loop<1) then
            loop = loop + 1
            go to 100
          end if
        end do
      end do

      symeulang(1, isym) = tet1*(180e0_dp/pi)
      symeulang(2, isym) = tet2*(180e0_dp/pi)
      symeulang(3, isym) = tet3*(180e0_dp/pi)

      if (nok/=9) write (1337, 130) nok
      write (1337, 120) isym, rotname(isymindex(isym)), invflag(isym), (symeulang(i,isym), i=1, 3), symunitary(isym)

    end do
    write (1337, '(8X,57("-"),/)')

    ! -----------------------------------------------------------------------
    ! initialize all rotation matrices
    ! -----------------------------------------------------------------------

    call cinit(nkmmax*nkmmax*nsym, drot)

    ! -----------------------------------------------------------------------
    ! create rotation matrices
    ! -----------------------------------------------------------------------

    if (irel<=2) then
      ireleff = 0
      nkeff = nl
    else
      ireleff = 3
      nkeff = nk
    end if

    do isym = 1, nsym

      call calcrotmat(nkeff, ireleff, symeulang(1,isym), symeulang(2,isym), symeulang(3,isym), drot(1,1,isym), fact, nkmmax)

    end do
    ! -----------------------------------------------------------------------
    ! create matrix for inversion
    ! -----------------------------------------------------------------------
    call cinit(nkmmax*nkmmax, dinv)

    i = 0
    if (irel>2) then
      ns = 2
    else
      ns = 1
    end if
    do l = 0, (nl-1)
      do m = 1, ns*(2*l+1)
        i = i + 1
        dinv(i, i) = (-1.0e0_dp)**l
      end do
    end do
    itop = i

    ! -----------------------------------------------------------------------
    ! include inversion
    ! -----------------------------------------------------------------------
    do isym = 1, nsym
      if (invflag(isym)/=0) then

        call zgemm('N', 'N', nkm, nkm, nkm, cone, drot(1,1,isym), nkmmax, dinv, nkmmax, czero, w2, nkmmax)

        do j = 1, nkm
          call zcopy(nkm, w2(1,j), 1, drot(1,j,isym), 1)
        end do
      end if
    end do

    ! -----------------------------------------------------------------------
    ! add second spin-diagonal block for  IREL=2
    ! spin off-diagonal blocks have been initialized before
    ! -----------------------------------------------------------------------
    if (irel==2) then
      nlm = nkm/2
      if (itop/=nlm) call errortrap('SYMTAUMAT', 11, 1)
      do isym = 1, nsym

        do j = 1, nlm
          call zcopy(nlm, drot(1,j,isym), 1, drot(nlm+1,nlm+j,isym), 1)
        end do
      end do
    end if
    ! -----------------------------------------------------------------------
    ! transform to real spherical representation for  KREL=0
    ! -----------------------------------------------------------------------
    n = nkm
    m = nkmmax
    if (krel==0) then
      do isym = 1, nsym
        call zgemm('N', 'N', n, n, n, cone, rc, m, drot(1,1,isym), m, czero, w1, m)
        call zgemm('N', 'C', n, n, n, cone, w1, m, rc, m, czero, drot(1,1,isym), m)
      end do
    end if
    ! -----------------------------------------------------------------------
    ! create matrix for time reversal
    ! -----------------------------------------------------------------------
    if (irel>1) then

      call cinit(nkmmax*nkmmax, dtim)

      i = 0
      do k = 1, nk
        l = k/2
        if (l*2==k) then
          sk = -1e0_dp
        else
          sk = +1e0_dp
        end if
        rj = l + sk*0.5_dp
        do rmj = -rj, +rj
          i1 = nint(2*l*(rj+0.5e0_dp)+rj+rmj+1)
          i2 = nint(2*l*(rj+0.5e0_dp)+rj-rmj+1)
          dtim(i1, i2) = sk*(-1)**nint(rmj+0.5e0_dp)
        end do
      end do
      if (iprint>0) then
        call cmatstr('Inversion     MATRIX', 20, dinv, nkm, nkmmax, 3, 3, 0, 1e-8_dp, 6)
        call cmatstr('Time reversal MATRIX', 20, dtim, nkm, nkmmax, 3, 3, 0, 1e-8_dp, 6)
      end if

    end if
    ! =======================================================================
    ! set up of transformation matrices completed
    ! =======================================================================

    ! =======================================================================
    ! include time reversal operation for anti-unitary transformations
    ! =======================================================================
    do isym = 1, nsym
      if (.not. symunitary(isym)) then
        if (irel==2) call errortrap('SYMTAUMAT', 14, 1)

        call zgemm('N', 'N', nkm, nkm, nkm, cone, drot(1,1,isym), nkmmax, dtim, nkmmax, czero, w2, nkmmax)
        do j = 1, nkm
          call zcopy(nkm, w2(1,j), 1, drot(1,j,isym), 1)
        end do
      end if
    end do

    ! -----------------------------------------------------------------------
    ! for testing

    ! ccc      write (6,*) ' NUMBER OF SYMMETRIES : ', NSYM
    ! ccc
    ! ccc      do isym = 1,nsym
    ! ccc         write(6,*) ' ISYM = ',isym
    ! ccc         call cmatstr('DROT',4,drot(1,1,isym),nkm,nkmmax,krel*3,krel*3,
    ! ccc     &        0,1d-12,6)
    ! ccc         write(6,*)
    ! ccc      end do

    ! -----------------------------------------------------------------------

    if (iprint==0) return

    ! =======================================================================
    ! find the structure of the site-diagonal TAU - matrices  TAUQ
    ! =======================================================================

    call taustruct(drot, nsym, symunitary, nkm, nq, nqmax, nkmmax, iprint, irel)

    return
110 format (5x, '<SYMTAUMAT> : rotation matrices acting on t/G/tau', /, /, 8x, 57('-'), /, 8x, 'ISYM            INV          Euler angles      Unitarity', /, 8x, 57('-'))
120 format (8x, i2, 3x, a, i3, 3f10.5, 3x, l1)
130 format (50('>'), ' trouble in <SYMTAUMAT>', i3, f10.5)
  end subroutine symtaumat

end module mod_symtaumat