コード例 #1
0
ファイル: test_qsymm.py プロジェクト: NPopiel/MPhil
def test_real_space_basis():
    lat = kwant.lattice.honeycomb(norbs=[1, 1])
    sym = kwant.TranslationalSymmetry(lat.vec((1, 0)), lat.vec((0, 1)))
    bulk = kwant.Builder(sym)
    bulk[[lat.a(0, 0), lat.b(0, 0)]] = 0
    bulk[lat.neighbors()] = 1

    # Including real space symmetries
    symmetries = find_builder_symmetries(bulk)
    hex_group_2D = hexagonal()
    hex_group_2D = set(
        PointGroupElement(
            np.array(s.R).astype(float), s.conjugate, s.antisymmetry, None)
        for s in hex_group_2D)
    assert len(symmetries) == len(hex_group_2D)
    assert all([
        s1 in symmetries and s2 in hex_group_2D
        for s1, s2 in zip(hex_group_2D, symmetries)
    ])

    # Only onsite discrete symmetries
    symmetries = find_builder_symmetries(bulk, spatial_symmetries=False)
    onsites = [
        PointGroupElement(np.eye(2), True, False, None),  # T
        PointGroupElement(np.eye(2), True, True, None),  # P
        PointGroupElement(np.eye(2), False, True, None),  # C
        PointGroupElement(np.eye(2), False, False, None)
    ]  # I
    assert len(symmetries) == len(onsites)
    assert all([
        s1 in symmetries and s2 in onsites
        for s1, s2 in zip(onsites, symmetries)
    ])
コード例 #2
0
ファイル: test_qsymm.py プロジェクト: dnnagy/kwantproject
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))
コード例 #3
0
def _get_builder_symmetries(builder):
    """Extract the declared symmetries of a Kwant builder.

    Parameters
    ----------
    builder : `~kwant.builder.Builder`

    Returns
    -------
    builder_symmetries : dict
        Dictionary of the discrete symmetries that the builder has.
        The symmetries can be particle-hole, time-reversal or chiral,
        which are returned as qsymm.PointGroupElements, or
        a conservation law, which is returned as a
        qsymm.ContinuousGroupGenerators.
    """

    dim = len(np.array(builder.symmetry.periods))
    symmetry_names = [
        'time_reversal', 'particle_hole', 'chiral', 'conservation_law'
    ]
    builder_symmetries = {
        name: getattr(builder, name)
        for name in symmetry_names if getattr(builder, name) is not None
    }
    for name, symmetry in builder_symmetries.items():
        if name == 'time_reversal':
            builder_symmetries[name] = PointGroupElement(
                np.eye(dim), True, False, symmetry)
        elif name == 'particle_hole':
            builder_symmetries[name] = PointGroupElement(
                np.eye(dim), True, True, symmetry)
        elif name == 'chiral':
            builder_symmetries[name] = PointGroupElement(
                np.eye(dim), False, True, symmetry)
        elif name == 'conservation_law':
            builder_symmetries[name] = ContinuousGroupGenerator(R=None,
                                                                U=symmetry)
        else:
            raise ValueError("Invalid symmetry name.")
    return builder_symmetries
コード例 #4
0
ファイル: test_qsymm.py プロジェクト: dnnagy/kwantproject
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)