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_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
def test_special_constructors(): for dtype in dtypes: for shape in some_shapes: assert ta.zeros(shape, dtype) == np.zeros(shape, dtype) assert ta.ones(shape, dtype) == np.ones(shape, dtype) for n in [0, 1, 2, 3, 17]: assert ta.identity(n, dtype) == np.identity(n, dtype)
def test_special_constructors(): for dtype in dtypes: for shape in some_shapes: assert_equal(ta.zeros(shape, dtype), np.zeros(shape, dtype)) assert_equal(ta.ones(shape, dtype), np.ones(shape, dtype)) for n in [0, 1, 2, 3, 17]: assert_equal(ta.identity(n, dtype), np.identity(n, dtype))
def time_reversal(realspace_dim, U=None, spin=None): """Return a time-reversal symmetry operator parameters ---------- realspace_dim : int Realspace dimension U: ndarray (optional) The unitary action on the Hilbert space. May be None, to be able to treat symmetry candidates. spin : float or sequence of arrays (optional) Spin representation to use for the unitary action of the time reversal operator. If float is provided, it should be integer or half-integer specifying the spin representation in the standard basis, see `spin_matrices`. Otherwise a sequence of 3 arrays of identical square size must be provided representing 3 components of the angular momentum operator. The unitary action of time-reversal operator is `U = exp(-i π s_y)`. Only one of `U` and `spin` may be provided. Returns ------- T : PointGroupElement """ if U is not None and spin is not None: raise ValueError('Only one of `U` and `spin` may be provided.') if spin is not None: U = spin_rotation(np.pi * np.array([0, 1, 0]), spin) R = ta.identity(realspace_dim, int) return PointGroupElement(R, conjugate=True, antisymmetry=False, U=U)
def identity(self): """Return identity element with the same structure as self.""" dim = self.R.shape[0] R = ta.identity(dim, int) if self.U is not None: U = np.eye(self.U.shape[0]) else: U = None return PointGroupElement(R, False, False, U)
def test_invalid_HoppingKind(): g = kwant.lattice.general(ta.identity(3)) h = kwant.lattice.general(np.identity(3)[:-1]) # 2D lattice in 3D delta = (1, 0, 0) # families have incompatible tags with raises(ValueError): builder.HoppingKind(delta, g, h) # delta is incompatible with tags with raises(ValueError): builder.HoppingKind(delta, h)
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 test_builder_with_symmetry(): g = kwant.lattice.general(ta.identity(3)) sym = kwant.TranslationalSymmetry((0, 0, 3), (0, 2, 0)) sys = builder.Builder(sym) t, V = 1.0j, 0.0 hoppings = [ (g(5, 0, 0), g(0, 5, 0)), (g(0, 5, 0), g(0, 0, 5)), (g(0, 0, 5), g(5, 0, 0)), (g(0, 3, 0), g(0, 0, 5)), (g(0, 7, -6), g(5, 6, -6)), ] hoppings_fd = [ (g(5, 0, 0), g(0, 5, 0)), (g(0, 1, 0), g(0, -4, 5)), (g(0, 0, 2), g(5, 0, -3)), (g(0, 1, 0), g(0, -2, 5)), (g(0, 1, 0), g(5, 0, 0)), ] sys[(a for a, b in hoppings)] = V sys[hoppings] = t # TODO: Once Tinyarray supports "<" the conversion to tuple can be removed. assert_equal(sorted(tuple(site.tag) for site in sys.sites()), sorted(set(tuple(hop[0].tag) for hop in hoppings_fd))) for sites in hoppings_fd: for site in sites: assert site in sys assert_equal(sys[site], V) # TODO: Once Tinyarray supports "<" the conversion to tuple can be removed. assert_equal( sorted((tuple(a.tag), tuple(b.tag)) for a, b in sys.hoppings()), sorted((tuple(a.tag), tuple(b.tag)) for a, b in hoppings_fd), ) for hop in hoppings_fd: rhop = hop[1], hop[0] assert hop in sys assert rhop in sys assert_equal(sys[hop], t) assert_equal(sys[rhop], t.conjugate()) del sys[g(0, 6, -4), g(0, 11, -9)] assert (g(0, 1, 0), g(0, -4, 5)) not in sys del sys[g(0, 3, -3)] assert_equal(list((a.tag, b.tag) for a, b in sys.hoppings()), [((0, 0, 2), (5, 0, -3))])
def inversion(realspace_dim, U=None): """Return an inversion operator parameters ---------- realspace_dim : int Realspace dimension U: ndarray (optional) The unitary action on the Hilbert space. May be None, to be able to treat symmetry candidates Returns ------- P : PointGroupElement """ R = -ta.identity(realspace_dim, int) return PointGroupElement(R, conjugate=False, antisymmetry=False, U=U)
def test_builder_with_symmetry(): g = kwant.lattice.general(ta.identity(3)) sym = kwant.TranslationalSymmetry((0, 0, 3), (0, 2, 0)) syst = builder.Builder(sym) t, V = 1.0j, 0.0 hoppings = [(g(5, 0, 0), g(0, 5, 0)), (g(0, 5, 0), g(0, 0, 5)), (g(0, 0, 5), g(5, 0, 0)), (g(0, 3, 0), g(0, 0, 5)), (g(0, 7, -6), g(5, 6, -6))] hoppings_fd = [(g(5, 0, 0), g(0, 5, 0)), (g(0, 1, 0), g(0, -4, 5)), (g(0, 0, 2), g(5, 0, -3)), (g(0, 1, 0), g(0, -2, 5)), (g(0, 1, 0), g(5, 0, 0))] syst[(a for a, b in hoppings)] = V syst[hoppings] = t # TODO: Once Tinyarray supports "<" the conversion to tuple can be removed. assert (sorted(tuple(site.tag) for site in syst.sites()) == sorted(set(tuple(hop[0].tag) for hop in hoppings_fd))) for sites in hoppings_fd: for site in sites: assert site in syst assert syst[site] == V # TODO: Once Tinyarray supports "<" the conversion to tuple can be removed. assert (sorted((tuple(a.tag), tuple(b.tag)) for a, b in syst.hoppings()) == sorted((tuple(a.tag), tuple(b.tag)) for a, b in hoppings_fd)) for hop in hoppings_fd: rhop = hop[1], hop[0] assert hop in syst assert rhop in syst assert syst[hop] == t assert syst[rhop] == t.conjugate() del syst[g(0, 6, -4), g(0, 11, -9)] assert (g(0, 1, 0), g(0, -4, 5)) not in syst del syst[g(0, 3, -3)] assert (list((a.tag, b.tag) for a, b in syst.hoppings()) == [((0, 0, 2), (5, 0, -3))])
def test_hermitian_conjugation(): 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 sys = builder.Builder() fam = builder.SimpleSiteFamily() sys[fam(0)] = sys[fam(1)] = ta.identity(2) sys[fam(0), fam(1)] = f assert sys[fam(0), fam(1)] is f assert isinstance(sys[fam(1), fam(0)], builder.HermConjOfFunc) assert_equal(sys[fam(1), fam(0)](fam(1), fam(0), 2), sys[fam(0), fam(1)](fam(0), fam(1), 2).conjugate().transpose()) sys[fam(0), fam(1)] = sys[fam(1), fam(0)] assert isinstance(sys[fam(0), fam(1)], builder.HermConjOfFunc) assert sys[fam(1), fam(0)] is f
def test_hermitian_conjugation(): 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 syst = builder.Builder() fam = builder.SimpleSiteFamily() syst[fam(0)] = syst[fam(1)] = ta.identity(2) syst[fam(0), fam(1)] = f assert syst[fam(0), fam(1)] is f assert isinstance(syst[fam(1), fam(0)], builder.HermConjOfFunc) assert (syst[fam(1), fam(0)](fam(1), fam(0), 2) == syst[fam(0), fam(1)](fam(0), fam(1), 2).conjugate().transpose()) syst[fam(0), fam(1)] = syst[fam(1), fam(0)] assert isinstance(syst[fam(0), fam(1)], builder.HermConjOfFunc) assert syst[fam(1), fam(0)] is f
def identity(dim, shape=None): """Return identity operator with appropriate shape. Parameters ---------- dim : int Dimension of real space. shape : int (optional) Size of the unitary part of the operator. If not provided, U is set to None. Returns ------- id : PointGroupElement """ R = ta.identity(dim, int) if shape is not None: U = np.eye(shape) else: U = None return PointGroupElement(R, False, False, U)
def test_operator_construction(): lat, syst = _random_square_system(3) fsyst = syst.finalized() N = len(fsyst.sites) # test construction failure if norbs not given latnone = kwant.lattice.chain() syst[latnone(0)] = 1 for A in opservables: raises(ValueError, A, syst.finalized()) del syst[latnone(0)] # test construction failure when dimensions of onsite do not match for A in opservables: raises(ValueError, A, fsyst, onsite=np.eye(2)) # test that error is raised when input array is the wrong size for A in opservables: a = A(fsyst) kets = list(map(np.ones, [(0, ), (N - 1, ), (N + 1, ), (N, 1)])) for ket in kets: raises(ValueError, a, ket) raises(ValueError, a, ket, ket) raises(ValueError, a.act, ket) raises(ValueError, a.act, ket, ket) # Test failure on non-hermitian for A in (ops.Density, ops.Current, ops.Source): raises(ValueError, A, fsyst, 1j) # Test output dtype ket = np.ones(len(fsyst.sites)) for A in (ops.Density, ops.Current, ops.Source): a = A(fsyst) a_nonherm = A(fsyst, check_hermiticity=False) assert a(ket, ket).dtype == np.complex128 assert a(ket).dtype == np.float64 assert a_nonherm(ket, ket).dtype == np.complex128 assert a_nonherm(ket).dtype == np.complex128 # test construction with different numbers of orbitals lat2 = kwant.lattice.chain(norbs=2) extra_sites = [lat2(i) for i in range(N)] syst[extra_sites] = np.eye(2) syst[zip(fsyst.sites, extra_sites)] = ta.matrix([1, 1]) for A in opservables: raises(ValueError, A, syst.finalized(), onsite=np.eye(2)) A(syst.finalized()) A.onsite == np.eye(2) del syst[extra_sites] check = [(ops.Density, np.arange(N).reshape(-1, 1), ta.identity(1)), (ops.Current, np.array(list(fsyst.graph)), ta.identity(1)), (ops.Source, np.arange(N).reshape(-1, 1), ta.identity(1))] # test basic construction for A, where, onsite in check: a = A(fsyst) assert np.all(np.asarray(a.where) == where) assert all(a.onsite == onsite for i in range(N)) # test construction with dict `onsite` for A in opservables: B = A(fsyst, {lat: 1}) assert all(B.onsite(i) == 1 for i in range(N)) # test construction with a functional onsite for A in opservables: B = A(fsyst, lambda site: site.pos[0]) # x-position operator assert all(B.onsite(i) == fsyst.sites[i].pos[0] for i in range(N)) # test construction with `where` given by a sequence where = [lat(2, 2), lat(1, 1)] fwhere = tuple(fsyst.id_by_site[s] for s in where) A = ops.Density(fsyst, where=where) assert np.all(np.asarray(A.where).reshape(-1) == fwhere) where = [(lat(2, 2), lat(1, 2)), (lat(0, 0), lat(0, 1))] fwhere = np.asarray([(fsyst.id_by_site[a], fsyst.id_by_site[b]) for a, b in where]) A = ops.Current(fsyst, where=where) assert np.all(np.asarray(A.where) == fwhere) # test construction with `where` given by a function tag_list = [(1, 0), (1, 1), (1, 2)] def where(site): return site.tag in tag_list A = ops.Density(fsyst, where=where) assert all(fsyst.sites[A.where[w, 0]].tag in tag_list for w in range(A.where.shape[0])) where_list = set(kwant.HoppingKind((1, 0), lat)(syst)) fwhere_list = set( (fsyst.id_by_site[a], fsyst.id_by_site[b]) for a, b in where_list) def where(a, b): return (a, b) in where_list A = ops.Current(fsyst, where=where) assert all((a, b) in fwhere_list for a, b in A.where) # test that `sum` is passed to constructors correctly for A in opservables: A(fsyst, sum=True).sum == True
"""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
def test_finalization(): """Test the finalization of finite and infinite systems. In order to exactly verify the finalization, low-level features of the build module are used directly. This is not the way one would use a finalized system in normal code. """ def set_sites(dest): while len(dest) < n_sites: site = rng.randrange(size), rng.randrange(size) if site not in dest: dest[site] = random_onsite_hamiltonian(rng) def set_hops(dest, sites): while len(dest) < n_hops: a, b = rng.sample(list(sites), 2) if (a, b) not in dest and (b, a) not in dest: dest[a, b] = random_hopping_integral(rng) rng = Random(123) size = 20 n_sites = 120 n_hops = 500 # Make scattering region blueprint. sr_sites = {} set_sites(sr_sites) sr_hops = {} set_hops(sr_hops, sr_sites) # Make lead blueprint. possible_neighbors = rng.sample(list(sr_sites), n_sites // 2) lead_sites = {} for pn in possible_neighbors: lead_sites[pn] = random_hopping_integral(rng) set_sites(lead_sites) lead_hops = {} # Hoppings within a single lead unit cell set_hops(lead_hops, lead_sites) lead_sites_list = list(lead_sites) neighbors = set() for i in range(n_hops): while True: a = rng.choice(lead_sites_list) b = rng.choice(possible_neighbors) neighbors.add(b) b = b[0] - size, b[1] if rng.randrange(2): a, b = b, a if (a, b) not in lead_hops and (b, a) not in lead_hops: break lead_hops[a, b] = random_hopping_integral(rng) neighbors = sorted(neighbors) # Build scattering region from blueprint and test it. syst = builder.Builder() fam = kwant.lattice.general(ta.identity(2)) for site, value in sr_sites.items(): syst[fam(*site)] = value for hop, value in sr_hops.items(): syst[fam(*hop[0]), fam(*hop[1])] = value fsyst = syst.finalized() check_id_by_site(fsyst) check_onsite(fsyst, sr_sites) check_hoppings(fsyst, sr_hops) # check that sites are sorted assert fsyst.sites == tuple(sorted(fam(*site) for site in sr_sites)) # Build lead from blueprint and test it. lead = builder.Builder(kwant.TranslationalSymmetry((size, 0))) for site, value in lead_sites.items(): shift = rng.randrange(-5, 6) * size site = site[0] + shift, site[1] lead[fam(*site)] = value with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") lead.finalized() # Trigger the warning. assert len(w) == 1 assert issubclass(w[0].category, RuntimeWarning) assert "disconnected" in str(w[0].message) for (a, b), value in lead_hops.items(): shift = rng.randrange(-5, 6) * size a = a[0] + shift, a[1] b = b[0] + shift, b[1] lead[fam(*a), fam(*b)] = value flead = lead.finalized() all_sites = list(lead_sites) all_sites.extend((x - size, y) for (x, y) in neighbors) check_id_by_site(fsyst) check_onsite(flead, all_sites, check_values=False) check_onsite(flead, lead_sites, subset=True) check_hoppings(flead, lead_hops) # Attach lead to system with empty interface. syst.leads.append(builder.BuilderLead(lead, ())) raises(ValueError, syst.finalized) # Attach lead with improper interface. syst.leads[-1] = builder.BuilderLead( lead, 2 * tuple(builder.Site(fam, n) for n in neighbors)) raises(ValueError, syst.finalized) # Attach lead properly. syst.leads[-1] = builder.BuilderLead( lead, (builder.Site(fam, n) for n in neighbors)) fsyst = syst.finalized() assert len(fsyst.lead_interfaces) == 1 assert ([fsyst.sites[i].tag for i in fsyst.lead_interfaces[0]] == neighbors) # test that we cannot finalize a system with a badly sorted interface order raises(ValueError, lead._finalized_infinite, [builder.Site(fam, n) for n in reversed(neighbors)]) # site ordering independent of whether interface was specified flead_order = lead._finalized_infinite([builder.Site(fam, n) for n in neighbors]) assert flead.sites == flead_order.sites syst.leads[-1] = builder.BuilderLead( lead, (builder.Site(fam, n) for n in neighbors)) fsyst = syst.finalized() assert len(fsyst.lead_interfaces) == 1 assert ([fsyst.sites[i].tag for i in fsyst.lead_interfaces[0]] == neighbors) # Add a hopping to the lead which couples two next-nearest cells and check # whether this leads to an error. a = rng.choice(lead_sites_list) b = rng.choice(possible_neighbors) b = b[0] + 2 * size, b[1] lead[fam(*a), fam(*b)] = random_hopping_integral(rng) raises(ValueError, lead.finalized)
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))
def test_finalization(): """Test the finalization of finite and infinite systems. In order to exactly verify the finalization, low-level features of the build module are used directly. This is not the way one would use a finalized system in normal code. """ def set_sites(dest): while len(dest) < n_sites: site = rng.randrange(size), rng.randrange(size) if site not in dest: dest[site] = random_onsite_hamiltonian(rng) def set_hops(dest, sites): while len(dest) < n_hops: a, b = rng.sample(list(sites), 2) if (a, b) not in dest and (b, a) not in dest: dest[a, b] = random_hopping_integral(rng) rng = Random(123) size = 20 n_sites = 120 n_hops = 500 # Make scattering region blueprint. sr_sites = {} set_sites(sr_sites) sr_hops = {} set_hops(sr_hops, sr_sites) # Make lead blueprint. possible_neighbors = rng.sample(list(sr_sites), n_sites // 2) lead_sites = {} for pn in possible_neighbors: lead_sites[pn] = random_hopping_integral(rng) set_sites(lead_sites) lead_hops = {} # Hoppings within a single lead unit cell set_hops(lead_hops, lead_sites) lead_sites_list = list(lead_sites) neighbors = set() for i in range(n_hops): while True: a = rng.choice(lead_sites_list) b = rng.choice(possible_neighbors) neighbors.add(b) b = b[0] - size, b[1] if rng.randrange(2): a, b = b, a if (a, b) not in lead_hops and (b, a) not in lead_hops: break lead_hops[a, b] = random_hopping_integral(rng) neighbors = sorted(neighbors) # Build scattering region from blueprint and test it. syst = builder.Builder() fam = kwant.lattice.general(ta.identity(2)) for site, value in sr_sites.items(): syst[fam(*site)] = value for hop, value in sr_hops.items(): syst[fam(*hop[0]), fam(*hop[1])] = value fsyst = syst.finalized() check_id_by_site(fsyst) check_onsite(fsyst, sr_sites) check_hoppings(fsyst, sr_hops) # check that sites are sorted assert fsyst.sites == tuple(sorted(fam(*site) for site in sr_sites)) # Build lead from blueprint and test it. lead = builder.Builder(kwant.TranslationalSymmetry((size, 0))) for site, value in lead_sites.items(): shift = rng.randrange(-5, 6) * size site = site[0] + shift, site[1] lead[fam(*site)] = value with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") lead.finalized() # Trigger the warning. assert len(w) == 1 assert issubclass(w[0].category, RuntimeWarning) assert "disconnected" in str(w[0].message) for (a, b), value in lead_hops.items(): shift = rng.randrange(-5, 6) * size a = a[0] + shift, a[1] b = b[0] + shift, b[1] lead[fam(*a), fam(*b)] = value flead = lead.finalized() all_sites = list(lead_sites) all_sites.extend((x - size, y) for (x, y) in neighbors) check_id_by_site(fsyst) check_onsite(flead, all_sites, check_values=False) check_onsite(flead, lead_sites, subset=True) check_hoppings(flead, lead_hops) # Attach lead to system with empty interface. syst.leads.append(builder.BuilderLead(lead, ())) raises(ValueError, syst.finalized) # Attach lead with improper interface. syst.leads[-1] = builder.BuilderLead( lead, 2 * tuple(builder.Site(fam, n) for n in neighbors)) raises(ValueError, syst.finalized) # Attach lead properly. syst.leads[-1] = builder.BuilderLead(lead, (builder.Site(fam, n) for n in neighbors)) fsyst = syst.finalized() assert len(fsyst.lead_interfaces) == 1 assert ([fsyst.sites[i].tag for i in fsyst.lead_interfaces[0]] == neighbors) # test that we cannot finalize a system with a badly sorted interface order raises(ValueError, builder.InfiniteSystem, lead, [builder.Site(fam, n) for n in reversed(neighbors)]) # site ordering independent of whether interface was specified flead_order = builder.InfiniteSystem( lead, [builder.Site(fam, n) for n in neighbors]) assert flead.sites == flead_order.sites syst.leads[-1] = builder.BuilderLead(lead, (builder.Site(fam, n) for n in neighbors)) fsyst = syst.finalized() assert len(fsyst.lead_interfaces) == 1 assert ([fsyst.sites[i].tag for i in fsyst.lead_interfaces[0]] == neighbors) # Add a hopping to the lead which couples two next-nearest cells and check # whether this leads to an error. a = rng.choice(lead_sites_list) b = rng.choice(possible_neighbors) b = b[0] + 2 * size, b[1] lead[fam(*a), fam(*b)] = random_hopping_integral(rng) raises(ValueError, lead.finalized)
def test_opservables_construction(): lat, syst = _random_square_system(3) fsyst = syst.finalized() N = len(fsyst.sites) # test construction failure if norbs not given latnone = kwant.lattice.chain() syst[latnone(0)] = 1 for A in opservables: raises(ValueError, A, syst.finalized()) del syst[latnone(0)] # test construction failure when dimensions of onsite do not match for A in opservables: raises(ValueError, A, fsyst, onsite=np.eye(2)) # test that error is raised when input array is the wrong size for A in opservables: a = A(fsyst) kets = list(map(np.ones, [(0,), (N - 1,), (N + 1,), (N, 1)])) for ket in kets: raises(ValueError, a, ket) raises(ValueError, a, ket, ket) raises(ValueError, a.act, ket) raises(ValueError, a.act, ket, ket) # Test `check_hermiticity=False` for A in (ops.Density, ops.Current, ops.Source): raises(ValueError, A, fsyst, 1j) # test construction with different numbers of orbitals lat2 = kwant.lattice.chain(norbs=2) extra_sites = [lat2(i) for i in range(N)] syst[extra_sites] = np.eye(2) syst[zip(fsyst.sites, extra_sites)] = ta.matrix([1, 1]) for A in opservables: raises(ValueError, A, syst.finalized(), onsite=np.eye(2)) A(syst.finalized()) A.onsite == np.eye(2) del syst[extra_sites] check = [(ops.Density, np.arange(N).reshape(-1, 1), ta.identity(1)), (ops.Current, np.array(list(fsyst.graph)), ta.identity(1)), (ops.Source, np.arange(N).reshape(-1, 1), ta.identity(1))] # test basic construction for A, where, onsite in check: a = A(fsyst) assert np.all(np.asarray(a.where) == where) assert all(a.onsite == onsite for i in range(N)) # test construction with dict `onsite` for A in opservables: B = A(fsyst, {lat: 1}) assert all(B.onsite(i) == 1 for i in range(N)) # test construction with a functional onsite for A in opservables: B = A(fsyst, lambda site: site.pos[0]) # x-position operator assert all(B.onsite(i) == fsyst.sites[i].pos[0] for i in range(N)) # test construction with `where` given by a sequence where = [lat(2, 2), lat(1, 1)] fwhere = tuple(fsyst.id_by_site[s] for s in where) A = ops.Density(fsyst, where=where) assert np.all(np.asarray(A.where).reshape(-1) == fwhere) where = [(lat(2, 2), lat(1, 2)), (lat(0, 0), lat(0, 1))] fwhere = np.asarray([(fsyst.id_by_site[a], fsyst.id_by_site[b]) for a, b in where]) A = ops.Current(fsyst, where=where) assert np.all(np.asarray(A.where) == fwhere) # test construction with `where` given by a function tag_list = [(1, 0), (1, 1), (1, 2)] def where(site): return site.tag in tag_list A = ops.Density(fsyst, where=where) assert all(fsyst.sites[A.where[w, 0]].tag in tag_list for w in range(A.where.shape[0])) where_list = set(kwant.HoppingKind((1, 0), lat)(syst)) fwhere_list = set((fsyst.id_by_site[a], fsyst.id_by_site[b]) for a, b in where_list) def where(a, b): return (a, b) in where_list A = ops.Current(fsyst, where=where) assert all((a, b) in fwhere_list for a, b in A.where)
"""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