Esempio n. 1
0
def test_site_state():
    @pb.site_state_modifier
    def mod(state):
        return np.ones_like(state)

    assert np.all(mod(zero))
    assert np.all(mod.apply(zero, one, one, one, one))

    capture = {}

    @pb.site_state_modifier
    def check_args(state, x, y, z, sub_id, sites):
        capture[sub_id] = [v.copy() for v in (state, x, y, z)]
        capture[sub_id].append(sites.argsort_nearest([0, graphene.a_cc / 2]))
        return state

    def assert_state(name, **kwargs):
        state, x, y, z, nearest = capture[name]
        assert state.shape == kwargs["shape"]
        assert pytest.fuzzy_equal(state, kwargs["state"])
        assert x.shape == kwargs["shape"]
        assert pytest.fuzzy_equal(x, kwargs["x"])
        assert pytest.fuzzy_equal(y, kwargs["y"])
        assert pytest.fuzzy_equal(z, kwargs["z"])
        assert np.all(nearest == kwargs["nearest"])

    model = build_model(check_args, pb.primitive(1, 2))
    assert model.hamiltonian.dtype == np.float32

    assert_state("A",
                 shape=(2, ),
                 state=[True] * 2,
                 nearest=[1, 0],
                 x=[-graphene.a / 2, 0],
                 y=[-2 * graphene.a_cc, -graphene.a_cc / 2],
                 z=[0, 0])
    assert_state("B",
                 shape=(2, ),
                 state=[True] * 2,
                 nearest=[1, 0],
                 x=[-graphene.a / 2, 0],
                 y=[-graphene.a_cc, graphene.a_cc / 2],
                 z=[0, 0])

    @pb.site_state_modifier
    def remove_site(state):
        state[0] = False
        return state

    model = build_model(remove_site, pb.primitive(2, 2))
    assert model.system.num_sites == 6

    @pb.site_state_modifier(min_neighbors=1)
    def remove_dangling(state, sub_id):
        state[sub_id == "A"] = False
        return state

    with pytest.raises(RuntimeError) as excinfo:
        build_model(remove_dangling, pb.primitive(3, 3))
    assert "0 sites" in str(excinfo.value)
Esempio n. 2
0
def test_multiorbital_hamiltonian():
    """For multi-orbital lattices the Hamiltonian size is larger than the number of sites"""
    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

    model = pb.Model(lattice(), pb.primitive(3))
    h = model.hamiltonian.toarray()

    assert model.system.num_sites == 3
    assert h.shape[0] == 6
    assert pytest.fuzzy_equal(h, h.T.conjugate())
    assert pytest.fuzzy_equal(h[:2, :2], h[-2:, -2:])
    assert pytest.fuzzy_equal(h[:2, :2], [[1, 3j], [-3j, 2]])
    assert pytest.fuzzy_equal(h[:2, 2:4], [[0, 1], [2, 3]])

    @pb.onsite_energy_modifier
    def onsite(energy, x, sub_id):
        return 3 * energy + sub_id.eye * 0 * x

    @pb.hopping_energy_modifier
    def hopping(energy):
        return 2 * energy

    model = pb.Model(lattice(), pb.primitive(3), onsite, hopping)
    h = model.hamiltonian.toarray()

    assert model.system.num_sites == 3
    assert h.shape[0] == 6
    assert pytest.fuzzy_equal(h, h.T.conjugate())
    assert pytest.fuzzy_equal(h[:2, :2], h[-2:, -2:])
    assert pytest.fuzzy_equal(h[:2, :2], [[3, 9j], [-9j, 6]])
    assert pytest.fuzzy_equal(h[:2, 2:4], [[0, 2], [4, 6]])
    assert pytest.fuzzy_equal(h[2:4, 4:6], [[0, 2], [4, 6]])

    def lattice_with_zero_diagonal():
        lat = pb.Lattice([1])
        lat.add_sublattices(("A", [0], [[0, 3j], [0, 0]]))
        return lat

    model = pb.Model(lattice_with_zero_diagonal(), pb.primitive(3))
    h = model.hamiltonian.toarray()

    assert model.system.num_sites == 3
    assert h.shape[0] == 6
    assert pytest.fuzzy_equal(h, h.T.conjugate())
    assert pytest.fuzzy_equal(h[:2, :2], h[-2:, -2:])
    assert pytest.fuzzy_equal(h[:2, :2], [[0, 3j], [-3j, 0]])
Esempio n. 3
0
def test_primitive():
    """The primitive shape can be positioned using the lattice origin"""
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    assert model.system.num_sites == 8
    assert np.isclose(model.system.x.min(), -1.5 * graphene.a, rtol=1e-3)
    assert np.isclose(model.system.y.min(), -2 * graphene.a_cc, rtol=1e-3)

    model = pb.Model(
        graphene.monolayer().with_offset(
            [0.5 * graphene.a, 0.5 * graphene.a_cc]), pb.primitive(2, 2))
    assert model.system.num_sites == 8
    assert np.isclose(model.system.x.min(), -graphene.a, rtol=1e-3)
    assert np.isclose(model.system.y.min(), -1.5 * graphene.a_cc, rtol=1e-3)
Esempio n. 4
0
def test_hopping_generator():
    """Generated next-nearest hoppings should produce the same result as the builtin lattice"""
    from scipy.spatial import cKDTree

    @pb.hopping_generator("tnn_test", energy=graphene.t_nn)
    def next_nearest(x, y, z):
        pos = np.stack([x, y, z], axis=1)
        dmin = graphene.a * 0.95
        dmax = graphene.a * 1.05
        kdtree = cKDTree(pos)
        coo = kdtree.sparse_distance_matrix(kdtree, dmax).tocoo()
        idx = coo.data > dmin
        return coo.row[idx], coo.col[idx]

    @pb.onsite_energy_modifier
    def onsite_offset(energy):
        return energy + 3 * graphene.t_nn

    model = pb.Model(graphene.monolayer(), next_nearest, onsite_offset,
                     graphene.hexagon_ac(1))
    expected = pb.Model(graphene.monolayer(2), graphene.hexagon_ac(1))
    assert pytest.fuzzy_equal(model.hamiltonian, expected.hamiltonian)

    @pb.hopping_generator("t_new", energy=1.0)
    def bad_generator():
        """Different array lengths"""
        return [0, 1, 2], [0, 1]

    model = pb.Model(graphene.monolayer(), pb.primitive(3, 3), bad_generator)
    with pytest.raises(RuntimeError) as excinfo:
        model.eval()
    assert "the number of `from` and `to` indices must be equal" in str(
        excinfo.value)
Esempio n. 5
0
def test_hopping_buffer():
    """The energy passed to hopping modifiers is buffered, but users should not be aware of it"""
    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

    capture = {}

    @pb.hopping_energy_modifier
    def check_buffer(energy, hop_id):
        capture.setdefault(hop_id, [])
        capture[hop_id] += [energy.copy()]
        energy[0] = 99
        return energy

    model = pb.Model(lattice(), pb.primitive(3000, 2), check_buffer)
    assert model.system.num_sites == 6000
    assert model.hamiltonian.shape[0] == 24000

    energies = capture["t44"]
    assert len(energies) >= 2
    assert energies[0].shape == (6250, 4, 4)
    for energy in energies:
        assert np.argwhere(energy == 99).size == 0
Esempio n. 6
0
def test_api():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system

    idx = system.num_sites // 2
    assert idx == system.find_nearest(system.xyz[idx])
    assert idx == system.find_nearest(system.xyz[idx], 'B')
    assert system.find_nearest([0, 0], 'A') != system.find_nearest([0, 0], 'B')

    with pytest.raises(IndexError) as excinfo:
        system.find_nearest([0, 0], 'invalid_sublattice')
    assert "There is no Site named" in str(excinfo.value)

    assert np.allclose(system.expanded_positions.x, system.positions.x)

    s = pb.Model(group6_tmd.monolayer_3band("MoS2"), pb.primitive(2, 2)).system
    assert s.expanded_positions.x.size == s.positions.x.size * 3
Esempio n. 7
0
def test_sites():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system

    sites = pb.system.Sites(system.positions, system.sublattices, system.lattice)
    idx = system.num_sites // 2
    assert idx == sites.find_nearest(system.xyz[idx])
    assert idx == sites.find_nearest(system.xyz[idx], system.sublattices[idx])
    assert sites.find_nearest([0, 0], 'A') != sites.find_nearest([0, 0], 'B')
Esempio n. 8
0
def test_sites():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system

    sites = pb.system.Sites(system.positions, system.sublattices)
    idx = system.num_sites // 2
    assert idx == sites.find_nearest(system.xyz[idx])
    assert idx == sites.find_nearest(system.xyz[idx], system.sublattices[idx])
    assert sites.find_nearest([0, 0], 'A') != sites.find_nearest([0, 0], 'B')
Esempio n. 9
0
def test_site_and_hopping_interaction():
    """Add a new row of sites and connect them just like the rest of the lattice"""
    d = 1.0
    v = 1.5
    t = 1.0

    def square_lattice():
        lat = pb.Lattice(a1=[d, 0], a2=[0, d])
        lat.add_sublattices(("A", [0, 0], v))
        lat.add_hoppings(([0, 1], "A", "A", t), ([1, 0], "A", "A", t))
        return lat

    @pb.site_generator(name="B", energy=v)
    def edge_sites(system):
        edge_atoms = system.count_neighbors() < 4
        x, y, z = (v[edge_atoms] for v in system.positions)

        top_edge_only = np.isclose(y, y.max())
        x, y, z = (v[top_edge_only] for v in (x, y, z))

        y += d
        return x, y, z

    @pb.hopping_generator(name="t_edge", energy=t)
    def edge_hoppings(system, y):
        new_sites = system.sub == "B"
        edge_atoms = np.logical_and(system.sub != "B",
                                    system.count_neighbors() < 4)
        top_edge_only = np.logical_and(edge_atoms,
                                       np.isclose(y, y[edge_atoms].max()))
        return new_sites, top_edge_only

    @pb.hopping_generator(name="t_edge2", energy=t)
    def edge_hoppings2(system):
        edge_idx = np.flatnonzero(system.sub == "B")
        to_idx = edge_idx[1:]
        from_idx = edge_idx[:-1]
        return to_idx, from_idx

    model = pb.Model(square_lattice(), pb.primitive(6, 4), edge_sites,
                     edge_hoppings, edge_hoppings2)
    expected = pb.Model(square_lattice(), pb.primitive(6, 5))
    assert pytest.fuzzy_equal(model.hamiltonian, expected.hamiltonian)
Esempio n. 10
0
def test_api():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system

    idx = system.num_sites // 2
    assert idx == system.find_nearest(system.xyz[idx])
    assert idx == system.find_nearest(system.xyz[idx], 'B')
    assert system.find_nearest([0, 0], 'A') != system.find_nearest([0, 0], 'B')

    with pytest.raises(IndexError) as excinfo:
        system.find_nearest([0, 0], 'invalid_sublattice')
    assert "There is no sublattice" in str(excinfo.value)
Esempio n. 11
0
def test_site_position():
    @pb.site_position_modifier
    def mod(x, y, z):
        return x + 1, y + 1, z + 1

    assert (one, ) * 3 == mod(zero, zero, zero)
    assert (one, ) * 3 == mod.apply(zero, zero, zero, one)

    capture = {}

    @pb.site_position_modifier
    def check_args(x, y, z, sub_id, sites):
        capture[sub_id] = [v.copy() for v in (x, y, z)]
        capture[sub_id].append(sites.argsort_nearest([0, graphene.a_cc / 2]))
        return x, y, z

    def assert_positions(name, **kwargs):
        x, y, z, nearest = capture[name]
        assert x.shape == kwargs["shape"]
        assert y.shape == kwargs["shape"]
        assert z.shape == kwargs["shape"]
        assert pytest.fuzzy_equal(x, kwargs["x"])
        assert pytest.fuzzy_equal(y, kwargs["y"])
        assert pytest.fuzzy_equal(z, kwargs["z"])
        assert np.all(nearest == kwargs["nearest"])

    model = build_model(check_args, pb.primitive(1, 2))
    assert model.hamiltonian.dtype == np.float32

    assert_positions("A",
                     shape=(2, ),
                     nearest=[1, 0],
                     x=[-graphene.a / 2, 0],
                     y=[-2 * graphene.a_cc, -graphene.a_cc / 2],
                     z=[0, 0])
    assert_positions("B",
                     shape=(2, ),
                     nearest=[1, 0],
                     x=[-graphene.a / 2, 0],
                     y=[-graphene.a_cc, graphene.a_cc / 2],
                     z=[0, 0])

    @pb.site_position_modifier
    def shift(x, y, z):
        return x + 1, y + 1, z + 1

    model = build_model(check_args, shift)
    assert pytest.fuzzy_equal(model.system.x, [1, 1])
    assert pytest.fuzzy_equal(model.system.y,
                              [1 - graphene.a_cc / 2, 1 + graphene.a_cc / 2])
    assert pytest.fuzzy_equal(model.system.z, [1, 1])
Esempio n. 12
0
def test_multiorbital_hamiltonian():
    """For multi-orbital lattices the Hamiltonian size is larger than the number of sites"""
    def lattice():
        lat = pb.Lattice([1])
        lat.add_sublattices(("A", [0], [[1, 3j], [0, 2]]))
        lat.register_hopping_energies({"t22": [[0, 1], [2, 3]]})
        lat.add_hoppings(([1], "A", "A", "t22"))
        return lat

    model = pb.Model(lattice(), pb.primitive(3))
    h = model.hamiltonian.todense()

    assert model.system.num_sites == 3
    assert h.shape[0] == 6
    assert pytest.fuzzy_equal(h, h.H)
    assert pytest.fuzzy_equal(h[:2, :2], h[-2:, -2:])
    assert pytest.fuzzy_equal(h[:2, :2], [[1, 3j], [-3j, 2]])
    assert pytest.fuzzy_equal(h[:2, 2:4], [[0, 1], [2, 3]])

    @pb.onsite_energy_modifier
    def onsite(energy):
        return 3 * energy

    @pb.hopping_energy_modifier
    def hopping(energy):
        return 2 * energy

    model = pb.Model(lattice(), pb.primitive(3), onsite, hopping)
    h = model.hamiltonian.todense()

    assert model.system.num_sites == 3
    assert h.shape[0] == 6
    assert pytest.fuzzy_equal(h, h.H)
    assert pytest.fuzzy_equal(h[:2, :2], h[-2:, -2:])
    assert pytest.fuzzy_equal(h[:2, :2], [[3, 9j], [-9j, 6]])
    assert pytest.fuzzy_equal(h[:2, 2:4], [[0, 2], [4, 6]])
    assert pytest.fuzzy_equal(h[2:4, 4:6], [[0, 2], [4, 6]])
Esempio n. 13
0
def test_wrapper_return():
    """Make sure the boost python wrapper return type conversion is working"""
    @pb.hopping_energy_modifier
    def mul(energy):
        """Returning a non-contiguous view will force the wrapper to create a copy"""
        energy = np.concatenate([energy, energy])
        energy *= 3
        return energy[::2]

    lattice = pb.Lattice([1, 0])
    lattice.add_sublattices(("A", [0, 0]), ("B", [0, 0]))
    lattice.add_one_hopping([0], "A", "B", 1.0)

    model = pb.Model(lattice, mul, pb.primitive(2))
    assert pytest.fuzzy_equal(model.hamiltonian.data, [3, 3, 3, 3])
Esempio n. 14
0
def test_api():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system

    idx = system.num_sites // 2
    assert idx == system.find_nearest(system.xyz[idx])
    assert idx == system.find_nearest(system.xyz[idx], system.sublattices[idx])
    assert system.find_nearest([0, 0], 'A') != system.find_nearest([0, 0], 'B')

    invalid_sublattice = 99
    with pytest.raises(KeyError) as excinfo:
        system.find_nearest([0, 0], invalid_sublattice)
    assert "There is no sublattice" in str(excinfo.value)

    with pytest.raises(KeyError) as excinfo:
        system.find_nearest([0, 0], 'invalid_sublattice')
    assert "There is no sublattice" in str(excinfo.value)
Esempio n. 15
0
def mymodel(dim=20, theta=0, B=0.0):
    # Pauli matrices
    S1 = array([[0, 1], [1, 0]])
    S2 = array([[0, -1j], [1j, 0]])
    S3 = array([[1, 0], [0, -1]])
    Tx = -S3  # Hopping in the x direction
    Ty = -S3  # Hopping in the y direction
    Tz = -S3 - 1j * S1  # Hopping in the z direction
    U = 5 * S3  # Onsite term
    # Building the lattice model
    lat = pb.Lattice(a1=[1, 0, 0], a2=[0, 1, 0], a3=[0, 0, 1])
    lat.add_sublattices(('A', [0, 0, 0], U))
    lat.add_hoppings(([1, 0, 0], 'A', 'A', Tx), ([0, 1, 0], 'A', 'A', Ty),
                     ([0, 0, 1], 'A', 'A', Tz))
    # generating the model object by combinig the lattice and the Peierls field
    model = pb.Model(lat, pb.primitive(a1=dim, a2=dim, a3=dim),
                     constant_magnetic_field(B=B, theta=theta))
    return model
Esempio n. 16
0
import pytest

import pybinding as pb
from pybinding.repository import graphene

models = {
    'graphene-monolayer': [graphene.monolayer(), graphene.hexagon_ac(1)],
    'graphene-monolayer-alt': [graphene.monolayer_alt(), pb.rectangle(1.6, 1.4)],
    'graphene-monolayer-4atom': [graphene.monolayer_4atom()],
    'graphene-monolayer-nn': [graphene.monolayer(2), pb.regular_polygon(6, 0.9)],
    'graphene-monolayer-periodic-1d': [graphene.monolayer(), pb.primitive(5, 5),
                                       pb.translational_symmetry(a1=True, a2=False)],
    'graphene-monolayer-periodic-1d-alt': [graphene.monolayer_4atom(), pb.rectangle(1),
                                           pb.translational_symmetry(a1=False, a2=0.6)],
    'graphene-monolayer-periodic-2d': [graphene.monolayer(), pb.primitive(a1=5, a2=5),
                                       pb.translational_symmetry(a1=1, a2=1)],
    'graphene-monolayer-4atom-periodic-2d': [graphene.monolayer_4atom(), pb.rectangle(1),
                                             pb.translational_symmetry(a1=0.6, a2=0.6)],
    'graphene-bilayer': [graphene.bilayer(), graphene.hexagon_ac(0.6)],
}


@pytest.fixture(scope='module', ids=list(models.keys()), params=models.values())
def model(request):
    return pb.Model(*request.param)


def test_api():
    model = pb.Model(graphene.monolayer(), pb.primitive(2, 2))
    system = model.system
Esempio n. 17
0
import pytest

import numpy as np
import pybinding as pb
from pybinding.repository import graphene, group6_tmd

models = {
    'graphene-monolayer': [graphene.monolayer(), graphene.hexagon_ac(1)],
    'graphene-monolayer-alt': [graphene.monolayer_alt(), pb.rectangle(1.6, 1.4)],
    'graphene-monolayer-4atom': [graphene.monolayer_4atom()],
    'graphene-monolayer-nn': [graphene.monolayer(2), pb.regular_polygon(6, 0.9)],
    'graphene-monolayer-periodic-1d': [graphene.monolayer(), pb.primitive(5, 5),
                                       pb.translational_symmetry(a1=True, a2=False)],
    'graphene-monolayer-periodic-1d-alt': [graphene.monolayer_4atom(), pb.rectangle(1),
                                           pb.translational_symmetry(a1=False, a2=0.6)],
    'graphene-monolayer-periodic-2d': [graphene.monolayer(), pb.primitive(a1=5, a2=5),
                                       pb.translational_symmetry(a1=1, a2=1)],
    'graphene-monolayer-4atom-periodic-2d': [graphene.monolayer_4atom(), pb.rectangle(1),
                                             pb.translational_symmetry(a1=0.6, a2=0.6)],
    'graphene-bilayer': [graphene.bilayer(), graphene.hexagon_ac(0.6)],
}


@pytest.fixture(scope='module', ids=list(models.keys()), params=models.values())
def model(request):
    return pb.Model(*request.param)


def test_pickle_round_trip(model):
    import pickle
    unpickled = pickle.loads(pickle.dumps(model.system))
Esempio n. 18
0
import numpy as np
import pybinding as pb
from pybinding.repository import graphene, group6_tmd

models = {
    'graphene-monolayer': [graphene.monolayer(),
                           graphene.hexagon_ac(1)],
    'graphene-monolayer-alt':
    [graphene.monolayer_alt(),
     pb.rectangle(1.6, 1.4)],
    'graphene-monolayer-4atom': [graphene.monolayer_4atom()],
    'graphene-monolayer-nn':
    [graphene.monolayer(2), pb.regular_polygon(6, 0.9)],
    'graphene-monolayer-periodic-1d': [
        graphene.monolayer(),
        pb.primitive(5, 5),
        pb.translational_symmetry(a1=True, a2=False)
    ],
    'graphene-monolayer-periodic-1d-alt': [
        graphene.monolayer_4atom(),
        pb.rectangle(1),
        pb.translational_symmetry(a1=False, a2=0.6)
    ],
    'graphene-monolayer-periodic-2d': [
        graphene.monolayer(),
        pb.primitive(a1=5, a2=5),
        pb.translational_symmetry(a1=1, a2=1)
    ],
    'graphene-monolayer-4atom-periodic-2d': [
        graphene.monolayer_4atom(),
        pb.rectangle(1),
Esempio n. 19
0
import pybinding as pb
import numpy as np
import matplotlib.pyplot as plt

d = 1

pb.pltutils.use_style()

lattice = pb.Lattice(a1=[d,0], a2=[d/2, d*np.math.sqrt(3)/2])
lattice.add_sublattices(("A", [0,0]))
lattice.add_hoppings(([0,1], "A", "A", 1), ([1,0], "A", "A", 1))

model = pb.Model(lattice, pb.primitive(a1=5, a2=5))
model.plot()
plt.show()
Esempio n. 20
0
def test_multiorbital_hoppings():
    """For multi-orbital lattices, hopping modifiers get `energy` as 3D array"""
    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.25, 0.0], tau_z + 2 * tau_x),
                            ("B", [0.0, 0.5], 0.5),
                            ("C", [0.25, 0.0], [1, 2, 3]))
        lat.register_hopping_energies({
            "t11": 1,
            "t1|2": 2,
            "t1|3": 3,
            "t22": 3 * tau_z,
            "t23": [[0, 1, 2], [3, 4, 5]],
            "t13": [[11, 12, 13]],
        })
        lat.add_hoppings(([1, 0], "B", "B", "t11"), ([0, 1], "B", "B", "t11"),
                         ([1, 1], "B", "B", "t1|2"),
                         ([1, -1], "B", "B", "t1|3"),
                         ([0, 1], "A", "A", "t22"), ([0, 0], "A", "C", "t23"),
                         ([0, 0], "B", "C", "t13"))
        return lat

    capture = {}

    @pb.hopping_energy_modifier
    def hopping(energy, hop_id, x1, y1, z1, x2, y2, z2):
        capture[hop_id] = [v.copy() for v in (energy, x1, y1, z1, x2, y2, z2)]
        return energy

    def assert_positions(name, **expected):
        _, x1, y1, z1, x2, y2, z2 = capture[name]

        assert pytest.fuzzy_equal(x1.squeeze(), expected["x1"])
        assert pytest.fuzzy_equal(y1.squeeze(), expected["y1"])
        assert pytest.fuzzy_equal(z1.squeeze(), expected["z1"])
        assert pytest.fuzzy_equal(x2.squeeze(), expected["x2"])
        assert pytest.fuzzy_equal(y2.squeeze(), expected["y2"])
        assert pytest.fuzzy_equal(z1.squeeze(), expected["z2"])

    def assert_hoppings(name, **expected):
        energy, *_ = capture[name]
        assert energy.shape == expected["shape"]
        for i in range(energy.shape[0]):
            assert pytest.fuzzy_equal(energy[i], expected["energy"])

    model = pb.Model(multi_orbital_lattice(), pb.primitive(2, 2), hopping)
    assert model.system.num_sites == 12
    assert model.hamiltonian.shape[0] == 24

    assert_positions("t11",
                     x1=[-1, -1, 0, -1],
                     y1=[-0.5, -0.5, -0.5, 0.5],
                     z1=[0, 0, 0, 0],
                     x2=[0, -1, 0, 0],
                     y2=[-0.5, 0.5, 0.5, 0.5],
                     z2=[0, 0, 0, 0])
    assert_positions("t22",
                     x1=[-1.25, -0.25],
                     y1=[-1, -1],
                     z1=[0, 0],
                     x2=[-1.25, -0.25],
                     y2=[0, 0],
                     z2=[0, 0])
    assert_positions("t23",
                     x1=[-1.25, -0.25, -1.25, -0.25],
                     y1=[-1, -1, 0, 0],
                     z1=[0, 0, 0, 0],
                     x2=[-0.75, 0.25, -0.75, 0.25],
                     y2=[-1, -1, 0, 0],
                     z2=[0, 0, 0, 0])
    assert_positions("t13",
                     x1=[-1, 0, -1, 0],
                     y1=[-0.5, -0.5, 0.5, 0.5],
                     z1=[0, 0, 0, 0],
                     x2=[-0.75, 0.25, -0.75, 0.25],
                     y2=[-1, -1, 0, 0],
                     z2=[0, 0, 0, 0])

    assert_hoppings("t11", shape=(4, ), energy=[1])
    assert_hoppings("t22", shape=(2, 2, 2), energy=[[3, 0], [0, -3]])
    assert_hoppings("t23", shape=(4, 2, 3), energy=[[0, 1, 2], [3, 4, 5]])
    assert_hoppings("t13", shape=(4, 1, 3), energy=[[11, 12, 13]])

    @pb.hopping_energy_modifier
    def hopping_mod(energy, hop_id, x1, y1, z1, x2, y2, z2):
        if hop_id == "t11":
            energy *= x1 * 0
        elif hop_id == "t1":
            energy *= 3
        elif hop_id == "t22":
            energy += [[0, 1], [1, 0]]
        elif hop_id == "t23":
            energy += [[1, 0, 0]]
        elif hop_id == "t13":
            energy *= 2

        capture[hop_id] = [v.copy() for v in (energy, x1, y1, z1, x2, y2, z2)]
        return energy

    model = pb.Model(multi_orbital_lattice(), pb.primitive(2, 2), hopping_mod)
    assert model.system.num_sites == 12
    assert model.hamiltonian.shape[0] == 24

    assert_hoppings("t11", shape=(4, ), energy=[0])
    assert_hoppings("t1|2", shape=(1, ), energy=[6])
    assert_hoppings("t1|3", shape=(1, ), energy=[9])
    assert_hoppings("t22", shape=(2, 2, 2), energy=[[3, 1], [1, -3]])
    assert_hoppings("t23", shape=(4, 2, 3), energy=[[1, 1, 2], [4, 4, 5]])
    assert_hoppings("t13", shape=(4, 1, 3), energy=[[22, 24, 26]])
Esempio n. 21
0
def test_multiorbital_hoppings():
    """For multi-orbital lattices, hopping modifiers get `energy` as 3D array"""
    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.25, 0.0], tau_z + 2 * tau_x),
                            ("B", [0.0, 0.5], 0.5),
                            ("C", [0.25, 0.0], [1, 2, 3]))
        lat.register_hopping_energies({
            "t11": 1,
            "t22": 3 * tau_z,
            "t23": [[0, 1, 2],
                    [3, 4, 5]],
            "t13": [[11, 12, 13]],
        })
        lat.add_hoppings(([1, 0], "B", "B", "t11"),
                         ([0, 1], "B", "B", "t11"),
                         ([0, 1], "A", "A", "t22"),
                         ([0, 0], "A", "C", "t23"),
                         ([0, 0], "B", "C", "t13"))
        return lat

    capture = {}

    @pb.hopping_energy_modifier
    def hopping(energy, hop_id, x1, y1, z1, x2, y2, z2):
        capture[hop_id] = [v.copy() for v in (energy, x1, y1, z1, x2, y2, z2)]
        return energy

    def assert_hoppings(name, **expected):
        energy, x1, y1, z1, x2, y2, z2 = capture[name]
        assert energy.shape == expected["shape"]

        expected_energy = np.array(expected["energy"])
        for index in np.ndindex(*expected_energy.shape):
            expected_slice = np.full(energy.shape[-1], expected_energy[index])
            assert pytest.fuzzy_equal(energy[index], expected_slice)

        assert pytest.fuzzy_equal(x1, expected["x1"])
        assert pytest.fuzzy_equal(y1, expected["y1"])
        assert pytest.fuzzy_equal(z1, expected["z1"])
        assert pytest.fuzzy_equal(x2, expected["x2"])
        assert pytest.fuzzy_equal(y2, expected["y2"])
        assert pytest.fuzzy_equal(z1, expected["z2"])

    model = pb.Model(multi_orbital_lattice(), pb.primitive(2, 2), hopping)
    assert model.system.num_sites == 12
    assert model.hamiltonian.shape[0] == 24

    assert_hoppings("t11", shape=(4,), energy=[1, 1, 1, 1],
                    x1=[-1, -1, 0, -1], y1=[-0.5, -0.5, -0.5, 0.5], z1=[0, 0, 0, 0],
                    x2=[0, -1, 0, 0], y2=[-0.5, 0.5, 0.5, 0.5], z2=[0, 0, 0, 0])

    assert_hoppings("t22", shape=(2, 2, 2), energy=[[3, 0],
                                                    [0, -3]],
                    x1=[-1.25, -0.25], y1=[-1, -1], z1=[0, 0],
                    x2=[-1.25, -0.25], y2=[0, 0], z2=[0, 0])

    assert_hoppings("t23", shape=(2, 3, 4), energy=[[0, 1, 2],
                                                    [3, 4, 5]],
                    x1=[-1.25, -0.25, -1.25, -0.25], y1=[-1, -1, 0, 0], z1=[0, 0, 0, 0],
                    x2=[-0.75, 0.25, -0.75, 0.25], y2=[-1, -1, 0, 0], z2=[0, 0, 0, 0])

    assert_hoppings("t13", shape=(1, 3, 4), energy=[[11, 12, 13]],
                    x1=[-1, 0, -1, 0], y1=[-0.5, -0.5, 0.5, 0.5], z1=[0, 0, 0, 0],
                    x2=[-0.75, 0.25, -0.75, 0.25], y2=[-1, -1, 0, 0], z2=[0, 0, 0, 0])