9. Parallel transport using custom b-vectors
In this tutorial, we will Wannierize a single isolated band of CuBr2, by constructing the parallel transport gauge (PTG).
However, the CuBr2 system has a special set of b-vectors: some nearest neighbors are not included. This breaks the requirement of the PTG, since it needs the overlap matrices of nearest neighbors along 6 directions. Therefore, we need to generate a custom set of b-vectors, write them to a nnkp file, rerun pw2wannier90.x, and use the new mmn file to construct the PTG.
The generated b-vectors do not satisfy the completeness condition, therefore it should not be used to compute the spread and other physical operators.
Outline
- construct a
Model, by reading thewin,amn,mmn, andeigfiles - generate a new set of b-vectors containing only the 6 directions
- write the new b-vectors to a
nnkpfile - launch
pw2wannier90.xto compute a newmmnfile - read the new
mmnfile, and construct the PTG - use the PTG gauge matrices in the
Model - maxiaml localize to smoothen the gauge
- interpolate band structure
This is a HTML version of the tutorial, you can download corresponding
- Jupyter notebook:
tutorial.ipynb - Julia script:
tutorial.jl
Preparation
Load the package
using Wannier
using WannierPlotsModel generation
We will use the read_w90 function to read the win, amn, mmn, and eig files, and construct a Model
Before you do the actual calculations, if you don't know the kpath of your structure, you can use the following functions to auto generate a kpath
win = read_win("CuBr2.win")
kp = get_kpath(win.unit_cell, win.atoms_frac, win.atom_labels)
kpi = Wannier.interpolate_w90(kp, 100)
Wannier.write_w90_kpt_label("CuBr2", kpi)The outputs are two files: CuBr2_band.kpt and CuBr2_band.labelinfo.dat, which are exactly in the same format as the Wannier90 output bands, you can inspect these two files and use them to populate the kpoint_path block in the win file, or the K_POINTS block in the pw.x bands calculation.
model = read_w90("CuBr2")lattice: Å
a1: 7.14000 0.00000 0.00000
a2: 1.85704 1.73000 -3.07238
a3: -1.85704 1.73000 3.07238
atoms: fractional
Cu: 0.00000 0.50000 0.50000
Br: 0.24000 0.98500 0.01500
Br: 0.76000 0.01500 0.98500
n_bands: 1
n_wann : 1
kgrid : 4 4 4
n_kpts : 64
n_bvecs: 10
b-vectors:
[bx, by, bz] / Å⁻¹ weight
1 0.22000 0.00000 0.13297 7.49333
2 -0.22000 0.00000 -0.13297 7.49333
3 0.22000 0.00000 -0.37829 2.53647
4 -0.22000 0.00000 0.37829 2.53647
5 0.44000 0.00000 -0.24532 -0.53128
6 -0.44000 0.00000 0.24532 -0.53128
7 -0.22000 0.45399 0.12266 1.21298
8 0.22000 -0.45399 -0.12266 1.21298
9 0.22000 0.45399 -0.12266 1.21298
10 -0.22000 -0.45399 0.12266 1.21298This is a simple system, you can even get good WFs with a simple max_localize(model). However, we will use this tutorial to demonstrate the method to overcome the b-vector problem in PTG.
The initial spread is
omega(model) WF center [rx, ry, rz]/Šspread/Ų
1 1.30125 -1.18938 0.77896 95.06736
Sum spread: Ω = ΩI + Ω̃, Ω̃ = ΩOD + ΩD
ΩI = 5.16812
Ω̃ = 89.89923
ΩOD = 0.00000
ΩD = 89.89923
Ω = 95.06736
Custom b-vectors
As shown here, the b-vectors are a bit strange that some nearest neighbors are not included,
using PlotlyJS
WannierPlots.plot(model.bvectors)
thus we need to use a different set of b-vectors, which simply includes all the 6 nearest neighbors.
bvectors_nn = Wannier.get_bvectors_nearest(model.kpoints, model.recip_lattice)
WannierPlots.plot(bvectors_nn)
now write to a new nnkp file
n_wann = model.n_wann
exclude_bands = collect(1:16)
Wannier.write_nnkp("CuBr2_nn.nnkp", bvectors_nn, n_wann, exclude_bands)[ Info: Writing nnkp file: CuBr2_nn.nnkpnow we can run pw2wannier90.x to generate a new mmn file. A template input file for pw2wannier90.x is provided here
&INPUTPP
outdir = './out/'
prefix = 'cubr2'
seedname = 'CuBr2_nn'
write_amn = .false.
write_eig = .false.
scdm_proj = .true. ! this is useless, but we need it to avoid p2w error
/Parallel transport
Now, we load the new mmn file, and construct a new Model
M_nn = WannierIO.read_mmn("CuBr2_nn.mmn")[1];
model_nn = Wannier.Model(
model.lattice,
model.atom_positions,
model.atom_labels,
model.kgrid,
model.kpoints,
bvectors_nn,
model.frozen_bands,
M_nn,
model.U,
model.E,
)lattice: Å
a1: 7.14000 0.00000 0.00000
a2: 1.85704 1.73000 -3.07238
a3: -1.85704 1.73000 3.07238
atoms: fractional
Cu: 0.00000 0.50000 0.50000
Br: 0.24000 0.98500 0.01500
Br: 0.76000 0.01500 0.98500
n_bands: 1
n_wann : 1
kgrid : 4 4 4
n_kpts : 64
n_bvecs: 6
b-vectors:
[bx, by, bz] / Å⁻¹ weight
1 0.22000 0.00000 0.13297 1.00000
2 -0.22000 0.00000 -0.13297 1.00000
3 0.00000 0.45399 -0.25563 1.00000
4 0.00000 -0.45399 0.25563 1.00000
5 0.00000 0.45399 0.25563 1.00000
6 0.00000 -0.45399 -0.25563 1.00000finally, we run parallel transport
U, _ = parallel_transport(model_nn)([1.0 - 7.705582489488652e-17im;;; 0.35424192344475075 + 0.935153816050688im;;; 0.8320062948033026 - 0.5547661898563032im;;; … ;;; 0.6944757027862014 - 0.7195161556487887im;;; -0.06397879638386897 - 0.9979512581350206im;;; -0.9846154177322565 - 0.17473545479934413im], Wannier.Obstruction{ComplexF64}([1.0000000000000002 - 5.551115123125783e-17im;;; 1.0000000000000004 + 0.0im;;; 0.9999999999999998 - 1.1102230246251565e-16im;;; 1.0000000000000002 - 5.551115123125783e-17im], [0.7071068004161116 + 0.707106761956983im;;; 0.7071066324925186 + 0.7071069298805451im;;; 0.7071067413965386 + 0.7071068209765542im;;; 0.7071065342094165 + 0.7071070281635922im], [0.980785281729587 + 0.19509031534808527im;;; 0.98078529056235 + 0.19509027094277775im;;; 0.9807852760386562 + 0.19509034395832411im;;; 0.9807852791050835 + 0.19509032854235353im], [1.0 + 0.0im;;; 1.0 + 0.0im;;; 1.0 + 0.0im;;; 1.0 + 0.0im;;;; 1.0 - 1.3877787807814457e-17im;;; 1.0 + 0.0im;;; 1.0 - 2.7755575615628926e-17im;;; 1.0 - 1.3877787807814457e-17im;;;; 1.0 - 2.7755575615628907e-17im;;; 1.0 + 0.0im;;; 1.0 - 5.551115123125783e-17im;;; 1.0 - 2.7755575615628907e-17im;;;; 1.0 - 4.163336342344336e-17im;;; 1.0 + 0.0im;;; 1.0 - 8.326672684688675e-17im;;; 1.0 - 4.163336342344336e-17im], [0.9999999999999999 - 8.854311322427737e-17im;;; 0.9999999999999999 - 1.6704774771121138e-16im;;; 1.0 + 2.2479189238238287e-17im;;; 0.9999999999999999 - 1.6704774771121138e-16im;;;; 0.9807852817295866 + 0.1950903153480853im;;; 0.9807852701470825 + 0.1950903735772582im;;; 0.9807852776587205 + 0.19509033581370977im;;; 0.9807852633680203 + 0.19509040765789296im;;;; 0.9238795377147694 + 0.3826834198027715im;;; 0.9238794922749718 + 0.38268352950413315im;;; 0.923879521744188 + 0.38268345835916495im;;; 0.9238794656797542 + 0.3826835937106419im;;;; 0.8314696236339739 + 0.5555702160609205im;;; 0.8314695246814325 + 0.5555703641538422im;;; 0.8314695888554381 + 0.5555702681106762im;;; 0.8314694667660272 + 0.5555704508303322im], [1.0000000000000002 + 1.1487288329390876e-17im;;; 1.0 + 5.39108863965794e-18im;;; 1.0000000000000002 + 1.1487288329390876e-17im;;; 1.0 + 5.39108863965794e-18im;;;; 0.9987954562885715 + 0.04906767262979589im;;; 0.9987954568439591 + 0.04906766132461526im;;; 0.9987954559307362 + 0.04906767991369822im;;; 0.9987954561235474 + 0.04906767598893461im;;;; 0.9951847270053904 + 0.09801713694659044im;;; 0.9951847292242656 + 0.0980171144179675im;;; 0.9951847255757738 + 0.09801715146173123im;;; 0.9951847263460898 + 0.09801714364058078im;;;; 0.989176510712961 + 0.1467304694115425im;;; 0.9891765156954052 + 0.14673043582262568im;;; 0.9891765075027827 + 0.14673049105280553im;;; 0.9891765092325135 + 0.14673047939190764im]))Since the b-vectors are not complete, computing spread on top of model_nn is meaningless, we assign back the gauge matrices to model
model.U .= U;and the new spread is
omega(model) WF center [rx, ry, rz]/Šspread/Ų
1 -0.00000 -1.73000 0.00000 6.63661
Sum spread: Ω = ΩI + Ω̃, Ω̃ = ΩOD + ΩD
ΩI = 5.16812
Ω̃ = 1.46849
ΩOD = 0.00000
ΩD = 1.46849
Ω = 6.63661
then further maximal localize it
U = max_localize(model)
model.U .= U;
omega(model) WF center [rx, ry, rz]/Šspread/Ų
1 -0.00000 -1.73000 0.00000 5.16812
Sum spread: Ω = ΩI + Ω̃, Ω̃ = ΩOD + ΩD
ΩI = 5.16812
Ω̃ = 0.00000
ΩOD = 0.00000
ΩD = 0.00000
Ω = 5.16812
Band interpolation
Finally, let's have a look at the band interpolation.
First load the QE band structure
kpoints_qe, E_qe = WannierIO.read_qe_band("qe_bands.dat");the Fermi energy from scf calculation
ef = 4.64594.6459Force using kpoint_path in win file
win = read_win("CuBr2.win")
kpath = Wannier.get_kpath(win.unit_cell, win.kpoint_path)
interp_model = Wannier.InterpModel(model; kpath=kpath)interpolate band structure the QE bands use 50 points per segment, so we use 50 here as well
kpi = Wannier.interpolate_w90(kpath, 50)
E = Wannier.interpolate(interp_model, kpi)plot band difference
fig = plot_band_diff(kpi, E_qe, E; fermi_energy=ef)
fig.plot.layout.width = 500
fig.plot.layout.height = 500
fig.plot.layout.autosize = false
fig
Main.HTMLPlot(fig, 500) # hideThat's all!
This page was generated using Literate.jl.