doped.thermodynamics module
Code for analysing the thermodynamics of defect formation in solids, including calculation of formation energies as functions of Fermi level and chemical potentials, charge transition levels, defect/carrier concentrations etc.
- class doped.thermodynamics.DefectThermodynamics(defect_entries: dict[str, DefectEntry] | list[DefectEntry], chempots: dict | None = None, el_refs: dict | None = None, vbm: float | None = None, band_gap: float | None = None, dist_tol: float = 1.5, check_compatibility: bool = True, bulk_dos: FermiDos | None = None, skip_dos_check: bool = False)[source]
Bases:
MSONable
Class for analysing the calculated thermodynamics of defects in solids. Similar to a
pymatgen
PhaseDiagram
object, allowing the analysis of formation energies as functions of Fermi level and chemical potentials (i.e. defect formation energy / transition level diagrams), charge transition levels, defect/carrier concentrations as functions of temperature, chemical potential etc.- This class can be used to return:
defect formation energy diagrams (plots),
stability of charge states for a given defect,
tables of all formation energies / symmetries & degeneracies,
tables of equilibrium and constrained defect/carrier concentrations,
charge transition levels, including metastable states,
doping analysis,
…
Note that
DefectThermodynamics
objects can be used to initialise theFermiSolver
class in this module, which implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), and also allowing greater control over constraints and approximations in defect concentration calculations; such as specifying (known) fixed concentrations of a defect/dopant, specifying defects to exclude from high-temperature concentration fixing in the frozen defect approximation (e.g. highly-mobile defects), and/or fixing defect charge states upon quenching.Create a
DefectThermodynamics
object, which can be used to analyse the calculated thermodynamics of defects in solids (formation energies, transition levels, concentrations etc.).Usually initialised using
DefectsParser.get_defect_thermodynamics()
, but can also be initialised with a list or dict ofDefectEntry
objects (e.g. fromDefectsParser.defect_dict
).Note that the
DefectEntry.name
attributes are used to label the defects in plots.- Parameters:
defect_entries (dict[str, DefectEntry] or list[DefectEntry]) – A dict or list of
DefectEntry
objects. Note thatDefectEntry.name
attributes are used for grouping and plotting purposes! These should be in the format “{defect_name}_{optional_site_info}_{charge_state}”. If theDefectEntry.name
attribute is not defined or does not end with the charge state, then the entry will be renamed with the doped default name.chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies. This can have the form of
{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) which allows easy analysis over a range of chemical potentials - where limit(s) (chemical potential limit(s)) to analyse/plot can later be chosen using thelimits
argument.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases in order to show the formal (relative) chemical potentials above the formation energy plot, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.If
None
(default), sets all chemical potentials to zero. Chemical potentials can also be supplied later in each analysis function, or set usingDefectThermodynamics.chempots = ...
(with the same input options).el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided in format generated bydoped
(see tutorials).If
None
(default), sets all elemental reference energies to zero. Reference energies can also be supplied later in each analysis function, or set usingDefectThermodynamics.el_refs = ...
(with the same input options).vbm (float) – VBM eigenvalue to use as Fermi level reference point for analysis. If None (default), will use
"vbm"
from thecalculation_metadata
dict attributes of the parsedDefectEntry
objects, which by default is taken from the bulk supercell VBM (unlessbulk_band_gap_vr
is set during defect parsing). Note thatvbm
should only affect the reference for the Fermi level values output bydoped
(as this VBM eigenvalue is used as the zero reference), thus affecting the position of the band edges in the defect formation energy plots and doping window / dopability limit functions, and the reference of the reported Fermi levels.band_gap (float) – Band gap of the host, to use for analysis. If
None
(default), will use “band_gap” from the calculation_metadata dict attributes of the DefectEntry objects indefect_entries
.dist_tol (float) – Threshold for the closest distance (in Å) between equivalent defect sites, for different species of the same defect type, to be grouped together (for plotting, transition level analysis and defect concentration calculations). In most cases, if the minimum distance between equivalent defect sites is less than
dist_tol
, then they will be grouped together, otherwise treated as separate defects. Seeplot()
andget_fermi_level_and_concentrations()
docstrings for more information. (Default: 1.5)check_compatibility (bool) – Whether to check the compatibility of the bulk entry for each defect entry (i.e. that all reference bulk energies are the same). (Default: True)
bulk_dos (FermiDos or Vasprun or PathLike) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating Fermi level positions and defect/carrier concentrations. Alternatively, can be apymatgen
Vasprun
object or path to thevasprun.xml(.gz)
output of a bulk DOS calculation in VASP. Can also be provided later when usingget_equilibrium_fermi_level()
,get_fermi_level_and_concentrations
etc., or set usingDefectThermodynamics.bulk_dos = ...
(with the same input options).Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculations (Default: None)skip_dos_check (bool) – Whether to skip the warning about the DOS VBM differing from the defect entries VBM by >0.05 eV. Should only be used when the reason for this difference is known/acceptable. (Default: False)
- Key Attributes:
- defect_entries (dict[str, DefectEntry]):
Dict of
DefectEntry
objects included in theDefectThermodynamics
set, with their names as keys.- chempots (dict):
Dictionary of chemical potentials to use for calculating the defect formation energies (and hence concentrations etc), in the
doped
format.- el_refs (dict):
Dictionary of elemental reference energies for the chemical potentials.
- vbm (float):
VBM energy to use as Fermi level reference point for analysis.
- band_gap (float):
Band gap of the host, to use for analysis.
- dist_tol (float):
Threshold for the closest distance (in Å) between equivalent defect sites, for different species of the same defect type, to be grouped together (for plotting, transition level analysis and defect concentration calculations).
- transition_levels (dict):
Dictionary of charge transition levels for each defect entry. (e.g.
{defect_name: {charge: transition_level}}
).- check_compatibility (bool):
Whether to check the compatibility of the bulk entry for each defect entry (i.e. that all reference bulk energies are the same).
- bulk_formula (str):
The reduced formula of the bulk structure (e.g. “CdTe”).
- bulk_dos (FermiDos):
pymatgen
FermiDos
for the bulk electronic density of states (DOS), used for calculating Fermi level positions and defect/carrier concentrations.- skip_dos_check (bool):
Whether to skip the warning about the DOS VBM differing from the defect entries VBM by >0.05 eV. Should only be used when the reason for this difference is known/acceptable.
- add_entries(defect_entries: dict[str, DefectEntry] | list[DefectEntry], check_compatibility: bool = True)[source]
Add additional defect entries to the DefectThermodynamics object.
- Parameters:
({str (defect_entries) – DefectEntry} or [DefectEntry]): A dict or list of
DefectEntry
objects, to add to theDefectThermodynamics.defect_entries
dict. Note thatDefectEntry.name
attributes are used for grouping and plotting purposes! These should be in the format “{defect_name}_{optional_site_info}_{charge_state}”. If theDefectEntry.name
attribute is not defined or does not end with the charge state, then the entry will be renamed with the doped default name.check_compatibility (bool) – Whether to check the compatibility of the bulk entry for each defect entry (i.e. that all reference bulk energies are the same). (Default: True)
- property all_stable_entries
List all stable entries (defect + charge) in the
DefectThermodynamics
set.
- property all_unstable_entries
List all unstable entries (defect + charge) in the
DefectThermodynamics
set.
- property bulk_dos
Get the
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating Fermi level positions and defect/carrier concentrations, if set.Otherwise, returns None.
- property chempots
Get the chemical potentials dictionary used for calculating the defect formation energies.
chempots
is a dictionary of chemical potentials to use for calculating the defect formation energies, in the form of:{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) which allows easy analysis over a range of chemical potentials - where limit(s) (chemical potential limit(s)) to analyse/plot can later be chosen using thelimits
argument.
- property defect_entries
Get the dict of parsed
DefectEntry
objects in theDefectThermodynamics
analysis object.
- property defect_names
List of names of defects in the
DefectThermodynamics
set.
- property dist_tol
Get the distance tolerance (in Å) used for grouping defects together (for plotting, transition level analysis and defect concentration calculations) based on the distances between their symmetry-equivalent sites.
For the most part,
DefectEntry
s of the same type and with distances between equivalent defect sites less thandist_tol
(1.5 Å by default) are grouped together. If aDefectEntry
's site has a distance less thandist_tol
to multiple sets of equivalent sites, then it should be matched to the one with the lowest minimum distance.This is used to group together different defect entries (different charge states, and/or ground and metastable states (different spin or geometries)) which correspond to the same defect type (e.g. interstitials at a given site), which is then used in plotting, transition level analysis and defect concentration calculations; e.g. in the frozen defect approximation, the total concentration of a given defect type group is calculated at the annealing temperature, and then the equilibrium relative population of the constituent entries is recalculated at the quenched temperature.
- property el_refs
Get the elemental reference energies for the chemical potentials.
This is in the form of a dictionary of elemental reference energies for the chemical potentials, in the format:
{element symbol: reference energy}
.
- classmethod from_dict(d)[source]
Reconstitute a
DefectThermodynamics
object from a dict representation created usingas_dict()
.- Parameters:
d (dict) – dict representation of
DefectThermodynamics
.- Returns:
DefectThermodynamics
object
- classmethod from_json(filename: str | PathLike)[source]
Load a
DefectThermodynamics
object from a json(.gz) file.Note that
.json.gz
files can be loaded directly.- Parameters:
filename (PathLike) – Filename of json file to load
DefectThermodynamics
object from.- Returns:
DefectThermodynamics
object
- get_dopability_limits(chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None) DataFrame [source]
Find the dopability limits of the defect system, searching over all limits (chemical potential limits) in
chempots
and returning the most p/n-type conditions, or for a given chemical potential limit (iflimit
is set orchempots
corresponds to a single chemical potential limit; i.e. {element symbol: chemical potential}).The dopability limites are defined by the (first) Fermi level positions at which defect formation energies become negative as the Fermi level moves towards/beyond the band edges, thus determining the maximum possible Fermi level range upon doping for this chemical potential limit.
Note that the Fermi level positions are given relative to
self.vbm
, which is the VBM eigenvalue of the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing.This is computed by obtaining the formation energy for every stable defect with non-zero charge, and then finding the highest Fermi level position at which a donor defect (positive charge) has zero formation energy (crosses the x-axis) - giving the lower dopability limit, and the lowest Fermi level position at which an acceptor defect (negative charge) has zero formation energy - giving the upper dopability limit.
- Parameters:
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus dopability limits). If
None
(default), will useself.chempots
. This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to calculate formation energies (and thus dopability limits). Can be either:
None
, in which case we search over all limits (chemical potential limits) inchempots
and return the most n/p-type conditions, unlesschempots
corresponds to a single chemical potential limit."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)
- Returns:
“limit”, “Compensating Defect”, “Dopability Limit” for both p/n-type where ‘Dopability limit’ are the corresponding Fermi level positions in eV, relative to the VBM (
self.vbm
).- Return type:
pandas
DataFrame
of dopability limits, with columns
- get_doping_windows(chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None) DataFrame [source]
Find the doping windows of the defect system, searching over all limits (chemical potential limits) in
chempots
and returning the most p/n-type conditions, or for a given chemical potential limit (iflimit
is set orchempots
corresponds to a single chemical potential limit; i.e. {element symbol: chemical potential}).Doping window is defined by the formation energy of the lowest energy compensating defect species at the corresponding band edge (i.e. VBM for hole doping and CBM for electron doping), as these set the upper limit to the formation energy of dopants which could push the Fermi level close to the band edge without being negated by defect charge compensation.
Note that the band edge positions are taken from
self.vbm
andself.band_gap
, which are parsed from the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing.If a dopant has a higher formation energy than the doping window at the band edge, then its charge will be compensated by formation of the corresponding limiting defect species (rather than free carrier populations).
- Parameters:
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus doping windows). If
None
(default), will useself.chempots
. This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to calculate formation energies (and thus doping windows). Can be either:
None
, in which case we search over all limits (chemical potential limits) inchempots
and return the most n/p-type conditions, unlesschempots
corresponds to a single chemical potential limit."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)
- Returns:
“limit”, “Compensating Defect”, “Doping Window” for both p/n-type where ‘Doping Window’ are the corresponding doping windows in eV.
- Return type:
pandas
DataFrame
of doping windows, with columns
- get_equilibrium_concentrations(temperature: float = 300, chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, fermi_level: float | None = None, per_charge: bool = True, per_site: bool = False, skip_formatting: bool = False, site_competition: bool | str = True, lean: bool = False) DataFrame [source]
Compute the equilibrium concentrations (in cm^-3) for all
DefectEntry
s in theDefectThermodynamics
object, at a given chemical potential limit, Fermi level and temperature, assuming the dilute limit approximation.Note that these are the equilibrium defect concentrations!
DefectThermodynamics.get_fermi_level_and_concentrations()
can instead be used to calculate the Fermi level and defect concentrations for a material grown/annealed at higher temperatures and then cooled (quenched) to room/operating temperature (where defect concentrations are assumed to remain fixed) - this is known as the frozen defect approach and is typically the most valid approximation (see its docstring for more information).The degeneracy/multiplicity factor “g” is an important parameter in the defect concentration equation (see discussion in https://doi.org/10.1039/D2FD00043A and https://doi.org/10.1039/D3CS00432E), affecting the final concentration by up to ~2 orders of magnitude. This factor is taken from the product of the
defect_entry.defect.multiplicity
anddefect_entry.degeneracy_factors
attributes.Note that the
FermiSolver
class implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), and also allowing greater control over constraints and approximations in defect concentration calculations (i.e. fixed/variable defect(s) and charge states), which may be useful. See theFermiSolver
tutorial: https://doped.readthedocs.io/en/latest/fermisolver_tutorial.html- Parameters:
temperature (float) – Temperature in Kelvin at which to calculate the equilibrium concentrations. Default is 300 K.
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations). If
None
(default), will useself.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (
limit
), in the format:{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to obtain the equilibrium concentrations. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)fermi_level (float) – Value corresponding to the electron chemical potential, referenced to the VBM (using
self.vbm
, which is the VBM of the bulk supercell calculation by default). If None (default), set to the mid-gap Fermi level (E_g/2).per_charge (bool) – Whether to break down the defect concentrations into individual defect charge states (e.g.
v_Cd_0
,v_Cd_-1
,v_Cd_-2
instead ofv_Cd
). (default: True)per_site (bool) – Whether to return the concentrations as percent concentrations per site, rather than the default of per cm^3. (default: False)
skip_formatting (bool) – Whether to skip formatting the defect charge states and concentrations as strings (and keep as
int
s andfloat
s instead). (default: False)site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.lean (bool) – Whether to return a leaner
DataFrame
with only the defect name, charge state, and concentration in cm^-3 (assumesskip_formatting=True
andper_site=False
). Only really intended for internaldoped
usage, to reduce compute times when calculating defect concentrations repeatedly. (default: False)
- Returns:
pandas
DataFrame
of defect concentrations (and formation energies) for eachDefectEntry
in theDefectThermodynamics
object.
- get_equilibrium_fermi_level(bulk_dos: FermiDos | Vasprun | str | PathLike | None = None, temperature: float = 300, chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, return_concs: bool = False, skip_dos_check: bool = False, effective_dopant_concentration: float | None = None, site_competition: bool = True) float | tuple[float, float, float] [source]
Calculate the self-consistent Fermi level, at a given chemical potential limit and temperature, assuming equilibrium defect concentrations (i.e. under annealing) and the dilute limit approximation, by self-consistently solving for the Fermi level which yields charge neutrality.
Note that the returned Fermi level is given relative to
self.vbm
, which is the VBM eigenvalue of the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing.Note that this assumes equilibrium defect concentrations!
DefectThermodynamics.get_fermi_level_and_concentrations()
can instead be used to calculate the Fermi level and defect concentrations for a material grown/annealed at higher temperatures and then cooled (quenched) to room/operating temperature (where defect concentrations are assumed to remain fixed) - this is known as the frozen defect approach and is typically the most valid approximation (see its docstring for more information).Note that the bulk DOS calculation should be well-converged with respect to k-points for accurate Fermi level predictions!
The degeneracy/multiplicity factor “g” is an important parameter in the defect concentration equation (see discussion in https://doi.org/10.1039/D2FD00043A and https://doi.org/10.1039/D3CS00432E), affecting the final concentration by up to ~2 orders of magnitude. This factor is taken from the product of the
defect_entry.defect.multiplicity
anddefect_entry.degeneracy_factors
attributes.Note that the
FermiSolver
class implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), and also allowing greater control over constraints and approximations in defect concentration calculations (i.e. fixed/variable defect(s) and charge states), which may be useful. See theFermiSolver
tutorial: https://doped.readthedocs.io/en/latest/fermisolver_tutorial.html- Parameters:
bulk_dos (FermiDos or Vasprun or PathLike) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating carrier concentrations. Alternatively, can be apymatgen
Vasprun
object or path to thevasprun.xml(.gz)
output of a bulk DOS calculation in VASP – however this will be much slower when looping over many conditions as it will re-parse the DOS each time! (So preferably useget_fermi_dos()
as shown in the defect thermodynamics tutorial).Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsbulk_dos
can also be left asNone
(default), if it has previously been provided and parsed, and thus is set as theself.bulk_dos
attribute. If provided, will overwrite theself.bulk_dos
attribute!temperature (float) – Temperature in Kelvin at which to calculate the equilibrium Fermi level. Default is 300 K.
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations and Fermi level). If
None
(default), will useself.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to determine the equilibrium Fermi level. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)return_concs (bool) – Whether to return the corresponding electron and hole concentrations (in cm^-3) as well as the Fermi level. (default: False)
skip_dos_check (bool) – Whether to skip the warning about the DOS VBM differing from
self.vbm
by >0.05 eV. Should only be used when the reason for this difference is known/acceptable. (default: False)effective_dopant_concentration (float) – Fixed concentration (in cm^-3) of an arbitrary dopant/impurity in the material to include in the charge neutrality condition, in order to analyse the Fermi level / doping response under hypothetical doping conditions. If a negative value is given, the dopant is assumed to be an acceptor dopant (i.e. negative defect charge state), while a positive value corresponds to donor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. (Default: None; no extrinsic dopant)site_competition (bool) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentrations, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
Self consistent Fermi level (in eV from the VBM (
self.vbm
)), and the corresponding electron and hole concentrations (in cm^-3) ifreturn_concs=True
.
- get_fermi_level_and_concentrations(bulk_dos: FermiDos | Vasprun | str | PathLike | None = None, annealing_temperature: float = 1000, quenched_temperature: float = 300, chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, delta_gap: float = 0, per_charge: bool = True, per_site: bool = False, skip_formatting: bool = False, return_annealing_values: bool = False, effective_dopant_concentration: float | None = None, site_competition: bool | str = True, **kwargs) tuple[float, float, float, DataFrame] | tuple[float, float, float, DataFrame, float, float, float, DataFrame] [source]
Calculate the self-consistent Fermi level and corresponding carrier/defect calculations, for a given chemical potential limit, annealing temperature and quenched/operating temperature, using the frozen defect and dilute limit approximations under the constraint of charge neutrality.
This function works by calculating the self-consistent Fermi level and total concentration of each defect type at the annealing temperature, then fixing the total concentrations to these values and re-calculating the self-consistent (constrained equilibrium) Fermi level and relative charge state concentrations under this constraint at the quenched/operating temperature.
According to the ‘frozen defect’ approximation, we typically expect defect concentrations to reach equilibrium during annealing/crystal growth (at elevated temperatures), but not upon quenching (i.e. at room/operating temperature) where we expect kinetic inhibition of defect annhiliation and hence non-equilibrium defect concentrations / Fermi level. Typically, this is approximated by computing the equilibrium Fermi level and defect concentrations at the annealing temperature, and then assuming the total concentration of each defect is fixed to this value, but that the relative populations of defect charge states (and the Fermi level) can re-equilibrate at the lower (room) temperature. See discussion in https://doi.org/10.1039/D3CS00432E (brief), https://doi.org/10.1016/j.cpc.2019.06.017 (detailed) and
doped
/py-sc-fermi
tutorials for more information. In certain cases (such as Li-ion battery materials or extremely slow charge capture/emission), these approximations may have to be adjusted such that some defects/charge states are considered fixed and some are allowed to re-equilibrate (e.g. highly mobile Li vacancies/interstitials). TheFermiSolver
class can be used in these cases for more fine-grained control over constraints and approximations in defect concentration calculations, as demonstrated in the tutorial: https://doped.readthedocs.io/en/latest/fermisolver_tutorial.htmlNote that different defect entries (different charge states, and/or ground and metastable states (different spin or geometries); e.g. interstitials at a given site) are grouped together in distinct defect types according to
self.dist_tol
, which is also used in plotting and transition level analysis. In the frozen defect approximation here, the total concentration of a given defect type group is calculated at the annealing temperature, and then the equilibrium relative population of the constituent entries is recalculated at the quenched temperature.Note that the bulk DOS calculation should be well-converged with respect to k-points for accurate Fermi level predictions!
The degeneracy/multiplicity factor “g” is an important parameter in the defect concentration equation (see discussion in https://doi.org/10.1039/D2FD00043A and https://doi.org/10.1039/D3CS00432E), affecting the final concentration by up to ~2 orders of magnitude. This factor is taken from the product of the
defect_entry.defect.multiplicity
anddefect_entry.degeneracy_factors
attributes.Note that, in addition to finer-grained control over constraints and approximations as mentioned above, the
FermiSolver
class implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), which may be useful – see tutorial.- Parameters:
bulk_dos (FermiDos or Vasprun or PathLike) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating carrier concentrations. Alternatively, can be apymatgen
Vasprun
object or path to thevasprun.xml(.gz)
output of a bulk DOS calculation in VASP – however this will be much slower when looping over many conditions as it will re-parse the DOS each time! (So preferably useget_fermi_dos()
as shown in the defect thermodynamics tutorial).Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsbulk_dos
can also be left asNone
(default), if it has previously been provided and parsed, and thus is set as theself.bulk_dos
attribute. If provided, will overwrite theself.bulk_dos
attribute!annealing_temperature (float) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is 1000 K.
quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations and Fermi level). If
None
(default), will useself.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to determine the Fermi level and concentrations. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)delta_gap (float) – Change in band gap (in eV) of the host material at the annealing temperature (e.g. due to thermal renormalisation), relative to the original band gap of the
FermiDos
object (assumed to correspond to the quenched temperature). If set, applies a scissor correction tofermi_dos
which renormalises the band gap symmetrically about the VBM and CBM (i.e. assuming equal up/downshifts of the band-edges around their original eigenvalues) while the defect levels remain fixed. (Default: 0)per_charge (bool) – Whether to break down the defect concentrations into individual defect charge states (e.g.
v_Cd_0
,v_Cd_-1
,v_Cd_-2
instead ofv_Cd
). (default: True)per_site (bool) – Whether to return the concentrations as percent concentrations per site, rather than the default of per cm^3. (default: False)
skip_formatting (bool) – Whether to skip formatting the defect charge states and concentrations as strings (and keep as
int
s andfloat
s instead). (default: False)return_annealing_values (bool) – If True, also returns the Fermi level, electron and hole concentrations and defect concentrations at the annealing temperature. (default: False)
effective_dopant_concentration (float) – Fixed concentration (in cm^-3) of an arbitrary dopant/impurity in the material to include in the charge neutrality condition, in order to analyse the Fermi level / doping response under hypothetical doping conditions. If a negative value is given, the dopant is assumed to be an acceptor dopant (i.e. negative defect charge state), while a positive value corresponds to donor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. (Default: None; no extrinsic dopant)site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.**kwargs – Additional keyword arguments to pass to
scissor_dos
(ifdelta_gap
is not 0) or_parse_fermi_dos
(skip_dos_check
; to skip the warning about the DOS VBM differing fromself.vbm
by >0.05 eV; default is False).
- Returns:
Predicted quenched Fermi level (in eV from the VBM (
self.vbm
)), the corresponding electron and hole concentrations (in cm^-3) and a dataframe of the quenched defect concentrations (in cm^-3);(fermi_level, e_conc, h_conc, conc_df)
. Ifreturn_annealing_values=True
, also returns the annealing Fermi level, electron and hole concentrations and a dataframe of the annealing defect concentrations (in cm^-3);(fermi_level, e_conc, h_conc, conc_df, annealing_fermi_level, annealing_e_conc, annealing_h_conc, annealing_conc_df)
.
- get_formation_energies(chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, fermi_level: float | None = None, skip_formatting: bool = False) DataFrame | list[DataFrame] [source]
Generates defect formation energy tables (DataFrames) for either a single chemical potential limit (i.e. phase diagram
limit
) or each limit in the phase diagram (chempots dict), depending on inputlimit
andchempots
.Table Key: (all energies in eV):
- ‘Defect’:
Defect name (without charge)
- ‘q’:
Defect charge state.
- ‘ΔEʳᵃʷ’:
Raw DFT energy difference between defect and host supercell (E_defect - E_host).
- ‘qE_VBM’:
Defect charge times the VBM eigenvalue (to reference the Fermi level to the VBM)
- ‘qE_F’:
Defect charge times the Fermi level (referenced to the VBM if qE_VBM is not 0 (if “vbm” in
DefectEntry.calculation_metadata
)
- ‘Σμ_ref’:
Sum of reference energies of the elemental phases in the chemical potentials sum.
- ‘Σμ_formal’:
Sum of formal atomic chemical potential terms (Σμ_DFT = Σμ_ref + Σμ_formal).
- ‘E_corr’:
Finite-size supercell charge correction.
- ‘Eᶠᵒʳᵐ’:
Defect formation energy, with the specified chemical potentials and Fermi level. Equals the sum of all other terms.
- ‘Path’:
Path to the defect calculation folder.
- ‘Δ[E_corr]’:
Estimated error in the charge correction, from the variance of the potential in the sampling region.
- Parameters:
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies. If None (default), will use
self.chempots
. This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.If None (default), sets all chemical potentials to zero. Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to tabulate formation energies. Can be either:
None, in which case tables are generated for all limits in
chempots
.”X-rich”/”X-poor” where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).
A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)fermi_level (float) – Value corresponding to the electron chemical potential, referenced to the VBM eigenvalue, which is taken from the
calculation_metadata
dict attributes ofDefectEntry
s inself.defect_entries
if present, otherwiseself.vbm
– which correspond to the VBM of the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing).None
(default), set to the mid-gap Fermi level (E_g/2).skip_formatting (bool) – Whether to skip formatting the defect charge states as strings (and keep as
int
s andfloat
s instead). (default: False)
- Returns:
pandas
DataFrame
or list ofDataFrame
s
- get_formation_energy(defect_entry: str | DefectEntry, chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, fermi_level: float | None = None) float [source]
Compute the formation energy for a
DefectEntry
at a given chemical potential limit and fermi_level.defect_entry
can be a string of the defect name, of theDefectEntry
object itself.- Parameters:
defect_entry (str or DefectEntry) – Either a string of the defect entry name (in
DefectThermodynamics.defect_entries
), or aDefectEntry
object. If the defect name is given without the charge state, then the formation energy of the lowest energy (stable) charge state at the chosen Fermi level will be given.chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energy. If None (default), will use
self.chempots
. This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.If None (default), sets all chemical potentials to zero. Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to calculate the formation energy. Can be either:
None (default), if
chempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict.”X-rich”/”X-poor” where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).
A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)fermi_level (float) – Value corresponding to the electron chemical potential, referenced to the VBM (using
self.vbm
, which is the VBM of the bulk supercell calculation by default). If None (default), set to the mid-gap Fermi level (E_g/2).
- Returns:
Formation energy value (float)
- get_quenched_fermi_level_and_concentrations(bulk_dos: FermiDos | Vasprun | str | PathLike | None = None, annealing_temperature: float = 1000, quenched_temperature: float = 300, chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, delta_gap: float = 0, per_charge: bool = True, per_site: bool = False, skip_formatting: bool = False, return_annealing_values: bool = False, effective_dopant_concentration: float | None = None, site_competition: bool | str = True, **kwargs) tuple[float, float, float, DataFrame] | tuple[float, float, float, DataFrame, float, float, float, DataFrame]
Calculate the self-consistent Fermi level and corresponding carrier/defect calculations, for a given chemical potential limit, annealing temperature and quenched/operating temperature, using the frozen defect and dilute limit approximations under the constraint of charge neutrality.
This function works by calculating the self-consistent Fermi level and total concentration of each defect type at the annealing temperature, then fixing the total concentrations to these values and re-calculating the self-consistent (constrained equilibrium) Fermi level and relative charge state concentrations under this constraint at the quenched/operating temperature.
According to the ‘frozen defect’ approximation, we typically expect defect concentrations to reach equilibrium during annealing/crystal growth (at elevated temperatures), but not upon quenching (i.e. at room/operating temperature) where we expect kinetic inhibition of defect annhiliation and hence non-equilibrium defect concentrations / Fermi level. Typically, this is approximated by computing the equilibrium Fermi level and defect concentrations at the annealing temperature, and then assuming the total concentration of each defect is fixed to this value, but that the relative populations of defect charge states (and the Fermi level) can re-equilibrate at the lower (room) temperature. See discussion in https://doi.org/10.1039/D3CS00432E (brief), https://doi.org/10.1016/j.cpc.2019.06.017 (detailed) and
doped
/py-sc-fermi
tutorials for more information. In certain cases (such as Li-ion battery materials or extremely slow charge capture/emission), these approximations may have to be adjusted such that some defects/charge states are considered fixed and some are allowed to re-equilibrate (e.g. highly mobile Li vacancies/interstitials). TheFermiSolver
class can be used in these cases for more fine-grained control over constraints and approximations in defect concentration calculations, as demonstrated in the tutorial: https://doped.readthedocs.io/en/latest/fermisolver_tutorial.htmlNote that different defect entries (different charge states, and/or ground and metastable states (different spin or geometries); e.g. interstitials at a given site) are grouped together in distinct defect types according to
self.dist_tol
, which is also used in plotting and transition level analysis. In the frozen defect approximation here, the total concentration of a given defect type group is calculated at the annealing temperature, and then the equilibrium relative population of the constituent entries is recalculated at the quenched temperature.Note that the bulk DOS calculation should be well-converged with respect to k-points for accurate Fermi level predictions!
The degeneracy/multiplicity factor “g” is an important parameter in the defect concentration equation (see discussion in https://doi.org/10.1039/D2FD00043A and https://doi.org/10.1039/D3CS00432E), affecting the final concentration by up to ~2 orders of magnitude. This factor is taken from the product of the
defect_entry.defect.multiplicity
anddefect_entry.degeneracy_factors
attributes.Note that, in addition to finer-grained control over constraints and approximations as mentioned above, the
FermiSolver
class implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), which may be useful – see tutorial.- Parameters:
bulk_dos (FermiDos or Vasprun or PathLike) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating carrier concentrations. Alternatively, can be apymatgen
Vasprun
object or path to thevasprun.xml(.gz)
output of a bulk DOS calculation in VASP – however this will be much slower when looping over many conditions as it will re-parse the DOS each time! (So preferably useget_fermi_dos()
as shown in the defect thermodynamics tutorial).Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsbulk_dos
can also be left asNone
(default), if it has previously been provided and parsed, and thus is set as theself.bulk_dos
attribute. If provided, will overwrite theself.bulk_dos
attribute!annealing_temperature (float) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is 1000 K.
quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations and Fermi level). If
None
(default), will useself.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to determine the Fermi level and concentrations. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)delta_gap (float) – Change in band gap (in eV) of the host material at the annealing temperature (e.g. due to thermal renormalisation), relative to the original band gap of the
FermiDos
object (assumed to correspond to the quenched temperature). If set, applies a scissor correction tofermi_dos
which renormalises the band gap symmetrically about the VBM and CBM (i.e. assuming equal up/downshifts of the band-edges around their original eigenvalues) while the defect levels remain fixed. (Default: 0)per_charge (bool) – Whether to break down the defect concentrations into individual defect charge states (e.g.
v_Cd_0
,v_Cd_-1
,v_Cd_-2
instead ofv_Cd
). (default: True)per_site (bool) – Whether to return the concentrations as percent concentrations per site, rather than the default of per cm^3. (default: False)
skip_formatting (bool) – Whether to skip formatting the defect charge states and concentrations as strings (and keep as
int
s andfloat
s instead). (default: False)return_annealing_values (bool) – If True, also returns the Fermi level, electron and hole concentrations and defect concentrations at the annealing temperature. (default: False)
effective_dopant_concentration (float) – Fixed concentration (in cm^-3) of an arbitrary dopant/impurity in the material to include in the charge neutrality condition, in order to analyse the Fermi level / doping response under hypothetical doping conditions. If a negative value is given, the dopant is assumed to be an acceptor dopant (i.e. negative defect charge state), while a positive value corresponds to donor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. (Default: None; no extrinsic dopant)site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.**kwargs – Additional keyword arguments to pass to
scissor_dos
(ifdelta_gap
is not 0) or_parse_fermi_dos
(skip_dos_check
; to skip the warning about the DOS VBM differing fromself.vbm
by >0.05 eV; default is False).
- Returns:
Predicted quenched Fermi level (in eV from the VBM (
self.vbm
)), the corresponding electron and hole concentrations (in cm^-3) and a dataframe of the quenched defect concentrations (in cm^-3);(fermi_level, e_conc, h_conc, conc_df)
. Ifreturn_annealing_values=True
, also returns the annealing Fermi level, electron and hole concentrations and a dataframe of the annealing defect concentrations (in cm^-3);(fermi_level, e_conc, h_conc, conc_df, annealing_fermi_level, annealing_e_conc, annealing_h_conc, annealing_conc_df)
.
- get_symmetries_and_degeneracies(skip_formatting: bool = False, symprec: float | None = None) DataFrame [source]
Generates a table of the bulk-site & relaxed defect point group symmetries, spin/orientational/total degeneracies and (bulk-)site multiplicities for each defect in the
DefectThermodynamics
object.Table Key:
‘Defect’: Defect name (without charge)
‘q’: Defect charge state.
‘Site_Symm’: Point group symmetry of the defect site in the bulk cell.
‘Defect_Symm’: Point group symmetry of the relaxed defect.
‘g_Orient’: Orientational degeneracy of the defect.
‘g_Spin’: Spin degeneracy of the defect.
‘g_Total’: Total degeneracy of the defect.
‘Mult’: Multiplicity of the defect site in the bulk cell, per primitive unit cell.
For interstitials, the bulk site symmetry corresponds to the point symmetry of the interstitial site with no relaxation of the host structure, while for vacancies/substitutions it is simply the symmetry of their corresponding bulk site. This corresponds to the point symmetry of
DefectEntry.defect
, orcalculation_metadata["bulk_site"]/["unrelaxed_defect_structure"]
.Point group symmetries are taken from the calculation_metadata (“relaxed point symmetry” and “bulk site symmetry”) if present (should be, if parsed with doped and defect supercell doesn’t break host periodicity), otherwise are attempted to be recalculated.
Note: doped tries to use the defect_entry.defect_supercell to determine the relaxed site symmetry. However, it should be noted that this is not guaranteed to work in all cases; namely for non-diagonal supercell expansions, or sometimes for non-scalar supercell expansion matrices (e.g. a 2x1x2 expansion)(particularly with high-symmetry materials) which can mess up the periodicity of the cell. doped tries to automatically check if this is the case, and will warn you if so.
This can also be checked by using this function on your doped generated defects:
from doped.generation import get_defect_name_from_entry for defect_name, defect_entry in defect_gen.items(): print(defect_name, get_defect_name_from_entry(defect_entry, relaxed=False), get_defect_name_from_entry(defect_entry), "\n")
And if the point symmetries match in each case, then doped should be able to correctly determine the final relaxed defect symmetry (and orientational degeneracy) - otherwise periodicity-breaking prevents this.
If periodicity-breaking prevents auto-symmetry determination, you can manually determine the relaxed defect and bulk-site point symmetries, and/or orientational degeneracy, from visualising the structures (e.g. using VESTA)(can use
get_orientational_degeneracy
to obtain the corresponding orientational degeneracy factor for given defect/bulk-site point symmetries) and setting the corresponding values in thecalculation_metadata['relaxed point symmetry']/['bulk site symmetry']
and/ordegeneracy_factors['orientational degeneracy']
attributes. Note that the bulk-site point symmetry corresponds to that ofDefectEntry.defect
, or equivalentlycalculation_metadata["bulk_site"]/["unrelaxed_defect_structure"]
, which for vacancies/substitutions is the symmetry of the corresponding bulk site, while for interstitials it is the point symmetry of the final relaxed interstitial site when placed in the (unrelaxed) bulk structure. The degeneracy factor is used in the calculation of defect/carrier concentrations and Fermi level behaviour (see e.g. https://doi.org/10.1039/D2FD00043A & https://doi.org/10.1039/D3CS00432E).- Parameters:
skip_formatting (bool) – Whether to skip formatting the defect charge states as strings (and keep as
int
s andfloat
s instead). (default: False)symprec (float) – Symmetry tolerance for
spglib
to use when determining relaxed defect point symmetries and thus orientational degeneracies. Default is0.1
which matches that used by theMaterials Project
and is larger than thepymatgen
default of0.01
(which is used bydoped
for unrelaxed/bulk structures) to account for residual structural noise in relaxed defect supercells. You may want to adjust for your system (e.g. if there are very slight octahedral distortions etc.). Ifsymprec
is set, then the point symmetries and corresponding orientational degeneracy will be re-parsed/computed even if already present in theDefectEntry
objectcalculation_metadata
.
- Returns:
pandas
DataFrame
- get_transition_levels(all: bool = False, format_charges: bool = True) DataFrame | None [source]
Return a
DataFrame
of the charge transition levels for the defects in theDefectThermodynamics
object (stored in thetransition_level_map
attribute).Note that the transition level (and Fermi level) positions are given relative to
self.vbm
, which is the VBM eigenvalue of the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing.By default, only returns the thermodynamic ground-state transition levels (i.e. those visible on the defect formation energy diagram), not including metastable defect states (which can be important for recombination, migration, degeneracy/concentrations etc, see e.g. https://doi.org/10.1039/D2FD00043A & https://doi.org/10.1039/D3CS00432E). e.g. negative-U defects will show the 2-electron transition level (N+1/N-1) rather than (N+1/N) and (N/N-1). If instead all single-electron transition levels are desired, set
all = True
.Returns a
DataFrame
with columns:“Defect”: Defect name
- “Charges”: Defect charge states which make up the transition level
(as a string if
format_charges=True
, otherwise as a list of integers)
“eV from VBM”: Transition level position in eV from the VBM (
self.vbm
)“In Band Gap?”: Whether the transition level is within the host band gap
- “N(Metastable)”: Number of metastable states involved in the transition level
(0, 1 or 2). Only included if all = True.
- Parameters:
all (bool) – Whether to print all single-electron transition levels (i.e. including metastable defect states), or just the thermodynamic ground-state transition levels (default).
format_charges (bool) – Whether to format the transition level charge states as strings (e.g. “ε(+1/+2)”) or keep in list format (e.g. [1,2]). (Default: True)
- plot(chempots: dict | None = None, limit: str | None = None, el_refs: dict | None = None, all_entries: bool | str = False, unstable_entries: bool | str = 'not shallow', chempot_table: bool | None = None, style_file: str | PathLike | None = None, xlim: tuple | None = None, ylim: tuple | None = None, fermi_level: float | None = None, include_site_info: bool = False, colormap: str | Colormap | None = None, linestyles: str | list[str] = '-', auto_labels: bool = False, filename: str | PathLike | None = None, **kwargs) Figure | list[Figure] [source]
Produce a defect formation energy vs Fermi level plot (a.k.a. a defect formation energy / transition level diagram), returning the
matplotlib
Figure
object to allow further plot customisation.Note that the band edge positions are taken from
self.vbm
andself.band_gap
, which are parsed from the bulk supercell calculation by default, unlessbulk_band_gap_vr
is set during defect parsing.Note that different defect entries (different charge states, and/or ground and metastable states (different spin or geometries); e.g. interstitials at a given site) are grouped together in distinct defect types according to
self.dist_tol
, which is also used in transition level analysis and defect concentrations. This can be adjusted as shown in the plotting customisation tutorial: https://doped.readthedocs.io/en/latest/plotting_customisation_tutorial.html- Parameters:
chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies. If None (default), will use
self.chempots
. This can have the form of{"limits": [{'limit': [chempot_dict]}]}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases in order to show the formal (relative) chemical potentials above the formation energy plot, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.If None (default), sets all chemical potentials to zero. Note that you can also set
DefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to plot formation energies. Can be either:
None, in which case plots are generated for all limits in
chempots
.”X-rich”/”X-poor” where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).
A key in the
(self.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
DefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)all_entries (bool, str) – Whether to plot the formation energy lines of all defect entries, rather than the default of showing only the equilibrium states at each Fermi level position (traditional). If instead set to “faded”, will plot the equilibrium states in bold, and all unstable states in faded grey (Default: False)
unstable_entries (bool, str) – Controls the plotting of unstable/shallow defect states; allowed values are
True
,False
or"not shallow"
. If"not shallow"
(default), defect entries which are predicted to be shallow (perturbed host) states according to eigenvalue analysis and only stable for Fermi levels within a small window to a band edge (shallow_stability_tol
) are omitted from plotting. IfFalse
, all defects which are not stable for any Fermi level in the band gap are also omitted from plotting.shallow_stability_tol
is set to the smaller of 0.05 eV or 10% of the band gap by default, but can be set by ashallow_charge_stability_tolerance = X
keyword argument. Ifunstable_entries=False
, the Fermi window stability tolerance for all defects (default = 0; meaning any in-gap stability) can be set by acharge_stability_tolerance = X
keyword argument (positive or negative). IfTrue
, defect entries are not pruned based on stability/shallow classification. Seeprune_to_stable_entries
for more info.chempot_table (Optional[bool]) – Whether to include a table of the chemical potentials above the formation energy plot. If
None
(default), shown if multiple plots are generated (i.e. multiple chemical potential limits) else not shown.style_file (PathLike) – Path to a mplstyle file to use for the plot. If None (default), uses the default doped style (from
doped/utils/doped.mplstyle
).xlim – Tuple (min,max) giving the range of the x-axis (Fermi level). May want to set manually when including transition level labels, to avoid crossing the axes. Default is to plot from -0.3 to +0.3 eV above the band gap.
ylim – Tuple (min,max) giving the range for the y-axis (formation energy). May want to set manually when including transition level labels, to avoid crossing the axes. Default is from 0 to just above the maximum formation energy value in the band gap.
fermi_level (float) – If set, plots a dashed vertical line at this Fermi level value, typically used to indicate the equilibrium Fermi level position (e.g. calculated with py-sc-fermi). (Default: None)
include_site_info (bool) – Whether to include site info in defect names in the plot legend (e.g. $Cd_{i_{C3v}}^{0}$ rather than $Cd_{i}^{0}$). Default is
False
, where site info is not included unless we have inequivalent sites for the same defect type. If, even with site info added, there are duplicate defect names, then “-a”, “-b”, “-c” etc are appended to the names to differentiate.colormap (str, matplotlib.colors.Colormap) – Colormap to use for the formation energy lines, either as a string (which can be a colormap name from https://matplotlib.org/stable/users/explain/colors/colormaps or from https://www.fabiocrameri.ch/colourmaps – append ‘S’ if using a sequential colormap from the latter) or a
Colormap
/ListedColormap
object. IfNone
(default), usestab10
withalpha=0.75
(if 10 or fewer lines to plot),tab20
(if 20 or fewer lines) orbatlow
(if more than 20 lines; citation: https://zenodo.org/records/8409685).linestyles (list) – Linestyles to use for the formation energy lines, either as a single linestyle (
str
) or list of linestyles (list[str]
) in the order of appearance of lines in the plot legend. Default is"-"
; i.e. solid linestyle for all entries.auto_labels (bool) – Whether to automatically label the transition levels with their charge states. If there are many transition levels, this can be quite ugly. (Default: False)
filename (PathLike) – Filename to save the plot to. (Default: None (not saved))
**kwargs – Additional keyword arguments for advanced customisation, such as
shallow_charge_stability_tolerance
orcharge_stability_tolerance
for controlling stability window tolerances with theunstable_entries
parameter (see argument description for more info).
- Returns:
matplotlib
Figure
object, or list ofFigure
objects if multiple limits chosen.
- print_transition_levels(all: bool = False)[source]
Iteratively prints the charge transition levels for the defects in the DefectThermodynamics object (stored in the transition_level_map attribute).
By default, only returns the thermodynamic ground-state transition levels (i.e. those visible on the defect formation energy diagram), not including metastable defect states (which can be important for recombination, migration, degeneracy/concentrations etc, see e.g. https://doi.org/10.1039/D2FD00043A & https://doi.org/10.1039/D3CS00432E). e.g. negative-U defects will show the 2-electron transition level (N+1/N-1) rather than (N+1/N) and (N/N-1). If instead all single-electron transition levels are desired, set
all = True
.- Parameters:
all (bool) – Whether to print all single-electron transition levels (i.e. including metastable defect states), or just the thermodynamic ground-state transition levels (default).
- prune_to_stable_entries(unstable_entries: bool | str = 'not shallow', shallow_charge_stability_tolerance: float | None = None, charge_stability_tolerance: float = 0, **kwargs) DefectThermodynamics [source]
This function takes the defect entries in
DefectThermodynamics.defect_entries
, prunes them to only those which pass a given stability criterion, and regenerates a newDefectThermodynamics
object with these defect entries.This function can be used to prune out defect entries which are detected to be shallow (perturbed host, ‘fake’) states according to eigenvalue analysis (see https://doped.readthedocs.io/en/latest/Tips.html#eigenvalue-electronic-structure-analysis for more info), and/or entries which are only stable for certain Fermi levels outside or within a small window of the band edges.
Does not modify the original
DefectThermodynamics
(self
) object!This function is used internally in
doped
with theunstable_entries
argument inDefectThermodynamics.plot()
, but can also be used to prune out shallow/unstable defect entries for other purposes (e.g. if one wants to exclude these entries in concentration calculations – though usually these states are irrelevant in such calculations due to their low/near-negligible statibilites; particularly when reasonable supercell sizes, DFT functionals and structure searching are used).- Parameters:
unstable_entries (bool, str) – Controls the pruning of unstable/shallow defect states; allowed values are
True
,False
or"not shallow"
. If"not shallow"
(default), defect entries which are predicted to be shallow (perturbed host) states according to eigenvalue analysis and only stable for Fermi levels within a small window to a band edge (shallow_stability_tol
) are omitted. IfFalse
, all defects which are not stable for any Fermi level in the band gap (charge_stability_tol
) are also omitted.shallow_stability_tol
andcharge_stability_tol
can be tuned with theshallow_charge_stability_tolerance
andcharge_stability_tolerance
keyword arguments respectively. IfTrue
, defect entries are not pruned based on stability/shallow classification.shallow_charge_stability_tolerance (float) – Tolerance for the Fermi level stability window for defects which have been classified as shallow states. If
None
(default), will be set to the smaller of 0.05 eV or 10% of the band gap.charge_stability_tolerance (float) – Tolerance for the Fermi level stability window for all defect charge states, if
unstable_entries=False
. Default is 0 eV, meaning all charge states which are stable for any Fermi level in the band gap will be included, but can be set to a positive value (meaning only defect charge states which are stable at Fermi levels in the band gap further than this energy window from a band edge) or negative value (which is a less strict pruning, only excluding charge states which become stable at Fermi levels outside the band gap further than the absolute value of this energy window from a band edge).**kwargs – Additional keyword arguments to pass to the
DefectThermodynamics()
initialisation (viaDefectThermodynamics.from_dict()
).
- Returns:
New
DefectThermodynamics
object with pruned defect entries.
- to_json(filename: str | PathLike | None = None)[source]
Save the
DefectThermodynamics
object as a json file, which can be reloaded with theDefectThermodynamics.from_json()
class method.Note that file extensions with “.gz” will be automatically compressed (recommended to save space)!
- Parameters:
filename (PathLike) – Filename to save json file as. If None, the filename will be set as
{Chemical Formula}_defect_thermodynamics.json.gz
where {Chemical Formula} is the chemical formula of the host material.
- class doped.thermodynamics.FermiSolver(defect_thermodynamics: DefectThermodynamics, bulk_dos: FermiDos | Vasprun | str | PathLike | None = None, chempots: dict | None = None, el_refs: dict | None = None, backend: str = 'doped', skip_dos_check: bool = False)[source]
Bases:
MSONable
Class to calculate the Fermi level, defect and carrier concentrations under various conditions, using the input
DefectThermodynamics
object.This class implements a number of convenience methods for thermodynamic analyses; such as scanning over temperatures, chemical potentials, effective dopant concentrations etc, minimising or maximising a target property (e.g. defect/carrier concentration), and also allowing greater control over constraints and approximations in defect concentration calculations; such as specifying (known) fixed concentrations of a defect/dopant, specifying defects to exclude from high-temperature concentration fixing in the frozen defect approximation (e.g. highly-mobile defects), and/or fixing defect charge states upon quenching.
This constructor initializes a
FermiSolver
object, setting up the necessary attributes, which includes loading the bulk density of states (DOS) data from either the inputDefectThermodynamics
orbulk_dos
.If using the
py-sc-fermi
backend (currently required for thefixed_defects
,free_defects
andfix_charge_states
options in the scanning functions), please cite the code paper: Squires et al., (2023). Journal of Open Source Software, 8(82), 4962 https://doi.org/10.21105/joss.04962Note that the
delta_gap
argument used inDefectThermodynamics
methods is not directly supported in this class. If band gap modulation is desired, it is recommended to use theDefectThermodynamics
methods directly withdelta_gap
as shown in the (advanced) defect thermodynamics tutorials.- Parameters:
defect_thermodynamics (DefectThermodynamics) – A
DefectThermodynamics
object, providing access to defect formation energies and other related thermodynamic properties.bulk_dos (FermiDos or Vasprun or PathLike) –
Either a path to the
vasprun.xml(.gz)
output of a bulk DOS calculation in VASP, apymatgen
Vasprun
object or apymatgen
FermiDos
for the bulk electronic DOS, for calculating carrier concentrations. If not provided, usesDefectThermodynamics.bulk_dos
if present.Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsNote that the
DefectThermodynamics.bulk_dos
will be set to match this input, if provided.chempots (Optional[dict]) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations and Fermi level), under different chemical environments.
If
None
(default), will useDefectThermodynamics.chempots
(= 0 for all chemical potentials by default, if not set).This can have the form of
{"limits": [{'limit': [chempot_dict]}], ...}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (limit), in the format:
{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.If provided here, then
defect_thermodynamics.chempots
is set to this input.Chemical potentials can also be supplied later in each analysis function, or set using
FermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
(with the same input options).el_refs (Optional[dict]) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present inDefectThermodynamics
in the format generated bydoped
(see tutorials), or ifDefectThermodynamics.el_refs
has been set.If provided here, then
defect_thermodynamics.el_refs
is set to this input.Elemental reference energies can also be supplied later in each analysis function, or set using
FermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
(with the same input options). Default isNone
.backend (Optional[str]) – The code backend to use for the thermodynamic calculations, which can be either
"doped"
or"py-sc-fermi"
."py-sc-fermi"
allows the use offixed_defects
andfree_defects
for advanced constrained defect equilibria (e.g. mobile defects, see advanced thermodynamics tutorial), while"doped"
is usually much quicker. Default isdoped
, but will attempt to switch topy-sc-fermi
if required (and installed).skip_dos_check (bool) – Whether to skip the warning about the DOS VBM differing from
DefectThermodynamics.vbm
by >0.05 eV. Should only be used when the reason for this difference is known/acceptable. Default isFalse
.
- Key attributes:
- defect_thermodynamics (DefectThermodynamics):
The
DefectThermodynamics
object used for the thermodynamic calculations.- backend (str):
The code backend used for the thermodynamic calculations (
"doped"
or"py-sc-fermi"
).- volume (float):
Volume of the unit cell in the bulk DOS calculation (stored in
self.defect_thermodynamics.bulk_dos
).- skip_dos_check (bool):
Whether to skip the warning about the DOS VBM differing from the defect entries VBM by >0.05 eV. Should only be used when the reason for this difference is known/acceptable.
- multiplicity_scaling (int):
Scaling factor to account for the difference in volume between the defect supercells and the bulk DOS calculation cell, when using the
py-sc-fermi
backend.- py_sc_fermi_dos (DOS):
A
py-sc-fermi
DOS
object, generated from the inputFermiDos
object, for use with thepy-sc-fermi
backend.
- equilibrium_solve(single_chempot_dict: dict[str, float], el_refs: dict[str, float] | None = None, temperature: float = 300, effective_dopant_concentration: float | None = None, append_chempots: bool = True, fixed_defects: dict[str, float] | None = None, site_competition: bool | str = True) DataFrame [source]
Calculate the Fermi level and defect/carrier concentrations under thermodynamic equilibrium, given a set of chemical potentials and a temperature.
Typically not intended for direct usage, as the same functionality is provided by
DefectThermodynamics.get_equilibrium_concentrations/fermi_level()
. Rather this is used internally to provide a unified interface for both backends, within thescan_...
functions.- Parameters:
single_chempot_dict (dict[str, float]) – Dictionary of chemical potentials to use for calculating the equilibrium Fermi level position and defect/carrier concentrations. Here, this should be a dictionary of chemical potentials for a single limit (
limit
), in the format:{element symbol: chemical potential}
. Ifel_refs
is provided or set inself.defect_thermodynamics.el_refs
then it is the formal chemical potentials (i.e. relative to the elemental reference energies) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.el_refs (dict[str, float]) – Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
. Unnecessary ifself.defect_thermodynamics.el_refs
is set (i.e. ifchempots
was provided toself.defect_thermodynamics
in the format generated bydoped
). (Default: None)temperature (float) – The temperature at which to solve for defect concentrations, in Kelvin. Defaults to 300 K.
effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.append_chempots (bool) – Whether to append the chemical potentials (and effective dopant concentration, if provided) to the output
DataFrame
. Default isTrue
.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the calculated defect and carrier concentrations, along with the self-consistent Fermi level. The columns include:”Defect”: The defect type.
”Concentration (cm^-3)”: The concentration of the defect in cm^-3.
”Temperature”: The temperature at which the calculation was performed.
”Fermi Level”: The self-consistent Fermi level in eV.
”Electrons (cm^-3)”: The electron concentration.
”Holes (cm^-3)”: The hole concentration.
”μ_X”: Chemical potentials in eV, if
append_chempots
isTrue
.”Dopant (cm^-3)”: The effective arbitrary dopant concentration, if set.
- Return type:
pd.DataFrame
- interpolate_chempots(n_points: int = 10, chempots: list[dict] | dict | None = None, limits: list[str] | None = None, el_refs: dict[str, float] | None = None, annealing_temperature: float | None = None, quenched_temperature: float = 300, temperature: float = 300, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Interpolate between two sets of chemical potentials and solve for the defect concentrations and Fermi level at each interpolated point.
Chemical potentials can be interpolated between two sets of chemical potential dictionaries/values, or between two specified limits.
If
annealing_temperature
(andquenched_temperature
; 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at that temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
n_points (int) – The number of points to generate between chemical potential end points. Defaults to 10.
chempots (Optional[list[dict]]) –
The chemical potentials to interpolate between. This can be either a list containing two dictionaries, each representing a set of chemical potentials for a single limit (in the format:
{element symbol: chemical potential}
) to interpolate between, or can be a single chemical potentials dictionary in thedoped
format (i.e.{"limits": [{'limit': [chempot_dict]}], ...}
) – in which caselimits
must be specified to pick the end-points to interpolate between.If
None
(default), will useself.defect_thermodynamics.chempots
. Note that you can also setFermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations.If manually specifying chemical potentials with a list of two dictionaries, you can also set the
el_refs
option with the DFT reference energies of the elemental phases if desired, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.limits (Optional[list[str]]) –
The chemical potential limits to interpolate between, as a list containing two strings. Each string should be in the format
"X-rich"/"X-poor"
, where X is an element in the system, or be a key in the(self.defect_thermodynamics.)chempots["limits"]
dictionary.If not provided,
chempots
must be specified as a list of two single chemical potential dictionaries for single limits, or must be a binary system with only two limits inchempots
.el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as[{element symbol: chemical potential}, ...]
). Unnecessary ifchempots
is provided/present in format generated bydoped
(i.e.{"limits": [{'limit': [chempot_dict]}], ...}
).Note that you can also set
FermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)annealing_temperature (Optional[float]) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature
under thermodynamic equilibrium).quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
temperature (float) – The temperature at which to solve for defect concentrations and Fermi level, under thermodynamic equilibrium (if
annealing_temperature
is not specified). Defaults to 300 K.effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the defect and carrier concentrations for each interpolated set of chemical potentials. Each row represents the concentrations for a different interpolated point.- Return type:
pd.DataFrame
- optimise(target: str, min_or_max: str = 'max', chempots: dict | None = None, annealing_temperature: float | None = None, quenched_temperature: float = 300, temperature: float = 300, tolerance: float = 0.01, n_points: int = 10, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Search for the chemical potentials that minimise or maximise a target variable, such as electron concentration, within a specified tolerance.
See
target
argument description below for valid choices. This function iterates over a grid of chemical potentials and “zooms in” on the chemical potential that either minimises or maximises the target variable. The process continues until the _relative_ change in the target variable is less than the specified tolerance.If
annealing_temperature
(andquenched_temperature
; 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at that temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
target (str) – The target variable to minimise or maximise, e.g., “Electrons”, “Te_i”, “Fermi Level” etc. Valid
target
values are column names (or substrings), such as ‘Electrons’, ‘Holes’, ‘Fermi Level’, ‘μ_X’, etc., or defect names (without charge states), such as ‘v_O’, ‘Te_i’, etc. If a full defect name is given (e.g. Te_i_Td_Te2.83) then the concentration of that defect will be used as the target variable. If a defect name substring is given instead (e.g. Te_i), then the target variable will be the summed concentration of all defects with that substring in their name (e.g. Te_i_Td_Te2.83, Te_i_C3v etc).min_or_max (str) – Specify whether to “minimise” (“min”) or “maximise” (“max”; default) the target variable.
chempots (Optional[dict]) –
Dictionary of chemical potentials to scan over, in the
doped
format (i.e.{"limits": [{'limit': [chempot_dict]}], ...}
) – the format generated bydoped
's chemical potential parsing functions (see tutorials).If
None
(default), will useself.defect_thermodynamics.chempots
.Note that you can also set
FermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
to set the default chemical potentials for all calculations, and you can setFermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
if you want to update the elemental reference energies for any reason.annealing_temperature (Optional[float]) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature
under thermodynamic equilibrium).quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
temperature (float) – The temperature at which to solve for defect concentrations and Fermi level, under thermodynamic equilibrium (if
annealing_temperature
is not specified). Defaults to 300 K.tolerance (float) – The convergence criterion for the target variable. The search stops when the relative change in the target value is less than this value. Defaults to
0.01
.n_points (int) – The number of points to generate along each axis of the chemical potentials grid for each iteration of the search. The higher the dimension of your chemical system (i.e. number of elements), the more sensitive the runtime will be to the choice of
n_points
. Defaults to10
.effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the results of the minimisation or maximisation process, including the optimal chemical potentials and the corresponding values of the target variable.- Return type:
pd.DataFrame
- Raises:
ValueError – If neither
chempots
norself.chempots
is provided, or ifmin_or_max
is not"minimise"/"min"
or"maximise"/"max"
.
- pseudo_equilibrium_solve(single_chempot_dict: dict[str, float], el_refs: dict[str, float] | None = None, annealing_temperature: float = 1000, quenched_temperature: float = 300, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, append_chempots: bool = True, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Calculate the self-consistent Fermi level and corresponding carrier/defect calculations under pseudo-equilibrium conditions given a set of elemental chemical potentials, an annealing temperature, and a quenched temperature.
Typically not intended for direct usage, as the same functionality is provided by
DefectThermodynamics.get_fermi_level_and_concentrations()
. Rather this is used internally to provide a unified interface for both backends, within thescan_...
functions.‘Pseudo-equilibrium’ here refers to the use of frozen defect and dilute limit approximations under the constraint of charge neutrality (i.e. constrained equilibrium). According to the ‘frozen defect’ approximation, we typically expect defect concentrations to reach equilibrium during annealing/crystal growth (at elevated temperatures), but not upon quenching (i.e. at room/operating temperature) where we expect kinetic inhibition of defect annhiliation and hence non-equilibrium defect concentrations / Fermi level. Typically this is approximated by computing the equilibrium Fermi level and defect concentrations at the annealing temperature, and then assuming the total concentration of each defect is fixed to this value, but that the relative populations of defect charge states (and the Fermi level) can re-equilibrate at the lower (room) temperature. See discussion in https://doi.org/10.1039/D3CS00432E (brief), https://doi.org/10.1016/j.cpc.2019.06.017 (detailed) and
doped
/py-sc-fermi
tutorials for more information. In certain cases (such as Li-ion battery materials or extremely slow charge capture/emission), these approximations may have to be adjusted such that some defects/charge states are considered fixed and some are allowed to re-equilibrate (e.g. highly mobile Li vacancies/interstitials). Modelling these specific cases can be achieved using thefree_defects
and/orfix_charge_states
options, as demonstrated in: https://doped.readthedocs.io/en/latest/fermisolver_tutorial.htmlThis function works by calculating the self-consistent Fermi level and total concentration of each defect at the annealing temperature, then fixing the total concentrations to these values and re-calculating the self-consistent (constrained equilibrium) Fermi level and relative charge state concentrations under this constraint at the quenched/operating temperature. If using the
"py-sc-fermi"
backend, then you can optionally fix the concentrations of individual defect charge states (rather than fixing total defect concentrations) usingfix_charge_states=True
, and/or optionally specifyfree_defects
to exclude from high-temperature concentration fixing (e.g. highly mobile defects).Note that the bulk DOS calculation should be well-converged with respect to k-points for accurate Fermi level predictions!
The degeneracy/multiplicity factor “g” is an important parameter in the defect concentration equation and thus Fermi level calculation (see discussion in https://doi.org/10.1039/D2FD00043A and https://doi.org/10.1039/D3CS00432E), affecting the final concentration by up to 2 orders of magnitude. This factor is taken from the product of the
defect_entry.defect.multiplicity
anddefect_entry.degeneracy_factors
attributes, automatically determined duringdoped
defect calculation parsing.- Parameters:
single_chempot_dict (dict[str, float]) – Dictionary of chemical potentials to use for calculating the pseudo-equilibrium Fermi level position and defect/carrier concentrations. Here, this should be a dictionary of chemical potentials for a single limit (
limit
), in the format:{element symbol: chemical potential}
. Ifel_refs
is provided or set inself.defect_thermodynamics.el_refs
then it is the formal chemical potentials (i.e. relative to the elemental reference energies) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.el_refs (dict[str, float]) – Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
. Unnecessary ifself.defect_thermodynamics.el_refs
is set (i.e. ifchempots
was provided toself.defect_thermodynamics
in the format generated bydoped
). (Default: None)annealing_temperature (float) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Defaults to 1000 K.
quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Defaults to 300 K.
effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix at the quenched temperature, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to fix the concentrations of specific defects regardless of the chemical potentials, or anneal-quench procedure (e.g. to simulate the effect of a fixed impurity concentration). Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.append_chempots (bool) – Whether to append the chemical potentials (and effective dopant concentration, if provided) to the output
DataFrame
. Default isTrue
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the defect and carrier concentrations under pseudo-equilibrium conditions, along with the self-consistent Fermi level. The columns include:”Defect”: The defect type.
”Concentration (cm^-3)”: The concentration of the defect in cm^-3.
”Annealing Temperature”: The annealing temperature.
”Quenched Temperature”: The quenched temperature.
”Fermi Level”: The self-consistent Fermi level in eV.
”Electrons (cm^-3)”: The electron concentration.
”Holes (cm^-3)”: The hole concentration.
”μ_X”: Chemical potentials in eV, if
append_chempots
isTrue
.”Dopant (cm^-3)”: The effective arbitrary dopant concentration, if set.
Additional columns may include concentrations for specific defects and other relevant data.
- Return type:
pd.DataFrame
- scan_chemical_potential_grid(chempots: dict | None = None, n_points: int = 10, annealing_temperature: float | None = None, quenched_temperature: float = 300, temperature: float = 300, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Given a
doped
-formatted chemical potential dictionary, generate aChemicalPotentialGrid
object and calculate the Fermi level positions and defect/carrier concentrations at the grid points.If
annealing_temperature
(andquenched_temperature
; 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at that temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
chempots (Optional[dict]) –
Dictionary of chemical potentials to scan over, in the
doped
format (i.e.{"limits": [{'limit': [chempot_dict]}], ...}
) – the format generated bydoped
's chemical potential parsing functions (see tutorials).If
None
(default), will useself.defect_thermodynamics.chempots
.Note that you can also set
FermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
to set the default chemical potentials for all calculations, and you can setFermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
if you want to update the elemental reference energies for any reason.n_points (int) – The number of points to generate along each axis of the grid. The actual number of grid points may be less, as points outside the convex hull are excluded. The higher the dimension of your chemical system (i.e. number of elements), the more sensitive the runtime will be to the choice of
n_points
. Default is 10.annealing_temperature (Optional[float]) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature
under thermodynamic equilibrium).quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
temperature (float) – The temperature at which to solve for defect concentrations and Fermi level, under thermodynamic equilibrium (if
annealing_temperature
is not specified). Defaults to 300 K.effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the Fermi level solutions at the grid points, based on the provided chemical potentials and conditions.- Return type:
pd.DataFrame
- scan_chempots(chempots: list[dict[str, float]] | dict[str, dict] | None = None, limits: list[str] | None = None, el_refs: dict[str, float] | None = None, annealing_temperature: float | None = None, quenched_temperature: float = 300, temperature: float = 300, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Scan over a range of chemical potentials and solve for the defect concentrations and Fermi level at each set of chemical potentials.
Note that this function only solves for the Fermi level and defect/carrier concentrations at the given chemical potentials (and not at any points between them), whereas
scan_chemical_potential_grid
,interpolate_chempots
andoptimise
scan over the grid/points between chemical potential limits, which may be desired.If
annealing_temperature
(andquenched_temperature
; 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at that temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
chempots (Optional[Union[list[dict], dict]]) –
The chemical potentials to scan over. This can be either a list containing dictionaries of a set of chemical potentials for a single limit (in the format:
{element symbol: chemical potential}
), or can be a single chemical potentials dictionary in thedoped
format (i.e.{"limits": [{'limit': [chempot_dict]}], ...}
) – in which caselimits
can be specified to pick the chemical potential limits to scan over (otherwise scans over all limits in thechempots
dictionary).If
None
(default), will useself.defect_thermodynamics.chempots
. Note that you can also setFermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations.If manually specifying chemical potentials with a list of dictionaries, you can also set the
el_refs
option with the DFT reference energies of the elemental phases if desired, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.limits (Optional[list[str]]) –
The chemical potential limits to scan over, as a list of strings, if
chempots
was provided / is present in thedoped
format. Each string should be in the format"X-rich"/"X-poor"
, where X is an element in the system, or be a key in the(self.defect_thermodynamics.)chempots["limits"]
dictionary.If
None
(default) andchempots
is in thedoped
format (rather than a list of single chemical potential limits), will scan over all limits in thechempots
dictionary.el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as[{element symbol: chemical potential}, ...]
). Unnecessary ifchempots
is provided/present in format generated bydoped
(i.e.{"limits": [{'limit': [chempot_dict]}], ...}
).Note that you can also set
FermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)annealing_temperature (Optional[float]) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature
under thermodynamic equilibrium).quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
temperature (float) – The temperature at which to solve for defect concentrations and Fermi level, under thermodynamic equilibrium (if
annealing_temperature
is not specified). Defaults to 300 K.effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing defect and carrier concentrations for each set of chemical potentials. Each row corresponds to a different set of chemical potentials.- Return type:
pd.DataFrame
- scan_dopant_concentration(effective_dopant_concentration_range: float | list[float], annealing_temperature: float | None = None, quenched_temperature: float = 300, temperature: float = 300, chempots: dict[str, float] | None = None, limit: str | None = None, el_refs: dict[str, float] | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Calculate the defect concentrations under a range of effective (hypothetical) dopant concentrations.
If
annealing_temperature
(andquenched_temperature
; 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at that temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
effective_dopant_concentration_range (Union[float, list[float]]) – The range of effective dopant concentrations to solve over. This can be a single value or a list of values representing different concentrations. These are taken as fixed concentrations (in cm^-3) of an arbitrary dopant or impurity in the material, included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. Positive values correspond to donor doping, while negative values correspond to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
.annealing_temperature (Optional[float]) – Temperature in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature
under thermodynamic equilibrium).quenched_temperature (float) – Temperature in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is 300 K.
temperature (float) – The temperature at which to solve for defect concentrations and Fermi level, under thermodynamic equilibrium (if
annealing_temperature
is not specified). Defaults to 300 K.chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations). If
None
(default), will useself.defect_thermodynamics.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}], ...}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (
limit
), in the format:{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
FermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to calculate the Fermi level positions and defect/carrier concentrations. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.defect_thermodynamics.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
FermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
A
DataFrame
containing the defect and carrier concentrations for each effective dopant concentration. Each row represents the concentrations for a different dopant concentration.- Return type:
pd.DataFrame
- scan_temperature(annealing_temperature_range: float | list[float] | None = None, quenched_temperature_range: float | list[float] = 300, temperature_range: float | list[float] = 300, chempots: dict[str, float] | None = None, limit: str | None = None, el_refs: dict[str, float] | None = None, effective_dopant_concentration: float | None = None, fixed_defects: dict[str, float] | None = None, free_defects: list[str] | None = None, fix_charge_states: bool = False, site_competition: bool | str = True) DataFrame [source]
Scan over a range of temperatures and solve for the defect concentrations, carrier concentrations, and Fermi level at each temperature / annealing & quenched temperature pair.
If
annealing_temperature_range
(andquenched_temperature_range
; just 300 K by default) are specified, then the frozen defect approximation is employed, whereby total defect concentrations are calculated at the elevated annealing temperature, then fixed at these values (unlessfree_defects
orfix_charge_states
are specified) and the Fermi level and relative charge state populations are recalculated at the quenched temperature. Otherwise, if onlytemperature_range
is specified, then the Fermi level and defect/carrier concentrations are calculated assuming thermodynamic equilibrium at each temperature.See
(pseudo_)equilibrium_solve
docstrings for more details.- Parameters:
annealing_temperature_range (Optional[Union[float, list[float]]]) – Temperature range in Kelvin at which to calculate the high temperature (fixed) total defect concentrations, which should correspond to the highest temperature during annealing/synthesis of the material (at which we assume equilibrium defect concentrations) within the frozen defect approach. Default is
None
(usestemperature_range
under thermodynamic equilibrium).quenched_temperature_range (Union[float, list[float]]) – Temperature, or range of temperatures, in Kelvin at which to calculate the self-consistent (constrained equilibrium) Fermi level and carrier concentrations, given the fixed total concentrations, which should correspond to operating temperature of the material (typically room temperature). Default is just 300 K.
temperature_range (Union[float, list[float]]) – Temperature range to solve over, under thermodynamic equilibrium (if
annealing_temperature_range
is not specified). Defaults to just 300 K.chempots (dict) –
Dictionary of chemical potentials to use for calculating the defect formation energies (and thus concentrations). If
None
(default), will useself.defect_thermodynamics.chempots
(= 0 for all chemical potentials by default). This can have the form of{"limits": [{'limit': [chempot_dict]}], ...}
(the format generated bydoped
's chemical potential parsing functions (see tutorials)) and specific limits (chemical potential limits) can then be chosen usinglimit
.Alternatively this can be a dictionary of chemical potentials for a single limit (
limit
), in the format:{element symbol: chemical potential}
. If manually specifying chemical potentials this way, you can set theel_refs
option with the DFT reference energies of the elemental phases, in which case it is the formal chemical potentials (i.e. relative to the elemental references) that should be given here, otherwise the absolute (DFT) chemical potentials should be given.Note that you can also set
FermiSolver.defect_thermodynamics.chempots = ...
orDefectThermodynamics.chempots = ...
(with the same input options) to set the default chemical potentials for all calculations. (Default: None)limit (str) –
The chemical potential limit for which to calculate the Fermi level positions and defect/carrier concentrations. Can be either:
None
, ifchempots
corresponds to a single chemical potential limit - otherwise will use the first chemical potential limit in thechempots
dict."X-rich"/"X-poor"
where X is an element in the system, in which case the most X-rich/poor limit will be used (e.g. “Li-rich”).A key in the
(self.defect_thermodynamics.)chempots["limits"]
dictionary.
The latter two options can only be used if
chempots
is in thedoped
format (see chemical potentials tutorial). (Default: None)el_refs (dict) –
Dictionary of elemental reference energies for the chemical potentials in the format:
{element symbol: reference energy}
(to determine the formal chemical potentials, whenchempots
has been manually specified as{element symbol: chemical potential}
). Unnecessary ifchempots
is provided/present in format generated bydoped
(see tutorials).Note that you can also set
FermiSolver.defect_thermodynamics.el_refs = ...
orDefectThermodynamics.el_refs = ...
(with the same input options) to set the default elemental reference energies for all calculations. (Default: None)effective_dopant_concentration (Optional[float]) – The fixed concentration (in cm^-3) of an arbitrary dopant or impurity in the material. This value is included in the charge neutrality condition to analyze the Fermi level and doping response under hypothetical doping conditions. A positive value corresponds to donor doping, while a negative value corresponds to acceptor doping. For dopants of charge
q
, the input value should beq * 'Dopant Concentration'
. Defaults toNone
, corresponding to no additional extrinsic dopant.fixed_defects (Optional[dict[str, float]]) – A dictionary of defect concentrations to fix regardless of chemical potentials / temperature / Fermi level, in the format:
{defect_name: concentration}
, wheredefect_name
is the name of a defect entry without (e.g."v_O"
) or with (e.g."v_O_+2"
) the charge state; which will then fix either the total concentration of that defect or only the concentration for the specified charge state. Concentrations should be given in cm^-3. This can be used to simulate the effect of a fixed impurity concentration. Defaults toNone
.free_defects (Optional[list[str]]) – A list of defects (without charge states) to be excluded from high-temperature concentration fixing. Useful for highly mobile defects that are not expected to be “frozen-in” upon quenching. Any defects whose names begin with a string in this list will be excluded from high-temperature concentration fixing (e.g.
"v_"
will match all vacancy defects withdoped
-formatted names). Defaults toNone
.fix_charge_states (bool) – Whether to fix the concentrations of individual defect charge states (
True
) or allow charge states to vary while keeping total defect concentrations fixed (False
) upon quenching. Not expected to be physically sensible in most cases. Defaults toFalse
.site_competition (bool | str) – If
True
(default), uses the updated Fermi-Dirac-like formula for defect concentration, which accounts for defect site competition at high concentrations (see Kasamatsu et al. (10.1016/j.ssi.2010.11.022) appendix for derivation – updated here to additionally account for configurational degeneraciesg
(see https://doi.org/10.1039/D3CS00432E)), which gives the following defect concentration equation:N_X = N*[g*exp(-E/kT) / (1 + sum(g_i*exp(-E_i/kT)))]
wherei
runs over all defects which occupy the same site as the defect of interest. IfFalse
, uses the standard dilute limit approximation. Alternativelysite_competition
can be set to a string ("verbose"
), which will give the same behaviour asTrue
as well as including the lattice site indices (used to determine which defects will compete for the same sites) in the outputDataFrame
. Note that this option is only used if thedoped
backend is being used, not supported for thepy-sc-fermi
backend. Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.
- Returns:
DataFrame containing defect and carrier concentrations.
- Return type:
pd.DataFrame
- doped.thermodynamics.bold_print(string: str) None [source]
Does what it says on the tin.
Prints the input string in bold.
- doped.thermodynamics.get_doping(fermi_dos: FermiDos, fermi_level: float, temperature: float) float [source]
Get the doping concentration (majority carrier - minority carrier concentration) in cm^-3 for a given Fermi level (in eV) and temperature (in K), for a
FermiDos
object.Note that the Fermi level here is NOT referenced to the VBM! So the Fermi level should be the corresponding eigenvalue within the calculation (or in other words, the Fermi level relative to the VBM plus the VBM eigenvalue).
Refactored from
FermiDos.get_doping()
to be more accurate/robust (independent of estimated VBM/CBM positions, avoiding overflow warnings).- Parameters:
fermi_dos (FermiDos) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating carrier concentrations.Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsfermi_level (float) – Value corresponding to the electron chemical potential, not referenced to the VBM! (i.e. same eigenvalue reference as the raw calculation)
temperature (float) – Temperature in Kelvin at which to calculate the equilibrium concentrations.
- Returns:
The electron and hole concentrations in cm^-3.
- Return type:
tuple[float, float]
- doped.thermodynamics.get_e_h_concs(fermi_dos: FermiDos, fermi_level: float, temperature: float) tuple[float, float] [source]
Get the corresponding electron and hole concentrations (in cm^-3) for a given Fermi level (in eV) and temperature (in K), for a
FermiDos
object.Note that the Fermi level here is NOT referenced to the VBM! So the Fermi level should be the corresponding eigenvalue within the calculation (or in other words, the Fermi level relative to the VBM plus the VBM eigenvalue).
- Parameters:
fermi_dos (FermiDos) –
pymatgen
FermiDos
for the bulk electronic density of states (DOS), for calculating carrier concentrations.Usually this is a static calculation with the primitive cell of the bulk material, with relatively dense k-point sampling (especially for materials with disperse band edges) to ensure an accurately-converged DOS and thus Fermi level. Using large
NEDOS
(>3000) andISMEAR = -5
(tetrahedron smearing) are recommended for best convergence (wrt k-point sampling) in VASP. Consistent functional settings should be used for the bulk DOS and defect supercell calculations. See https://doped.readthedocs.io/en/latest/Tips.html#density-of-states-dos-calculationsfermi_level (float) – Value corresponding to the electron chemical potential, not referenced to the VBM! (i.e. same eigenvalue reference as the raw calculation)
temperature (float) – Temperature in Kelvin at which to calculate the equilibrium concentrations.
- Returns:
The electron and hole concentrations in cm^-3.
- Return type:
tuple[float, float]
- doped.thermodynamics.get_fermi_dos(dos_vr: str | PathLike | Vasprun)[source]
Create a
FermiDos
object from the provideddos_vr
, which can be either a path to avasprun.xml(.gz)
file, or apymatgen
Vasprun
object (parsed withparse_dos = True
).- Parameters:
dos_vr (Union[PathLike, Vasprun]) – Path to a
vasprun.xml(.gz)
file, or aVasprun
object.- Returns:
The
FermiDos
object.- Return type:
FermiDos
- doped.thermodynamics.get_rich_poor_limit_dict(chempots: dict) dict [source]
Get a dictionary of {“X-rich”: limit, “X-poor”: limit…} for each element X in the chempots phase diagram.
- Parameters:
chempots (dict) – The chempots dict, in the doped format.
- doped.thermodynamics.group_defects_by_distance(entry_list: list[DefectEntry], dist_tol: float = 1.5, symprec: float = 0.1) dict[int, set[DefectEntry]] [source]
Given an input list of
DefectEntry
objects, returns a dictionary of defect entries clustered according to the givendist_tol
distance tolerance (between symmetry-equivalent sites in the bulk supercell), in the format:{cluster index: {DefectEntry, ...}}
.This is used to group together different defect entries (different charge states, and/or ground and metastable states (different spin or geometries)) which occupy similar sites in the host lattice, which is then used in plotting, transition level analysis and defect concentration calculations; e.g. in the frozen defect approximation, the total concentration of a given defect type group is calculated at the annealing temperature, and then the equilibrium relative population of the constituent entries is recalculated at the quenched temperature. When
site_competition = True
(default) in defect concentration calculations, the grouping returned by this function is used to determine which defects occupy the same sites (and hence compete for site occupancy). Note that while largedist_tol
s are often preferable for plotting (to condense the defect formation energy lines), this is often not ideal for determining site competition in concentration analyses as it can lead to unrealistically-large clusters.Note: The
get_min_dist_between_equiv_sites
function indoped.utils.symmetry
can be useful for analysing the inter-defect distances and resulting clustering behaviour.- Parameters:
entry_list ([DefectEntry, ...]) – A list of DefectEntry objects to group together.
dist_tol (float) – Distance threshold (in Å) for clustering equivalent defect sites. (Default: 1.5)
symprec (float) – Symmetry precision for finding equivalent sites in the bulk supercell, for site clustering. Default is 0.1 (matching
doped
default for point symmetry determination for relaxed defect supercells).
- Returns:
Dictionary of
{cluster index: {DefectEntry, ...}}
.- Return type:
dict
- doped.thermodynamics.group_defects_by_name(entry_list: list[DefectEntry]) dict[str, list[DefectEntry]] [source]
Given an input list of
DefectEntry
objects, returns a dictionary of{defect name without charge: [DefectEntry]}
, where the values are lists ofDefectEntry
objects with the same defect name (excluding charge state).The
DefectEntry.name
attributes are used to get the defect names. These should be in the format: “{defect_name}_{optional_site_info}_{charge_state}”. If theDefectEntry.name
attribute is not defined or does not end with the charge state, then the entry will be renamed with the doped default name for the unrelaxed defect (i.e. using the point symmetry of the defect site in the bulk cell).For example,
v_Cd_C3v_+1
,v_Cd_Td_+1
andv_Cd_C3v_+2
will be grouped as {v_Cd_C3v
: [v_Cd_C3v_+1
,v_Cd_C3v_+2
],v_Cd_Td
: [v_Cd_Td_+1
]}.- Parameters:
entry_list ([DefectEntry]) – A list of DefectEntry objects to group together by defect name (without charge).
- Returns:
Dictionary of {defect name without charge: [DefectEntry]}.
- Return type:
dict
- doped.thermodynamics.group_defects_by_type_and_distance(defect_entries: list[DefectEntry], dist_tol: float = 1.5, symprec: float = 0.1) dict[str, dict[int, set[DefectEntry]]] [source]
Given an input list of
DefectEntry
objects, returns a dictionary of defect types with sub-dictionaries of defect entries clustered according to the givendist_tol
distance tolerance (between symmetry-equivalent sites in the bulk supercell), in the format:{simple defect name: {cluster index: {DefectEntry, ...}}
, wheresimple defect name
is the nominal defect type (e.g.Te_i
forTe_i_Td_Cd2.83_+2
) and{DefectEntry, ...}
is a set ofDefectEntry
objects which have been grouped in the same cluster.This is used to group together different defect entries (different charge states, and/or ground and metastable states (different spin or geometries)) which correspond to the same defect type (e.g. interstitials at a given site) and occupy similar sites in the host lattice, which is then used in plotting, transition level analysis and defect concentration calculations; e.g. in the frozen defect approximation, the total concentration of a given defect type group is calculated at the annealing temperature, and then the equilibrium relative population of the constituent entries is recalculated at the quenched temperature.
Note: The
get_min_dist_between_equiv_sites
function indoped.utils.symmetry
can be useful for analysing the inter-defect distances and resulting clustering behaviour.- Parameters:
defect_entries (list[DefectEntry]) – A list of
DefectEntry
objects to group together based on type and distance between symmetry-equivalent sites.dist_tol (float) – Distance threshold (in Å) for clustering equivalent defect sites. (Default: 1.5)
symprec (float) – Symmetry precision for finding equivalent sites in the bulk supercell, for site clustering. Default is 0.1 (matching
doped
default for point symmetry determination for relaxed defect supercells).
- Returns:
Dictionary of
{simple defect name: {cluster index: {DefectEntry, ...}}}
.- Return type:
dict
- doped.thermodynamics.raw_energy_from_chempots(composition: str | dict | Composition, chempots: dict) float [source]
Given an input composition (as a
str
,dict
orpymatgen
Composition
object) and chemical potentials dictionary, get the corresponding raw energy of the composition (i.e. taking the energies given in the'limits'
subdicts ofchempots
, in thedoped
chemical potentials dictionary format).- Parameters:
composition (Union[str, dict, Composition]) – Composition to get the raw energy of.
chempots (dict) – Chemical potentials dictionary.
- Returns:
Raw energy of the composition.
- doped.thermodynamics.scissor_dos(delta_gap: float, dos: Dos | FermiDos, tol: float = 1e-08, verbose: bool = True)[source]
Given an input Dos/FermiDos object, rigidly shifts the valence and conduction bands of the DOS object to give a band gap that is now increased/decreased by
delta_gap
eV, where this rigid scissor shift is applied symmetrically around the original gap (i.e. the VBM is downshifted bydelta_gap/2
and the CBM is upshifted bydelta_gap/2
).Note this assumes a non-spin-polarised (i.e. non-magnetic) density of states!
- Parameters:
delta_gap (float) – The amount by which to increase/decrease the band gap (in eV).
dos (Dos/FermiDos) – The input DOS object to scissor.
tol (float) – The tolerance to use for determining the VBM and CBM (used in
Dos.get_gap(tol=tol)
). Default: 1e-8.verbose (bool) – Whether to print information about the original and new band gaps.
- Returns:
The scissored DOS object.
- Return type:
FermiDos