From 5d445f475eae50f17e8acc909349ac3bdf912fc8 Mon Sep 17 00:00:00 2001
From: Anton Akhmerov <anton.akhmerov@gmail.com>
Date: Wed, 24 Apr 2013 15:01:05 -0400
Subject: [PATCH] remove an option to pass kwargs to System.Hamiltonian

---
 doc/source/images/ab_ring.py.diff      |  2 +-
 doc/source/images/quantum_well.py.diff |  2 +-
 doc/source/tutorial/ab_ring.py         |  2 +-
 doc/source/tutorial/closed_system.py   |  2 +-
 doc/source/tutorial/quantum_well.py    |  2 +-
 doc/source/tutorial/tutorial2.rst      |  9 +++----
 doc/source/whatsnew/0.3.rst            | 33 ++++++++++++++++-------
 kwant/_system.pyx                      | 32 +++++++++++-----------
 kwant/builder.py                       | 12 ++++-----
 kwant/physics/dispersion.py            |  8 +++---
 kwant/physics/tests/test_noise.py      |  3 +--
 kwant/plotter.py                       |  8 +++---
 kwant/solvers/common.py                | 37 +++++++++-----------------
 kwant/solvers/tests/_test_sparse.py    |  3 +--
 kwant/system.py                        | 26 ++++++++----------
 kwant/tests/test_system.py             |  2 +-
 16 files changed, 87 insertions(+), 96 deletions(-)

diff --git a/doc/source/images/ab_ring.py.diff b/doc/source/images/ab_ring.py.diff
index d954155..d1adc09 100644
--- a/doc/source/images/ab_ring.py.diff
+++ b/doc/source/images/ab_ring.py.diff
@@ -80,7 +80,7 @@
      # compute conductance
  
 @@ -87,18 +133,29 @@
-         smatrix = kwant.solve(sys, energy, kwargs={'phi': flux})
+         smatrix = kwant.solve(sys, energy, args=[flux])
          data.append(smatrix.transmission(1, 0))
  
 -    pyplot.figure()
diff --git a/doc/source/images/quantum_well.py.diff b/doc/source/images/quantum_well.py.diff
index 1b62946..7d64ca0 100644
--- a/doc/source/images/quantum_well.py.diff
+++ b/doc/source/images/quantum_well.py.diff
@@ -9,7 +9,7 @@
  
  def make_system(a=1, t=1.0, W=10, L=30, L_well=10):
 @@ -52,19 +53,25 @@
-         smatrix = kwant.solve(sys, energy, kwargs={'pot': -welldepth})
+         smatrix = kwant.solve(sys, energy, args=[-welldepth])
          data.append(smatrix.transmission(1, 0))
  
 -    pyplot.figure()
diff --git a/doc/source/tutorial/ab_ring.py b/doc/source/tutorial/ab_ring.py
index 827ae81..1877973 100644
--- a/doc/source/tutorial/ab_ring.py
+++ b/doc/source/tutorial/ab_ring.py
@@ -94,7 +94,7 @@ def plot_conductance(sys, energy, fluxes):
     normalized_fluxes = [flux / (2 * pi) for flux in fluxes]
     data = []
     for flux in fluxes:
-        smatrix = kwant.solve(sys, energy, kwargs={'phi': flux})
+        smatrix = kwant.solve(sys, energy, args=[flux])
         data.append(smatrix.transmission(1, 0))
 
     pyplot.figure()
diff --git a/doc/source/tutorial/closed_system.py b/doc/source/tutorial/closed_system.py
index 8b46ece..c649c87 100644
--- a/doc/source/tutorial/closed_system.py
+++ b/doc/source/tutorial/closed_system.py
@@ -63,7 +63,7 @@ def plot_spectrum(sys, Bfields):
     energies = []
     for B in Bfields:
         # Obtain the Hamiltonian as a dense matrix
-        ham_mat = sys.hamiltonian_submatrix(sparse=True, kwargs={'B': B})
+        ham_mat = sys.hamiltonian_submatrix(sparse=True, args=[B])
 
         # we only calculate the 15 lowest eigenvalues
         ev = sla.eigsh(ham_mat, k=15, which='SM', return_eigenvectors=False)
diff --git a/doc/source/tutorial/quantum_well.py b/doc/source/tutorial/quantum_well.py
index 81d0631..a41cbf3 100644
--- a/doc/source/tutorial/quantum_well.py
+++ b/doc/source/tutorial/quantum_well.py
@@ -54,7 +54,7 @@ def plot_conductance(sys, energy, welldepths):
     # Compute conductance
     data = []
     for welldepth in welldepths:
-        smatrix = kwant.solve(sys, energy, kwargs={'pot': -welldepth})
+        smatrix = kwant.solve(sys, energy, args=[-welldepth])
         data.append(smatrix.transmission(1, 0))
 
     pyplot.figure()
diff --git a/doc/source/tutorial/tutorial2.rst b/doc/source/tutorial/tutorial2.rst
index 094d663..39e473c 100644
--- a/doc/source/tutorial/tutorial2.rst
+++ b/doc/source/tutorial/tutorial2.rst
@@ -179,11 +179,10 @@ Finally, we compute the transmission probability:
     :start-after: #HIDDEN_BEGIN_sqvr
     :end-before: #HIDDEN_END_sqvr
 
-``kwant.solve`` allows us to specify a dictionary, `kwargs`, that will be
-passed as additional keyword arguments to the functions that provide the
-Hamiltonian matrix elements.  In this example we are able to solve the system
-for different depths of the potential well by passing the keyword argument
-`pot`. We obtain the result:
+``kwant.solve`` allows us to specify a list, `args`, that will be passed as
+additional arguments to the functions that provide the Hamiltonian matrix
+elements.  In this example we are able to solve the system for different depths
+of the potential well by passing the potential value. We obtain the result:
 
 .. image:: ../images/quantum_well_result.*
 
diff --git a/doc/source/whatsnew/0.3.rst b/doc/source/whatsnew/0.3.rst
index dd82bc8..a99b3fc 100644
--- a/doc/source/whatsnew/0.3.rst
+++ b/doc/source/whatsnew/0.3.rst
@@ -75,16 +75,12 @@ regular function parameters (e.g. global variables).
 
 Now the value functions may accept arbitrary arguments after the `Site`
 arguments.  These extra arguments can be specified when
-`~kwant.solvers.default.solve` is called by setting the keyword arguments:
+`~kwant.solvers.default.solve` is called by setting the arguments:
 
 args
     A tuple of values to be passed as the positional arguments to the
     Hamiltonian value functions (not including the `Site` arguments).
 
-kwargs
-    A dictionary of keyword-value pairs to be passed as the keyword
-    arguments to the Hamiltonian value functions.
-
 For example, if the hopping and onsite Hamiltonian value functions have
 the following prototype::
 
@@ -97,11 +93,30 @@ the following prototype::
 then the values of `t`, `B` and `pot` for which to solve the system can be
 passed to `solve` like this::
 
-    time = 2
-    magnetic_field = 3
-    potential = 4
     kwant.solve(sys, energy,
-                args=(time,), kwargs={'B': magnetic_field, 'pot': potential})
+                args=(2., 3., 4.))
+
+A more verbose way to do the same is to pass to the functions an object,
+containing all the parameters as attributes::
+
+    class SimpleNamespace(object):
+        def __init__(self, **kwargs):
+            self.__dict__.update(kwargs)
+    # With Python >= 3.3 we can have instead:
+    # from types import SimpleNamespace
+
+    params = SimpleNamespace()
+
+    def onsite(site, p):
+        mu = p.mu
+        ...
+
+    def hopping(site1, site2, p):
+        t, B = p.t, p.B
+        ...
+
+    kwant.solve(sys, energy,
+                args=(params(t=1., mu=2., B=0.1))
 
 Arguments can be passed in an equivalent way in calls to
 `~kwant.solvers.default.wave_function` and `~kwant.solvers.default.ldos`.
diff --git a/kwant/_system.pyx b/kwant/_system.pyx
index 17a1b82..ee263b9 100644
--- a/kwant/_system.pyx
+++ b/kwant/_system.pyx
@@ -20,7 +20,7 @@ msg = 'Hopping from site {0} to site {1} does not match the ' \
     'dimensions of onsite Hamiltonians of these sites.'
 
 @cython.boundscheck(False)
-def make_sparse(ham, args, kwargs, CGraph gr, diag,
+def make_sparse(ham, args, CGraph gr, diag,
                 gint [:] from_sites, n_by_to_site,
                 gint [:] to_norb, gint [:] to_off,
                 gint [:] from_norb, gint [:] from_off):
@@ -69,7 +69,7 @@ def make_sparse(ham, args, kwargs, CGraph gr, diag,
             if ts not in n_by_to_site:
                 continue
             n_ts = n_by_to_site[ts]
-            h = matrix(ham(ts, fs, *args, **kwargs), complex)
+            h = matrix(ham(ts, fs, *args), complex)
             if h.shape[0] != to_norb[n_ts] or h.shape[1] != from_norb[n_fs]:
                 raise ValueError(msg.format(fs, ts))
             for i in xrange(h.shape[0]):
@@ -83,7 +83,7 @@ def make_sparse(ham, args, kwargs, CGraph gr, diag,
 
 
 @cython.boundscheck(False)
-def make_sparse_full(ham, args, kwargs, CGraph gr, diag,
+def make_sparse_full(ham, args, CGraph gr, diag,
                      gint [:] to_norb, gint [:] to_off,
                      gint [:] from_norb, gint [:] from_off):
     """For internal use by hamiltonian_submatrix."""
@@ -125,7 +125,7 @@ def make_sparse_full(ham, args, kwargs, CGraph gr, diag,
         for ts in nbors.data[:nbors.size]:
             if ts < fs:
                 continue
-            h = matrix(ham(ts, fs, *args, **kwargs), complex)
+            h = matrix(ham(ts, fs, *args), complex)
             if h.shape[0] != to_norb[ts] or h.shape[1] != from_norb[fs]:
                 raise ValueError(msg.format(fs, ts))
             for i in xrange(h.shape[0]):
@@ -140,7 +140,7 @@ def make_sparse_full(ham, args, kwargs, CGraph gr, diag,
 
 
 @cython.boundscheck(False)
-def make_dense(ham, args, kwargs, CGraph gr, diag,
+def make_dense(ham, args, CGraph gr, diag,
                gint [:] from_sites, n_by_to_site,
                gint [:] to_norb, gint [:] to_off,
                gint [:] from_norb, gint [:] from_off):
@@ -169,7 +169,7 @@ def make_dense(ham, args, kwargs, CGraph gr, diag,
             if ts not in n_by_to_site:
                 continue
             n_ts = n_by_to_site[ts]
-            h = matrix(ham(ts, fs, *args, **kwargs), complex)
+            h = matrix(ham(ts, fs, *args), complex)
             if h.shape[0] != to_norb[n_ts] or h.shape[1] != from_norb[n_fs]:
                 raise ValueError(msg.format(fs, ts))
             h_sub_view[to_off[n_ts] : to_off[n_ts + 1],
@@ -178,7 +178,7 @@ def make_dense(ham, args, kwargs, CGraph gr, diag,
 
 
 @cython.boundscheck(False)
-def make_dense_full(ham, args, kwargs, CGraph gr, diag,
+def make_dense_full(ham, args, CGraph gr, diag,
                     gint [:] to_norb, gint [:] to_off,
                     gint [:] from_norb, gint [:] from_off):
     """For internal use by hamiltonian_submatrix."""
@@ -202,7 +202,7 @@ def make_dense_full(ham, args, kwargs, CGraph gr, diag,
         for ts in nbors.data[:nbors.size]:
             if ts < fs:
                 continue
-            h = mat = matrix(ham(ts, fs, *args, **kwargs), complex)
+            h = mat = matrix(ham(ts, fs, *args), complex)
             h_herm = mat.transpose().conjugate()
             if h.shape[0] != to_norb[ts] or h.shape[1] != from_norb[fs]:
                 raise ValueError(msg.format(fs, ts))
@@ -215,7 +215,7 @@ def make_dense_full(ham, args, kwargs, CGraph gr, diag,
 
 def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
                           sparse=False, return_norb=False,
-                          args=(), kwargs={}):
+                          args=()):
     """Return a submatrix of the system Hamiltonian.
 
     Parameters
@@ -228,8 +228,6 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
         Whether to return arrays of numbers of orbitals.  Defaults to `False`.
     args : tuple, defaults to empty
         Positional arguments to pass to the ``hamiltonian`` method.
-    kwargs : dictionary, defaults to empty
-        Keyword arguments to pass to the ``hamiltonian`` method.
 
     Returns
     -------
@@ -260,7 +258,7 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
         diag = n * [None]
         from_norb = np.empty(n, gint_dtype)
         for site in xrange(n):
-            diag[site] = h = matrix(ham(site, site, *args, **kwargs), complex)
+            diag[site] = h = matrix(ham(site, site, *args), complex)
             from_norb[site] = h.shape[0]
     else:
         diag = len(from_sites) * [None]
@@ -268,7 +266,7 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
         for n_site, site in enumerate(from_sites):
             if site < 0 or site >= n:
                 raise IndexError('Site number out of range.')
-            diag[n_site] = h = matrix(ham(site, site, *args, **kwargs),
+            diag[n_site] = h = matrix(ham(site, site, *args),
                                       complex)
             from_norb[n_site] = h.shape[0]
     from_off = np.empty(from_norb.shape[0] + 1, gint_dtype)
@@ -282,14 +280,14 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
         if to_sites is None:
             to_norb = np.empty(n, gint_dtype)
             for site in xrange(n):
-                h = matrix(ham(site, site, *args, **kwargs), complex)
+                h = matrix(ham(site, site, *args), complex)
                 to_norb[site] = h.shape[0]
         else:
             to_norb = np.empty(len(to_sites), gint_dtype)
             for n_site, site in enumerate(to_sites):
                 if site < 0 or site >= n:
                     raise IndexError('Site number out of range.')
-                h = matrix(ham(site, site, *args, **kwargs), complex)
+                h = matrix(ham(site, site, *args), complex)
                 to_norb[n_site] = h.shape[0]
         to_off = np.empty(to_norb.shape[0] + 1, gint_dtype)
         to_off[0] = 0
@@ -298,7 +296,7 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
 
     if to_sites is from_sites is None:
         func = make_sparse_full if sparse else make_dense_full
-        mat = func(ham, args, kwargs, self.graph, diag, to_norb, to_off,
+        mat = func(ham, args, self.graph, diag, to_norb, to_off,
                    from_norb, from_off)
     else:
         if to_sites is None:
@@ -314,6 +312,6 @@ def hamiltonian_submatrix(self, to_sites=None, from_sites=None,
             from_sites = np.asarray(from_sites, gint_dtype)
 
         func = make_sparse if sparse else make_dense
-        mat = func(ham, args, kwargs, self.graph, diag, from_sites,
+        mat = func(ham, args, self.graph, diag, from_sites,
                    n_by_to_site, to_norb, to_off, from_norb, from_off)
     return (mat, to_norb, from_norb) if return_norb else mat
diff --git a/kwant/builder.py b/kwant/builder.py
index 660ae1d..4c945d9 100644
--- a/kwant/builder.py
+++ b/kwant/builder.py
@@ -1226,12 +1226,12 @@ class FiniteSystem(system.FiniteSystem):
 
     Usable as input for the solvers in `kwant.solvers`.
     """
-    def hamiltonian(self, i, j, *args, **kwargs):
+    def hamiltonian(self, i, j, *args):
         if i == j:
             value = self.onsite_hamiltonians[i]
             if hasattr(value, '__call__'):
                 value = value(self.symmetry.to_fd(self.sites[i]),
-                                                  *args, **kwargs)
+                                                  *args)
             return value
         else:
             edge_id = self.graph.first_edge_id(i, j)
@@ -1245,7 +1245,7 @@ class FiniteSystem(system.FiniteSystem):
                 site_i = self.sites[i]
                 site_j = self.sites[j]
                 site_i, site_j = self.symmetry.to_fd(site_i,site_j)
-                value = value(site_i, site_j, *args, **kwargs)
+                value = value(site_i, site_j, *args)
             if conj:
                 value = herm_conj(value)
             return value
@@ -1259,14 +1259,14 @@ class FiniteSystem(system.FiniteSystem):
 
 class InfiniteSystem(system.InfiniteSystem):
     """Finalized infinite system, extracted from a `Builder`."""
-    def hamiltonian(self, i, j, *args, **kwargs):
+    def hamiltonian(self, i, j, *args):
         if i == j:
             if i >= self.slice_size:
                 i -= self.slice_size
             value = self.onsite_hamiltonians[i]
             if hasattr(value, '__call__'):
                 value = value(self.symmetry.to_fd(self.sites[i]),
-                                                  *args, **kwargs)
+                                                  *args)
             return value
         else:
             edge_id = self.graph.first_edge_id(i, j)
@@ -1280,7 +1280,7 @@ class InfiniteSystem(system.InfiniteSystem):
                 site_i = self.sites[i]
                 site_j = self.sites[j]
                 site_i, site_j = self.symmetry.to_fd(site_i, site_j)
-                value = value(site_i, site_j, *args, **kwargs)
+                value = value(site_i, site_j, *args)
             if conj:
                 value = herm_conj(value)
             return value
diff --git a/kwant/physics/dispersion.py b/kwant/physics/dispersion.py
index 61562a0..a951424 100644
--- a/kwant/physics/dispersion.py
+++ b/kwant/physics/dispersion.py
@@ -22,8 +22,6 @@ class Bands(object):
         calculated.
     args : tuple, defaults to empty
         Positional arguments to pass to the ``hamiltonian`` method.
-    kwargs : dictionary, defaults to empty
-        Keyword arguments to pass to the ``hamiltonian`` method.
 
     Notes
     -----
@@ -41,11 +39,11 @@ class Bands(object):
     >>> pyplot.show()
     """
 
-    def __init__(self, sys, args=(), kwargs={}):
-        self.ham = sys.slice_hamiltonian(args=args, kwargs=kwargs)
+    def __init__(self, sys, args=()):
+        self.ham = sys.slice_hamiltonian(args=args)
         if not np.allclose(self.ham, self.ham.T.conj()):
             raise ValueError('The slice Hamiltonian is not Hermitian.')
-        hop = sys.inter_slice_hopping(args=args, kwargs=kwargs)
+        hop = sys.inter_slice_hopping(args=args)
         self.hop = np.empty(self.ham.shape, dtype=complex)
         self.hop[:, : hop.shape[1]] = hop
         self.hop[:, hop.shape[1]:] = 0
diff --git a/kwant/physics/tests/test_noise.py b/kwant/physics/tests/test_noise.py
index a8bcb27..bf5f1d5 100644
--- a/kwant/physics/tests/test_noise.py
+++ b/kwant/physics/tests/test_noise.py
@@ -43,9 +43,8 @@ class LeadWithOnlySelfEnergy(object):
     def __init__(self, lead):
         self.lead = lead
 
-    def self_energy(self, energy, args=(), kwargs={}):
+    def self_energy(self, energy, args=()):
         assert args == ()
-        assert kwargs == {}
         return self.lead.self_energy(energy)
 
 
diff --git a/kwant/plotter.py b/kwant/plotter.py
index f8a726c..2b68dc7 100644
--- a/kwant/plotter.py
+++ b/kwant/plotter.py
@@ -861,8 +861,8 @@ def map(sys, value, colorbar=True, cmap=None, vmin=None, vmax=None,
     return output_fig(fig, file=file, show=show)
 
 
-def bands(sys, momenta=65, args=(), kwargs={},
-          file=None, show=True, dpi=None, fig_size=None):
+def bands(sys, momenta=65, args=(), file=None, show=True, dpi=None,
+          fig_size=None):
     """Plot band structure of a translationally invariant 1D system.
 
     Parameters
@@ -871,8 +871,6 @@ def bands(sys, momenta=65, args=(), kwargs={},
         A system bands of which are to be plotted.
     args : tuple, defaults to empty
         Positional arguments to pass to the ``hamiltonian`` method.
-    kwargs : dictionary, defaults to empty
-        Keyword arguments to pass to the ``hamiltonian`` method.
     momenta : int or 1D array-like
         Either a number of sampling points on the interval [-pi, pi], or an
         array of points at which the band structure has to be evaluated.
@@ -901,7 +899,7 @@ def bands(sys, momenta=65, args=(), kwargs={},
     if momenta.ndim != 1:
         momenta = np.linspace(-np.pi, np.pi, momenta)
 
-    bands = physics.Bands(sys, args=args, kwargs=kwargs)
+    bands = physics.Bands(sys, args=args)
     energies = [bands(k) for k in momenta]
 
     fig = Figure()
diff --git a/kwant/solvers/common.py b/kwant/solvers/common.py
index 1c4d42f..b8d25e9 100644
--- a/kwant/solvers/common.py
+++ b/kwant/solvers/common.py
@@ -93,7 +93,7 @@ class SparseSolver(object):
 
     def _make_linear_sys(self, sys, out_leads, in_leads, energy=0,
                         force_realspace=False, check_hermiticity=True,
-                        args=(), kwargs={}):
+                        args=()):
         """
         Make a sparse linear system of equations defining a scattering
         problem.
@@ -117,8 +117,6 @@ class SparseSolver(object):
             Check if Hamiltonian matrices are in fact Hermitian.
         args : tuple, defaults to empty
             Positional arguments to pass to the ``hamiltonian`` method.
-        kwargs : dictionary, defaults to empty
-            Keyword arguments to pass to the ``hamiltonian`` method.
 
         Returns
         -------
@@ -150,7 +148,7 @@ class SparseSolver(object):
             raise ValueError('System contains no leads.')
         lhs, norb = sys.hamiltonian_submatrix(sparse=True,
                                               return_norb=True,
-                                              args=args, kwargs=kwargs)[:2]
+                                              args=args)[:2]
         lhs = getattr(lhs, 'to' + self.lhsformat)()
         lhs = lhs - energy * sp.identity(lhs.shape[0], format=self.lhsformat)
 
@@ -171,7 +169,7 @@ class SparseSolver(object):
         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(args=args, kwargs=kwargs)
+                h = lead.slice_hamiltonian(args=args)
 
                 if check_hermiticity:
                     if not np.allclose(h, h.T.conj(), rtol=1e-13):
@@ -180,7 +178,7 @@ class SparseSolver(object):
                         raise ValueError(msg.format(leadnum))
 
                 h -= energy * np.identity(h.shape[0])
-                v = lead.inter_slice_hopping(args=args, kwargs=kwargs)
+                v = lead.inter_slice_hopping(args=args)
                 modes = physics.modes(h, v)
                 lead_info.append(modes)
 
@@ -237,7 +235,7 @@ class SparseSolver(object):
                     # See comment about zero-shaped sparse matrices at the top.
                     rhs.append(np.zeros((lhs.shape[1], 0)))
             else:
-                sigma = lead.self_energy(energy, args, kwargs)
+                sigma = lead.self_energy(energy, args)
                 lead_info.append(sigma)
                 indices = np.r_[tuple(slice(offsets[i], offsets[i + 1])
                                       for i in interface)]
@@ -280,7 +278,7 @@ class SparseSolver(object):
 
     def solve(self, sys, energy=0, out_leads=None, in_leads=None,
               force_realspace=False, check_hermiticity=True,
-              args=(), kwargs={}):
+              args=()):
         """
         Compute the scattering matrix or Green's function between leads.
 
@@ -307,8 +305,6 @@ class SparseSolver(object):
             Check if the Hamiltonian matrices are Hermitian.
         args : tuple, defaults to empty
             Positional arguments to pass to the ``hamiltonian`` method.
-        kwargs : dictionary, defaults to empty
-            Keyword arguments to pass to the ``hamiltonian`` method.
 
         Returns
         -------
@@ -360,8 +356,7 @@ class SparseSolver(object):
 
         linsys, lead_info = self._make_linear_sys(sys, out_leads, in_leads,
                                                   energy, force_realspace,
-                                                  check_hermiticity,
-                                                  args, kwargs)
+                                                  check_hermiticity, args)
 
         # Do not perform factorization if no calculation is to be done.
         len_rhs = sum(i.shape[1] for i in linsys.rhs)
@@ -379,7 +374,7 @@ class SparseSolver(object):
         return BlockResult(data, lead_info, out_leads, in_leads)
 
 
-    def ldos(self, fsys, energy=0, args=(), kwargs={}):
+    def ldos(self, fsys, energy=0, args=()):
         """
         Calculate the local density of states of a system at a given energy.
 
@@ -393,9 +388,6 @@ class SparseSolver(object):
         args : tuple of arguments, or empty tuple
             Positional arguments to pass to the function(s) which
             evaluate the hamiltonian matrix elements
-        kwargs : dictionary of keyword, argument pairs or empty dictionary
-            Optional keyword arguments to pass to the function(s) which
-            evaluate the hamiltonian matrix elements
 
         Returns
         -------
@@ -410,7 +402,7 @@ class SparseSolver(object):
 
         (h, rhs, kept_vars), lead_info = \
             self._make_linear_sys(fsys, [], xrange(len(fsys.leads)), energy,
-                                  args=args, kwargs=kwargs)
+                                  args=args)
 
         Modes = physics.Modes
         num_extra_vars = sum(li.vecs.shape[1] - li.nmodes
@@ -435,7 +427,7 @@ class SparseSolver(object):
 
         return ldos * (0.5 / np.pi)
 
-    def wave_function(self, sys, energy=0, args=(), kwargs={}):
+    def wave_function(self, sys, energy=0, args=()):
         """
         Return a callable object for the computation of the wave function
         inside the scattering region.
@@ -448,9 +440,6 @@ class SparseSolver(object):
         args : tuple of arguments, or empty tuple
             Positional arguments to pass to the function(s) which
             evaluate the hamiltonian matrix elements
-        kwargs : dictionary of keyword, argument pairs or empty dictionary
-            Optional keyword arguments to pass to the function(s) which
-            evaluate the hamiltonian matrix elements
 
         Notes
         -----
@@ -465,11 +454,11 @@ class SparseSolver(object):
         >>> wf = kwant.solvers.default.wave_function(some_sys, some_energy)
         >>> wfs_of_lead_2 = wf(2)
         """
-        return WaveFunction(self, sys, energy, args, kwargs)
+        return WaveFunction(self, sys, energy, args)
 
 
 class WaveFunction(object):
-    def __init__(self, solver, sys, energy=0, args=(), kwargs={}):
+    def __init__(self, solver, sys, energy=0, args=()):
         for lead in sys.leads:
             if not isinstance(lead, system.InfiniteSystem):
                 # TODO: fix this
@@ -477,7 +466,7 @@ class WaveFunction(object):
                 raise ValueError(msg)
         (h, self.rhs, kept_vars), lead_info = \
             solver._make_linear_sys(sys, [], xrange(len(sys.leads)),
-                                    energy, args=args, kwargs=kwargs)
+                                    energy, args=args)
         Modes = physics.Modes
         num_extra_vars = sum(li.vecs.shape[1] - li.nmodes
                              for li in lead_info if isinstance(li, Modes))
diff --git a/kwant/solvers/tests/_test_sparse.py b/kwant/solvers/tests/_test_sparse.py
index c6b10d8..710dfc3 100644
--- a/kwant/solvers/tests/_test_sparse.py
+++ b/kwant/solvers/tests/_test_sparse.py
@@ -21,9 +21,8 @@ class LeadWithOnlySelfEnergy(object):
     def __init__(self, lead):
         self.lead = lead
 
-    def self_energy(self, energy, args=(), kwargs={}):
+    def self_energy(self, energy, args=()):
         assert args == ()
-        assert kwargs == {}
         return self.lead.self_energy(energy)
 
 
diff --git a/kwant/system.py b/kwant/system.py
index 44d7ad1..1d6fd10 100644
--- a/kwant/system.py
+++ b/kwant/system.py
@@ -35,17 +35,17 @@ class System(object):
     """
     __metaclass__ = abc.ABCMeta
 
-    def num_orbitals(self, site, *args, **kwargs):
+    def num_orbitals(self, site, *args):
         """Return the number of orbitals of a site.
 
         This is an inefficient general implementation.  It should be
         overridden, if a more efficient way to calculate is available.
         """
-        ham = self.hamiltonian(site, site, *args, **kwargs)
+        ham = self.hamiltonian(site, site, *args)
         return 1 if np.isscalar(ham) else ham.shape[0]
 
     @abc.abstractmethod
-    def hamiltonian(self, i, j, *args, **kwargs):
+    def hamiltonian(self, i, j, *args):
         """Return the hamiltonian matrix element for sites `i` and `j`.
 
         If ``i == j``, return the on-site Hamiltonian of site `i`.
@@ -68,8 +68,7 @@ class FiniteSystem(System):
     Instance Variables
     ------------------
     leads : sequence of lead objects
-        Each lead object has to provide a method
-        ``self_energy(energy, args, kwargs)``.
+        Each lead object has to provide a method ``self_energy(energy, args)``.
     lead_interfaces : sequence of sequences of integers
         Each sub-sequence contains the indices of the system sites to which the
         lead is connected.
@@ -133,32 +132,29 @@ class InfiniteSystem(System):
     """
     __metaclass__ = abc.ABCMeta
 
-    def slice_hamiltonian(self, sparse=False, args=(), kwargs={}):
+    def slice_hamiltonian(self, sparse=False, args=()):
         """Hamiltonian of a single slice of the infinite system."""
         slice_sites = xrange(self.slice_size)
         return self.hamiltonian_submatrix(slice_sites, slice_sites,
-                                          sparse=sparse, args=args,
-                                          kwargs=kwargs)
+                                          sparse=sparse, args=args)
 
-    def inter_slice_hopping(self, sparse=False, args=(), kwargs={}):
+    def inter_slice_hopping(self, sparse=False, args=()):
         """Hopping Hamiltonian between two slices of the infinite system."""
         slice_sites = xrange(self.slice_size)
         neighbor_sites = xrange(self.slice_size, self.graph.num_nodes)
         return self.hamiltonian_submatrix(slice_sites, neighbor_sites,
-                                          sparse=sparse, args=args,
-                                          kwargs=kwargs)
+                                          sparse=sparse, args=args)
 
-    def self_energy(self, energy, args=(), kwargs={}):
+    def self_energy(self, energy, args=()):
         """Return self-energy of a lead.
 
         The returned matrix has the shape (n, n), where n is
         ``sum(self.num_orbitals(i) for i in range(self.slice_size))``.
         """
-        ham = self.slice_hamiltonian(args=args, kwargs=kwargs)
+        ham = self.slice_hamiltonian(args=args)
         shape = ham.shape
         assert len(shape) == 2
         assert shape[0] == shape[1]
         # Subtract energy from the diagonal.
         ham.flat[::ham.shape[0] + 1] -= energy
-        return physics.self_energy(ham, self.inter_slice_hopping(args=args,
-                                                                 kwargs=kwargs))
+        return physics.self_energy(ham, self.inter_slice_hopping(args=args))
diff --git a/kwant/tests/test_system.py b/kwant/tests/test_system.py
index 58664bb..72d1caf 100644
--- a/kwant/tests/test_system.py
+++ b/kwant/tests/test_system.py
@@ -77,7 +77,7 @@ def test_hamiltonian_submatrix():
     sys[(gr(i) for i in xrange(3))] = onsite
     sys[((gr(i), gr(i + 1)) for i in xrange(2))] = hopping
     sys2 = sys.finalized()
-    mat = sys2.hamiltonian_submatrix(args=(2,), kwargs={'p2': 1})
+    mat = sys2.hamiltonian_submatrix(args=(2, 1))
     mat_should_be = [[5, 1, 0], [1, 4, 1.], [0, 1, 3]]
 
     # Sorting is required due to unknown compression order of builder.
-- 
GitLab