Exemple #1
0
def test_closest():
    rng = ensure_rng(10)
    for sym_dim in range(1, 4):
        for space_dim in range(sym_dim, 4):
            lat = kwant.lattice.general(ta.identity(space_dim))

            # Choose random periods.
            while True:
                periods = rng.randint(-10, 11, (sym_dim, space_dim))
                if np.linalg.det(np.dot(periods, periods.T)) > 0.1:
                    # Periods are reasonably linearly independent.
                    break
            syst = builder.Builder(kwant.TranslationalSymmetry(*periods))

            for tag in rng.randint(-30, 31, (4, space_dim)):
                # Add site and connect it to the others.
                old_sites = list(syst.sites())
                new_site = lat(*tag)
                syst[new_site] = None
                syst[((new_site, os) for os in old_sites)] = None

                # Test consistency with fill().
                for point in 200 * rng.random_sample((10, space_dim)) - 100:
                    closest = syst.closest(point)
                    dist = closest.pos - point
                    dist = ta.dot(dist, dist)
                    syst2 = builder.Builder()
                    syst2.fill(syst, inside_disc(point, 2 * dist), closest)
                    assert syst2.closest(point) == closest
                    for site in syst2.sites():
                        dd = site.pos - point
                        dd = ta.dot(dd, dd)
                        assert dd >= 0.999999 * dist
Exemple #2
0
 def act(self, element, a, b=None):
     m_part = self._get_site_family_data(a.family)[0]
     try:
         delta = ta.dot(m_part, element)
     except ValueError:
         msg = 'Expecting a {0}-tuple group element, but got `{1}` instead.'
         raise ValueError(msg.format(self.num_directions, element))
     if self.is_reversed:
         delta = -delta
     if b is None:
         return builder.Site(a.family, a.tag + delta, True)
     elif b.family == a.family:
         return (builder.Site(a.family, a.tag + delta, True),
                 builder.Site(b.family, b.tag + delta, True))
     else:
         m_part = self._get_site_family_data(b.family)[0]
         try:
             delta2 = ta.dot(m_part, element)
         except ValueError:
             msg = ('Expecting a {0}-tuple group element, '
                    'but got `{1}` instead.')
             raise ValueError(msg.format(self.num_directions, element))
         if self.is_reversed:
             delta2 = -delta2
         return (builder.Site(a.family, a.tag + delta, True),
                 builder.Site(b.family, b.tag + delta2, True))
Exemple #3
0
 def act(self, element, a, b=None):
     element = ta.array(element)
     if element.dtype is not int:
         raise ValueError("group element must be a tuple of integers")
     m_part = self._get_site_family_data(a.family)[0]
     try:
         delta = ta.dot(m_part, element)
     except ValueError:
         msg = 'Expecting a {0}-tuple group element, but got `{1}` instead.'
         raise ValueError(msg.format(self.num_directions, element))
     if self.is_reversed:
         delta = -delta
     if b is None:
         return builder.Site(a.family, a.tag + delta, True)
     elif b.family == a.family:
         return (builder.Site(a.family, a.tag + delta, True),
                 builder.Site(b.family, b.tag + delta, True))
     else:
         m_part = self._get_site_family_data(b.family)[0]
         try:
             delta2 = ta.dot(m_part, element)
         except ValueError:
             msg = ('Expecting a {0}-tuple group element, '
                    'but got `{1}` instead.')
             raise ValueError(msg.format(self.num_directions, element))
         if self.is_reversed:
             delta2 = -delta2
         return (builder.Site(a.family, a.tag + delta, True),
                 builder.Site(b.family, b.tag + delta2, True))
def test_dot():
    # Check acceptance of non-tinyarray arguments.
    assert ta.dot([1, 2], (3, 4)) == 11

    for dtype in dtypes:
        shape_pairs = [(1, 1), (2, 2), (3, 3),
                       (0, 0),
                       (0, (0, 1)), ((0, 1), 1),
                       (0, (0, 2)), ((0, 2), 2),
                       (1, (1, 2)), ((2, 1), 1),
                       (2, (2, 1)), ((1, 2), 2),
                       (2, (2, 3)), ((3, 2), 2),
                       ((1, 1), (1, 1)), ((2, 2), (2, 2)),
                       ((3, 3), (3, 3)), ((2, 3), (3, 2)), ((2, 1), (1, 2)),
                       ((2, 3, 4), (4, 3)),
                       ((2, 3, 4), 4),
                       ((3, 4), (2, 4, 3)),
                       (4, (2, 4, 3))]

        # We have to use almost_equal here because the result of numpy's dot
        # does not always agree to the last bit with a naive implementation.
        # (This is probably due to their usage of SSE or parallelization.)
        #
        # On my machine in summer 2012 with Python 2.7 and 3.2 the program
        #
        # import numpy as np
        # a = np.array([13.2, 14.3, 15.4, 16.5])
        # b = np.array([-5.0, -3.9, -2.8, -1.7])
        # r = np.dot(a, b)
        # rr = sum(x * y for x, y in zip(a, b))
        # print(r - rr)
        #
        # outputs 2.84217094304e-14.
        for sa, sb in shape_pairs:
            a = make(sa, dtype)
            b = make(sb, dtype) - 5
            assert_almost_equal(ta.dot(ta.array(a), ta.array(b)), np.dot(a, b),
                                13)

        shape_pairs = [((), 2), (2, ()),
                       (1, 2),
                       (1, (2, 2)), ((1, 1), 2),
                       ((2, 2), (3, 2)),
                       ((2, 3, 2), (4, 3)),
                       ((2, 3, 4), 3),
                       ((3, 3), (2, 4, 3)),
                       (3, (2, 4, 3))]
        for sa, sb in shape_pairs:
            a = make(sa, dtype)
            b = make(sb, dtype) - 5
            raises(ValueError, ta.dot, ta.array(a.tolist()),
                   ta.array(b.tolist()))
            raises(ValueError, ta.dot, ta.array(a), ta.array(b))
def test_dot():
    # Check acceptance of non-tinyarray arguments.
    assert_equal(ta.dot([1, 2], (3, 4)), 11)

    for dtype in dtypes:
        shape_pairs = [(1, 1), (2, 2), (3, 3),
                       (0, 0),
                       (0, (0, 1)), ((0, 1), 1),
                       (0, (0, 2)), ((0, 2), 2),
                       (1, (1, 2)), ((2, 1), 1),
                       (2, (2, 1)), ((1, 2), 2),
                       (2, (2, 3)), ((3, 2), 2),
                       ((1, 1), (1, 1)), ((2, 2), (2, 2)),
                       ((3, 3), (3, 3)), ((2, 3), (3, 2)), ((2, 1), (1, 2)),
                       ((2, 3, 4), (4, 3)),
                       ((2, 3, 4), 4),
                       ((3, 4), (2, 4, 3)),
                       (4, (2, 4, 3))]

        # We have to use almost_equal here because the result of numpy's dot
        # does not always agree to the last bit with a naive implementation.
        # (This is probably due to their usage of SSE or parallelization.)
        #
        # On my machine in summer 2012 with Python 2.7 and 3.2 the program
        #
        # import numpy as np
        # a = np.array([13.2, 14.3, 15.4, 16.5])
        # b = np.array([-5.0, -3.9, -2.8, -1.7])
        # r = np.dot(a, b)
        # rr = sum(x * y for x, y in zip(a, b))
        # print(r - rr)
        #
        # outputs 2.84217094304e-14.
        for sa, sb in shape_pairs:
            a = make(sa, dtype)
            b = make(sb, dtype) - 5
            assert_almost_equal(ta.dot(ta.array(a), ta.array(b)), np.dot(a, b),
                                13)

        shape_pairs = [((), 2), (2, ()),
                       (1, 2),
                       (1, (2, 2)), ((1, 1), 2),
                       ((2, 2), (3, 2)),
                       ((2, 3, 2), (4, 3)),
                       ((2, 3, 4), 3),
                       ((3, 3), (2, 4, 3)),
                       (3, (2, 4, 3))]
        for sa, sb in shape_pairs:
            a = make(sa, dtype)
            b = make(sb, dtype) - 5
            assert_raises(ValueError, ta.dot, ta.array(a.tolist()),
                          ta.array(b.tolist()))
            assert_raises(ValueError, ta.dot, ta.array(a), ta.array(b))
Exemple #6
0
    def __init__(self, prim_vecs, basis, name='', norbs=None):
        prim_vecs = ta.array(prim_vecs, float)
        if prim_vecs.ndim != 2:
            raise ValueError('`prim_vecs` must be a 2d array-like object.')
        dim = prim_vecs.shape[1]
        if name is None:
            name = ''
        if isinstance(name, str):
            name = [name + str(i) for i in range(len(basis))]

        if prim_vecs.shape[0] > dim:
            raise ValueError('Number of primitive vectors exceeds '
                             'the space dimensionality.')
        basis = ta.array(basis, float)
        if basis.ndim != 2:
            raise ValueError('`basis` must be a 2d array-like object.')
        if basis.shape[1] != dim:
            raise ValueError('Basis dimensionality does not match '
                             'the space dimensionality.')

        try:
            norbs = list(norbs)
            if len(norbs) != len(basis):
                raise ValueError('Length of `norbs` is not the same as '
                                 'the number of basis vectors')
        except TypeError:
            norbs = [norbs] * len(basis)

        self.sublattices = [Monatomic(prim_vecs, offset, sname, norb)
                            for offset, sname, norb in zip(basis, name, norbs)]
        # Sequence of primitive vectors of the lattice.
        self._prim_vecs = prim_vecs
        # Precalculation of auxiliary arrays for real space calculations.
        self.reduced_vecs, self.transf = lll.lll(prim_vecs)
        self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf)
Exemple #7
0
    def __init__(self, prim_vecs, basis, name='', norbs=None):
        prim_vecs = ta.array(prim_vecs, float)
        _check_prim_vecs(prim_vecs)

        dim = prim_vecs.shape[1]
        if name is None:
            name = ''
        if isinstance(name, str):
            name = [name + str(i) for i in range(len(basis))]

        basis = ta.array(basis, float)
        if basis.ndim != 2:
            raise ValueError('`basis` must be a 2d array-like object.')
        if basis.shape[1] != dim:
            raise ValueError('Basis dimensionality does not match '
                             'the space dimensionality.')

        try:
            norbs = list(norbs)
            if len(norbs) != len(basis):
                raise ValueError('Length of `norbs` is not the same as '
                                 'the number of basis vectors')
        except TypeError:
            norbs = [norbs] * len(basis)

        self.sublattices = [
            Monatomic(prim_vecs, offset, sname, norb)
            for offset, sname, norb in zip(basis, name, norbs)
        ]
        # Sequence of primitive vectors of the lattice.
        self._prim_vecs = prim_vecs
        # Precalculation of auxiliary arrays for real space calculations.
        self.reduced_vecs, self.transf = lll.lll(prim_vecs)
        self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf)
Exemple #8
0
    def which(self, site):
        det_x_inv_m_part, det_m = self._get_site_family_data(site.family)[-2:]
        if isinstance(site, system.Site):
            result = ta.dot(det_x_inv_m_part, site.tag) // det_m
        elif isinstance(site, system.SiteArray):
            result = np.dot(det_x_inv_m_part, site.tags.transpose()) // det_m
        else:
            raise TypeError("'site' must be a Site or a SiteArray")

        return -result if self.is_reversed else result
Exemple #9
0
    def subgroup(self, *generators):
        """Return the subgroup generated by a sequence of group elements.

        Parameters
        ----------
        *generators: sequence of int
            Each generator must have length ``self.num_directions``.
        """
        generators = ta.array(generators)
        if generators.dtype != int:
            raise ValueError('Generators must be sequences of integers.')
        return TranslationalSymmetry(*ta.dot(generators, self.periods))
Exemple #10
0
    def vec(self, int_vec):
        """
        Return the coordinates of a Bravais lattice vector in real space.

        Parameters
        ----------
        vec : integer vector

        Returns
        -------
        output : real vector
        """
        return ta.dot(int_vec, self._prim_vecs)
Exemple #11
0
    def vec(self, int_vec):
        """
        Return the coordinates of a Bravais lattice vector in real space.

        Parameters
        ----------
        vec : integer vector

        Returns
        -------
        output : real vector
        """
        return ta.dot(int_vec, self._prim_vecs)
Exemple #12
0
 def act(self, element, a, b=None):
     is_site = isinstance(a, system.Site)
     # Tinyarray for small arrays (single site) else numpy
     array_mod = ta if is_site else np
     element = array_mod.array(element)
     if not np.issubdtype(element.dtype, np.integer):
         raise ValueError("group element must be a tuple of integers")
     if (len(element.shape) == 2 and is_site):
         raise ValueError("must provide a single group element when "
                          "acting on single sites.")
     if (len(element.shape) == 1 and not is_site):
         # We can act on a whole SiteArray with a single group element
         # using numpy broadcasting.
         element = element.reshape(1, -1)
     m_part = self._get_site_family_data(a.family)[0]
     try:
         delta = array_mod.dot(m_part, element)
     except ValueError:
         msg = 'Expecting a {0}-tuple group element, but got `{1}` instead.'
         raise ValueError(msg.format(self.num_directions, element))
     if self.is_reversed:
         delta = -delta
     if b is None:
         if is_site:
             return system.Site(a.family, a.tag + delta, True)
         else:
             return system.SiteArray(a.family, a.tags + delta.transpose())
     elif b.family == a.family:
         if is_site:
             return (system.Site(a.family, a.tag + delta, True),
                     system.Site(b.family, b.tag + delta, True))
         else:
             return (system.SiteArray(a.family, a.tags + delta.transpose()),
                     system.SiteArray(b.family, b.tags + delta.transpose()))
     else:
         m_part = self._get_site_family_data(b.family)[0]
         try:
             delta2 = ta.dot(m_part, element)
         except ValueError:
             msg = ('Expecting a {0}-tuple group element, '
                    'but got `{1}` instead.')
             raise ValueError(msg.format(self.num_directions, element))
         if self.is_reversed:
             delta2 = -delta2
         if is_site:
             return (system.Site(a.family, a.tag + delta, True),
                     system.Site(b.family, b.tag + delta2, True))
         else:
             return (system.SiteArray(a.family, a.tags + delta.transpose()),
                     system.SiteArray(b.family,
                                      b.tags + delta2.transpose()))
Exemple #13
0
    def has_subgroup(self, other):
        if isinstance(other, system.NoSymmetry):
            return True
        elif not isinstance(other, TranslationalSymmetry):
            raise ValueError("Unknown symmetry type.")

        if other.periods.shape[1] != self.periods.shape[1]:
            return False  # Mismatch of spatial dimensionalities.

        inv = np.linalg.pinv(self.periods)
        factors = np.dot(other.periods, inv)
        # Absolute tolerance is correct in the following since we want an error
        # relative to the closest integer.
        return (np.allclose(factors, np.round(factors), rtol=0, atol=1e-8)
                and np.allclose(ta.dot(factors, self.periods), other.periods))
Exemple #14
0
        def f(*args, **kwargs):
            a, b, *args = args
            assert not (args and kwargs)
            sym_b = sym.act(elem, b)
            k = [kwargs[k] for k in momenta] if kwargs else args[mnp:]
            phase = cmath.exp(1j * ta.dot(elem, k))
            if not callable(val):
                v = val
            elif kwargs:
                if not takes_kwargs:
                    kwargs = {p: kwargs[p] for p in extra_params}
                v = val(a, sym_b, **kwargs)
            else:
                v = val(a, sym_b, *args[:mnp])

            return phase * v
Exemple #15
0
    def __init__(self, prim_vecs, offset=None, name='', norbs=None):
        prim_vecs = ta.array(prim_vecs, float)
        if prim_vecs.ndim != 2:
            raise ValueError('``prim_vecs`` must be a 2d array-like object.')
        dim = prim_vecs.shape[1]
        if name is None:
            name = ''
        if prim_vecs.shape[0] > dim:
            raise ValueError('Number of primitive vectors exceeds '
                             'the space dimensionality.')
        if offset is None:
            offset = ta.zeros(dim)
        else:
            offset = ta.array(offset, float)
            if offset.shape != (dim, ):
                raise ValueError('Dimensionality of offset does not match '
                                 'that of the space.')

        msg = '{0}({1}, {2}, {3}, {4})'
        cl = self.__module__ + '.' + self.__class__.__name__
        canonical_repr = msg.format(cl, short_array_repr(prim_vecs),
                                    short_array_repr(offset), repr(name),
                                    repr(norbs))
        super().__init__(canonical_repr, name, norbs)

        self.sublattices = [self]
        self._prim_vecs = prim_vecs
        self.inv_pv = ta.array(np.linalg.pinv(prim_vecs))
        self.offset = offset

        # Precalculation of auxiliary arrays for real space calculations.
        self.reduced_vecs, self.transf = lll.lll(prim_vecs)
        self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf)

        self.dim = dim
        self.lattice_dim = len(prim_vecs)

        if name != '':
            msg = "<Monatomic lattice {0}{1}>"
            orbs = ' with {0} orbitals'.format(
                self.norbs) if self.norbs else ''
            self.cached_str = msg.format(name, orbs)
        else:
            msg = "<unnamed Monatomic lattice, vectors {0}, origin [{1}]{2}>"
            orbs = ', with {0} orbitals'.format(norbs) if norbs else ''
            self.cached_str = msg.format(short_array_str(self._prim_vecs),
                                         short_array_str(self.offset), orbs)
Exemple #16
0
    def __init__(self, prim_vecs, offset=None, name='', norbs=None):
        prim_vecs = ta.array(prim_vecs, float)
        if prim_vecs.ndim != 2:
            raise ValueError('``prim_vecs`` must be a 2d array-like object.')
        dim = prim_vecs.shape[1]
        if name is None:
            name = ''
        if prim_vecs.shape[0] > dim:
            raise ValueError('Number of primitive vectors exceeds '
                             'the space dimensionality.')
        if offset is None:
            offset = ta.zeros(dim)
        else:
            offset = ta.array(offset, float)
            if offset.shape != (dim,):
                raise ValueError('Dimensionality of offset does not match '
                                 'that of the space.')

        msg = '{0}({1}, {2}, {3}, {4})'
        cl = self.__module__ + '.' + self.__class__.__name__
        canonical_repr = msg.format(cl, short_array_repr(prim_vecs),
                                    short_array_repr(offset),
                                    repr(name), repr(norbs))
        super().__init__(canonical_repr, name, norbs)

        self.sublattices = [self]
        self._prim_vecs = prim_vecs
        self.inv_pv = ta.array(np.linalg.pinv(prim_vecs))
        self.offset = offset

        # Precalculation of auxiliary arrays for real space calculations.
        self.reduced_vecs, self.transf = lll.lll(prim_vecs)
        self.voronoi = ta.dot(lll.voronoi(self.reduced_vecs), self.transf)

        self.dim = dim
        self.lattice_dim = len(prim_vecs)

        if name != '':
            msg = "<Monatomic lattice {0}{1}>"
            orbs = ' with {0} orbitals'.format(self.norbs) if self.norbs else ''
            self.cached_str = msg.format(name, orbs)
        else:
            msg = "<unnamed Monatomic lattice, vectors {0}, origin [{1}]{2}>"
            orbs = ', with {0} orbitals'.format(norbs) if norbs else ''
            self.cached_str = msg.format(short_array_str(self._prim_vecs),
                                         short_array_str(self.offset), orbs)
Exemple #17
0
def _mul(R1, R2):
    # Cached multiplication of spatial parts.
    if is_sympy_matrix(R1) and is_sympy_matrix(R2):
        # If spatial parts are sympy matrices, use cached multiplication.
        R = R1 * R2
    elif not (is_sympy_matrix(R1) or is_sympy_matrix(R2)):
        # If arrays, use dot
        R = ta.dot(R1, R2)
    elif ((is_sympy_matrix(R1) or is_sympy_matrix(R2)) and
        (isinstance(R1, ta.ndarray_int) or isinstance(R2, ta.ndarray_int))):
        # Multiplying sympy and integer tinyarray is ok, should result in sympy
        R = sympy.ImmutableMatrix(R1) * sympy.ImmutableMatrix(R2)
    else:
        raise ValueError("Mixing of sympy and floating point in the spatial part R is not allowed. "
                         "To avoid this error, make sure that all PointGroupElements are initialized "
                         "with either floating point arrays or sympy matrices as rotations. "
                         "Integer arrays are allowed in both cases.")
    R = _make_int(R)
    return R
Exemple #18
0
 def disk(site):
     pos = site.pos
     return ta.dot(pos, pos) < 13
Exemple #19
0
 def halfplane(site):
     return ta.dot(site.pos - (-1, 1), (-0.9, 0.63)) > 0
def vec_norm(vec):
    return np.sqrt(ta.dot(vec, vec))
Exemple #21
0
def test_fill():
    g = kwant.lattice.square()
    sym_x = kwant.TranslationalSymmetry((-1, 0))
    sym_xy = kwant.TranslationalSymmetry((-1, 0), (0, 1))

    template_1d = builder.Builder(sym_x)
    template_1d[g(0, 0)] = None
    template_1d[g.neighbors()] = None

    def line_200(site):
        return -100 <= site.pos[0] < 100

    ## Test that copying a builder by "fill" preserves everything.
    for sym, func in [
        (kwant.TranslationalSymmetry(*np.diag([3, 4, 5])), lambda pos: True),
        (builder.NoSymmetry(), lambda pos: ta.dot(pos, pos) < 17)
    ]:
        cubic = kwant.lattice.general(ta.identity(3))

        # Make a weird system.
        orig = kwant.Builder(sym)
        sites = cubic.shape(func, (0, 0, 0))
        for i, site in enumerate(orig.expand(sites)):
            if i % 7 == 0:
                continue
            orig[site] = i
        for i, hopp in enumerate(orig.expand(cubic.neighbors(1))):
            if i % 11 == 0:
                continue
            orig[hopp] = i * 1.2345
        for i, hopp in enumerate(orig.expand(cubic.neighbors(2))):
            if i % 13 == 0:
                continue
            orig[hopp] = i * 1j

        # Clone the original using fill.
        clone = kwant.Builder(sym)
        clone.fill(orig, lambda s: True, (0, 0, 0))

        # Verify that both are identical.
        assert set(clone.site_value_pairs()) == set(orig.site_value_pairs())
        assert (set(clone.hopping_value_pairs()) == set(
            orig.hopping_value_pairs()))

    ## Test for warning when "start" is out.
    target = builder.Builder()
    for start in [(-101, 0), (101, 0)]:
        with warns(RuntimeWarning):
            target.fill(template_1d, line_200, start)

    ## Test filling of infinite builder.
    for n in [1, 2, 4]:
        sym_n = kwant.TranslationalSymmetry((n, 0))
        for start in [g(0, 0), g(20, 0)]:
            target = builder.Builder(sym_n)
            sites = target.fill(template_1d,
                                lambda s: True,
                                start,
                                max_sites=10)
            assert len(sites) == n
            assert len(list(target.hoppings())) == n
            assert set(sym_n.to_fd(s) for s in sites) == set(target.sites())

    ## test max_sites
    target = builder.Builder()
    for max_sites in (-1, 0):
        with raises(ValueError):
            target.fill(template_1d,
                        lambda site: True,
                        g(0, 0),
                        max_sites=max_sites)
        assert len(list(target.sites())) == 0
    target = builder.Builder()
    with raises(RuntimeError):
        target.fill(template_1d, line_200, g(0, 0), max_sites=10)
    ## test filling
    target = builder.Builder()
    added_sites = target.fill(template_1d, line_200, g(0, 0))
    assert len(added_sites) == 200
    # raise warning if target already contains all starting sites
    with warns(RuntimeWarning):
        target.fill(template_1d, line_200, g(0, 0))

    ## test multiplying unit cell size in 1D
    n_cells = 10
    sym_nx = kwant.TranslationalSymmetry(*(sym_x.periods * n_cells))
    target = builder.Builder(sym_nx)
    target.fill(template_1d, lambda site: True, g(0, 0))

    should_be_syst = builder.Builder(sym_nx)
    should_be_syst[(g(i, 0) for i in range(n_cells))] = None
    should_be_syst[g.neighbors()] = None

    assert sorted(target.sites()) == sorted(should_be_syst.sites())
    assert sorted(target.hoppings()) == sorted(should_be_syst.hoppings())

    ## test multiplying unit cell size in 2D
    template_2d = builder.Builder(sym_xy)
    template_2d[g(0, 0)] = None
    template_2d[g.neighbors()] = None
    template_2d[builder.HoppingKind((2, 2), g)] = None

    nm_cells = (3, 5)
    sym_nmxy = kwant.TranslationalSymmetry(*(sym_xy.periods * nm_cells))
    target = builder.Builder(sym_nmxy)
    target.fill(template_2d, lambda site: True, g(0, 0))

    should_be_syst = builder.Builder(sym_nmxy)
    should_be_syst[(g(i, j) for i in range(10) for j in range(10))] = None
    should_be_syst[g.neighbors()] = None
    should_be_syst[builder.HoppingKind((2, 2), g)] = None

    assert sorted(target.sites()) == sorted(should_be_syst.sites())
    assert sorted(target.hoppings()) == sorted(should_be_syst.hoppings())

    ## test filling 0D builder with 2D builder
    def square_shape(site):
        x, y = site.tag
        return 0 <= x < 10 and 0 <= y < 10

    target = builder.Builder()
    target.fill(template_2d, square_shape, g(0, 0))

    should_be_syst = builder.Builder()
    should_be_syst[(g(i, j) for i in range(10) for j in range(10))] = None
    should_be_syst[g.neighbors()] = None
    should_be_syst[builder.HoppingKind((2, 2), g)] = None

    assert sorted(target.sites()) == sorted(should_be_syst.sites())
    assert sorted(target.hoppings()) == sorted(should_be_syst.hoppings())

    ## test that 'fill' respects the symmetry of the target builder
    lat = kwant.lattice.chain(a=1)
    template = builder.Builder(kwant.TranslationalSymmetry((-1, )))
    template[lat(0)] = 2
    template[lat.neighbors()] = -1

    target = builder.Builder(kwant.TranslationalSymmetry((-2, )))
    target[lat(0)] = None
    to_target_fd = target.symmetry.to_fd
    # Refuses to fill the target because target already contains the starting
    # site.
    with warns(RuntimeWarning):
        target.fill(template, lambda x: True, lat(0))

    # should only add a single site (and hopping)
    new_sites = target.fill(template, lambda x: True, lat(1))
    assert target[lat(0)] is None  # should not be overwritten by template
    assert target[lat(-1)] == template[lat(0)]
    assert len(new_sites) == 1
    assert to_target_fd(new_sites[0]) == to_target_fd(lat(-1))
Exemple #22
0
 def f(a, *args):
     phase = cmath.exp(1j * ta.dot(elem, args[mnp:]))
     v = val(a, sym.act(elem, a), *args[:mnp]) if callable(val) else val
     pv = phase * v
     return pv + herm_conj(pv)
Exemple #23
0
 def f(a, b, *args):
     phase = cmath.exp(1j * ta.dot(elem, args[mnp:]))
     v = val(a, sym.act(elem, b), *args[:mnp]) if callable(val) else val
     return phase * v
Exemple #24
0
 def make_lattice(a, theta):
     x = ta.dot(R(theta), (a, 0))
     y = ta.dot(R(theta), (0, a))
     return kwant.lattice.general([x, y], norbs=1)
Exemple #25
0
 def pos(self, tag):
     """Return the real-space position of the site with a given tag."""
     return ta.dot(tag, self._prim_vecs) + self.offset
Exemple #26
0
 def f(*args):
     a, b, *args = args
     phase = cmath.exp(1j * ta.dot(elem, args[mnp:]))
     v = val(a, sym.act(elem, b), *args[:mnp]) if callable(val) else val
     return phase * v
Exemple #27
0
 def which(self, site):
     det_x_inv_m_part, det_m = self._get_site_family_data(site.family)[-2:]
     result = ta.dot(det_x_inv_m_part, site.tag) // det_m
     return -result if self.is_reversed else result
Exemple #28
0
 def f(*args):
     a, *args = args
     phase = cmath.exp(1j * ta.dot(elem, args[mnp:]))
     v = val(a, sym.act(elem, a), *args[:mnp]) if callable(val) else val
     pv = phase * v
     return pv + herm_conj(pv)
Exemple #29
0
 def pos(self, tag):
     """Return the real-space position of the site with a given tag."""
     return ta.dot(tag, self._prim_vecs) + self.offset
Exemple #30
0
 def wire_shape(pos):
     rel_pos = pos - center
     projection = rel_pos - direction * ta.dot(direction, rel_pos)
     return sum(projection * projection) <= r_squared
Exemple #31
0
 def shape(site):
     d = site.pos - center
     dd = ta.dot(d, d)
     return dd <= rr
Exemple #32
0
 def make_lattice(a, salt='0'):
     theta_x = kwant.digest.uniform('x', salt=salt) * np.pi / 6
     theta_y = kwant.digest.uniform('y', salt=salt) * np.pi / 6
     x = ta.dot(R(theta_x), (a, 0))
     y = ta.dot(R(theta_y), (0, a))
     return kwant.lattice.general([x, y], norbs=1)
Exemple #33
0
def plot_2d_bands(syst, k_x=31, k_y=31, params=None,
                  mask_brillouin_zone=False, extend_bbox=0, file=None,
                  show=True, dpi=None, fig_size=None, ax=None):
    """Plot 2D band structure of a wrapped around system.

    This function is primarily useful for systems that have translational
    symmetry vectors that are non-orthogonal (e.g. graphene). This function
    will properly plot the band structure in an orthonormal basis in k-space,
    as opposed to in the basis of reciprocal lattice vectors (which would
    produce a "skewed" Brillouin zone).

    If your system has orthogonal lattice vectors, you are probably better
    off using `kwant.plotter.spectrum`.

    Parameters
    ----------
    syst : `kwant.system.FiniteSystem`
        A 2D system that was finalized from a Builder produced by
        `kwant.wraparound.wraparound`.  Note that this *must* be a finite
        system; so `kwant.wraparound.wraparound` should have been called with
        ``keep=None``.
    k_x, k_y : int or sequence of float, default: 31
        Either a number of sampling points, or a sequence of points at which
        the band structure is to be evaluated, in units of inverse length.
    params : dict, optional
        Dictionary of parameter names and their values, not including the
        momentum parameters.
    mask_brillouin_zone : bool, default: False
        If True, then the band structure will only be plotted over the first
        Brillouin zone. By default the band structure is plotted over a
        rectangular bounding box that contains the Brillouin zone.
    extend_bbox : float, default: 0
        Amount by which to extend the region over which the band structure is
        plotted, expressed as a proportion of the Brillouin zone bounding box
        length. i.e. ``extend_bbox=0.1`` will extend the region by 10% (in all
        directions).
    file : string or file object, optional
        The output file.  If None, output will be shown instead.
    show : bool, default: False
        Whether ``matplotlib.pyplot.show()`` is to be called, and the output is
        to be shown immediately.  Defaults to `True`.
    dpi : float, optional
        Number of pixels per inch.  If not set the ``matplotlib`` default is
        used.
    fig_size : tuple, optional
        Figure size `(width, height)` in inches.  If not set, the default
        ``matplotlib`` value is used.
    ax : ``matplotlib.axes.Axes`` instance, optional
        If `ax` is not `None`, no new figure is created, but the plot is done
        within the existing Axes `ax`. in this case, `file`, `show`, `dpi`
        and `fig_size` are ignored.

    Returns
    -------
    fig : matplotlib figure
        A figure with the output if `ax` is not set, else None.

    Notes
    -----
    This function produces plots where the units of momentum are inverse
    length. This is contrary to `kwant.plotter.bands`, where the units
    of momentum are inverse lattice constant.

    If the lattice vectors for the symmetry of ``syst`` are not orthogonal,
    then part of the plotted band structure will be outside the first Brillouin
    zone (inside the bounding box of the brillouin zone). Setting
    ``mask_brillouin_zone=True`` will cause the plot to be truncated outside of
    the first Brillouin zone.

    See Also
    --------
    kwant.plotter.spectrum
    """
    if not hasattr(syst, '_wrapped_symmetry'):
        raise TypeError("Expecting a system that was produced by "
                        "'kwant.wraparound.wraparound'.")
    if not isinstance(syst, system.FiniteSystem):
        msg = ("All symmetry directions must be wrapped around: specify "
               "'keep=None' when calling 'kwant.wraparound.wraparound'.")
        raise TypeError(msg)

    params = params or {}
    lat_ndim, space_ndim = syst._wrapped_symmetry.periods.shape

    if lat_ndim != 2:
        raise ValueError("Expected a system with a 2D translational symmetry.")
    if space_ndim != lat_ndim:
        raise ValueError("Lattice dimension must equal realspace dimension.")

    # columns of B are lattice vectors
    B = np.array(syst._wrapped_symmetry.periods).T
    # columns of A are reciprocal lattice vectors
    A = np.linalg.pinv(B).T

    ## calculate the bounding box for the 1st Brillouin zone

    # Get lattice points that neighbor the origin, in basis of lattice vectors
    reduced_vecs, transf = lll.lll(A.T)
    neighbors = ta.dot(lll.voronoi(reduced_vecs), transf)
    # Add the origin to these points.
    klat_points = np.concatenate(([[0] * lat_ndim], neighbors))
    # Transform to cartesian coordinates and rescale.
    # Will be used in 'outside_bz' function, later on.
    klat_points = 2 * np.pi * np.dot(klat_points, A.T)
    # Calculate the Voronoi cell vertices
    vor = scipy.spatial.Voronoi(klat_points)
    around_origin = vor.point_region[0]
    bz_vertices = vor.vertices[vor.regions[around_origin]]
    # extract bounding box
    k_max = np.max(np.abs(bz_vertices), axis=0)

    ## build grid along each axis, if needed
    ks = []
    for k, km in zip((k_x, k_y), k_max):
        k = np.array(k)
        if not k.shape:
            if extend_bbox:
                km += km * extend_bbox
            k = np.linspace(-km, km, k)
        ks.append(k)

    # TODO: It is very inefficient to call 'momentum_to_lattice' once for
    #       each point (for trivial Hamiltonians 60% of the time is spent
    #       doing this). We should instead transform the whole grid in one call.

    def momentum_to_lattice(k):
        k, residuals = scipy.linalg.lstsq(A, k)[:2]
        if np.any(abs(residuals) > 1e-7):
            raise RuntimeError("Requested momentum doesn't correspond"
                               " to any lattice momentum.")
        return k

    def ham(k_x, k_y=None, **params):
        # transform into the basis of reciprocal lattice vectors
        k = momentum_to_lattice([k_x] if k_y is None else [k_x, k_y])
        p = dict(zip(syst._momentum_names, k), **params)
        return syst.hamiltonian_submatrix(params=p, sparse=False)

    def outside_bz(k_x, k_y, **_):
        dm = scipy.spatial.distance_matrix(klat_points, [[k_x, k_y]])
        return np.argmin(dm) != 0  # is origin no closest 'klat_point' to 'k'?

    fig = plotter.spectrum(ham,
                           x=('k_x', ks[0]),
                           y=('k_y', ks[1]) if lat_ndim == 2 else None,
                           params=params,
                           mask=(outside_bz if mask_brillouin_zone else None),
                           file=file, show=show, dpi=dpi,
                           fig_size=fig_size, ax=ax)
    return fig
Exemple #34
0
 def which(self, site):
     det_x_inv_m_part, det_m = self._get_site_family_data(site.family)[-2:]
     result = ta.dot(det_x_inv_m_part, site.tag) // det_m
     return -result if self.is_reversed else result
Exemple #35
0
lat = kwant.lattice.triangular()
sys = kwant.Builder()
sys[lat.shape(circle, (0, 0))] = 0
sys[lat.neighbors()] = 1

lead_dirs = [lat.vec((-3, 1)), lat.vec((0, -1)), lat.vec((2, -1))]
for d in lead_dirs:
    lead = kwant.Builder(kwant.TranslationalSymmetry(d))
    lead[lat.wire((0, 0), 2.1)] = 0
    lead[lat.neighbors()] = 1
    sys.attach_lead(lead)

fig = kwant.plot(sys, show=False)
ax = pyplot.gca()
pyplot.text(-2, 5.5, 'scattering region', size=15)
pyplot.text(-10, -1, 'lead 0', color='red', size=15)
pyplot.text(-3, -7.7, 'lead 1', color='red', size=15)
pyplot.text(5.5, 0, 'lead 2', color='red', size=15)

for dir, offset in zip(lead_dirs, [10.5, 8, 8.6]):
    dir = dir / math.sqrt(ta.dot(dir, dir))
    for i in [0, 0.4, 0.8]:
        ax.add_artist(Circle(dir * (offset + i), 0.06, fc='k'))

pyplot.axis('off')
pyplot.xlim((-11, 9))
pyplot.ylim((-8, 6))
fig.tight_layout()
fig.set_size_inches(*(5, 3.75))
fig.savefig("tbsys.pdf")
Exemple #36
0
 def wire_shape(pos):
     rel_pos = pos - center
     projection = rel_pos - direction * ta.dot(direction, rel_pos)
     return sum(projection * projection) <= r_squared