From 8074eed3c4a066a335dab743e81aa17ca46da6bb Mon Sep 17 00:00:00 2001
From: Christoph Groth <christoph.groth@cea.fr>
Date: Tue, 6 Nov 2012 15:01:14 +0100
Subject: [PATCH] use the term (lead) interface (sites) instead of lead
 neighbors

This new nomenclature avoids the confusion between "lead neighbors" and "site
neighbors".
---
 examples/square.py                  |  12 +--
 examples/tests/test_square.py       |   4 +-
 kwant/builder.py                    | 121 ++++++++++++++--------------
 kwant/graph/tests/test_slicer.py    |   4 +-
 kwant/plotter.py                    |   4 +-
 kwant/solvers/common.py             |  43 +++++-----
 kwant/solvers/tests/_test_sparse.py |   6 +-
 kwant/system.py                     |  12 +--
 kwant/tests/test_builder.py         |  10 +--
 9 files changed, 107 insertions(+), 109 deletions(-)

diff --git a/examples/square.py b/examples/square.py
index 62a02059..64b47c49 100644
--- a/examples/square.py
+++ b/examples/square.py
@@ -20,10 +20,6 @@ class Lead(object):
                                   fermi_energy)
 
 class System(kwant.system.FiniteSystem):
-    # Override abstract attributes.
-    graph = None
-    lead_neighbor_seqs = None
-
     def __init__(self, shape, hopping,
                  potential=0, lead_potentials=(0, 0),
                  return_scalars_as_matrix=True):
@@ -64,13 +60,13 @@ class System(kwant.system.FiniteSystem):
                 g.add_edges(edges)
         self.graph = g.compressed()
 
-        self.lead_neighbor_seqs = []
+        self.lead_interfaces = []
         for x in [0, shape[0] - 1]:
             # We have to use list here, as numpy.array does not understand
             # generators.
-            lead_neighbors = list(self.nodeid_from_pos((x, y))
-                              for y in xrange(shape[1]))
-            self.lead_neighbor_seqs.append(np.array(lead_neighbors))
+            interface = list(self.nodeid_from_pos((x, y))
+                             for y in xrange(shape[1]))
+            self.lead_interfaces.append(np.array(interface))
 
         self.leads = [Lead(shape[1], hopping, lead_potentials[i])
                       for i in range(2)]
diff --git a/examples/tests/test_square.py b/examples/tests/test_square.py
index e9b020b9..e49d67ff 100644
--- a/examples/tests/test_square.py
+++ b/examples/tests/test_square.py
@@ -28,9 +28,9 @@ def test_hamiltonian():
 
 def test_self_energy():
     sys = square.System((2, 4), 1)
-    for lead in xrange(len(sys.lead_neighbor_seqs)):
+    for lead in xrange(len(sys.lead_interfaces)):
         n_orb = sum(
-            sys.num_orbitals(site) for site in sys.lead_neighbor_seqs[lead])
+            sys.num_orbitals(site) for site in sys.lead_interfaces[lead])
         se = sys.self_energy(lead, 0)
         assert_equal(len(se.shape), 2)
         assert_equal(se.shape[0], se.shape[1])
diff --git a/kwant/builder.py b/kwant/builder.py
index 17b98e5e..ffc8f8ba 100644
--- a/kwant/builder.py
+++ b/kwant/builder.py
@@ -299,13 +299,13 @@ class Lead(object):
 
     Instance Variables
     ------------------
-    neighbors : sequence of sites
+    interface : sequence of sites
     """
     __metaclass__ = abc.ABCMeta
 
-    def check_neighbors(self):
-        if len(self.neighbors) == 0:
-            raise ValueError('Lead is not connected (no neighbors).')
+    def check_interface(self):
+        if len(self.interface) == 0:
+            raise ValueError('Lead is not connected (no interface sites).')
 
     @abc.abstractmethod
     def finalized():
@@ -324,7 +324,8 @@ class Lead(object):
         The method ``self_energy`` of the finalized lead must return a square
         matrix of appropriate size.
 
-        The order of neighbors is assumed to be preserved during finalization.
+        The order of interface sites is assumed to be preserved during
+        finalization.
         """
         pass
 
@@ -338,7 +339,7 @@ class BuilderLead(Lead):
         The tight-binding system of a lead. It has to possess appropriate
         symmetry, and it may not contain hoppings between further than
         neighboring lead slices.
-    neighbors : sequence of `Site` instances
+    interface : sequence of `Site` instances
         Sequence of sites in the scattering region to which the lead is
         attached.
 
@@ -349,24 +350,24 @@ class BuilderLead(Lead):
     the symmetry vector (i.e. the lead is 'leaving' the system and starts
     with a hopping).
 
-    The given order of neighbors is preserved throughout finalization.
+    The given order of interface sites is preserved throughout finalization.
 
     Every system has an attribute `leads`, which stores a list of
     `BuilderLead` objects with all the information about the leads that are
     attached.
     """
-    def __init__(self, builder, neighbors):
+    def __init__(self, builder, interface):
         self.builder = builder
-        self.neighbors = tuple(neighbors)
-        self.check_neighbors()
+        self.interface = tuple(interface)
+        self.check_interface()
 
     def finalized(self):
         """Return a `kwant.system.InfiniteSystem` corresponding to the
         compressed lead.
 
-        The order of neighbors is kept during finalization.
+        The order of interface sites is kept during finalization.
         """
-        return self.builder._finalized_infinite(self.neighbors)
+        return self.builder._finalized_infinite(self.interface)
 
 
 class SelfEnergy(Lead):
@@ -375,14 +376,14 @@ class SelfEnergy(Lead):
     Parameters
     ----------
     self_energy_func : function
-        Function which returns the self energy matrix for the neighbors given
-        the energy.
-    neighbors : sequence of `Site` instances
+        Function which returns the self energy matrix for the interface sites
+        given the energy.
+    interface : sequence of `Site` instances
     """
-    def __init__(self, self_energy_func, neighbors):
+    def __init__(self, self_energy_func, interface):
         self.self_energy_func = self_energy_func
-        self.neighbors = tuple(neighbors)
-        self.check_neighbors()
+        self.interface = tuple(interface)
+        self.check_interface()
 
     def finalized(self):
         """Trivial finalization: the object is returned itself."""
@@ -508,9 +509,9 @@ class Builder(object):
     The behavior of builders with a symmetry is slightly more sophisticated.
     First of all, it is implicitly assumed throughout kwant that **every**
     function assigned as a value to a builder with a symmetry possesses the
-    same symmetry.  Secondly, all keys are mapped to the fundamental before
-    storing them.  This may produce confusing results when neighbors of a site
-    are queried.
+    same symmetry.  Secondly, all keys are mapped to the fundamental domain
+    before storing them.  This may produce confusing results when neighbors of
+    a site are queried.
 
     The methods `possible_hoppings` and `attach_lead` *work* only if the sites
     affected by them have tags which are sequences of integers.  They *make
@@ -797,17 +798,17 @@ class Builder(object):
             if site not in self.H:
                 continue
             while site:
-                pneighbors = tuple(self._out_neighbors(site))
-                if pneighbors:
-                    assert len(pneighbors) == 1
-                    pneighbor = pneighbors[0]
-                    self._del_edge(pneighbor, site)
-                    if self._out_degree(pneighbor) > 1:
-                        pneighbor = False
+                neighbors = tuple(self._out_neighbors(site))
+                if neighbors:
+                    assert len(neighbors) == 1
+                    neighbor = neighbors[0]
+                    self._del_edge(neighbor, site)
+                    if self._out_degree(neighbor) > 1:
+                        neighbor = False
                 else:
-                    pneighbor = False
+                    neighbor = False
                 del self.H[site]
-                site = pneighbor
+                site = neighbor
 
     def __iter__(self):
         """Return an iterator over all sites and hoppings."""
@@ -970,7 +971,7 @@ class Builder(object):
         min_dom = min(all_doms)
         del all_doms
 
-        neighbors = set()
+        interface = set()
         added = set()
         # Initialize flood-fill: create the outermost sites.
         for site in H:
@@ -980,7 +981,7 @@ class Builder(object):
                     if neighbor not in self:
                         self[neighbor] = lead_builder[neighbor]
                         added.add(neighbor)
-                    neighbors.add(neighbor)
+                    interface.add(neighbor)
 
         # Do flood-fill.
         covered = True
@@ -1006,7 +1007,7 @@ class Builder(object):
                     self[site_new, site] = lead_builder[site_new, site]
             added = added2
 
-        self.leads.append(BuilderLead(lead_builder, list(neighbors)))
+        self.leads.append(BuilderLead(lead_builder, tuple(interface)))
         return len(self.leads) - 1
 
     def finalized(self):
@@ -1059,7 +1060,7 @@ class Builder(object):
 
         #### Connect leads.
         finalized_leads = []
-        lead_neighbor_seqs = []
+        lead_interfaces = []
         for lead_nr, lead in enumerate(self.leads):
             try:
                 finalized_leads.append(lead.finalized())
@@ -1067,8 +1068,8 @@ class Builder(object):
                 msg = 'Problem finalizing lead {0}:'
                 e.args = (' '.join((msg.format(lead_nr),) + e.args),)
                 raise
-            lns = [id_by_site[neighbor] for neighbor in lead.neighbors]
-            lead_neighbor_seqs.append(np.array(lns))
+            interface = [id_by_site[isite] for isite in lead.interface]
+            lead_interfaces.append(np.array(interface))
 
         #### Assemble and return result.
         result = FiniteSystem()
@@ -1078,24 +1079,24 @@ class Builder(object):
         result.hoppings = [self._get_edge(sites[tail], sites[head])
                            for tail, head in g]
         result.onsite_hamiltonians = [self.H[site][1] for site in sites]
-        result.lead_neighbor_seqs = lead_neighbor_seqs
+        result.lead_interfaces = lead_interfaces
         result.symmetry = self.symmetry
         return result
 
-    def _finalized_infinite(self, order_of_neighbors=None):
+    def _finalized_infinite(self, interface_order=None):
         """
         Finalize this builder instance which has to have exactly a single
         symmetry direction.
 
-        If order_of_neighbors is not set, the order of the neighbors in the
-        finalized system will be arbitrary.  If order_of_neighbors is set to a
-        sequence of neighbor sites, this order will be kept.
+        If interface_order is not set, the order of the interface sites in the
+        finalized system will be arbitrary.  If interface_order is set to a
+        sequence of interface sites, this order will be kept.
         """
         sym = self.symmetry
         assert sym.num_directions == 1
 
         #### For each site of the fundamental domain, determine whether it has
-        #### neighbors or not.
+        #### neighbors in the previous domain or not.
         lsites_with = []       # Fund. domain sites with neighbors in prev. dom
         lsites_without = []    # Remaining sites of the fundamental domain
         for tail in self.H:    # Loop over all sites of the fund. domain.
@@ -1116,42 +1117,42 @@ class Builder(object):
         ### Create list of sites and a lookup table
         minus_one = ta.array((-1,))
         plus_one = ta.array((1,))
-        if order_of_neighbors is None:
-            neighbors = [sym.act(minus_one, s) for s in lsites_with]
+        if interface_order is None:
+            interface = [sym.act(minus_one, s) for s in lsites_with]
         else:
-            shift = ta.array((-sym.which(order_of_neighbors[0])[0] - 1,))
+            shift = ta.array((-sym.which(interface_order[0])[0] - 1,))
             lsites_with_set = set(lsites_with)
             lsites_with = []
-            neighbors = []
-            for out_of_place_neighbor in order_of_neighbors:
-                # Shift the neighbor domain before the fundamental domain.
-                # That's the right place for the neighbors of a lead to be, but
-                # the neighbors in order_of_neighbors might live in a different
+            interface = []
+            for shifted_iface_site in interface_order:
+                # Shift the interface domain before the fundamental domain.
+                # That's the right place for the interface of a lead to be, but
+                # the sites of interface_order might live in a different
                 # domain.
-                neighbor = sym.act(shift, out_of_place_neighbor)
-                lsite = sym.act(plus_one, neighbor)
+                iface_site = sym.act(shift, shifted_iface_site)
+                lsite = sym.act(plus_one, iface_site)
 
                 try:
                     lsites_with_set.remove(lsite)
                 except KeyError:
-                    if (-sym.which(out_of_place_neighbor)[0] - 1,) != shift:
+                    if (-sym.which(shifted_iface_site)[0] - 1,) != shift:
                         raise ValueError(
-                            'The sites in order_of_neighbors do not all '
+                            'The sites in interface_order do not all '
                             'belong to the same lead slice.')
                     else:
-                        raise ValueError('A site in order_of_neighbors is '
-                                         'not a neighbor:\n' + str(neighbor))
-                neighbors.append(neighbor)
+                        raise ValueError('A site in interface_order is not an '
+                                         'interface site:\n' + str(iface_site))
+                interface.append(iface_site)
                 lsites_with.append(lsite)
             if lsites_with_set:
                 raise ValueError(
-                    'order_of_neighbors did not contain all neighbors.')
+                    'interface_order did not contain all interface sites.')
             del lsites_with_set
 
-        sites = lsites_with + lsites_without + neighbors
+        sites = lsites_with + lsites_without + interface
         del lsites_with
         del lsites_without
-        del neighbors
+        del interface
         id_by_site = {}
         for site_id, site in enumerate(sites):
             id_by_site[site] = site_id
diff --git a/kwant/graph/tests/test_slicer.py b/kwant/graph/tests/test_slicer.py
index bacec81c..e9ba6c76 100644
--- a/kwant/graph/tests/test_slicer.py
+++ b/kwant/graph/tests/test_slicer.py
@@ -41,8 +41,8 @@ def test_rectangle():
         fsys = sys.finalized()
 
         slices = slicer.slice(fsys.graph,
-                              fsys.lead_neighbor_seqs[0],
-                              fsys.lead_neighbor_seqs[1])
+                              fsys.lead_interfaces[0],
+                              fsys.lead_interfaces[1])
 
         # In the rectangle case, the slicing is very constricted and
         # we know that all slices must have the same shape.
diff --git a/kwant/plotter.py b/kwant/plotter.py
index 1135cdfc..46ccdd31 100644
--- a/kwant/plotter.py
+++ b/kwant/plotter.py
@@ -277,7 +277,7 @@ def iterate_lead_sites_builder(syst, lead_copies):
         if not isinstance(lead, builder.BuilderLead):
             continue
         sym = lead.builder.symmetry
-        shift = sym.which(lead.neighbors[0]) + 1
+        shift = sym.which(lead.interface[0]) + 1
 
         for i in xrange(lead_copies):
             for site in lead.builder.sites():
@@ -289,7 +289,7 @@ def iterate_lead_hoppings_builder(syst, lead_copies):
         if not isinstance(lead, builder.BuilderLead):
             continue
         sym = lead.builder.symmetry
-        shift = sym.which(lead.neighbors[0]) + 1
+        shift = sym.which(lead.interface[0]) + 1
 
         for i in xrange(lead_copies):
             for site1, site2 in lead.builder.hoppings():
diff --git a/kwant/solvers/common.py b/kwant/solvers/common.py
index 44dc9548..d488bc48 100644
--- a/kwant/solvers/common.py
+++ b/kwant/solvers/common.py
@@ -135,10 +135,10 @@ class SparseSolver(object):
         splhsmat = getattr(sp, self.lhsformat + '_matrix')
         sprhsmat = getattr(sp, self.rhsformat + '_matrix')
 
-        if not sys.lead_neighbor_seqs:
+        if not sys.lead_interfaces:
             raise ValueError('System contains no leads.')
-        lhs, norb = sys.hamiltonian_submatrix(
-            sparse=True, return_norb=True)[:2]
+        lhs, norb = sys.hamiltonian_submatrix(sparse=True,
+                                              return_norb=True)[:2]
         lhs = getattr(lhs, 'to' + self.lhsformat)()
         lhs = lhs - energy * sp.identity(lhs.shape[0], format=self.lhsformat)
 
@@ -146,7 +146,8 @@ class SparseSolver(object):
             if np.any(abs((lhs - lhs.T.conj()).data) > 1e-13):
                 raise ValueError('System Hamiltonian is not Hermitian.')
 
-        offsets = np.zeros(norb.shape[0] + 1, int)
+        offsets = np.empty(norb.shape[0] + 1, int)
+        offsets[0] = 0
         offsets[1 :] = np.cumsum(norb)
 
         # Process the leads, generate the eigenvector matrices and lambda
@@ -155,7 +156,7 @@ class SparseSolver(object):
         kept_vars = []
         rhs = []
         lead_info = []
-        for leadnum, lead_neighbors in enumerate(sys.lead_neighbor_seqs):
+        for leadnum, interface in enumerate(sys.lead_interfaces):
             lead = sys.leads[leadnum]
             if isinstance(lead, system.InfiniteSystem) and not force_realspace:
                 h = lead.slice_hamiltonian()
@@ -189,21 +190,21 @@ class SparseSolver(object):
                 # Construct a matrix of 1's that translates the
                 # inter-slice hopping to a proper hopping
                 # from the system to the lead.
-                neighbors = np.r_[tuple(np.arange(offsets[i], offsets[i + 1])
-                                        for i in lead_neighbors)]
-                coords = np.r_[[np.arange(neighbors.size)], [neighbors]]
-                tmp = sp.csc_matrix((np.ones(neighbors.size), coords),
-                                    shape=(neighbors.size, lhs.shape[0]))
+                iface_orbs = np.r_[tuple(slice(offsets[i], offsets[i + 1])
+                                        for i in interface)]
+                coords = np.r_[[np.arange(iface_orbs.size)], [iface_orbs]]
+                transf = sp.csc_matrix((np.ones(iface_orbs.size), coords),
+                                       shape=(iface_orbs.size, lhs.shape[0]))
 
                 if svd is not None:
-                    v_sp = sp.csc_matrix(svd[2].T.conj()) * tmp
-                    vdaguout_sp = tmp.T * sp.csc_matrix(np.dot(svd[2] * svd[1],
-                                                               u_out))
+                    v_sp = sp.csc_matrix(svd[2].T.conj()) * transf
+                    vdaguout_sp = transf.T * \
+                        sp.csc_matrix(np.dot(svd[2] * svd[1], u_out))
                     lead_mat = - ulinv_out
                 else:
-                    v_sp = tmp
-                    vdaguout_sp = tmp.T * sp.csc_matrix(np.dot(v.T.conj(),
-                                                               u_out))
+                    v_sp = transf
+                    vdaguout_sp = transf.T * sp.csc_matrix(np.dot(v.T.conj(),
+                                                                  u_out))
                     lead_mat = - ulinv_out
 
                 lhs = sp.bmat([[lhs, vdaguout_sp], [v_sp, lead_mat]],
@@ -211,10 +212,10 @@ class SparseSolver(object):
 
                 if leadnum in in_leads and nprop > 0:
                     if svd:
-                        vdaguin_sp = tmp.T * sp.csc_matrix(
+                        vdaguin_sp = transf.T * sp.csc_matrix(
                             -np.dot(svd[2] * svd[1], u_in))
                     else:
-                        vdaguin_sp = tmp.T * sp.csc_matrix(
+                        vdaguin_sp = transf.T * sp.csc_matrix(
                             -np.dot(v.T.conj(), u_in))
 
                     # defer formation of the real matrix until the proper
@@ -226,8 +227,8 @@ class SparseSolver(object):
             else:
                 sigma = lead.self_energy(energy)
                 lead_info.append(sigma)
-                indices = np.r_[tuple(range(offsets[i], offsets[i + 1]) for i
-                                      in lead_neighbors)]
+                indices = np.r_[tuple(slice(offsets[i], offsets[i + 1])
+                                      for i in interface)]
                 assert sigma.shape == 2 * indices.shape
                 y, x = np.meshgrid(indices, indices)
                 sig_sparse = splhsmat((sigma.flat, [x.flat, y.flat]),
@@ -321,7 +322,7 @@ class SparseSolver(object):
         expensive and can be less stable.
         """
 
-        n = len(sys.lead_neighbor_seqs)
+        n = len(sys.lead_interfaces)
         if in_leads is None:
             in_leads = range(n)
         if out_leads is None:
diff --git a/kwant/solvers/tests/_test_sparse.py b/kwant/solvers/tests/_test_sparse.py
index ed3aeb20..d95eb21c 100644
--- a/kwant/solvers/tests/_test_sparse.py
+++ b/kwant/solvers/tests/_test_sparse.py
@@ -229,10 +229,10 @@ def test_tricky_singular_hopping(solve):
     lead = kwant.Builder(kwant.TranslationalSymmetry([(4, 0)]))
     lead.default_site_group = system.default_site_group = square
 
-    neighbors = []
+    interface = []
     for i in xrange(n):
         site = square(-1, i)
-        neighbors.append(site)
+        interface.append(site)
         system[site] = 0
         for j in xrange(4):
             lead[j, i] = 0
@@ -245,7 +245,7 @@ def test_tricky_singular_hopping(solve):
             lead[(j, i), (j+1, i)] = -1
     del lead[(1, 0), (2, 0)]
 
-    system.leads.append(kwant.builder.BuilderLead(lead, neighbors))
+    system.leads.append(kwant.builder.BuilderLead(lead, interface))
     fsys = system.finalized()
 
     s = solve(fsys, -1.3)[0]
diff --git a/kwant/system.py b/kwant/system.py
index f2d130ab..9f64c36f 100644
--- a/kwant/system.py
+++ b/kwant/system.py
@@ -60,21 +60,21 @@ class FiniteSystem(System):
     leads : sequence of lead objects
         Each lead object has to provide at least a method
         ``self_energy(energy)``.
-    lead_neighbor_seqs : sequence of sequences of integers
+    lead_interfaces : sequence of sequences of integers
         Each sub-sequence contains the indices of the system sites to which the
         lead is connected.
 
     Notes
     -----
-    The length of `leads` must be equal to the length of `lead_neighbor_seqs`.
+    The length of `leads` must be equal to the length of `lead_interfaces`.
 
     For lead ``n``, the method leads[n].self_energy must return a square matrix
     whose size is ``sum(self.num_orbitals(neighbor) for neighbor in
-    self.lead_neighbor_seqs[n])``.
+    self.lead_interfaces[n])``.
 
     Often, the elements of `leads` will be instances of `InfiniteSystem`.  If
-    this is the case for lead ``n``, the sites ``lead_neighbor_seqs[n]`` match
-    the first ``len(lead_neighbor_seqs[n])`` sites of the InfiniteSystem.
+    this is the case for lead ``n``, the sites ``lead_interfaces[n]`` match
+    the first ``len(lead_interfaces[n])`` sites of the InfiniteSystem.
     """
     __metaclass__ = abc.ABCMeta
 
@@ -100,7 +100,7 @@ class InfiniteSystem(System):
     previous slice.  They are included so that hoppings between slices can be
     represented.  The N sites of the previous slice correspond to the first `N`
     sites of the fully included slice.  When an InfiniteSystem is used as a
-    lead, `N` acts also as the number of neighbors to which it must be
+    lead, `N` acts also as the number of interface sites to which it must be
     connected.
 
     The drawing shows three slices of an infinite system.  Each slice consists
diff --git a/kwant/tests/test_builder.py b/kwant/tests/test_builder.py
index c078ea7d..d162d720 100644
--- a/kwant/tests/test_builder.py
+++ b/kwant/tests/test_builder.py
@@ -288,8 +288,8 @@ def test_finalization():
     sys.leads.append(builder.BuilderLead(
             lead, (builder.Site(sg, n) for n in neighbors)))
     fsys = sys.finalized()
-    assert_equal(len(fsys.lead_neighbor_seqs), 1)
-    assert_equal([fsys.site(i).tag for i in fsys.lead_neighbor_seqs[0]],
+    assert_equal(len(fsys.lead_interfaces), 1)
+    assert_equal([fsys.site(i).tag for i in fsys.lead_interfaces[0]],
                  neighbors)
 
     # Add a hopping to the lead which couples two next-nearest slices and check
@@ -442,13 +442,13 @@ def test_attach_lead():
     sys[(0,)] = 1
     sys.attach_lead(lead0)
     assert_equal(len(list(sys.sites())), 3)
-    assert_equal(set(sys.leads[0].neighbors), set([gr(-1), gr(0)]))
+    assert_equal(set(sys.leads[0].interface), set([gr(-1), gr(0)]))
     sys[(-10,)] = sys[(-11,)] = 0
     sys.attach_lead(lead0)
-    assert_equal(set(sys.leads[1].neighbors), set([gr(-10), gr(-11)]))
+    assert_equal(set(sys.leads[1].interface), set([gr(-10), gr(-11)]))
     assert_equal(len(list(sys.sites())), 5)
     sys.attach_lead(lead0, gr(-5))
-    assert_equal(set(sys.leads[0].neighbors), set([gr(-1), gr(0)]))
+    assert_equal(set(sys.leads[0].interface), set([gr(-1), gr(0)]))
     sys.finalized()
 
 
-- 
GitLab