Example #1
0
    def orthogonalization_matrix(self, inverse=False):
        """orthogonalization matrix for crystal to cartesian coordinates
        not to be confused with the unit cell orthogonalization matrix, which is the transpose of this one

        Dunitz convention, Dunitz, 1979, p237"""

        a, b, c, al, be, ga = self.parameters

        al = radians(al)
        be = radians(be)
        ga = radians(ga)

        vol = self.volume

        if inverse:
            mat = ta.array([[
                old_div(1, a),
                old_div((-1 * cos(ga)), (a * sin(ga))),
                old_div((cos(ga) * cos(al) - cos(be)), (a * vol * sin(ga)))
            ],
                            [
                                0,
                                old_div(1, (b * sin(ga))),
                                old_div((cos(ga) * cos(be) - cos(al)),
                                        (b * vol * sin(ga)))
                            ], [0, 0, old_div((a * b * sin(ga)), (vol))]])
        else:
            mat = ta.array(
                [[a, b * cos(ga), c * cos(be)],
                 [0, b * sin(ga), c * (cos(al) - cos(be) * cos(ga)) / sin(ga)],
                 [0, 0, old_div(vol, (a * b * sin(ga)))]])

        return mat
def test_broadcasting():
    for sa in [(), 1, (1, 1, 1, 1), 2, (3, 2), (4, 3, 2), (5, 4, 3, 2)]:
        for sb in [(), 1, (1, 1), (4, 1, 1), 2, (1, 2), (3, 1), (1, 3, 2)]:
            a = make(sa, int)
            b = make(sb, int)
            assert ta.array(a.tolist()) + ta.array(b.tolist()) == a + b
            assert ta.array(a) + ta.array(b) == a + b
def test_iteration():
    for dtype in dtypes:
        raises(TypeError, tuple, ta.array(1, dtype))
        for shape in [0, 1, 2, 3, (1, 0), (2, 2), (17, 17),
                      (1, 1, 1), (2, 2, 1), (2, 0, 3)]:
            a = make(shape, dtype)
            assert tuple(ta.array(a)) == tuple(a)
Example #4
0
    def metric_tensor(self, inverse=False):
        """Returns the metric tensor

        http://reference.iucr.org/dictionary/Metric_tensor

        Dunitz, 1979, p227"""

        a, b, c, al, be, ga = self.parameters

        al = radians(al)
        be = radians(be)
        ga = radians(ga)

        vol = self.volume

        if inverse:
            m11 = (b * c * sin(al) / vol)**2
            m22 = (c * a * sin(be) / vol)**2
            m33 = (a * b * sin(ga) / vol)**2

            m12 = a * b * (old_div(c, vol))**2 * (cos(al) * cos(be) - cos(ga))
            m23 = b * c * (old_div(a, vol))**2 * (cos(be) * cos(ga) - cos(al))
            m13 = a * c * (old_div(b, vol))**2 * (cos(ga) * cos(al) - cos(be))

            mat = ta.array([[m11, m12, m13], [m12, m22, m23], [m13, m23, m33]])
        else:
            mat = ta.array([[a * a, a * b * cos(ga), a * c * cos(be)],
                            [a * b * cos(ga), b * b, b * c * cos(al)],
                            [a * c * cos(be), b * c * cos(al), c * c]])

        return mat
Example #5
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)
Example #6
0
def test_promotion():
    for dtypea in dtypes:
        for dtypeb in dtypes:
            a = make(3, dtypea)
            b = make(3, dtypeb)
            assert_equal(ta.array(a.tolist()) + ta.array(b.tolist()), a + b)
            assert_equal(ta.array(a) + ta.array(b), a + b)
Example #7
0
def test_broadcasting():
    for sa in [(), 1, (1, 1, 1, 1), 2, (3, 2), (4, 3, 2), (5, 4, 3, 2)]:
        for sb in [(), 1, (1, 1), (4, 1, 1), 2, (1, 2), (3, 1), (1, 3, 2)]:
            a = make(sa, int)
            b = make(sb, int)
            assert_equal(ta.array(a.tolist()) + ta.array(b.tolist()), a + b)
            assert_equal(ta.array(a) + ta.array(b), a + b)
Example #8
0
def angle_pos(atom_pos, bond_pos, bond_length, degrees, coplanar=None):
    if coplanar is not None and len(coplanar) > 0:
        # may have one or two coplanar positions specified,
        # if two, compute both resultant positions and average
        # (the up vector has to be negated for the second one)
        xforms = []
        if len(coplanar) > 2:
            raise ValueError("More than 2 coplanar positions specified!")
        for cpos in coplanar:
            up = cpos - atom_pos
            if xforms:
                up = tinyarray.negative(up)
            # lookAt puts ref point opposite that of zAlign, so
            # also rotate 180 degrees around y axis
            xform = rotation(
                (0.0, 1.0, 0.0), 180.0) * look_at(atom_pos, bond_pos, up)
            xforms.append(xform)

    else:
        xforms = [z_align(atom_pos, bond_pos)]
    points = []
    for xform in xforms:
        radians = pi * degrees / 180.0
        angle = tinyarray.array(
            [0.0, bond_length * sin(radians), bond_length * cos(radians)])
        points.append(xform.inverse() * angle)

    if len(points) > 1:
        midpoint = points[0] + (points[1] - points[0]) / 2.0
        v = midpoint - atom_pos
        v = v * bond_length / norm(v)
        return atom_pos + v

    return tinyarray.array(points[0])
Example #9
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)
Example #10
0
def test_promotion():
    for dtypea in dtypes:
        for dtypeb in dtypes:
            a = make(3, dtypea)
            b = make(3, dtypeb)
            assert ta.array(a.tolist()) + ta.array(b.tolist()) == a + b
            assert ta.array(a) + ta.array(b) == a + b
Example #11
0
def make_system(W, theta,
                kz):  #make a 2D cut of the original system with fixed kz
    syst = kwant.Builder()
    lat = kwant.lattice.square(a=1, name='u', norbs=2)
    sigma_x = ta.array([[0, 1], [1, 0]])
    sigma_y = ta.array([[0, -1j], [1j, 0]])
    sigma_z = ta.array([[1, 0], [0, -1]])

    x, y = W, W
    M = 0.7  #same parameter as before
    k0 = 1

    for i in range(x):
        for j in range(y):
            syst[lat(i, j)] = M * (k0**2 - 4 - kz**2) * sigma_z + (
                -sin(theta) / sqrt(2) * sin(kz) -
                1j * sin(theta) / sqrt(2) * sin(kz)) * sigma_x

            if i > 0:
                syst[lat(i, j), lat(i - 1, j)] = 1j / 2 * (cos(
                    theta / 2)**2) * sigma_x + 1j / 2 * (sin(
                        theta / 2)**2) * sigma_y + M * sigma_z

            if j > 0:
                syst[lat(i, j), lat(i, j - 1)] = 1j / 2 * (cos(
                    theta / 2)**2) * sigma_y + 1j / 2 * (sin(
                        theta / 2)**2) * sigma_x + M * sigma_z

    syst1 = syst.finalized()
    return syst1
Example #12
0
 def __init__(self, dim=1):
     self.__dim = dim
     self.__s = [
         ta.array([[1, 0], [0, 1]]),
         ta.array([[0, 1], [1, 0]]),
         ta.array([[0, -1j], [1j, 0]]),
         ta.array([[1, 0], [0, -1]])
     ]
Example #13
0
def test_unary_operators():
    ops = operator
    for op in [ops.neg, ops.pos, ops.abs]:
        for dtype in dtypes:
            for shape in [(), 1, 3, (3, 2)]:
                a = make(shape, dtype)
                assert_equal(op(ta.array(a.tolist())), op(a))
                assert_equal(op(ta.array(a)), op(a))
Example #14
0
def test_unary_operators():
    ops = operator
    for op in [ops.neg, ops.pos, ops.abs]:
        for dtype in dtypes:
            for shape in [(), 1, 3, (3, 2)]:
                a = make(shape, dtype)
                assert op(ta.array(a.tolist())) == op(a)
                assert op(ta.array(a)) == op(a)
Example #15
0
def _inv_int(A):
    """Invert an integer square matrix A. """
    _A = ta.array(A, int)
    if A == np.empty((0, 0)):
        return A
    if _A != A or abs(la.det(A)) != 1:
        raise ValueError('Input needs to be an invertible integer matrix')
    return ta.array(np.round(la.inv(_A)), int)
Example #16
0
def _inv(R):
    if isinstance(R, ta.ndarray_int):
        Rinv = ta.array(_inv_int(R), int)
    elif isinstance(R, ta.ndarray_float):
        Rinv = ta.array(la.inv(R))
    elif is_sympy_matrix(R):
        Rinv = R**(-1)
    else:
        raise ValueError('Invalid rotation matrix.')
    return Rinv
Example #17
0
def test_comparison():
    ops = operator
    for op in [ops.ge, ops.gt, ops.le, ops.lt, ops.eq, ops.ne]:
        for dtype in (int, float, complex):
            for left, right in it.product((np.zeros, np.ones), repeat=2):
                for shape in [(), (1,), (2,), (2, 2), (2, 2, 2), (2, 3)]:
                    a = left(shape, dtype)
                    b = right(shape, dtype)
                    if dtype is complex and op not in [ops.eq, ops.ne]:
                        # unorderable types
                        raises(TypeError, op, ta.array(a), ta.array(b))
                    else:
                        # passing the same object
                        same = ta.array(a)
                        assert op(same, same) == op(a.tolist(), a.tolist())
                        # passing different objects, but equal
                        assert (op(ta.array(a), ta.array(a)) ==
                                op(a.tolist(), a.tolist()))
                        # passing different objects, not equal
                        assert (op(ta.array(a), ta.array(b)) ==
                                op(a.tolist(), b.tolist()))
                # test different ndims and different shapes
                for shp1, shp2 in [((2,), (2, 2)), ((2, 2), (2, 3))]:
                    a = left(shp1, dtype)
                    b = right(shp2, dtype)
                    if op not in (ops.eq, ops.ne):
                        # unorderable types
                        raises(TypeError, op, ta.array(a), ta.array(b))
def test_value_types(k=(-1.1, 0.5), E=2, t=1):
    sym_extents = [1, 2, 3]
    lattices = [kwant.lattice.honeycomb(), kwant.lattice.square()]
    lat_syms = [(lat,
                 kwant.TranslationalSymmetry(lat.vec((n, 0)), lat.vec((0, n))))
                for n, lat in itertools.product(sym_extents, lattices)]
    for lat, sym in lat_syms:
        syst = wraparound(_simple_syst(lat, E, t, sym)).finalized()
        H = syst.hamiltonian_submatrix(k, sparse=False)
        for E1, t1 in [(float(E), float(t)),
                       (np.array([[E]], float), np.array([[t]], float)),
                       (ta.array([[E]], float), ta.array([[t]], float))]:
            # test when Hamiltonian values do not take any extra parameters
            # (only 'k' needs to be passed)
            for E2 in [E1, lambda a: E1]:
                for t2 in [t1, lambda a, b: t1]:
                    syst = wraparound(_simple_syst(lat, E2, t2,
                                                   sym)).finalized()
                    H_alt = syst.hamiltonian_submatrix(k, sparse=False)
                    np.testing.assert_equal(H_alt, H)
            # test when Hamiltonian value functions take extra parameters and
            # have compatible signatures (can be passed with 'args')
            onsites = [
                lambda a, E, t: E,
                lambda a, E, *args: E,
                lambda a, *args: args[0],
            ]
            hoppings = [
                lambda a, b, E, t: t,
                lambda a, b, E, *args: args[0],
                lambda a, b, *args: args[1],
            ]
            args = (E1, t1) + k
            for E2, t2 in itertools.product(onsites, hoppings):
                syst = wraparound(_simple_syst(lat, E2, t2, sym)).finalized()
                H_alt = syst.hamiltonian_submatrix(args, sparse=False)
                np.testing.assert_equal(H_alt, H)
            # test when hamiltonian value functions take extra parameters and
            # have incompatible signaures (must be passed with 'params')
            onsites = [
                lambda a, E: E,
                lambda a, **kwargs: kwargs['E'],
                lambda a, *, E: E,
            ]
            hoppings = [
                lambda a, b, t: t,
                lambda a, b, **kwargs: kwargs['t'],
                lambda a, b, *, t: t,
            ]
            params = dict(E=E1, t=t1, **dict(zip(['k_x', 'k_y'], k)))
            for E2, t2 in itertools.product(onsites, hoppings):
                syst = wraparound(_simple_syst(lat, E2, t2, sym)).finalized()
                H_alt = syst.hamiltonian_submatrix(params=params, sparse=False)
                np.testing.assert_equal(H_alt, H)
Example #19
0
def _eq(R1, R2):
    if type(R1) != type(R2):
        R1 = ta.array(np.array(R1).astype(float), float)
        R2 = ta.array(np.array(R2).astype(float), float)
    if isinstance(R1, ta.ndarray_float):
        # Check equality with allclose if floating point
        R_eq = allclose(R1, R2)
    else:
        # If exact use exact equality
        R_eq = (R1 == R2)
    return R_eq
Example #20
0
def test_value_types(k=(-1.1, 0.5), E=0, t=1):
    for lat in [kwant.lattice.honeycomb(), kwant.lattice.square()]:
        syst = wraparound(_simple_syst(lat, E, t)).finalized()
        H = syst.hamiltonian_submatrix(k, sparse=False)
        for E1, t1 in [(float(E), float(t)),
                       (np.array([[E]], float), np.array([[1]], float)),
                       (ta.array([[E]], float), ta.array([[1]], float))]:
            for E2 in [E1, lambda a: E1]:
                for t2 in [t1, lambda a, b: t1]:
                    syst = wraparound(_simple_syst(lat, E2, t2)).finalized()
                    H_alt = syst.hamiltonian_submatrix(k, sparse=False)
                    np.testing.assert_equal(H_alt, H)
def test_value_types(k=(-1.1, 0.5), E=0, t=1):
    for lat in [kwant.lattice.honeycomb(), kwant.lattice.square()]:
        syst = wraparound(_simple_syst(lat, E, t)).finalized()
        H = syst.hamiltonian_submatrix(k, sparse=False)
        for E1, t1 in [(float(E), float(t)),
                       (np.array([[E]], float), np.array([[1]], float)),
                       (ta.array([[E]], float), ta.array([[1]], float))]:
            for E2 in [E1, lambda a: E1]:
                for t2 in [t1, lambda a, b: t1]:
                    syst = wraparound(_simple_syst(lat, E2, t2)).finalized()
                    H_alt = syst.hamiltonian_submatrix(k, sparse=False)
                    np.testing.assert_equal(H_alt, H)
Example #22
0
def make_system_step1(q):
    L1 = tinyarray.array((3 / sqrt(3), 0))
    SC1 = L1
    L2 = tinyarray.array((0, q))
    SC2 = L2

    syst = kwant.Builder()

    ##primitive graphene,dispersion without B:
    #    for i in range(1):
    #    #for i in range(q):
    #      for j in range(1):
    #        # On-site Hamiltonian
    #        syst[a(i, j)] =0
    #        syst[b(i, j)] =0
    #    syst[a(0,0),b(0,0)]=-1-np.exp(1j*k1)-np.exp(1j*k2)
    #
    def rectangle(pos):
        xR, yR = pos
        #print(pos)
        #sys.exit()
        # xR,yR=list(x*v1+y*v2)
        #return (xR <=Lx2)&(yR<=Ly2)&(xR >= Lx1)&(yR>=Ly1)
        return (-cos_30 / 3 - 0.00001 <= xR < 3 / sqrt(3) * Nx -
                1 / sqrt(3)) & (0 - 0.0001 <= yR <= Ny * q - 0.0001)

    syst[graphene.shape(rectangle, (0, 0))] = 0

    syst0 = syst.finalized()
    N_ToT = syst0.graph.num_nodes
    print(N_ToT)

    def neighbors():
        nns = [[] for i in range(N_ToT)]
        for ni in range(N_ToT):
            #print(ni)
            ri = syst0.sites[ni].pos

            for nj in range(N_ToT):
                rj = syst0.sites[nj].pos

                for n1 in range(-1, 2):
                    for n2 in range(-1, 2):
                        rjn = rj + (n1 * SC1 + n2 * SC2)
                        ss = ri - rjn
                        dis = sqrt(np.dot(ss, ss))
                        if (abs(dis - 1 / sqrt(3)) < 10**-5):
                            if not ((n1 == 0) & (n2 == 0) & (nj == ni)):
                                nns[ni].append((nj, n1, n2))
        return nns

    nns = neighbors()
    return nns, syst, syst0
Example #23
0
    def __lt__(self, other):
        # Sort group elements:
        # First by conjugate and a, then R = identity, then the rest
        # lexicographically
        Rs = ta.array(np.array(self.R).astype(float), float)
        Ro = ta.array(np.array(other.R).astype(float), float)
        identity = ta.array(np.eye(Rs.shape[0], dtype=int))

        if not (self.conjugate, self.antisymmetry) == (other.conjugate, other.antisymmetry):
            return (self.conjugate, self.antisymmetry) < (other.conjugate, other.antisymmetry)
        elif (Rs == identity) ^ (Ro == identity):
            return Rs == identity
        else:
            return Rs < Ro
Example #24
0
def test_pickle():
    import pickle

    for dtype in dtypes:
        for shape in some_shapes:
            a = ta.array(make(shape, dtype))
            assert pickle.loads(pickle.dumps(a)) == a
Example #25
0
def test_iteration():
    for dtype in dtypes:
        assert_raises(TypeError, tuple, ta.array(1, dtype))
        for shape in [0, 1, 2, 3, (1, 0), (2, 2), (17, 17),
                      (1, 1, 1), (2, 2, 1), (2, 0, 3)]:
            a = make(shape, dtype)
            assert_equal(tuple(a), a)
Example #26
0
def test_hash_equality():
    random.seed(123)
    maxint = sys.maxsize + 1    # will be typically 2**31 or 2**63
    int_bits = 63 if maxint > 2**32 else 31

    special = [float('nan'), float('inf'), float('-inf'),
               0, -1, -1.0, -1 + 0j,
               303, -312424, -0.3, 1.7, 0.4j, -12.3j, 1 - 12.3j, 1.3 - 12.3j,
               (), (-1,), (2,),
               (0, 0), (-1, -1), (-5, 7), (3, -1, 0),
               ((0, 1), (2, 3)), (((-1,),),)]
    powers = [sign * (2**e + a) for sign in [1, -1] for a in [-1, 0, 1]
              for e in range(int_bits)]
    powers.extend([2**int_bits - 1, -2**int_bits, -2**int_bits + 1])
    small_random_ints = (random.randrange(-2**16, 2**16) for i in range(1000))
    large_random_ints = (random.randrange(-maxint, maxint) for i in range(1000))
    small_random_floats = (random.gauss(0, 1) for i in range(1000))
    large_random_floats = (random.gauss(0, 1e100) for i in range(1000))

    for collection in [special, powers,
                       small_random_ints, large_random_ints,
                       small_random_floats, large_random_floats]:
        for thing in collection:
            arr = ta.array(thing)
            if thing == thing:
                assert arr == thing
                assert not (arr != thing)
            assert_equal(hash(arr), hash(thing), repr(thing))
Example #27
0
 def subgroup(self, *generators):
     generators = ta.array(generators)
     assert generators.shape == (1, 1)
     if generators.dtype != int:
         raise ValueError('Generators must be sequences of integers.')
     g = generators[0, 0]
     return VerySimpleSymmetry(g * self.period)
Example #28
0
def test_other_scalar_types():
    types = [np.int16, np.int32, np.int64,
             np.float16, np.float32, np.float64]
    for t in types:
        a = t(123.456)
        assert_equal(ta.array(a), np.array(a))
        assert_equal(ta.matrix(a), np.matrix(a))
Example #29
0
def test_pickle():
    import pickle

    for dtype in dtypes:
        for shape in some_shapes:
            a = ta.array(make(shape, dtype))
            assert_equal(pickle.loads(pickle.dumps(a)), a)
Example #30
0
def test_hash_equality():
    random.seed(123)
    maxint = sys.maxsize + 1    # will be typically 2**31 or 2**63
    int_bits = 63 if maxint > 2**32 else 31

    special = [float('nan'), float('inf'), float('-inf'),
               0, -1, -1.0, -1 + 0j,
               303, -312424, -0.3, 1.7, 0.4j, -12.3j, 1 - 12.3j, 1.3 - 12.3j,
               (), (-1,), (2,),
               (0, 0), (-1, -1), (-5, 7), (3, -1, 0),
               ((0, 1), (2, 3)), (((-1,),),)]
    powers = [sign * (2**e + a) for sign in [1, -1] for a in [-1, 0, 1]
              for e in range(int_bits)]
    powers.extend([2**int_bits - 1, -2**int_bits, -2**int_bits + 1])
    small_random_ints = (random.randrange(-2**16, 2**16) for i in range(1000))
    large_random_ints = (random.randrange(-maxint, maxint) for i in range(1000))
    small_random_floats = (random.gauss(0, 1) for i in range(1000))
    large_random_floats = (random.gauss(0, 1e100) for i in range(1000))

    for collection in [special, powers,
                       small_random_ints, large_random_ints,
                       small_random_floats, large_random_floats]:
        for thing in collection:
            arr = ta.array(thing)
            if thing == thing:
                assert arr == thing
                assert not (arr != thing)
            assert hash(arr) == hash(thing), repr(thing)
Example #31
0
    def force(self, model):
        res = ta.array([0.0, 0.0])
        res += -model.gradient('pressure', self)

        if viscosity:
            res += viscosity * model.laplace('velocity', self)
        if nudge:
            res -= self.velocity * nudge

        if model.t < 1.0:
            res -= self.velocity * 1.0
            res = res * ta.array([0.0, 10.0])

        res += ta.array([0.0, gravitiy])

        return res
Example #32
0
def test_other_scalar_types():
    types = [np.int16, np.int32, np.int64,
             np.float16, np.float32, np.float64]
    for t in types:
        a = t(123.456)
        assert_equal(ta.array(a), np.array(a))
        assert_equal(ta.matrix(a), np.matrix(a))
Example #33
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))
Example #34
0
 def __init__(self,
              R,
              conjugate=False,
              antisymmetry=False,
              U=None,
              _strict_eq=False):
     if isinstance(R, sympy.ImmutableMatrix):
         # If it is integer, recast to integer tinyarray
         R = _make_int(R)
     elif isinstance(R, ta.ndarray_int):
         pass
     elif isinstance(R, ta.ndarray_float):
         R = _make_int(R)
     elif isinstance(R, sympy.matrices.MatrixBase):
         R = sympy.ImmutableMatrix(R)
         R = _make_int(R)
     elif isinstance(R, np.ndarray):
         # If it is integer, recast to integer tinyarray
         R = ta.array(R)
         R = _make_int(R)
     else:
         raise ValueError(
             'Real space rotation must be provided as a sympy matrix or an array.'
         )
     self.R, self.conjugate, self.antisymmetry, self.U = R, conjugate, antisymmetry, U
     # Calculating sympy inverse is slow, remember it
     self._strict_eq = _strict_eq
Example #35
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)
def make_system(a, t, W, L, salt):
    # Start with an empty tight-binding system and a single square lattice.
    # `a` is the lattice constant (by default set to 1 for simplicity).

    def hopping(site1, site2):

        alpha = uniform(repr(site1), salt) * 2 * np.pi
        beta = np.arccos(1 - 2 * uniform(repr(site1.pos), salt)) / 2
        gamma = uniform(repr(site2), salt) * 2 * np.pi
        #        np.random.seed(seed=salt)
        #        alpha=np.random.rand()*2*np.pi
        #        beta=np.arccos(1-2*np.random.rand())/2
        #        gamma=np.random.rand()*2*np.pi
        return -tinyarray.array([[
            cmath.exp(1j * alpha) * math.cos(beta),
            cmath.exp(1j * gamma) * math.sin(beta)
        ],
                                 [
                                     -cmath.exp(-1j * gamma) * math.sin(beta),
                                     cmath.exp(-1j * alpha) * math.cos(beta)
                                 ]])


#        return np.array([[1,0],[0,1]])

    lat = kwant.lattice.square(a)

    sys = kwant.Builder()

    #### Define the scattering region. ####
    sys[(lat(x, y) for x in range(L)
         for y in range(W))] = tinyarray.array([[0, 0], [0, 0]])

    # hoppings in x-direction
    sys[lat.neighbors()] = hopping

    #### Define the left lead. ####
    lead = kwant.Builder(kwant.TranslationalSymmetry((-a, 0)))

    lead[(lat(0, j) for j in range(W))] = tinyarray.array([[0, 0], [0, 0]])
    # hoppings in x-direction
    lead[lat.neighbors()] = -sigma_0
    #### Attach the leads and return the finalized system. ####
    sys.attach_lead(lead)
    sys.attach_lead(lead.reversed())

    return sys
Example #37
0
def grad_weight(displacement):
    res = list()
    for i in range(len(displacement)):
        res.append(
            grad_weight_1d(displacement[i]) *
            weight(displacement[j]
                   for j in range(len(displacement)) if j != i))
    return ta.array(res)
Example #38
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)
Example #39
0
def test_symmetry_act():
    lat = lattice.square(norbs=1)
    sym = lattice.TranslationalSymmetry((1, 0), (0, 1))
    site = lat(0, 0)
    hopping = (lat(0, 0), lat(1, 0))
    el = (1, 0)

    # Verify that the dtype of tags of sites returned by 'act' is 'int'
    for el in [el, ta.array(el, int)]:
        assert sym.act(el, site).tag.dtype is int
        assert all(s.tag.dtype is int for s in sym.act(el, *hopping))

    for el in [(1.0, 0), (1.5, 0)]:
        with raises(ValueError):
            sym.act(el, site)
        with raises(ValueError):
            sym.act(ta.array(el), site)
Example #40
0
def single_pos(bondee, bond_len, toward=None, away=None):
    if toward is not None:
        v = toward - bondee
        return bondee + normalize(v) * bond_len
    elif away is not None:
        v = bondee - away
        return bondee + normalize(v) * bond_len
    return bondee + tinyarray.array([bond_len, 0.0, 0.0])
Example #41
0
 def make_int(R):
     # If close to an integer array convert to integer tinyarray, else
     # return None
     R_int = ta.array(np.round(R), int)
     if qsymm.linalg.allclose(R, R_int):
         return R_int
     else:
         return None
Example #42
0
def test_as_dict_key():
    n = 100
    d = {}
    for dtype in dtypes + dtypes:
        for i in range(n):
            d[ta.array(range(i), dtype)] = i
        assert len(d) == n
    for i in range(n):
        assert d[tuple(range(i))] == i
Example #43
0
def test_binary_operators():
    ops = operator
    operations = [ops.add, ops.sub, ops.mul, ops.mod, ops.floordiv, ops.truediv]
    if sys.version_info.major < 3:
        operations.append(ops.div)

    with warnings.catch_warnings():
        warnings.filterwarnings("ignore", category=RuntimeWarning)

        for op in operations:
            for dtype in dtypes:
                for shape in [(), 1, 3, (3, 2)]:
                    if dtype is complex and op in [ops.mod, ops.floordiv]:
                        continue
                    a = make(shape, dtype)
                    b = make(shape, dtype)
                    assert_equal(op(ta.array(a.tolist()), ta.array(b.tolist())),
                                 op(a, b))
                    assert_equal(op(ta.array(a), ta.array(b)), op(a, b))
Example #44
0
    def wire(self, center, radius):
        """Return a key for all the lattice sites inside an infinite cylinder.

        This method makes it easy to define cylindrical (2d: rectangular) leads
        that point in any direction.  The object returned by this method is
        primarily meant to be used as a key for indexing `~kwant.builder.Builder`
        instances.  See example below.

        Parameters
        ----------
        center : 1d array-like of floats
            A point belonging to the axis of the cylinder.
        radius : float
            The radius of the cylinder.

        Notes
        -----
        The function returned by this method is to be called with a
        `~kwant.builder.TranslationalSymmetry` instance (or a
        `~kwant.builder.Builder` instance whose symmetry is used then) as sole
        argument.  All the lattice sites (in the fundamental domain of the
        symmetry) inside the specified infinite cylinder are yielded.  The
        direction of the cylinder is determined by the symmetry.

        Examples
        --------
        >>> lat = kwant.lattice.honeycomb()
        >>> sym = kwant.TranslationalSymmetry(lat.a.vec((-2, 1)))
        >>> lead = kwant.Builder(sym)
        >>> lead[lat.wire((0, -5), 5)] = 0
        >>> lead[lat.neighbors()] = 1
        """
        center = ta.array(center, float)

        def wire_sites(sym):
            if not isinstance(sym, builder.Symmetry):
                sym = sym.symmetry
            if not isinstance(sym, TranslationalSymmetry):
                raise ValueError('wire shape only works with '
                                 'translational symmetry.')
            if len(sym.periods) != 1:
                raise ValueError('wire shape only works with one-dimensional '
                                 'translational symmetry.')
            period = np.array(sym.periods)[0]
            direction = ta.array(period / np.linalg.norm(period))
            r_squared = radius**2

            def wire_shape(pos):
                rel_pos = pos - center
                projection = rel_pos - direction * ta.dot(direction, rel_pos)
                return sum(projection * projection) <= r_squared

            return self.shape(wire_shape, center)(sym)

        return wire_sites
Example #45
0
 def __init__(self, *periods):
     self.periods = ta.array(periods)
     if self.periods.ndim != 2:
         # TODO: remove the second part of the following message once
         # everybody got used to it.
         msg = ("TranslationalSymmetry takes 1d sequences as parameters.\n"
                "See What's new in Kwant 0.2 in the documentation.")
         raise ValueError(msg)
     if np.linalg.matrix_rank(periods) < len(periods):
         raise ValueError("Translational symmetry periods must be "
                          "linearly independent")
     # A dictionary containing cached data required for applying the
     # symmetry to different site families.
     self.site_family_data = {}
     self.is_reversed = False
Example #46
0
def test_value_equality_and_identity():
    m = ta.array([[1, 2], [3j, 4j]])
    syst = builder.Builder()
    fam = builder.SimpleSiteFamily()

    syst[fam(0)] = m
    syst[fam(1)] = m
    assert syst[fam(1)] is m

    syst[fam(0), fam(1)] = m
    assert syst[fam(1), fam(0)] == m.transpose().conjugate()
    assert syst[fam(0), fam(1)] is m

    syst[fam(1), fam(0)] = m
    assert syst[fam(0), fam(1)] == m.transpose().conjugate()
    assert syst[fam(1), fam(0)] is m
Example #47
0
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))
Example #48
0
        def wire_sites(sym):
            if not isinstance(sym, builder.Symmetry):
                sym = sym.symmetry
            if not isinstance(sym, TranslationalSymmetry):
                raise ValueError('wire shape only works with '
                                 'translational symmetry.')
            if len(sym.periods) != 1:
                raise ValueError('wire shape only works with one-dimensional '
                                 'translational symmetry.')
            period = np.array(sym.periods)[0]
            direction = ta.array(period / np.linalg.norm(period))
            r_squared = radius**2

            def wire_shape(pos):
                rel_pos = pos - center
                projection = rel_pos - direction * ta.dot(direction, rel_pos)
                return sum(projection * projection) <= r_squared

            return self.shape(wire_shape, center)(sym)
Example #49
0
def test_matrix():
    for l in [(), 3, (3,), ((3,)), (1, 2), ((1, 2), (3, 4))]:
        a = ta.matrix(l)
        b = np.matrix(l)
        assert a == b
        assert a.shape == b.shape
        a = ta.matrix(ta.array(l))
        assert a == b
        assert a.shape == b.shape
        a = ta.matrix(np.array(l))
        assert a == b
        assert a.shape == b.shape

        if sys.version_info[:2] > (2, 6):
            # Creation of tinyarrays from NumPy matrices only works for Python >
            # 2.6.  I don't know whether this is our bug or their's.
            a = ta.matrix(b)
            assert a == b

    for l in [(((),),), ((3,), ()), ((1, 2), (3,))]:
        raises(ValueError, ta.matrix, l)
Example #50
0
def test(n=20000):
    """Test the generator with the dieharder suite generating n**2 samples.

    Executing this function may take a very long time.
    """
    import os
    import tempfile
    import subprocess
    from tinyarray import array
    from struct import pack

    f = tempfile.NamedTemporaryFile(delete=False)
    try:
        for x in xrange(n):
            for y in xrange(n):
                a = array((x, y))
                i = int(2**32 * uniform(a))
                f.write(pack('I', i))
        f.close()
        subprocess.call(['dieharder', '-a', '-g', '201', '-f', f.name])
    finally:
        os.remove(f.name)
Example #51
0
def test_conversion():
    for src_dtype in dtypes:
        for dest_dtype in dtypes:
            src = ta.zeros(3, src_dtype)
            tsrc = tuple(src)
            npsrc = np.array(tsrc)
            impossible = src_dtype is complex and dest_dtype in [int, float]
            for s in [src, tsrc, npsrc]:
                if impossible:
                    raises(TypeError, ta.array, s, dest_dtype)
                else:
                    dest = ta.array(s, dest_dtype)
                    assert isinstance(dest[0], dest_dtype)
                    assert src == dest

    # Check for overflow.
    long_overflow = [1e300, np.array([1e300])]
    # This check only works for Python 2.
    if 18446744073709551615 > sys.maxsize:
        long_overflow.extend([np.array([18446744073709551615], np.uint64),
                              18446744073709551615])

    for s in long_overflow:
        raises(OverflowError, ta.array, s, int)
Example #52
0
def test_array():
    for dtype in dtypes:
        for a_shape in some_shapes:
            a = make(a_shape, dtype)

            # Creation from list.  This also tests creation from scalars.
            l = a.tolist()
            b = ta.array(l)
            b_shape = shape_of_seq(l)

            # a_shape and b_shape are not always equal.
            # Example: a_shape == (0, 0), b_shape = (0,).

            assert isinstance(repr(b), str)
            assert b.ndim == len(b_shape)
            assert tuple(b.shape) == b_shape
            assert b.size == a.size
            if a_shape != ():
                assert len(b) == len(a)
                assert_equal(np.array(ta.array(b)), np.array(l))
            else:
                assert b.dtype == dtype
                raises(TypeError, len, b)
            if sys.version_info[:2] > (2, 6):
                # Python 2.6 does not have memoryview.
                assert memoryview(b).tobytes() == memoryview(a).tobytes()
            assert_equal(np.array(b), np.array(l))
            assert ta.transpose(l) == np.transpose(l)

            # Here, the tinyarray is created via the buffer interface.  It's
            # possible to distinguish shape 0 from (0, 0).
            b = ta.array(a)

            # This tests creation of arrays from non-C-contiguous buffers.
            assert b == ta.array(a.transpose()).transpose()

            assert isinstance(repr(b), str)
            assert b.ndim == len(b.shape)
            assert b.shape == a.shape
            assert b.size == a.size
            assert b == a
            assert_equal(np.array(b), a)
            if a_shape != ():
                assert len(b) == len(a)
            else:
                raises(TypeError, len, b)
            if sys.version_info[:2] > (2, 6):
                # Python 2.6 does not have memoryview.
                assert memoryview(b).tobytes() == memoryview(a).tobytes()
            assert ta.transpose(b) == np.transpose(a)

            # Check creation from NumPy matrix.  This only works for Python >
            # 2.6.  I don't know whether this is our bug or their's.
            if sys.version_info[:2] > (2, 6):
                if not isinstance(a_shape, tuple) or len(a_shape) <= 2:
                    b = ta.array(np.matrix(a))
                    assert b.ndim == 2
                    assert b == np.matrix(a)

        l = []
        for i in range(16):
            l = [l]
        raises(ValueError, ta.array, l, dtype)

        raises(TypeError, ta.array, [0, [0, 0]], dtype)
        raises(ValueError, ta.array, [[0], [0, 0]], dtype)
        raises(ValueError, ta.array, [[0, 0], 0], dtype)
        raises(ValueError, ta.array, [[0, 0], [0]], dtype)
        raises(ValueError, ta.array, [[0, 0], [[0], [0]]], dtype)
Example #53
0
 def which(self, site):
     return ta.array((site.tag[0] // self.period,), int)
Example #54
0
 def f(i, j, arg):
     i, j = i.tag, j.tag
     if j[0] == i[0] + 1:
         return arg * ta.array([[1, 2j], [3 + 1j, 4j]])
     else:
         raise ValueError
Example #55
0
 def closest(self, pos):
     """
     Find the lattice coordinates of the site closest to position ``pos``.
     """
     return ta.array(self.n_closest(pos)[0])
Example #56
0


################ Library of lattices

def chain(a=1, name='', norbs=None):
    """Make a one-dimensional lattice."""
    return Monatomic(((a,),), name=name, norbs=norbs)


def square(a=1, name='', norbs=None):
    """Make a square lattice."""
    return Monatomic(((a, 0), (0, a)), name=name, norbs=norbs)


tri = ta.array(((1, 0), (0.5, 0.5 * sqrt(3))))

def triangular(a=1, name='', norbs=None):
    """Make a triangular lattice."""
    return Monatomic(a * tri, name=name, norbs=norbs)


def honeycomb(a=1, name='', norbs=None):
    """Make a honeycomb lattice."""
    lat = Polyatomic(a * tri, ((0, 0), (0, a / sqrt(3))),
                     name=name, norbs=norbs)
    lat.a, lat.b = lat.sublattices
    return lat


def kagome(a=1, name='', norbs=None):
"""An example of advanced system creation."""

from math import tanh
from cmath import exp
import tinyarray as ta
import kwant


sigma_0 = ta.identity(2)
sigma_x = ta.array([[0, 1], [1, 0]])
sigma_y = ta.array([[0, -1j], [1j, 0]])
sigma_z = ta.array([[1, 0], [0, -1]])


def make_system(R):
    def in_ring(pos):
        x, y = pos
        return R**2 / 4 < x**2 + y**2 < R**2

    def in_lead(pos):
        x, y = pos
        return -R / 4 < y < R / 4

    def pot(site, B):
        x, y = site.pos
        return (0.1 * tanh(x / R) + tanh(2 * y / R)) * sigma_z

    def hop(site1, site2, B):
        x1, y1 = site1.pos
        x2, y2 = site2.pos
        return - exp(.5j * B * (x1 - x2) * (y1 + y2)) * sigma_0
Example #58
0
 def normalize_tag(self, tag):
     tag = ta.array(tag, int)
     if len(tag) != self.lattice_dim:
         raise ValueError("Dimensionality mismatch.")
     return tag
Example #59
0
    def add_site_family(self, fam, other_vectors=None):
        """
        Select a fundamental domain for site family and cache associated data.

        Parameters
        ----------
        fam : `SiteFamily`
            the site family which has to be processed.  Be sure to delete the
            previously processed site families from `site_family_data` if you
            want to modify the cache.

        other_vectors : 2d array-like of integers
            Bravais lattice vectors used to complement the periods in forming
            a basis. The fundamental domain consists of all the lattice sites
            for which the zero coefficients corresponding to the symmetry
            periods in the basis formed by the symmetry periods and
            `other_vectors`. If an insufficient number of `other_vectors` is
            provided to form a basis, the missing ones are selected
            automatically.

        Raises
        ------
        KeyError
            If `fam` is already stored in `site_family_data`.
        ValueError
            If lattice `fam` is incompatible with given periods.
        """
        ensure_isinstance(fam, Monatomic)

        dim = self.periods.shape[1]
        if fam in self.site_family_data:
            raise KeyError('Family already processed, delete it from '
                           'site_family_data first.')
        inv = np.linalg.pinv(fam.prim_vecs)
        try:
            bravais_periods = np.dot(self.periods, inv)
        except ValueError:
            fam_space_dim = fam.prim_vecs.shape[1]
            if dim == fam_space_dim:
                raise
            msg = ("{0}-d-embedded lattice is incompatible with "
                   "{1}-d translational symmetry.")
            raise ValueError(msg.format(fam_space_dim, dim))
        # Absolute tolerance is correct in the following since we want an error
        # relative to the closest integer.
        if (not np.allclose(bravais_periods, np.round(bravais_periods),
                            rtol=0, atol=1e-8) or
            not np.allclose([fam.vec(i) for i in bravais_periods],
                            self.periods)):
            msg = ('Site family {0} does not have commensurate periods with '
                   'symmetry {1}.')
            raise ValueError(msg.format(fam, self))
        bravais_periods = np.array(np.round(bravais_periods), dtype='int')
        (num_dir, lat_dim) = bravais_periods.shape
        if other_vectors is None:
            other_vectors = np.zeros((0, lat_dim), dtype=int)
        else:
            other_vectors = np.array(other_vectors)
            if other_vectors.ndim != 2:
                raise ValueError(
                    '`other_vectors` must be a 2d array-like object.')
            if np.any(np.round(other_vectors) - other_vectors):
                raise ValueError('Only integer other_vectors are allowed.')
            other_vectors = np.array(np.round(other_vectors), dtype=int)

        m = np.zeros((lat_dim, lat_dim), dtype=int)

        m.T[:num_dir] = bravais_periods
        num_vec = num_dir + len(other_vectors)
        m.T[num_dir:num_vec] = other_vectors

        if np.linalg.matrix_rank(m) < num_vec:
            raise ValueError('other_vectors and symmetry periods are not '
                             'linearly independent.')

        # To define the fundamental domain of the new site family we now need to
        # choose `lat_dim - num_vec` extra lattice vectors that are not
        # linearly dependent on the vectors we already have. To do so we
        # continuously add the lattice basis vectors one by one such that they
        # are not linearly dependent on the existent vectors
        while num_vec < lat_dim:
            vh = np.linalg.svd(np.dot(m[:, :num_vec].T, fam.prim_vecs),
                               full_matrices=False)[2]
            projector = np.identity(dim) - np.dot(vh.T, vh)

            residuals = np.dot(fam.prim_vecs, projector)
            residuals = np.apply_along_axis(np.linalg.norm, 1, residuals)
            m[np.argmax(residuals), num_vec] = 1
            num_vec += 1

        det_m = int(round(np.linalg.det(m)))
        if det_m == 0:
            raise RuntimeError('Adding site family failed.')

        det_x_inv_m = np.array(np.round(det_m * np.linalg.inv(m)), dtype=int)
        assert (np.dot(m, det_x_inv_m) // det_m == np.identity(lat_dim)).all()

        det_x_inv_m_part = det_x_inv_m[:num_dir, :]
        m_part = m[:, :num_dir]
        self.site_family_data[fam] = (ta.array(m_part),
                                     ta.array(det_x_inv_m_part), det_m)
# --------------------------
#  - Repetition of previously used concepts (band structure calculations,
#    matrices as values in Builder).
#  - Main motivation is to contrast to the implementation of superconductivity
#    in tutorial5b.py

import kwant

import numpy as np
import tinyarray

# For plotting
from matplotlib import pyplot

#HIDDEN_BEGIN_nbvn
tau_x = tinyarray.array([[0, 1], [1, 0]])
tau_z = tinyarray.array([[1, 0], [0, -1]])


def make_lead(a=1, t=1.0, mu=0.7, Delta=0.1, W=10):
    # Start with an empty lead with a single square lattice
    lat = kwant.lattice.square(a)

    sym_lead = kwant.TranslationalSymmetry((-a, 0))
    lead = kwant.Builder(sym_lead)

    # build up one unit cell of the lead, and add the hoppings
    # to the next unit cell
    for j in xrange(W):
        lead[lat(0, j)] = (4 * t - mu) * tau_z + Delta * tau_x