sitesym_dis_extract_symmetry Subroutine

public subroutine sitesym_dis_extract_symmetry(sitesym, lambda, umat, zmat, ik, n, num_bands, num_wann, stdout, error, comm)

Uses

  • proc~~sitesym_dis_extract_symmetry~~UsesGraph proc~sitesym_dis_extract_symmetry sitesym_dis_extract_symmetry module~w90_wannier90_types w90_wannier90_types proc~sitesym_dis_extract_symmetry->module~w90_wannier90_types module~w90_constants w90_constants module~w90_wannier90_types->module~w90_constants

Arguments

Type IntentOptional Attributes Name
type(sitesym_type), intent(in) :: sitesym
complex(kind=dp), intent(out) :: lambda(:,:)
complex(kind=dp), intent(inout) :: umat(:,:)
complex(kind=dp), intent(in) :: zmat(:,:)
integer, intent(in) :: ik
integer, intent(in) :: n
integer, intent(in) :: num_bands
integer, intent(in) :: num_wann
integer, intent(in) :: stdout
type(w90_error_type), intent(out), allocatable :: error
type(w90_comm_type), intent(in) :: comm

Calls

proc~~sitesym_dis_extract_symmetry~~CallsGraph proc~sitesym_dis_extract_symmetry sitesym_dis_extract_symmetry proc~set_error_alloc set_error_alloc proc~sitesym_dis_extract_symmetry->proc~set_error_alloc proc~set_error_dealloc set_error_dealloc proc~sitesym_dis_extract_symmetry->proc~set_error_dealloc proc~set_error_fatal set_error_fatal proc~sitesym_dis_extract_symmetry->proc~set_error_fatal proc~symmetrize_ukirr symmetrize_ukirr proc~sitesym_dis_extract_symmetry->proc~symmetrize_ukirr zgemm zgemm proc~sitesym_dis_extract_symmetry->zgemm zhpgvx zhpgvx proc~sitesym_dis_extract_symmetry->zhpgvx proc~comms_sync_error comms_sync_error proc~set_error_alloc->proc~comms_sync_error proc~set_base_error set_base_error proc~set_error_alloc->proc~set_base_error proc~set_error_dealloc->proc~comms_sync_error proc~set_error_dealloc->proc~set_base_error proc~set_error_fatal->proc~comms_sync_error proc~set_error_fatal->proc~set_base_error proc~symmetrize_ukirr->proc~set_error_fatal proc~symmetrize_ukirr->zgemm proc~orthogonalize_u orthogonalize_u proc~symmetrize_ukirr->proc~orthogonalize_u proc~set_error_unconv set_error_unconv proc~symmetrize_ukirr->proc~set_error_unconv proc~orthogonalize_u->proc~set_error_dealloc proc~orthogonalize_u->proc~set_error_fatal zgesvd zgesvd proc~orthogonalize_u->zgesvd proc~set_error_unconv->proc~comms_sync_error proc~set_error_unconv->proc~set_base_error

Called by

proc~~sitesym_dis_extract_symmetry~~CalledByGraph proc~sitesym_dis_extract_symmetry sitesym_dis_extract_symmetry proc~dis_extract dis_extract proc~dis_extract->proc~sitesym_dis_extract_symmetry proc~dis_main dis_main proc~dis_main->proc~dis_extract proc~w90_disentangle~2 w90_disentangle proc~w90_disentangle~2->proc~dis_main proc~w90_disentangle w90_disentangle proc~w90_disentangle->proc~w90_disentangle~2 program~wannier wannier program~wannier->proc~w90_disentangle~2

Source Code

  subroutine sitesym_dis_extract_symmetry(sitesym, lambda, umat, zmat, ik, n, num_bands, num_wann, &
                                          stdout, error, comm)
    !================================================!
    !
    !   minimize Omega_I by steepest descendent
    !
    !   delta U_{mu I}(k) = Z_{mu mu'}*U_{mu' I}(k)
    !                        - \sum_{J} lambda_{JI} U_{mu J}(k)
    !   lambda_{JI}=U^{*}_{mu J} Z_{mu mu'} U_{mu' I}
    !
    !================================================!

    use w90_wannier90_types, only: sitesym_type

    implicit none

    ! arguments
    type(sitesym_type), intent(in) :: sitesym
    type(w90_error_type), allocatable, intent(out) :: error
    type(w90_comm_type), intent(in) :: comm

    integer, intent(in) :: num_bands
    integer, intent(in) :: stdout
    integer, intent(in) :: num_wann
    integer, intent(in) :: ik, n

    complex(kind=dp), intent(in) :: zmat(:, :) !(num_bands, num_bands)
    complex(kind=dp), intent(out) :: lambda(:, :) !(num_wann, num_wann)
    complex(kind=dp), intent(inout) :: umat(:, :) !(num_bands, num_wann)

    ! local variables
    complex(kind=dp), allocatable :: umatnew(:, :) !(num_bands, num_wann)
    complex(kind=dp), allocatable :: ZU(:, :) !(num_bands, num_wann)
    complex(kind=dp), allocatable :: deltaU(:, :) !(num_bands, num_wann)
    complex(kind=dp), allocatable :: carr(:) !(num_bands)
    integer :: i, m, INFO, IFAIL(2), IWORK(5*2)
    complex(kind=dp) :: HP(3), SP(3), V(2, 2), CWORK(2*2)
    real(kind=dp)    :: W(2), RWORK(7*2), sp3
    integer :: iter, ierr
    integer, parameter :: niter = 50

    allocate (umatnew(num_bands, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating umatnew in sitesym_dis_extract_symmetry', comm)
      return
    end if
    allocate (ZU(num_bands, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating ZU in sitesym_dis_extract_symmetry', comm)
      return
    end if
    allocate (deltaU(num_bands, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating deltaU in sitesym_dis_extract_symmetry', comm)
      return
    end if
    allocate (carr(num_bands), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating carr in sitesym_dis_extract_symmetry', comm)
      return
    end if

    do iter = 1, niter
      !  Z*U
      call zgemm('N', 'N', n, num_wann, n, cmplx_1, zmat, num_bands, umat, num_bands, cmplx_0, ZU, &
                 num_bands)
      ! lambda = U^{+}*Z*U
      call zgemm('C', 'N', num_wann, num_wann, n, cmplx_1, umat, num_bands, ZU, num_bands, &
                 cmplx_0, lambda, num_wann)

      deltaU(:, :) = ZU(:, :) - matmul(umat, lambda)
      if (sum(abs(deltaU(:n, :))) .lt. 1e-10) return

      ! band-by-band minimization
      do i = 1, num_wann
        ! diagonalize 2x2 matrix
        HP(1) = real(dot_product(umat(1:n, i), ZU(1:n, i)), kind=dp)
        HP(2) = dot_product(ZU(1:n, i), deltaU(1:n, i)) ! (1,2) matrix element
        carr(1:n) = matmul(zmat(1:n, 1:n), deltaU(1:n, i))
        HP(3) = real(dot_product(deltaU(1:n, i), carr(1:n)), kind=dp) ! (2,2)

        SP(1) = real(dot_product(umat(1:n, i), umat(1:n, i)), kind=dp)
        SP(2) = dot_product(umat(1:n, i), deltaU(1:n, i))
        SP(3) = real(dot_product(deltaU(1:n, i), deltaU(1:n, i)), kind=dp)

        sp3 = real(SP(3), kind=dp)
        if (abs(sp3) .lt. 1e-10) then
          umatnew(:, i) = umat(:, i)
          cycle
        end if
        call ZHPGVX(1, 'V', 'A', 'U', 2, HP, SP, 0.0_dp, 0.0_dp, 0, 0, &
                    -1.0_dp, m, W, V, 2, CWORK, RWORK, IWORK, IFAIL, INFO)
        if (INFO .ne. 0) then
          write (stdout, *) 'error in sitesym_dis_extract_symmetry: INFO=', INFO
          if (INFO .gt. 0) then
            if (INFO .le. 2) then
              write (stdout, *) INFO, ' eigenvectors failed to converge'
              write (stdout, *) IFAIL(1:INFO)
            else
              write (stdout, *) ' S is not positive definite'
              write (stdout, *) 'sp3=', sp3
            end if
            call set_error_fatal(error, 'error at sitesym_dis_extract_symmetry', comm)
            return
          end if
        end if
        ! choose the larger eigenstate
        umatnew(:, i) = V(1, 2)*umat(:, i) + V(2, 2)*deltaU(:, i)
      end do ! i
      call symmetrize_ukirr(num_wann, num_bands, sitesym%ik2ir(ik), num_bands, umatnew, sitesym, &
                            stdout, error, comm, n)
      if (allocated(error)) return

      umat(:, :) = umatnew(:, :)
    end do ! iter

    deallocate (umatnew, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating umatnew in sitesym_dis_extract_symmetry', comm)
      return
    end if
    deallocate (ZU, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating ZU in sitesym_dis_extract_symmetry', comm)
      return
    end if
    deallocate (deltaU, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating deltaU in sitesym_dis_extract_symmetry', comm)
      return
    end if
    deallocate (carr, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating carr in sitesym_dis_extract_symmetry', comm)
      return
    end if

    return
  end subroutine sitesym_dis_extract_symmetry