BCD convergence with NK #499
Replies: 5 comments 27 replies
|
BCD is really quite a delicate thing to claculate, so maybe you actually need a denser grid. However, my advice is :
|
|
Is there a systematic way to choose the energy windows for SAWF, or is it purely trial and error? I used the same windows that worked perfectly for my Maximum Localization (MLWF) run, but when I switched to Symmetry-Adapted Wannier Functions (SAWF), the interpolated bands failed to match the Quantum ESPRESSO results.
This was the code I was using for the SAWF process: import os
import ray
import numpy as np
from matplotlib import pyplot as plt
import scipy
import wannierberri as wb
import irrep
import spglib
NUM_CPUS = 16
ray.init(num_cpus=NUM_CPUS)
print(f"Python version:\t\t{__import__('sys').version.split()[0]}")
print(f"WannierBerri version:\t{wb.__version__}")
print(f"irrep version:\t\t{irrep.__version__}")
print(f"spglib version:\t\t{spglib.__version__}")
QE_PREFIX = "gete" # prefix in scf/nscf input → looks for tmp/gete.save
SEEDNAME = "my" # wannier90 seedname (my.win, my.mmn, my.eig, …)
PATH_DATA = "./" # folder containing tmp/, my.mmn, my.eig, …
assert os.path.exists(PATH_DATA), f"PATH_DATA={PATH_DATA} not found"
assert os.path.exists(os.path.join(PATH_DATA, "tmp")), \
"QE outdir 'tmp/' not found; adjust PATH_DATA or QE_PREFIX"
from irrep.bandstructure import BandStructure
print("\n── 2. Reading bandstructure & detecting symmetries ──")
bandstructure = BandStructure(
code="espresso",
prefix=os.path.join(PATH_DATA, "tmp", QE_PREFIX),
magmom=None, # no magnetic moments → pure TR symmetry
include_TR=True, # include time-reversal (and its combinations with spatial ops)
)
spacegroup = bandstructure.spacegroup
print(f"Detected spacegroup number: {spacegroup.number}")
# spacegroup.show() # uncomment to list all detected symmetry operations
print("\n── 3. Creating w90data (eig + symmetrizer from irrep) ──")
w90data = wb.w90files.Wannier90data.from_bandstructure(
bandstructure=bandstructure,
files=["eig", "symmetrizer"], # MMN will be read separately
)
print(" Reading MMN from pw2wannier90 output …")
mmn_path = os.path.join(PATH_DATA, SEEDNAME) # → ./my (w/o extension)
mmn = wb.w90files.mmn.MMN.from_w90_file(mmn_path, bkvec=w90data.bkvec)
w90data.set_file("mmn", mmn, overwrite=True)
npz_path = os.path.join(PATH_DATA, f"{SEEDNAME}_w90data")
w90data.to_npz(npz_path)
print(f" Saved to {npz_path}.*.npz (load later with Wannier90data.from_npz)")
# Fractional coordinates taken directly from nscf input (ATOMIC_POSITIONS crystal)
from wannierberri.symmetry.projections import Projection, ProjectionsSet
pos_Te = [[0.5227847276, 0.5227847276, 0.5227847276]]
pos_Ge = [[0.9982152724, 0.9982152724, 0.9982152724]]
proj_Te_s = Projection(position_num=pos_Te, orbital="s", spacegroup=spacegroup)
proj_Te_p = Projection(position_num=pos_Te, orbital="p", spacegroup=spacegroup)
proj_Ge_s = Projection(position_num=pos_Ge, orbital="s", spacegroup=spacegroup)
proj_Ge_p = Projection(position_num=pos_Ge, orbital="p", spacegroup=spacegroup)
projections_set = ProjectionsSet(projections=[proj_Te_s, proj_Te_p, proj_Ge_s, proj_Ge_p])
w90data.set_projections(projections_set, bandstructure=bandstructure)
froz_max = 13.65
_ = wb.wannierise.wannierise(
w90data=w90data,
froz_min=-4.79,
froz_max=froz_max,
outer_min=-4.79,
outer_max=16.75,
print_progress_every=500,
num_iter=5000,
conv_tol=1e-8, # tighter than default; loosen to 1e-6 if too slow
localise=True, # True = disentangle + localise; False = only disentangle
sitesym=True, # enforces symmetry (SAWF)
)
system = wb.system.System_w90(w90data= w90data, berry=True, transl_inv_JM=True,
symmetrize=True)
# optionally - save it for later use
system.save_npz("my_system")
# K-path from your my.win (kpoint_path block), in reduced coordinates
path = wb.Path.from_nodes(
system,
nodes=[
[0.0000000000, 0.0000000000, 0.0000000000], # G
[0.0000000000, 0.5000000000, 0.0000000000], # L
[0.3714285714, 0.6285714286, 0.0000000000], # U
[0.5000000000, 0.5000000000, 0.0000000000], # X
[0.0000000000, 0.0000000000, 0.0000000000], # G
[0.5000000000, 0.5000000000, 0.5000000000], # Z
[0.6285714286, 0.2432432432, 0.6285714286], # U
],
labels=["G", "L", "U", "X", "G", "Z", "U"],
length=2000,
)
bands_path = wb.evaluate_k_path(system, path=path)
fig, ax = plt.subplots(figsize=(8, 6))
bands_path.plot_path_fat(
path,
quantity=None,
Eshift=0,
Emin=-5.0,
Emax=15.0,
iband=None,
mode="fatband",
fatfactor=20,
linecolor="red",
close_fig=False,
show_fig=False,
label="WannierBerri (SAWF)",
)Is there any error in the code for wannierisation? Will playing with the energy windows be enough to get the good overlap with the DFT bands? I got these warnings in the process as well:
wberri_3500095.txt - file with the wannierisation data |
|
My first suggestion - get more bands in the nscf run, and increase the upper edge of the outer window. Because, also with Wannier90, on the 0th iteration (right after the disentanglement), you get huge spreads for the Ge WFs This indicates that something is wrong, probably some of the Ge bands are actually higher than band 40. Also, you may try to first get a good wannierisation for scalar bands (no spin-orbit), and than proceed to the spinor case. Please, try the scalar case with a 4x4x4 grid and ~50 bands in the nscf run. If it still fails, upload the data. |
|
Hi, How do we ensure SOC is enabled in the SAWF process? I was using s and p orbitals of Ge and Te, so with SOC, num_wann = 16. In the tutorial, I couldn't find the part with SOC for wannierisation. The current code was giving |















Uh oh!
There was an error while loading. Please reload this page.
Hi everyone,
I am currently calculating the Berry Curvature Dipole (BCD) for GeTe. By symmetry, we expect$D_{xy} = -D_{yx}$ . However, I am running into severe convergence issues, both when scaling up my NK grid and when comparing the FermiSea vs. FermiSurface formulations. I saw a very similar discussion in #239, and I was wondering if there have been any recent recommended workarounds for this feature?
To ensure a strict mathematical comparison, I evaluated both methods at strictly$T=0$ K
Calculators separated: FermiSea and FermiSurface evaluated in distinct run() calls to prevent confusing the adaptive mesh.
Method: tetra=True applied to both calculators.
Symmetry: system.set_symmetry(['TimeReversal', 'C3z', 'My']) and use_irred_kpt=True.
Adaptive Refinement: Heavy refinement focused on a narrow energy window (adpt_num_iter=75, adpt_fac=10, adpt_mesh=3).
Base Grids: NK = 100, 150, 200.
Despite these heavy optimizations, the BCD values are fluctuating wildly, particularly for the volume integration (FermiSea).
At E=E_F,
NK=100:
NK=150:
NK= 200:
As you can see, the FermiSurface and the FermiSea values are fluctuating.
Is the FermiSea volume integration mathematically unstable for BCD in materials like GeTe? Should I increase the adaptive iterations and the NK grid even further?
Are there any other suggestions or undocumented tweaks to improve the convergence of the tetrahedron method here?
Thanks
Dominic
All reactions