Esempio n. 1
0
def test_init():
    lat1d = pb.Lattice(1)
    assert len(lat1d.vectors) == 1
    assert pytest.fuzzy_equal(lat1d.vectors[0], [1, 0, 0])

    lat2d = pb.Lattice([1, 0], [0, 1])
    assert len(lat2d.vectors) == 2
    assert pytest.fuzzy_equal(lat2d.vectors[0], [1, 0, 0])
    assert pytest.fuzzy_equal(lat2d.vectors[1], [0, 1, 0])

    lat3d = pb.Lattice([1, 0, 0], [0, 1, 0], [0, 0, 1])
    assert len(lat3d.vectors) == 3
    assert pytest.fuzzy_equal(lat3d.vectors[0], [1, 0, 0])
    assert pytest.fuzzy_equal(lat3d.vectors[1], [0, 1, 0])
    assert pytest.fuzzy_equal(lat3d.vectors[2], [0, 0, 1])
Esempio n. 2
0
def monolayer_4atom(onsite=(0, 0)):
    """Nearest-neighbor with 4 atoms per unit cell: square lattice instead of oblique

    Parameters
    ----------
    onsite : Tuple[float, float]
        Onsite energy for sublattices A and B.
    """
    from .constants import a_cc, a, t

    lat = pb.Lattice(a1=[a, 0], a2=[0, 3*a_cc])

    lat.add_sublattices(('A',  [  0, -a_cc/2], onsite[0]),
                        ('B',  [  0,  a_cc/2], onsite[1]))

    lat.add_aliases(('A2', 'A', [a / 2, a_cc]),
                    ('B2', 'B', [a / 2, 2 * a_cc]))

    lat.add_hoppings(
        # inside the unit sell
        ([0, 0], 'A',  'B',  t),
        ([0, 0], 'B',  'A2', t),
        ([0, 0], 'A2', 'B2', t),
        # between neighbouring unit cells
        ([-1, -1], 'A', 'B2', t),
        ([ 0, -1], 'A', 'B2', t),
        ([-1,  0], 'B', 'A2', t),
    )

    lat.min_neighbors = 2
    return lat
Esempio n. 3
0
def bilayer_graphene():
    """Bilayer lattice in the AB-stacked form (Bernal-stacked)

    This is the simplest model with just a single intralayer and a single interlayer hopping.
    """
    a = 0.24595  # [nm] unit cell length
    a_cc = 0.142  # [nm] carbon-carbon distance
    c0 = 0.335  # [nm] interlayer spacing

    lat = pb.Lattice(a1=[a / 2, a / 2 * sqrt(3)], a2=[a / 2, -a / 2 * sqrt(3)])

    lat.add_sublattices(('A1', [0, -a_cc / 2, 0]), ('B1', [0, a_cc / 2, 0]),
                        ('A2', [0, a_cc / 2, -c0]),
                        ('B2', [0, 3 * a_cc / 2, -c0]))

    lat.register_hopping_energies({
        'gamma0': -2.8,  # [eV] intralayer
        'gamma1': -0.4,  # [eV] interlayer
    })

    lat.add_hoppings(
        # layer 1
        ([0, 0], 'A1', 'B1', 'gamma0'),
        ([0, 1], 'A1', 'B1', 'gamma0'),
        ([-1, 0], 'A1', 'B1', 'gamma0'),
        # layer 2
        ([0, 0], 'A2', 'B2', 'gamma0'),
        ([0, 1], 'A2', 'B2', 'gamma0'),
        ([-1, 0], 'A2', 'B2', 'gamma0'),
        # interlayer
        ([0, 0], 'B1', 'A2', 'gamma1'))

    return lat
Esempio n. 4
0
def benzene():
    """Return the lattice specification for benzene  """
    N = 1  # number of rings
    a = 0.2462  # [nm] site-site distance
    al = (N + 1) * a * sqrt(3)  # [nm] unit cell length
    t = -1  # [eV] nearest neighbour hopping
    #t2 = 0.2
    # create a lattice with 2 primitive vectors
    lat = pb.Lattice(a1=[al, 0], a2=[0, 3 * a])

    lat.add_sublattices(
        # name and position
        ('C1', [-0.5 * a * sqrt(3), 0.5 * a], 0),
        ('C2', [-0.5 * a * sqrt(3), -0.5 * a], 0),
        ('C3', [0, a], 0),
        ('C4', [0, -a], 0),
        ('C5', [0.5 * a * sqrt(3), 0.5 * a], 0),
        ('C6', [0.5 * a * sqrt(3), -0.5 * a], 0))

    lat.add_hoppings(
        # inside the main cell
        ([0, 0], 'C1', 'C2', t),
        ([0, 0], 'C1', 'C3', t),
        ([0, 0], 'C3', 'C5', t),
        ([0, 0], 'C5', 'C6', t),
        ([0, 0], 'C4', 'C6', t),
        ([0, 0], 'C2', 'C4', t)
        # between neighboring cells
        #        ([1, -1], 'A', 'B', t),
    )

    return lat
Esempio n. 5
0
def graphene_initial(onsite=(0, 0)):
    theta = np.pi / 3
    a1 = np.array([1 + np.cos(theta), np.sin(theta)])
    a2 = np.array([0, 2 * np.sin(theta)])

    lat = pb.Lattice(a1=a1, a2=a2)
    lat.add_sublattices(
        # name, position, and onsite potential
        ('A', [0, 0], onsite[0]),
        ('B', [1, 0], onsite[1]))

    lat.add_hoppings(
        # inside the main cell, between which atoms, and the value
        ([0, 0], 'A', 'B', -1),
        # between neighboring cells, between which atoms, and the value
        ([-1, 0], 'A', 'B', -1 / EnergyScale),
        ([-1, 1], 'A', 'B', -1 / EnergyScale))

    node0 = [[+0, +0], 'A']
    node1 = [[+0, +0], 'B']
    node2 = [[-1, +0], 'B']
    node3 = [[-1, +1], 'B']

    struc_disorder_one = kite.StructuralDisorder(lat, position=[[32, 32]])
    struc_disorder_one.add_structural_disorder(
        (*node0, *node1, timp), (*node0, *node2, timp), (*node0, *node3, timp),
        (*node0, limp))

    return lat, [struc_disorder_one]
Esempio n. 6
0
def haldane():
    """Return the lattice specification for Haldane model"""

    a = 0.24595  # [nm] unit cell length
    a_cc = 0.142  # [nm] carbon-carbon distance

    t = -1
    t2 = t / 10
    m = 0
    # create a lattice with 2 primitive vectors
    lat = pb.Lattice(a1=[a, 0], a2=[a / 2, a / 2 * sqrt(3)])

    lat.add_sublattices(
        # name and position
        ('A', [0, -a_cc / 2], -m),
        ('B', [0, a_cc / 2], m))

    lat.add_hoppings(
        # inside the main cell
        ([0, 0], 'A', 'B', t),
        # between neighboring cells
        ([1, -1], 'A', 'B', t),
        ([0, -1], 'A', 'B', t),
        ([1, 0], 'A', 'A', t2 * 1j),
        ([0, -1], 'A', 'A', t2 * 1j),
        ([-1, 1], 'A', 'A', t2 * 1j),
        ([1, 0], 'B', 'B', t2 * -1j),
        ([0, -1], 'B', 'B', t2 * -1j),
        ([-1, 1], 'B', 'B', t2 * -1j))

    return lat
Esempio n. 7
0
def graphene(onsite=(0, 0)):
    """Make a honeycomb lattice with nearest neighbor hopping

    Parameters
    ----------
    onsite : tuple or list
        Onsite energy at different sublattices.
    """

    theta = np.pi / 3
    t = 2.8  # eV
    a1 = np.array([1, 0, 0] )
    a2 = np.array([0, 1, 0])
    a3 = np.array([0, 0, 1])
    lat = pb.Lattice(
        a1=a1, a2=a2, a3=a3
    )
    lat.add_sublattices(
        # name, position, and onsite potential
        ('A', [0, 0, 0], onsite[0])
    )
    lat.add_hoppings(
        ([1, 0, 0], 'A', 'A', - t),
        ([0, 1, 0], 'A', 'A', - t),
        ([0, 0, 1], 'A', 'A', - t)
    )

    return lat
Esempio n. 8
0
def test_brillouin_zone():
    from math import pi, sqrt

    lat = pb.Lattice(a1=1)
    assert pytest.fuzzy_equal(lat.brillouin_zone(), [-pi, pi])

    lat = pb.Lattice(a1=[0, 1], a2=[0.5, 0.5])
    assert pytest.fuzzy_equal(
        lat.brillouin_zone(),
        [[0, -2 * pi], [2 * pi, 0], [0, 2 * pi], [-2 * pi, 0]])

    # Identical lattices represented using acute and obtuse angles between primitive vectors
    acute = pb.Lattice(a1=[1, 0], a2=[1 / 2, 1 / 2 * sqrt(3)])
    obtuse = pb.Lattice(a1=[1 / 2, 1 / 2 * sqrt(3)],
                        a2=[1 / 2, -1 / 2 * sqrt(3)])
    assert pytest.fuzzy_equal(acute.brillouin_zone(), obtuse.brillouin_zone())
Esempio n. 9
0
def monolayer_alt(onsite=(0, 0)):
    """Nearest-neighbor lattice with alternative lattice vectors

    This lattice is mainly here to demonstrate specifying hoppings in matrix form.

    Parameters
    ----------
    onsite : Tuple[float, float]
        Onsite energy for sublattices A and B.
    """
    from math import sqrt
    from .constants import a_cc, a, t

    lat = pb.Lattice(
        a1=[a / 2, a / 2 * sqrt(3)],
        a2=[-a / 2, a / 2 * sqrt(3)],
    )

    lat.add_sublattices(('A', [0, 0], onsite[0]), ('B', [0, a_cc], onsite[1]))

    # matrix hopping specification
    r0 = [0, 0]
    r1 = [0, -1]
    r2 = [-1, 0]

    tr0 = [[0, t], [t, 0]]
    tr1 = [[0, t], [0, 0]]
    tr2 = [[0, t], [0, 0]]

    lat.add_hopping_matrices([r0, tr0], [r1, tr1], [r2, tr2])
    lat.min_neighbors = 2
    return lat
Esempio n. 10
0
def honeycomb_lattice(onsite=(0, 0)):
    """Make a honeycomb lattice with nearest neighbor hopping
    
    Parameters
    ----------
    onsite : tuple or list
        Onsite energy at different sublattices.
    """ ""

    # define lattice vectors
    theta = np.pi / 3
    a1 = np.array([1 + np.cos(theta), np.sin(theta)])
    a2 = np.array([0, 2 * np.sin(theta)])

    # create a lattice with 2 primitive vectors
    lat = pb.Lattice(a1=a1, a2=a2)

    # Add sublattices
    lat.add_sublattices(
        # name, position, and onsite potential
        ('A', [0, 0], onsite[0]),
        ('B', [1, 0], onsite[1]))

    # Add hoppings
    lat.add_hoppings(
        # inside the main cell, between which atoms, and the value
        ([+0, +0], 'A', 'B', -1),
        # between neighboring cells, between which atoms, and the value
        ([-1, +0], 'A', 'B', -1),
        ([-1, +1], 'A', 'B', -1))

    return lat
Esempio n. 11
0
def graphene_initial(onsite=(0,0)):

    theta = np.pi / 3
    a1 = np.array([2 * np.sin(theta), 0])
    a2 = np.array([np.sin(theta), 1 + np.cos(theta)])

    # create a lattice with 2 primitive vectors
    lat = pb.Lattice(
    a1=a1,
    a2=a2
    )

    # Add sublattices
    lat.add_sublattices(
    # name, position, and onsite potential
    ('A', [0, 0], onsite[0]),
    ('B', [0, 1], onsite[1])
    )

    # Add hoppings
    lat.add_hoppings(
    # inside the main cell, between which atoms, and the value
    ([0, 0], 'A', 'B', - 1),
    # between neighboring cells, between which atoms, and the value
    ([0, -1], 'A', 'B', - 1),
    ([1, -1], 'A', 'B', - 1)
    )

    return lat
Esempio n. 12
0
def graphene(onsite=(0, 0), nearest_neighbors=1):
    """Make a honeycomb lattice with nearest neighbor hopping

    Parameters
    ----------
    onsite : tuple or list
        Onsite energy at different sublattices.
    """

    theta = np.pi / 3

    a1 = np.array([1 + np.cos(theta), np.sin(theta)])
    a2 = np.array([0, 2 * np.sin(theta)])
    lat = pb.Lattice(a1=a1, a2=a2)
    lat.add_sublattices(
        # name, position, and onsite potential
        ('A', [0, 0], onsite[0]),
        ('B', [1, 0], onsite[1]))
    lat.add_hoppings(([0, 0], 'A', 'B', -t), ([-1, 0], 'A', 'B', -t),
                     ([-1, 1], 'A', 'B', -t))

    if nearest_neighbors >= 2:
        lat.add_hoppings(
            ([0, -1], 'A', 'A', t_nn),
            ([0, -1], 'B', 'B', t_nn),
            ([1, -1], 'A', 'A', t_nn),
            ([1, -1], 'B', 'B', t_nn),
            ([1, 0], 'A', 'A', t_nn),
            ([1, 0], 'B', 'B', t_nn),
        )

    return lat
Esempio n. 13
0
def bilayer(gamma3=False, gamma4=False, onsite=(0, 0, 0, 0)):
    """Bilayer lattice in the AB-stacked form (Bernal-stacked)

    * :math:`\gamma_0` is the single-layer hopping within the top layer (A1/B1)
      and bottom layer (A2/B2)
    * :math:`\gamma_1` is the inter-layer hopping between B1 and A2
      (where atom B1 lies directly over A2)
    * Hoppings :math:`\gamma_3` and :math:`\gamma_4` are optional (see parameters)

    Parameters
    ----------
    gamma3, gamma4 : bool
        Enable :math:`\gamma_3` and/or :math:`\gamma_4` hoppings.
        By default, only :math:`\gamma_0` and :math:`\gamma_1` are active.
    onsite : Tuple[float, float, float, float]
        Onsite energy for A1, B1, A2, B2
    """
    from math import sqrt
    from .constants import a_cc, a, t

    lat = pb.Lattice(a1=[a / 2, a / 2 * sqrt(3)], a2=[-a / 2, a / 2 * sqrt(3)])

    c0 = 0.335  # [nm] interlayer spacing
    lat.add_sublattices(('A1', [0, -a_cc / 2, 0], onsite[0]),
                        ('B1', [0, a_cc / 2, 0], onsite[1]),
                        ('A2', [0, a_cc / 2, -c0], onsite[2]),
                        ('B2', [0, 3 * a_cc / 2, -c0], onsite[3]))

    lat.register_hopping_energies({
        'gamma0': t,
        'gamma1': -0.4,
        'gamma3': -0.3,
        'gamma4': -0.04
    })

    lat.add_hoppings(
        # layer 1
        ([0, 0], 'A1', 'B1', 'gamma0'),
        ([0, -1], 'A1', 'B1', 'gamma0'),
        ([-1, 0], 'A1', 'B1', 'gamma0'),
        # layer 2
        ([0, 0], 'A2', 'B2', 'gamma0'),
        ([0, -1], 'A2', 'B2', 'gamma0'),
        ([-1, 0], 'A2', 'B2', 'gamma0'),
        # interlayer
        ([0, 0], 'B1', 'A2', 'gamma1'))

    if gamma3:
        lat.add_hoppings(([0, 1], 'B2', 'A1', 'gamma3'),
                         ([1, 0], 'B2', 'A1', 'gamma3'),
                         ([1, 1], 'B2', 'A1', 'gamma3'))

    if gamma4:
        lat.add_hoppings(([0, 0], 'A2', 'A1', 'gamma4'),
                         ([0, 1], 'A2', 'A1', 'gamma4'),
                         ([1, 0], 'A2', 'A1', 'gamma4'))

    lat.min_neighbors = 2
    return lat
Esempio n. 14
0
 def square_lattice(d=1, t=1):
     lat = pb.Lattice(a1=[d, 0], a2=[0, d])
     lat.add_sublattices(('A', [0, 0]))
     lat.add_hoppings(
         ([0, 1], 'A', 'A', -t),
         ([1, 0], 'A', 'A', -t),
     )
     return lat
Esempio n. 15
0
def square_lattice(onsite=0):
    a1 = np.array([1, 0])
    a2 = np.array([0, 1])

    lat = pb.Lattice(a1=a1, a2=a2)
    lat.add_sublattices(('A', [0, 0], onsite))
    lat.add_hoppings(([1, 0], 'A', 'A', -1), ([0, 1], 'A', 'A', -1))
    return lat
Esempio n. 16
0
def trestle(a=0.2, t1=0.8 + 0.6j, t2=2):
    """A more complicated 1D lattice with 2 sublattices"""
    lat = pb.Lattice(1.3 * a)
    lat.add_sublattices(('A', [0, 0], 0), ('B', [a / 2, a], 0))
    lat.add_hoppings((0, 'A', 'B', t1), (1, 'A', 'B', t1), (1, 'A', 'A', t2),
                     (1, 'B', 'B', t2))
    lat.min_neighbors = 2
    return lat
Esempio n. 17
0
def mock_lattice():
    a_cc, a, t = 1, 1.73, 1
    lat = pb.Lattice([a, 0], [0.5 * a, 0.866 * a])
    lat.add_sublattices(['a', (0, -a_cc / 2)], ['b', (0, a_cc / 2)])
    lat.add_hoppings([(0, 0), 'a', 'b', t], [(1, -1), 'a', 'b', t],
                     [(0, -1), 'a', 'b', t])
    lat.min_neighbors = 2
    return lat
Esempio n. 18
0
def phosphorene_4band():
    """Monolayer phosphorene lattice using the four-band model"""
    a = 0.222
    ax = 0.438
    ay = 0.332
    theta = 96.79 * (pi / 180)
    phi = 103.69 * (pi / 180)

    lat = pb.Lattice(a1=[ax, 0], a2=[0, ay])

    h = a * sin(phi - pi / 2)
    s = 0.5 * ax - a * cos(theta / 2)
    lat.add_sublattices(('A', [-ax / 4 - s / 2, -ay / 4, h], 0),
                        ('B', [-ax / 4 + s / 2, -ay / 4, 0], 0),
                        ('C', [ax / 4 - s / 2, ay / 4, 0], 0),
                        ('D', [ax / 4 + s / 2, ay / 4, h], 0))

    lat.register_hopping_energies({
        't1': -1.22,
        't2': 3.665,
        't3': -0.205,
        't4': -0.105,
        't5': -0.055
    })

    lat.add_hoppings(
        # t1
        ([-1, 0], 'A', 'D', 't1'),
        ([-1, -1], 'A', 'D', 't1'),
        ([0, 0], 'B', 'C', 't1'),
        ([0, -1], 'B', 'C', 't1'),
        # t2
        ([0, 0], 'A', 'B', 't2'),
        ([0, 0], 'C', 'D', 't2'),
        # t3
        ([0, 0], 'A', 'D', 't3'),
        ([0, -1], 'A', 'D', 't3'),
        ([1, 1], 'C', 'B', 't3'),
        ([1, 0], 'C', 'B', 't3'),
        # t4
        ([0, 0], 'A', 'C', 't4'),
        ([0, -1], 'A', 'C', 't4'),
        ([-1, 0], 'A', 'C', 't4'),
        ([-1, -1], 'A', 'C', 't4'),
        ([0, 0], 'B', 'D', 't4'),
        ([0, -1], 'B', 'D', 't4'),
        ([-1, 0], 'B', 'D', 't4'),
        ([-1, -1], 'B', 'D', 't4'),
        # t5
        ([-1, 0], 'A', 'B', 't5'),
        ([0, 1], 'A', 'B', 't5'),
        ([0, -1], 'A', 'B', 't5'),
        ([-1, 0], 'C', 'D', 't5'),
        ([0, 1], 'C', 'D', 't5'),
        ([0, -1], 'C', 'D', 't5'),
    )

    return lat
Esempio n. 19
0
def monolayer(nearest_neighbors=1, onsite=(0, 0), **kwargs):
    """Monolayer graphene lattice up to `nearest_neighbors` hoppings

    Parameters
    ----------
    nearest_neighbors : int
        Number of nearest neighbors to consider.
    onsite : Tuple[float, float]
        Onsite energy for sublattices A and B.
    **kwargs
        Specify the hopping parameters `t`, `t_nn` and `t_nnn`.
        If not given, the default values from :mod:`.graphene.constants` will be used.
    """
    from math import sqrt
    from .constants import a_cc, a, t, t_nn

    lat = pb.Lattice(a1=[a, 0], a2=[a / 2, a / 2 * sqrt(3)])

    # The next-nearest hoppings shift the Dirac point away from zero energy.
    # This will push it back to zero for consistency with the first-nearest model.
    onsite_offset = 0 if nearest_neighbors < 2 else 3 * kwargs.get(
        't_nn', t_nn)

    lat.add_sublattices(('A', [0, -a_cc / 2], onsite[0] + onsite_offset),
                        ('B', [0, a_cc / 2], onsite[1] + onsite_offset))

    lat.register_hopping_energies({
        't': kwargs.get('t', t),
        't_nn': kwargs.get('t_nn', t_nn),
        't_nnn': kwargs.get('t_nnn', 0.05),
    })

    lat.add_hoppings(([0, 0], 'A', 'B', 't'), ([1, -1], 'A', 'B', 't'),
                     ([0, -1], 'A', 'B', 't'))

    if nearest_neighbors >= 2:
        lat.add_hoppings(
            ([0, -1], 'A', 'A', 't_nn'),
            ([0, -1], 'B', 'B', 't_nn'),
            ([1, -1], 'A', 'A', 't_nn'),
            ([1, -1], 'B', 'B', 't_nn'),
            ([1, 0], 'A', 'A', 't_nn'),
            ([1, 0], 'B', 'B', 't_nn'),
        )

    if nearest_neighbors >= 3:
        lat.add_hoppings(
            [(1, -2), 'A', 'B', 't_nnn'],
            [(1, 0), 'A', 'B', 't_nnn'],
            [(-1, 0), 'A', 'B', 't_nnn'],
        )

    if nearest_neighbors >= 4:
        raise RuntimeError("No more")

    lat.min_neighbors = 2
    return lat
Esempio n. 20
0
def anthracene():
    """Return the lattice specification for anthracene (3 rings) """
    N=3 # number of rings
    a = 0.2462  # [nm] site-site distance
    al = 1.5*N*a*sqrt(3)  # [nm] unit cell length
    t = -1      # [eV] nearest neighbour hopping
    #t2 = 0.2
    # create a lattice with 2 primitive vectors
    lat = pb.Lattice(
        a1=[al, 0],
        a2=[al/2, al/2 * sqrt(3)]
    )

    lat.add_sublattices(
        # name and position
        ('C1', [-0.5*a*sqrt(3),0.5*a],0),
        ('C2', [-0.5*a*sqrt(3),-0.5*a],0),
        ('C3', [0, a], 0),
        ('C4', [0, -a], 0),
        ('C5', [0.5 * a * sqrt(3), 0.5 * a], 0),
        ('C6', [0.5 * a * sqrt(3), -0.5 * a], 0),
        ('C7', [a * sqrt(3), a], 0),
        ('C8', [a * sqrt(3), -a], 0),
        ('C9', [1.5 * a * sqrt(3), 0.5 * a], 0),
        ('C10',[1.5 * a * sqrt(3), -0.5 * a], 0),
        ('C11', [2*a * sqrt(3), a], 0),
        ('C12', [2*a * sqrt(3), -a], 0),
        ('C13', [2.5 * a * sqrt(3), 0.5 * a], 0),
        ('C14', [2.5 * a * sqrt(3), -0.5 * a], 0)
    )

    lat.add_hoppings(
        # inside the main cell
        ([0,  0], 'C1', 'C2', t),
        ([0,  0], 'C1', 'C3', t),
        ([0,  0], 'C3', 'C5', t),
        ([0, 0], 'C2', 'C4', t),
        ([0, 0], 'C4', 'C6', t),
        ([0, 0], 'C5', 'C6', t),
        ([0,  0], 'C5', 'C7', t),
        ([0,  0], 'C7', 'C9', t),
        ([0,  0], 'C6', 'C8', t),
        ([0, 0], 'C8', 'C10', t),
        ([0, 0], 'C9', 'C10', t),
        ([0, 0], 'C9', 'C11', t),
        ([0, 0], 'C11', 'C13', t),
        ([0, 0], 'C10', 'C12', t),
        ([0, 0], 'C12', 'C14', t),
        ([0, 0], 'C13', 'C14', t)

        # between neighboring cells
#        ([1, -1], 'A', 'B', t),

    )

    return lat
Esempio n. 21
0
def monolayer_graphene(a, t):

    lat = pb.Lattice(a1=[3 * a / 2, sqrt(3) * a / 2],
                     a2=[3 * a / 2, -sqrt(3) * a / 2])
    lat.add_sublattices(('a', [0, 0]), ('b', [a / 2, sqrt(3) * a / 2]))

    lat.add_hoppings(([0, 0], 'a', 'b', t), ([-1, 1], 'a', 'b', t),
                     ([-1, 0], 'a', 'b', t))

    return lat
Esempio n. 22
0
 def lattice():
     lat = pb.Lattice([1])
     lat.add_sublattices(("A", [0], [[1, 3j], [0, 2]]))
     lat.register_hopping_energies({
         "t22": [[0, 1], [2, 3]],
         "t11":
         1,  # incompatible hopping - it's never used so it shouldn't raise any errors
     })
     lat.add_hoppings(([1], "A", "A", "t22"))
     return lat
Esempio n. 23
0
    def lattice():
        lat = pb.Lattice([1, 0], [0, 1])

        lat.add_sublattices(("A", [0, 0], [0, 0, 0, 0]))
        lat.register_hopping_energies({
            "t44": [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11],
                    [12, 13, 14, 15]]
        })
        lat.add_hoppings(([1, 0], "A", "A", "t44"), ([0, 1], "A", "A", "t44"))
        return lat
Esempio n. 24
0
 def checkerboard_lattice(delta, t):
     lat = pb.Lattice(a1=[1, 0], a2=[0, 1])
     lat.add_sublattices(('A', [0, 0], -delta),
                         ('B', [1 / 2, 1 / 2], delta))
     lat.add_hoppings(
         ([0, 0], 'A', 'B', t),
         ([0, -1], 'A', 'B', t),
         ([-1, 0], 'A', 'B', t),
         ([-1, -1], 'A', 'B', t),
     )
     return lat
Esempio n. 25
0
def test_builder():
    """Builder pattern methods"""
    lattice = pb.Lattice([1, 0], [0, 1])

    copy = lattice.with_offset([0, 0.5])
    assert pytest.fuzzy_equal(copy.offset, [0, 0.5, 0])
    assert pytest.fuzzy_equal(lattice.offset, [0, 0, 0])

    copy = lattice.with_min_neighbors(5)
    assert copy.min_neighbors == 5
    assert lattice.min_neighbors == 1
    def hbn_monolayer():
        """Create a lattice of monolayer hBN """

        a = math.sqrt(3) * a_bn
        lat = pb.Lattice(a1=[a / 2, a / 2 * math.sqrt(3)],
                         a2=[-a / 2, a / 2 * math.sqrt(3)])
        lat.add_sublattices(('Br', [0, -a_bn, -c0], vb),
                            ('N', [0, 0, -c0], vn))

        lat.min_neighbors = 2  # no need for hoppings lattice is used only to generate coordinates
        return lat
Esempio n. 27
0
    def multi_orbital_lattice():
        lat = pb.Lattice([1, 0], [0, 1])

        tau_z = np.array([[1, 0], [0, -1]])
        tau_x = np.array([[0, 1], [1, 0]])
        lat.add_sublattices(("A", [0, 0], tau_z + 2 * tau_x),
                            ("B", [0, 0.1], 0.5), ("C", [0, 0.2], [1, 2, 3]))
        lat.add_hoppings(([0, -1], "A", "A", 3 * tau_z),
                         ([1, 0], "A", "A", 3 * tau_z),
                         ([0, 0], "B", "C", [[2, 3, 4]]))
        return lat
Esempio n. 28
0
def three_band_lattice():
    """MoS2 lattice using the three-band model"""
    # TODO: this is a proof of concept for `Lattice.add_hopping_matrices()`
    # TODO: still needs to be checked for accuracy

    # lattice constant
    a = 0.319  # [nm]
    # onsite energies
    eps0 = 1.046
    eps2 = 2.104
    # hoppings
    t0 = -0.184
    t1 = 0.401
    t2 = 0.507
    t11 = 0.218
    t12 = 0.338
    t22 = 0.057
    # convenient constant
    rt3 = math.sqrt(3)

    lat = pb.Lattice(a1=[a, 0], a2=[0.5 * a, 0.5 * rt3 * a])
    lat.add_sublattices(('s1', [0, 0], eps0), ('s2', [0, 0], eps2),
                        ('s3', [0, 0], eps2))

    r1 = [1, 0]
    r2 = [1, -1]
    r3 = [0, -1]

    t_mat1 = [[t0, t1, t2], [-t1, t11, t12], [t2, -t12, t22]]

    t_mat2 = [[t0, 0.5 * t1 - 0.5 * rt3 * t2, -0.5 * rt3 * t1 - 0.5 * t2],
              [
                  -0.5 * t1 - 0.5 * rt3 * t2, 0.25 * t11 + 0.75 * t22,
                  0.25 * rt3 * (t22 - t11) - t12
              ],
              [
                  0.5 * rt3 * t1 - 0.5 * t2, 0.25 * rt3 * (t22 - t11) + t12,
                  0.75 * t11 + 0.25 * t22
              ]]

    t_mat3 = [[t0, -0.5 * t1 + 0.5 * rt3 * t2, -0.5 * rt3 * t1 - 0.5 * t2],
              [
                  0.5 * t1 + 0.5 * rt3 * t2, 0.25 * t11 + 0.75 * t22,
                  0.25 * rt3 * (t11 - t22) + t12
              ],
              [
                  0.5 * rt3 * t1 - 0.5 * t2, -0.25 * rt3 * (t11 + t22) - t12,
                  0.75 * t11 + 0.25 * t22
              ]]

    lat.add_hopping_matrices([r1, t_mat1], [r2, t_mat2], [r3, t_mat3])
    lat.min_neighbors = 2
    return lat
Esempio n. 29
0
def test_add_hopping(capsys):
    lat = pb.Lattice([1, 0], [0, 1])
    lat.add_sublattices(("A", [0.0, 0.5]), ("B", [0.5, 0.0]))
    lat.add_hoppings(([0, 0], "A", "B", 1), ([1, -1], "A", "B", 1),
                     ([0, -1], "A", "B", 2))

    assert lat.nhop == 2
    assert lat.hoppings["__anonymous__0"].family_id == 0
    assert lat.hoppings["__anonymous__0"].energy == 1
    assert lat.hoppings["__anonymous__1"].family_id == 1
    assert lat.hoppings["__anonymous__1"].energy == 2

    lat.add_hoppings(([0, 1], "A", "B", 1))
    assert lat.nhop == 2

    lat.add_hoppings(([1, 0], "A", "B", 3))
    assert lat.nhop == 3

    with pytest.raises(RuntimeError) as excinfo:
        lat.add_one_hopping([0, 0], "A", "B", 1)
    assert "hopping already exists" in str(excinfo.value)

    with pytest.raises(RuntimeError) as excinfo:
        lat.add_one_hopping([0, 0], "A", "A", 1)
    assert "Don't define onsite energy here" in str(excinfo.value)

    with pytest.raises(IndexError) as excinfo:
        lat.add_one_hopping([0, 0], "C", "A", 1)
    assert "There is no sublattice named 'C'" in str(excinfo.value)

    lat.register_hopping_energies({"t_nn": 0.1, "t_nnn": 0.01})

    assert lat.nhop == 5
    assert lat.hoppings["t_nn"].energy == 0.1
    assert lat.hoppings["t_nnn"].energy == 0.01

    lat.add_one_hopping([0, 1], "A", "A", "t_nn")

    with pytest.raises(RuntimeError) as excinfo:
        lat.register_hopping_energies({"": 0.0})
    assert "Hopping name can't be blank" in str(excinfo.value)

    with pytest.raises(RuntimeError) as excinfo:
        lat.register_hopping_energies({"t_nn": 0.2})
    assert "Hopping 't_nn' already exists" in str(excinfo.value)

    with pytest.raises(IndexError) as excinfo:
        lat.add_one_hopping((0, 1), "A", "A", "tt")
    assert "There is no hopping named 'tt'" in str(excinfo.value)

    with pytest.warns(LoudDeprecationWarning):
        assert lat("t_nn") == "t_nn"
    capsys.readouterr()
Esempio n. 30
0
def monolayer_4band(num_hoppings=4):
    """Monolayer phosphorene lattice using the four-band model

    Parameters
    ----------
    num_hoppings : int
        Number of hopping terms to consider: from t2 to t5.
    """
    a = 0.222  # nm
    ax = 0.438  # nm
    ay = 0.332  # nm
    theta = 96.79 * (pi / 180)
    phi = 103.69 * (pi / 180)

    lat = pb.Lattice(a1=[ax, 0], a2=[0, ay])

    h = a * sin(phi - pi / 2)
    s = 0.5 * ax - a * cos(theta / 2)
    lat.add_sublattices(
        ('A', [-s / 2, -ay / 2, h], 0), ('B', [s / 2, -ay / 2, 0], 0),
        ('C', [-s / 2 + ax / 2, 0, 0], 0), ('D', [s / 2 + ax / 2, 0, h], 0))

    lat.register_hopping_energies({
        't1': -1.22,
        't2': 3.665,
        't3': -0.205,
        't4': -0.105,
        't5': -0.055
    })

    if num_hoppings < 2:
        raise RuntimeError("t1 and t2 must be included")
    elif num_hoppings > 5:
        raise RuntimeError("t5 is the last one")

    if num_hoppings >= 2:
        lat.add_hoppings(([-1, 0], 'A', 'D', 't1'), ([-1, -1], 'A', 'D', 't1'),
                         ([0, 0], 'B', 'C', 't1'), ([0, -1], 'B', 'C', 't1'))
        lat.add_hoppings(([0, 0], 'A', 'B', 't2'), ([0, 0], 'C', 'D', 't2'))
    if num_hoppings >= 3:
        lat.add_hoppings(([0, 0], 'A', 'D', 't3'), ([0, -1], 'A', 'D', 't3'),
                         ([1, 1], 'C', 'B', 't3'), ([1, 0], 'C', 'B', 't3'))
    if num_hoppings >= 4:
        lat.add_hoppings(([0, 0], 'A', 'C', 't4'), ([0, -1], 'A', 'C', 't4'),
                         ([-1, 0], 'A', 'C', 't4'), ([-1, -1], 'A', 'C', 't4'),
                         ([0, 0], 'B', 'D', 't4'), ([0, -1], 'B', 'D', 't4'),
                         ([-1, 0], 'B', 'D', 't4'), ([-1, -1], 'B', 'D', 't4'))
    if num_hoppings >= 5:
        lat.add_hoppings(([-1, 0], 'A', 'B', 't5'), ([-1, 0], 'C', 'D', 't5'))

    lat.min_neighbors = 2
    return lat