dos_main Subroutine

public subroutine dos_main(pw90_berry, dis_manifold, pw90_dos, kpoint_dist, kpt_latt, pw90_oper_read, pw90_band_deriv_degen, pw90_spin, ws_region, w90_system, print_output, wannier_data, ws_distance, wigner_seitz, HH_R, SS_R, u_matrix, v_matrix, eigval, real_lattice, scissors_shift, mp_grid, num_bands, num_kpts, num_wann, effective_model, have_disentangled, spin_decomp, seedname, stdout, timer, error, comm)

Uses

  • proc~~dos_main~~UsesGraph proc~dos_main dos_main module~w90_comms w90_comms proc~dos_main->module~w90_comms module~w90_get_oper w90_get_oper proc~dos_main->module~w90_get_oper module~w90_io w90_io proc~dos_main->module~w90_io module~w90_postw90_common w90_postw90_common proc~dos_main->module~w90_postw90_common module~w90_postw90_types w90_postw90_types proc~dos_main->module~w90_postw90_types module~w90_types w90_types proc~dos_main->module~w90_types module~w90_utility w90_utility proc~dos_main->module~w90_utility module~w90_wan_ham w90_wan_ham proc~dos_main->module~w90_wan_ham module~w90_constants w90_constants module~w90_comms->module~w90_constants module~w90_error_base w90_error_base module~w90_comms->module~w90_error_base module~w90_get_oper->module~w90_comms module~w90_get_oper->module~w90_io module~w90_get_oper->module~w90_constants module~w90_error w90_error module~w90_get_oper->module~w90_error module~w90_io->module~w90_constants module~w90_postw90_common->module~w90_constants module~w90_postw90_common->module~w90_error module~w90_postw90_types->module~w90_comms module~w90_postw90_types->module~w90_constants module~w90_types->module~w90_constants module~w90_utility->module~w90_comms module~w90_utility->module~w90_constants module~w90_wan_ham->module~w90_constants module~w90_wan_ham->module~w90_error module~w90_error->module~w90_comms module~w90_error->module~w90_error_base

Computes the electronic density of states. Can resolve into up-spin and down-spin parts, project onto selected Wannier orbitals, and use adaptive broadening, as in PRB 75, 195121 (2007) [YWVS07].

Arguments

Type IntentOptional Attributes Name
type(pw90_berry_mod_type), intent(in) :: pw90_berry
type(dis_manifold_type), intent(in) :: dis_manifold
type(pw90_dos_mod_type), intent(in) :: pw90_dos
type(kpoint_dist_type), intent(in) :: kpoint_dist
real(kind=dp), intent(in) :: kpt_latt(:,:)
type(pw90_oper_read_type), intent(in) :: pw90_oper_read
type(pw90_band_deriv_degen_type), intent(in) :: pw90_band_deriv_degen
type(pw90_spin_mod_type), intent(in) :: pw90_spin
type(ws_region_type), intent(in) :: ws_region
type(w90_system_type), intent(in) :: w90_system
type(print_output_type), intent(in) :: print_output
type(wannier_data_type), intent(in) :: wannier_data
type(ws_distance_type), intent(inout) :: ws_distance
type(wigner_seitz_type), intent(inout) :: wigner_seitz
complex(kind=dp), intent(inout), allocatable :: HH_R(:,:,:)
complex(kind=dp), intent(inout), allocatable :: SS_R(:,:,:,:)
complex(kind=dp), intent(in) :: u_matrix(:,:,:)
complex(kind=dp), intent(in) :: v_matrix(:,:,:)
real(kind=dp), intent(in) :: eigval(:,:)
real(kind=dp), intent(in) :: real_lattice(3,3)
real(kind=dp), intent(in) :: scissors_shift
integer, intent(in) :: mp_grid(3)
integer, intent(in) :: num_bands
integer, intent(in) :: num_kpts
integer, intent(in) :: num_wann
logical, intent(in) :: effective_model
logical, intent(in) :: have_disentangled
logical, intent(in) :: spin_decomp
character(len=50), intent(in) :: seedname
integer, intent(in) :: stdout
type(timer_list_type), intent(inout) :: timer
type(w90_error_type), intent(out), allocatable :: error
type(w90_comm_type), intent(in) :: comm

Calls

proc~~dos_main~~CallsGraph proc~dos_main dos_main interface~comms_reduce comms_reduce proc~dos_main->interface~comms_reduce proc~dos_get_k dos_get_k proc~dos_main->proc~dos_get_k proc~dos_get_levelspacing dos_get_levelspacing proc~dos_main->proc~dos_get_levelspacing proc~get_hh_r get_HH_R proc~dos_main->proc~get_hh_r proc~get_ss_r get_SS_R proc~dos_main->proc~get_ss_r proc~io_stopwatch_start io_stopwatch_start proc~dos_main->proc~io_stopwatch_start proc~io_stopwatch_stop io_stopwatch_stop proc~dos_main->proc~io_stopwatch_stop proc~mpirank mpirank proc~dos_main->proc~mpirank proc~mpisize mpisize proc~dos_main->proc~mpisize proc~pw90common_fourier_r_to_k pw90common_fourier_R_to_k proc~dos_main->proc~pw90common_fourier_r_to_k proc~set_error_alloc set_error_alloc proc~dos_main->proc~set_error_alloc proc~set_error_dealloc set_error_dealloc proc~dos_main->proc~set_error_dealloc proc~utility_diagonalize utility_diagonalize proc~dos_main->proc~utility_diagonalize proc~utility_recip_lattice_base utility_recip_lattice_base proc~dos_main->proc~utility_recip_lattice_base proc~wham_get_eig_deleig wham_get_eig_deleig proc~dos_main->proc~wham_get_eig_deleig proc~comms_reduce_cmplx comms_reduce_cmplx interface~comms_reduce->proc~comms_reduce_cmplx proc~comms_reduce_int comms_reduce_int interface~comms_reduce->proc~comms_reduce_int proc~comms_reduce_real comms_reduce_real interface~comms_reduce->proc~comms_reduce_real proc~set_error_input set_error_input proc~dos_get_k->proc~set_error_input proc~spin_get_nk spin_get_nk proc~dos_get_k->proc~spin_get_nk proc~utility_w0gauss utility_w0gauss proc~dos_get_k->proc~utility_w0gauss interface~pw90common_kmesh_spacing pw90common_kmesh_spacing proc~dos_get_levelspacing->interface~pw90common_kmesh_spacing proc~get_hh_r->proc~io_stopwatch_start proc~get_hh_r->proc~io_stopwatch_stop proc~get_hh_r->proc~mpirank interface~comms_bcast comms_bcast proc~get_hh_r->interface~comms_bcast proc~fourier_q_to_r fourier_q_to_R proc~get_hh_r->proc~fourier_q_to_r proc~get_win_min get_win_min proc~get_hh_r->proc~get_win_min proc~operator_wigner_setup operator_wigner_setup proc~get_hh_r->proc~operator_wigner_setup proc~set_error_fatal set_error_fatal proc~get_hh_r->proc~set_error_fatal proc~set_error_file set_error_file proc~get_hh_r->proc~set_error_file proc~get_hh_r->proc~set_error_input proc~get_ss_r->proc~io_stopwatch_start proc~get_ss_r->proc~io_stopwatch_stop proc~get_ss_r->proc~mpirank proc~get_ss_r->proc~set_error_alloc proc~get_ss_r->proc~set_error_dealloc proc~get_ss_r->interface~comms_bcast proc~get_ss_r->proc~fourier_q_to_r proc~get_gauge_overlap_matrix get_gauge_overlap_matrix proc~get_ss_r->proc~get_gauge_overlap_matrix proc~get_ss_r->proc~operator_wigner_setup proc~get_ss_r->proc~set_error_fatal proc~get_ss_r->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~utility_diagonalize->proc~set_error_fatal zhpevx zhpevx proc~utility_diagonalize->zhpevx proc~utility_inv3 utility_inv3 proc~utility_recip_lattice_base->proc~utility_inv3 proc~wham_get_eig_deleig->proc~get_hh_r proc~wham_get_eig_deleig->proc~pw90common_fourier_r_to_k proc~wham_get_eig_deleig->proc~utility_diagonalize proc~wham_get_deleig_a wham_get_deleig_a proc~wham_get_eig_deleig->proc~wham_get_deleig_a 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~kmesh_spacing_mesh kmesh_spacing_mesh interface~pw90common_kmesh_spacing->proc~kmesh_spacing_mesh proc~kmesh_spacing_singleinteger kmesh_spacing_singleinteger interface~pw90common_kmesh_spacing->proc~kmesh_spacing_singleinteger proc~comms_reduce_cmplx->proc~comms_sync_error proc~comms_no_sync_reduce_cmplx comms_no_sync_reduce_cmplx proc~comms_reduce_cmplx->proc~comms_no_sync_reduce_cmplx proc~comms_reduce_int->proc~comms_sync_error proc~comms_no_sync_reduce_int comms_no_sync_reduce_int proc~comms_reduce_int->proc~comms_no_sync_reduce_int proc~comms_reduce_real->proc~comms_sync_error proc~comms_no_sync_reduce_real comms_no_sync_reduce_real proc~comms_reduce_real->proc~comms_no_sync_reduce_real proc~get_gauge_overlap_matrix->proc~get_win_min proc~utility_zgemmm utility_zgemmm proc~get_gauge_overlap_matrix->proc~utility_zgemmm proc~set_error_fatal->proc~comms_sync_error proc~set_error_fatal->proc~set_base_error proc~set_error_file->proc~comms_sync_error proc~set_error_file->proc~set_base_error proc~set_error_input->proc~comms_sync_error proc~set_error_input->proc~set_base_error proc~spin_get_nk->proc~pw90common_fourier_r_to_k proc~spin_get_nk->proc~utility_diagonalize proc~utility_rotate_diag utility_rotate_diag proc~spin_get_nk->proc~utility_rotate_diag proc~utility_w0gauss->proc~set_error_input proc~wham_get_deleig_a->proc~utility_diagonalize proc~utility_rotate utility_rotate proc~wham_get_deleig_a->proc~utility_rotate proc~wham_get_deleig_a->proc~utility_rotate_diag 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~utility_matmul_diag utility_matmul_diag proc~utility_rotate_diag->proc~utility_matmul_diag proc~utility_zgemm_new utility_zgemm_new proc~utility_rotate_diag->proc~utility_zgemm_new proc~utility_zgemmm->proc~utility_zgemm_new zgemm zgemm proc~utility_zgemm_new->zgemm

Called by

proc~~dos_main~~CalledByGraph proc~dos_main dos_main program~postw90 postw90 program~postw90->proc~dos_main

Source Code

  subroutine dos_main(pw90_berry, dis_manifold, pw90_dos, kpoint_dist, kpt_latt, pw90_oper_read, &
                      pw90_band_deriv_degen, pw90_spin, ws_region, w90_system, print_output, &
                      wannier_data, ws_distance, wigner_seitz, HH_R, SS_R, u_matrix, v_matrix, &
                      eigval, real_lattice, scissors_shift, mp_grid, num_bands, num_kpts, &
                      num_wann, effective_model, have_disentangled, spin_decomp, seedname, stdout, &
                      timer, error, comm)
    !================================================!
    !
    !! Computes the electronic density of states. Can
    !! resolve into up-spin and down-spin parts, project
    !! onto selected Wannier orbitals, and use adaptive
    !! broadening, as in PRB 75, 195121 (2007) [YWVS07].
    !
    !================================================!

    use w90_comms, only: comms_reduce, w90_comm_type, mpirank, mpisize
    use w90_postw90_common, only: pw90common_fourier_R_to_k
    use w90_postw90_types, only: pw90_dos_mod_type, pw90_berry_mod_type, &
                                 pw90_band_deriv_degen_type, pw90_spin_mod_type, pw90_oper_read_type, wigner_seitz_type, &
                                 kpoint_dist_type
    use w90_types, only: print_output_type, wannier_data_type, dis_manifold_type, &
                         ws_region_type, w90_system_type, ws_distance_type, timer_list_type
    use w90_get_oper, only: get_HH_R, get_SS_R
    use w90_io, only: io_date, io_stopwatch_start, io_stopwatch_stop
    use w90_utility, only: utility_diagonalize, utility_recip_lattice_base
    use w90_wan_ham, only: wham_get_eig_deleig

    implicit none

    ! arguments
    type(pw90_berry_mod_type), intent(in)        :: pw90_berry
    type(dis_manifold_type), intent(in)          :: dis_manifold
    type(pw90_dos_mod_type), intent(in)          :: pw90_dos
    type(kpoint_dist_type), intent(in)           :: kpoint_dist
    type(pw90_oper_read_type), intent(in)        :: pw90_oper_read
    type(pw90_band_deriv_degen_type), intent(in) :: pw90_band_deriv_degen
    type(pw90_spin_mod_type), intent(in)         :: pw90_spin
    type(ws_region_type), intent(in)             :: ws_region
    type(w90_system_type), intent(in)            :: w90_system
    type(print_output_type), intent(in)          :: print_output
    type(wannier_data_type), intent(in)          :: wannier_data
    type(ws_distance_type), intent(inout)        :: ws_distance
    type(wigner_seitz_type), intent(inout)       :: wigner_seitz
    type(timer_list_type), intent(inout)         :: timer
    type(w90_comm_type), intent(in)               :: comm
    type(w90_error_type), allocatable, intent(out) :: error

    complex(kind=dp), allocatable, intent(inout) :: HH_R(:, :, :)
    complex(kind=dp), allocatable, intent(inout) :: SS_R(:, :, :, :)
    complex(kind=dp), intent(in) :: u_matrix(:, :, :), v_matrix(:, :, :)

    real(kind=dp), intent(in) :: eigval(:, :), real_lattice(3, 3)
    real(kind=dp), intent(in) :: scissors_shift
    real(kind=dp), intent(in) :: kpt_latt(:, :)

    integer, intent(in) :: mp_grid(3)
    integer, intent(in) :: num_bands, num_kpts, num_wann
    integer, intent(in) :: stdout

    character(len=50), intent(in) :: seedname
    logical, intent(in) :: have_disentangled
    logical, intent(in) :: spin_decomp
    logical, intent(in) :: effective_model

    ! local variables
    ! 'dos_k' contains contrib. from one k-point,
    ! 'dos_all' from all nodes/k-points (first summed on one node and
    ! then reduced (i.e. summed) over all nodes)
    real(kind=dp) :: recip_lattice(3, 3), volume

    integer :: i, loop_x, loop_y, loop_z, loop_tot, ifreq
    integer :: dos_unit, ndim, ierr
    integer :: my_node_id, num_nodes
    integer :: num_freq !! Number of sampling points

    real(kind=dp), allocatable :: dos_k(:, :)
    real(kind=dp), allocatable :: dos_all(:, :)
    real(kind=dp) :: kweight, kpt(3), omega
    real(kind=dp), allocatable :: dos_energyarray(:)
    real(kind=dp) :: del_eig(num_wann, 3)
    real(kind=dp) :: eig(num_wann), levelspacing_k(num_wann)
    real(kind=dp) :: d_omega !! Step between energies

    complex(kind=dp), allocatable :: HH(:, :)
    complex(kind=dp), allocatable :: delHH(:, :, :)
    complex(kind=dp), allocatable :: UU(:, :)
    logical :: on_root = .false.

    my_node_id = mpirank(comm)
    num_nodes = mpisize(comm)
    if (my_node_id == 0) on_root = .true.

    num_freq = nint((pw90_dos%energy_max - pw90_dos%energy_min)/pw90_dos%energy_step) + 1
    if (num_freq == 1) num_freq = 2
    d_omega = (pw90_dos%energy_max - pw90_dos%energy_min)/(num_freq - 1)

    allocate (dos_energyarray(num_freq), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating dos_energyarray in dos subroutine', comm)
      return
    end if

    do ifreq = 1, num_freq
      dos_energyarray(ifreq) = pw90_dos%energy_min + real(ifreq - 1, dp)*d_omega
    end do

    allocate (HH(num_wann, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating HH in dos', comm)
      return
    end if
    allocate (delHH(num_wann, num_wann, 3), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating delHH in dos', comm)
      return
    end if
    allocate (UU(num_wann, num_wann), stat=ierr)
    if (ierr /= 0) then
      call set_error_alloc(error, 'Error in allocating UU in dos', comm)
      return
    end if

    call get_HH_R(dis_manifold, kpt_latt, print_output, wigner_seitz, HH_R, u_matrix, v_matrix, &
                  eigval, real_lattice, scissors_shift, num_bands, num_kpts, num_wann, &
                  w90_system%num_valence_bands, effective_model, have_disentangled, seedname, ws_distance, ws_region, &
                  stdout, timer, error, comm)

    if (allocated(error)) return

    if (spin_decomp) then
      ndim = 3
      call get_SS_R(dis_manifold, kpt_latt, print_output, pw90_oper_read, SS_R, v_matrix, eigval, &
                    wigner_seitz, ws_distance, ws_region, num_bands, num_kpts, num_wann, &
                    have_disentangled, seedname, stdout, timer, error, comm)

      if (allocated(error)) return

    else
      ndim = 1
    end if

    allocate (dos_k(num_freq, ndim))
    allocate (dos_all(num_freq, ndim))

    if (print_output%iprint > 0) then

      if (print_output%timing_level > 1) call io_stopwatch_start('dos', timer)

!       write(stdout,'(/,1x,a)') '============'
!       write(stdout,'(1x,a)')   'Calculating:'
!       write(stdout,'(1x,a)')   '============'

      write (stdout, '(/,/,1x,a)') &
        'Properties calculated in module  d o s'
      write (stdout, '(1x,a)') &
        '--------------------------------------'

      if (pw90_dos%num_project == num_wann) then
        write (stdout, '(/,3x,a)') '* Total density of states (_dos)'
      else
        write (stdout, '(/,3x,a)') &
          '* Density of states projected onto selected WFs (_dos)'
        write (stdout, '(3x,a)') 'Selected WFs |Rn> are:'
        do i = 1, pw90_dos%num_project
          write (stdout, '(5x,a,2x,i3)') 'n =', pw90_dos%project(i)
        end do
      end if

      write (stdout, '(/,5x,a,f9.4,a,f9.4,a)') &
        'Energy range: [', pw90_dos%energy_min, ',', pw90_dos%energy_max, '] eV'

      write (stdout, '(/,5x,a,(f6.3,1x))') &
        'Adaptive smearing width prefactor: ', &
        pw90_dos%smearing%adaptive_prefactor

      write (stdout, '(/,/,1x,a20,3(i0,1x))') 'Interpolation grid: ', &
        pw90_dos%kmesh%mesh(1:3)

    end if

    dos_all = 0.0_dp

    call utility_recip_lattice_base(real_lattice, recip_lattice, volume)
    if (pw90_berry%wanint_kpoint_file) then
      !
      ! Unlike for optical properties, this should always work for the DOS
      !
      if (print_output%iprint > 0) write (stdout, '(/,1x,a)') 'Sampling the irreducible BZ only'

      ! Loop over k-points on the irreducible wedge of the Brillouin zone,
      ! read from file 'kpoint.dat'
      !
      do loop_tot = 1, kpoint_dist%num_int_kpts_on_node(my_node_id)
        kpt(:) = kpoint_dist%int_kpts(:, loop_tot)
        if (pw90_dos%smearing%use_adaptive) then
          call wham_get_eig_deleig(dis_manifold, kpt_latt, pw90_band_deriv_degen, ws_region, &
                                   print_output, wannier_data, ws_distance, wigner_seitz, delHH, &
                                   HH, HH_R, u_matrix, UU, v_matrix, del_eig, eig, eigval, kpt, &
                                   real_lattice, scissors_shift, mp_grid, num_bands, num_kpts, &
                                   num_wann, w90_system%num_valence_bands, effective_model, &
                                   have_disentangled, seedname, stdout, timer, error, comm)
          if (allocated(error)) return

          call dos_get_levelspacing(del_eig, pw90_dos%kmesh%mesh, levelspacing_k, num_wann, &
                                    recip_lattice)
          call dos_get_k(w90_system%num_elec_per_state, ws_region, kpt, dos_energyarray, eig, &
                         dos_k, num_wann, wannier_data, real_lattice, mp_grid, pw90_dos, &
                         spin_decomp, pw90_spin, ws_distance, wigner_seitz, HH_R, SS_R, &
                         pw90_dos%smearing, error, comm, levelspacing_k=levelspacing_k, UU=UU)
          if (allocated(error)) return

        else
          call pw90common_fourier_R_to_k(ws_region, wannier_data, ws_distance, wigner_seitz, HH, &
                                         HH_R, kpt, real_lattice, mp_grid, 0, num_wann, error, comm)
          if (allocated(error)) return

          call utility_diagonalize(HH, num_wann, eig, UU, error, comm)
          if (allocated(error)) return

          call dos_get_k(w90_system%num_elec_per_state, ws_region, kpt, dos_energyarray, eig, &
                         dos_k, num_wann, wannier_data, real_lattice, mp_grid, pw90_dos, &
                         spin_decomp, pw90_spin, ws_distance, wigner_seitz, HH_R, SS_R, &
                         pw90_dos%smearing, error, comm, UU=UU)
          if (allocated(error)) return

        end if
        dos_all = dos_all + dos_k*kpoint_dist%weight(loop_tot)
      end do

    else

      if (print_output%iprint > 0) write (stdout, '(/,1x,a)') 'Sampling the full BZ'

      kweight = 1.0_dp/real(PRODUCT(pw90_dos%kmesh%mesh), kind=dp)
      do loop_tot = my_node_id, PRODUCT(pw90_dos%kmesh%mesh) - 1, num_nodes
        loop_x = loop_tot/(pw90_dos%kmesh%mesh(2)*pw90_dos%kmesh%mesh(3))
        loop_y = (loop_tot - loop_x*(pw90_dos%kmesh%mesh(2) &
                                     *pw90_dos%kmesh%mesh(3)))/pw90_dos%kmesh%mesh(3)
        loop_z = loop_tot - loop_x*(pw90_dos%kmesh%mesh(2)*pw90_dos%kmesh%mesh(3)) &
                 - loop_y*pw90_dos%kmesh%mesh(3)
        kpt(1) = real(loop_x, dp)/real(pw90_dos%kmesh%mesh(1), dp)
        kpt(2) = real(loop_y, dp)/real(pw90_dos%kmesh%mesh(2), dp)
        kpt(3) = real(loop_z, dp)/real(pw90_dos%kmesh%mesh(3), dp)
        if (pw90_dos%smearing%use_adaptive) then
          call wham_get_eig_deleig(dis_manifold, kpt_latt, pw90_band_deriv_degen, ws_region, &
                                   print_output, wannier_data, ws_distance, wigner_seitz, delHH, &
                                   HH, HH_R, u_matrix, UU, v_matrix, del_eig, eig, eigval, kpt, &
                                   real_lattice, scissors_shift, mp_grid, num_bands, num_kpts, &
                                   num_wann, w90_system%num_valence_bands, effective_model, &
                                   have_disentangled, seedname, stdout, timer, error, comm)
          if (allocated(error)) return

          call dos_get_levelspacing(del_eig, pw90_dos%kmesh%mesh, levelspacing_k, num_wann, &
                                    recip_lattice)
          call dos_get_k(w90_system%num_elec_per_state, ws_region, kpt, dos_energyarray, eig, &
                         dos_k, num_wann, wannier_data, real_lattice, mp_grid, pw90_dos, &
                         spin_decomp, pw90_spin, ws_distance, wigner_seitz, HH_R, SS_R, &
                         pw90_dos%smearing, error, comm, levelspacing_k=levelspacing_k, UU=UU)
          if (allocated(error)) return

        else
          call pw90common_fourier_R_to_k(ws_region, wannier_data, ws_distance, wigner_seitz, HH, &
                                         HH_R, kpt, real_lattice, mp_grid, 0, num_wann, error, comm)
          if (allocated(error)) return

          call utility_diagonalize(HH, num_wann, eig, UU, error, comm)
          if (allocated(error)) return

          call dos_get_k(w90_system%num_elec_per_state, ws_region, kpt, dos_energyarray, eig, &
                         dos_k, num_wann, wannier_data, real_lattice, mp_grid, pw90_dos, &
                         spin_decomp, pw90_spin, ws_distance, wigner_seitz, HH_R, SS_R, &
                         pw90_dos%smearing, error, comm, UU=UU)
          if (allocated(error)) return

        end if
        dos_all = dos_all + dos_k*kweight
      end do

    end if

    ! Collect contributions from all nodes
    !
    call comms_reduce(dos_all(1, 1), num_freq*ndim, 'SUM', error, comm)
    if (allocated(error)) return

    if (print_output%iprint > 0) then
      write (stdout, '(1x,a)') 'Output data files:'
      write (stdout, '(/,3x,a)') trim(seedname)//'-dos.dat'
      open (newunit=dos_unit, FILE=trim(seedname)//'-dos.dat', STATUS='UNKNOWN', &
            FORM='FORMATTED')
      do ifreq = 1, num_freq
        omega = dos_energyarray(ifreq)
        write (dos_unit, '(4E16.8)') omega, dos_all(ifreq, :)
      end do
      close (dos_unit)
      if (print_output%timing_level > 1) call io_stopwatch_stop('dos', timer)
    end if

    deallocate (HH, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating HH in dos_main', comm)
      return
    end if
    deallocate (delHH, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating delHH in dos_main', comm)
      return
    end if
    deallocate (UU, stat=ierr)
    if (ierr /= 0) then
      call set_error_dealloc(error, 'Error in deallocating UU in dos_main', comm)
      return
    end if

  end subroutine dos_main