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])
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)
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
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
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
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