dis_main Subroutine

public subroutine dis_main(dis_control, dis_spheres, dis_manifold, kmesh_info, kpt_latt, sitesym, print_output, m_matrix_orig_local, u_matrix, u_matrix_opt, eigval, real_lattice, omega_invariant, num_bands, num_kpts, num_wann, gamma_only, lsitesymmetry, stdout, timer, dist_k, error, comm)

Uses

  • proc~~dis_main~~UsesGraph proc~dis_main dis_main module~w90_comms w90_comms proc~dis_main->module~w90_comms module~w90_constants w90_constants proc~dis_main->module~w90_constants module~w90_error w90_error proc~dis_main->module~w90_error module~w90_io w90_io proc~dis_main->module~w90_io module~w90_sitesym w90_sitesym proc~dis_main->module~w90_sitesym module~w90_types w90_types proc~dis_main->module~w90_types module~w90_utility w90_utility proc~dis_main->module~w90_utility module~w90_wannier90_types w90_wannier90_types proc~dis_main->module~w90_wannier90_types module~w90_comms->module~w90_constants module~w90_error_base w90_error_base module~w90_comms->module~w90_error_base module~w90_error->module~w90_comms module~w90_error->module~w90_error_base module~w90_io->module~w90_constants module~w90_sitesym->module~w90_comms module~w90_sitesym->module~w90_constants module~w90_sitesym->module~w90_error module~w90_types->module~w90_constants module~w90_utility->module~w90_comms module~w90_utility->module~w90_constants module~w90_wannier90_types->module~w90_constants

Main disentanglement routine

Arguments

Type IntentOptional Attributes Name
type(dis_control_type), intent(inout) :: dis_control
type(dis_spheres_type), intent(in) :: dis_spheres
type(dis_manifold_type), intent(inout) :: dis_manifold
type(kmesh_info_type), intent(in) :: kmesh_info
real(kind=dp), intent(in) :: kpt_latt(:,:)
type(sitesym_type), intent(inout) :: sitesym
type(print_output_type), intent(in) :: print_output
complex(kind=dp), intent(inout) :: m_matrix_orig_local(:,:,:,:)
complex(kind=dp), intent(inout) :: u_matrix(:,:,:)
complex(kind=dp), intent(inout) :: u_matrix_opt(:,:,:)
real(kind=dp), intent(in), pointer :: eigval(:,:)
real(kind=dp), intent(in) :: real_lattice(3,3)
real(kind=dp), intent(inout) :: omega_invariant
integer, intent(in) :: num_bands
integer, intent(in) :: num_kpts
integer, intent(in) :: num_wann
logical, intent(in) :: gamma_only
logical, intent(in) :: lsitesymmetry
integer, intent(in) :: stdout
type(timer_list_type), intent(inout) :: timer
integer, intent(in) :: dist_k(:)
type(w90_error_type), intent(out), allocatable :: error
type(w90_comm_type), intent(in) :: comm

Calls

proc~~dis_main~~CallsGraph proc~dis_main dis_main proc~dis_extract dis_extract proc~dis_main->proc~dis_extract proc~dis_extract_gamma dis_extract_gamma proc~dis_main->proc~dis_extract_gamma proc~dis_proj_froz dis_proj_froz proc~dis_main->proc~dis_proj_froz proc~dis_project dis_project proc~dis_main->proc~dis_project proc~dis_windows dis_windows proc~dis_main->proc~dis_windows proc~dis_windows_proj dis_windows_proj proc~dis_main->proc~dis_windows_proj proc~internal_check_orthonorm internal_check_orthonorm proc~dis_main->proc~internal_check_orthonorm proc~internal_find_u internal_find_u proc~dis_main->proc~internal_find_u proc~internal_find_u_gamma internal_find_u_gamma proc~dis_main->proc~internal_find_u_gamma proc~internal_slim_m internal_slim_m proc~dis_main->proc~internal_slim_m proc~io_stopwatch_start io_stopwatch_start proc~dis_main->proc~io_stopwatch_start proc~io_stopwatch_stop io_stopwatch_stop proc~dis_main->proc~io_stopwatch_stop proc~mpirank mpirank proc~dis_main->proc~mpirank proc~set_error_alloc set_error_alloc proc~dis_main->proc~set_error_alloc proc~set_error_dealloc set_error_dealloc proc~dis_main->proc~set_error_dealloc proc~set_error_fatal set_error_fatal proc~dis_main->proc~set_error_fatal proc~sitesym_replace_d_matrix_band sitesym_replace_d_matrix_band proc~dis_main->proc~sitesym_replace_d_matrix_band proc~sitesym_symmetrize_u_matrix sitesym_symmetrize_u_matrix proc~dis_main->proc~sitesym_symmetrize_u_matrix proc~utility_recip_lattice_base utility_recip_lattice_base proc~dis_main->proc~utility_recip_lattice_base zgemm zgemm proc~dis_main->zgemm proc~dis_extract->proc~io_stopwatch_start proc~dis_extract->proc~io_stopwatch_stop proc~dis_extract->proc~set_error_alloc proc~dis_extract->proc~set_error_dealloc proc~dis_extract->proc~set_error_fatal proc~dis_extract->proc~sitesym_symmetrize_u_matrix proc~dis_extract->zgemm interface~comms_allreduce comms_allreduce proc~dis_extract->interface~comms_allreduce interface~comms_bcast comms_bcast proc~dis_extract->interface~comms_bcast proc~internal_test_convergence~2 internal_test_convergence proc~dis_extract->proc~internal_test_convergence~2 proc~internal_zmatrix internal_zmatrix proc~dis_extract->proc~internal_zmatrix proc~io_wallclocktime io_wallclocktime proc~dis_extract->proc~io_wallclocktime proc~sitesym_dis_extract_symmetry sitesym_dis_extract_symmetry proc~dis_extract->proc~sitesym_dis_extract_symmetry proc~sitesym_symmetrize_zmatrix sitesym_symmetrize_zmatrix proc~dis_extract->proc~sitesym_symmetrize_zmatrix zhpevx zhpevx proc~dis_extract->zhpevx proc~dis_extract_gamma->proc~io_stopwatch_start proc~dis_extract_gamma->proc~io_stopwatch_stop proc~dis_extract_gamma->proc~set_error_alloc proc~dis_extract_gamma->proc~set_error_dealloc proc~dis_extract_gamma->proc~set_error_fatal proc~dis_extract_gamma->zgemm dspevx dspevx proc~dis_extract_gamma->dspevx proc~dis_extract_gamma->proc~internal_test_convergence~2 proc~internal_zmatrix_gamma internal_zmatrix_gamma proc~dis_extract_gamma->proc~internal_zmatrix_gamma proc~io_time io_time proc~dis_extract_gamma->proc~io_time proc~dis_proj_froz->proc~io_stopwatch_start proc~dis_proj_froz->proc~io_stopwatch_stop proc~dis_proj_froz->proc~set_error_alloc proc~dis_proj_froz->proc~set_error_dealloc proc~dis_proj_froz->proc~set_error_fatal proc~dis_proj_froz->zhpevx proc~dis_project->proc~io_stopwatch_start proc~dis_project->proc~io_stopwatch_stop proc~dis_project->proc~set_error_alloc proc~dis_project->proc~set_error_dealloc proc~dis_project->proc~set_error_fatal zgesvd zgesvd proc~dis_project->zgesvd proc~dis_windows->proc~io_stopwatch_start proc~dis_windows->proc~io_stopwatch_stop proc~dis_windows->proc~set_error_fatal 10 10 proc~dis_windows->10 proc~set_error_input set_error_input proc~dis_windows->proc~set_error_input proc~dis_windows_proj->proc~io_stopwatch_start proc~dis_windows_proj->proc~io_stopwatch_stop proc~dis_windows_proj->proc~set_error_alloc proc~dis_windows_proj->proc~set_error_fatal proc~dis_windows_proj->10 proc~dis_otsu_thresholds dis_otsu_thresholds proc~dis_windows_proj->proc~dis_otsu_thresholds proc~internal_check_orthonorm->proc~io_stopwatch_start proc~internal_check_orthonorm->proc~io_stopwatch_stop proc~internal_check_orthonorm->proc~set_error_fatal proc~internal_find_u->proc~io_stopwatch_start proc~internal_find_u->proc~io_stopwatch_stop proc~internal_find_u->proc~set_error_alloc proc~internal_find_u->proc~set_error_dealloc proc~internal_find_u->proc~set_error_fatal proc~internal_find_u->proc~sitesym_symmetrize_u_matrix proc~internal_find_u->zgemm proc~internal_find_u->interface~comms_bcast proc~internal_find_u->zgesvd proc~internal_find_u_gamma->proc~io_stopwatch_start proc~internal_find_u_gamma->proc~io_stopwatch_stop proc~internal_find_u_gamma->proc~set_error_alloc proc~internal_find_u_gamma->proc~set_error_dealloc proc~internal_find_u_gamma->proc~set_error_fatal dgemm dgemm proc~internal_find_u_gamma->dgemm dgesvd dgesvd proc~internal_find_u_gamma->dgesvd proc~internal_slim_m->proc~io_stopwatch_start proc~internal_slim_m->proc~io_stopwatch_stop proc~internal_slim_m->proc~mpirank proc~internal_slim_m->proc~set_error_alloc proc~internal_slim_m->proc~set_error_dealloc 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~sitesym_replace_d_matrix_band->proc~set_error_alloc proc~sitesym_replace_d_matrix_band->proc~set_error_dealloc proc~sitesym_symmetrize_u_matrix->proc~set_error_fatal proc~sitesym_symmetrize_u_matrix->zgemm proc~symmetrize_ukirr symmetrize_ukirr proc~sitesym_symmetrize_u_matrix->proc~symmetrize_ukirr proc~utility_inv3 utility_inv3 proc~utility_recip_lattice_base->proc~utility_inv3 proc~comms_allreduce_cmplx comms_allreduce_cmplx interface~comms_allreduce->proc~comms_allreduce_cmplx proc~comms_allreduce_real comms_allreduce_real interface~comms_allreduce->proc~comms_allreduce_real proc~comms_bcast_char comms_bcast_char interface~comms_bcast->proc~comms_bcast_char proc~comms_bcast_cmplx comms_bcast_cmplx interface~comms_bcast->proc~comms_bcast_cmplx proc~comms_bcast_int comms_bcast_int interface~comms_bcast->proc~comms_bcast_int proc~comms_bcast_logical comms_bcast_logical interface~comms_bcast->proc~comms_bcast_logical proc~comms_bcast_real comms_bcast_real interface~comms_bcast->proc~comms_bcast_real proc~internal_test_convergence~2->proc~set_error_alloc proc~internal_test_convergence~2->proc~set_error_dealloc proc~internal_zmatrix->proc~io_stopwatch_start proc~internal_zmatrix->proc~io_stopwatch_stop proc~internal_zmatrix->zgemm proc~internal_zmatrix_gamma->proc~io_stopwatch_start proc~internal_zmatrix_gamma->proc~io_stopwatch_stop proc~internal_zmatrix_gamma->zgemm proc~set_error_input->proc~comms_sync_error proc~set_error_input->proc~set_base_error proc~sitesym_dis_extract_symmetry->proc~set_error_alloc proc~sitesym_dis_extract_symmetry->proc~set_error_dealloc proc~sitesym_dis_extract_symmetry->proc~set_error_fatal proc~sitesym_dis_extract_symmetry->zgemm proc~sitesym_dis_extract_symmetry->proc~symmetrize_ukirr zhpgvx zhpgvx proc~sitesym_dis_extract_symmetry->zhpgvx proc~sitesym_symmetrize_zmatrix->zgemm 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~comms_allreduce_cmplx->proc~comms_sync_error proc~comms_no_sync_allreduce_cmplx comms_no_sync_allreduce_cmplx proc~comms_allreduce_cmplx->proc~comms_no_sync_allreduce_cmplx proc~comms_allreduce_real->proc~comms_sync_error proc~comms_no_sync_allreduce_real comms_no_sync_allreduce_real proc~comms_allreduce_real->proc~comms_no_sync_allreduce_real proc~comms_bcast_char->proc~comms_sync_error proc~comms_no_sync_bcast_char comms_no_sync_bcast_char proc~comms_bcast_char->proc~comms_no_sync_bcast_char proc~comms_bcast_cmplx->proc~comms_sync_error proc~comms_no_sync_bcast_cmplx comms_no_sync_bcast_cmplx proc~comms_bcast_cmplx->proc~comms_no_sync_bcast_cmplx proc~comms_bcast_int->proc~comms_sync_error proc~comms_no_sync_bcast_int comms_no_sync_bcast_int proc~comms_bcast_int->proc~comms_no_sync_bcast_int proc~comms_bcast_logical->proc~comms_sync_error proc~comms_no_sync_bcast_logical comms_no_sync_bcast_logical proc~comms_bcast_logical->proc~comms_no_sync_bcast_logical proc~comms_bcast_real->proc~comms_sync_error proc~comms_no_sync_bcast_real comms_no_sync_bcast_real proc~comms_bcast_real->proc~comms_no_sync_bcast_real proc~orthogonalize_u->proc~set_error_dealloc proc~orthogonalize_u->proc~set_error_fatal proc~orthogonalize_u->zgesvd proc~set_error_unconv->proc~comms_sync_error proc~set_error_unconv->proc~set_base_error

Called by

proc~~dis_main~~CalledByGraph proc~dis_main dis_main 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 dis_main(dis_control, dis_spheres, dis_manifold, kmesh_info, kpt_latt, sitesym, &
                      print_output, m_matrix_orig_local, u_matrix, u_matrix_opt, eigval, &
                      real_lattice, omega_invariant, num_bands, num_kpts, num_wann, gamma_only, &
                      lsitesymmetry, stdout, timer, dist_k, error, comm)
    !================================================!
    !
    !! Main disentanglement routine
    !
    !================================================!
    use w90_comms, only: comms_bcast, w90_comm_type, mpirank
    use w90_constants, only: dp, cmplx_0, cmplx_1
    use w90_error
    use w90_io, only: io_stopwatch_start, io_stopwatch_stop
    use w90_sitesym, only: sitesym_replace_d_matrix_band, sitesym_symmetrize_u_matrix, &
                           sitesym_symmetrize_zmatrix, sitesym_dis_extract_symmetry
    use w90_types, only: dis_manifold_type, kmesh_info_type, print_output_type, timer_list_type
    use w90_utility, only: utility_recip_lattice_base
    use w90_wannier90_types, only: dis_control_type, dis_spheres_type, sitesym_type

    ! arguments
    integer, intent(in) :: num_bands, num_kpts, num_wann
    integer, intent(in) :: stdout
    integer, intent(in) :: dist_k(:)

    logical, intent(in) :: lsitesymmetry
    logical, intent(in) :: gamma_only

    real(kind=dp), pointer, intent(in) :: eigval(:, :) ! (num_bands, num_kpts)
    real(kind=dp), intent(in) :: kpt_latt(:, :)
    real(kind=dp), intent(inout) :: omega_invariant
    real(kind=dp), intent(in) :: real_lattice(3, 3)

    complex(kind=dp), intent(inout) :: u_matrix(:, :, :) ! (num_wann, num_wann, num_kpts)
    complex(kind=dp), intent(inout) :: u_matrix_opt(:, :, :) ! (num_bands, num_wann, num_kpts)
    complex(kind=dp), intent(inout) :: m_matrix_orig_local(:, :, :, :) ! this is the only "m matrix" here now

    type(dis_control_type), intent(inout)  :: dis_control
    type(dis_manifold_type), intent(inout) :: dis_manifold
    type(dis_spheres_type), intent(in) :: dis_spheres
    type(kmesh_info_type), intent(in) :: kmesh_info
    type(print_output_type), intent(in) :: print_output
    type(sitesym_type), intent(inout) :: sitesym
    type(w90_comm_type), intent(in) :: comm
    type(timer_list_type), intent(inout) :: timer
    type(w90_error_type), allocatable, intent(out) :: error

    ! internal variables
    real(kind=dp) :: recip_lattice(3, 3), volume
    integer :: nkp, nkp2, nn, j, ierr, nkp_global
    logical :: linner                         !! Is there a frozen window
    logical :: lfrozen(num_bands, num_kpts)   !! true if the i-th band inside outer window is frozen
    integer :: ndimfroz(num_kpts)             !! number of frozen bands at nkp-th k point
    integer :: indxfroz(num_bands, num_kpts)  !! number of bands inside outer window at nkp-th k point
    integer :: indxnfroz(num_bands, num_kpts) !! outer-window band index for the i-th non-frozen state
    complex(kind=dp), allocatable :: a_matrix(:, :, :) ! (num_bands, num_wann, num_kpts)
    !! (equals 1 if it is the bottom of outer window)

    real(kind=dp), allocatable :: eigval_opt(:, :)  !! At input it contains a large set of eigenvalues. At
    !! it is slimmed down to contain only those inside the energy window.

    complex(kind=dp), allocatable :: cwb(:, :), cww(:, :)

    ! pllel setup
    integer :: nkrank, ikg, ikl, my_node_id
    integer, allocatable :: global_k(:)
    logical :: on_root = .false.

    my_node_id = mpirank(comm)
    on_root = (my_node_id == 0)
    nkrank = count(dist_k == my_node_id) ! this routine must proceed also in the case of zero k-points this rank, to ensure collective communications are matched

    allocate (a_matrix(num_bands, num_wann, num_kpts), stat=ierr) ! a_matrix is local to disentangle()
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating a_matrix in dis_main', comm)
      return
    end if
    a_matrix = u_matrix_opt ! initial projections are passed to this routine via u_matrix_opt

    allocate (global_k(nkrank), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating global_k in dis_main', comm)
      return
    end if
    global_k = huge(1); ikl = 1
    do ikg = 1, num_kpts
      if (dist_k(ikg) == my_node_id) then
        global_k(ikl) = ikg
        ikl = ikl + 1
      end if
    end do

    if (print_output%timing_level > 0) call io_stopwatch_start('dis: main', timer)

    call utility_recip_lattice_base(real_lattice, recip_lattice, volume)

    if (print_output%iprint > 0) write (stdout, '(/1x,a)') &
      '*------------------------------- DISENTANGLE --------------------------------*'

    ! Allocate arrays
    allocate (eigval_opt(num_bands, num_kpts), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating eigval_opt in dis_main', comm)
      return
    end if
    eigval_opt(1:num_bands, 1:num_kpts) = eigval(1:num_bands, 1:num_kpts)

    ! Set up energy windows
    if (dis_manifold%frozen_proj) then
      call dis_windows_proj(dis_manifold, eigval_opt, a_matrix, m_matrix_orig_local, &
                            indxfroz, indxnfroz, ndimfroz, dis_manifold%nfirstwin, &
                            print_output%iprint, kmesh_info%nnlist, kmesh_info%nntot, num_bands, &
                            num_kpts, num_wann, print_output%timing_level, lfrozen, linner, &
                            on_root, stdout, dist_k, global_k, my_node_id, timer, error, comm)
      if (allocated(error)) return
    else
      call dis_windows(dis_spheres, dis_manifold, eigval_opt, kpt_latt, recip_lattice, indxfroz, &
                       indxnfroz, ndimfroz, print_output%iprint, num_bands, num_kpts, num_wann, &
                       print_output%timing_level, lfrozen, linner, on_root, stdout, timer, error, comm)
      if (allocated(error)) return
    end if

    ! Construct the unitarized projection
    call dis_project(a_matrix, u_matrix_opt, dis_manifold%ndimwin, dis_manifold%nfirstwin, &
                     num_bands, num_kpts, num_wann, print_output%timing_level, on_root, &
                     print_output%iprint, timer, error, stdout, comm)
    if (allocated(error)) return

    ! If there is an inner window, need to modify projection procedure
    ! (Sec. III.G SMV)
    if (linner) then
      if (lsitesymmetry) then
        call set_error_fatal(error, 'in symmetry-adapted mode, frozen window not implemented yet', &
                             comm)
        return
      end if
      if (print_output%iprint > 0) write (stdout, '(3x,a)') 'Using an inner window (linner = T)'
      call dis_proj_froz(u_matrix_opt, indxfroz, ndimfroz, dis_manifold%ndimwin, &
                         print_output%iprint, num_bands, num_kpts, num_wann, &
                         print_output%timing_level, lfrozen, on_root, timer, error, stdout, comm)
      if (allocated(error)) return
    else
      if (print_output%iprint > 0) write (stdout, '(3x,a)') 'No inner window (linner = F)'
    end if

    ! Debug
    call internal_check_orthonorm(u_matrix_opt, dis_manifold%ndimwin, num_kpts, num_wann, &
                                  print_output%timing_level, on_root, timer, error, stdout, comm)
    if (allocated(error)) return

    ! For frozen_proj, these are done inside dis_windows_proj()
    if (.not. dis_manifold%frozen_proj) then
      ! Slim down the original Mmn(k,b)

      call internal_slim_m(m_matrix_orig_local, dis_manifold%ndimwin, dis_manifold%nfirstwin, &
                           kmesh_info%nnlist, kmesh_info%nntot, num_bands, print_output%timing_level, &
                           timer, dist_k, global_k, error, comm)
      if (allocated(error)) return

      dis_manifold%lwindow = .false.
      do nkp = 1, num_kpts
        do j = dis_manifold%nfirstwin(nkp), dis_manifold%nfirstwin(nkp) + dis_manifold%ndimwin(nkp) - 1
          dis_manifold%lwindow(j, nkp) = .true.
        end do
      end do
    end if

    if (lsitesymmetry) then
      call sitesym_symmetrize_u_matrix(sitesym, u_matrix_opt, num_bands, num_bands, num_kpts, &
                                       num_wann, stdout, error, comm, dis_manifold%lwindow)
      if (allocated(error)) return
    end if

    !RS: calculate initial U_{opt}(Rk) from U_{opt}(k)
    ! Extract the optimally-connected num_wann-dimensional subspaces

    if (gamma_only) then
      call dis_extract_gamma(dis_control, kmesh_info, print_output, dis_manifold, &
                             m_matrix_orig_local, u_matrix_opt, eigval_opt, omega_invariant, &
                             indxnfroz, ndimfroz, num_bands, num_kpts, num_wann, timer, error, &
                             stdout, comm)
      if (allocated(error)) return
    else
      call dis_extract(dis_control, kmesh_info, sitesym, print_output, dis_manifold, &
                       m_matrix_orig_local, u_matrix_opt, eigval_opt, omega_invariant, indxnfroz, &
                       ndimfroz, my_node_id, num_bands, num_kpts, num_wann, lsitesymmetry, timer, &
                       nkrank, global_k, error, stdout, comm)
      if (allocated(error)) return
    end if

    ! Allocate workspace
    allocate (cwb(num_wann, num_bands), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating cwb in dis_main', comm)
      return
    end if
    allocate (cww(num_wann, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating cww in dis_main', comm)
      return
    end if

    ! Find the num_wann x num_wann overlap matrices between
    ! the basis states of the optimal subspaces
    do nkp = 1, nkrank
      nkp_global = global_k(nkp)
      do nn = 1, kmesh_info%nntot
        nkp2 = kmesh_info%nnlist(nkp_global, nn)
        call zgemm('C', 'N', num_wann, dis_manifold%ndimwin(nkp2), dis_manifold%ndimwin(nkp_global), &
                   cmplx_1, u_matrix_opt(:, :, nkp_global), num_bands, &
                   m_matrix_orig_local(:, :, nn, nkp), num_bands, cmplx_0, cwb, num_wann)
        call zgemm('N', 'N', num_wann, num_wann, dis_manifold%ndimwin(nkp2), cmplx_1, cwb, &
                   num_wann, u_matrix_opt(:, :, nkp2), num_bands, cmplx_0, cww, num_wann)
        m_matrix_orig_local(1:num_wann, 1:num_wann, nn, nkp) = cww(:, :)
      end do
    end do

    ! Find the initial u_matrix
    if (lsitesymmetry) call sitesym_replace_d_matrix_band(sitesym, num_wann, error, comm)

    if (gamma_only) then
      call internal_find_u_gamma(a_matrix, u_matrix, u_matrix_opt, dis_manifold%ndimwin, num_wann, &
                                 print_output%timing_level, stdout, timer, error, comm)
      if (allocated(error)) return
    else
      call internal_find_u(sitesym, a_matrix, u_matrix, u_matrix_opt, dis_manifold%ndimwin, &
                           num_bands, num_kpts, num_wann, print_output%timing_level, &
                           lsitesymmetry, on_root, stdout, timer, error, comm)
      if (allocated(error)) return
    end if

    !zero the unused elements of u_matrix_opt (just in case...)
    do nkp = 1, num_kpts
      do j = 1, num_wann
        if (dis_manifold%ndimwin(nkp) < num_bands) &
          u_matrix_opt(dis_manifold%ndimwin(nkp) + 1:, j, nkp) = cmplx_0
      end do
    end do

    ! Deallocate workspace
    deallocate (cww, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating cww in dis_main', comm)
      return
    end if
    deallocate (cwb, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating cwb in dis_main', comm)
      return
    end if
    deallocate (global_k, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating global_k in dis_main', comm)
      return
    end if
    deallocate (a_matrix, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating a_matrix in dis_main', comm)
      return
    end if

    if (print_output%timing_level > 0 .and. on_root) call io_stopwatch_stop('dis: main', timer)

    return
    !================================================!
  end subroutine dis_main