Commit 20b86bd2 authored by Christoph Groth's avatar Christoph Groth
Browse files

make fill() "sticky"

parent e20aa36c
......@@ -1263,8 +1263,17 @@ class Builder:
def fill(self, template, shape, start, *, max_sites=10**7):
"""Populate builder using another one as a template.
Sites and hoppings that already exist in the target builder are never
overwritten.
Starting from one or multiple sites, traverse the graph of the template
builder and copy sites and hoppings to the target builder. The
traversal stops at sites that are already present in the target and on
sites that are not inside the provided shape.
This function takes into account translational symmetry. As such,
typically the template will have a higher symmetry than the target.
Newly added sites are connected by hoppings to sites that were already
present. This facilitates construction of a system by a series of
calls to 'fill'.
Parameters
----------
......@@ -1380,21 +1389,21 @@ class Builder:
if (head_fd not in old_active
and head_fd not in new_active):
# The 'head' site has not been filled yet.
if not shape(head_fd):
continue
if head_fd not in H:
# Fill 'head' site.
new_active.add(head_fd)
H.setdefault(head_fd, [head_fd, None])
else:
# The 'head' site exists and won't be visited:
# fill the incoming edge as well to balance the
# hopping.
if head_fd in H:
# The 'head' site exists. (It doesn't matter
# whether it's in the shape or not.) Fill the
# incoming edge as well to balance the hopping.
other_value = template._get_edge(
*templ_sym.to_fd(head, tail))
self._set_edge(*to_fd(head, tail)
+ (other_value,))
else:
if not shape(head_fd):
# There is no site at 'head' and it's
# outside the shape.
continue
new_active.add(head_fd)
H.setdefault(head_fd, [head_fd, None])
# Fill the outgoing edge.
if head in old_heads:
......
......@@ -790,6 +790,42 @@ def test_fill():
assert to_target_fd(new_sites[0]) == to_target_fd(lat(-1))
def test_fill_sticky():
"""Test that adjacent regions are properly interconnected when filled
separately.
"""
# Generate model template.
lat = kwant.lattice.kagome()
template = kwant.Builder(kwant.TranslationalSymmetry(
lat.vec((1, 0)), lat.vec((0, 1))))
for i, sl in enumerate(lat.sublattices):
template[sl(0, 0)] = i
for i in range(1, 3):
for j, hop in enumerate(template.expand(lat.neighbors(i))):
template[hop] = j * 1j
def disk(site):
pos = site.pos
return ta.dot(pos, pos) < 13
def halfplane(site):
return ta.dot(site.pos - (-1, 1), (-0.9, 0.63)) > 0
# Fill in one go.
syst0 = kwant.Builder()
syst0.fill(template, disk, (0, 0))
# Fill in two stages.
syst1 = kwant.Builder()
syst1.fill(template, lambda s: disk(s) and halfplane(s), (-2, 1))
syst1.fill(template, lambda s: disk(s) and not halfplane(s), (0, 0))
# Verify that both results are identical.
assert set(syst0.site_value_pairs()) == set(syst1.site_value_pairs())
assert (set(syst0.hopping_value_pairs())
== set(syst1.hopping_value_pairs()))
def test_attach_lead():
fam = builder.SimpleSiteFamily()
fam_noncommensurate = builder.SimpleSiteFamily(name='other')
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment