Defect generation#
defermi can be used to generate defects structures to be used in atomistic simulations or analysis. The library returns objects from the defects module, in particular:
VacancySubstitutionsInterstitials
defermi uses the pymatgen.symmetry.analyzer.SpacegroupAnalyzer class to defect non-symmetry-equivalent lattice sites, and returns for each a defect object.
We start from a pristine structure, in this example from the tetragonal phase of \(\mathrm{BaTiO_3}\).
[17]:
from pymatgen.core import Structure
structure_bulk = Structure.from_dict({
"@module": "pymatgen.core.structure", "@class": "Structure", "charge": 0,
"lattice": {"matrix": [
[3.99037921, 0.0, 2.4434025634553223e-16],
[6.417019188399763e-16, 3.99037921, 2.4434025634553223e-16],
[0.0, 0.0, 4.10265539]],
"pbc": [True, True, True],
"a": 3.99037921, "b": 3.99037921, "c": 4.10265539,
"alpha": 90.0, "beta": 90.0, "gamma": 89.99999999999999,
"volume": 65.32709969254628},
"properties": {},
"sites": [
{"species": [{"element": "Ba","occu": 1}], "abc": [0.5, 0.5, 0.5825414600000001], "properties": {}, "label": "Ba2+", "xyz": [1.9951896050000002, 1.995189605, 2.38996686076747]},
{"species": [{"element": "Ti","occu": 1}], "abc": [0.0, 0.0, 0.1000427], "properties": {}, "label": "Ti4+", "xyz": [0.0, 0.0, 0.41044072238515295]},
{"species": [{"element": "O", "occu": 1}], "abc": [0.0, 0.5, 0.06422054], "properties": {}, "label": "O2-", "xyz": [3.2085095941998815e-16, 1.995189605, 0.26347474457971076]},
{"species": [{"element": "O", "occu": 1}], "abc": [0.5, 0.0, 0.06422054], "properties": {}, "label": "O2-", "xyz": [1.995189605, 0.0, 0.26347474457971076]},
{"species": [{"element": "O", "occu": 1}], "abc": [0.0, 0.0, 0.54897175], "properties": {}, "label": "O2-", "xyz": [0.0, 0.0, 2.252241909095232]}
]
})
structure_bulk
[17]:
Structure Summary
Lattice
abc : 3.99037921 3.99037921 4.10265539
angles : 90.0 90.0 90.0
volume : 65.32709969254628
A : np.float64(3.99037921) np.float64(0.0) np.float64(2.4434025634553223e-16)
B : np.float64(6.417019188399763e-16) np.float64(3.99037921) np.float64(2.4434025634553223e-16)
C : np.float64(0.0) np.float64(0.0) np.float64(4.10265539)
pbc : True True True
PeriodicSite: Ba2+ (Ba) (1.995, 1.995, 2.39) [0.5, 0.5, 0.5825]
PeriodicSite: Ti4+ (Ti) (0.0, 0.0, 0.4104) [0.0, 0.0, 0.1]
PeriodicSite: O2- (O) (3.209e-16, 1.995, 0.2635) [0.0, 0.5, 0.06422]
PeriodicSite: O2- (O) (1.995, 0.0, 0.2635) [0.5, 0.0, 0.06422]
PeriodicSite: O2- (O) (0.0, 0.0, 2.252) [0.0, 0.0, 0.549]
Vacancies#
Specify which elements must form a vacancy with the elements argument. If elements is not specified vacancies for all species are generated. Generate a defect in a supercell with the supercell_size argument. Pass kwargs to the SpaceGroupAnalyzer class to change symmetry criteria for the lattice site classification.
[ ]:
from defermi.generator import create_vacancies, create_interstitials
defects = create_vacancies(structure=structure_bulk, elements=None, supercell_size=3)
defects
[Defect: type=Vacancy, species=Ba, label=a, site= [0.16666667 0.16666667 0.19418049],
Defect: type=Vacancy, species=Ti, label=a, site= [0. 0. 0.03334757],
Defect: type=Vacancy, species=O, label=a, site= [0. 0.16666667 0.02140685],
Defect: type=Vacancy, species=O, label=b, site= [0. 0. 0.18299058]]
Defect gets assigned a different label.charge property. Use the set_charge method to assign it. Several properties can be accessed through the Defect object. Use the generate_defect_structure method to create a Structure object containing the defect.[21]:
defect = defects[-1]
defect.set_charge(2) # set defect charge
print(f"Defect name: {defect.name}")
print(f"Defect type: {defect.type}")
print(f"Defect species: {defect.specie}")
print(f"Defect label: {defect.label}")
print(f"Particle number difference btw defect and pristine material: {defect.delta_atoms}")
print(f"Symbol: {defect.symbol_with_charge}")
print(f"Symbol in Kröger-Vink notation: {defect.symbol_with_charge_kv}")
# get structure containing defect
defect.generate_defect_structure().composition
Defect name: Vac_O(b)
Defect type: Vacancy
Defect species: O
Defect label: b
Particle number difference btw defect and pristine material: {'O': -1}
Symbol: $V_{O}$(b)$^{+2}$
Symbol in Kröger-Vink notation: $V_{O}$(b)$^{°°}$
[21]:
Composition('Ba27 Ti27 O80')
Substitutions#
Substitution objects. Use the elements_to_replace argument to specify the substituting and substituted elements.dict in this format: {"element to be replaced":"element to replace with"}.Let’s substitute Ti with Fe and assign it a \(-1\) charge.
[28]:
from defermi.generator import create_substitutions
defects = create_substitutions(
structure=structure_bulk,
elements_to_replace={'Ti':'Fe'},
supercell_size=3)
defect = defects[0]
defect.set_charge(-1)
print(defect.symbol_with_charge)
defect.generate_defect_structure().composition
$Fe_{Ti}$(a)$^{-1}$
[28]:
Composition('Ba27 Fe1 Ti26 O81')
Interstitials#
Interstitials are definitely not as straightforward as vacancies and substitutions. defermi relies on pymatgen.analysis.defects.generators.VoronoiInterstitialGenerator. Change defaults using kwargs:
clustering_tol: Tolerance for clustering the Voronoi nodesmin_dist: Minimum distance between an interstitial and the nearest atomltol: Tolerance for lattice matchingstol: Tolerance for structure matchingangle_tol: Angle tolerance for structure matchingkwargs: Additional keyword arguments for theTopographyAnalyzerconstructor
The function returns a list of Interstitial objects.
[31]:
from defermi.generator import create_interstitials
defects = create_interstitials(structure=structure_bulk,elements=['O'],supercell_size=3)
defects
[31]:
[Defect: type=Interstitial, species=O, label=mult216, site= [0.07860922 0.74527589 0.60653553],
Defect: type=Interstitial, species=O, label=mult81, site= [0.33333333 0.83333333 0.52150661]]
[37]:
# lattice site multiplicity is stored in the defect label
for defect in defects:
print(f"Interstitial with multiplicity: {defect.label.strip('mult')}")
defect.set_charge(-2) # set interstitial charge
print(f"Defect name: {defect.name}")
print(f"Defect type: {defect.type}")
print(f"Defect species: {defect.specie}")
print(f"Defect label: {defect.label}")
print(f"Particle number difference btw defect and pristine material: {defect.delta_atoms}")
print(f"Symbol: {defect.symbol_with_charge}")
print(f"Symbol in Kröger-Vink notation: {defect.symbol_with_charge_kv}")
# get structure containing defect
print(f"Composition: {defect.generate_defect_structure().composition}\n")
Interstitial with multiplicity: 216
Defect name: Int_O(mult216)
Defect type: Interstitial
Defect species: O
Defect label: mult216
Particle number difference btw defect and pristine material: {'O': 1}
Symbol: $O_i$(mult216)$^{-2}$
Symbol in Kröger-Vink notation: $O_i$(mult216)$^{''}$
Composition: Ba27 Ti27 O82
Interstitial with multiplicity: 81
Defect name: Int_O(mult81)
Defect type: Interstitial
Defect species: O
Defect label: mult81
Particle number difference btw defect and pristine material: {'O': 1}
Symbol: $O_i$(mult81)$^{-2}$
Symbol in Kröger-Vink notation: $O_i$(mult81)$^{''}$
Composition: Ba27 Ti27 O82