Builder

A sample is built using a lattice, a collection of sites, periodic boundary conditions, and a hopping dictionary.

The lattice contains lattice vectors, and site locations within the unit cell. It tells the sample where a site with a certain coordinate (n0,n1,n2), orbital_index is located in space. The integer coordinates (n0,n1,n2) give a unit cell location in terms of lattice vectors. The orbital index gives the location of a site within its unit cell.

A collection of sites is given by a list of coordinates (n0,n1,n2), orbital_index. This tells the sample which sites you want to include in your model.

The periodic boundary condition function tells the sample how to deal with its edge. It takes coordinates falling outside the sample, and returns coordinates within the sample.

Finally, the hopping dictionary lists the hoppings in the tight-binding system. You can see it as a collection of hopping matrices from the (0,0,0) unit cell to other unit cells (n0,n1,n2). The size of these hopping matrices is given by the number of orbitals in the unit cell. The first index of the hopping matrix corresponds to the orbital in the origin unit cell (0,0,0), and the second index of the hopping matrix corresponds to the orbital in the target unit cell (n0,n1,n2).

Lattice

A Lattice object contains the geometrical information of a material. It is initiated with a list of 2 or 3 lattice vectors and a list of orbital coordinates. E.g., for graphene:

a = 0.24 # lattice constant in nm
b = a / sqrt(3.) # carbon-carbon distance in nm
vectors        = [[1.5 * b, -0.5 * a, 0.],
                  [1.5 * b, 0.5 * a, 0.]]
orbital_coords = [[-b / 2., 0., 0.],
                  [b / 2., 0., 0.]]
lat = tipsi.Lattice(vectors, orbital_coords)

If you are working with multiple orbitals per site, each orbital must be listed separately in the second argument. In tipsi, you should always use nanometers as distance unit.

class tipsi.builder.Lattice(vectors, orbital_coords)

Lattice class

A lattice object contains information about the geometry of the lattice.

vectors

(3,3) numpy array

array of lattice vectors [a_0, a_1, a_2]

vectorsT

(3,3) numpy array

transposed lattice vectors

orbital_coords

(n,3) numpy array

array of orbital coordinates for all n orbitals

extended

integer

number of times the unit cell has been extended, default 1

area_unit_cell()

Get unit cell area.

Returns:unit cell area
Return type:float
reciprocal_latt()

Get reciprocal lattice vectors.

Returns:array containing [k_0, k_1, k_2]
Return type:(3,3) numpy array of floats
site_pos(unit_cell_coords, orbital)

Get orbital position in Cartesian coordinates.

Parameters:
  • unit_cell_coords (integer 3-tuple) – unit cell coordinates
  • orbital (integer) – orbital index
Returns:

x, y and z coordinates of orbital

Return type:

numpy array of floats

volume_unit_cell()

Get unit cell volume.

Returns:unit cell volume
Return type:float

SiteSet

A SiteSet object contains sites, that are added by unit cell coordinate and orbital index. E.g., for graphene:

W = 10 # width
H = 10 # height
site_set = tipsi.SiteSet()
for i in range(W):
    for j in range(H):
        unit_cell_coords = (i, j, 0)
        site_set.add_site(unit_cell_coords, 0)
        site_set.add_site(unit_cell_coords, 1)

At each unit cell coordinate, we add two sites, generating 10 by 10 unit cells in total.

class tipsi.builder.SiteSet

SiteSet class

A SiteSet object contains a dict of site tags.

sites

dict

dict of site tags in the sample

add_site(unit_cell_coords, orbital=0)

Add orbital to sample.

Parameters:
  • unit_cell_coords (3-tuple of integers) – unit cell coordinates
  • orbital (integer, optional) – orbital index
delete_site(unit_cell_coords, orbital)

Delete orbital from sample.

Parameters:
  • unit_cell_coords (3-tuple of integers) – unit cell coordinates
  • orbital (integer) – orbital index

HopDict

A HopDict object contains the electronic information of a material. It is given by a list of hopping matrices corresponding to relative unit cell coordinates. E.g., for graphene:

# graphene example for hop_dict.set((n0,n1,n2), A)
# (n0,n1,n2) gives relative unit cell coordinate
# A[i, j] gives hopping from orbital i in (0,0,0)
# to orbital j in (n1,n2,n3)

t = 2.7 # hopping constant in eV
e = 0.0 # on-site potential in eV
A_0   = [[e, t],
         [t, e]]
A_nn0 = [[0., 0.],
         [t, 0.]]
A_nn1 = [[0., t],
         [0., 0.]]

hop_dict = tipsi.HopDict()
hop_dict.set((0, 0, 0),  A_0)
hop_dict.set((1, 0, 0),  A_nn0)
hop_dict.set((-1, 0, 0), A_nn1)
hop_dict.set((0, 1, 0),  A_nn0)
hop_dict.set((0, -1, 0), A_nn1)

Alternatively, you can set matrix elements individually, using:

t = 2.7 # hopping constant in eV
e = 0.0 # on-site potential in eV

hop_dict = tipsi.HopDict()
hop_dict.empty((0, 0, 0), (2, 2)) # create a 2 by 2 empty hopping matrix
hop_dict.set_element((0, 0, 0), (0, 0), e)
hop_dict.set_element((0, 0, 0), (1, 0), t)
hop_dict.set_element((0, 0, 0), (1, 1), e)
hop_dict.set_element((0, 0, 0), (0, 1), t)

hop_dict.empty((1, 0, 0), (2, 2))
hop_dict.set_element((1, 0, 0), (0, 1), t)
hop_dict.empty((0, 1, 0), (2, 2))
hop_dict.set_element((0, 1, 0), (0, 1), t)
hop_dict.empty((-1, 0, 0), (2, 2))
hop_dict.set_element((-1, 0, 0), (1, 0), t)
hop_dict.empty((0, -1, 0), (2, 2))
hop_dict.set_element((0, -1, 0), (1, 0), t)

In tipsi, you should always use the energy unit electronvolts.

class tipsi.builder.HopDict

HopDict class

A hopping dictionary contains relative hoppings.

dict

dictionary

dictionary with site tags as keys and complex matrices as values

add_conjugates()

Adds hopping conjugates to self.dict.

delete(rel_unit_cell)

Delete hopping matrix from dictionary.

Parameters:rel_unit_cell (3-tuple of integers) – relative unit cell coordinates
Returns:True if site was deleted, false if not
Return type:boolean
empty(rel_unit_cell, shape)

Add empty hopping matrix to dictionary.

Parameters:
  • rel_unit_cell (3-tuple of integers) – relative unit cell coordinates
  • shape (2-tuple of integers) – shape of empty hopping matrix
remove_z_hoppings()

Remove z-direction hoppings.

set(rel_unit_cell, hopping)

Add hopping matrix to dictionary.

Parameters:
  • rel_unit_cell (3-tuple of integers) – relative unit cell coordinates
  • hopping (complex float or matrix of floats) – hopping value or matrix of hopping values
set_element(rel_unit_cell, element, hop)

Add single hopping to hopping matrix.

Parameters:
  • rel_unit_cell (3-tuple of integers) – relative unit cell coordinates
  • element (2-tuple of integers) – element indices
  • hop (complex float) – hopping value
sparse()

Get sparse hopping dictionary.

Returns:
Return type:sparse hopping dictionary

Periodic boundary conditions

We need to tell tipsihow to treat the boundary of the sample. Hence, we define a function that takes a site coordinate outside the sample, and returns a coordinate that falls within the sample. E.g., for graphene:

def pbc_func(unit_cell_coords, orbital):
    n0, n1, n2 = unit_cell_coords
    # PBC are given by n0 modulo W and n1 modulo H
    # so that site coordinate n0 = W is mapped to n0 = 0
    # and so that site coordinate n0 = W + 1 is mapped to n0 = 1
    # etcetera - same for the n1 coordinate
    return (n0 % W, n1 % H, n2), orbital

This gives periodic boundary conditions in all directions. Of course, we could also define periodic boundary conditions in only one direction, to create a ribbon sample:

def pbc_func_ribbon(unit_cell_coords, orbital):
    n0, n1, n2 = unit_cell_coords
    return (n0 % W, n1, n2), orbital

If you don’t specify periodic boundary conditions, tipsi uses closed boundary conditions.

tipsi.builder.bc_default(unit_cell_coords, orbital)

Default (closed) boundary conditions.

Parameters:
  • unit_cell_coords (3-tuple of integers) – unit cell coordinates
  • orbital (integer) – orbital index
Returns:

  • unit_cell_coords (3-tuple of integers) – unit cell coordinates
  • orbital (integer) – orbital index

Sample

We now have all the ingredients to create a sample. A Sample object generates the full tight-binding Hamiltonian, given a Lattice, SiteSet, HopDict, and boundary conditions. Also, keep in mind the Hamiltonian will have to be rescaled, to fulfill the requirement that all eigenvalues must be in the range [-1, 1]:

sample = tipsi.Sample(lat, site_set, pbc_func)
sample.add_hop_dict(hop_dict) # apply HopDict
sample.rescale_H(9.) # rescale Hamiltonian
sample.plot() # plot sample

The resulting plot looks like the following image. As you can see, there are hoppings between the outer sites of the sample, indicating that there are periodic boundary conditions in both directions.

_images/sample.png
class tipsi.builder.Sample(lattice, site_set=[], bc_func=<function bc_default>, nr_processes=1, read_from_file=False)

Sample class

A Sample object contains sample information, such as sites and hoppings.

lattice

lattice object

the lattice used for the sample

bc_func

function

function for boundary conditions

nr_processes

int

number of processes to use for parallel functionality

rescale

float

Hamiltonian rescale value; default value: 1.

index_to_tag

list of 3-tuples

ordered list of sites in sample

tag_to_index

dict (keys: 3-tuple, values: integer)

dictionary giving index for each site tag

site_x

list of floats

site x-locations

site_y

list of floats

site y-locations

site_z

list of floats

site z-locations

indices

numpy array of integers

csr-indices for hoppings & distances

indptr

numpy array of integers

csr-indptr for hoppings & distances

hop

numpy array of complex floats

sparse Hamiltonian

dx

numpy array of floats

x-distances of hoppings

dy

numpy array of floats

y-distances of hoppings

Hk(momentum)

Calculate the Fourier transform of the Hamiltonian.

Parameters:momentum (3-list of floats) – momentum [kx, ky, kz]
Returns:Hk – k-space Hamiltonian
Return type:(tot_nr_orbitals, tot_nr_orbitals) list of complex floats
add_hop_dict(hop_dict)

Apply hopping dictionary.

Parameters:hop_dict (hopping dictionary object) – hopping information
band_structure(momenta)

Calculate band structure of the Sample.

Parameters:momenta ((n_momenta, 3) list of floats) – momenta [kx, ky, kz] for band structure calculation
Returns:bands – list of energies corresponding to input momenta
Return type:(n_momenta, n_tot_orbitals) list of complex floats
delete_hopping(unit_cell_coord0, unit_cell_coord1, orbital0=0, orbital1=0)

Delete hopping.

Parameters:
  • unit_cell_coord0 (3-tuple) – unit cell coordinate for site 0
  • unit_cell_coord1 (3-tuple) – unit cell coordinate for site 1
  • orbital0 (int, optional) – orbital 0
  • orbital1 (int, optional) – orbital 1
Returns:

True if hopping value is deleted False if hopping value is not found

Return type:

bool

energy_range()

Energy range to consider in calculations.

Returns:en_range – All eigenvalues are between (-en_range / 2, en_range / 2)
Return type:float
get_loc(tag)
plot(fig_name='system.png', single_site_coord=False, single_site_orbital=0, draw_size=5, draw_dpi=600)

Plot sample in 2D, save to file.

Parameters:
  • fig_name (string, optional) – save to this file
  • single_site_coord (int 3-tuple int, optional) – if not False, only print hoppings to a single site with this site coordinate
  • single_site_orbital (int, optional) – only print hoppings to a single site with this orbital index
  • draw_size (float, optional) – scale site and hopping drawing size
  • draw_dpi (integer, optional) – dpi of image
rescale_H(value=False)

Rescale Hamiltonian.

Parameters:value (float, positive, optional) – All hoppings are divided by this value. Choose it such that the absolute value of the largest eigenenergy is smaller than 1. If no value is chosen, a good value is found, but this is really slow for large matrices.
Returns:value – Rescale value.
Return type:float
save(filename='sample.hdf5')

Save sample

Parameters:filename (string) – Save to this hdf5 file. Default value: “sample.hdf5”.
set_hopping(hop, unit_cell_coord0, unit_cell_coord1, orbital0=0, orbital1=0)

Add or change hopping, automatically add conjugate.

Parameters:
  • hop (float) – hopping value
  • unit_cell_coord0 (3-tuple) – unit cell coordinate for site 0
  • unit_cell_coord1 (3-tuple) – unit cell coordinate for site 1
  • orbital0 (int, optional) – orbital 0
  • orbital1 (int, optional) – orbital 1
Returns:

True if hopping value is changed False if hopping value is added

Return type:

bool

set_magnetic_field(B)

Set magnetic field

Parameters:B (float) – magnetic field in Tesla, distance units must be in nanometers, hoppings must be in eV

Adding disorder

We can introduce many types of disorder to our tight-binding model.

Vacancies can be made by deleting a site from the SiteSet, before initializing the Sample object:

site_set.delete_site(unit_cell_coords, orbital)

After adding a HopDict, we can add or change individual hoppings with:

sample.set_hopping(hop, unit_cell_coord0, \
    unit_cell_coord1, orbital0, orbital1)

Moreover, tipsi has some convenience functions for common types of global disorder.

We can uniformly strain the Lattice, HopDict pair with (for black phosphorus):

strain = 5     # strain in percent
beta = 4.5     # strain coefficient
strain_tensor = np.diag([-0.002 * strain, \
                         0.01 * strain, \
                         -0.002 * strain])
lattice, hop_dict = tipsi.uniform_strain(lattice, \
    hop_dict, strain_tensor, beta)

If we have a HopDict with interlayer hoppings, we can create a multilayer sample and add bias by using:

n_layers = 2   # number of layers
bias = 1.0     # bias in eV/nm
n_orbitals = 2 # number of orbitals

# extend unit cell in z-direction
lattice, hop_dict = \
    tipsi.extend_unit_cell(lattice, hop_dict, \
                           2, n_layers)

# add bias
for i in range(n_orbitals * n_layers):
    z = lat.site_pos((0, 0, 0), i)[2]
    onsite_pot = z * bias
    hops.set_element((0, 0, 0), (i, i), onsite_pot)

# remove redundant z-direction hoppings
hops.remove_z_hoppings()

Finally, a magnetic field can be introduced using a Peierls substitution, using units of Tesla, with:

sample.set_magnetic_field(B)
tipsi.builder.uniform_strain(lattice_old, hop_dict_old, strain_tensor, beta)

Uniformly strain a Lattice, HopDict pair.

Parameters:
  • lattice_old (tipsi.Lattice) – lattice to strain
  • hop_dict_old (tipsi.HopDict) – hopping dictionary to strain
  • strain_tensor ((3,3)-list of floats) – strain tensor
  • beta (float) – strain coefficient
Returns:

  • lattice_new (tipsi.Lattice) – strained lattice
  • hop_dict_new (tipsi.HopDict) – strained hopping dictionary

tipsi.builder.extend_unit_cell(lattice_old, hop_dict_old, direction, amount)

Extend the unit cell in a certain direction. Especially helpful for including bias.

Parameters:
  • lattice_old (tipsi.Lattice) – lattice to extend
  • hop_dict_old (tipsi.HopDict) – hopping dictionary to extend
  • direction (integer) – index of lattice vector giving direction of extension
  • amount (integer) – number of unit cells to combine
Returns:

  • lattice_new (tipsi.Lattice) – extended lattice
  • hop_dict_new (tipsi.HopDict) – extended hopping dictionary

Interface with Wannier90

It is easy to create a Lattice, HopDict pair using Wannier90 output files. To this end, we use the function:

lattice, hop_dict = \
    read_wannier90(lat_file, coord_file, ham_file[, correct_file])
Here:
  • lat_file is the file containing lattice vectors and atom numbers, usually named *.win.
  • coord_file is the file containing orbital coordinates, usually named *_centres.xyz. It can be generated by parameter write_xyz = true in wannier90 input file.
  • ham_file is the file containing all the hoppings, usually named *_hr.dat. It can be generated by parameter write_hr = true in wannier90 input file.
  • correct_file (optional) correction terms for hoppings, usually named *_wsvec.dat. It can be generated by parameter use_ws_distance = true (available since wannier90 2.1) in wannier90 input file.
tipsi.input.read_wannier90(lat_file, coord_file, ham_file, correct_file=False)

Read Lattice and HopDict information from Wannier90 file

Parameters:
  • lat_file (string) – read lattice vectors from this file, usually named “*.win”
  • coord_file (string) – read wannier centres from this file, usually named “*_centres.xyz”
  • ham_file (string) – read hopping terms from this file, usually named “*_hr.dat”
  • correct_file (string, optional) – correction terms for hoppings, available since Wannier90 2.1, usually named “*_wsvec.dat”
Returns:

  • lat (Lattice object) – contains geometric information
  • hop_dict (HopDict object) – contains electric information

k-space functions

To check the Lattice and HopDict objects, we can calculate the band structure that they produce, provided a list of points in k-space:

bands = tipsi.band_structure(hop_dict, lat, kpoints)
for band in bands.swapaxes(0, 1):
    plt.plot(kvals, band)

We can also calculate band structures for entire Sample objects, although this is of course not feasible for larger systems:

bands = sample.band_structure(kpoints)
tipsi.builder.hop_dict_ft(hop_dict, lattice, momentum)

Calculate Fourier transform of a HopDict, Lattice pair.

Parameters:
  • hop_dict (HopDict object) – contains electronic information
  • lattice (Lattice object) – contains geometric information
  • momentum (3-list of floats) – momentum [kx, ky, kz]
Returns:

Hk – k-space Hamiltonian

Return type:

(nr_orbitals, nr_orbitals) list of complex floats

tipsi.builder.interpolate_k_points(k_points, resolution)

Get list of momenta by interpolation between symmetry points.

Parameters:
  • k_points ((n, 3) list of floats) – k-point coordinates
  • resolution (integer) – number of momenta between two k-points
Returns:

  • momenta (((n - 1) * resolution + 1, 3) list of floats) – interpolated k-point coordinates
  • xvals (((n - 1) * resolution + 1) list of floats) – x-axis values for band plot
  • ticks ((n) list of floats) – list of xvals corresponding to symmetry points

tipsi.builder.band_structure(hop_dict, lattice, momenta)

Calculate band structure for a HopDict, Lattice pair.

Parameters:
  • hop_dict (HopDict object) – contains electronic information
  • lattice (Lattice object) – contains geometric information
  • momenta ((n_momenta, 3) list of floats) – momenta [kx, ky, kz] for band structure calculation
Returns:

bands – list of energies corresponding to input momenta

Return type:

(n_momenta, n_orbitals) list of complex floats