Esempio n. 1
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])
Esempio n. 2
0
def test_HoppingKind():
    g = kwant.lattice.general(ta.identity(3), name="some_lattice")
    h = kwant.lattice.general(ta.identity(3), name="another_lattice")
    sym = kwant.TranslationalSymmetry((0, 2, 0))
    sys = builder.Builder(sym)
    sys[((h if max(x, y, z) % 2 else g)(x, y, z) for x in range(4) for y in range(2) for z in range(4))] = None
    for delta, ga, gb, n in [
        ((1, 0, 0), g, h, 4),
        ((1, 0, 0), h, g, 7),
        ((0, 1, 0), g, h, 1),
        ((0, 4, 0), h, h, 21),
        ((0, 0, 1), g, h, 4),
    ]:
        ph = list(builder.HoppingKind(delta, ga, gb)(sys))
        assert_equal(len(ph), n)
        ph = set(ph)
        assert_equal(len(ph), n)

        ph2 = list((sym.to_fd(b, a) for a, b in builder.HoppingKind(ta.negative(delta), gb, ga)(sys)))
        assert_equal(len(ph2), n)
        ph2 = set(ph2)
        assert_equal(ph2, ph)

        for a, b in ph:
            assert a.family == ga
            assert b.family == gb
            assert sym.to_fd(a) == a
            assert_equal(a.tag - b.tag, delta)
Esempio n. 3
0
def test_HoppingKind():
    g = kwant.lattice.general(ta.identity(3), name='some_lattice')
    h = kwant.lattice.general(ta.identity(3), name='another_lattice')
    sym = kwant.TranslationalSymmetry((0, 2, 0))
    syst = builder.Builder(sym)
    syst[((h if max(x, y, z) % 2 else g)(x, y, z)
         for x in range(4) for y in range(2) for z in range(4))] = None
    for delta, ga, gb, n in [((1, 0, 0), g, h, 4),
                             ((1, 0, 0), h, g, 7),
                             ((0, 1, 0), g, h, 1),
                             ((0, 4, 0), h, h, 21),
                             ((0, 0, 1), g, h, 4)]:
        ph = list(builder.HoppingKind(delta, ga, gb)(syst))
        assert len(ph) == n
        ph = set(ph)
        assert len(ph) == n

        ph2 = list((
                sym.to_fd(b, a) for a, b in
                builder.HoppingKind(ta.negative(delta), gb, ga)(syst)))
        assert len(ph2) == n
        ph2 = set(ph2)
        assert ph2 == ph

        for a, b in ph:
            assert a.family == ga
            assert b.family == gb
            assert sym.to_fd(a) == a
            assert a.tag - b.tag == delta

        # test hashability and equality
        hk = builder.HoppingKind((1, 0, 0), g)
        hk2 = builder.HoppingKind((1, 0, 0), g)
        hk3 = builder.HoppingKind((1, 0, 0), g, h)
        assert hk == hk2
        assert hash(hk) == hash(hk2)
        assert hk != hk3
        assert hash(hk) != hash(hk3)
        assert len({hk: 0, hk2:1, hk3: 2}) == 2
Esempio n. 4
0
def test_HoppingKind():
    g = kwant.lattice.general(ta.identity(3), name='some_lattice')
    h = kwant.lattice.general(ta.identity(3), name='another_lattice')
    sym = kwant.TranslationalSymmetry((0, 2, 0))
    syst = builder.Builder(sym)
    syst[((h if max(x, y, z) % 2 else g)(x, y, z)
         for x in range(4) for y in range(2) for z in range(4))] = None
    for delta, ga, gb, n in [((1, 0, 0), g, h, 4),
                             ((1, 0, 0), h, g, 7),
                             ((0, 1, 0), g, h, 1),
                             ((0, 4, 0), h, h, 21),
                             ((0, 0, 1), g, h, 4)]:
        ph = list(builder.HoppingKind(delta, ga, gb)(syst))
        assert len(ph) == n
        ph = set(ph)
        assert len(ph) == n

        ph2 = list((
                sym.to_fd(b, a) for a, b in
                builder.HoppingKind(ta.negative(delta), gb, ga)(syst)))
        assert len(ph2) == n
        ph2 = set(ph2)
        assert ph2 == ph

        for a, b in ph:
            assert a.family == ga
            assert b.family == gb
            assert sym.to_fd(a) == a
            assert a.tag - b.tag == delta

        # test hashability and equality
        hk = builder.HoppingKind((1, 0), g)
        hk2 = builder.HoppingKind((1, 0), g)
        hk3 = builder.HoppingKind((1, 0), g, h)
        assert hk == hk2
        assert hash(hk) == hash(hk2)
        assert hk != hk3
        assert hash(hk) != hash(hk3)
        assert len({hk: 0, hk2:1, hk3: 2}) == 2
Esempio n. 5
0
def planar_pos(bondee,
               bonded,
               bond_len,
               coplanar=None,
               toward=None,
               away=None,
               toward2=None,
               away2=None):
    new_bonded = []
    cur_bonded = bonded[:]
    if len(cur_bonded) == 0:
        pos = single_pos(bondee, bond_len, toward, away)
        toward = away = None
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 1:
        # add at 120 degree angle, co-planar if required
        if coplanar is None:
            if toward is not None or toward2 is not None:
                coplanar = [toward if toward is not None else toward2]
            elif away is not None or away2 is not None:
                ninety = right_angle((away if away is not None else away2) -
                                     bondee)
                coplanar = [bondee + ninety]
        pos = angle_pos(bondee, cur_bonded[0], bond_len, 120.0, coplanar)
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 2:
        # position along anti-bisector of current bonds
        v1 = normalize(cur_bonded[0] - bondee)
        v2 = normalize(cur_bonded[1] - bondee)
        anti_bi = normalize(tinyarray.negative(v1 + v2)) * bond_len
        new_bonded.append(bondee + anti_bi)
    return new_bonded
Esempio n. 6
0
def tetra_pos(bondee,
              bonded,
              bond_len,
              toward=None,
              away=None,
              toward2=None,
              away2=None):
    new_bonded = []
    cur_bonded = bonded[:]
    if len(cur_bonded) == 0:
        pos = single_pos(bondee, bond_len, toward, away)
        toward = toward2
        away = away2
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 1:
        # add at 109.5 degree angle
        coplanar = toward or away
        if coplanar:
            coplanar = [coplanar]
        else:
            coplanar = None
        pos = angle_pos(bondee,
                        cur_bonded[0],
                        bond_len,
                        109.5,
                        coplanar=coplanar)
        if toward or away:
            # find the other 109.5 position in the toward/away
            # plane and the closer/farther position as appropriate
            old = normalize(bondee - cur_bonded[0])
            new = pos - bondee
            midpoint = tinyarray.array(bondee + old * norm(new) * cos705)
            other_pos = pos + (midpoint - pos) * 2
            d1 = sqlength(pos - (toward or away))
            d2 = sqlength(other_pos - (toward or away))
            if toward is not None:
                if d2 < d1:
                    pos = other_pos
            elif away is not None and d2 > d1:
                pos = other_pos

        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 2:
        # add along anti-bisector of current bonds and raised up
        # 54.75 degrees from plane of those bonds (half of 109.5)
        v1 = normalize(cur_bonded[0] - bondee)
        v2 = normalize(cur_bonded[1] - bondee)
        anti_bi = normalize(tinyarray.negative(v1 + v2))
        # in order to stabilize the third and fourth tetrahedral
        # positions, cross the longer vector by the shorter
        if sqlength(v1) > sqlength(v2):
            cross_v = normalize(cross_product(v1, v2))
        else:
            cross_v = normalize(cross_product(v2, v1))

        anti_bi = anti_bi * cos5475 * bond_len
        cross_v = cross_v * sin5475 * bond_len

        pos = bondee + anti_bi + cross_v
        if toward or away:
            other_pos = bondee + anti_bi - cross_v
            d1 = sqlength(pos - (toward or away))
            d2 = sqlength(other_pos - (toward or away))
            if toward is not None:
                if d2 < d1:
                    pos = other_pos
            elif away is not None and d2 > d1:
                pos = other_pos
        new_bonded.append(pos)
        cur_bonded.append(pos)

    if len(cur_bonded) == 3:
        unitized = []
        for cb in cur_bonded:
            v = normalize(cb - bondee)
            unitized.append(bondee + v)
        pl = Plane(unitized)
        normal = pl.normal
        # if normal on other side of plane from bondee, we need to
        # invert the normal;  the (signed) distance from bondee
        # to the plane indicates if it is on the same side
        # (positive == same side)
        d = pl.distance(bondee)
        if d < 0.0:
            normal = tinyarray.negative(normal)
        new_bonded.append(bondee + normal * bond_len)
    return new_bonded