SlaterKosterTable

class SlaterKosterTable(**kwargs)

Class for representing the parameters that determine the parameters of a Slater-Koster basis.

The constructor takes parameters specified as keyword arguments. These arguments follow one of two conventions, depending on wether offsite or onsite parameters are being specified:

Onsite keyword arguments are in the form element=instance, where element is the full name of an element as a string, and instance is a SlaterKosterOnsiteParameters object

Offsite keyword arguments are in the form element1_element2_XYZ=list, where
element1: the first element - e.g. carbon.
element2: the second element - e.g. hydrogen.
X: the orbital on the first element - s, p, d.
Y: the orbital on the second element - s, p, d.
Z: the type of interaction - s for sigma, p for pi, d for delta.
list: A list of tuples in one of two formats: Either, [(d0,h0,s0), (d1,h1,s1), ...] where (d,h,s) indicate distance, hamiltonian and overlap elements. Or, [(d0,h0), (d1,h1), ...] in the case the overlap matrix is diagonal.

offsiteParameters()
Returns:

The offsite parameters.

Return type:

dict

onsiteParameters()
Returns:

The onsite parameters.

Return type:

dict

Usage Examples

Define a SlaterKosterTable with a Vogl silicon basis

# Generate a basis set for Silicon using
# J. Phys. Chem. solids Vol. 44, 365-378, 1983

# Parameters, distances in Angstrom silicon
a = 5.4306*Ang
d_n1 = math.sqrt(3.0)/4.0*a
d_n2 = math.sqrt(2.0)/2.0*a

# Matrix elements from paper, energies in eV
E_s =     -4.545*eV
E_p =      1.715*eV
E_sstar =  6.6850*eV

V_ss =    -8.3000*eV
V_xx =     1.7150*eV
V_xy =     4.5750*eV
V_sp =     5.7292*eV
V_sstarp = 5.3749*eV

# -----------------------------------------------------------------------------
# The paper is nearest neighbour Slater-Koster parameterization,
# hence it has to be tabulated using a power law.

# Specify that the cutoff for the matrix elements between 1. and 2. nn
rcut = 0.5*d_n1 + 0.5*d_n2

# Generate a series of strain -0.1 from +0.1
epsilon = numpy.linspace(-0.10, 0.10, 21)

# Specify the distances for which the matrix elements are specified
distances = [ d_n1*(1.0+x) for x in epsilon ]+ [ rcut ]

# Using a power-law to get the distance dependence of the matrix elements
sss  = [ 0.25*V_ss/(1.0+x)**2             for x in epsilon ] + [0.0*eV]
sps  = [ 0.25*math.sqrt(3)*V_sp/(1.0+x)**2     for x in epsilon ] + [0.0*eV]
pps  = [ 0.25*(V_xx+2.0*V_xy)/(1.0+x)**2  for x in epsilon ] + [0.0*eV]
ppp  = [ 0.25*(V_xx-V_xy)/(1.0+x)**2      for x in epsilon ] + [0.0*eV]
ps1s = [ 0.25*math.sqrt(3)*V_sstarp/(1.0+x)**2 for x in epsilon ] + [0.0*eV]

# Create the onsite.
si_onsite = SlaterKosterOnsiteParameters(element = Silicon, # Not needed.
                                         angular_momenta = [0,1,0],
                                         occupations =     [2,2,0],
                                         ionization_potential = [E_s, E_p, E_sstar],
                                         onsite_hartree_shift = ATK_U(Silicon, ['3s','3p','3s']),
                                         onsite_spin_split = ATK_W(Silicon, ['3s','3p','3s']),
)

Silicon_Basis = SlaterKosterTable(silicon_silicon_sss =  zip(distances, sss),
                            silicon_silicon_sps =  zip(distances, sps),
                            silicon_silicon_pps =  zip(distances, pps),
                            silicon_silicon_ppp =  zip(distances, ppp),
                            silicon_silicon_ps1s = zip(distances, ps1s),
                            silicon = si_onsite,
                            )


Notes

  • The onsite and offsite arguments can be specified at the same time, and in any order.

    carbon_onsite_settings = SlaterKosterOnsiteParameters(...)
    hydrogen_onsite_settings = SlaterKosterOnsiteParameters(...)
    t = SlaterKosterTable(carbon=carbon_onsite_settings,
                          hydrogen=hydrogen_onsite_settings,
                          hydrogen_hydrogen_sss=[(1.1*Ang,0.2*eV,0.2), ... ],
                          hydrogen_carbon_spp=[(0.2*Ang,0.1*eV), ... ])
    
  • If there are multiple orbitals in an angular shell the shells are named, s0, s1, s2, ..

    carbon_onsite_settings = SlaterKosterOnsiteParameters(...)
    hydrogen_onsite_settings = SlaterKosterOnsiteParameters(...)
    t = SlaterKosterTable(carbon=carbon_onsite_settings,
                          hydrogen=hydrogen_onsite_settings,
                          hydrogen_hydrogen_s0s0s=[(1.1*Ang,0.2*eV,0.2), ... ],
                          hydrogen_hydrogen_s1s1s=[(1.1*Ang,0.22*eV), ... ],
                          hydrogen_carbon_s0pp=[(0.2*Ang,0.1*eV), ... ])
                          hydrogen_carbon_s1pp=[(0.2*Ang,0.15*eV), ... ])
    

    Note that s is equivalent with s0, see the example Vogl.py above which defines orbitals s and s1.

  • In the offsite keyword arguments the order of the element and shell pairs is irrelevant. E.g., it is equivalent to define

    t = SlaterKosterTable(carbon=carbon_onsite_settings,
                          hydrogen=hydrogen_onsite_settings,
                          hydrogen_carbon_sps=[(0.2*Ang,0.1*eV), ... ]),
                          ...
    

    or

    t = SlaterKosterTable(carbon=carbon_onsite_settings,
                          hydrogen=hydrogen_onsite_settings,
                          carbon_hydrogen_pss=[(0.2*Ang,0.1*eV), ... ]),
                          ...
    

    The proper signs for even and odd parity are enforced internally, therefore each interaction should be specified only once.

  • Matrix elements that are not specified in the SlaterKosterTable are set to zero.

Specifying custom tags for a Slater-Koster table

It is possible to assign different parametrizations for different atoms of the same type by using tags. The tags must be strings without the underscore (_) character, and they must also be valid Python keyword arguments. For example, foo1, HfO2 and specialtag are all valid tag names, but my_tag and 1foo are not. In this case, the last one is not a valid Python keyword argument. The tags are also treated as case-insensitive, i.e. HfO2 and hfo2 correspond to the same tag.

The tags can be specified for a Slater-Koster table in a similar fashion as for any periodic table element. The syntax looks as follows:

t = SlaterKosterTable(element1=SlaterKosterOnSiteParameters(...),
                      element2=SlaterKosterOnSiteParameters(...),
                      tag1=SlaterKosterOnSiteParameters(...),
                      tag2=SlaterKosterOnSiteParameters(...),
                      element1_element2_sss=...,
                      element1_tag1_sss=...,
                      element1_tag2_sss=...)

Note that here we presume that the off-site terms are only required between element1 and both tagged basis sets. In order for the special on-site parameters to be used in the calculation, the tagged atoms must also be specified on the configuration, i.e.

configuration.addTags('tag1', tag1_indices)
configuration.addTags('tag2', tag2_indices)

Note

All atoms in the configuration must have onsite parameters specified for the element type or through tags.

The following example script demonstrates how to use tags for a Slater-Koster table to substitute the first two Gallium atoms with a simplified VCA parameter for a InGaAs alloy with a 50 % molar fraction of Indium.

# Set up lattice
vector_a = [5.63685, 0.0, 0.0]*Angstrom
vector_b = [0.0, 5.63685, 0.0]*Angstrom
vector_c = [0.0, 0.0, 5.63685]*Angstrom
lattice = UnitCell(vector_a, vector_b, vector_c)

# Define elements
elements = [Gallium, Arsenic, Gallium, Arsenic, Gallium, Arsenic, Gallium,
            Arsenic]

# Define coordinates
fractional_coordinates = [[ 0.  ,  0.  ,  0.  ],
                          [ 0.25,  0.25,  0.25],
                          [ 0.5 ,  0.5 ,  0.  ],
                          [ 0.75,  0.75,  0.25],
                          [ 0.5 ,  0.  ,  0.5 ],
                          [ 0.75,  0.25,  0.75],
                          [ 0.  ,  0.5 ,  0.5 ],
                          [ 0.25,  0.75,  0.75]]
# Set up configuration
bulk_configuration = BulkConfiguration(
    bravais_lattice=lattice,
    elements=elements,
    fractional_coordinates=fractional_coordinates
    )

# Fetch Bassani InAs and GaAs basis sets.
inas_basis = Bassani.InAs_Basis
gaas_basis = Bassani.GaAs_Basis

# Set up keyword arguments for the Slater-Koster table; add
# the GaAs onsite and off-site parameters there.
args = {}
args.update(gaas_basis.onsiteParameters())
args.update(gaas_basis.offsiteParameters())

# Add the tag 'inga' for the first two Ga atoms.
bulk_configuration.addTags('inga', [0, 2])

# Create the InGa on-site term by mixing the ionization potentials
# of In and Ga.
indium_onsite_term = inas_basis.onsiteParameters()['in']
gallium_onsite_term = gaas_basis.onsiteParameters()['ga']

ga_onsite_potential = gallium_onsite_term.ionizationPotential()
in_onsite_potential = indium_onsite_term.ionizationPotential()

inga_onsite_potential = 0.5 * (ga_onsite_potential + in_onsite_potential)
inga_onsite_term = gallium_onsite_term(ionization_potential=inga_onsite_potential)

# Use the 'inga' tag to apply the special on-site term for
# the first two Ga atoms.
args.update({'inga': inga_onsite_term})
# One should also generate inga_as_sss, inga_as_sps, ... off-site terms according
# to some interpolation between In-As and Ga-As.
# For sake of simplicity we will assume that they are all identical to the ga-as interactions:
args.update({
    'inga_as_sss'  : gaas_basis.offsiteParameters()['ga_as_sss'],
    'inga_as_sps'  : gaas_basis.offsiteParameters()['ga_as_sps'],
    'inga_as_sds'  : gaas_basis.offsiteParameters()['ga_as_sds'],
    'inga_as_s1s1s': gaas_basis.offsiteParameters()['ga_as_s1s1s'],
    'inga_as_s1ps' : gaas_basis.offsiteParameters()['ga_as_s1ps'],
    'inga_as_s1ds' : gaas_basis.offsiteParameters()['ga_as_s1ds'],
    'inga_as_pps'  : gaas_basis.offsiteParameters()['ga_as_pps'],
    'inga_as_ppp'  : gaas_basis.offsiteParameters()['ga_as_ppp'],
    'inga_as_pds'  : gaas_basis.offsiteParameters()['ga_as_pds'],
    'inga_as_pdp'  : gaas_basis.offsiteParameters()['ga_as_pdp'],
    'inga_as_dds'  : gaas_basis.offsiteParameters()['ga_as_dds'],
    'inga_as_ddp'  : gaas_basis.offsiteParameters()['ga_as_ddp'],
    'inga_as_ddd'  : gaas_basis.offsiteParameters()['ga_as_ddd'],
    'as_inga_ss1s' : gaas_basis.offsiteParameters()['as_ga_ss1s'],
    'as_inga_sps'  : gaas_basis.offsiteParameters()['as_ga_sps'],
    'as_inga_sds'  : gaas_basis.offsiteParameters()['as_ga_sds'],
    'as_inga_s1ss' : gaas_basis.offsiteParameters()['as_ga_s1ss'],
    'as_inga_s1ps' : gaas_basis.offsiteParameters()['as_ga_s1ps'],
    'as_inga_s1ds' : gaas_basis.offsiteParameters()['as_ga_s1ds'],
    'as_inga_pds'  : gaas_basis.offsiteParameters()['as_ga_pds'],
    'as_inga_pdp'  : gaas_basis.offsiteParameters()['as_ga_pdp'],
    })

# Set up the basis and calculate band structure.
basis = SlaterKosterTable(**args)
calculator = SemiEmpiricalCalculator(
    hamiltonian_parametrization=SlaterKosterHamiltonianParametrization(basis_set=basis))
bulk_configuration.setCalculator(calculator)
bandstructure = Bandstructure(bulk_configuration)

For the details of the Slater-Koster model, see the chapter on Semi Empirical.