Wannierize
These are some Wannierization algorithms.
Contents
Index
Wannier.MagModelWannier.SpreadCenterWannier.GU_to_GX_GYWannier.U_to_X_YWannier.XY_to_X_YWannier.X_Y_to_UWannier.X_Y_to_XYWannier.check_frozen_bandsWannier.choose_poleWannier.compute_errorWannier.disentangleWannier.disentangleWannier.disentangle_centerWannier.disentangle_centerWannier.get_fg!_center_disentangleWannier.get_fg!_center_disentangleWannier.get_fg!_center_maxlocWannier.get_fg!_disentangleWannier.get_fg!_disentangleWannier.get_fg!_maxlocWannier.get_fg!_rotateWannier.get_frozen_bandsWannier.get_frozen_projWannier.interpolate_vecWannier.matrix_parallel_transportWannier.matrix_transportWannier.max_localizeWannier.max_localize_centerWannier.omegaWannier.omegaWannier.omega_centerWannier.omega_centerWannier.omega_centerWannier.omega_centerWannier.omega_centerWannier.omega_center_gradWannier.omega_center_gradWannier.omega_center_gradWannier.omega_gradWannier.omega_updnWannier.opt_rotateWannier.orthonorm_freezeWannier.overlap_updnWannier.overlap_updn_gradWannier.overlap_updn_gradWannier.parallel_transportWannier.propagate!Wannier.rotate_UWannier.set_frozen_degen!Wannier.set_frozen_proj!Wannier.set_frozen_win!Wannier.split_eigWannier.split_eigWannier.split_modelWannier.split_modelWannier.split_unkWannier.split_unkWannier.split_wannierizeWannier.split_wannierizeWannier.zero_froz_grad!
Disentanglement
Wannier.GU_to_GX_GY — MethodGU_to_GX_GY(G, X, Y, frozen)Compute dΩ/dX and dΩ/dY from dΩ/dU.
Acutally they are the conjugate gradients, e.g., $\frac{d \Omega}{d U^*}$.
Arguments
G:n_bands * n_wann * n_kptsarray for gradient dΩ/dUX:n_wann * n_wann * n_kptsarray for XY:n_bands * n_wann * n_kptsarray for Yfrozen:n_bands * n_kptsBitMatrix for frozen bands
Wannier.U_to_X_Y — MethodU_to_X_Y(U::Array{T,3}, frozen::BitMatrix) where {T<:Complex}Convert the U layout to the (X, Y) layout.
See also X_Y_to_U.
Arguments
U:n_bands * n_wann * n_kptsfrozen:n_bands * n_kpts
Wannier.XY_to_X_Y — MethodXY_to_X_Y(XY::Matrix{T}, n_bands::Int, n_wann::Int)Convert the XY layout to the (X, Y) layout.
See also X_Y_to_U.
Arguments
XY:n_bands * n_wann * n_kptscontiguous arrayn_bands: number of bands, to be used to reshapeXYn_wann: number of wannier functions, to be used to reshapeXY
Wannier.X_Y_to_U — MethodX_Y_to_U(X::Array{T,3}, Y::Array{T,3})Convert the (X, Y) layout to the U layout.
There are three formats: U, (X, Y), and XY stored contiguously in memory. For each kpoint,
U:size(U) = (n_bands, n_wann), the format used in the rest of the code(X, Y):size(X) = (n_wann, n_wann),size(Y) = (n_bands, n_wann), intermediate formatXY: this is the format used in the optimizer
Wannier.X_Y_to_XY — MethodX_Y_to_XY(X::Array{T,3}, Y::Array{T,3}) where {T<:Complex}Convert the (X, Y) layout to the XY layout.
See also X_Y_to_U.
Wannier.check_frozen_bands — Methodcheck_frozen_bands(frozen_bands, n_wann)Sanity check that the number of frozen bands at each kpoint <= n_wann.
Arguments
frozen_bands: theBitMatrixof frozen bandsn_wann: the number of wannier functions
Wannier.disentangle — Methoddisentangle(model; random_gauge=false, f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Run disentangle on the Model.
Arguments
model: model
Keyword arguments
random_gauge: use randomUmatrices as initial guessf_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.get_fg!_disentangle — Methodget_fg!_disentangle(model::Model)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.get_frozen_bands — Methodget_frozen_bands(E, dis_froz_max, dis_froz_min)Generate a BitMatrix of frozen bands by checking the two frozen windows.
Arguments
E: the energy eigenvalues of the Hamiltoniandis_froz_max: the upper bound of the frozen windowdis_froz_min: the lower bound of the frozen window
The dis_froz_max and dis_froz_min work similarly as Wannier90.
Wannier.get_frozen_proj — Methodget_frozen_proj(E, U, dis_proj_max)Get frozen bands according to band projectability.
Arguments
E: the energy eigenvalues of the HamiltonianU: the gauge rotation matricesdis_proj_max: the upper bound projectability. Bands with projectability >=dis_proj_maxare frozen.
The band projectability for band $n$ at kpoint $\bm{k}$ is calculated by $p_{n \bm{k}} = \sum_{m=1}^{m=n_{wann}} | U_{nm \bm{k}} |^2$, and usually each element $p_{n \bm{k}} \in [0.0, 1.0]$. In such cases, the dis_proj_max is usually set to sth. like 0.9 to freeze high-projectability bands.
Wannier.omega — Methodomega(bvectors, M, X, Y)Compute WF spread in the (X, Y) layout.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarray
Wannier.omega — Methodomega(model, X, Y)Compute WF spread in the (X, Y) layout.
Arguments
model:ModelX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarray
Wannier.omega_grad — Methodomega_grad(bvectors, M, X, Y, frozen)Compute gradient of WF spread in the (X, Y) layout.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarrayfrozen:n_bands * n_kptsarray for frozen bands
Wannier.orthonorm_freeze — Methodorthonorm_freeze(U, frozen)Normalize and freeze a block of a matrix.
Conditions:
- Block form:
U = vcat(Uf, Ur) - Semiunitary
U' * U = IUf' * Uf + Ur' * Ur = I
- Frozen:
Uf * Uf' = I - Also:
Uf * Ur' = 0
Strategy:
- orthogonalize
Uf - project
Ufout ofUr - orthogonalize the range of
Ur
Arguments
U: the matrix to be orthonormalized and frozenfrozen: theBitVectorspecifying which bands are frozen
Wannier.set_frozen_degen! — Methodset_frozen_degen!(frozen_bands, E, atol=1e-4)Freeze bands which are degenerate with the frozen_bands.
In some cases, we might want to freeze the whole set of degenerated eigen vectors.
Arguments
frozen_bands: theBitMatrixof frozen bandsE: the energy eigenvalues of the Hamiltonianatol: the tolerance of degeneracy
Wannier.set_frozen_proj! — Methodset_frozen_proj!(model, dis_proj_max; degen=false, degen_atol=1e-4)Set frozen bands of the Model according to projectability.
Arguments
model: theModelto be setdis_proj_max: the upper bound projectability. Bands with projectability >=dis_proj_maxare frozen.
Keyword Arguments
degen: whether to freeze the whole set of degenerated eigen vectorsdegen_atol: the tolerance of degeneracy
Wannier.set_frozen_win! — Methodset_frozen_win!(model, dis_froz_max, dis_froz_min=-Inf; degen=false, degen_atol=1e-4)Set frozen bands of the Model according to two energy windows.
Arguments
model: theModelto be setdis_froz_max: the upper bound of the frozen windowdis_froz_min: the lower bound of the frozen window
Keyword Arguments
degen: whether to freeze the whole set of degenerated eigen vectorsdegen_atol: the tolerance of degeneracy
Wannier.zero_froz_grad! — Methodzero_froz_grad!(G, frozen)Set gradient of frozen bands to 0.
This is used in test.
Arguments
G: gradient of the spread, inXYlayoutfrozen:BitMatrixfor frozen bands,n_bands * n_kpts
Maximal localization
Wannier.get_fg!_maxloc — Methodget_fg!_maxloc(model::Model)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.max_localize — Methodmax_localize(model; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Maximally localize spread functional w.r.t. all kpoints on a unitary matrix manifold.
Arguments
model: model
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Parallel transport
Wannier.compute_error — Methodcompute_error(model, U::Array{Complex{T},3})Compute the smoothness error of the gauge.
Wannier.parallel_transport — Methodparallel_transport(model::Model{T}; use_U=false, log_interp=false)Parallel transport the gauge from the first kpoint to all other kpoints.
Assumptions:
- the kpoints are contained in a
N1 * N2 * N3cartesian grid - the neighbor list must contain the six cartesian neighbors along x, y, z directions
Arguments
model: model
Keyword arguments
use_U: use the gaugeUinstead of random matrixlog_interp: use logarithmic interpolation method
Wannier.choose_pole — MethodChoose the column and the target point to contract the vector path of the columns of matrix_path
Wannier.interpolate_vec — MethodCreate an interpolation path between x and y, unit vectors by normalizing the linear interpolation of parameter t[i].
Wannier.matrix_parallel_transport — MethodCompute the parallel transport of the matrix path (matrixpath) along the homotopy of the frame (framepath) that starts with the columns (columns[]) of matrix_path.
size(framepath) = (ncol, ncol, nk, nt) size(matrixpath) = (ncol, ncol, n_k)
Wannier.matrix_transport — MethodContract the matrix_path to a single matrix point in the space of unitaries using parallel transport.
i.e., contract Obs(k) matrices to constant vectors.
size(matrixpath) = nwann x nwann x nk t: vector of kpoint indexes along a different k direction
Wannier.propagate! — MethodPropagate U, defined at the first kpt, to the given list of kpts. Those must be neighbors, and only the first kpoint is assumed to have been rotated.
Arguments
U:n_wann * n_wann * n_kptsgauge matriceskpts: list of kpoints along which to propagate the gauge matricesdk: the distance between two consecutive kpoints, in fractional coordinatesM: overlap matriceskpoints:BVectors.kpoints, kpoint coordinates of the gridkpb_k:BVectors.kpb_kkpb_b:BVectors.kpb_b
Optimal rotation
Wannier.get_fg!_rotate — Methodget_fg!_rotate(model::Model)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.opt_rotate — Methodopt_rotate(model; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Maximally localize spread functional w.r.t. single unitary matrix W.
Arguments
model: model
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.rotate_U — Methodrotate_U(U::Array{T,3}, W::Matrix{T}) where {T<:Complex}Rotate the U matrices at each kpoint by the same W matrix.
$\forall \bm{k}$, $U_{\bm{k}} W$
Useful once we have the optimal rotation matrix W, then update the initial U matrices by rotating them by W.
Splitting the Model
Wannier.split_eig — Methodsplit_eig(E, U, eig_groups)Split eigenvalues into several groups.
The separation is done by
- construct Wannier gauge Hamiltonian, $H_{\bm{k}} = U_{\bm{k}}^\dagger [\epsilon_{n \bm{k}}] U_{\bm{k}}$
- diagonalize the Hamiltonian, the eigenvalues are sorted in ascending order, and they are split into several groups according to the indices in
eig_groups.
Arguments
E: eigenvaluesU: (semi-)Unitary matrices gauge transformationeig_groups: a Vector, in which each element is a Vector of indices of eigenvalues that belong to the same group.
For example, if one wants to split valence+conduction into two groups, valence and conduction, respectively, then eig_groups should be [[1:n_val], [n_val+1:n_wann]]. Usually, the U are the maximally localized gauge matrices from a valence+conduction band Wannierization, this function split the gauge matrices U into two groups by diagonalizing the Hamiltonian, so we have two set of eigenvalues and gauge matrices for valence and conduction bands, respectively. However, the diagonalization introduce random gauges, so the returned two gauge matrices for valence and conduction are bad, we new to run a parallel transport to smoothen the gauges.
Wannier.split_eig — Methodsplit_eig(E, U, n_val)Split eigenvalues into two groups.
The separation is done by
- construct Wannier gauge Hamiltonian, $H_{\bm{k}} = U_{\bm{k}}^\dagger [\epsilon_{n \bm{k}}] U_{\bm{k}}$
- diagonalize the Hamiltonian, the eigenvalues are sorted in ascending order, so that the first
n_valeigenvalues are the occupied states, and the rest are the unoccupied states.
Arguments
E: eigenvaluesU: (semi-)Unitary matrices gauge transformationn_val: number of valence states
Wannier.split_model — Methodsplit_model(model, n_val)Split the Model into two Models.
Arguments
model: theModelto be splitn_val: number of valence WFs
Wannier.split_model — Methodsplit_model(model, eig_groups)Split the Model into several Models.
Arguments
model: theModelto be spliteig_groups: a Vector, in which each element is a Vector of indices of eigenvalues that belong to the same group.
Rotation eigenvectors are also returned, useful for further rotation of UNK files or other operators.
Wannier.split_unk — Methodsplit_unk(dir, Us, outdirs)Rotate UNK files.
These are large matrices, so we read/write to disk for each kpoint sequentially, inside the function.
Arguments
dir: directory whereUNKfiles are storedUs: a Vector of Wannier (semi-)unitary gauge matrices for rotating band groupsoutdirs: a Vector of output directories for each band group
Keyword arguments
binary: whether to write in Fortran binary format
Wannier.split_unk — Methodsplit_unk(dir, Uv, Uc, outdir_val="val", outdir_cond="cond")Rotate UNK files.
These are large matrices, so we read/write to disk for each kpoint sequentially, inside the function.
Arguments
dir: directory whereUNKfiles are storedUv: the Wannier (semi-)unitary matrix for rotating valence bandsUc: the Wannier (semi-)unitary matrix for rotating conduction bandsoutdir_val: output directory for valence bandsoutdir_cond: output directory for conduction bands
Keyword arguments
binary: whether to write in Fortran binary format
Wannier.split_wannierize — Methodsplit_wannierize(model::Model, n_val::Int)Split the model and run parallel transport to smoothen the gauge.
Arguments
model: theModelto be splitn_val: number of valence WFs
Wannier.split_wannierize — Methodsplit_wannierize(model::Model, eig_groups)Split the model and run parallel transport to smoothen the gauge.
Arguments
model: theModelto be spliteig_groups: a Vector, in which each element is a Vector of indices of eigenvalues that belong to the same group.
Return two separated Models and rotation matrices which are useful for UNK files or other operators.
Co-optimization of spin-polarized WFs
Wannier.MagModel — TypeModel for spin polarized system with constraint.
Traditionally, we run two independent Wannierizations for spin up and spin down. Here we add a constraint to maximally overlap the spin-up and spin-down WFs, so that they map one-by-one to each other.
Wannier.disentangle — Methoddisentangle(model; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Run disentangle on a MagModel.
Arguments
model: MagModelλ: Lagrange multiplier of the ↑↓ overlap term
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.get_fg!_disentangle — Functionget_fg!_disentangle(model::MagModel)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.omega_updn — Methodomega_updn(M)Compute QPPM Eq. 8.
Arguments
M: the overlap matrix between up and down WFs, size: (nwann, nwann), should be the matrix returned fromoverlap_updn.
Wannier.overlap_updn — Methodoverlap_updn(up::Model{T}, dn::Model{T}, M::Array{Complex{T},3}) where {T<:Real}Compute the overlap between up and down WFs.
Actually N - Ω↑↓, according to QPPM Eq. 8, where N = n_wann.
Arguments
M: theMagModel.Mmatrices, size (nbands, nbands, n_kpts)Uup: the up gauge matrices, size: (nbands, nwann, n_kpts)Udn: the down gauge matrices, size: (nbands, nwann, n_kpts)
Wannier.overlap_updn_grad — Methodoverlap_updn_grad(model::MagModel, Uup, Udn)Compute gradients of overlap_updn.
$\frac{d \Omega}{d U^{\uparrow}}$ and $\frac{d \Omega}{d U^{\downarrow}}$.
TODO: this is actually the gradient of Tr[overlap_updn]
Arguments
M: theMagModel.Mmatrices, size (nbands, nbands, n_kpts)Uup: the up gauge matrices, size: (nbands, nwann, n_kpts)Udn: the down gauge matrices, size: (nbands, nwann, n_kpts)
Wannier.overlap_updn_grad — Methodoverlap_updn_grad(model::MagModel, Xup, Yup, Xdn, Ydn)Compute gradient of overlap_updn.
$\frac{d \Omega}{d X^{\uparrow}}$, $\frac{d \Omega}{d Y^{\uparrow}}$, $\frac{d \Omega}{d X^{\downarrow}}$, $\frac{d \Omega}{d Y^{\downarrow}}$.
Constraining WF centers
Disentanglement
Wannier.disentangle_center — Methoddisentangle(model, r₀, λ=1.0; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Run disentangle on the Model with center penalty.
Arguments
model: modelr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.get_fg!_center_disentangle — Methodget_fg!_center_disentangle(model, r₀, λ=1.0)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.omega_center — Methodomega_center(bvectors, M, X, Y, r₀, λ)Compute WF spread with center penalty, in the (X, Y) layout.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarrayr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center — Methodomega_center(mode, X, Y, r₀, λ)Compute WF spread with center penalty, in the (X, Y) layout.
Arguments
model:ModelX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarrayr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center_grad — Methodomega_center_grad(bvectors, M, X, Y, frozen, r₀, λ)Compute gradient of WF spread with center penalty, in the (X, Y) layout.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayX:n_wann * n_wann * n_kptsarrayY:n_bands * n_wann * n_kptsarrayfrozen:n_bands * n_kptsarray for frozen bandsr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Maximal localization
Wannier.SpreadCenter — Typestruct SpreadCenterA struct containing both Spread and WF center penalty.
Wannier.get_fg!_center_maxloc — Methodget_fg!_center_maxloc(model, r₀, λ=1.0)Return a tuple of two functions (f, g!) for spread and gradient, respectively.
Wannier.max_localize_center — Methodmax_localize_center(model, r₀, λ=1.0; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Maximally localize spread functional with center constraint on a unitary matrix manifold.
Arguments
model: modelr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.omega_center — Methodomega_center(bvectors, M, U, r₀, λ)Compute WF spread with center penalty, for maximal localization.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayU:n_wann * n_wann * n_kptsarrayr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center — Methodomega_center(model, U, r₀, λ)Compute WF spread with center penalty, for maximal localization.
Arguments
model:ModelU:n_wann * n_wann * n_kptsarrayr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center — Methodomega_center(model, r₀, λ)Compute WF spread with center penalty, for maximal localization.
Arguments
model:Modelr₀:3 * n_wann, WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center_grad — Methodomega_center_grad(bvectors, M, U, r₀, λ)Compute gradient of WF spread with center penalty, for maximal localization.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayU:n_wann * n_wann * n_kptsarrayr₀:3 * n_wann, the target WF centers in cartesian coordinatesλ: penalty strength
Wannier.omega_center_grad — Methodomega_center_grad(bvectors, M, U, r, r₀, λ)Compute gradient of WF spread with center penalty, for maximal localization.
Arguments
bvectors: bvecotersM:n_bands * n_bands * * n_bvecs * n_kptsoverlap arrayU:n_wann * n_wann * n_kptsarrayr:3 * n_wann, the current WF centers in cartesian coordinatesr₀:3 * n_wann, the target WF centers in cartesian coordinatesλ: penalty strength
Co-optimization of spin-polarized WFs
Wannier.disentangle_center — Methoddisentangle(model; f_tol=1e-7, g_tol=1e-5, max_iter=200, history_size=3)Run disentangle on a MagModel, with center constraints.
Arguments
model: MagModelr₀:3 * n_wann, WF centers in cartesian coordinatesλc: Lagrange multiplier of the center termλs: Lagrange multiplier of the spin-up and spin-down overlap term
Keyword arguments
f_tol: tolerance for spread convergenceg_tol: tolerance for gradient convergencemax_iter: maximum number of iterationshistory_size: history size of LBFGS
Wannier.get_fg!_center_disentangle — Methodget_fg!_center_disentangle(model::MagModel, r₀, λc, λs)Return a tuple of two functions (f, g!) for spread and gradient, respectively.