From b108491cd7bc81488cc33d8b5089c6b8f6ef7fda Mon Sep 17 00:00:00 2001 From: Christoph Groth <christoph.groth@cea.fr> Date: Mon, 27 May 2013 23:29:58 +0200 Subject: [PATCH] make lattice.shape return a nested function --- doc/source/reference/kwant.lattice.rst | 1 - kwant/lattice.py | 181 +++++++++++++------------ 2 files changed, 91 insertions(+), 91 deletions(-) diff --git a/doc/source/reference/kwant.lattice.rst b/doc/source/reference/kwant.lattice.rst index e3e975fc..6da3fc23 100644 --- a/doc/source/reference/kwant.lattice.rst +++ b/doc/source/reference/kwant.lattice.rst @@ -12,7 +12,6 @@ General general Monatomic Polyatomic - Shape Library of lattices ------------------- diff --git a/kwant/lattice.py b/kwant/lattice.py index 432d24a8..89871662 100644 --- a/kwant/lattice.py +++ b/kwant/lattice.py @@ -99,11 +99,99 @@ class Polyatomic(object): self._voronoi = ta.dot(lll.voronoi(self._reduced_vecs), self._transf) def shape(self, function, start): - """Yield sites belonging to a certain shape. + """Return a key for all the lattice sites inside a given shape. - See `~kwant.lattice.Shape` for more information. + The object returned by this method is primarily meant to be used as a + key for indexing `kwant.Builder` instances. See example below. + + Parameters + ---------- + function : callable + A function of real space coordinates that returns a truth value: + true for coordinates inside the shape, and false otherwise. + start : float vector + The origin for the flood-fill algorithm. + + Returns + ------- + shape_sites : function + + Notes + ----- + When the function returned by this method is called, a flood-fill + algorithm finds and yields all the lattice sites inside the specified + shape starting from the specified position. + + A `~kwant.builder.Symmetry` or `~kwant.builder.Builder` may be passed as + sole argument when calling the function returned by this method. This + will restrict the flood-fill to the fundamental domain of the symmetry + (or the builder's symmetry). Note that unless the shape function has + that symmetry itself, the result may be unexpected. + + Examples + -------- + >>> def circle(pos): + ... x, y = pos + ... return x**2 + y**2 < 100 + ... + >>> lat = kwant.lattice.honeycomb() + >>> sys = kwant.Builder() + >>> sys[lat.shape(circle, (0, 0))] = 0 + >>> sys[lat.neighbors()] = 1 """ - return Shape(self, function, start) + def shape_sites(symmetry=None): + Site = builder.Site + + if symmetry is None: + symmetry = builder.NoSymmetry() + elif not isinstance(symmetry, builder.Symmetry): + symmetry = symmetry.symmetry + + def fd_site(lat, tag): + return symmetry.to_fd(Site(lat, tag, True)) + + dim = len(start) + if dim != self.prim_vecs.shape[1]: + raise ValueError('Dimensionality of start position does not ' + 'match the space dimensionality.') + lats = self.sublattices + deltas = list(self._voronoi) + + #### Flood-fill #### + sites = [] + for tag in set(lat.closest(start) for lat in lats): + for lat in lats: + site = fd_site(lat, tag) + if function(site.pos): + sites.append(site) + if not sites: + msg = 'No sites close to {0} are inside the desired shape.' + raise ValueError(msg.format(start)) + tags = set(s.tag for s in sites) + + while sites: + old_tags = tags + tags = set() + for site in sites: + yield site + tags.add(site.tag) + old_tags |= tags + + new_tags = set() + for tag in tags: + for delta in deltas: + new_tag = tag + delta + if new_tag not in old_tags: + new_tags.add(new_tag) + + sites = set() + for tag in new_tags: + for lat in lats: + site = fd_site(lat, tag) + if site.tag not in old_tags and function(site.pos): + sites.add(site) + + return shape_sites def neighbors(self, n=1, eps=1e-8): """ @@ -476,93 +564,6 @@ class TranslationalSymmetry(builder.Symmetry): return result -class Shape(object): - def __init__(self, lattice, function, start): - """A class for finding all the lattice sites inside a shape. - - When an instance of this class is called, a flood-fill algorithm finds - and yields all the sites inside the specified shape starting from the - specified position. - - Parameters - ---------- - lattice : Polyatomic or Monoatomic lattice - Lattice, to which the resulting sites should belong. - function : callable - A function of real space coordinates that returns a truth value: - true for coordinates inside the shape, and false otherwise. - start : float vector - The origin for the flood-fill algorithm. - - Notes - ----- - A `~kwant.builder.Symmetry` or `~kwant.builder.Builder` may be passed as - sole argument when calling an instance of this class. This will - restrict the flood-fill to the fundamental domain of the symmetry (or - the builder's symmetry). Note that unless the shape function has that - symmetry itself, the result may be unexpected. - - Because a `~kwant.builder.Builder` can be indexed with functions or - iterables of functions, ``Shape`` instances (or any non-tuple - iterables of them, e.g. a list) can be used directly as "wildcards" when - setting or deleting sites. - """ - self.lat, self.func, self.start = lattice, function, start - - def __call__(self, symmetry=None): - Site = builder.Site - lat, func, start = self.lat, self.func, self.start - - if symmetry is None: - symmetry = builder.NoSymmetry() - elif not isinstance(symmetry, builder.Symmetry): - symmetry = symmetry.symmetry - - def fd_site(lat, tag): - return symmetry.to_fd(Site(lat, tag, True)) - - dim = len(start) - if dim != lat.prim_vecs.shape[1]: - raise ValueError('Dimensionality of start position does not match' - ' the space dimensionality.') - sls = lat.sublattices - deltas = list(lat._voronoi) - - #### Flood-fill #### - sites = [] - for tag in set(sl.closest(start) for sl in sls): - for sl in sls: - site = fd_site(sl, tag) - if func(site.pos): - sites.append(site) - if not sites: - msg = 'No sites close to {0} are inside the desired shape.' - raise ValueError(msg.format(start)) - tags = set(s.tag for s in sites) - - while sites: - old_tags = tags - tags = set() - for site in sites: - yield site - tags.add(site.tag) - old_tags |= tags - - new_tags = set() - for tag in tags: - for delta in deltas: - new_tag = tag + delta - if new_tag not in old_tags: - new_tags.add(new_tag) - - sites = set() - for tag in new_tags: - for sl in sls: - site = fd_site(sl, tag) - if site.tag not in old_tags and func(site.pos): - sites.add(site) - - ################ Library of lattices (to be extended) def chain(a=1, name=''): -- GitLab