SMTG-Bham / doped

doped is a Python software for the generation, pre-/post-processing and analysis of defect supercell calculations, implementing the defect simulation workflow in an efficient, reproducible, user-friendly yet powerful and fully-customisable manner.
https://doped.readthedocs.io
MIT License
131 stars 31 forks source link

Different bandgap values from py-sc-fermi and doped #90

Open rushikd27 opened 3 weeks ago

rushikd27 commented 3 weeks ago

Hi,

I am working on the defects in BaZrS3 and noticed that when I try to load the DOS object using py-sc-fermi and check the band gap, it comes different from the doped.thermodynamics.get_fermi_dos.get_gap().

For both cases, I used the same vasprun.xml file, a 2x2x1 supercell of an orthorhombic BaZrS3 with a k-mesh of 2x2x2. The INCAR also matches the defect calculations.

I get a gap of 1.86 eV from py-sc-fermi, which is also stored in the DefectThermodynamics object when parsing the defect and from get_fermi_dos.get_gap(), I get 1.59 eV. Now I understand that for the density of states, I should be running a primitive cell dense-mesh calculation, which is what I did next, and I still have the same discrepancy.

The correct bandgap from experiments should be between 1.7 and 1.8. Can you let me know if I am doing something wrong?

I also plotted the density of states using Sumo and Pymatgen's dos plotter, which is attached below. I see the VBM is not exactly at zero, but even after that, the pymatgen band gap is different.

sumo_dos.pdf dos_pymatgen

kavanase commented 3 weeks ago

Hi @rushikd27, Thanks for your interest in doped!

Do you know what band gap you're expecting? Have you used sumo-bandstats on a band structure calculation, or bandgap OUTCAR (using the tool from Alex Ganose here: https://github.com/utf/materials-toolbox), or just manually looking at the EIGENVAL output and calculating the gap? This will help narrow down the issue, and is the band gap that should be used.

Sometimes there can be numerical issues with the pymatgen band gap determination functions (at least some of which should be alleviated after my PR https://github.com/materialsproject/pymatgen/pull/3879). I would suspect the doped band gap value here is the most reliable, as this is generally the case, and as you show here, pymatgen is not detecting the correct VBM.

rushikd27 commented 2 weeks ago

Hi Sean,

Thanks for your reply! My main concern is when calculating the DefectsThermodynamics object, it takes the correct vbm and band-gap but while making the FermiDos object for calculating the e-h concentrations, it uses the pymatgen states. Now I can circumvent this by change the code a little bit but I don’t want to break anything.

I haven’t run the bandstructure calculation yet, but what doped is giving through the DefectThermodynamics object is also correct. It’s the e-h concentrations that are referenced to the pymatgen’s DOS.

Does that make sense?

Thank you, Rushik

kavanase commented 2 weeks ago

Hmm ok I see. I appreciate you raising and checking this point.

So yes the pymatgen FermiDos object will return the wrong gap with get_gap(), but this shouldn't affect any of the carrier concentration / Fermi level functions in doped, which take the VBM and Fermi level values from the correctly-determined DefectThermodynamics VBM, as you can see here: https://github.com/SMTG-Bham/doped/blob/main/doped/thermodynamics.py#L3137 (the fermi_level used in this case is from DefectThermodynamics and is not aligned to any VBM eigenvalues (it's the raw Fermi level eigenvalue)).

Note that as stated in those docstrings, this means that no alignment is performed with the DefectThermodynamics VBM and DOS VBM, as they are assumed to have the same eigenvalue references (which should be the case if computed with the same functional and lattice constants)(and there is also the bulk_band_gap_vr option with DefectsParser in case the bulk VBM is not captured in the bulk supercell due to k-point sampling issues etc).

Still, I agree it would be nice for fermi_dos.get_gap() to just return the correct value... An issue with this is that it's not so straightforward to correctly determine the band gap from a DOS, as these may be smeared in some way which then makes the band edges less sharp. I can have a look at fixing this, if you could provide your DOS object as a json? With:

from monty.serialization import dumpfn
dumpfn(defect_thermo.fermi_dos, "fermi_dos.json")