Пример #1
0
def test_inverse_transform():
    # Define family on square lattice
    s = spin_matrices(1 / 2)
    # Time reversal
    TR = PointGroupElement(
        np.eye(2), True, False,
        spin_rotation(2 * np.pi * np.array([0, 1 / 2, 0]), s))
    # Mirror symmetry
    Mx = PointGroupElement(
        np.array([[-1, 0], [0, 1]]), False, False,
        spin_rotation(2 * np.pi * np.array([1 / 2, 0, 0]), s))
    # Fourfold
    C4 = PointGroupElement(
        np.array([[0, 1], [-1, 0]]), False, False,
        spin_rotation(2 * np.pi * np.array([0, 0, 1 / 4]), s))
    symmetries = [TR, Mx, C4]

    # One site per unit cell
    norbs = OrderedDict([('A', 2)])
    # Hopping to a neighbouring atom one primitive lattice vector away
    hopping_vectors = [('A', 'A', [1, 0])]
    # Make family
    family = bloch_family(hopping_vectors, symmetries, norbs)
    fam = hamiltonian_from_family(family, tosympy=False)
    # Atomic coordinates within the unit cell
    atom_coords = [(0, 0)]
    lat_vecs = [(1, 0), (0, 1)]
    syst = model_to_builder(fam, norbs, lat_vecs, atom_coords)
    # Convert it back
    ham2 = builder_to_model(syst).tomodel(nsimplify=True)
    # Check that it's the same as the original
    assert fam == ham2

    # Check that the Hamiltonians are identical at random points in the Brillouin zone
    sysw = kwant.wraparound.wraparound(syst).finalized()
    H1 = sysw.hamiltonian_submatrix
    H2 = ham2.lambdify()
    H3 = fam.lambdify()
    coeffs = 0.5 + np.random.rand(3)
    for _ in range(20):
        kx, ky = 3 * np.pi * (np.random.rand(2) - 0.5)
        params = dict(c0=coeffs[0], c1=coeffs[1], c2=coeffs[2], k_x=kx, k_y=ky)
        assert allclose(H1(params=params), H2(**params))
        assert allclose(H1(params=params), H3(**params))
Пример #2
0
def test_graphene_to_kwant():

    norbs = OrderedDict([('A', 1), ('B', 1)
                         ])  # A and B atom per unit cell, one orbital each
    hopping_vectors = [('A', 'B', [1, 0])
                       ]  # Hopping between neighbouring A and B atoms
    # Atomic coordinates within the unit cell
    atom_coords = [(0, 0), (1, 0)]
    # We set the interatom distance to 1, so the lattice vectors have length sqrt(3)
    lat_vecs = [(3 / 2, np.sqrt(3) / 2), (3 / 2, -np.sqrt(3) / 2)]

    # Time reversal
    TR = PointGroupElement(sympy.eye(2), True, False, np.eye(2))
    # Chiral symmetry
    C = PointGroupElement(sympy.eye(2), False, True, np.array([[1, 0], [0,
                                                                        -1]]))
    # Atom A rotates into A, B into B.
    sphi = 2 * sympy.pi / 3
    RC3 = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],
                        [sympy.sin(sphi), sympy.cos(sphi)]])
    C3 = PointGroupElement(RC3, False, False, np.eye(2))

    # Generate graphene Hamiltonian in Kwant from qsymm
    symmetries = [C, TR, C3]
    # Generate using a family
    family = bloch_family(hopping_vectors, symmetries, norbs)
    syst_from_family = model_to_builder(family,
                                        norbs,
                                        lat_vecs,
                                        atom_coords,
                                        coeffs=None)
    # Generate using a single Model object
    g = sympy.Symbol('g', real=True)
    ham = hamiltonian_from_family(family, coeffs=[g])
    ham = Model(hamiltonian=ham, momenta=family[0].momenta)
    syst_from_model = model_to_builder(ham, norbs, lat_vecs, atom_coords)

    # Make the graphene Hamiltonian using kwant only
    atoms, orbs = zip(*[(atom, norb) for atom, norb in norbs.items()])
    # Make the kwant lattice
    lat = kwant.lattice.general(lat_vecs, atom_coords, norbs=orbs)
    # Store sublattices by name
    sublattices = {
        atom: sublat
        for atom, sublat in zip(atoms, lat.sublattices)
    }

    sym = kwant.TranslationalSymmetry(*lat_vecs)
    bulk = kwant.Builder(sym)

    bulk[[sublattices['A'](0, 0), sublattices['B'](0, 0)]] = 0

    def hop(site1, site2, c0):
        return c0

    bulk[lat.neighbors()] = hop

    fsyst_family = kwant.wraparound.wraparound(syst_from_family).finalized()
    fsyst_model = kwant.wraparound.wraparound(syst_from_model).finalized()
    fsyst_kwant = kwant.wraparound.wraparound(bulk).finalized()

    # Check that the energies are identical at random points in the Brillouin zone
    coeff = 0.5 + np.random.rand()
    for _ in range(20):
        kx, ky = 3 * np.pi * (np.random.rand(2) - 0.5)
        params = dict(c0=coeff, k_x=kx, k_y=ky)
        hamiltonian1 = fsyst_kwant.hamiltonian_submatrix(params=params,
                                                         sparse=False)
        hamiltonian2 = fsyst_family.hamiltonian_submatrix(params=params,
                                                          sparse=False)
        assert allclose(hamiltonian1, hamiltonian2)
        params = dict(g=coeff, k_x=kx, k_y=ky)
        hamiltonian3 = fsyst_model.hamiltonian_submatrix(params=params,
                                                         sparse=False)
        assert allclose(hamiltonian2, hamiltonian3)

    # Include random onsites as well
    one = sympy.numbers.One()
    onsites = [
        Model({one: np.array([[1, 0], [0, 0]])}, momenta=family[0].momenta),
        Model({one: np.array([[0, 0], [0, 1]])}, momenta=family[0].momenta)
    ]
    family = family + onsites
    syst_from_family = model_to_builder(family,
                                        norbs,
                                        lat_vecs,
                                        atom_coords,
                                        coeffs=None)
    gs = list(sympy.symbols('g0:%d' % 3, real=True))
    ham = hamiltonian_from_family(family, coeffs=gs)
    ham = Model(hamiltonian=ham, momenta=family[0].momenta)
    syst_from_model = model_to_builder(ham, norbs, lat_vecs, atom_coords)

    def onsite_A(site, c1):
        return c1

    def onsite_B(site, c2):
        return c2

    bulk[[sublattices['A'](0, 0)]] = onsite_A
    bulk[[sublattices['B'](0, 0)]] = onsite_B

    fsyst_family = kwant.wraparound.wraparound(syst_from_family).finalized()
    fsyst_model = kwant.wraparound.wraparound(syst_from_model).finalized()
    fsyst_kwant = kwant.wraparound.wraparound(bulk).finalized()

    # Check equivalence of the Hamiltonian at random points in the BZ
    coeffs = 0.5 + np.random.rand(3)
    for _ in range(20):
        kx, ky = 3 * np.pi * (np.random.rand(2) - 0.5)
        params = dict(c0=coeffs[0], c1=coeffs[1], c2=coeffs[2], k_x=kx, k_y=ky)
        hamiltonian1 = fsyst_kwant.hamiltonian_submatrix(params=params,
                                                         sparse=False)
        hamiltonian2 = fsyst_family.hamiltonian_submatrix(params=params,
                                                          sparse=False)
        assert allclose(hamiltonian1, hamiltonian2)
        params = dict(g0=coeffs[0], g1=coeffs[1], g2=coeffs[2], k_x=kx, k_y=ky)
        hamiltonian3 = fsyst_model.hamiltonian_submatrix(params=params,
                                                         sparse=False)
        assert allclose(hamiltonian2, hamiltonian3)