# 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 float
reciprocal_latt()

Get reciprocal lattice vectors.

Returns: array containing [k_0, k_1, k_2] (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 x, y and z coordinates of orbital numpy array of floats
volume_unit_cell()

Get unit cell volume.

Returns: unit cell volume 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)


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)

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()

delete(rel_unit_cell)

Delete hopping matrix from dictionary.

Parameters: rel_unit_cell (3-tuple of integers) – relative unit cell coordinates True if site was deleted, false if not 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)

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: 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 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.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.

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] Hk – k-space Hamiltonian (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 bands – list of energies corresponding to input momenta (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 True if hopping value is deleted False if hopping value is not found bool
energy_range()

Energy range to consider in calculations.

Returns: en_range – All eigenvalues are between (-en_range / 2, en_range / 2) 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. value – Rescale value. 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)

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 True if hopping value is changed False if hopping value is added 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

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)

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 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 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 = \

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” 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] Hk – k-space Hamiltonian (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 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 bands – list of energies corresponding to input momenta (n_momenta, n_orbitals) list of complex floats