This module contains the core routines to extract an optimal subspace from a set of entangled bands.
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=dp), | public, | parameter | :: | otsu_lower_bound | = | 0.0_dp | |
| real(kind=dp), | public, | parameter | :: | otsu_upper_bound | = | 1.0_dp | |
| integer, | public, | parameter | :: | otsu_nbins | = | 64 |
Main disentanglement routine
| Type | Intent | Optional | 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 |
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(kmesh_info_type), | intent(in) | :: | kmesh_info | |||
| type(print_output_type), | intent(in) | :: | print_output | |||
| complex(kind=dp), | intent(inout) | :: | m_matrix_local(:,:,:,:) | |||
| complex(kind=dp), | intent(in) | :: | m_matrix_orig_local(:,:,:,:) | |||
| complex(kind=dp), | intent(in) | :: | u_matrix(:,:,:) | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| 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 |
This subroutine checks that the states in the columns of the final matrix U_opt are orthonormal at every k-point, i.e., that the matrix is unitary in the sense that conjg(U_opt).U_opt = 1 (but not U_opt.conjg(U_opt) = 1).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(in) | :: | on_root | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| integer, | intent(in) | :: | stdout | |||
| type(w90_comm_type), | intent(in) | :: | comm |
This subroutine slims down the original Mmn(k,b), removing rows and columns corresponding to u_nks that fall outside the outer energy window.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | m_matrix_orig_local(:,:,:,:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | nfirstwin(:) | |||
| integer, | intent(in) | :: | nnlist(:,:) | |||
| integer, | intent(in) | :: | nntot | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | timing_level | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| integer, | intent(in) | :: | dist_k(:) | |||
| integer, | intent(in) | :: | global_k(:) | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| type(w90_comm_type), | intent(in) | :: | comm |
This subroutine finds the initial guess for the square unitary rotation matrix u_matrix. The method is similar to Sec. III.D of SMV, but with square instead of rectangular matrices:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(sitesym_type), | intent(inout) | :: | sitesym | |||
| complex(kind=dp), | intent(in) | :: | a_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(in) | :: | lsitesymmetry | |||
| logical, | intent(in) | :: | on_root | |||
| 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 |
Make initial u_matrix real Must be the case when gamma_only = .true.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(in) | :: | a_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| 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 |
This subroutine selects the states that are inside the outer window (ie, the energy window out of which we fish out the optimally-connected subspace) and those that are inside the inner window (that make up the frozen manifold, and are straightfowardly included as they are). This, in practice, amounts to slimming down the original num_wann x num_wann overlap matrices, removing rows and columns that belong to u_nks that have been excluded forever, and marking (indexing) the rows and columns that correspond to frozen states.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(dis_spheres_type), | intent(in) | :: | dis_spheres | |||
| type(dis_manifold_type), | intent(inout) | :: | dis_manifold | |||
| real(kind=dp), | intent(inout) | :: | eigval_opt(:,:) | |||
| real(kind=dp), | intent(in) | :: | kpt_latt(3,num_kpts) | |||
| real(kind=dp), | intent(in) | :: | recip_lattice(3,3) | |||
| integer, | intent(inout) | :: | indxfroz(:,:) | |||
| integer, | intent(inout) | :: | indxnfroz(:,:) | |||
| integer, | intent(inout) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | iprint | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(inout) | :: | lfrozen(:,:) | |||
| logical, | intent(inout) | :: | linner | |||
| logical, | intent(in) | :: | on_root | |||
| 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 |
This subroutine selects the states for disentanglement and frozen based on projectability. States with projectability < dis_proj_min are discarded, states with projectability >= dis_proj_min are included in the disentanglement, states with projectability
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(dis_manifold_type), | intent(inout) | :: | dis_manifold | |||
| real(kind=dp), | intent(inout) | :: | eigval_opt(:,:) | |||
| complex(kind=dp), | intent(inout) | :: | a_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | m_matrix_orig_local(:,:,:,:) | |||
| integer, | intent(inout) | :: | indxfroz(:,:) | |||
| integer, | intent(inout) | :: | indxnfroz(:,:) | |||
| integer, | intent(inout) | :: | ndimfroz(:) | |||
| integer, | intent(inout) | :: | nfirstwin(:) | |||
| integer, | intent(in) | :: | iprint | |||
| integer, | intent(in) | :: | nnlist(:,:) | |||
| integer, | intent(in) | :: | nntot | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(inout) | :: | lfrozen(:,:) | |||
| logical, | intent(inout) | :: | linner | |||
| logical, | intent(in) | :: | on_root | |||
| integer, | intent(in) | :: | stdout | |||
| integer, | intent(in) | :: | dist_k(:) |
assignment of k-points to MPI processes and global/local k index map |
||
| integer, | intent(in) | :: | global_k(:) |
assignment of k-points to MPI processes and global/local k index map |
||
| integer, | intent(in) | :: | my_node_id | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| type(w90_comm_type), | intent(in) | :: | comm |
Construct projections for the start of the disentanglement routine
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | a_matrix(:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | nfirstwin(:) | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(in) | :: | on_root | |||
| integer, | intent(in) | :: | iprint | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| integer, | intent(in) | :: | stdout | |||
| type(w90_comm_type), | intent(in) | :: | comm |
COMPUTES THE LEADING EIGENVECTORS OF Q_froz . P_s . Q_froz, WHERE P_s PROJECTOR OPERATOR ONTO THE SUBSPACE S OF THE PROJECTED GAUSSIANS, P_f THE PROJECTOR ONTO THE FROZEN STATES, AND Q_froz = 1 - P_froz, ALL EXP IN THE BASIS OF THE BLOCH EIGENSTATES INSIDE THE OUTER ENERGY WINDOW (See Eq. (27) in Sec. III.G of SMV)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| integer, | intent(in) | :: | indxfroz(:,:) | |||
| integer, | intent(in) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | iprint | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| logical, | intent(in) | :: | lfrozen(:,:) | |||
| logical, | intent(in) | :: | on_root | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| integer, | intent(in) | :: | stdout | |||
| type(w90_comm_type), | intent(in) | :: | comm |
Extracts an num_wann-dimensional subspace at each k by minimizing Omega_I
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(dis_control_type), | intent(in) | :: | dis_control | |||
| type(kmesh_info_type), | intent(in) | :: | kmesh_info | |||
| type(sitesym_type), | intent(in) | :: | sitesym | |||
| type(print_output_type), | intent(in) | :: | print_output | |||
| type(dis_manifold_type), | intent(in) | :: | dis_manifold | |||
| complex(kind=dp), | intent(inout) | :: | m_matrix_orig_local(:,:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| real(kind=dp), | intent(inout) | :: | eigval_opt(:,:) | |||
| real(kind=dp), | intent(out) | :: | omega_invariant | |||
| integer, | intent(in) | :: | indxnfroz(:,:) | |||
| integer, | intent(in) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | my_node_id | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| logical, | intent(in) | :: | lsitesymmetry | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| integer, | intent(in) | :: | ranknk | |||
| integer, | intent(in) | :: | global_k(:) | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| integer, | intent(in) | :: | stdout | |||
| type(w90_comm_type), | intent(in) | :: | comm |
Check if we have converged
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=dp), | intent(inout) | :: | history(:) | |||
| real(kind=dp), | intent(in) | :: | delta_womegai | |||
| real(kind=dp), | intent(in) | :: | dis_conv_tol | |||
| integer, | intent(in) | :: | iter | |||
| integer, | intent(in) | :: | dis_conv_window | |||
| logical, | intent(inout) | :: | dis_converged | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| type(w90_comm_type), | intent(in) | :: | comm |
Compute the Z-matrix
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | cbw(:,:) | |||
| complex(kind=dp), | intent(out) | :: | cmtrx(:,:) |
(M,N)-TH ENTRY IN THE (NDIMWIN(NKP)-NDIMFROZ(NKP)) x (NDIMWIN(NKP)-NDIMFRO HERMITIAN MATRIX AT THE NKP-TH K-POINT |
||
| complex(kind=dp), | intent(in) | :: | m_matrix_orig_local(:,:,:,:) | |||
| complex(kind=dp), | intent(in) | :: | u_matrix_opt(:,:,:) | |||
| real(kind=dp), | intent(in) | :: | wb(:) | |||
| integer, | intent(in) | :: | indxnfroz(:,:) | |||
| integer, | intent(in) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | nnlist(:,:) | |||
| integer, | intent(in) | :: | nkp | |||
| integer, | intent(in) | :: | nkp_loc | |||
| integer, | intent(in) | :: | nntot | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| type(timer_list_type), | intent(inout) | :: | timer |
Extracts an num_wann-dimensional subspace at each k by minimizing Omega_I (Gamma point version)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| type(dis_control_type), | intent(in) | :: | dis_control | |||
| type(kmesh_info_type), | intent(in) | :: | kmesh_info | |||
| type(print_output_type), | intent(in) | :: | print_output | |||
| type(dis_manifold_type), | intent(in) | :: | dis_manifold | |||
| complex(kind=dp), | intent(inout) | :: | m_matrix_orig_local(:,:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| real(kind=dp), | intent(inout) | :: | eigval_opt(:,:) | |||
| real(kind=dp), | intent(out) | :: | omega_invariant | |||
| integer, | intent(in) | :: | indxnfroz(:,:) | |||
| integer, | intent(in) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_kpts | |||
| integer, | intent(in) | :: | num_wann | |||
| type(timer_list_type), | intent(inout) | :: | timer | |||
| type(w90_error_type), | intent(out), | allocatable | :: | error | ||
| integer, | intent(in) | :: | stdout | |||
| type(w90_comm_type), | intent(in) | :: | comm |
Compute Z-matrix (Gamma point routine)
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| complex(kind=dp), | intent(inout) | :: | cbw(:,:) | |||
| complex(kind=dp), | intent(in) | :: | m_matrix_orig_local(:,:,:,:) | |||
| complex(kind=dp), | intent(inout) | :: | u_matrix_opt(:,:,:) | |||
| real(kind=dp), | intent(out) | :: | rmtrx(:,:) | |||
| real(kind=dp), | intent(in) | :: | wb(:) | |||
| integer, | intent(in) | :: | indxnfroz(:,:) | |||
| integer, | intent(in) | :: | ndimfroz(:) | |||
| integer, | intent(in) | :: | ndimwin(:) | |||
| integer, | intent(in) | :: | nnlist(:,:) | |||
| integer, | intent(in) | :: | nkp | |||
| integer, | intent(in) | :: | nntot | |||
| integer, | intent(in) | :: | num_bands | |||
| integer, | intent(in) | :: | num_wann | |||
| integer, | intent(in) | :: | timing_level | |||
| type(timer_list_type), | intent(inout) | :: | timer |
Multi-class Otsu thresholding of a scalar distribution in
[lower_bound, upper_bound].
Histograms values into nbins equal-width bins over that FIXED range
and finds the nclasses-1 ascending thresholds that maximise the between-class
variance (exhaustive search, strict tie-break so the first-found maximum in
ascending enumeration wins). Returns bin-centre thresholds in thr(1:nclasses_eff-1).
The number of classes cannot exceed the number of populated bins (a cut
must fall in a gap between clusters), so the effective class count is
nclasses_eff = min(nclasses, populated bins); the caller is expected to
note any reduction. Sets degenerate = .true. (thresholds undefined) only
when fewer than three bins are populated.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=dp), | intent(in) | :: | values(:) | |||
| real(kind=dp), | intent(in) | :: | lower_bound | |||
| real(kind=dp), | intent(in) | :: | upper_bound | |||
| integer, | intent(in) | :: | nbins | |||
| integer, | intent(in) | :: | nclasses | |||
| real(kind=dp), | intent(out) | :: | thr(nclasses-1) | |||
| integer, | intent(out) | :: | nclasses_eff | |||
| logical, | intent(out) | :: | degenerate |