tran_find_integral_signatures Subroutine

private subroutine tran_find_integral_signatures(signatures, num_G, print_output, real_lattice, u_matrix_opt, u_matrix, num_bands, num_wann, have_disentangled, wannier_centres_translated, stdout, seedname, timer, error, comm)

Uses

  • proc~~tran_find_integral_signatures~~UsesGraph proc~tran_find_integral_signatures tran_find_integral_signatures module~w90_constants w90_constants proc~tran_find_integral_signatures->module~w90_constants module~w90_error w90_error proc~tran_find_integral_signatures->module~w90_error module~w90_io w90_io proc~tran_find_integral_signatures->module~w90_io module~w90_types w90_types proc~tran_find_integral_signatures->module~w90_types module~w90_comms w90_comms module~w90_error->module~w90_comms module~w90_error_base w90_error_base module~w90_error->module~w90_error_base module~w90_io->module~w90_constants module~w90_types->module~w90_constants module~w90_comms->module~w90_constants module~w90_comms->module~w90_error_base

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(out), allocatable :: signatures(:,:)
integer, intent(out) :: num_G
type(print_output_type), intent(in) :: print_output
real(kind=dp), intent(in) :: real_lattice(3,3)
complex(kind=dp), intent(in) :: u_matrix_opt(:,:,:)
complex(kind=dp), intent(in) :: u_matrix(:,:,:)
integer, intent(in) :: num_bands
integer, intent(in) :: num_wann
logical, intent(in) :: have_disentangled
real(kind=dp), intent(in) :: wannier_centres_translated(:,:)
integer, intent(in) :: stdout
character(len=50), intent(in) :: seedname
type(timer_list_type), intent(inout) :: timer
type(w90_error_type), intent(out), allocatable :: error
type(w90_comm_type), intent(in) :: comm

Calls

proc~~tran_find_integral_signatures~~CallsGraph proc~tran_find_integral_signatures tran_find_integral_signatures proc~io_stopwatch_start io_stopwatch_start proc~tran_find_integral_signatures->proc~io_stopwatch_start proc~io_stopwatch_stop io_stopwatch_stop proc~tran_find_integral_signatures->proc~io_stopwatch_stop proc~set_error_alloc set_error_alloc proc~tran_find_integral_signatures->proc~set_error_alloc proc~set_error_dealloc set_error_dealloc proc~tran_find_integral_signatures->proc~set_error_dealloc proc~set_error_file set_error_file proc~tran_find_integral_signatures->proc~set_error_file 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_file->proc~comms_sync_error proc~set_error_file->proc~set_base_error

Called by

proc~~tran_find_integral_signatures~~CalledByGraph proc~tran_find_integral_signatures tran_find_integral_signatures proc~tran_main tran_main proc~tran_main->proc~tran_find_integral_signatures proc~w90_transport w90_transport proc~w90_transport->proc~tran_main program~wannier wannier program~wannier->proc~w90_transport

Source Code

  subroutine tran_find_integral_signatures(signatures, num_G, print_output, real_lattice, &
                                           u_matrix_opt, u_matrix, num_bands, num_wann, &
                                           have_disentangled, wannier_centres_translated, stdout, &
                                           seedname, timer, error, comm)
    !================================================!
    ! Reads <seedname>.unkg file that contains the u_nk(G) and calculate
    ! Fourier components of each wannier function. Linear combinations of
    ! these provide integral of different spatial dependence.
    ! The set of these integrals provide a signature for distinguishing the
    ! type and 'parity' of each wannier function.
    !================================================!
    use w90_constants, only: dp, cmplx_0, twopi, cmplx_i
    use w90_io, only: io_date, io_stopwatch_start, io_stopwatch_stop
    use w90_types, only: print_output_type, timer_list_type
    use w90_error, only: w90_error_type, set_error_alloc, set_error_file, set_error_file, &
                         set_error_dealloc

    implicit none

    type(print_output_type), intent(in) :: print_output
    type(timer_list_type), intent(inout) :: timer
    type(w90_error_type), allocatable, intent(out) :: error
    type(w90_comm_type), intent(in) :: comm

    integer, intent(in) :: num_bands
    integer, intent(in) :: num_wann
    integer, intent(in) :: stdout
    integer, intent(out) :: num_G
    complex(kind=dp), intent(in) :: u_matrix(:, :, :)
    complex(kind=dp), intent(in) :: u_matrix_opt(:, :, :)
    real(kind=dp), allocatable, intent(out) :: signatures(:, :)
    real(kind=dp), intent(in) :: real_lattice(3, 3)
    real(kind=dp), intent(in) :: wannier_centres_translated(:, :)
    character(len=50), intent(in)  :: seedname
    logical, intent(in) :: have_disentangled

    integer, allocatable :: g_abc(:, :)
    integer :: i, ibnd, file_unit, ierr, p, p_max, n, m, ig, a, b, c, ig_idx(32)
    real(kind=dp) :: i_unkg, r_unkg, wf_frac(3), det_rl, inv_t_rl(3, 3), mag_signature_sq
    complex(kind=dp), allocatable :: unkg(:, :), tran_u_matrix(:, :)
    complex(kind=dp) :: phase_factor, signature_basis(32)
    logical :: have_file

    if (print_output%timing_level > 1) call io_stopwatch_start('tran: find_sigs_unkg_int', timer)

    inquire (file=trim(seedname)//'.unkg', exist=have_file)
    if (.not. have_file) then
      call set_error_file(error, 'tran_hr_parity_unkg: file '//trim(seedname)// &
                          '.unkg not found', comm)
      return
    end if
    open (newunit=file_unit, file=trim(seedname)//'.unkg', form='formatted', action='read')

    write (stdout, '(3a)') ' Reading '//trim(seedname)//'.unkg  file'
    read (file_unit, *) num_G

    allocate (signatures(20, num_bands), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating signatures in tran_find_integral_signatures', comm)
      return
    end if
    allocate (unkg(num_G, num_bands), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating unkg in tran_find_integral_signatures', comm)
      return
    end if
    allocate (g_abc(num_G, 3), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating g_abc in tran_find_integral_signatures', comm)
      return
    end if
    if (have_disentangled) then
      allocate (tran_u_matrix(num_bands, num_wann), stat=ierr)
      if (ierr /= 0) then
        call set_error_alloc(error, 'Error in allocating tran_u_matrix in tran_find_integral_signatures', comm)
        return
      end if
    else
      allocate (tran_u_matrix(num_wann, num_wann), stat=ierr)
      if (ierr /= 0) then
        call set_error_alloc(error, 'Error in allocating tran_u_matrix in tran_find_integral_signatures', comm)
        return
      end if
    end if

    unkg = cmplx_0
    do m = 1, num_bands
      do i = 1, num_G
        read (file_unit, *) ibnd, ig, a, b, c, r_unkg, i_unkg
        if ((ig .ne. i) .OR. (ibnd .ne. m)) then
          call set_error_file(error, 'tran_find_integral_signatures: Incorrect bands or g vectors', comm)
          return
        end if
        unkg(i, m) = cmplx(r_unkg, i_unkg, kind=dp)
        g_abc(i, :) = (/a, b, c/)
      end do
    end do

    close (file_unit)

    ! Computing inverse of transpose of real_lattice

    det_rl = real_lattice(1, 1)*(real_lattice(2, 2)*real_lattice(3, 3) &
                                 - real_lattice(2, 3)*real_lattice(3, 2)) &
             - real_lattice(2, 2)*(real_lattice(2, 1)*real_lattice(3, 3) &
                                   - real_lattice(2, 3)*real_lattice(3, 1)) &
             + real_lattice(3, 3)*(real_lattice(2, 1)*real_lattice(3, 2) &
                                   - real_lattice(2, 2)*real_lattice(3, 1))

    inv_t_rl(1, 1) = (real_lattice(2, 2)*real_lattice(3, 3) - real_lattice(3, 2)*real_lattice(2, 3))
    inv_t_rl(1, 2) = (real_lattice(2, 1)*real_lattice(3, 3) - real_lattice(3, 1)*real_lattice(2, 3))
    inv_t_rl(1, 3) = (real_lattice(2, 1)*real_lattice(3, 2) - real_lattice(3, 1)*real_lattice(2, 2))

    inv_t_rl(2, 1) = (real_lattice(1, 2)*real_lattice(3, 3) - real_lattice(3, 2)*real_lattice(1, 3))
    inv_t_rl(2, 2) = (real_lattice(1, 1)*real_lattice(3, 3) - real_lattice(3, 1)*real_lattice(1, 3))
    inv_t_rl(2, 3) = (real_lattice(1, 1)*real_lattice(3, 2) - real_lattice(3, 1)*real_lattice(1, 2))

    inv_t_rl(3, 1) = (real_lattice(1, 2)*real_lattice(2, 3) - real_lattice(2, 2)*real_lattice(1, 3))
    inv_t_rl(3, 2) = (real_lattice(1, 1)*real_lattice(2, 3) - real_lattice(2, 1)*real_lattice(1, 3))
    inv_t_rl(3, 3) = (real_lattice(1, 1)*real_lattice(2, 2) - real_lattice(2, 1)*real_lattice(1, 2))

    inv_t_rl = inv_t_rl/det_rl

    !Loop over wannier functions to compute generalised U matrix

    signatures = 0.0_dp
    tran_u_matrix = cmplx_0
    do n = 1, num_wann

      !Disentanglement step

      if (have_disentangled) then
        do p = 1, num_bands
          do m = 1, num_wann
            tran_u_matrix(p, n) = tran_u_matrix(p, n) + u_matrix(m, n, 1)*u_matrix_opt(p, m, 1)
          end do
        end do
        p_max = num_bands
      else
        tran_u_matrix = u_matrix(:, :, 1)
        p_max = num_wann
      end if
    end do

    if (print_output%iprint .ge. 5) write (stdout, *) 'Printing integral signatures for each &
      &wannier function:'

    ! Loop over all wannier functions

    do n = 1, num_wann

      ! Find fraction coordinate of wannier function in lattice vector basis
      ! wf_frac(:)=(transpose(real_lattice))^(-1) * wannier_centres_translated(:,n)

      wf_frac = 0.0_dp
      wf_frac = matmul(inv_t_rl, wannier_centres_translated(:, n))

      ! Loop over all g vectors, find a,b,c's required

      do ig = 1, num_G
        ! 0th Order
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(1) = ig   ! 1
        ! 1st Order
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(2) = ig   ! x
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(3) = ig   ! y
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(4) = ig   ! z
        ! 2nd Order
        if ((g_abc(ig, 1) .eq. 2) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(5) = ig   ! x^2
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(6) = ig   ! xy
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. -1) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(7) = ig   ! xy
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(8) = ig   ! xz
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(9) = ig   ! xz
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 2) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(10) = ig  ! y^2
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(11) = ig  ! yz
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(12) = ig  ! yz
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 2)) ig_idx(13) = ig  ! z^2
        ! 3rd Order
        if ((g_abc(ig, 1) .eq. 3) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(14) = ig  ! x^3
        if ((g_abc(ig, 1) .eq. 2) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(15) = ig  ! x^2y
        if ((g_abc(ig, 1) .eq. 2) .and. (g_abc(ig, 2) .eq. -1) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(16) = ig  ! x^2y
        if ((g_abc(ig, 1) .eq. 2) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(17) = ig  ! x^2z
        if ((g_abc(ig, 1) .eq. 2) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(18) = ig  ! x^2z
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 2) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(19) = ig  ! xy^2
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. -2) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(20) = ig  ! xy^2
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(21) = ig  ! xyz
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(22) = ig  ! xyz
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. -1) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(23) = ig  ! xyz
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. -1) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(24) = ig  ! xyz
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 2)) ig_idx(25) = ig  ! xz^2
        if ((g_abc(ig, 1) .eq. 1) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. -2)) ig_idx(26) = ig  ! xz^2
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 3) .and. (g_abc(ig, 3) .eq. 0)) ig_idx(27) = ig  ! y^3
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 2) .and. (g_abc(ig, 3) .eq. 1)) ig_idx(28) = ig  ! y^2z
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 2) .and. (g_abc(ig, 3) .eq. -1)) ig_idx(29) = ig  ! y^2z
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. 2)) ig_idx(30) = ig  ! yz^2
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 1) .and. (g_abc(ig, 3) .eq. -2)) ig_idx(31) = ig  ! yz^2
        if ((g_abc(ig, 1) .eq. 0) .and. (g_abc(ig, 2) .eq. 0) .and. (g_abc(ig, 3) .eq. 3)) ig_idx(32) = ig  ! z^3
      end do

      ! Loop over the 32 required g-vectors

      signature_basis = cmplx_0
      do ig = 1, 32
        phase_factor = cmplx_0

        ! Compute the phase factor exp(-i*G*x_c)

        phase_factor = exp(-twopi*cmplx_i*(g_abc(ig_idx(ig), 1)*wf_frac(1) &
                                           + g_abc(ig_idx(ig), 2)*wf_frac(2) &
                                           + g_abc(ig_idx(ig), 3)*wf_frac(3)))

        ! Compute integrals that form the basis of the spatial integrals that form the signature
        do p = 1, p_max
          signature_basis(ig) = signature_basis(ig) + tran_u_matrix(p, n)*conjg(unkg(ig_idx(ig), p))
        end do
        signature_basis(ig) = signature_basis(ig)*phase_factor
      end do

      ! Definitions of the signature integrals

      ! 0th Order
      signatures(1, n) = real(signature_basis(1))                                                    ! 1
      ! 1st Order
      signatures(2, n) = aimag(signature_basis(2))                                                   ! x
      signatures(3, n) = aimag(signature_basis(3))                                                   ! y
      signatures(4, n) = aimag(signature_basis(4))                                                   ! z
      ! 2nd Orde r
      signatures(5, n) = real(signature_basis(1) - signature_basis(5))/2                             ! x^2
      signatures(6, n) = real(signature_basis(7) - signature_basis(6))/2                             ! xy
      signatures(7, n) = real(signature_basis(9) - signature_basis(8))/2                             ! xz
      signatures(8, n) = real(signature_basis(1) - signature_basis(10))/2                            ! y^2
      signatures(9, n) = real(signature_basis(12) - signature_basis(11))/2                           ! yz
      signatures(10, n) = real(signature_basis(1) - signature_basis(13))/2                           ! z^2
      ! 3rd Order
      signatures(11, n) = aimag(3*signature_basis(2) - signature_basis(14))/4                        ! x^3
      signatures(12, n) = aimag(2*signature_basis(3) + signature_basis(16) - signature_basis(15))/4  ! x^2y
      signatures(13, n) = aimag(2*signature_basis(4) + signature_basis(18) - signature_basis(17))/4  ! x^2z
      signatures(14, n) = aimag(2*signature_basis(2) - signature_basis(20) - signature_basis(19))/4  ! xy^2
      signatures(15, n) = aimag(signature_basis(23) + signature_basis(22) - signature_basis(21) &
                                - signature_basis(24))/4                                             ! xyz
      signatures(16, n) = aimag(2*signature_basis(2) - signature_basis(26) - signature_basis(25))/4  ! xz^2
      signatures(17, n) = aimag(3*signature_basis(3) - signature_basis(27))/4                        ! y^3
      signatures(18, n) = aimag(2*signature_basis(4) + signature_basis(29) - signature_basis(28))/4  ! y^2z
      signatures(19, n) = aimag(2*signature_basis(3) - signature_basis(31) - signature_basis(30))/4  ! yz^2
      signatures(20, n) = aimag(3*signature_basis(4) - signature_basis(32))/4                        ! z^3

      if (print_output%iprint .ge. 5) then
        write (stdout, *) ' '
        write (stdout, *) ' Wannier function: ', n
        do ig = 1, 20
          write (stdout, *) ig - 1, signatures(ig, n)
        end do
      end if

      !Normalise signature of each wannier function to a unit vector

      mag_signature_sq = 0.0_dp
      do ig = 1, 20
        mag_signature_sq = mag_signature_sq + abs(signatures(ig, n))**2
      end do
      signatures(:, n) = signatures(:, n)/sqrt(mag_signature_sq)

    end do ! Wannier Function loop

    ! Set num_G = 20 to ensure later subroutines work correctly

    num_G = 20

    deallocate (tran_u_matrix, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error deallocating tran_u_matrix in tran_find_integral_signatures', comm)
      return
    end if
    deallocate (g_abc, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error deallocating g_abc in tran_find_integral_signatures', comm)
      return
    end if
    deallocate (unkg, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error deallocating unkg in tran_find_integral_signatures', comm)
      return
    end if

    if (print_output%timing_level > 1) call io_stopwatch_stop('tran: find_sigs_unkg_int', timer)

    return

  end subroutine tran_find_integral_signatures