Quick Start#
Installation#
The package can be installed from PyPI using pip install pymatgen-analysis-defects
.
Once installed, the different modules can be imported via the pymatgen.analysis.defects
namespace.
from pymatgen.analysis.defects import core, ccd, finder
To ensure that the namespace is installed properly run
from pymatgen.analysis.defects.core import __file__
and look at the __file__
variable to make sure that it is accessing the code from pymatgen-analysis-defect
and not pymatgen
.
Definition of a defect#
Our code defines defects using a combination of bulk structure and sites.
Since the bulk primitive structure is, in principle, unique up to arbitrary translations, equivalence of defects can be now easily checked using StructureMatcher
.
Below we show how you can create a basic substitutional defect from a pymatgen.core.Structure
object by replacing one of the Ga atoms in GaN with Mg.
Note that we create a MgGa defect by creating a PeriodicSite Object mg_ga
with the data of the first Ga site but
from pathlib import Path
from pymatgen.analysis.defects.core import Substitution
from pymatgen.core import PeriodicSite, Species, Structure
TEST_FILES = Path("../../../tests/test_files")
gan_struct = Structure.from_file(TEST_FILES / "GaN.vasp")
# make a substitution site
ga_site = gan_struct[0]
mg_site = PeriodicSite(
species=Species("Mg"), coords=ga_site.frac_coords, lattice=gan_struct.lattice
)
# instantiate the defect object
mg_ga = Substitution(structure=gan_struct, site=mg_site)
print(mg_ga)
Mg subsitituted on the Ga site at at site #0
mg_ga.defect_structure
Structure Summary
Lattice
abc : 3.2162901334217344 3.2162901334217344 5.239962
angles : 90.0 90.0 120.00000274450079
volume : 46.9428220153705
A : 1.608145 -2.785389 0.0
B : 1.608145 2.785389 0.0
C : 0.0 0.0 5.239962
pbc : True True True
PeriodicSite: Mg (1.608, -0.9285, 2.615) [0.6667, 0.3333, 0.4991]
PeriodicSite: Ga (Ga3+) (1.608, 0.9285, 5.235) [0.3333, 0.6667, 0.9991]
PeriodicSite: N (N3-) (1.608, -0.9285, 4.59) [0.6667, 0.3333, 0.8759]
PeriodicSite: N (N3-) (1.608, 0.9285, 1.97) [0.3333, 0.6667, 0.3759]
Instantiating FormationEnergyDiagram
#
The object responsible for analyzing the formation energy is described by the following fields.
FormationEnergyDiagram(
bulk_entry: 'ComputedStructureEntry',
defect_entries: 'List[DefectEntry]',
pd_entries: 'list[ComputedEntry]',
vbm: 'float',
band_gap: 'Optional[float]' = None,
inc_inf_values: 'bool' = True,
)
Using a convenience constructor with_directories
you can just feed in dictionary of {str
: Path
}
pointing to the directories where the supercell calculations are stored.
The keys, other than bulk
will be the charge states of the calculations.
As long as the vasprun.xml
and LOCPOT
files are in the directories the FormationEnergyDiagram
object can be constructed.
import warnings
from monty.serialization import loadfn
from pymatgen.analysis.defects.thermo import FormationEnergyDiagram
from pymatgen.io.vasp import Vasprun
warnings.filterwarnings("ignore")
sc_dir = TEST_FILES / "Mg_Ga"
# ents = MPRester().get_entries_in_chemsys("Mg-Ga-N") # Query from MPRester
ents = loadfn(TEST_FILES / "Ga_Mg_N.json") # Load from local
fed = FormationEnergyDiagram.with_directories(
directory_map={
"bulk": sc_dir / "bulk_sc",
0: sc_dir / "q=0",
-1: sc_dir / "q=-1",
1: sc_dir / "q=1",
},
defect=mg_ga,
pd_entries=ents,
dielectric=10,
)
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
Cell In[5], line 12
10 # ents = MPRester().get_entries_in_chemsys("Mg-Ga-N") # Query from MPRester
11 ents = loadfn(TEST_FILES / "Ga_Mg_N.json") # Load from local
---> 12 fed = FormationEnergyDiagram.with_directories(
13 directory_map={
14 "bulk": sc_dir / "bulk_sc",
15 0: sc_dir / "q=0",
16 -1: sc_dir / "q=-1",
17 1: sc_dir / "q=1",
18 },
19 defect=mg_ga,
20 pd_entries=ents,
21 dielectric=10,
22 )
File ~/work/pymatgen-analysis-defects/pymatgen-analysis-defects/pymatgen/analysis/defects/thermo.py:450, in FormationEnergyDiagram.with_directories(cls, directory_map, defect, pd_entries, dielectric, vbm, **kwargs)
443 q_entry, q_locpot = _read_dir(q_dir)
444 q_d_entry = DefectEntry(
445 defect=defect,
446 charge_state=int(qq),
447 sc_entry=q_entry,
448 )
--> 450 q_d_entry.get_freysoldt_correction(
451 defect_locpot=q_locpot,
452 bulk_locpot=bulk_locpot,
453 dielectric=dielectric,
454 )
455 def_entries.append(q_d_entry)
456 if vbm is None:
File ~/work/pymatgen-analysis-defects/pymatgen-analysis-defects/pymatgen/analysis/defects/thermo.py:148, in DefectEntry.get_freysoldt_correction(self, defect_locpot, bulk_locpot, dielectric, defect_struct, bulk_struct, **kwargs)
143 raise ValueError(
144 msg,
145 )
147 if self.sc_defect_frac_coords is None:
--> 148 finder = DefectSiteFinder()
149 defect_fpos = finder.get_defect_fpos(
150 defect_structure=defect_struct,
151 base_structure=bulk_struct,
152 )
153 self.sc_defect_frac_coords = defect_fpos
File ~/work/pymatgen-analysis-defects/pymatgen-analysis-defects/pymatgen/analysis/defects/finder.py:61, in DefectSiteFinder.__init__(self, symprec, angle_tolerance)
59 if SOAP is None:
60 msg = "dscribe is required to use DefectSiteFinder. Install with ``pip install dscribe``."
---> 61 raise ImportError(
62 msg,
63 )
64 self.symprec = symprec
65 self.angle_tolerance = angle_tolerance
ImportError: dscribe is required to use DefectSiteFinder. Install with ``pip install dscribe``.
Getting the formation energy diagram#
The chemical potential limits can be access using:
fed.chempot_limits
If you have crystal_toolkit
and the its jupyter lab extensions installed you can view the chemical potential diagram by importing crystal_toolkit
and running a cell with the the chempot_diagram
on the last line.
import crystal_toolkit
fed.chempot_diagram
Note that it is different from chemical potential plot hosted on the material project because the elemental phases are set to zero energy.
Now we can plot the formation energy diagram by calculating the Fermi level and formation energy at the different charge state transitions.
import numpy as np
from matplotlib import pyplot as plt
ts = np.array(fed.get_transitions(fed.chempot_limits[1], x_max=5))
plt.plot(ts[:, 0], ts[:, 1], "-o")
plt.xlabel("Fermi Level (eV)")
plt.ylabel("Formation Energy(eV)")