Source code for wannierberri.models

"""Here we define some models, that can be used to test the code, or just to play around"""

import numpy as np


[docs] def Haldane_tbm(delta=0.2, hop1=-1.0, hop2=0.15, phi=np.pi / 2): """ Defines a Haldane model within `TBmodels <https://tbmodels.greschd.ch>`__ Parameters ----------- delta : float difference between the on-site potentials of the two atoms t : float nearest-neighbour hopping hop2 : float magnitude of next nearest-neighbour hopping phi : float phase of next nearest-neighbour hopping Notes ----- TBmodels should be installed to use this (`pip install tbmodels`) """ import tbmodels t2 = hop2 * np.exp(1.j * phi) t2c = t2.conjugate() my_model = tbmodels.Model( on_site=[-delta, delta], uc=[[1.0, 0.0], [0.5, np.sqrt(3.0) / 2.0]], dim=2, occ=1, pos=[[1. / 3., 1. / 3.], [2. / 3., 2. / 3.]]) my_model.add_hop(hop1, 0, 1, [0, 0]) my_model.add_hop(hop1, 1, 0, [1, 0]) my_model.add_hop(hop1, 1, 0, [0, 1]) my_model.add_hop(t2, 0, 0, [1, 0]) my_model.add_hop(t2, 1, 1, [1, -1]) my_model.add_hop(t2, 1, 1, [0, 1]) my_model.add_hop(t2c, 1, 1, [1, 0]) my_model.add_hop(t2c, 0, 0, [1, -1]) my_model.add_hop(t2c, 0, 0, [0, 1]) return my_model
[docs] def Haldane_ptb(delta=0.2, hop1=-1.0, hop2=0.15, phi=np.pi / 2): """same as :func:`~wannierberri.models.Haldane_tbm`, but uses `PythTB <http://www.physics.rutgers.edu/pythtb/>`__ Notes ----- PythTB should be installed to use this (`pip install pythtb`) """ import pythtb lat = [[1.0, 0.0], [0.5, np.sqrt(3.0) / 2.0]] orb = [[1. / 3., 1. / 3.], [2. / 3., 2. / 3.]] my_model = pythtb.tb_model(2, 2, lat, orb) delta = 0.2 t2 = hop2 * np.exp(1.j * phi) t2c = t2.conjugate() my_model.set_onsite([-delta, delta]) my_model.set_hop(hop1, 0, 1, [0, 0]) my_model.set_hop(hop1, 1, 0, [1, 0]) my_model.set_hop(hop1, 1, 0, [0, 1]) my_model.set_hop(t2, 0, 0, [1, 0]) my_model.set_hop(t2, 1, 1, [1, -1]) my_model.set_hop(t2, 1, 1, [0, 1]) my_model.set_hop(t2c, 1, 1, [1, 0]) my_model.set_hop(t2c, 0, 0, [1, -1]) my_model.set_hop(t2c, 0, 0, [0, 1]) return my_model
[docs] def Chiral(delta=2, hop1=1, hop2=1 / 3, phi=np.pi / 10, hopz_right=0.0, hopz_left=0.2, hopz_vert=0.0): """Create a chiral model - a chirally stacked haldane model - using `PythTB <http://www.physics.rutgers.edu/pythtb/>`__ Following the article by `Yoda,Yokoyama & Murakami 2018 <https://doi.org/10.1021/acs.nanolett.7b04300>`__ this model breaks time-reversal and inversion, so it can be used to test almost any quantity. Has a symmetry C3z Parameters ----------- delta : float difference between the on-site potentials of the two atoms hop1 : float nearest-neighbour in-plane hopping hop2 : float magnitude of next nearest-neighbour in-plane hopping phi : float phase of next nearest-neighbour in-plane hopping hopz_vert : float or complex interlayer vertical hopping hopz_right : float or complex chiral right-handed hopping in the z direction hopz_left : float or complex chiral left-handed hopping in the z direction Notes ----- PythTB should be installed to use this (`pip install pythtb`) """ import pythtb lat = [[1.0, 0.0, 0.0], [0.5, np.sqrt(3.0) / 2.0, 0.0], [0.0, 0.0, 1.0]] # define coordinates of orbitals orb = [[1. / 3., 1. / 3., 0.0], [2. / 3., 2. / 3., 0.0]] # make tree dimensional (stacked) tight-binding Haldene model my_model = pythtb.tb_model(3, 3, lat, orb) # set model parameters t2 = hop2 * np.exp(1.j * phi) # set on-site energies my_model.set_onsite([-delta, delta]) # set hoppings (one for each connected pair of orbitals) # from j in R to i in 0 # (amplitude, i, j, [lattice vector to cell containing j]) my_model.set_hop(hop1, 0, 1, [0, 0, 0]) my_model.set_hop(hop1, 1, 0, [1, 0, 0]) my_model.set_hop(hop1, 1, 0, [0, 1, 0]) # add second neighbour complex hoppings my_model.set_hop(t2, 0, 0, [0, -1, 0]) my_model.set_hop(t2, 0, 0, [1, 0, 0]) my_model.set_hop(t2, 0, 0, [-1, 1, 0]) my_model.set_hop(t2, 1, 1, [-1, 0, 0]) my_model.set_hop(t2, 1, 1, [1, -1, 0]) my_model.set_hop(t2, 1, 1, [0, 1, 0]) # add vertical hoppings my_model.set_hop(hopz_vert, 0, 0, [0, 0, 1]) my_model.set_hop(hopz_vert, 1, 1, [0, 0, 1]) # add chiral hoppings (left-handed) my_model.set_hop(hopz_left, 0, 0, [0, -1, 1]) my_model.set_hop(hopz_left, 0, 0, [1, 0, 1]) my_model.set_hop(hopz_left, 0, 0, [-1, 1, 1]) my_model.set_hop(hopz_left, 1, 1, [-1, 0, 1]) my_model.set_hop(hopz_left, 1, 1, [1, -1, 1]) my_model.set_hop(hopz_left, 1, 1, [0, 1, 1]) # add chiral hoppings (right-handed) my_model.set_hop(hopz_right, 0, 0, [0, -1, -1]) my_model.set_hop(hopz_right, 0, 0, [1, 0, -1]) my_model.set_hop(hopz_right, 0, 0, [-1, 1, -1]) my_model.set_hop(hopz_right, 1, 1, [-1, 0, -1]) my_model.set_hop(hopz_right, 1, 1, [1, -1, -1]) my_model.set_hop(hopz_right, 1, 1, [0, 1, -1]) return my_model
def CuMnAs_2d( nx=0, ny=1, nz=0, hop1=1, hop2=0.08, l=0.8, J=0.6, dt=0.0, ): """Create a 2D model of antiferromagnetic CuMnAs using `PythTB <http://www.physics.rutgers.edu/pythtb/>`__ Following the article by `Šmejkal, Železný, Sinova & Jungwirth 2017 <https://doi.org/10.1103/PhysRevLett.118.106402>`__ this model breaks time-reversal and inversion, but it preserves the combination of both (P*T). Parameters ----------- nx : float x-component of the Néel vector ny : float y-component of the Néel vector nz : float z-component of the Néel vector hop1 : float magnitude of nearest-neighbour hopping (A-A) hop2 : float magnitude of next nearest-neighbour hopping (A-B) l : float second nearest-neighbor spin-orbit coupling J : float magnitude of the Néel vector dt : float PT-breaking term making the A-A and B-B hoppings different Notes ----- PythTB should be installed to use this (`pip install pythtb`) """ import pythtb # initialize the CuMnAs model lat = [[1.0, 0.0], [0.0, 1.0]] orb = [[0., 0.], [0., 0.], [0.5, 0.5], [0.5, 0.5]] # Neel vector orientation nabs = np.sqrt(nx**2 + ny**2 + nz**2) nx = nx / nabs ny = ny / nabs nz = nz / nabs my_model = pythtb.tb_model(2, 2, lat, orb) # set hoppings (one for each connected pair of orbitals) # (amplitude, i, j, [lattice vector to cell containing j]) # nearest-neighbor (A-B hopping) my_model.set_hop(-0.5 * hop1, 0, 2, [0, 0]) my_model.set_hop(-0.5 * hop1, 0, 2, [-1, 0]) my_model.set_hop(-0.5 * hop1, 0, 2, [0, -1]) my_model.set_hop(-0.5 * hop1, 0, 2, [-1, -1]) my_model.set_hop(-0.5 * hop1, 1, 3, [0, 0]) my_model.set_hop(-0.5 * hop1, 1, 3, [-1, 0]) my_model.set_hop(-0.5 * hop1, 1, 3, [0, -1]) my_model.set_hop(-0.5 * hop1, 1, 3, [-1, -1]) # second nearest-neighbor (A-A hopping) my_model.set_hop(-0.5 * hop2, 0, 0, [1, 0]) my_model.set_hop(-0.5 * hop2, 0, 0, [0, 1]) my_model.set_hop(-0.5 * hop2, 1, 1, [1, 0]) my_model.set_hop(-0.5 * hop2, 1, 1, [0, 1]) my_model.set_hop(-0.5 * hop2, 2, 2, [1, 0]) my_model.set_hop(-0.5 * hop2, 2, 2, [0, 1]) my_model.set_hop(-0.5 * hop2, 3, 3, [1, 0]) my_model.set_hop(-0.5 * hop2, 3, 3, [0, 1]) # second neighbor SOC my_model.set_hop(-0.5 * l, 0, 1, [1, 0]) my_model.set_hop(0.5 * l, 0, 1, [-1, 0]) my_model.set_hop(0.5 * l * 1j, 0, 1, [0, 1]) my_model.set_hop(-0.5 * l * 1j, 0, 1, [0, -1]) my_model.set_hop(0.5 * l, 2, 3, [1, 0]) my_model.set_hop(-0.5 * l, 2, 3, [-1, 0]) my_model.set_hop(-0.5 * l * 1j, 2, 3, [0, 1]) my_model.set_hop(0.5 * l * 1j, 2, 3, [0, -1]) # AF exchange coupling my_model.set_hop(J * (nx - 1j * ny), 0, 1, [0, 0]) my_model.set_hop(J * (-nx + 1j * ny), 2, 3, [0, 0]) # set on-site energies my_model.set_onsite([J * nz, -J * nz, -J * nz, J * nz]) # break PT by making sublattices different my_model.set_hop(-0.5 * dt, 0, 0, [1, 0], mode='add') my_model.set_hop(-0.5 * dt, 0, 0, [0, 1], mode='add') my_model.set_hop(-0.5 * dt, 1, 1, [1, 0], mode='add') my_model.set_hop(-0.5 * dt, 1, 1, [0, 1], mode='add') my_model.set_hop(0.5 * dt, 2, 2, [1, 0], mode='add') my_model.set_hop(0.5 * dt, 2, 2, [0, 1], mode='add') my_model.set_hop(0.5 * dt, 3, 3, [1, 0], mode='add') my_model.set_hop(0.5 * dt, 3, 3, [0, 1], mode='add') return my_model def KaneMele_ptb(topological): """Return a Kane-Mele model in the normal or topological phase. example taken from `PythTB web page <https://www.physics.rutgers.edu/pythtb/examples.html#kane-mele-model-using-spinor-features>`__ topological : `even` or `odd` """ import pythtb # define lattice vectors lat = [[1.0, 0.0], [0.5, np.sqrt(3.0) / 2.0]] # define coordinates of orbitals orb = [[1. / 3., 1. / 3.], [2. / 3., 2. / 3.]] # make two dimensional tight-binding Kane-Mele model ret_model = pythtb.tb_model(2, 2, lat, orb, nspin=2) # set model parameters depending on whether you are in the topological # phase or not if topological == "even": esite = 2.5 elif topological == "odd": esite = 1.0 # set other parameters of the model thop = 1.0 spin_orb = 0.6 * thop * 0.5 rashba = 0.25 * thop # set on-site energies ret_model.set_onsite([esite, (-1.0) * esite]) # set hoppings (one for each connected pair of orbitals) # (amplitude, i, j, [lattice vector to cell containing j]) # useful definitions sigma_x = np.array([0., 1., 0., 0]) sigma_y = np.array([0., 0., 1., 0]) sigma_z = np.array([0., 0., 0., 1]) # spin-independent first-neighbor hoppings ret_model.set_hop(thop, 0, 1, [0, 0]) ret_model.set_hop(thop, 0, 1, [0, -1]) ret_model.set_hop(thop, 0, 1, [-1, 0]) # second-neighbour spin-orbit hoppings (s_z) ret_model.set_hop(-1.j * spin_orb * sigma_z, 0, 0, [0, 1]) ret_model.set_hop(1.j * spin_orb * sigma_z, 0, 0, [1, 0]) ret_model.set_hop(-1.j * spin_orb * sigma_z, 0, 0, [1, -1]) ret_model.set_hop(1.j * spin_orb * sigma_z, 1, 1, [0, 1]) ret_model.set_hop(-1.j * spin_orb * sigma_z, 1, 1, [1, 0]) ret_model.set_hop(1.j * spin_orb * sigma_z, 1, 1, [1, -1]) # Rashba first-neighbor hoppings: (s_x)(dy)-(s_y)(d_x) r3h = np.sqrt(3.0) / 2.0 # bond unit vectors are (r3h,half) then (0,-1) then (-r3h,half) ret_model.set_hop(1.j * rashba * (0.5 * sigma_x - r3h * sigma_y), 0, 1, [0, 0], mode="add") ret_model.set_hop(1.j * rashba * (-1.0 * sigma_x), 0, 1, [0, -1], mode="add") ret_model.set_hop(1.j * rashba * (0.5 * sigma_x + r3h * sigma_y), 0, 1, [-1, 0], mode="add") return ret_model def Chiral_OSD(): """ Chiral model to trest OSD """ from pythtb import tb_model # define lattice vectors a = 1.0 c = 1.0 a1 = [np.sqrt(3.0) * a, 0.0, 0.0] a2 = [np.sqrt(3.0) * a / 2.0, 3.0 * a / 2.0, 0.0] a3 = [0.0, 0.0, c] lat = [a1, a2, a3] # define coordinates of orbitals orb = [[0.0, 0.0, 0.0], [1 / 3, 1 / 3, 0.0]] # make three dimensional tight-binding model my_model = tb_model(3, 3, lat, orb, nspin=2) # set model parameters t1 = 1.0 Delta = 0.5 * t1 l1 = -0.06 * t1 l2 = 0.05 * t1 # useful definitions # Pauli matrices P0 = np.array([1.0, 0.0, 0.0, 0.0]) P1 = np.array([0.0, 1.0, 0.0, 0.0]) P2 = np.array([0.0, 0.0, 1.0, 0.0]) P3 = np.array([0.0, 0.0, 0.0, 1.0]) # nearest-neighbor vectors d1 = [0.0, a, 0.0] d2 = [np.sqrt(3.0) * a / 2.0, -a / 2.0, 0.0] d3 = [-np.sqrt(3.0) * a / 2.0, -a / 2.0, 0.0] # set on-site energies my_model.set_onsite([-Delta * P0, Delta * P0]) # set hoppings (one for each connected pair of orbitals) # (amplitude, i, j, [lattice vector to cell containing j]) # nearest-neighbor hoppings (spin-independent and -dependent): my_model.set_hop(1.j * t1 * P0, 1, 0, [0, 0, 0]) my_model.set_hop(1.j * t1 * P0, 1, 0, [1, 0, 0]) my_model.set_hop(1.j * t1 * P0, 1, 0, [0, 1, 0]) my_model.set_hop((1.j * l1 / a) * (d1[0] * P1 + d1[1] * P2), 1, 0, [0, 1, 0], mode='add') my_model.set_hop((1.j * l1 / a) * (d2[0] * P1 + d2[1] * P2), 1, 0, [1, 0, 0], mode='add') my_model.set_hop((1.j * l1 / a) * (d3[0] * P1 + d3[1] * P2), 1, 0, [0, 0, 0], mode='add') # next-to-nearest neighbor hoppings (helical): my_model.set_hop((1.j * l2 / a) * (a1[0] * P1 + a1[1] * P2 + a3[2] * P3), 0, 0, [1, 0, 1]) my_model.set_hop((1.j * l2 / a) * (-a2[0] * P1 - a2[1] * P2 + a3[2] * P3), 0, 0, [0, -1, 1]) my_model.set_hop((1.j * l2 / a) * ((-a1[0] + a2[0]) * P1 + (-a1[1] + a2[1]) * P2 + a3[2] * P3), 0, 0, [-1, 1, 1]) my_model.set_hop((1.j * l2 / a) * (a2[0] * P1 + a2[1] * P2 + a3[2] * P3), 1, 1, [0, 1, 1]) my_model.set_hop((1.j * l2 / a) * (-a1[0] * P1 - a1[1] * P2 + a3[2] * P3), 1, 1, [-1, 0, 1]) my_model.set_hop((1.j * l2 / a) * ((a1[0] - a2[0]) * P1 + (a1[1] - a2[1]) * P2 + a3[2] * P3), 1, 1, [1, -1, 1]) return my_model