0% found this document useful (0 votes)
363 views

Kwant 1.3.1 Documentation: C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, Et Al

manual de Kwant

Uploaded by

Ferzz Montejo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
363 views

Kwant 1.3.1 Documentation: C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, Et Al

manual de Kwant

Uploaded by

Ferzz Montejo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 169

Kwant 1.3.

1 documentation
Release 1.3.1

C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, et al.

Sep 11, 2017


CONTENTS

1 Preliminaries 1
1.1 About Kwant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 What’s new in Kwant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.3 Installation of Kwant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.4 Authors of Kwant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.5 Citing Kwant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.6 Contributing to Kwant and reporting problems . . . . . . . . . . . . . . . . . . . . . . . . 17
1.7 Kwant license . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2 Tutorial: learning Kwant through examples 19


2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 First steps: setting up a simple system and computing conductance . . . . . . . . . . . . 20
2.3 More interesting systems: spin, potential, shape . . . . . . . . . . . . . . . . . . . . . . . 28
2.4 Beyond transport: Band structure and closed systems . . . . . . . . . . . . . . . . . . . . 38
2.5 Beyond square lattices: graphene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.6 Superconductors: orbital degrees of freedom, conservation laws and symmetries . . . . . . 50
2.7 Computing local quantities: densities and currents . . . . . . . . . . . . . . . . . . . . . . 55
2.8 Plotting Kwant systems and data in various styles . . . . . . . . . . . . . . . . . . . . . . 63
2.9 Calculating spectral density with the kernel polynomial method . . . . . . . . . . . . . . 72
2.10 Discretizing continuous Hamiltonians . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

3 Core modules 85
3.1 kwant – Top level package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
3.2 kwant.builder – High-level construction of systems . . . . . . . . . . . . . . . . . . . . . 86
3.3 kwant.lattice – Bravais lattices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.4 kwant.plotter – Plotting of systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
3.5 kwant.solvers – Library of solvers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
3.6 kwant.operator – Operators and Observables . . . . . . . . . . . . . . . . . . . . . . . . 122
3.7 kwant.physics – Physics-related algorithms . . . . . . . . . . . . . . . . . . . . . . . . . 128

4 Other modules 135


4.1 kwant.digest – Random-access random numbers . . . . . . . . . . . . . . . . . . . . . . 135
4.2 kwant.rmt – Random matrix theory Hamiltonians . . . . . . . . . . . . . . . . . . . . . . 135
4.3 kwant.kpm – Kernel Polynomial Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
4.4 kwant.continuum – Tools for continuum systems . . . . . . . . . . . . . . . . . . . . . . . 139
4.5 kwant.wraparound – Wrapping around translational symmetries . . . . . . . . . . . . . . 143

5 Modules mainly for internal use 147


5.1 kwant.system – Low-level interface of systems . . . . . . . . . . . . . . . . . . . . . . . . 147
5.2 kwant.graph – Low-level, efficient directed graphs . . . . . . . . . . . . . . . . . . . . . . 153
5.3 kwant.linalg – Linear algebra routines . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

Bibliography 161

i
ii
CHAPTER

ONE

PRELIMINARIES

1.1 About Kwant

Kwant is a free (open source) Python package for numerical calculations on tight-binding models with
a strong focus on quantum transport. It is designed to be flexible and easy to use. Thanks to the use
of innovative algorithms, Kwant is often faster than other available codes, even those entirely written in
the low level FORTRAN and C/C++ languages.
Tight-binding models can describe a vast variety of systems and phenomena in quantum physics. There-
fore, Kwant can be used to simulate
• metals,
• graphene,
• topological insulators,
• quantum Hall effect,
• superconductivity,
• spintronics,
• molecular electronics,
• any combination of the above, and many other things.
Kwant can calculate
• transport properties (conductance, noise, scattering matrix),
• dispersion relations,
• modes,
• wave functions,
• various Green’s functions,
• out-of-equilibrium local quantities.
Other computations involving tight-binding Hamiltonians can be implemented easily.

1.2 What’s new in Kwant

1.2.1 What’s new in Kwant 1.3

This article explains the user-visible changes in Kwant 1.3.0, released on 19 May 2017. See also the full
list of changes up to the most recent bugfix release of the 1.3 series.

1
Kwant 1.3.1 documentation

Using high-symmetry builders as models

Builders now have a fill method that fills a builder instance with copies of a template builder. This
can be used to “cut out” shapes from high-symmetry models, or to increase the symmetry period of a
lead.
Thus Kwant gains the new concept of a “model”. Models may be created manually, or with the new
function kwant.continuum.discretize (see next paragraph). There is also support for finalizing models
and e.g. calculating their band structure (see Finalizing builders with multiple translational symmetries).

Tools for continuum Hamiltonians

The new sub-package continuum is a collection of tools for working with continuum models and for
discretizing them into tight-binding models. It aims at providing a handy interface to convert symbolic
Hamiltonians into a builder with N-D translational symmetry that can be use to calculate tight-binding
band structures or construct systems with different/lower symmetry. For example in just a few lines we
can construct a two-band model that exhibits a quantum anomalous spin Hall phase:

def make_model(a):
ham = ("alpha * (k_x * sigma_x - k_y * sigma_y)"
"+ (m + beta * kk) * sigma_z"
"+ (gamma * kk + U) * sigma_0")
subs = {"kk": "k_x**2 + k_y**2"}
return kwant.continuum.discretize(ham, locals=subs, grid_spacing=a)

From: QAHE example script


See the tutorial: Discretizing continuous Hamiltonians
See the reference documentation: kwant.continuum – Tools for continuum systems

Calculating charges and currents using the operator module

Often one may wish to calculate quantities that are defined over sites of the system (such as charge
density, spin density along some axis etc), or over hoppings of the system (such as current or spin
current). With the introduction of the operator module it has now become much easier to calculate
such quantities. To obtain the regular density and current everywhere in a system due to a wavefunction
psi, one only needs to do the following:

syst = make_system().finalized()
psi = kwant.wave_function(syst)(0)[0]

# create the operators


Q = kwant.physics.LocalOperator(syst)
J = kwant.physics.Current(syst)

# evaluate the expectation value with the wavefunction


q = Q(psi)
j = J(psi)

See the tutorial: Computing local quantities: densities and currents

Plotting of currents

Quantities defined on system hoppings (e.g. currents calculated using Current) can be directly plotted
as a streamplot over the system using kwant.plotter.current. This is similar to how kwant.plotter.
map can be used to plot quantities defined on sites. The example below shows edge states of a quantum
anomalous Hall phase of the two-band model shown in the above section:

2 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

J = kwant.operator.Current(syst).bind(params=params)
current = sum(J(p) for p in psi)
kwant.plotter.current(syst, current)

30

20

10

10

20

30

40 30 20 10 0 10 20 30 40

From: QAHE example script

Scattering states with discrete symmetries and conservation laws

Given a lead Hamiltonian that has a conservation law, it is now possible to construct lead modes that
have definite values of the conservation law. This is done by declaring projectors that block diagonalize
the Hamiltonian before the modes are computed. For a Hamiltonian that has one or more of the three
fundamental discrete symmetries (time-reversal symmetry, particle-hole symmetry and chiral symmetry),
it is now possible to declare the symmetries in Kwant. The symmetries are then used to construct
scattering states that are properly related by symmetry. The discrete symmetries may be combined with
conservation laws, such that if different blocks of the Hamiltonian are related by a discrete symmetry,
the lead modes are computed to reflect this.
See the updated tutorial: Superconductors: orbital degrees of freedom, conservation laws and symmetries

Named parameters for value functions

In Kwant < 1.3 whenever Hamiltonian values were provided as functions, they all had to take the
same extra parameters (after the site(s)) regardless of whether or not they actually used them at all.
For example, if we had some onsite potential and a magnetic field that we model using the Peierls
substitution, we would have to define our value functions like so:

# formally depends on 'B', but 'B' is never used


def onsite(site, V, B):

1.2. What’s new in Kwant 3


Kwant 1.3.1 documentation

return V

# formally depends on 'V', but 'V' is never used


def hopping(site_a, site_b, V, B):
return (site_b.pos[1] - site_a.pos[1]) * B

This was because previously extra arguments were provided to the system by passing them as a sequence
via the args parameter to various Kwant functions (e.g. kwant.smatrix or hamiltonian_submatrix).
In Kwant 1.3 it is now possible for value functions to depend on different parameters, e.g.:

def onsite(site, V):


return V

def hopping(site_a, site_b, B):


return (site_b.pos[1] - site_a.pos[1]) * B

If you make use of this feature then you must in addition pass your arguments via the params parameter.
The value provided to params must be a dict that maps parameter names to values, e.g.:

kwant.smatrix(syst, params=dict(B=0.1, V=2))

as opposed to the old way:

kwant.smatrix(syst, args=(2, 0.1))

Passing a dictionary of parameters via params is now the recommended way to provide parameters to
the system.

Reference implementation of the kernel polynomial method

The kernel polynomial method is now implemented within Kwant to obtain the density of states or, more
generally, the spectral density of a given operator acting on a system or Hamiltonian.
See the tutorial: Calculating spectral density with the kernel polynomial method
See the reference documentation: kwant.kpm – Kernel Polynomial Method

Finalizing builders with multiple translational symmetries

While it remains impossible to finalize a builder with more than a single direction of translational
symmetry, the wraparound module has been added as a temporary work-around until the above limitation
gets lifted.
The function wraparound transforms all (or all but one) translational symmetries of a given builder into
named momentum parameters k_x, k_y, etc. This makes it easy to compute transport through systems
with periodic boundary conditions or across infinite planes.
Plotting the 2-d band structure of graphene is now as straightforward as:

from matplotlib import pyplot


import kwant

lat = kwant.lattice.honeycomb()
sym = kwant.TranslationalSymmetry(lat.vec((1, 0)), lat.vec((0, 1)))

bulk = kwant.Builder(sym)
bulk[ [lat.a(0, 0), lat.b(0, 0)] ] = 0
bulk[lat.neighbors()] = 1
wrapped = kwant.wraparound.wraparound(bulk).finalized()
kwant.wraparound.plot_2d_bands(wrapped)

4 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

Consistent ordering of sites in finalized builders

In Python 3 the internal ordering of dictionaries is not deterministic. This meant that running a Kwant
script twice would produce systems with different ordering of sites, which leads to non-reproducible
calculations. Now, sites in finalized builders are always ordered first by their site family, then by their
tag.
Coincidentally, this means that you can plot a wavefunction in a simple 1D system by just saying:

lattice_1D = chain()
syst = make_system(lattice_1D)
h = syst.hamiltonian_submatrix()
pyplot.plot(np.eigs(h)[1][0])

attach_lead() can now handle leads with greater than nearest-neighbor hoppings

When attaching a lead with greater than nearest-neighbor hoppings, the symmetry period of the finalized
lead is suitably extended and the unit cell size is increased.

Pickling support

It is now possible to pickle and unpickle Builder and System instances.

Improved build configuration

The name of the build configuration file, build.conf by default, is now configurable with the
--configfile=PATH option to setup.py. (This makes build configuration usable with the pip tool.) The
build configuration as specified in this file is now more general, allowing to modify any build parameter
for any of the compiled extensions contained in Kwant. See the Installation instructions for details.

Builder.neighbors() respects symmetries

Given a site, the method neighbors of Builder returns an iterator over sites that are connected by a
hopping to the provided site. This is in contrast to previous versions of Kwant, where the neighbors were
yielded not of the provided site, but of it’s image in the fundamental domain.
This change is documented here for completeness. We expect that the vast majority of users of Kwant
will not be affected by it.

1.2.2 What’s new in Kwant 1.2

This article explains the user-visible changes in Kwant 1.2.2, released on 9 December 2015. See also the
full list of changes up to the most recent bugfix release of the 1.2 series.
Kwant 1.2 is identical to Kwant 1.1 except that it has been updated to run on Python 3.4 and above.
Bugfix releases for the 1.1 and 1.2 series will mirror each other, i.e. 1.1.3 and 1.2.3 will fix the same bugs.
Starting with Kwant 1.2, all Kwant development will target Python 3. We plan, however, to maintain
Python 2 support with the 1.1 series for several years.

How to upgrade Kwant scripts to Python 3

Even though the interface and functionality of Kwant remain unchanged between versions 1.1 and 1.2,
scripts using Kwant need to be updated to Python 3. This can be done by running the automatic
conversion tool on the command line:

1.2. What’s new in Kwant 5


Kwant 1.3.1 documentation

2to3 -w example.py

(The above command will rename the original file to example.py.bak.) The necessary changes are
typically only superficial, as described in What’s New In Python 3.0.

1.2.3 What’s new in Kwant 1.1

This article explains the user-visible changes in Kwant 1.1.0, released on 21 October 2015. See also the
full list of changes up to the most recent bugfix release of the 1.1 series.

Harmonize Bands with modes

Kwant’s convention is that momenta are positive in the direction of TranslationalSymmetry. While
the momenta returned by modes did respect this convention, the momenta read off the band structure
as given by Bands had the wrong sign. This has been fixed now.

New option add_cells of attach_lead

Before actually attaching a lead to a builder, the method attach_lead of Builder prepares a “nice”
interface by adding “missing” sites such that the first unit cell of the lead is completely connected with
the system under construction. These sites and their hoppings are taken over from the lead.
By setting the new option add_cells, attach_lead can now be told to add in addition any number of
complete unit cells of the lead to the system before attaching it. Among other things, this can be useful
for
• controlling the hopping between the lead and the system (Leads are always attached with their
inter-unit-cell hopping to the system, but absorbing one lead unit cell into the system allows to
control this),
• creating a buffer for long range disorder present in the system to die away before the translation-
invariant lead begins.
To support these applications, attach_lead now returns a list of all the sites that have been added to
the system. Creating a buffer for disorder can be thus done as follows:

syst[syst.attach_lead(lead, add_cells=10)] = onsite

Note how we set the onsite Hamiltonians of the sites that have been added to the value used in the
system.

New method conductance_matrix

SMatrix and GreensFunction have each gained a method conductance_matrix that returns the matrix
𝐺 such that 𝐼 = 𝐺𝑉 where 𝐼 and 𝑉 are, respectively, the vectors of currents and voltages for all the
leads. This matrix is useful for calculating non-local resistances. See Section 2.4 of the book by S. Datta.

Deduction of transmission probabilities

If smatrix or greens_function have been called with check_hermicity=True (on by default) and a
restricted number of leads in the out_leads and in_leads parameters, calls to transmission and
conductance_matrix will work whenever it is possible to deduce the result from current conservation.
This allows leaving out one lead (preferably the widest) from out_leads and in_leads, and still to
calculate all transmission probabilities. Doing so has been measured to speed up computations by 20%
in some cases.

6 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

Clearer error messages

The error messages (exceptions) that appear when the Kwant interface is used incorrectly have been
improved in many cases. For example, if instead of

builder[lattice(0, 1)] = 1

one writes

builder[(0, 1)] = 1

the error message will be more helpful now.


Please continue reporting confusing error messages on the Kwant mailing list.

New option pos_transform of kwant.plotter.map

This option which already existed for kwant.plotter.plot is now also available for kwant.plotter.map.

1.2.4 What’s new in Kwant 1.0

This article explains the new features in Kwant 1.0 compared to Kwant 0.2. Kwant 1.0 was released on
9 September 2013. Please consult the full list of changes in Kwant for all the changes up to the most
recent bugfix release.

Lattice and shape improvements

Lattices now have a method neighbors, which calculates all the n-th shortest possible hoppings on this
lattice. This replaces the nearest attribute that some lattices used to have.
shape uses an improved flood-fill algorithm, making it work better on narrow ribbons (which were
sometimes buggy before with non-square lattices). Additionally, it was made symmetry-aware: If shape
is used with a lead, the shape does not have to be limited along the lead direction anymore. In fact, if
the shape function does not have the same symmetry as the lead, the result may be unexpected, so it is
highly recommended to use shape functions that have the same symmetry as the lead.
closest now returns an exact, and not approximate closest point. A new method n_closest was added,
which returns the n closest lattice points.

possible_hoppings replaced by HoppingKind

The Builder method possible_hoppings has been rendered obsolete. Where previously one would
have had

for kind in lat.nearest:


syst[syst.possible_hoppings(*kind)] = t

now it suffices to write

syst[lat.neighbors()] = t

This is possible because Builder now accepts functions as keys in addition to Site objects and tuples
of them (hoppings). These functions are expected to yield either sites or hoppings, when given a builder
instance as the sole argument. The use of such keys is to implement sets of sites or hoppings that depend
on what is already present in the builder, such as HoppingKind. In the above example, lat.neighbors()
is a list of HoppingKind objects.

1.2. What’s new in Kwant 7


Kwant 1.3.1 documentation

Some renames

• site groups are now called site families. This affects all the names that used to contain “group” or
“groups”.
• lead slices are now referred to as lead cells: This affects all names that used to contain “slice” or
“slices” in the context of leads.
• self_energy has been renamed to selfenergy in all cases, most notably in kwant.physics.
selfenergy.
• wave_func has been renamed to wave_function,
• MonatomicLattice has been renamed to Monatomic,
• PolyatomicLattice has been renamed to Polyatomic.
• solve was split into two functions: smatrix, and greens_function. The former calculates the
scattering matrix, the latter the retarded Green’s function between the sites adjacent to the leads.
It is temporarily not possible to mix self-energy and modes leads within the same system.
• The object that contained the results, BlockResult was also split into SMatrix and
GreensFunction.

Band structure plots

A convenience function bands for quick plotting of band structure was implemented.

Immutable site families

In order to make naming more consistent, kwant.make_lattice was renamed and can be found now as
kwant.lattice.general. Classes Chain, Square, and Honeycomb from lattice were made functions
chain, square, and honeycomb.
In previous versions if one executed a = kwant.lattice.square(); b = kwant.lattice.square()
then a and b were actually different lattices. This often led to confusions in more convoluted use cases,
so this behavior was changed. Now two site families created with the same parameters are actually
indistinguishable by Kwant. If it is desired to make two site families which have the same geometry,
but mean different things, as for instance in Superconductors: orbital degrees of freedom, conservation
laws and symmetries, then the name argument has to be used when creating a lattice, e.g. a = kwant.
lattice.square(name='a'); b = kwant.lattice.square(name='b').

Parameters to Hamiltonian

Kwant now allows the Hamiltonian matrix elements to be described with functions that depend on an
arbitrary number of parameters in addition to the sites on which they are defined.
Previously, functions defining the Hamiltonian matrix elements had to have the following prototypes:

def onsite(site):
...

def hopping(site1, site2):


...

If the Hamiltonian elements need to depend on some other external parameters (e.g. magnetic field) then
those had to be provided by some other means than 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 smatrix is called by setting the arguments:

8 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

args A tuple of values to be passed as the positional arguments to the Hamiltonian value functions (not
including the Site arguments).
For example, if the hopping and onsite Hamiltonian value functions have the following prototype:

def onsite(site, t, B, pot):


...

def hopping(site1, site2, t, B, pot):


...

then the values of t, B and pot for which to solve the system can be passed to smatrix like this:

kwant.smatrix(syst, energy,
args=(2., 3., 4.))

With many parameters it can be less error-prone to collect all of them into a single object and pass this
object as the single argument. Such a parameter collection could be a dictionary, or a class instance, for
example:

class SimpleNamespace(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
# With Python >= 3.3 we can have instead:
# from types import SimpleNamespace

def onsite(site, p):


return p.mu * ...

def hopping(site1, site2, p):


return p.t * exp(-1j * p.B * ...)

params = SimpleNamespace(t=1, mu=2)


for params.B in B_values:
kwant.smatrix(syst, energy, args=[params])

Arguments can be passed in an equivalent way to wave_function, hamiltonian_submatrix, etc.

Calculation of modes separated from solving

The interface that solvers expect from leads attached to a FiniteSystem has been simplified and codified
(see there). Similar to self-energy, calculation of modes is now the lead’s own responsibility.
The new class ModesLead allows to attach leads that have a custom way of calculating their modes (e.g.
ideal leads) directly to a Builder.
Modes or self-energies can now be precomputed before passing the system to a solver, using the method
precalculate. This may save time, when the linear system has to be solved many times with the same
lead parameters.

Change of the modes and lead_info format

The function modes now returns two objects: PropagatingModes and StabilizedModes. The first one
contains the wave functions of all the propagating modes in real space, as well as their velocities and
momenta. All these quantities were previously not directly available. The second object contains the
propagating and evanescent modes in the compressed format expected by the sparse solver (previously
this was the sole output of modes). Accordingly, the lead_info attribute of SMatrix contains the real
space information about the modes in the leads (a list of PropagatingModes objects).

1.2. What’s new in Kwant 9


Kwant 1.3.1 documentation

New module for random-access random numbers

The module kwant.digest provides functions that given some input compute a “random” output that
depends on the input in a (cryptographically) intractable way. This functionality is useful for introducing
disorder, e.g.:

def onsite(site):
return 0.3 * kwant.digest.gauss(repr(site)) + 4

New module for random matrix theory Hamiltonians

The module kwant.rmt supports the creation of random matrix theory Hamiltonians.

Improved plotting functionality

The plotting functionality has been extended. By default, symbols and lines in plots are now relative to
the system coordinates, i.e. will scale accordingly if different zoom-levels are used. Different styles for
representing sites and hoppings are now possible. 3D plotting has been made more efficient.

1.2.5 What’s new in Kwant 0.2

This article explains the user-visible changes in Kwant 0.2. Kwant 0.2 was released on 29 November
2012.

Improved performance

This has been the main focus of this release. Through optimization a level of performance has been
reached that we consider satisfactory: runs of Kwant for mid-sized (100x100 say) systems now typically
spend most time in highly optimized libraries and not anymore in Python-implemented code. For large,
truly performance-critical systems almost all time is now spent in optimized libraries.
An important optimization has been replacing NumPy for most uses within Kwant by tinyarray. tinyarray
provides a subset of NumPy’s functionality in a way that is highly optimized for small arrays such as
the tags of sites in Kwant.

New MUMPS-based solver

The code for sparse matrix solvers has been reorganized and a new solver has been added next to
kwant.solvers.sparse: kwant.solvers.mumps. The new solver uses the MUMPS software package and is
much (typically several times) faster than the UMFPACK-based old solver. In addition, MUMPS uses
considerably less memory for a given system while at the same time it is able to take advantage of more
than 2 GiB of RAM.

New tutorial dealing with superconductivity

Superconductors: orbital degrees of freedom, conservation laws and symmetries

New plotter module

plotter has been rewritten using matplotlib, which allows plot post-processing, basic 3D plotting and
many other features. Due to the possibility to easily modify a matplotlib plot after it has been generated,
function plot has much fewer input parameters, and is less flexible than its previous implementation. Its

10 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

interface is also much more similar to that of matplotlib. For the detailed interface and input description
check plot documentation.
The behavior of plot with low level systems has changed. Arguments of plot which are functions are
given site numbers in place of Site objects when plotting a low level system. This provides an easy way
to make the appearance of lines and symbols depend on computation results.
A new function map was implemented. It allows to show a map of spatial dependence of a function of a
system site (e.g. density of states) without showing the sites themselves.

TranslationalSymmetry is used differently

When constructing an instance of TranslationalSymmetry a sole parameter used to be expected: A


sequence of sequences of 1d real space vectors. Now TranslationalSymmetry can take an arbitrary
number of parameters, each of them a 1d real space vector. This reduced the number of parantheses
necessary in the common case where there is just a single parameter
Example of old usage:

sym = kwant.TranslationalSymmetry([(-1, 0)])

New usage:

sym = kwant.TranslationalSymmetry((-1, 0))

Band structure functionality has been moved

The functionality that used to be provided by the method energies of kwant.system.InfiniteSystem


has been moved to the kwant.physics package. See the documentation of kwant.physics.Bands and
Beyond transport: Band structure and closed systems.

Calculation of the local density of states

The new function of sparse solvers ldos allows the calculation of the local density of states.

Calculation of wave functions in the scattering region

(Kwant 0.3 update: wave_func has been renamed to wave_function.)


The new function of sparse solvers wave_func allows the calculation of the wave function in the scattering
region due to any mode of any lead.

Return value of sparse solver

The function solve of sparse solvers now always returns a single instance of BlockResult. The latter has
been generalized to include more information for leads defined as infinite systems.

1.3 Installation of Kwant

Ready-to-use Kwant packages are available for many platforms (like GNU/Linux, Mac OS X, Microsoft
Windows). See the installation page of the Kwant website for instructions on how to install Kwant on
your platform. This is the recommended way for new users.
The remainder of this section documents how to build Kwant from source. This information is mostly
of interest to contributors and packagers.

1.3. Installation of Kwant 11


Kwant 1.3.1 documentation

1.3.1 Generic instructions

Obtaining the source code

Source distributions of Kwant (and Tinyarray) are available at the downloads section of the Kwant
website as well as PyPI. The sources may be also cloned directly from the official Kwant git repository.

Prerequisites

Building Kwant requires


• Python 3.4 or above (Kwant 1.1 is the last version to support Python 2),
• NumPy 1.8.1 or newer,
• SciPy 0.14 or newer,
• LAPACK and BLAS, (For best performance we recommend the free OpenBLAS or the nonfree
MKL.)
• Tinyarray 1.2 or newer,
a NumPy-like Python package optimized for very small arrays,
• An environment which allows to compile Python extensions written in C and C++.
The following software is highly recommended though not strictly required:
• matplotlib 1.4.2 or newer, for the module kwant.plotter and the tutorial,
• SymPy 0.7.6 or newer, for the subpackage kwant.continuum.
• MUMPS, a sparse linear algebra library that will in many cases speed up Kwant several times
and reduce the memory footprint. (Kwant uses only the sequential, single core version of
MUMPS. The advantages due to MUMPS as used by Kwant are thus independent of the
number of CPU cores of the machine on which Kwant runs.)
• The py.test testing framework for running the tests included with Kwant.
In addition, to build a copy of Kwant that has been checked-out directly from version control, you will
also need Cython 0.22 or newer. You do not need Cython to build Kwant that has been unpacked from
a source .tar.gz-file.

Building and installing Kwant

Kwant can be built and installed following the usual Python conventions by running the following com-
mands in the root directory of the Kwant distribution.

python3 setup.py build


python3 setup.py install

Depending on your system, you might have to run the second command with administrator privileges
(e.g. prefixing it with sudo).
After installation, tests can be run with:

python3 -c 'import kwant; kwant.test()'

The tutorial examples can be found in the directory tutorial inside the root directory of the Kwant
source distribution.
(Cython will be run automatically when the source tree has been checked out of version control. Kwant
tarballs include the Cython-generated files, and cythonization is disabled when building not from git. If
ever necessary, this default can be overridden by giving the --cython option to setup.py.)

12 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

Build configuration

Kwant contains several extension modules. The compilation and linking of these modules can be config-
ured by editing a build configuration file. By default, this file is build.conf in the root directory of the
Kwant distribution. A different path may be provided using the --configfile=PATH option.
This configuration file consists of sections, one for each extension module that is contained in Kwant,
led by a [section name] header and followed by key = value lines.
The sections bear the names of the extension modules, for example [kwant.operator] or [kwant.
linalg.lapack]. There can be also a [DEFAULT] section that provides default values for all extensions,
also those not explicitly present in the file.
Possible keys are the keyword arguments for distutils.core.Extension (For a complete list, see its
documentation). The corresponding values are whitespace-separated lists of strings.
Example build.conf for compiling Kwant with C assertions and Cython’s line trace feature:

[DEFAULT]
undef_macros = NDEBUG
define_macros = CYTHON_TRACE=1

Kwant must be linked against LAPACK & BLAS, and, optionally, MUMPS. The main application
of build configuration is adopting the build process to the various (deployment) variants of these li-
braries. By default setup.py assumes that LAPACK and BLAS can be found under their usual names.
MUMPS will be not linked against by default, except on Debian-based systems when the package
libmumps-scotch-dev is installed.
The sections [kwant.linalg.lapack] and [kwant.linalg._mumps] may be used to adapt the build
process. (For simplicity and backwards compatibility, [lapack] and [mumps] are aliases for the above.)
The section [lapack] configures the linking against LAPACK _AND_ BLAS, the section [mumps]
against MUMPS. The contents of [lapack] are appended to the configuration for MUMPS itself needs
LAPACK and BLAS as well.
Example build.conf for linking Kwant against a self-compiled MUMPS, SCOTCH and METIS:

[mumps]
libraries = zmumps mumps_common pord metis esmumps scotch scotcherr mpiseq gfortran

Example build.conf for linking Kwant with Intel MKL.:

[lapack]
libraries = mkl_intel_lp64 mkl_sequential mkl_core mkl_def
library_dirs = /opt/intel/mkl/lib/intel64
extra_link_args = -Wl,-rpath=/opt/intel/mkl/lib/intel64

The detailed syntax of build.conf is explained in the documentation of Python’s configparser module.

Building the documentation

To build the documentation, the Sphinx documentation generator is required with numpydoc extension
(version 0.5 or newer). If PDF documentation is to be built, the tools from the libRSVG (Debian/Ubuntu
package librsvg2-bin) are needed to convert SVG drawings into the PDF format.
As a prerequisite for building the documentation, Kwant must have been built successfully using python3
setup.py build as described above (or Kwant must be already installed in Python’s search path).
HTML documentation is built by entering the doc subdirectory of the Kwant package and executing
make html. PDF documentation is generated by executing make latex followed by make all-pdf in
doc/build/latex.

1.3. Installation of Kwant 13


Kwant 1.3.1 documentation

Because of some quirks of how Sphinx works, it might be necessary to execute make clean between
building HTML and PDF documentation. If this is not done, Sphinx may mistakenly use PNG files for
PDF output or other problems may appear.

1.3.2 Hints for specific platforms

Unix-like systems (GNU/Linux)

Kwant should run on all recent Unix-like systems. The following instructions have been verified to work
on Debian 8 (Jessie) or newer, and on Ubuntu 14.04 or newer. For other distributions step 1 will likely
have to be adapted. If Ubuntu-style sudo is not available, the respective command must be run as root.
1. Install the required packages. On Debian-based systems like Ubuntu this can be done by running
the command
sudo apt-get install python3-dev python3-scipy python3-matplotlib python3-pytest g++␣
↪gfortran libopenblas-dev liblapack-dev libmumps-scotch-dev

2. Unpack Tinyarray, enter its directory. To build and install, run


python3 setup.py build
sudo python3 setup.py install

3. Inside the Kwant source distribution’s root directory run


python3 setup.py build
sudo python3 setup.py install

By default the package will be installed under /usr/local. Run python3 setup.py --help install
for installation options.

Mac OS X: MacPorts

The following instructions are valid for Kwant 1.1 with Python 2.7. They need to be updated for Kwant
1.2. (Help is welcome.)
The required dependencies of Kwant are best installed with one of the packaging systems. Here we only
consider the case of MacPorts in detail. Some remarks for homebrew are given below.
1. Install a recent version of MacPorts, as explained in the installation instructions of MacPorts.
2. Install the required dependencies:
sudo port install gcc47 python27 py27-numpy py27-scipy py27-matplotlib mumps_seq
sudo port select --set python python27

3. Unpack Tinyarray, enter its directory, build and install:


python setup.py build
sudo python setup.py install

p5. Unpack Kwant, go to the Kwant directory, and edit build.conf to read:
[lapack]
extra_link_args = -Wl,-framework -Wl,Accelerate
[mumps]
include_dirs = /opt/local/include
library_dirs = /opt/local/lib
libraries = zmumps_seq mumps_common_seq pord_seq esmumps scotch scotcherr mpiseq gfortran

6. Then, build and install Kwant.

14 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

CC=gcc-mp-4.7 LDSHARED='gcc-mp-4.7 -shared -undefined dynamic_lookup' python setup.py build


sudo python setup.py install

You might note that installing Kwant on Mac OS X is somewhat more involved than installing on Linux.
Part of the reason is that we need to mix Fortran and C code in Kwant: While C code is usually compiled
using Apple compilers, Fortran code must be compiled with the Gnu Fortran compiler (there is no Apple
Fortran compiler). For this reason we force the Gnu compiler suite with the environment variables CC
and LDSHARED as shown above.

Mac OS X: homebrew

The following instructions are valid for Kwant 1.1 with Python 2.7. They need to be updated for Kwant
1.2. (Help is welcome.)
It is also possible to build Kwant using homebrew. The dependencies can be installed as

brew install gcc python


brew tap homebrew/science
brew tap homebrew/python
brew tap kwant-project/kwant
pip install pytest pytest-runner six
brew install numpy scipy matplotlib

Note that during the installation you will be told which paths to add when you want to compile/link
against scotch/metis/mumps; you need to add these to the build.conf file. Also, when linking against
MUMPS, one needs also to link against METIS (in addition to the libraries needed for MacPorts).

Microsoft Windows

Our efforts to compile Kwant on Windows using only free software (MinGW) were only moderately
successful. At the end of a very complicated process we obtained packages that worked, albeit unreliably.
As the only recommended way to compile Python extensions on Windows is using Visual C++, it may
well be that there exists no easy solution.
It is possible to compile Kwant on Windows using non-free compilers, however we (the authors of Kwant)
have no experience with this. The existing Windows binary installers of Kwant and Tinyarray were kindly
prepared by Christoph Gohlke.

1.4 Authors of Kwant

The Kwant authors can be reached at [email protected].


The principal developers of Kwant are
• Christoph W. Groth (CEA Grenoble)
• Michael Wimmer (TU Delft)
• Anton R. Akhmerov (TU Delft)
• Xavier Waintal (CEA Grenoble)
• Joseph Weston (TU Delft)
Contributors to Kwant include
• Jörg Behrmann (FU Berlin)
• Mathieu Istas (CEA Grenoble)
• Daniel Jaschke (CEA Grenoble)

1.4. Authors of Kwant 15


Kwant 1.3.1 documentation

• Bas Nijholt (TU Delft)


• Michał Nowak (TU Delft)
• Viacheslav Ostroukh (Leiden University)
• Pablo Pérez Piskunow (TU Delft)
• Tómas Örn Rosdahl (TU Delft)
• Sebastian Rubbert (TU Delft)
• Rafał Skolasiński (TU Delft)
• Adrien Sorgniard (CEA Grenoble)
We thank Christoph Gohlke for the creation of installers for Microsoft Windows.
CEA is the French Commissariat à l’énergie atomique et aux énergies alternatives. The CEA is the
copyright holder for the contributions of C. W. Groth, X. Waintal, and its other employees involved in
Kwant.
To find out who wrote a certain part of Kwant, please use the “blame” feature of Git, the version control
system.

1.4.1 Funding

Research related to Kwant was funded by


• the US Office of Naval Research,
• the European Research Council,
• the Netherlands Organisation for Scientific Research NWO (formerly NWO/FOM).
• the French National Agency for Research (ANR)
• the Future and Emerging Technologies (FET) & Information and Communication Technologies
(ICT) actions
• Lawrence Golub fellowship

1.5 Citing Kwant

We provide Kwant as free software under a BSD license as a service to the physics community. If you
have used Kwant for work that has lead to a scientific publication, please mention the fact that you used
it explicitly in the text body. For example, you may add
the numerical calculations were performed using the Kwant code
to the description of your numerical calculations. In addition, we ask you to cite the main paper that
introduces Kwant:
C. W. Groth, M. Wimmer, A. R. Akhmerov, X. Waintal, Kwant: a software package for
quantum transport, New J. Phys. 16, 063065 (2014).

1.5.1 Other references we ask you to consider

If you have profited from the quantum transport functionality of Kwant, please also cite the upcoming
paper that describes the relevant algorithms. The reference will also be added here once it is available.
Kwant owes much of its current performance to the use of the MUMPS library for solving systems of
sparse linear equations. If you have done high-performance calculations, we suggest citing

16 Chapter 1. Preliminaries
Kwant 1.3.1 documentation

P. R. Amestoy, I. S. Duff, J. S. Koster, J. Y. L’Excellent, SIAM. J. Matrix Anal. & Appl. 23


(1), 15 (2001).
Finally, if you use the routine for generation of circular ensembles of random matrices, please cite
F. Mezzadri, Notices Am. Math. Soc. 54, 592 (2007).

1.6 Contributing to Kwant and reporting problems

We see Kwant not just as a package with fixed functionality, but rather as a framework for implementing
different physics-related algorithms using a common set of concepts and, if possible, a shared interface.
We have designed it leaving room for growth, and plan to keep extending it.
External contributions to Kwant are highly welcome. You can help to advance the project not only by
writing code, but also by reporting bugs, and fixing/improving the documentation. Please see the Kwant
website for information on how to get in touch with the Kwant community.

1.7 Kwant license

Copyright 2011-2015 C. W. Groth (CEA), M. Wimmer, A. R. Akhmerov, X. Waintal (CEA), and others.
All rights reserved.
(CEA = Commissariat à l’énergie atomique et aux énergies alternatives)
Redistribution and use in source and binary forms, with or without modification, are permitted provided
that the following conditions are met:
• Redistributions of source code must retain the above copyright notice, this list of conditions and
the following disclaimer.
• Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the dis-
tribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS
IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIB-
UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUB-
STITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTER-
RUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CON-
TRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBIL-
ITY OF SUCH DAMAGE.

1.6. Contributing to Kwant and reporting problems 17


Kwant 1.3.1 documentation

18 Chapter 1. Preliminaries
CHAPTER

TWO

TUTORIAL: LEARNING KWANT THROUGH EXAMPLES

2.1 Introduction

In this tutorial, the most important features of Kwant are explained using simple, but still physically
meaningful examples. Each of the examples is commented extensively. In addition, you will find notes
about more subtle, technical details at the end of each example. At first reading, these notes may be
safely skipped.
A scientific article about Kwant is available as well, see Citing Kwant.
The article introduces Kwant with a somewhat different focus than the tutorial and it is the authors’
intention that both texts complement each other. While the tutorial is more “hands-on”, the article
presents Kwant in a more conceptual way, as well as discussing questions of design and performance.

2.1.1 Quantum transport

This introduction to the software Kwant is written for people that already have some experience with
the theory of quantum transport. Several introductions to the field are available, the most widely known
is probably the book “Electronic transport in mesoscopic systems” by Supriyo Datta.

2.1.2 The Python programming language

Kwant is a library for Python. Care was taken to fit well with the spirit of the language and to take
advantage of its expressive power. If you do not know Python yet, do not fear: Python is widely regarded
as one of the most accessible programming languages. For an introduction we recommend the official
Python Tutorial. The Beginner’s Guide to Python contains a wealth of links to other tutorials, guides
and books including some for absolute beginners.

2.1.3 Kwant

There are two steps in obtaining a numerical solution to a problem: The first is defining the problem in
a computer-accessible way, the second solving it. The aim of a software package like Kwant is to make
both steps easier.
In Kwant, the definition of the problem amounts to the creation of a tight binding system. The solution
of the problem, i.e. the calculation of the values of physical observables, is achieved by passing the
system to a solver.
The definition of a tight binding system can be seen as nothing else than the creation of a huge sparse
matrix (the Hamiltonian). Equivalently, the sparse Hamiltonian matrix can be seen as an annotated
graph: the nodes of the graph are the sites of the tight binding system, the edges are the hoppings.
Sites are annotated with the corresponding on-site Hamiltonian matrix, hoppings are annotated with
the corresponding hopping integral matrix.

19
Kwant 1.3.1 documentation

One of the central goals of Kwant is to allow easy creation of such annotated graphs that represent tight
binding system. Kwant can be made to know about the general structure of a particular system, the
involved lattices and symmetries. For example, a system with a 1D translational symmetry may be used
as a lead and attached to a another system. If both systems have sites which belong to the same lattices,
the attaching can be done automatically, even if the shapes of the systems are irregular.
Once a tight binding system has been created, solvers provided by Kwant can be used to compute physical
observables. Solvers expect the system to be in a different format than the one used for construction
– the system has to be finalized. In a finalized system the tight binding graph is fixed but the matrix
elements of the Hamiltonian may still change. The finalized format is both more efficient and simpler
– the solvers don’t have to deal with the various details which were facilitating the construction of the
system.
The typical workflow with Kwant is as follows:
1. Create an “empty” tight binding system.
2. Set its matrix elements and hoppings.
3. Attach leads (tight binding systems with translational symmetry).
4. Pass the finalized system to a solver.
Please note that even though this tutorial mostly shows 2-d systems, Kwant is completely general with
respect to the number of dimensions. Kwant does not care in the least whether systems live in one, two,
three, or any other number of dimensions. The only exception is plotting, which out-of-the-box only
works for up to three dimensions. (But custom projections can be specified!)

2.2 First steps: setting up a simple system and computing conduc-


tance

2.2.1 Discretization of a Schrödinger Hamiltonian

As first example, we compute the transmission probability through a two-dimensional quantum wire.
The wire is described by the two-dimensional Schrödinger equation
−ℏ2 2
𝐻= (𝜕 + 𝜕𝑦2 ) + 𝑉 (𝑦)
2𝑚 𝑥
with a hard-wall confinement 𝑉 (𝑦) in y-direction.
To be able to implement the quantum wire with Kwant, the continuous Hamiltonian 𝐻 has to be
discretized thus turning it into a tight-binding model. For simplicity, we discretize 𝐻 on the sites of
a square lattice with lattice constant 𝑎. Each site with the integer lattice coordinates (𝑖, 𝑗) has the
real-space coordinates (𝑥, 𝑦) = (𝑎𝑖, 𝑎𝑗).
Introducing the discretized positional states

|𝑖, 𝑗⟩ ≡ |𝑎𝑖, 𝑎𝑗⟩ = |𝑥, 𝑦⟩

the second-order differential operators can be expressed in the limit 𝑎 → 0 as


1
𝜕𝑥2 = ∑ (|𝑖 + 1, 𝑗⟩ ⟨𝑖, 𝑗| + |𝑖, 𝑗⟩ ⟨𝑖 + 1, 𝑗| − 2 |𝑖, 𝑗⟩ ⟨𝑖, 𝑗|) ,
𝑎2 𝑖,𝑗

and an equivalent expression for 𝜕𝑦2 . Subsitituting them in the Hamiltonian gives us

𝐻 = ∑ [ (𝑉 (𝑎𝑖, 𝑎𝑗) + 4𝑡) |𝑖, 𝑗⟩ ⟨𝑖, 𝑗| − 𝑡( |𝑖 + 1, 𝑗⟩ ⟨𝑖, 𝑗| + |𝑖, 𝑗⟩ ⟨𝑖 + 1, 𝑗| + |𝑖, 𝑗 + 1⟩ ⟨𝑖, 𝑗| + |𝑖, 𝑗⟩ ⟨𝑖, 𝑗 + 1| )]
𝑖,𝑗

with
ℏ2
𝑡= .
2𝑚𝑎2

20 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

For finite 𝑎, this discretized Hamiltonian approximates the continuous one to any required accuracy. The
approximation is good for all quantum states with a wave length considerably larger than 𝑎.
The remainder of this section demonstrates how to realize the discretized Hamiltonian in Kwant and how
to perform transmission calculations. For simplicity, we choose to work in such units that 𝑡 = 𝑎 = 1.

2.2.2 Transport through a quantum wire

See also:
The complete source code of this example can be found in tutorial/quantum_wire.py
In order to use Kwant, we need to import it:

import kwant

Enabling Kwant is as easy as this1 !


The first step is now the definition of the system with scattering region and leads. For this we make use
of the Builder type that allows to define a system in a convenient way. We need to create an instance
of it:

syst = kwant.Builder()

Observe that we just accessed Builder by the name kwant.Builder. We could have just as well written
kwant.builder.Builder instead. Kwant consists of a number of sub-packages that are all covered in the
reference documentation. For convenience, some of the most widely-used members of the sub-packages
are also accessible directly through the top-level kwant package.
Apart from Builder we also need to specify what kind of sites we want to add to the system. Here we
work with a square lattice. For simplicity, we set the lattice constant to unity:

a = 1
lat = kwant.lattice.square(a)

Since we work with a square lattice, we label the points with two integer coordinates (i, j). Builder
then allows us to add matrix elements corresponding to lattice points: syst[lat(i, j)] = ... sets the
on-site energy for the point (i, j), and syst[lat(i1, j1), lat(i2, j2)] = ... the hopping matrix
element from point (i2, j2) to point (i1, j1).
Note that we need to specify sites for Builder in the form lat(i, j). The lattice object lat does the
translation from integer coordinates to proper site format needed in Builder (more about that in the
technical details below).
We now build a rectangular scattering region that is W lattice points wide and L lattice points long:

t = 1.0
W = 10
L = 30

# Define the scattering region

for i in range(L):
for j in range(W):
# On-site Hamiltonian
syst[lat(i, j)] = 4 * t

# Hopping in y-direction
if j > 0:
syst[lat(i, j), lat(i, j - 1)] = -t

1 https://xkcd.com/353/

2.2. First steps: setting up a simple system and computing conductance 21


Kwant 1.3.1 documentation

# Hopping in x-direction
if i > 0:
syst[lat(i, j), lat(i - 1, j)] = -t

Observe how the above code corresponds directly to the terms of the discretized Hamiltonian: “On-site
Hamiltonian” implements

∑ (𝑉 (𝑎𝑖, 𝑎𝑗) + 4𝑡) |𝑖, 𝑗⟩ ⟨𝑖, 𝑗|


𝑖,𝑗

(with zero potential). “Hopping in x-direction” implements

∑ −𝑡( |𝑖 + 1, 𝑗⟩ ⟨𝑖, 𝑗| + |𝑖, 𝑗⟩ ⟨𝑖 + 1, 𝑗| ),


𝑖,𝑗

and “Hopping in y-direction” implements

∑ −𝑡( |𝑖, 𝑗 + 1⟩ ⟨𝑖, 𝑗| + |𝑖, 𝑗⟩ ⟨𝑖, 𝑗 + 1| ).


𝑖,𝑗

The hard-wall confinement is realized by not having hoppings (and sites) beyond a certain region of
space.
Next, we define the leads. Leads are also constructed using Builder, but in this case, the system must
have a translational symmetry:

sym_left_lead = kwant.TranslationalSymmetry((-a, 0))


left_lead = kwant.Builder(sym_left_lead)

Here, the Builder takes a TranslationalSymmetry as the optional parameter. Note that the (real-
space) vector (-a, 0) defining the translational symmetry must point in a direction away from the
scattering region, into the lead – hence, lead 02 will be the left lead, extending to infinity to the left.
For the lead itself it is enough to add the points of one unit cell as well as the hoppings inside one unit
cell and to the next unit cell of the lead. For a square lattice, and a lead in y-direction the unit cell is
simply a vertical line of points:

for j in range(W):
left_lead[lat(0, j)] = 4 * t
if j > 0:
left_lead[lat(0, j), lat(0, j - 1)] = -t
left_lead[lat(1, j), lat(0, j)] = -t

Note that here it doesn’t matter if you add the hoppings to the next or the previous unit cell – the
translational symmetry takes care of that. The isolated, infinite is attached at the correct position using

syst.attach_lead(left_lead)

This call returns the lead number which will be used to refer to the lead when computing transmissions
(further down in this tutorial). More details about attaching leads can be found in the tutorial Nontrivial
shapes.
We also want to add a lead on the right side. The only difference to the left lead is that the vector of
the translational symmetry must point to the right, the remaining code is the same:

sym_right_lead = kwant.TranslationalSymmetry((a, 0))


right_lead = kwant.Builder(sym_right_lead)

for j in range(W):
right_lead[lat(0, j)] = 4 * t
if j > 0:

2 Leads are numbered in the python convention, starting from 0.

22 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

right_lead[lat(0, j), lat(0, j - 1)] = -t


right_lead[lat(1, j), lat(0, j)] = -t

syst.attach_lead(right_lead)

Note that here we added points with x-coordinate 0, just as for the left lead. You might object that the
right lead should be placed L (or L+1?) points to the right with respect to the left lead. In fact, you do
not need to worry about that.
Now we have finished building our system! We plot it, to make sure we didn’t make any mistakes:
kwant.plot(syst)

This should bring up this picture:

8
6
4
2
0
0 5 10 15 20 25 30

The system is represented in the usual way for tight-binding systems: dots represent the lattice points (i,
j), and for every nonzero hopping element between points there is a line connecting these points. From
the leads, only a few (default 2) unit cells are shown, with fading color.
In order to use our system for a transport calculation, we need to finalize it
syst = syst.finalized()

Having successfully created a system, we now can immediately start to compute its conductance as a
function of energy:
energies = []
data = []
for ie in range(100):
energy = ie * 0.01

# compute the scattering matrix at a given energy


smatrix = kwant.smatrix(syst, energy)

# compute the transmission probability from lead 0 to


# lead 1
energies.append(energy)
data.append(smatrix.transmission(1, 0))

We use kwant.smatrix which is a short name for kwant.solvers.default.smatrix of the default solver
module kwant.solvers.default. kwant.smatrix computes the scattering matrix smatrix solving a
sparse linear system. smatrix itself allows to directly compute the total transmission probability from
lead 0 to lead 1 as smatrix.transmission(1, 0). The numbering used to refer to the leads here is the
same as the numbering assigned by the call to attach_lead earlier in the tutorial.
Finally we can use matplotlib to make a plot of the computed data (although writing to file and using
an external viewer such as gnuplot or xmgrace is just as viable)
pyplot.figure()
pyplot.plot(energies, data)

2.2. First steps: setting up a simple system and computing conductance 23


Kwant 1.3.1 documentation

pyplot.xlabel("energy [t]")
pyplot.ylabel("conductance [e^2/h]")
pyplot.show()

This should yield the result

3.0

2.5

2.0
conductance [e^2/h]

1.5

1.0

0.5

0.0
0.0 0.2 0.4 0.6 0.8 1.0
energy [t]

We see a conductance quantized in units of 𝑒2 /ℎ, increasing in steps as the energy is increased. The
value of the conductance is determined by the number of occupied subbands that increases with energy.
Technical details
• In the example above, when building the system, only one direction of hopping is given, i.e.
syst[lat(i, j), lat(i, j-1)] = ... and not also syst[lat(i, j-1), lat(i, j)] = .
... The reason is that Builder automatically adds the other direction of the hopping such that
the resulting system is Hermitian.
However, it does not hurt to define the opposite direction of hopping as well:

syst[lat(1, 0), lat(0, 0)] = -t


syst[lat(0, 0), lat(1, 0)] = -t.conj()

(assuming that t is complex) is perfectly fine. However, be aware that also

syst[lat(1, 0), lat(0, 0)] = -1


syst[lat(0, 0), lat(1, 0)] = -2

is valid code. In the latter case, the hopping syst[lat(1, 0), lat(0, 0)] is overwritten by the
last line and also equals to -2.
• Some more details the relation between Builder and the square lattice lat in the example:
Technically, Builder expects sites as indices. Sites themselves have a certain type, and belong to
a site family. A site family is also used to convert something that represents a site (like a tuple)

24 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

into a proper Site object that can be used with Builder.


In the above example, lat is the site family. lat(i, j) then translates the description of a lattice
site in terms of two integer indices (which is the natural way to do here) into a proper Site object.
The concept of site families and sites allows Builder to mix arbitrary lattices and site families
• In the example, we wrote

syst = syst.finalized()

In doing so, we transform the Builder object (with which we built up the system step by step)
into a System that has a fixed structure (which we cannot change any more).
Note that this means that we cannot access the Builder object any more. This is not necesarry
any more, as the computational routines all expect finalized systems. It even has the advantage
that python is now free to release the memory occupied by the Builder which, for large systems,
can be considerable. Roughly speaking, the above code corresponds to

fsyst = syst.finalized()
del syst
syst = fsyst

• Even though the vector passed to the TranslationalSymmetry is specified in real space, it must
be compatible with the lattice symmetries. A single lead can consists of sites belonging to more
than one lattice, but of course the translational symmetry of the lead has to be shared by all of
them.
• Instead of plotting to the screen (which is standard) plot can also write to a file specified by the
argument file. For the plotting to the screen to work the module matplotlib.pyplot has to be
imported. (An informative error message will remind you if you forget.) The reason for this is
pretty technical: matplotlib’s “backend” can only be chosen before matplotlib.pyplot has been
imported. Would Kwant import that module by itself, it would deprive you of the possibility to
choose a non-default backend later.

2.2.3 Building the same system with less code

See also:
The complete source code of this example can be found in tutorial/quantum_wire_revisited.py
Kwant allows for more than one way to build a system. The reason is that Builder is essentially just a
container that can be filled in different ways. Here we present a more compact rewrite of the previous
example (still with the same results).
Also, the previous example was written in the form of a Python script with little structure, and with
everything governed by global variables. This is OK for such a simple example, but for larger projects it
makes sense to partition the code into separate entities. In this example we therefore also aim at more
structure.
We begin the program collecting all imports in the beginning of the file and put the build-up of the
system into a separate function make_system:

import kwant

# For plotting
from matplotlib import pyplot

def make_system(a=1, t=1.0, W=10, L=30):


# Start with an empty tight-binding system and a single square lattice.
# `a` is the lattice constant (by default set to 1 for simplicity.
lat = kwant.lattice.square(a)

2.2. First steps: setting up a simple system and computing conductance 25


Kwant 1.3.1 documentation

syst = kwant.Builder()

Previously, the scattering region was build using two for-loops. Instead, we now write:

syst[(lat(x, y) for x in range(L) for y in range(W))] = 4 * t

Here, all lattice points are added at once in the first line. The construct ((i, j) for i in range(L)
for j in range(W)) is a generator that iterates over all points in the rectangle as did the two for-loops
in the previous example. In fact, a Builder can not only be indexed by a single lattice point – it also
allows for lists of points, or, as in this example, a generator (as is also used in list comprehensions in
python).
Having added all lattice points in one line, we now turn to the hoppings. In this case, an iterable like
for the lattice points becomes a bit cumbersome, and we use instead another feature of Kwant:

syst[lat.neighbors()] = -t

In regular lattices, hoppings form large groups such that hoppings within a group can be transformed
into one another by lattice translations. In order to allow to easily manipulate such hoppings, an object
HoppingKind is provided. When given a Builder as an argument, HoppingKind yields all the hoppings
of a certain kind that can be added to this builder without adding new sites. When HoppingKind is
given to Builder as a key, it means that something is done to all the possible hoppings of this kind. A
list of HoppingKind objects corresponding to nearest neighbors in lattices in Kwant is obtained using
lat.neighbors(). syst[lat.neighbors()] = -t then sets all of those hopping matrix elements at
once. In order to set values for all the nth-nearest neighbors at once, one can similarly use syst[lat.
neighbors(n)] = -t. More detailed example of using HoppingKind directly will be provided in Matrix
structure of on-site and hopping elements.
The left lead is constructed in an analogous way:

lead = kwant.Builder(kwant.TranslationalSymmetry((-a, 0)))


lead[(lat(0, j) for j in range(W))] = 4 * t
lead[lat.neighbors()] = -t

The previous example duplicated almost identical code for the left and the right lead. The only difference
was the direction of the translational symmetry vector. Here, we only construct the left lead, and use
the method reversed of Builder to obtain a copy of a lead pointing in the opposite direction. Both
leads are attached as before and the finished system returned:

syst.attach_lead(lead)
syst.attach_lead(lead.reversed())

return syst

The remainder of the script has been organized into two functions. One for the plotting of the conduc-
tance.

def plot_conductance(syst, energies):


# Compute conductance
data = []
for energy in energies:
smatrix = kwant.smatrix(syst, energy)
data.append(smatrix.transmission(1, 0))

pyplot.figure()
pyplot.plot(energies, data)
pyplot.xlabel("energy [t]")
pyplot.ylabel("conductance [e^2/h]")
pyplot.show()

26 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

And one main function.

def main():
syst = make_system()

# Check that the system looks as intended.


kwant.plot(syst)

# Finalize the system.


syst = syst.finalized()

# We should see conductance steps.


plot_conductance(syst, energies=[0.01 * i for i in range(100)])

Finally, we use the following standard Python construct3 to execute main if the program is used as a
script (i.e. executed as python quantum_wire_revisited.py):

if __name__ == '__main__':
main()

If the example, however, is imported inside Python using import quantum_wire_revisted as qw, main
is not executed automatically. Instead, you can execute it manually using qw.main(). On the other
hand, you also have access to the other functions, make_system and plot_conductance, and can thus
play with the parameters.
The result of the example should be identical to the previous one. Technical details
• We have seen different ways to add lattice points to a Builder. It allows to
– add single points, specified as sites
– add several points at once using a generator (as in this example)
– add several points at once using a list (typically less effective compared to a generator)
For technical reasons it is not possible to add several points using a tuple of sites. Hence it is worth
noting a subtle detail in

syst[(lat(x, y) for x in range(L) for y in range(W))] = 4 * t

Note that (lat(x, y) for x in range(L) for y in range(W)) is not a tuple, but a generator.
Let us elaborate a bit more on this using a simpler example:

>>> a = (0, 1, 2, 3)
>>> b = (i for i in range(4))

Here, a is a tuple, whereas b is a generator. One difference is that one can subscript tuples, but
not generators:

>>> a[0]
0
>>> b[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'generator' object is unsubscriptable

However, both can be used in for-loops, for example.


• In the example, we have added all the hoppings using HoppingKind. In fact, hoppings can be
added in the same fashion as sites, namely specifying
– a single hopping
3 https://docs.python.org/3/library/__main__.html

2.2. First steps: setting up a simple system and computing conductance 27


Kwant 1.3.1 documentation

– several hoppings via a generator


– several hoppings via a list
A hopping is defined using two sites. If several hoppings are added at once, these two sites should
be encapsulated in a tuple. In particular, one must write:

syst[((lat(0,j+1), lat(0, j)) for j in range(W-1)] = ...

or:

syst[[(site1, site2), (site3, site4), ...]] = ...

You might wonder, why it is then possible to write for a single hopping:

syst[site1, site2] = ...

instead of

syst[(site1, site2)] = ...

In fact, due to the way python handles subscripting, syst[site1, site2] is the same as
syst[(site1, site2)].
(This is the deeper reason why several sites cannot be added as a tuple – it would be impossible
to distinguish whether one would like to add two separate sites, or one hopping.

2.3 More interesting systems: spin, potential, shape

Each of the following three examples highlights different ways to go beyond the very simple examples of
the previous section.

2.3.1 Matrix structure of on-site and hopping elements

See also:
The complete source code of this example can be found in tutorial/spin_orbit.py
We begin by extending the simple 2DEG-Hamiltonian by a Rashba spin-orbit coupling and a Zeeman
splitting due to an external magnetic field:

−ℏ2 2
𝐻= (𝜕 + 𝜕𝑦2 ) − 𝑖𝛼(𝜕𝑥 𝜎𝑦 − 𝜕𝑦 𝜎𝑥 ) + 𝐸Z 𝜎𝑧 + 𝑉 (𝑦)
2𝑚 𝑥
Here 𝜎𝑥,𝑦,𝑧 denote the Pauli matrices.
It turns out that this well studied Rashba-Hamiltonian has some peculiar properties in (ballistic)
nanowires: It was first predicted theoretically in Phys. Rev. Lett. 90, 256601 (2003) that such a
system should exhibit non-monotonic conductance steps due to a spin-orbit gap. Only very recently,
this non-monotonic behavior has been supposedly observed in experiment: Nature Physics 6, 336 (2010).
Here we will show that a very simple extension of our previous examples will exactly show this behavior
(Note though that no care was taken to choose realistic parameters).
The tight-binding model corresponding to the Rashba-Hamiltonian naturally exhibits a 2x2-matrix struc-
ture of onsite energies and hoppings. In order to use matrices in our program, we import the Tinyarray
package. (NumPy would work as well, but Tinyarray is much faster for small arrays.)

import tinyarray

For convenience, we define the Pauli-matrices first (with 𝜎0 the unit matrix):

28 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

sigma_0 = tinyarray.array([[1, 0], [0, 1]])


sigma_x = tinyarray.array([[0, 1], [1, 0]])
sigma_y = tinyarray.array([[0, -1j], [1j, 0]])
sigma_z = tinyarray.array([[1, 0], [0, -1]])

Previously, we used numbers as the values of our matrix elements. However, Builder also accepts
matrices as values, and we can simply write:

syst[(lat(x, y) for x in range(L) for y in range(W))] = \


4 * t * sigma_0 + e_z * sigma_z
# hoppings in x-direction
syst[kwant.builder.HoppingKind((1, 0), lat, lat)] = \
-t * sigma_0 - 1j * alpha * sigma_y
# hoppings in y-directions
syst[kwant.builder.HoppingKind((0, 1), lat, lat)] = \
-t * sigma_0 + 1j * alpha * sigma_x

Note that the Zeeman energy adds to the onsite term, whereas the Rashba spin-orbit term adds to
the hoppings (due to the derivative operator). Furthermore, the hoppings in x and y-direction have a
different matrix structure. We now cannot use lat.neighbors() to add all the hoppings at once, since
we now have to distinguish x and y-direction. Because of that, we have to explicitly specify the hoppings
in the form expected by HoppingKind:
• A tuple with relative lattice indices. For example, (1, 0) means hopping from (i, j) to (i+1, j),
whereas (1, 1) would mean hopping to (i+1, j+1).
• The target lattice (where to hop to)
• The source lattice (where the hopping originates)
Since we are only dealing with a single lattice here, source and target lattice are identical, but still must
be specified (for an example with hopping between different (sub)lattices, see Beyond square lattices:
graphene).
Again, it is enough to specify one direction of the hopping (i.e. when specifying (1, 0) it is not necessary
to specify (-1, 0)), Builder assures hermiticity.
The leads also allow for a matrix structure,

lead[(lat(0, j) for j in range(W))] = 4 * t * sigma_0 + e_z * sigma_z


# hoppings in x-direction
lead[kwant.builder.HoppingKind((1, 0), lat, lat)] = \
-t * sigma_0 - 1j * alpha * sigma_y
# hoppings in y-directions
lead[kwant.builder.HoppingKind((0, 1), lat, lat)] = \
-t * sigma_0 + 1j * alpha * sigma_x

The remainder of the code is unchanged, and as a result we should obtain the following, clearly non-
monotonic conductance steps:

2.3. More interesting systems: spin, potential, shape 29


Kwant 1.3.1 documentation

4
conductance [e^2/h]

0
0.2 0.0 0.2 0.4 0.6
energy [t]

Technical details
• The Tinyarray package, one of the dependencies of Kwant, implements efficient small arrays. It is
used internally in Kwant for storing small vectors and matrices. For performance, it is preferable
to define small arrays that are going to be used with Kwant using Tinyarray. However, NumPy
would work as well:

import numpy
sigma_0 = numpy.array([[1, 0], [0, 1]])
sigma_x = numpy.array([[0, 1], [1, 0]])
sigma_y = numpy.array([[0, -1j], [1j, 0]])
sigma_z = numpy.array([[1, 0], [0, -1]])

Tinyarray arrays behave for most purposes like NumPy arrays except that they are immutable:
they cannot be changed once created. This is important for Kwant: it allows them to be used
directly as dictionary keys.
• It should be emphasized that the relative hopping used for HoppingKind is given in terms of lattice
indices, i.e. relative to the Bravais lattice vectors. For a square lattice, the Bravais lattice vectors
are simply (a,0) and (0,a), and hence the mapping from lattice indices (i,j) to real space and back
is trivial. This becomes more involved in more complicated lattices, where the real-space directions
corresponding to, for example, (1,0) and (0,1) need not be orthogonal any more (see Beyond square
lattices: graphene).

2.3.2 Spatially dependent values through functions

See also:
The complete source code of this example can be found in tutorial/quantum_well.py
Up to now, all examples had position-independent matrix-elements (and thus translational invariance

30 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

along the wire, which was the origin of the conductance steps). Now, we consider the case of a position-
dependent potential:

ℏ2 2
𝐻= (𝜕 + 𝜕𝑦2 ) + 𝑉 (𝑥, 𝑦)
2𝑚 𝑥
The position-dependent potential enters in the onsite energies. One possibility would be to again set
the onsite matrix elements of each lattice point individually (as in Transport through a quantum wire).
However, changing the potential then implies the need to build up the system again.
Instead, we use a python function to define the onsite energies. We define the potential profile of a
quantum well as:
def make_system(a=1, t=1.0, W=10, L=30, L_well=10):
# Start with an empty tight-binding system and a single square lattice.
# `a` is the lattice constant (by default set to 1 for simplicity.
lat = kwant.lattice.square(a)

syst = kwant.Builder()

#### Define the scattering region. ####


# Potential profile
def potential(site, pot):
(x, y) = site.pos
if (L - L_well) / 2 < x < (L + L_well) / 2:
return pot
else:
return 0

This function takes two arguments: the first of type Site, from which you can get the real-space coordi-
nates using site.pos, and the value of the potential as the second. Note that in potential we can access
variables of the surrounding function: L and L_well are taken from the namespace of make_system.
Kwant now allows us to pass a function as a value to Builder:
def onsite(site, pot=0):
return 4 * t + potential(site, pot)

syst[(lat(x, y) for x in range(L) for y in range(W))] = onsite


syst[lat.neighbors()] = -t

For each lattice point, the corresponding site is then passed as the first argument to the function onsite.
The values of any additional parameters, which can be used to alter the Hamiltonian matrix elements
at a later stage, are specified later during the call to smatrix. Note that we had to define onsite, as it is
not possible to mix values and functions as in syst[...] = 4 * t + potential.
For the leads, we just use constant values as before. If we passed a function also for the leads (which
is perfectly allowed), this function would need to be compatible with the translational symmetry of the
lead – this should be kept in mind.
Finally, we compute the transmission probability:

# Compute conductance
data = []
for welldepth in welldepths:
smatrix = kwant.smatrix(syst, energy, args=[-welldepth])
data.append(smatrix.transmission(1, 0))

pyplot.figure()
pyplot.plot(welldepths, data)
pyplot.xlabel("well depth [t]")
pyplot.ylabel("conductance [e^2/h]")
pyplot.show()

2.3. More interesting systems: spin, potential, shape 31


Kwant 1.3.1 documentation

kwant.smatrix 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:

1.0

0.9

0.8
conductance [e^2/h]

0.7

0.6

0.5

0.4
0.0 0.2 0.4 0.6 0.8 1.0
well depth [t]

Starting from no potential (well depth = 0), we observe the typical oscillatory transmission behavior
through resonances in the quantum well.

Warning: If functions are used to set values inside a lead, then they must satisfy the same symmetry
as the lead does. There is (currently) no check and wrong results will be the consequence of a
misbehaving function.

Technical details
• Functions can also be used for hoppings. In this case, they take two Site‘s as arguments and then
an arbitrary number of additional arguments.
• Apart from the real-space position pos, Site has also an attribute tag containing the lattice indices
of the site.

2.3.3 Nontrivial shapes

See also:
The complete source code of this example can be found in tutorial/ab_ring.py
Up to now, we only dealt with simple wire geometries. Now we turn to the case of a more complex
geometry, namely transport through a quantum ring that is pierced by a magnetic flux Φ:

32 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

For a flux line, it is possible to choose a gauge such that a charged particle acquires a phase 𝑒Φ/ℎ
whenever it crosses the branch cut originating from the flux line (branch cut shown as red dashed line)1 .
There are more symmetric gauges, but this one is most convenient to implement numerically.
Defining such a complex structure adding individual lattice sites is possible, but cumbersome. Fortu-
nately, there is a more convenient solution: First, define a boolean function defining the desired shape,
i.e. a function that returns True whenever a point is inside the shape, and False otherwise:

def make_system(a=1, t=1.0, W=10, r1=10, r2=20):


# Start with an empty tight-binding system and a single square lattice.
# `a` is the lattice constant (by default set to 1 for simplicity).

lat = kwant.lattice.square(a)

syst = kwant.Builder()

#### Define the scattering region. ####


# Now, we aim for a more complex shape, namely a ring (or annulus)
def ring(pos):
(x, y) = pos
rsq = x ** 2 + y ** 2
return (r1 ** 2 < rsq < r2 ** 2)

Note that this function takes a real-space position as argument (not a Site).
We can now simply add all of the lattice points inside this shape at once, using the function shape
provided by the lattice:

syst[lat.shape(ring, (0, r1 + 1))] = 4 * t


syst[lat.neighbors()] = -t

Here, lat.shape takes as a second parameter a (real-space) point that is inside the desired shape. The
hoppings can still be added using lat.neighbors() as before.
Up to now, the system contains constant hoppings and onsite energies, and we still need to include the
phase shift due to the magnetic flux. This is done by overwriting the values of hoppings in x-direction
along the branch cut in the lower arm of the ring. For this we select all hoppings in x-direction that are
of the form (lat(1, j), lat(0, j)) with j<0:

def hopping_phase(site1, site2, phi):


return -t * exp(1j * phi)

1 The corresponding vector potential is 𝐴 (𝑥, 𝑦) = Φ𝛿(𝑥)Θ(−𝑦) which yields the correct magnetic field 𝐵(𝑥, 𝑦) =
𝑥
Φ𝛿(𝑥)𝛿(𝑦).

2.3. More interesting systems: spin, potential, shape 33


Kwant 1.3.1 documentation

def crosses_branchcut(hop):
ix0, iy0 = hop[0].tag

# builder.HoppingKind with the argument (1, 0) below


# returns hoppings ordered as ((i+1, j), (i, j))
return iy0 < 0 and ix0 == 1 # ix1 == 0 then implied

# Modify only those hopings in x-direction that cross the branch cut
def hops_across_cut(syst):
for hop in kwant.builder.HoppingKind((1, 0), lat, lat)(syst):
if crosses_branchcut(hop):
yield hop
syst[hops_across_cut] = hopping_phase

Here, crosses_branchcut is a boolean function that returns True for the desired hoppings. We then use
again a generator (this time with an if-conditional) to set the value of all hoppings across the branch
cut to fluxphase. The rationale behind using a function instead of a constant value for the hopping is
again that we want to vary the flux through the ring, without constantly rebuilding the system – instead
the flux is governed by the parameter phi.
For the leads, we can also use the lat.shape-functionality:

sym_lead = kwant.TranslationalSymmetry((-a, 0))


lead = kwant.Builder(sym_lead)

def lead_shape(pos):
(x, y) = pos
return (-W / 2 < y < W / 2)

lead[lat.shape(lead_shape, (0, 0))] = 4 * t


lead[lat.neighbors()] = -t

Here, the shape must be compatible with the translational symmetry of the lead sym_lead. In particular,
this means that it should extend to infinity along the translational symmetry direction (note how there
is no restriction on x in lead_shape)2 .
Attaching the leads is done as before:

syst.attach_lead(lead)
syst.attach_lead(lead.reversed())

In fact, attaching leads seems not so simple any more for the current structure with a scattering region
very much different from the lead shapes. However, the choice of unit cell together with the translational
vector allows to place the lead unambiguously in real space – the unit cell is repeated infinitely many
times in the direction and opposite to the direction of the translational vector. Kwant examines the lead
starting from infinity and traces it back (going opposite to the direction of the translational vector) until
it intersects the scattering region. At this intersection, the lead is attached:

2 Despite the “infinite” shape, the unit cell will still be finite; the TranslationalSymmetry takes care of that.

34 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

After the lead has been attached, the system should look like this:

20

15

10

10

15

20
20 10 0 10 20

The computation of the conductance goes in the same fashion as before. Finally you should get the
following result:

2.3. More interesting systems: spin, potential, shape 35


Kwant 1.3.1 documentation

1.0

0.8
conductance [e^2/h]

0.6

0.4

0.2

0.0
0.0 0.5 1.0 1.5 2.0 2.5 3.0
flux [flux quantum]

where one can observe the conductance oscillations with the period of one flux quantum. Technical
details
• Leads have to have proper periodicity. Furthermore, the Kwant format requires the hopping from
the leads to the scattering region to be identical to the hoppings between unit cells in the lead.
attach_lead takes care of all these details for you! In fact, it even adds points to the scattering
region, if proper attaching requires this. This becomes more apparent if we attach the leads a bit
further away from the central axis o the ring, as was done in this example:

36 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

20

15

10

10

15

20
20 10 0 10 20

• Per default, attach_lead attaches the lead to the “outside” of the structure, by tracing the lead
backwards, coming from infinity.
One can also attach the lead to the inside of the structure, by providing an alternative starting
point from where the lead is traced back:

syst.attach_lead(lead1, lat(0, 0))

starts the trace-back in the middle of the ring, resulting in the lead being attached to the inner
circle:

2.3. More interesting systems: spin, potential, shape 37


Kwant 1.3.1 documentation

20

15

10

10

15

20
20 15 10 5 0 5 10 15 20

Note that here the lead is treated as if it would pass over the other arm of the ring, without
intersecting it.

2.4 Beyond transport: Band structure and closed systems

2.4.1 Band structure calculations

See also:
The complete source code of this example can be found in tutorial/band_structure.py
When doing transport simulations, one also often needs to know the band structure of the leads, i.e. the
energies of the propagating plane waves in the leads as a function of momentum. This band structure
contains information about the number of modes, their momenta and velocities.
In this example, we aim to compute the band structure of a simple tight-binding wire.
Computing band structures in Kwant is easy. Just define a lead in the usual way:

def make_lead(a=1, t=1.0, W=10):


# Start with an empty lead with a single square lattice
lat = kwant.lattice.square(a)

38 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

sym_lead = kwant.TranslationalSymmetry((-a, 0))


lead = kwant.Builder(sym_lead)

# build up one unit cell of the lead, and add the hoppings
# to the next unit cell
for j in range(W):
lead[lat(0, j)] = 4 * t

if j > 0:
lead[lat(0, j), lat(0, j - 1)] = -t

lead[lat(1, j), lat(0, j)] = -t

return lead

“Usual way” means defining a translational symmetry vector, as well as one unit cell of the lead, and
the hoppings to neighboring unit cells. This information is enough to make the infinite, translationally
invariant system needed for band structure calculations.
In the previous examples Builder instances like the one created above were attached as leads to the
Builder instance of the scattering region and the latter was finalized. The thus created system contained
implicitly finalized versions of the attached leads. However, now we are working with a single lead and
there is no scattering region. Hence, we have to finalize the Builder of our sole lead explicitly.
That finalized lead is then passed to bands. This function calculates energies of various bands at a range
of momenta and plots the calculated energies. It is really a convenience function, and if one needs to do
something more profound with the dispersion relation these energies may be calculated directly using
Bands. For now we just plot the bandstructure:

def main():
lead = make_lead().finalized()
kwant.plotter.bands(lead, show=False)
pyplot.xlabel("momentum [(lattice constant)^-1]")
pyplot.ylabel("energy [t]")
pyplot.show()

This gives the result:

2.4. Beyond transport: Band structure and closed systems 39


Kwant 1.3.1 documentation

5
energy [t]

0
3 2 1 0 1 2 3
momentum [(lattice constant)^-1]

where we observe the cosine-like dispersion of the square lattice. Close to k=0 this agrees well with the
quadratic dispersion this tight-binding Hamiltonian is approximating.

2.4.2 Closed systems

See also:
The complete source code of this example can be found in tutorial/closed_system.py
Although Kwant is (currently) mainly aimed towards transport problems, it can also easily be used to
compute properties of closed systems – after all, a closed system is nothing more than a scattering region
without leads!
In this example, we compute the wave functions of a closed circular quantum dot and its spectrum as a
function of magnetic field (Fock-Darwin spectrum).
To compute the eigenenergies and eigenstates, we will make use of the sparse linear algebra functionality
of SciPy, which interfaces the ARPACK package:

import scipy.sparse.linalg as sla

We set up the system using the shape-function as in Nontrivial shapes, but do not add any leads:

lat = kwant.lattice.square(a, norbs=1)

syst = kwant.Builder()

# Define the quantum dot


def circle(pos):
(x, y) = pos
rsq = x ** 2 + y ** 2

40 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

return rsq < r ** 2

def hopx(site1, site2, B=0):


# The magnetic field is controlled by the parameter B
y = site1.pos[1]
return -t * exp(-1j * B * y)

syst[lat.shape(circle, (0, 0))] = 4 * t


# hoppings in x-direction
syst[kwant.builder.HoppingKind((1, 0), lat, lat)] = hopx
# hoppings in y-directions
syst[kwant.builder.HoppingKind((0, 1), lat, lat)] = -t

# It's a closed system for a change, so no leads


return syst

We add the magnetic field using a function and a global variable as we did in the two previous tutorial.
(Here, the gauge is chosen such that 𝐴𝑥 (𝑦) = −𝐵𝑦 and 𝐴𝑦 = 0.)
The spectrum can be obtained by diagonalizing the Hamiltonian of the system, which in turn can be
obtained from the finalized system using hamiltonian_submatrix:

def plot_spectrum(syst, Bfields):

# In the following, we compute the spectrum of the quantum dot


# using dense matrix methods. This works in this toy example, as
# the system is tiny. In a real example, one would want to use
# sparse matrix methods

energies = []
for B in Bfields:
# Obtain the Hamiltonian as a dense matrix
ham_mat = syst.hamiltonian_submatrix(args=[B], sparse=True)

# we only calculate the 15 lowest eigenvalues


ev = sla.eigsh(ham_mat, k=15, which='SM', return_eigenvectors=False)

energies.append(ev)

pyplot.figure()
pyplot.plot(Bfields, energies)
pyplot.xlabel("magnetic field [arbitrary units]")
pyplot.ylabel("energy [t]")
pyplot.show()

Note that we use sparse linear algebra to efficiently calculate only a few lowest eigenvalues. Finally, we
obtain the result:

2.4. Beyond transport: Band structure and closed systems 41


Kwant 1.3.1 documentation

0.7

0.6

0.5
energy [t]

0.4

0.3

0.2

0.1

0.000 0.025 0.050 0.075 0.100 0.125 0.150 0.175 0.200


magnetic field [arbitrary units]

At zero magnetic field several energy levels are degenerate (since our quantum dot is rather symmetric).
These degeneracies are split by the magnetic field, and the eigenenergies flow towards the Landau level
energies at higher magnetic fields1 .
The eigenvectors are obtained very similarly, and can be plotted directly using map:

def plot_wave_function(syst):
# Calculate the wave functions in the system.
ham_mat = syst.hamiltonian_submatrix(sparse=True)
evecs = sla.eigsh(ham_mat, k=20, which='SM')[1]

# Plot the probability density of the 10th eigenmode.


kwant.plotter.map(syst, np.abs(evecs[:, 9])**2,
colorbar=False, oversampling=1)

1 Again, in this tutorial example no care was taken into choosing appropriate material parameters or units. For this

reason, magnetic field is given only in “arbitrary units”.

42 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

20

10

10

20

20 10 0 10 20

The last two arguments to map are optional. The first prevents a colorbar from appearing. The second,
oversampling=1, makes the image look better for the special case of a square lattice.
As our model breaks time reversal symmetry (because of the applied magnetic field) we can also see
an intereting property of the eigenstates, namely that they can have non-zero local current. We can
calculate the local current due to a state by using kwant.operator.Current and plotting it using
kwant.plotter.current:

def plot_current(syst):
# Calculate the wave functions in the system.
ham_mat = syst.hamiltonian_submatrix(sparse=True)
evecs = sla.eigsh(ham_mat, k=20, which='SM')[1]

# Calculate and plot the local current of the 10th eigenmode.


J = kwant.operator.Current(syst)
current = J(evecs[:, 9])
kwant.plotter.current(syst, current, colorbar=False)

2.4. Beyond transport: Band structure and closed systems 43


Kwant 1.3.1 documentation

30

20

10

10

20

30
30 20 10 0 10 20 30

Technical details
• hamiltonian_submatrix can also return a sparse matrix, if the optional argument sparse=True.
The sparse matrix is in SciPy’s scipy.sparse.coo_matrix format, which can be easily be con-
verted to various other sparse matrix formats (see SciPy’s documentation).

2.5 Beyond square lattices: graphene

See also:
The complete source code of this example can be found in tutorial/graphene.py
In the following example, we are going to calculate the conductance through a graphene quantum dot
with a p-n junction and two non-collinear leads. In the process, we will touch all of the topics that
we have seen in the previous tutorials, but now for the honeycomb lattice. As you will see, everything
carries over nicely.
We begin by defining the honeycomb lattice of graphene. This is in principle already done in kwant.
lattice.honeycomb, but we do it explicitly here to show how to define a new lattice:

44 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

graphene = kwant.lattice.general([(1, 0), (sin_30, cos_30)],


[(0, 0), (0, 1 / sqrt(3))])
a, b = graphene.sublattices

The first argument to the general function is the list of primitive vectors of the lattice; the second one
is the coordinates of basis atoms. The honeycomb lattice has two basis atoms. Each type of basis atom
by itself forms a regular lattice of the same type as well, and those sublattices are referenced as a and b
above.
In the next step we define the shape of the scattering region (circle again) and add all lattice points
using the shape-functionality:

def make_system(r=10, w=2.0, pot=0.1):

#### Define the scattering region. ####


# circular scattering region
def circle(pos):
x, y = pos
return x ** 2 + y ** 2 < r ** 2

syst = kwant.Builder()

# w: width and pot: potential maximum of the p-n junction


def potential(site):
(x, y) = site.pos
d = y * cos_30 + x * sin_30
return pot * tanh(d / w)

syst[graphene.shape(circle, (0, 0))] = potential

As you can see, this works exactly the same for any kind of lattice. We add the onsite energies using a
function describing the p-n junction; in contrast to the previous tutorial, the potential value is this time
taken from the scope of make_system, since we keep the potential fixed in this example.
As a next step we add the hoppings, making use of HoppingKind. For illustration purposes we define
the hoppings ourselves instead of using graphene.neighbors():

hoppings = (((0, 0), a, b), ((0, 1), a, b), ((-1, 1), a, b))

The nearest-neighbor model for graphene contains only hoppings between different basis atoms. For this
type of hoppings, it is not enough to specify relative lattice indices, but we also need to specify the
proper target and source sublattices. Remember that the format of the hopping specification is (i,j),
target, source. In the previous examples (i.e. Matrix structure of on-site and hopping elements)
target=source=lat, whereas here we have to specify different sublattices. Furthermore, note that the
directions given by the lattice indices (1, 0) and (0, 1) are not orthogonal anymore, since they are given
with respect to the two primitive vectors [(1, 0), (sin_30, cos_30)].
Adding the hoppings however still works the same way:

syst[[kwant.builder.HoppingKind(*hopping) for hopping in hoppings]] = -1

Modifying the scattering region is also possible as before. Let’s do something crazy, and remove an atom
in sublattice A (which removes also the hoppings from/to this site) as well as add an additional link:

del syst[a(0, 0)]


syst[a(-2, 1), b(2, 2)] = -1

Note again that the conversion from a tuple (i,j) to site is done by the sublattices a and b.
The leads are defined almost as before:

2.5. Beyond square lattices: graphene 45


Kwant 1.3.1 documentation

# left lead
sym0 = kwant.TranslationalSymmetry(graphene.vec((-1, 0)))

def lead0_shape(pos):
x, y = pos
return (-0.4 * r < y < 0.4 * r)

lead0 = kwant.Builder(sym0)
lead0[graphene.shape(lead0_shape, (0, 0))] = -pot
lead0[[kwant.builder.HoppingKind(*hopping) for hopping in hoppings]] = -1

# The second lead, going to the top right


sym1 = kwant.TranslationalSymmetry(graphene.vec((0, 1)))

def lead1_shape(pos):
v = pos[1] * sin_30 - pos[0] * cos_30
return (-0.4 * r < v < 0.4 * r)

lead1 = kwant.Builder(sym1)
lead1[graphene.shape(lead1_shape, (0, 0))] = pot
lead1[[kwant.builder.HoppingKind(*hopping) for hopping in hoppings]] = -1

Note the method vec used in calculating the parameter for TranslationalSymmetry. The latter expects
a real-space symmetry vector, but for many lattices symmetry vectors are more easily expressed in the
natural coordinate system of the lattice. The vec-method is thus used to map a lattice vector to a
real-space vector.
Observe also that the translational vectors graphene.vec((-1, 0)) and graphene.vec((0, 1)) are
not orthogonal any more as they would have been in a square lattice – they follow the non-orthogonal
primitive vectors defined in the beginning.
Later, we will compute some eigenvalues of the closed scattering region without leads. This is why
we postpone attaching the leads to the system. Instead, we return the scattering region and the leads
separately.

return syst, [lead0, lead1]

The computation of some eigenvalues of the closed system is done in the following piece of code:

def compute_evs(syst):
# Compute some eigenvalues of the closed system
sparse_mat = syst.hamiltonian_submatrix(sparse=True)

evs = sla.eigs(sparse_mat, 2)[0]


print(evs.real)

Here we use in contrast to the previous example a sparse matrix and the sparse linear algebra functionality
of SciPy.
The code for computing the band structure and the conductance is identical to the previous examples,
and needs not be further explained here.
Finally, in the main function we make and plot the system:

def main():
pot = 0.1
syst, leads = make_system(pot=pot)

# To highlight the two sublattices of graphene, we plot one with


# a filled, and the other one with an open circle:
def family_colors(site):
return 0 if site.family == a else 1

46 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

# Plot the closed system without leads.


kwant.plot(syst, site_color=family_colors, site_lw=0.1, colorbar=False)

We customize the plotting: we set the site_colors argument of plot to a function which returns 0 for
sublattice a and 1 for sublattice b:

def family_colors(site):
return 0 if site.family == a else 1

The function plot shows these values using a color scale (grayscale by default). The symbol size is
specified in points, and is independent on the overall figure size.
Plotting the closed system gives this result:

10.0

7.5

5.0

2.5

0.0

2.5

5.0

7.5

10.0
10.0 7.5 5.0 2.5 0.0 2.5 5.0 7.5 10.0

Computing the eigenvalues of largest magnitude,

compute_evs(syst.finalized())

should yield two eigenvalues equal to [ 3.07869311, -3.06233144].


The remaining code of main attaches the leads to the system and plots it again:

2.5. Beyond square lattices: graphene 47


Kwant 1.3.1 documentation

10

10
15 10 5 0 5 10

It computes the band structure of one of lead 0:

48 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

1
energy [t]

3
3 2 1 0 1 2 3
momentum [(lattice constant)^-1]

showing all the features of a zigzag lead, including the flat edge state bands (note that the band structure
is not symmetric around zero energy, due to a potential in the leads).
Finally the transmission through the system is computed,

2.5. Beyond square lattices: graphene 49


Kwant 1.3.1 documentation

1.0

0.8
conductance [e^2/h]

0.6

0.4

0.2

0.0
0.20 0.15 0.10 0.05 0.00 0.05 0.10 0.15 0.20
energy [t]

showing the typical resonance-like transmission probability through an open quantum dot Technical
details
• In a lattice with more than one basis atom, you can always act either on all sublattices at the same
time, or on a single sublattice only.
For example, you can add lattice points for all sublattices in the current example using:

syst[graphene.shape(...)] = ...

or just for a single sublattice:

syst[a.shape(...)] = ...

and the same of course with b. Also, you can selectively remove points:

del syst[graphene.shape(...)]
del syst[a.shape(...)]

where the first line removes points in both sublattices, whereas the second line removes only points
in one sublattice.

2.6 Superconductors: orbital degrees of freedom, conservation laws


and symmetries

See also:
The complete source code of this example can be found in tutorial/superconductor.py

50 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

This example deals with superconductivity on the level of the Bogoliubov-de Gennes (BdG) equation.
In this framework, the Hamiltonian is given as

𝐻0 − 𝜇 Δ
𝐻=( )
Δ† 𝜇 − 𝒯𝐻0 𝒯−1

where 𝐻0 is the Hamiltonian of the system without superconductivity, 𝜇 the chemical potential, Δ the
superconducting order parameter, and 𝒯 the time-reversal operator. The BdG Hamiltonian introduces
electron and hole degrees of freedom (an artificial doubling - be aware of the fact that electron and hole
excitations are related!), which we will need to include in our model with Kwant.
For this we restrict ourselves to a simple spinless system without magnetic field, so that Δ is just a
number (which we choose real), and 𝒯𝐻0 𝒯−1 = 𝐻0∗ = 𝐻0 . Furthermore, note that the Hamiltonian has
particle-hole symmetry 𝒫, i. e. 𝒫𝐻𝒫−1 = −𝐻.
Care must be taken when transport calculations are done with the BdG equation. Electrons and holes
carry charge with opposite sign, such that it is necessary to separate the electron and hole degrees of
freedom in the scattering matrix. In particular, the conductance of a N-S-junction is given as

𝑒2
𝐺= (𝑁 − 𝑅ee + 𝑅he ) ,

where 𝑁 is the number of electron channels in the normal lead, and 𝑅ee the total probability of reflection
from electrons to electrons in the normal lead, and 𝑅eh the total probability of reflection from electrons
to holes in the normal lead. Fortunately, in Kwant it is straightforward to partition the scattering matrix
in these two degrees of freedom.
Let us consider a system that consists of a normal lead on the left, a superconductor on the right, and
a tunnel barrier in between:

We implement the BdG Hamiltonian in Kwant using a 2x2 matrix structure for all Hamiltonian matrix
elements, as we did previously in the spin example. We declare the square lattice and construct the
scattering region with the following:
def make_system(a=1, W=10, L=10, barrier=1.5, barrierpos=(3, 4),
mu=0.4, Delta=0.1, Deltapos=4, t=1.0, phs=True):
# Start with an empty tight-binding system. On each site, there
# are now electron and hole orbitals, so we must specify the
# number of orbitals per site. The orbital structure is the same
# as in the Hamiltonian.
lat = kwant.lattice.square(norbs=2)
syst = kwant.Builder()

#### Define the scattering region. ####


# The superconducting order parameter couples electron and hole orbitals
# on each site, and hence enters as an onsite potential.
# The pairing is only included beyond the point 'Deltapos' in the scattering region.
syst[(lat(x, y) for x in range(Deltapos) for y in range(W))] = (4 * t - mu) * tau_z
syst[(lat(x, y) for x in range(Deltapos, L) for y in range(W))] = (4 * t - mu) * tau_z +␣
↪Delta * tau_x

# The tunnel barrier


syst[(lat(x, y) for x in range(barrierpos[0], barrierpos[1])
for y in range(W))] = (4 * t + barrier - mu) * tau_z

2.6. Superconductors: orbital degrees of freedom, conservation laws and symmetries 51


Kwant 1.3.1 documentation

# Hoppings
syst[lat.neighbors()] = -t * tau_z

Note the new argument norbs to square. This is the number of orbitals per site in the discretized BdG
Hamiltonian - of course, norbs = 2, since each site has one electron orbital and one hole orbital. It is
necessary to specify norbs here, such that we may later separate the scattering matrix into electrons
and holes. Aside from this, creating the system is syntactically equivalent to spin example. The only
difference is that the Pauli matrices now act in electron-hole space. Note that the tunnel barrier is added
by overwriting previously set on-site matrix elements.
The superconducting order parameter is nonzero only in a part of the scattering region - the part to
the right of the tunnel barrier. Thus, the scattering region is split into a superconducting part (the
right side of it), and a normal part where the pairing is zero (the left side of it). The next step towards
computing conductance is to attach leads. Let’s attach two leads: a normal one to the left end, and a
superconducting one to the right end. Starting with the left lead, we have:

#### Define the leads. ####


# Left lead - normal, so the order parameter is zero.
sym_left = kwant.TranslationalSymmetry((-a, 0))
# Specify the conservation law used to treat electrons and holes separately.
# We only do this in the left lead, where the pairing is zero.
lead0 = kwant.Builder(sym_left, conservation_law=-tau_z, particle_hole=tau_y)
lead0[(lat(0, j) for j in range(W))] = (4 * t - mu) * tau_z
lead0[lat.neighbors()] = -t * tau_z

Note the two new new arguments in Builder, conservation_law and particle_hole. For the purpose
of computing conductance, conservation_law is the essential one, as it allows us to separate the electron
and hole degrees of freedom. Note that it is not necessary to specify particle_hole in Builder to
correctly compute the conductance in this example. We will discuss the argument particle_hole later
on. First, let us discuss conservation_law in more detail.
Observe that electrons and holes are uncoupled in the left (normal) lead, since the superconducting
order parameter that couples them is zero. Consequently, we may view the electron and hole degrees of
freedom as being conserved, and may therefore separate them in the Hamiltonian.
In more technical terms, the conservation law implies that the Hamiltonian can be block diagonalized
into uncoupled electron and hole blocks. Since the blocks are uncoupled, we can construct scattering
states in each block independently. Of course, any scattering state from the electron (hole) block is
entirely electron (hole) like. As a result, the scattering matrix separates into blocks that describe the
scattering between different types of carriers, such as electron to electron, hole to electron, et cetera.
As we saw above, conservation laws in Kwant are specified with the conservation_law argument in
Builder. Specifically, conservation_law is a matrix that acts on a single site and it must in addition
have integer eigenvalues. Of course, it must also commute with the onsite Hamiltonian and hoppings to
adjacent sites. Internally, Kwant then uses the eigenvectors of the conservation law to block diagonalize
the Hamiltonian. Here, we’ve specified the conservation law −𝜎𝑧 , such that the eigenvectors with eigen-
values −1 and 1 pick out the electron and hole blocks, respectively. Internally in Kwant, the blocks are
stored in the order of ascending eigenvalues of the conservation law.
In order to move on with the conductance calculation, let’s attach the second lead to the right side of
the scattering region:

# Right lead - superconducting, so the order parameter is included.


sym_right = kwant.TranslationalSymmetry((a, 0))
lead1 = kwant.Builder(sym_right)
lead1[(lat(0, j) for j in range(W))] = (4 * t - mu) * tau_z + Delta * tau_x
lead1[lat.neighbors()] = -t * tau_z

#### Attach the leads and return the system. ####


syst.attach_lead(lead0)
syst.attach_lead(lead1)

52 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

return syst

The second (right) lead is superconducting, such that the electron and hole blocks are coupled. Of
course, this means that we can not separate them into uncoupled blocks as we did before, and therefore
no conservation law is specified.
Kwant is now aware of the block structure of the Hamiltonian in the left lead. This means that we
can extract transmission and reflection amplitudes not only into the left lead, but also between different
conservation law blocks in the left lead. Generally if leads 𝑖 and 𝑗 both have a conservation law specified,
smatrix.transmission((i, a), (j, b)) gives us the scattering probability of carriers from block
𝑏 of lead 𝑗, to block 𝑎 of lead 𝑖. In our example, reflection from electrons to electrons in the left
lead is thus smatrix.transmission((0, 0), (0, 0)) (Don’t get confused by the fact that it says
transmission – transmission into the same lead is reflection), and reflection from electrons to holes is
smatrix.transmission((0, 1), (0, 0)):

def plot_conductance(syst, energies):


# Compute conductance
data = []
for energy in energies:
smatrix = kwant.smatrix(syst, energy)
# Conductance is N - R_ee + R_he
data.append(smatrix.submatrix((0, 0), (0, 0)).shape[0] -
smatrix.transmission((0, 0), (0, 0)) +
smatrix.transmission((0, 1), (0, 0)))

Note that smatrix.submatrix((0, 0), (0, 0)) returns the block concerning reflection of electrons to
electrons, and from its size we can extract the number of modes 𝑁 .
For the default parameters, we obtain the following conductance:

2.00

1.75

1.50

1.25
conductance [e^2/h]

1.00

0.75

0.50

0.25

0.00
0.00 0.05 0.10 0.15 0.20
energy [t]

2.6. Superconductors: orbital degrees of freedom, conservation laws and symmetries 53


Kwant 1.3.1 documentation

We a see a conductance that is proportional to the square of the tunneling probability within the gap,
and proportional to the tunneling probability above the gap. At the gap edge, we observe a resonant
Andreev reflection.
Remember that when we defined Builder for the left lead above, we not only declared an electron-
hole conservation law, but also that the Hamiltonian has the particle-hole symmetry 𝒫 = 𝜎𝑦 which
anticommutes with the Hamiltonian, using the argument particle_hole. In Kwant, whenever one or
more of the fundamental discrete symmetries (time-reversal, particle-hole and chiral) are present in a
lead Hamiltonian, they can be declared in Builder. Kwant then automatically uses them to construct
scattering states that obey the specified symmetries. In this example, we have a discrete symmetry
declared in addition to a conservation law. For any two conservation law blocks that are transformed to
each other by the discrete symmetry, Kwant then automatically computes the scattering states of one
block by applying the symmetry operator to the scattering states of the other.
Now, 𝒫 relates electrons and holes at opposite energies. However, a scattering problem is always solved at
a fixed energy, so generally 𝒫 does not give a relation between the electron and hole blocks. The exception
is of course at zero energy, in which case particle-hole symmetry transforms between the electron and
hole blocks, resulting in a symmetric scattering matrix. We can check the symmetry explicitly with

def check_PHS(syst):
# Scattering matrix
s = kwant.smatrix(syst, energy=0)
# Electron to electron block
s_ee = s.submatrix((0,0), (0,0))
# Hole to hole block
s_hh = s.submatrix((0,1), (0,1))
print('s_ee: \n', np.round(s_ee, 3))
print('s_hh: \n', np.round(s_hh[::-1, ::-1], 3))
print('s_ee - s_hh^*: \n',
np.round(s_ee - s_hh[::-1, ::-1].conj(), 3), '\n')
# Electron to hole block
s_he = s.submatrix((0,1), (0,0))
# Hole to electron block
s_eh = s.submatrix((0,0), (0,1))
print('s_he: \n', np.round(s_he, 3))
print('s_eh: \n', np.round(s_eh[::-1, ::-1], 3))
print('s_he + s_eh^*: \n',
np.round(s_he + s_eh[::-1, ::-1].conj(), 3))

which yields the output

s_ee:
[[ 0.538+0.823j 0.000-0.j ]
[ 0.000+0.j 0.515-0.856j]]
s_hh:
[[ 0.538-0.823j -0.000+0.j ]
[ 0.000-0.j 0.515+0.856j]]
s_ee - s_hh^*:
[[ 0.-0.j 0.-0.j]
[-0.-0.j -0.-0.j]]

s_he:
[[-0.000-0.j 0.054-0.j]
[ 0.179-0.j -0.000-0.j]]
s_eh:
[[ 0.000-0.j -0.054-0.j]
[-0.179+0.j 0.000-0.j]]
s_he + s_eh^*:
[[ 0.-0.j 0.-0.j]
[-0.-0.j -0.-0.j]]

Note that 𝒫 flips the sign of momentum, and for the parameters we consider here, there are two electron
and two hole modes active at zero energy. We thus reorder the matrix elements of the scattering matrix

54 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

blocks above, to ensure that the same matrix elements in the electron and hole blocks relate scattering
states and their particle hole partners. Technical details
• If you are only interested in particle (thermal) currents you do not need to separate the electron and
hole degrees of freedom. Still, separating them using a conservation law makes the lead calculation
in the solving phase more efficient.

2.7 Computing local quantities: densities and currents

In the previous tutorials we have mainly concentrated on calculating global properties such as conductance
and band structures. Often, however, insight can be gained from calculating locally-defined quantities,
that is, quantities defined over individual sites or hoppings in your system. In the Closed systems
tutorial we saw how we could visualize the density associated with the eigenstates of a system using
kwant.plotter.map.
In this tutorial we will see how we can calculate more general quantities than simple densities by studying
spin transport in a system with a magnetic texture.
See also:
The complete source code of this example can be found in tutorial/magnetic_texture.py

2.7.1 Introduction

Our starting point will be the following spinful tight-binding model on a square lattice:

𝐻 = − ∑ ∑ |𝑖𝛼⟩⟨𝑗𝛼| + 𝐽 ∑ ∑ m𝑖 ⋅ 𝛼𝛽 |𝑖𝛼⟩⟨𝑖𝛽|,
⟨𝑖𝑗⟩ 𝛼 𝑖 𝛼𝛽

where latin indices run over sites, and greek indices run over spin. We can identify the first term as a
nearest-neighbor hopping between like-spins, and the second as a term that couples spins on the same
site. The second term acts like a magnetic field of strength 𝐽 that varies from site to site and that, on
site 𝑖, points in the direction of the unit vector m𝑖 . 𝛼𝛽 is a vector of Pauli matrices. We shall take the
following form for m𝑖 :
𝑇
𝑥𝑖 𝑦
m𝑖 = ( sin 𝜃𝑖 , 2 𝑖 2 sin 𝜃𝑖 , cos 𝜃𝑖 ) ,
𝑥2𝑖 + 𝑦𝑖2 𝑥𝑖 + 𝑦𝑖
𝜋 𝑟 − 𝑟0
𝜃𝑖 = tanh 𝑖 ,
2 𝛿

where 𝑥𝑖 and 𝑦𝑖 are the 𝑥 and 𝑦 coordinates of site 𝑖, and 𝑟𝑖 = √𝑥2𝑖 + 𝑦𝑖2 .
To define this model in Kwant we start as usual by defining functions that depend on the model param-
eters:

def field_direction(pos, r0, delta):


x, y = pos
r = np.linalg.norm(pos)
r_tilde = (r - r0) / delta
theta = (tanh(r_tilde) - 1) * (pi / 2)

if r == 0:
m_i = [0, 0, 1]
else:
m_i = [
(x / r) * sin(theta),
(y / r) * sin(theta),
cos(theta),
]

2.7. Computing local quantities: densities and currents 55


Kwant 1.3.1 documentation

return np.array(m_i)

def scattering_onsite(site, r0, delta, J):


m_i = field_direction(site.pos, r0, delta)
return J * np.dot(m_i, sigma)

def lead_onsite(site, J):


return J * sigma_z

and define our system as a square shape on a square lattice with two orbitals per site, with leads attached
on the left and right:

lat = kwant.lattice.square(norbs=2)

def make_system(L=80):

syst = kwant.Builder()

def square(pos):
return all(-L/2 < p < L/2 for p in pos)

syst[lat.shape(square, (0, 0))] = scattering_onsite


syst[lat.neighbors()] = -sigma_0

lead = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)),


conservation_law=-sigma_z)

lead[lat.shape(square, (0, 0))] = lead_onsite


lead[lat.neighbors()] = -sigma_0

syst.attach_lead(lead)
syst.attach_lead(lead.reversed())

return syst

Below is a plot of a projection of m𝑖 onto the x-y plane inside the scattering region. The z component
is shown by the color scale:

56 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

1.00
40

0.75
30

20 0.50

10 0.25

0 0.00

10 0.25

20 0.50

30
0.75

40
40 30 20 10 0 10 20 30 40
We will now be interested in analyzing the form of the scattering states that originate from the left lead:

params = dict(r0=20, delta=10, J=1)


wf = kwant.wave_function(syst, energy=-1, params=params)
psi = wf(0)[0]

2.7.2 Local densities

If we were simulating a spinless system with only a single degree of freedom, then calculating the density
on each site would be as simple as calculating the absolute square of the wavefunction like:

density = np.abs(psi)**2

When there are multiple degrees of freedom per site, however, one has to be more careful. In the present
case with two (spin) degrees of freedom per site one could calculate the per-site density like:

# even (odd) indices correspond to spin up (down)


up, down = psi[::2], psi[1::2]
density = np.abs(up)**2 + np.abs(down)**2

With more than one degree of freedom per site we have more freedom as to what local quantities we can
meaningfully compute. For example, we may wish to calculate the local z-projected spin density. We
could calculate this in the following way:

# spin down components have a minus sign


spin_z = np.abs(up)**2 - np.abs(down)**2

2.7. Computing local quantities: densities and currents 57


Kwant 1.3.1 documentation

If we wanted instead to calculate the local y-projected spin density, we would need to use an even more
complicated expression:

# spin down components have a minus sign


spin_y = 1j * (down.conjugate() * up - up.conjugate() * down)

The kwant.operator module aims to alleviate somewhat this tedious book-keeping by providing a simple
interface for defining operators that act on wavefunctions. To calculate the above quantities we would
use the Density operator like so:

rho = kwant.operator.Density(syst)
rho_sz = kwant.operator.Density(syst, sigma_z)
rho_sy = kwant.operator.Density(syst, sigma_y)

# calculate the expectation values of the operators with 'psi'


density = rho(psi)
spin_z = rho_sz(psi)
spin_y = rho_sy(psi)

Density takes a System as its first parameter as well as (optionally) a square matrix that defines the
quantity that you wish to calculate per site. When an instance of a Density is then evaluated with a
wavefunction, the quantity

𝜌𝑖 = †𝑖 M𝑖

is calculated for each site 𝑖, where 𝑖 is a vector consisting of the wavefunction components on that site
and M is the square matrix referred to previously.
Below we can see colorplots of the above-calculated quantities. The array that is returned by evaluating
a Density can be used directly with kwant.plotter.map:
0 z y
40 40 40

30 30 30

20 20 20

10 10 10

0 0 0

10 10 10

20 20 20

30 30 30

40 40 40
40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40

Technical Details
Although we refer loosely to “densities” and “operators” above, a Density actually represents a collection
of linear operators. This can be made clear by rewriting the above definition of 𝜌𝑖 in the following way:

𝜌𝑖 = ∑ 𝜓𝛼 ℳ𝑖𝛼𝛽 𝜓𝛽
𝛼𝛽

where greek indices run over the degrees of freedom in the Hilbert space of the scattering region and
latin indices run over sites. We can this identify ℳ𝑖𝛼𝛽 as the components of a rank-3 tensor and can
represent them as a “vector of matrices”:

M 0 … 0 0 …
ℳ=⎡⎛
⎜ 0 0 … ⎞
⎟ , ⎛
⎜0 M …⎞⎟ , …⎤
⎢ ⎥
⎣⎝ ⋮ ⋮ ⋱ ⎠ ⎝⋮ ⋮ ⋱⎠ ⎦

where M is defined as in the main text, and the 0 are zero matrices of the same shape as M.

58 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

2.7.3 Local currents

kwant.operator also has a class Current for calculating local currents, analogously to the local “den-
sities” described above. If one has defined a density via a matrix M and the above equation, then one
can define a local current flowing from site 𝑏 to site 𝑎:

𝐽𝑎𝑏 = 𝑖 (†𝑏 (H𝑎𝑏 )† M𝑎 − †𝑎 MH𝑎𝑏𝑏 ) ,

where H𝑎𝑏 is the hopping matrix from site 𝑏 to site 𝑎. For example, to calculate the local current and
spin current:

J_0 = kwant.operator.Current(syst)
J_z = kwant.operator.Current(syst, sigma_z)
J_y = kwant.operator.Current(syst, sigma_y)

# calculate the expectation values of the operators with 'psi'


current = J_0(psi)
spin_z_current = J_z(psi)
spin_y_current = J_y(psi)

Evaluating a Current operator on a wavefunction returns a 1D array of values that can be directly used
with kwant.plotter.current:
J0 Jz Jy
40 40 40

30 30 30

20 20 20

10 10 10

0 0 0

10 10 10

20 20 20

30 30 30

40 40 40
40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40

Note: Evaluating a Current operator on a wavefunction returns a 1D array of the same length as the
number of hoppings in the system, ordered in the same way as the edges in the system’s graph.

Technical Details
Similarly to how we saw in the previous section that Density can be thought of as a collection of
operators, Current can be defined in a similar way. Starting from the definition of a “density”:

𝜌𝑎 = ∑ 𝜓𝛼 ℳ𝑎𝛼𝛽 𝜓𝛽 ,
𝛼𝛽

we can define currents 𝐽𝑎𝑏 via the continuity equation:

𝜕𝜌𝑎
− ∑ 𝐽𝑎𝑏 = 0
𝜕𝑡 𝑏

where the sum runs over sites 𝑏 neigboring site 𝑎. Plugging in the definition for 𝜌𝑎 , along with the
Schrödinger equation and the assumption that ℳ is time independent, gives:


𝐽𝑎𝑏 = ∑ 𝜓𝛼 (𝑖 ∑ ℋ∗𝑎𝑏𝛾𝛼 ℳ𝑎𝛾𝛽 − ℳ𝑎𝛼𝛾 ℋ𝑎𝑏𝛾𝛽 ) 𝜓𝛽 ,
𝛼𝛽 𝛾

2.7. Computing local quantities: densities and currents 59


Kwant 1.3.1 documentation

where latin indices run over sites and greek indices run over the Hilbert space degrees of freedom, and

⋱ ⋮ ⋮ ⋮ ⋰

⎜⋯ ⋱ 0 H𝑎𝑏 ⋯⎞⎟
⎜ ⎟
ℋ𝑎𝑏 =⎜
⎜⋯ 0 ⋱ 0 ⋯⎟⎟ .

⎜⋯ 0 ⎟
0 ⋱ ⋯⎟
⎝⋰ ⋮ ⋮ ⋮ ⋱⎠

i.e. ℋ𝑎𝑏 is a matrix that is zero everywhere except on elements connecting from site 𝑏 to site 𝑎, where
it is equal to the hopping matrix H𝑎𝑏 between these two sites.
This allows us to identify the rank-4 quantity

𝒥𝑎𝑏𝛼𝛽 = 𝑖 ∑ ℋ∗𝑎𝑏𝛾𝛼 ℳ𝑎𝛾𝛽 − ℳ𝑎𝛼𝛾 ℋ𝑎𝑏𝛾𝛽


𝛾

as the local current between connected sites.


The diagonal part of this quantity, 𝒥𝑎𝑎 , represents the extent to which the density defined by ℳ𝑎 is not
conserved on site 𝑎. It can be calculated using Source, rather than Current, which only computes the
off-diagonal part.

2.7.4 Spatially varying operators

The above examples are reasonably simple in the sense that the book-keeping required to manually
calculate the various densities and currents is still manageable. Now we shall look at the case where we
wish to calculate some projected spin currents, but where the spin projection axis varies from place to
place. More specifically, we want to visualize the spin current along the direction of m𝑖 , which changes
continuously over the whole scattering region.
Doing this is as simple as passing a function when instantiating the Current, instead of a constant
matrix:

def following_m_i(site, r0, delta):


m_i = field_direction(site.pos, r0, delta)
return np.dot(m_i, sigma)

J_m = kwant.operator.Current(syst, following_m_i)

# evaluate the operator


m_current = J_m(psi, params=dict(r0=25, delta=10))

The function must take a Site as its first parameter, and may optionally take other parameters (i.e. it
must have the same signature as a Hamiltonian onsite function), and must return the square matrix that
defines the operator we wish to calculate.

Note: In the above example we had to pass the extra parameters needed by the following_operator
function via the param keyword argument. In general you must pass all the parameters needed by
the Hamiltonian via params (as you would when calling smatrix or wave_function). In the previous
examples, however, we used the fact that the system hoppings do not depend on any parameters (these
are the only Hamiltonian elements required to calculate currents) to avoid passing the system parameters
for the sake of brevity.

Using this we can see that the spin current is essentially oriented along the direction of 𝑚𝑖 in the present
regime where the onsite term in the Hamiltonian is dominant:

60 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

Jmi Jz
40 40

30 30

20 20

10 10

0 0

10 10

20 20

30 30

40 40
40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40

Note: Although this example used exclusively Current, you can do the same with Density.

2.7.5 Defining operators over parts of a system

Another useful feature of kwant.operator is the ability to calculate operators over selected parts of a
system. For example, we may wish to calculate the total density of states in a certain part of the system,
or the current flowing through a cut in the system. We can do this selection when creating the operator
by using the keyword parameter where.

Density of states in a circle

To calculate the density of states inside a circle of radius 20 we can simply do:
def circle(site):
return np.linalg.norm(site.pos) < 20

rho_circle = kwant.operator.Density(syst, where=circle, sum=True)

all_states = np.vstack((wf(0), wf(1)))


dos_in_circle = sum(rho_circle(p) for p in all_states) / (2 * pi)
print('density of states in circle:', dos_in_circle)

density of states in circle: 778.648587165

note that we also provide sum=True, which means that evaluating the operator on a wavefunction will
produce a single scalar. This is semantically equivalent to providing sum=False (the default) and running
numpy.sum on the output.

Current flowing through a cut

Below we calculate the probability current and z-projected spin current near the interfaces with the left
and right leads.
def left_cut(site_to, site_from):
return site_from.pos[0] <= -39 and site_to.pos[0] > -39

2.7. Computing local quantities: densities and currents 61


Kwant 1.3.1 documentation

def right_cut(site_to, site_from):


return site_from.pos[0] < 39 and site_to.pos[0] >= 39

J_left = kwant.operator.Current(syst, where=left_cut, sum=True)


J_right = kwant.operator.Current(syst, where=right_cut, sum=True)

Jz_left = kwant.operator.Current(syst, sigma_z, where=left_cut, sum=True)


Jz_right = kwant.operator.Current(syst, sigma_z, where=right_cut, sum=True)

print('J_left:', J_left(psi), ' J_right:', J_right(psi))


print('Jz_left:', Jz_left(psi), ' Jz_right:', Jz_right(psi))

J_left: 0.957446786044 J_right: 0.957446786044


Jz_left: 0.942580711424 Jz_right: 0.960155316092

We see that the probability current is conserved across the scattering region, but the z-projected spin
current is not due to the fact that the Hamiltonian does not commute with 𝜎𝑧 everywhere in the scattering
region.

Note: where can also be provided as a sequence of Site or a sequence of hoppings (i.e. pairs of Site),
rather than a function.

2.7.6 Advanced Topics

Using bind for speed

In most of the above examples we only used each operator once after creating it. Often one will want to
evaluate an operator with many different wavefunctions, for example with all scattering wavefunctions at
a certain energy, but with the same set of parameters. In such cases it is best to tell the operator to pre-
compute the onsite matrices and any necessary Hamiltonian elements using the given set of parameters,
so that this work is not duplicated every time the operator is evaluated.
This can be achieved with bind:

Warning: Take care that you do not use an operator that was bound to a particular set of parameters
with wavefunctions calculated with a different set of parameters. This will almost certainly give
incorrect results.

J_m = kwant.operator.Current(syst, following_m_i)


J_z = kwant.operator.Current(syst, sigma_z)

J_m_bound = J_m.bind(params=dict(r0=25, delta=10, J=1))


J_z_bound = J_z.bind(params=dict(r0=25, delta=10, J=1))

# Sum current local from all scattering states on the left at energy=-1
wf_left = wf(0)
J_m_left = sum(J_m_bound(p) for p in wf_left)
J_z_left = sum(J_z_bound(p) for p in wf_left)

62 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

Jmi (from left) J z (from left)


40 40

30 30

20 20

10 10

0 0

10 10

20 20

30 30

40 40
40 30 20 10 0 10 20 30 40 40 30 20 10 0 10 20 30 40

2.8 Plotting Kwant systems and data in various styles

The plotting functionality of Kwant has been used extensively (through plot and map) in the previous
tutorials. In addition to this basic use, plot offers many options to change the plotting style extensively.
It is the goal of this tutorial to show how these options can be used to achieve various very different
objectives.

2.8.1 2D example: graphene quantum dot

See also:
The complete source code of this example can be found in tutorial/plot_graphene.py
We begin by first considering a circular graphene quantum dot (similar to what has been used in parts
of the tutorial Beyond square lattices: graphene.) In contrast to previous examples, we will also use
hoppings beyond next-nearest neighbors:

lat = kwant.lattice.honeycomb()
a, b = lat.sublattices

def make_system(r=8, t=-1, tp=-0.1):

def circle(pos):
x, y = pos
return x**2 + y**2 < r**2

syst = kwant.Builder()
syst[lat.shape(circle, (0, 0))] = 0
syst[lat.neighbors()] = t
syst.eradicate_dangling()
if tp:
syst[lat.neighbors(2)] = tp

return syst

Note that adding hoppings hoppings to the n-th nearest neighbors can be simply done by passing n
as an argument to neighbors. Also note that we use the method eradicate_dangling to get rid of

2.8. Plotting Kwant systems and data in various styles 63


Kwant 1.3.1 documentation

single atoms sticking out of the shape. It is necessary to do so before adding the next-nearest-neighbor
hopping1 .
Of course, the system can be plotted simply with default settings:

def plot_system(syst):
kwant.plot(syst)

However, due to the richer structure of the lattice, this results in a rather busy plot:

8 6 4 2 0 2 4 6 8

A much clearer plot can be obtained by using different colors for both sublattices, and by having different
line widths for different hoppings. This can be achieved by passing a function to the arguments of plot,
instead of a constant. For properties of sites, this must be a function taking one site as argument, for
hoppings a function taking the start end end site of hopping as arguments:

def family_color(site):
return 'black' if site.family == a else 'white'

def hopping_lw(site1, site2):

1 A dangling site is defined as having only one hopping connecting it to the rest. With next-nearest-neighbor hopping

also all sites that are dangling with only nearest-neighbor hopping have more than one hopping.

64 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

return 0.04 if site1.family == site2.family else 0.1

kwant.plot(syst, site_lw=0.1, site_color=family_color, hop_lw=hopping_lw)

Note that since we are using an unfinalized Builder, a site is really an instance of Site. With these
adjustments we arrive at a plot that carries the same information, but is much easier to interpret:

8 6 4 2 0 2 4 6 8

Apart from plotting the system itself, plot can also be used to plot data living on the system.
As an example, we now compute the eigenstates of the graphene quantum dot and intend to plot the
wave function probability in the quantum dot. For aesthetic reasons (the wave functions look a bit nicer),
we restrict ourselves to nearest-neighbor hopping. Computing the wave functions is done in the usual
way (note that for a large-scale system, one would probably want to use sparse linear algebra):
def plot_data(syst, n):
import scipy.linalg as la

syst = syst.finalized()
ham = syst.hamiltonian_submatrix()
evecs = la.eigh(ham)[1]

2.8. Plotting Kwant systems and data in various styles 65


Kwant 1.3.1 documentation

wf = abs(evecs[:, n])**2

In most cases, to plot the wave function probability, one wouldn’t use plot, but rather map. Here, we
plot the n-th wave function using it:

kwant.plotter.map(syst, wf, oversampling=10, cmap='gist_heat_r')

This results in a standard pseudocolor plot, showing in this case (n=225) a graphene edge state, i.e. a
wave function mostly localized at the zigzag edges of the quantum dot.

0.035
8

6 0.030

4
0.025

2
0.020
0

0.015
2

4 0.010

6
0.005
6 4 2 0 2 4 6

0.000

However although in general preferable, map has a few deficiencies for this small system: For example,
there are a few distortions at the edge of the dot. (This cannot be avoided in the type of interpolation
used in map). However, we can also use plot to achieve a similar, but smoother result.
For this note that plot can also take an array of floats (or function returning floats) as value for the
site_color argument (the same holds for the hoppings). Via the colormap specified in cmap these are
mapped to color, just as map does! In addition, we can also change the symbol shape depending on the
sublattice. With a triangle pointing up and down on the respective sublattice, the symbols used by plot
fill the space completely:

66 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

def family_shape(i):
site = syst.sites[i]
return ('p', 3, 180) if site.family == a else ('p', 3, 0)

def family_color(i):
return 'black' if syst.sites[i].family == a else 'white'

kwant.plot(syst, site_color=wf, site_symbol=family_shape,


site_size=0.5, hop_lw=0, cmap='gist_heat_r')

Note that with hop_lw=0 we deactivate plotting the hoppings (that would not serve any purpose here).
Moreover, site_size=0.5 guarantees that the two different types of triangles touch precisely: By default,
plot takes all sizes in units of the nearest-neighbor spacing. site_size=0.5 thus means half the distance
between neighboring sites (and for the triangles this is interpreted as the radius of the inner circle).
Finally, note that since we are dealing with a finalized system now, a site i is represented by an integer.
In order to obtain the original Site, syst.sites[i] can be used.
With this we arrive at

0.035
8
0.030
6

4 0.025

2
0.020
0

2 0.015

4
0.010

6
0.005
8 6 4 2 0 2 4 6 8

0.000

with the same information as map, but with a cleaner look.

2.8. Plotting Kwant systems and data in various styles 67


Kwant 1.3.1 documentation

The way how data is presented of course influences what features of the data are best visible in a given
plot. With plot one can easily go beyond pseudocolor-like plots. For example, we can represent the
wave function probability using the symbols itself:

def site_size(i):
return 3 * wf[i] / wf.max()

kwant.plot(syst, site_size=site_size, site_color=(0, 0, 1, 0.3),


hop_lw=0.1)

Here, we choose the symbol size proportional to the wave function probability, while the site color is
transparent to also allow for overlapping symbols to be visible. The hoppings are also plotted in order
to show the underlying lattice.
With this, we arrive at

8 6 4 2 0 2 4 6 8

which shows the edge state nature of the wave function most clearly.

68 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

2.8.2 3D example: zincblende structure

See also:
The complete source code of this example can be found in tutorial/plot_zincblende.py
Zincblende is a very common crystal structure of semiconductors. It is a face-centered cubic crystal with
two inequivalent atoms in the unit cell (i.e. two different types of atoms, unlike diamond which has the
same crystal structure, but two equivalent atoms per unit cell).
It is very easily generated in Kwant with kwant.lattice.general:

lat = kwant.lattice.general([(0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0)],


[(0, 0, 0), (0.25, 0.25, 0.25)])
a, b = lat.sublattices

Note how we keep references to the two different sublattices for later use.
A three-dimensional structure is created as easily as in two dimensions, by using the shape-functionality:

def make_cuboid(a=15, b=10, c=5):


def cuboid_shape(pos):
x, y, z = pos
return 0 <= x < a and 0 <= y < b and 0 <= z < c

syst = kwant.Builder()
syst[lat.shape(cuboid_shape, (0, 0, 0))] = None
syst[lat.neighbors()] = None

return syst

We restrict ourselves here to a simple cuboid, and do not bother to add real values for onsite and hopping
energies, but only the placeholder None (in a real calculation, several atomic orbitals would have to be
considered).
plot can plot 3D systems just as easily as its two-dimensional counterparts:

syst = make_cuboid()

kwant.plot(syst)

resulting in

2.8. Plotting Kwant systems and data in various styles 69


Kwant 1.3.1 documentation

8
6
4
2
0
2
4

12
10
8
0 6
2 4
4 2
6
8 0
10
12 2
14

You might notice that the standard options for plotting are quite different in 3D than in 2D. For example,
by default hoppings are not printed, but sites are instead represented by little “balls” touching each other
(which is achieved by a default site_size=0.5). In fact, this style of plotting 3D shows quite decently
the overall geometry of the system.
When plotting into a window, the 3D plots can also be rotated and scaled arbitrarily, allowing for a good
inspection of the geometry from all sides.

Note: Interactive 3D plots usually do not have the proper aspect ratio, but are a bit squashed.
This is due to bugs in matplotlib’s 3D plotting module that does not properly honor the corresponding
arguments. By resizing the plot window however one can manually adjust the aspect ratio.

Also for 3D it is possible to customize the plot. For example, we can explicitly plot the hoppings as lines,
and color sites differently depending on the sublattice:
syst = make_cuboid(a=1.5, b=1.5, c=1.5)

def family_colors(site):
return 'r' if site.family == a else 'g'

70 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

kwant.plot(syst, site_size=0.18, site_lw=0.01, hop_lw=0.05,


site_color=family_colors)

which results in a 3D plot that allows to interactively (when plotted in a window) explore the crystal
structure:

1.2

1.0

0.8

0.6

0.4

0.2

0.0
1.2
1.0
0.8
0.0 0.6
0.2
0.4 0.4
0.6
0.8 0.2
1.0 0.0
1.2

Hence, a few lines of code using Kwant allow to explore all the different crystal lattices out there!

Note:
• The 3D plots are in fact only fake 3D. For example, sites will always be plotted above hoppings
(this is due to the limitations of matplotlib’s 3d module)
• Plotting hoppings in 3D is inherently much slower than plotting sites. Hence, this is not done by
default.

2.8. Plotting Kwant systems and data in various styles 71


Kwant 1.3.1 documentation

2.9 Calculating spectral density with the kernel polynomial method

We have already seen in the “Closed systems” tutorial that we can use Kwant simply to build Hamilto-
nians, which we can then directly diagonalize using routines from Scipy.
This already allows us to treat systems with a few thousand sites without too many problems. For larger
systems one is often not so interested in the exact eigenenergies and eigenstates, but more in the density
of states.
The kernel polynomial method (KPM), is an algorithm to obtain a polynomial expansion of the density
of states. It can also be used to calculate the spectral density of arbitrary operators. Kwant has an
implementation of the KPM method that is based on the algorithms presented in Ref.1 .
Roughly speaking, KPM approximates the density of states (or any other spectral density) by expanding
the action of the Hamiltonian (and operator of interest) on a (small) set of random vectors as a sum
of Chebyshev polynomials up to some order, and then averaging. The accuracy of the method can be
tuned by modifying the order of the Chebyshev expansion and the number of random vectors. See notes
on accuracy below for details.
See also:
The complete source code of this example can be found in tutorial/kernel_polynomial_method.py
Performance and accuracy
The KPM method is especially well suited for large systems, and in the case when one is not interested
in individual eigenvalues, but rather in obtaining an approximate spectral density.
The accuracy in the energy resolution is dominated by the number of moments. The lowest accuracy is
at the center of the spectrum, while slightly higher accuracy is obtained at the edges of the spectrum.
If we use the KPM method (with the Jackson kernel, see Ref.1 ) to describe a delta peak at the center
of the spectrum, we will obtain a function similar to a Gaussian of width 𝜎 = 𝜋𝑎/𝑁 , where 𝑁 is the
number of moments, and 𝑎 is the width of the spectrum.
On the other hand, the random vectors will explore the range of the spectrum, and as the system gets
bigger, the number of random vectors that are necessary to sample the whole spectrum reduces. Thus,
a small number of random vectors is in general enough, and increasing this number will not result in a
visible improvement of the approximation.

2.9.1 Introduction

Our aim is to use the kernel polynomial method to obtain the spectral density 𝜌𝐴 (𝐸), as a function of
the energy 𝐸, of some Hilbert space operator 𝐴. We define

𝜌𝐴 (𝐸) = 𝜌(𝐸)𝐴(𝐸),

where 𝐴(𝐸) is the expectation value of 𝐴 for all the eigenstates of the Hamiltonian with energy 𝐸, and
the density of states is
𝐷−1
𝜌(𝐸) = ∑ 𝛿(𝐸 − 𝐸𝑘 ),
𝑘=0

𝐷 being the Hilbert space dimension, and 𝐸𝑘 the eigenvalues.


In the special case when 𝐴 is the identity, then 𝜌𝐴 (𝐸) is simply 𝜌(𝐸), the density of states.

2.9.2 Calculating the density of states

In the following example, we will use the KPM implementation in Kwant to obtain the density of states
of a graphene disk.
1 Rev. Mod. Phys., Vol. 78, No. 1 (2006).

72 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

We start by importing kwant and defining our system.

# necessary imports
import kwant
import numpy as np

# define the system


def make_syst(r=30, t=-1, a=1):
syst = kwant.Builder()
lat = kwant.lattice.honeycomb(a, norbs=1)

def circle(pos):
x, y = pos
return x ** 2 + y ** 2 < r ** 2

syst[lat.shape(circle, (0, 0))] = 0.


syst[lat.neighbors()] = t
syst.eradicate_dangling()

return syst

After making a system we can then create a SpectralDensity object that represents the density of
states for this system.

fsyst = make_syst().finalized()

spectrum = kwant.kpm.SpectralDensity(fsyst)

The SpectralDensity can then be called like a function to obtain a sequence of energies in the spectrum
of the Hamiltonian, and the corresponding density of states at these energies.

energies, densities = spectrum()

When called with no arguments, an optimal set of energies is chosen (these are not evenly distributed
over the spectrum, see Ref.1 for details), however it is also possible to provide an explicit sequence of
energies at which to evaluate the density of states.

energy_subset = np.linspace(0, 2)
density_subset = spectrum(energy_subset)

2.9. Calculating spectral density with the kernel polynomial method 73


Kwant 1.3.1 documentation

densities
2000 density subset

1500
DoS [a.u.]

1000

500

0
3 2 1 0 1 2 3
energy [t]
In addition to being called like functions, SpectralDensity objects also have a method integrate which
can be used to integrate the density of states against some distribution function over the whole spectrum.
If no distribution function is specified, then the uniform distribution is used:

print('identity resolution:', spectrum.integrate())

identity resolution: 6493.0

We see that the integral of the density of states is normalized to the total number of available states in
the system. If we wish to calculate, say, the number of states populated in equilibrium, then we should
integrate with respect to a Fermi-Dirac distribution:

# Fermi energy 0.1 and temperature 0.2


fermi = lambda E: 1 / (np.exp((E - 0.1) / 0.2) + 1)

print('number of filled states:', spectrum.integrate(fermi))

number of filled states: 3308.44698264

Stability and performance: spectral bounds


The KPM method internally rescales the spectrum of the Hamiltonian to the interval (-1, 1) (see Ref1
for details), which requires calculating the boundaries of the spectrum (using scipy.sparse.linalg.
eigsh). This can be very costly for large systems, so it is possible to pass this explicitly as via the
bounds parameter when instantiating the SpectralDensity (see the class documentation for details).
Additionally, SpectralDensity accepts a parameter epsilon, which ensures that the rescaled Hamilto-
nian (used internally), always has a spectrum strictly contained in the interval (-1, 1). If bounds are
not provided then the tolerance on the bounds calculated with scipy.sparse.linalg.eigsh is set to
epsilon/2.

74 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

2.9.3 Increasing the accuracy of the approximation

SpectralDensity has two methods for increasing the accuracy of the method, each of which offers
different levels of control over what exactly is changed.
The simplest way to obtain a more accurate solution is to use the add_moments method:

spectrum.add_moments(energy_resolution=0.03)

This will update the number of calculated moments and also the default number of sampling points
such that the maximum distance between successive energy points is energy_resolution (see notes on
accuracy).

density
2500 higher energy resolution

2000

1500
DoS [a.u.]

1000

500

0
3 2 1 0 1 2 3
energy [t]
Alternatively, you can directly increase the number of moments with add_moments, or the number of
random vectors with add_vectors.

spectrum.add_moments(100)
spectrum.add_vectors(5)

2.9. Calculating spectral density with the kernel polynomial method 75


Kwant 1.3.1 documentation

density
2500 higher number of moments

2000
DoS [a.u.]

1500

1000

500

0
3 2 1 0 1 2 3
energy [t]

2.9.4 Calculating the spectral density of an operator

Above, we saw how to calculate the density of states by creating a SpectralDensity and passing it a
finalized Kwant system. When instantiating a SpectralDensity we may optionally supply an operator
in addition to the system. In this case it is the spectral density of the given operator that is calculated.
SpectralDensity accepts the operators in a few formats:
• explicit matrices (numpy array of scipy sparse matrices will work)
• operators from kwant.operator
If an explicit matrix is provided then it must have the same shape as the system Hamiltonian.

# identity matrix
matrix_op = scipy.sparse.eye(len(fsyst.sites))
matrix_spectrum = kwant.kpm.SpectralDensity(fsyst, operator=matrix_op)

Or, to do the same calculation using kwant.operator.Density:

# 'sum=True' means we sum over all the sites


kwant_op = kwant.operator.Density(fsyst, sum=True)
operator_spectrum = kwant.kpm.SpectralDensity(fsyst, operator=kwant_op)

Using operators from kwant.operator allows us to calculate quantities such as the local density of states
by telling the operator not to sum over all the sites of the system:

# 'sum=False' is the default, but we include it explicitly here for clarity.


kwant_op = kwant.operator.Density(fsyst, sum=False)
local_dos = kwant.kpm.SpectralDensity(fsyst, operator=kwant_op)

SpectralDensity will properly handle this vector output, which allows us to plot the local density of
states at different point in the spectrum:

76 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

zero_energy_ldos = local_dos(energy=0)
finite_energy_ldos = local_dos(energy=1)

_, axes = plt.subplots(1, 2, figsize=(12, 7))


plot_ldos(fsyst, axes,[
('energy = 0', zero_energy_ldos),
('energy = 1', finite_energy_ldos),
])

energy = 0 energy = 1
30 30

20 20

10 10

0 0

10 10

20 20

30 30
30 20 10 0 10 20 30 30 20 10 0 10 20 30

This nicely illustrates the edge states of the graphene dot at zero energy, and the bulk states at higher
energy.

2.9.5 Advanced topics

Custom distributions for random vectors

By default SpectralDensity will use random vectors whose components are unit complex numbers with
phases drawn from a uniform distribution. There are several reasons why you may wish to make a
different choice of distribution for your random vectors, for example to enforce certain symmetries or to
only use real-valued vectors.
To change how the random vectors are generated, you need only specify a function that takes the
dimension of the Hilbert space as a single parameter, and which returns a vector in that Hilbert space:

# construct vectors with n random elements -1 or +1.


def binary_vectors(n):
return np.rint(np.random.random_sample(n)) * 2 - 1

custom_factory = kwant.kpm.SpectralDensity(fsyst,
vector_factory=binary_vectors)

Reproducible calculations

Because KPM internally uses random vectors, running the same calculation twice will not give bit-for-bit
the same result. However, similarly to the funcions in rmt, the random number generator can be directly
manipulated by passing a value to the rng parameter of SpectralDensity. rng can itself be a random
number generator, or it may simply be a seed to pass to the numpy random number generator (that is
used internally by default).

2.9. Calculating spectral density with the kernel polynomial method 77


Kwant 1.3.1 documentation

Defining operators as sesquilinear maps

Above, we showed how SpectralDensity can calculate the spectral density of operators, and how we can
define operators by using kwant.operator. If you need even more flexibility, SpectralDensity will also
accept a function as its operator parameter. This function must itself take two parameters, (bra, ket)
and must return either a scalar or a one-dimensional array. In order to be meaningful the function must
be a sesquilinear map, i.e. antilinear in its first argument, and linear in its second argument. Below, we
compare two methods for computing the local density of states, one using kwant.operator.Density,
and the other using a custom function.

rho = kwant.operator.Density(fsyst, sum=True)

# sesquilinear map that does the same thing as `rho`


def rho_alt(bra, ket):
return np.vdot(bra, ket)

rho_spectrum = kwant.kpm.SpectralDensity(fsyst, operator=rho)


rho_alt_spectrum = kwant.kpm.SpectralDensity(fsyst, operator=rho_alt)

References

2.10 Discretizing continuous Hamiltonians

2.10.1 Introduction

In “Discretization of a Schrödinger Hamiltonian” we have learnt that Kwant works with tight-binding
Hamiltonians. Often, however, one will start with a continuum model and will subsequently need to
discretize it to arrive at a tight-binding model. Although discretizing a Hamiltonian is usually a simple
process, it is tedious and repetitive. The situation is further exacerbated when one introduces additional
on-site degrees of freedom, and tracking all the necessary terms becomes a chore. The continuum sub-
package aims to be a solution to this problem. It is a collection of tools for working with continuum
models and for discretizing them into tight-binding models.
See also:
The complete source code of this tutorial can be found in tutorial/discretize.py

2.10.2 Discretizing by hand

As an example, let us consider the following continuum Schrödinger equation for a semiconducting
heterostructure (using the effective mass approximation):

ℏ2
(𝑘𝑥 𝑘 ) 𝜓(𝑥) = 𝐸 𝜓(𝑥).
2𝑚(𝑥) 𝑥

Replacing the momenta by their corresponding differential operators

𝑘𝛼 = −𝑖𝜕𝛼 ,

for 𝛼 = 𝑥, 𝑦 or 𝑧, and discretizing on a regular lattice of points with spacing 𝑎, we obtain the tight-binding
model
1 𝑎 1 𝑎 𝑎
𝐻=− ∑ 𝐴 (𝑥 + ) ( |𝑖⟩ ⟨𝑖 + 1| + ℎ.𝑐.) + 2 ∑ (𝐴 (𝑥 + ) + 𝐴 (𝑥 − )) |𝑖⟩ ⟨𝑖| ,
𝑎2 𝑖 2 𝑎 𝑖 2 2

with 𝐴(𝑥) = ℏ2 .
2𝑚(𝑥)

78 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

2.10.3 Using discretize to obtain a template

The function kwant.continuum.discretize takes a symbolic Hamiltonian and turns it into a Builder
instance with appropriate spatial symmetry that serves as a template. (We will see how to use the
template to build systems with a particular shape later).

template = kwant.continuum.discretize('k_x * A(x) * k_x')


print(template)

It is worth noting that discretize treats k_x and x as non-commuting operators, and so their order is
preserved during the discretization process.
The builder produced by discretize may be printed to show the source code of its onsite and hopping
functions (this is a special feature of builders returned by discretize):

# Discrete coordinates: x

# Onsite element:
def onsite(site, A):
(x, ) = 1 * site.tag
_const_0 = (A(1/2 + x))
_const_1 = (A(-1/2 + x))
return (_const_0 + _const_1)

# Hopping in direction (1,):


def hopping_1(site1, site2, A):
(x, ) = 1 * site1.tag
_const_0 = (A(1/2 + x))
return (-_const_0)

Technical details
• kwant.continuum uses sympy internally to handle symbolic expressions. Strings are converted using
kwant.continuum.sympify, which essentially applies some Kwant-specific rules (such as treating
k_x and x as non-commutative) before calling sympy.sympify
• The builder returned by discretize will have an N-D translational symmetry, where N is the
number of dimensions that were discretized. This is the case, even if there are expressions in the
input (e.g. V(x, y)) which in principle may not have this symmetry. When using the returned
builder directly, or when using it as a template to construct systems with different/lower symmetry,
it is important to ensure that any functional parameters passed to the system respect the symmetry
of the system. Kwant provides no consistency check for this.
• The discretization process consists of taking input 𝐻(𝑘𝑥 , 𝑘𝑦 , 𝑘𝑧 ), multiplying it from the right by
𝜓(𝑥, 𝑦, 𝑧) and iteratively applying a second-order accurate central derivative approximation for
every 𝑘𝛼 = −𝑖𝜕𝛼 :

1 𝑎 𝑎
𝜕𝛼 𝜓(𝛼) = (𝜓 (𝛼 + ) − 𝜓 (𝛼 − )) .
𝑎 2 2
This process is done separately for every summand in Hamiltonian. Once all symbols denoting
operators are applied internal algorithm is calculating gcd for hoppings coming from each summand
in order to find best possible approximation. Please see source code for details.
• Instead of using discretize one can use discretize_symbolic to obtain symbolic output. When
working interactively in Jupyter notebooks it can be useful to use this to see a symbolic rep-
resentation of the discretized Hamiltonian. This works best when combined with sympy Pretty
Printing.
• The symbolic result of discretization obtained with discretize_symbolic can be converted into
a builder using build_discretized. This can be useful if one wants to alter the tight-binding
Hamiltonian before building the system.

2.10. Discretizing continuous Hamiltonians 79


Kwant 1.3.1 documentation

2.10.4 Building a Kwant system from the template

Let us now use the output of discretize as a template to build a system and plot some of its energy
eigenstate. For this example the Hamiltonian will be

𝐻 = 𝑘𝑥2 + 𝑘𝑦2 + 𝑉 (𝑥, 𝑦),

where 𝑉 (𝑥, 𝑦) is some arbitrary potential.


First, use discretize to obtain a builder that we will use as a template:

hamiltonian = "k_x**2 + k_y**2 + V(x, y)"


template = kwant.continuum.discretize(hamiltonian)
print(template)

We now use this system with the fill method of Builder to construct the system we want to investigate:

def stadium(site):
(x, y) = site.pos
x = max(abs(x) - 20, 0)
return x**2 + y**2 < 30**2

syst = kwant.Builder()
syst.fill(template, stadium, (0, 0));
syst = syst.finalized()

After finalizing this system, we can plot one of the system’s energy eigenstates:

def plot_eigenstate(syst, n=2, Vx=.0003, Vy=.0005):

def potential(x, y):


return Vx * x + Vy * y

ham = syst.hamiltonian_submatrix(params=dict(V=potential), sparse=True)


evecs = scipy.sparse.linalg.eigsh(ham, k=10, which='SM')[1]
kwant.plotter.map(syst, abs(evecs[:, n])**2, show=False)

0.0014

0.0012

20 0.0010
10
0.0008
0
10 0.0006

20 0.0004

40 20 0 20 40 0.0002

80 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

Note in the above that we provided the function V to syst.hamiltonian_submatrix using


params=dict(V=potential), rather than via args.
In addition, the function passed as V expects two input parameters x and y, the same as in the initial
continuum Hamiltonian.

2.10.5 Models with more structure: Bernevig-Hughes-Zhang

When working with multi-band systems, like the Bernevig-Hughes-Zhang (BHZ) model12 , one can pro-
vide matrix input to discretize using identity and kron. For example, the definition of the BHZ
model can be written succinctly as:

hamiltonian = """
+ C * identity(4) + M * kron(sigma_0, sigma_z)
- B * (k_x**2 + k_y**2) * kron(sigma_0, sigma_z)
- D * (k_x**2 + k_y**2) * kron(sigma_0, sigma_0)
+ A * k_x * kron(sigma_z, sigma_x)
- A * k_y * kron(sigma_0, sigma_y)
"""

template = kwant.continuum.discretize(hamiltonian, grid_spacing=a)

We can then make a ribbon out of this template system:

def shape(site):
(x, y) = site.pos
return (0 <= y < W and 0 <= x < L)

def lead_shape(site):
(x, y) = site.pos
return (0 <= y < W)

syst = kwant.Builder()
syst.fill(template, shape, (0, 0))

lead = kwant.Builder(kwant.TranslationalSymmetry([-a, 0]))


lead.fill(template, lead_shape, (0, 0))

syst.attach_lead(lead)
syst.attach_lead(lead.reversed())

syst = syst.finalized()

and plot its dispersion using kwant.plotter.bands:

kwant.plotter.bands(syst.leads[0], params=params,
momenta=np.linspace(-0.3, 0.3, 201), show=False)

1 Science, 314, 1757 (2006).


2 Phys. Rev. B 82, 045122 (2010).

2.10. Discretizing continuous Hamiltonians 81


Kwant 1.3.1 documentation

0.04

0.02
energy [eV]

0.00

0.02

0.04

0.3 0.2 0.1 0.0 0.1 0.2 0.3


momentum [1/A]
In the above we see the edge states of the quantum spin Hall effect, which we can visualize using kwant.
plotter.map:

# get scattering wave functions at E=0


wf = kwant.wave_function(syst, energy=0, params=params)

# prepare density operators


sigma_z = np.array([[1, 0], [0, -1]])
prob_density = kwant.operator.Density(syst, np.eye(4))
spin_density = kwant.operator.Density(syst, np.kron(sigma_z, np.eye(2)))

# calculate expectation values and plot them


wf_sqr = sum(prob_density(psi) for psi in wf(0)) # states from left lead
rho_sz = sum(spin_density(psi) for psi in wf(0)) # states from left lead

fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, figsize=(16, 4))


kwant.plotter.map(syst, wf_sqr, ax=ax1)
kwant.plotter.map(syst, rho_sz, ax=ax2)

Probability density Spin density


1.00
1.0
800 0.75
0.8 0.50
600 0.25
0.6 0.00
400 0.25
0.4
0.50
200
0.2 0.75
0 1.00
400 600 800 1000 1200 1400 1600 400 600 800 1000 1200 1400 1600

82 Chapter 2. Tutorial: learning Kwant through examples


Kwant 1.3.1 documentation

2.10.6 Limitations of discretization

It is important to remember that the discretization of a continuum model is an approximation that is


only valid in the low-energy limit. For example, the quadratic continuum Hamiltonian
ℏ2 2
𝐻continuous (𝑘𝑥 ) = 𝑘
2𝑚 𝑥
and its discretized approximation
𝐻tight-binding (𝑘𝑥 ) = 2𝑡(1 − cos(𝑘𝑥 𝑎)),
2

where 𝑡 = 2𝑚𝑎 2 , are only valid in the limit 𝐸 < 𝑡. The grid spacing 𝑎 must be chosen according to how
high in energy you need your tight-binding model to be valid.
It is possible to set 𝑎 through the grid_spacing parameter to discretize, as we will illustrate in the
following example. Let us start from the continuum Hamiltonian
𝐻(𝑘) = 𝑘𝑥2 𝟙2×2 + 𝛼𝑘𝑥 𝜎𝑦 .
We start by defining this model as a string and setting the value of the 𝛼 parameter:
hamiltonian = "k_x**2 * identity(2) + alpha * k_x * sigma_y"
params = dict(alpha=.5)

Now we can use kwant.continuum.lambdify to obtain a function that computes 𝐻(𝑘):


h_k = kwant.continuum.lambdify(hamiltonian, locals=params)
k_cont = np.linspace(-4, 4, 201)
e_cont = [scipy.linalg.eigvalsh(h_k(k_x=ki)) for ki in k_cont]

We can also construct a discretized approximation using kwant.continuum.discretize, in a similar


manner to previous examples:
template = kwant.continuum.discretize(hamiltonian, grid_spacing=a)
syst = kwant.wraparound.wraparound(template).finalized()

def h_k(k_x):
p = dict(k_x=k_x, **params)
return syst.hamiltonian_submatrix(params=p)

k_tb = np.linspace(-np.pi/a, np.pi/a, 201)


e_tb = [scipy.linalg.eigvalsh(h_k(k_x=a*ki)) for ki in k_tb]

Below we can see the continuum and tight-binding dispersions for two different values of the discretization
grid spacing 𝑎:
a=1 a=0.25
14
continuum continuum
12 tight-binding tight-binding
10
8
energy [a.u.]

energy [a.u.]

6
4
2
0
4 3 2 1 0 1 2 3 4 4 3 2 1 0 1 2 3 4
momentum [a.u.] momentum [a.u.]

We clearly see that the smaller grid spacing is, the better we approximate the original continuous dis-
persion. It is also worth remembering that the Brillouin zone also scales with grid spacing: [− 𝜋𝑎 , 𝜋𝑎 ].

2.10. Discretizing continuous Hamiltonians 83


Kwant 1.3.1 documentation

2.10.7 Advanced topics

The input to kwant.continuum.discretize and kwant.continuum.lambdify can be not only a string,


as we saw above, but also a sympy expression or a sympy matrix. This functionality will probably be
mostly useful to people who are already experienced with sympy.
It is possible to use identity (for identity matrix), kron (for Kronecker product), as well as Pauli
matrices sigma_0, sigma_x, sigma_y, sigma_z in the input to lambdify and discretize, in order to
simplify expressions involving matrices. Matrices can also be provided explicitly using square [] brackets.
For example, all following expressions are equivalent:

sympify = kwant.continuum.sympify
subs = {'sx': [[0, 1], [1, 0]], 'sz': [[1, 0], [0, -1]]}

e = (
sympify('[[k_x**2, alpha * k_x], [k_x * alpha, -k_x**2]]'),
sympify('k_x**2 * sigma_z + alpha * k_x * sigma_x'),
sympify('k_x**2 * sz + alpha * k_x * sx', locals=subs),
)

print(e[0] == e[1] == e[2])

True

We can use the locals keyword parameter to substitute expressions and numerical values:

subs = {'A': 'A(x) + B', 'V': 'V(x) + V_0', 'C': 5}


print(sympify('k_x * A * k_x + V + C', locals=subs))

B*k_x**2 + V_0 + 5 + k_x*A(x)*k_x + V(x)

Symbolic expressions obtained in this way can be directly passed to all discretizer functions. Tech-
nical details
Because of the way that sympy handles commutation relations all symbols representing position and
momentum operators are set to be non commutative. This means that the order of momentum and
position operators in the input expression is preserved. Note that it is not possible to define individual
commutation relations within sympy, even expressions such 𝑥𝑘𝑦 𝑥 will not be simplified, even though
mathematically [𝑥, 𝑘𝑦 ] = 0.

References

84 Chapter 2. Tutorial: learning Kwant through examples


CHAPTER

THREE

CORE MODULES

The following modules of Kwant are used directly most frequently.

3.1 kwant – Top level package

For convenience, short names are provided for a few widely used objects from the sub-packages. Other-
wise, this package has only very limited functionality of its own.

3.1.1 Generic functionality

The version of Kwant is available under the name __version__.

KwantDeprecationWarning Class of warnings about a deprecated feature of


Kwant.
UserCodeError Class for errors that occur in user-provided code.

kwant.KwantDeprecationWarning

exception kwant.KwantDeprecationWarning
Bases: Warning
Class of warnings about a deprecated feature of Kwant.
DeprecationWarning has been made invisible by default in Python 2.7 in order to not confuse non-
developer users with warnings that are not relevant to them. In the case of Kwant, by far most
users are developers, so we feel that a KwantDeprecationWarning that is visible by default is useful.

kwant.UserCodeError

exception kwant.UserCodeError
Bases: Exception
Class for errors that occur in user-provided code.
Usually users will define value functions that Kwant calls in order to evaluate the Hamiltonian. If
one of these function raises an exception then it is caught and this error is raised in its place. This
makes it clear that the error is from the user’s code (and not a bug in Kwant) and also makes it
possible for any libraries that wrap Kwant to detect when a user’s function causes an error.

3.1.2 From kwant.builder

Builder([symmetry, conservation_law, ...]) A tight binding system defined on a graph.


Continued on next page

85
Kwant 1.3.1 documentation

Table 3.2 – continued from previous page


HoppingKind A pattern for matching hoppings.

3.1.3 From kwant.lattice

TranslationalSymmetry(*periods) A translational symmetry defined in real space.

3.1.4 From kwant.plotter

plot(sys[, num_lead_cells, unit, ...]) Plot a system in 2 or 3 dimensions.

3.1.5 From kwant.solvers.default

greens_function(sys[, energy, args, ...]) Compute the retarded Green’s function of the sys-
tem between its leads.
ldos(sys[, energy, args, check_hermiticity, ...]) Calculate the local density of states of a system at a
given energy.
smatrix(sys[, energy, args, out_leads, ...]) Compute the scattering matrix of a system.
wave_function(sys[, energy, args, ...]) Return a callable object for the computation of the
wave function inside the scattering region.

3.2 kwant.builder – High-level construction of systems

3.2.1 Types

Builder([symmetry, conservation_law, ...]) A tight binding system defined on a graph.


Site A site, member of a SiteFamily.
HoppingKind A pattern for matching hoppings.
SimpleSiteFamily([name, norbs]) A site family used as an example and for testing.
BuilderLead(builder, interface) A lead made from a Builder with a spatial symme-
try.
SelfEnergyLead(selfenergy_func, interface) A general lead defined by its self energy.
ModesLead(modes_func, interface) A general lead defined by its modes wave functions.

kwant.builder.Builder

class kwant.builder.Builder(symmetry=None, *, conservation_law=None,


time_reversal=None, particle_hole=None, chiral=None)
Bases: object
A tight binding system defined on a graph.
This is one of the central types in Kwant. It is used to construct tight binding systems in a flexible
way.
The nodes of the graph are Site instances. The edges, i.e. the hoppings, are pairs (2-tuples) of
sites. Each node and each edge has a value associated with it. The values associated with nodes
are interpreted as on-site Hamiltonians, the ones associated with edges as hopping integrals.
To make the graph accessible in a way that is natural within the Python language it is exposed
as a mapping (much like a built-in Python dictionary). Keys are sites or hoppings. Values are 2d
arrays (e.g. NumPy or Tinyarray) or numbers (interpreted as 1 by 1 matrices).

86 Chapter 3. Core modules


Kwant 1.3.1 documentation

Parameters symmetry : Symmetry or None


The spatial symmetry of the system.
conservation_law : 2D array, dictionary, function, or None
An onsite operator with integer eigenvalues that commutes with the Hamilto-
nian. The ascending order of eigenvalues corresponds to the selected ordering
of the Hamiltonian subblocks. If a dict is given, it maps from site families to
such matrices. If a function is given it must take the same arguments as the
onsite Hamiltonian functions of the system and return the onsite matrix.
time_reversal : scalar, 2D array, dictionary, function, or None
The unitary part of the onsite time-reversal symmetry operator. Same format
as that of conservation_law.
particle_hole : scalar, 2D array, dictionary, function, or None
The unitary part of the onsite particle-hole symmetry operator. Same format
as that of conservation_law.
chiral : 2D array, dictionary, function or None
The unitary part of the onsite chiral symmetry operator. Same format as
that of conservation_law.

Notes

Values can be also functions that receive the site or the hopping (passed to the function as two sites)
and possibly additional arguments and are expected to return a valid value. This allows to define
systems quickly, to modify them without reconstructing, and to save memory for many-orbital
models.
In addition to simple keys (single sites and hoppings) more powerful keys are possible as well
that allow to manipulate multiple sites/hoppings in a single operation. Such keys are internally
expanded into a sequence of simple keys by using the method Builder.expand. For example,
syst[general_key] = value is equivalent to

for simple_key in syst.expand(general_key):


syst[simple_key] = value

Builder instances automatically ensure that every hopping is Hermitian, so that if builder[a, b]
has been set, there is no need to set builder[b, a].
Builder instances can be made to automatically respect a Symmetry that is passed to them during
creation. The behavior of builders with a symmetry is slightly more sophisticated: all keys are
mapped to the fundamental domain of the symmetry before storing them. This may produce
confusing results when neighbors of a site are queried.
The method attach_lead works only if the sites affected by them have tags which are sequences
of integers. It makes sense only when these sites live on a regular lattice, like the ones provided by
kwant.lattice.
Attaching a lead manually (without the use of attach_lead) amounts to creating a Lead object
and appending it to this list.

Warning: If functions are used to set values in a builder with a symmetry, then they must sat-
isfy the same symmetry. There is (currently) no check and wrong results will be the consequence
of a misbehaving function.

3.2. kwant.builder – High-level construction of systems 87


Kwant 1.3.1 documentation

Examples

Define a site.

>>> builder[site] = value

Print the value of a site.

>>> print(builder[site])

Define a hopping.

>>> builder[site1, site2] = value

Delete a site.

>>> del builder[site3]

Detach the last lead. (This does not remove the sites that were added to the scattering region by
attach_lead.)

>>> del builder.leads[-1]

Attributes

leads (list of Lead instances) The leads that are attached to the system.

Methods

attach_lead(lead_builder, origin=None, add_cells=0)


Attach a lead to the builder, possibly adding missing sites.
Returns the lead number (integer) of the attached lead.
Parameters lead_builder : Builder with 1D translational symmetry
Builder of the lead which has to be attached.
origin : Site
The site which should belong to a domain where the lead should begin. It is
used to attach a lead inside the system, e.g. to an inner radius of a ring.
add_cells : int
Number of complete unit cells of the lead to be added to the system after
the missing sites have been added.
Returns added_sites : list of Site objects that were added to the system.
Raises ValueError
If lead_builder does not have proper symmetry, has hoppings with range of
more than one lead unit cell, or if it is not completely interrupted by the
system.

Notes

This method is not fool-proof, i.e. if it returns an error, there is no guarantee that the system
stayed unaltered.

88 Chapter 3. Core modules


Kwant 1.3.1 documentation

The lead numbering starts from zero and increments from there, i.e. the leads are numbered
in the order in which they are attached.
closest(pos)
Return the site that is closest to the given position.
This function takes into account the symmetry of the builder. It is assumed that the symmetry
is a translational symmetry.
This function executes in a time proportional to the number of sites, so it is not efficient
for large builders. It is especially slow for builders with a symmetry, but such systems often
contain only a limited number of sites.
dangling()
Return an iterator over all dangling sites.
degree(site)
Return the number of neighbors of a site.
eradicate_dangling()
Keep deleting dangling sites until none are left.
expand(key)
Expand a general key into an iterator over simple keys.
Parameters key : builder key (see notes)
The key to be expanded

Notes

Keys are (recursively):


• Simple keys: sites or 2-tuples of sites (=hoppings).
• Any (non-tuple) iterable of keys, e.g. a list or a generator expression.
• Any function that returns a key when passed a builder as sole argument, e.g. a
HoppingKind instance or the function returned by shape.

This method is internally used to expand the keys when getting or deleting items of a builder
(i.e. syst[key] = value or del syst[key]).
fill(template, shape, start, *, max_sites=10000000)
Populate builder using another one as a template.
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 template : Builder instance
The builder used as the template. The symmetry of the target builder must
be a subgroup of the symmetry of the template.
shape : callable
A boolean function of site returning whether the site should be added to the
target builder or not. The shape must be compatible with the symmetry of
the target builder.
start : Site instance or iterable thereof or iterable of numbers

3.2. kwant.builder – High-level construction of systems 89


Kwant 1.3.1 documentation

The site(s) at which the the flood-fill starts. If start is an iterable of numbers,
the starting site will be template.closest(start).
max_sites : positive number
The maximal number of sites that may be added before RuntimeError is
raised. Used to prevent using up all memory.
Returns added_sites : list of Site objects that were added to the system.
Raises ValueError
If the symmetry of the target isn’t a subgroup of the template symmetry.
RuntimeError
If more than max_sites sites are to be added. The target builder will be left
in an unusable state.

Notes

This function uses a flood-fill algorithm. If the template builder consists of disconnected parts,
the fill will stop at their boundaries.
finalized()
Return a finalized (=usable with solvers) copy of the system.
Returns finalized_system : kwant.system.FiniteSystem
If there is no symmetry.
finalized_system : kwant.system.InfiniteSystem
If a symmetry is present.

Notes

This method does not modify the Builder instance for which it is called.
Upon finalization, it is implicitly assumed that every function assigned as a value to a builder
with a symmetry possesses the same symmetry.
Attached leads are also finalized and will be present in the finalized system to be returned.
Currently, only Builder instances without or with a 1D translational Symmetry can be finalized.
hopping_value_pairs()
Return an iterator over all (hopping, value) pairs.
hoppings()
Return an iterator over all Builder hoppings.
The hoppings that are returned belong to the fundamental domain of the Builder symmetry,
and are not necessarily the ones that were set initially (but always the equivalent ones).
neighbors(site)
Return an iterator over all neighbors of a site.
Technical note: This method respects the symmetry of the builder, i.e. the returned sites are
really connected to the given site (and not to its image in the fundamental domain).
reversed()
Return a shallow copy of the builder with the symmetry reversed.
This method can be used to attach the same infinite system as lead from two opposite sides.
It requires a builder to which an infinite symmetry is associated.

90 Chapter 3. Core modules


Kwant 1.3.1 documentation

site_value_pairs()
Return an iterator over all (site, value) pairs.
sites()
Return a read-only set over all sites.
The sites that are returned belong to the fundamental domain of the Builder symmetry, and
are not necessarily the ones that were set initially (but always the equivalent ones).
update(other)
Update builder from other.
All sites and hoppings of other, together with their values, are written to self, overwriting
already existing sites and hoppings. The leads of other are appended to the leads of the
system being updated.
This method requires that both builders share the same symmetry.

kwant.builder.Site

class kwant.builder.Site
Bases: tuple
A site, member of a SiteFamily.
Sites are the vertices of the graph which describes the tight binding system in a Builder.
A site is uniquely identified by its family and its tag.
Parameters family : an instance of SiteFamily
The ‘type’ of the site.
tag : a hashable python object
The unique identifier of the site within the site family, typically a vector of
integers.
Raises ValueError
If tag is not a proper tag for family.

Notes

For convenience, family(*tag) can be used instead of Site(family, tag) to create a site.
The parameters of the constructor (see above) are stored as instance variables under the same
names. Given a site site, common things to query are thus site.family, site.tag, and site.
pos.

Methods

count(value) → integer – return number of occurrences of value


index(value[, start [, stop ]]) → integer – return first index of value.
Raises ValueError if the value is not present.

Attributes

family
The site family to which the site belongs.

3.2. kwant.builder – High-level construction of systems 91


Kwant 1.3.1 documentation

pos
Real space position of the site.
This relies on family having a pos method (see SiteFamily).
tag
The tag of the site.

kwant.builder.HoppingKind

class kwant.builder.HoppingKind
Bases: tuple
A pattern for matching hoppings.
A hopping (a, b) matches precisely when the site family of a equals family_a and that of b
equals family_b and (a.tag - b.tag) is equal to delta. In other words, the matching hoppings
have the form: (family_a(x + delta), family_b(x))
Parameters delta : Sequence of integers
The sequence is interpreted as a vector with integer elements.
family_a : SiteFamily
family_b : SiteFamily or None (default)
The default value means: use the same family as family_a.

Notes

A HoppingKind is a callable object: When called with a Builder as sole argument, an instance of
this class will return an iterator over all possible matching hoppings whose sites are already present
in the system. The hoppings do not have to be already present in the system. For example:

kind = kwant.builder.HoppingKind((1, 0), lat)


syst[kind(syst)] = 1

Because a Builder can be indexed with functions or iterables of functions, HoppingKind instances
(or any non-tuple iterables of them, e.g. a list) can be used directly as “wildcards” when setting
or deleting hoppings:

kinds = [kwant.builder.HoppingKind(v, lat) for v in [(1, 0), (0, 1)]]


syst[kinds] = 1

Methods

count(value) → integer – return number of occurrences of value


index(value[, start [, stop ]]) → integer – return first index of value.
Raises ValueError if the value is not present.

Attributes

delta
The difference between the tags of the hopping’s sites
family_a
The family of the first site in the hopping

92 Chapter 3. Core modules


Kwant 1.3.1 documentation

family_b
The family of the second site in the hopping

kwant.builder.SimpleSiteFamily

class kwant.builder.SimpleSiteFamily(name=None, norbs=None)


Bases: kwant.builder.SiteFamily
A site family used as an example and for testing.
A family of sites tagged by any python objects where object satisfied condition object ==
eval(repr(object)).
It exists to provide a basic site family that can be used for testing the builder module without
other dependencies. It can be also used to tag sites with non-numeric objects like strings should
this every be useful.
Due to its low storage efficiency for numbers it is not recommended to use SimpleSiteFamily
when kwant.lattice.Monatomic would also work.

Methods

normalize_tag(tag)

kwant.builder.BuilderLead

class kwant.builder.BuilderLead(builder, interface)


Bases: kwant.builder.Lead
A lead made from a Builder with a spatial symmetry.
Parameters builder : Builder
The tight-binding system of a lead. It has to possess appropriate symmetry,
and it may not contain hoppings between further than neighboring images
of the fundamental domain.
interface : sequence of Site instances
Sequence of sites in the scattering region to which the lead is attached.

Notes

The hopping from the scattering region to the lead is assumed to be equal to the hopping from a
lead unit cell to the next one in the direction of the symmetry vector (i.e. the lead is ‘leaving’ the
system and starts with a hopping).
Every system has an attribute leads, which stores a list of BuilderLead objects with all the infor-
mation about the leads that are attached.

Attributes

builder (Builder) The tight-binding system of a lead.


interface (list of Site instances) A sorted list of interface sites.

3.2. kwant.builder – High-level construction of systems 93


Kwant 1.3.1 documentation

Methods

finalized()
Return a kwant.system.InfiniteSystem corresponding to the compressed lead.
The order of interface sites is kept during finalization.

kwant.builder.SelfEnergyLead

class kwant.builder.SelfEnergyLead(selfenergy_func, interface)


Bases: kwant.builder.Lead
A general lead defined by its self energy.
Parameters selfenergy_func : function
Has the same signature as selfenergy (without the self parameter) and
returns the self energy matrix for the interface sites.
interface : sequence of Site instances

Methods

finalized()
Trivial finalization: the object is returned itself.
selfenergy(energy, args=(), *, params=None)

kwant.builder.ModesLead

class kwant.builder.ModesLead(modes_func, interface)


Bases: kwant.builder.Lead
A general lead defined by its modes wave functions.
Parameters modes_func : function
Has the same signature as modes (without the self parameter) and
returns the modes of the lead as a tuple of PropagatingModes and
StabilizedModes.
interface :
sequence of Site instances

Methods

finalized()
Trivial finalization: the object is returned itself.
modes(energy, args=(), *, params=None)
selfenergy(energy, args=(), *, params=None)

3.2.2 Abstract base classes

SiteFamily(canonical_repr, name, norbs) Abstract base class for site families.


Symmetry Abstract base class for spatial symmetries.
Continued on next page

94 Chapter 3. Core modules


Kwant 1.3.1 documentation

Table 3.7 – continued from previous page


Lead Abstract base class for leads that can be attached to
a Builder.

kwant.builder.SiteFamily

class kwant.builder.SiteFamily(canonical_repr, name, norbs)


Bases: object
Abstract base class for site families.
Site families are the ‘type’ of Site objects. Within a family, individual sites are uniquely identified
by tags. Valid tags must be hashable Python objects, further details are up to the family.
Site families must be immutable and fully defined by their initial arguments. They must inherit
from this abstract base class and call its __init__ function providing it with two arguments: a
canonical representation and a name. The canonical representation will be returned as the objects
representation and must uniquely identify the site family instance. The name is a string used to
distinguish otherwise identical site families. It may be empty. norbs defines the number of orbitals
on sites associated with this site family; it may be None, in which case the number of orbitals is
not specified.
All site families must define the method normalize_tag which brings a tag to the standard format
for this site family.
Site families that are intended for use with plotting should also provide a method pos(tag), which
returns a vector with real-space coordinates of the site belonging to this family with a given tag.
If the norbs of a site family are provided, and sites of this family are used to populate a Builder,
then the associated Hamiltonian values must have the correct shape. That is, if a site family
has norbs = 2, then any on-site terms for sites belonging to this family should be 2x2 matrices.
Similarly, any hoppings to/from sites belonging to this family must have a matrix structure where
there are two rows/columns. This condition applies equally to Hamiltonian values that are given
by functions. If this condition is not satisfied, an error will be raised.

Methods

normalize_tag(tag)
Return a normalized version of the tag.
Raises TypeError or ValueError if the tag is not acceptable.

kwant.builder.Symmetry

class kwant.builder.Symmetry
Bases: object
Abstract base class for spatial symmetries.
Many physical systems possess a discrete spatial symmetry, which results in special properties of
these systems. This class is the standard way to describe discrete spatial symmetries in Kwant.
An instance of this class can be passed to a Builder instance at its creation. The most important
kind of symmetry is translational symmetry, used to define scattering leads.
Each symmetry has a fundamental domain – a set of sites and hoppings, generating all the possible
sites and hoppings upon action of symmetry group elements. A class derived from Symmetry has
to implement mapping of any site or hopping into the fundamental domain, applying a symmetry
group element to a site or a hopping, and a method which to determine the group element bringing
some site from the fundamental domain to the requested one. Additionally, it has to have a property
num_directions returning the number of independent symmetry group generators (number of
elementary periods for translational symmetry).

3.2. kwant.builder – High-level construction of systems 95


Kwant 1.3.1 documentation

A ValueError must be raised by the symmetry class whenever a symmetry is used together with
sites whose site family is not compatible with it. A typical example of this is when the vector
defining a translational symmetry is not a lattice vector.
The type of the domain objects as handled by the methods of this class is not specified. The only
requirement is that it must support the unary minus operation. The reference implementation of
to_fd() is hence self.act(-self.which(a), a, b).

Methods

act(element, a, b=None)
Act with a symmetry group element on a site or hopping.
has_subgroup(other)
Test whether self has the subgroup other...
or, in other words, whether other is a subgroup of self. The reason why this is the abstract
method (and not is_subgroup) is that in general it’s not possible for a subgroup to know its
supergroups.
in_fd(site)
Tell whether site lies within the fundamental domain.
subgroup(*generators)
Return the subgroup generated by a sequence of group elements.
to_fd(a, b=None)
Map a site or hopping to the fundamental domain.
If b is None, return a site equivalent to a within the fundamental domain. Otherwise, return a
hopping equivalent to (a, b) but where the first element belongs to the fundamental domain.
Equivalent to self.act(-self.which(a), a, b).
which(site)
Calculate the domain of the site.
Return the group element whose action on a certain site from the fundamental domain will
result in the given site.

Attributes

num_directions
Number of elementary periods of the symmetry.

kwant.builder.Lead

class kwant.builder.Lead
Bases: object
Abstract base class for leads that can be attached to a Builder.
To attach a lead to a builder, append it to the builder’s leads instance variable. See the documen-
tation of kwant.builder for the concrete classes of leads derived from this one.

Attributes

interface (sequence of sites)

96 Chapter 3. Core modules


Kwant 1.3.1 documentation

Methods

finalized()
Return a finalized version of the lead.
Returns finalized_lead

Notes

The finalized lead must be an object that can be used as a lead in a kwant.system.
FiniteSystem. It could be an instance of kwant.system.InfiniteSystem for example.
The order of sites for the finalized lead must be the one specified in interface.

3.3 kwant.lattice – Bravais lattices

3.3.1 General

TranslationalSymmetry(*periods) A translational symmetry defined in real space.


general(prim_vecs[, basis, name, norbs]) Create a Bravais lattice of any dimensionality, with
any number of sites.
Monatomic(prim_vecs[, offset, name, norbs]) A Bravais lattice with a single site in the basis.
Polyatomic(prim_vecs, basis[, name, norbs]) A Bravais lattice with an arbitrary number of sites
in the basis.

kwant.lattice.TranslationalSymmetry

class kwant.lattice.TranslationalSymmetry(*periods)
Bases: kwant.builder.Symmetry
A translational symmetry defined in real space.
Group elements of this symmetry are integer tuples of appropriate length.
Parameters p0, p1, p2, ... : sequences of real numbers
The symmetry periods in real space.

Notes

This symmetry automatically chooses the fundamental domain for each new SiteFamily it en-
counters. If this site family does not correspond to a Bravais lattice, or if it does not have a
commensurate period, an error is produced. A certain flexibility in choice of the fundamental
domain can be achieved by calling manually the add_site_family method and providing it the
other_vectors parameter.
The fundamental domain for hoppings are all hoppings (a, b) with site a in fundamental domain
of sites.

Methods

act(element, a, b=None)
add_site_family(fam, other_vectors=None)
Select a fundamental domain for site family and cache associated data.

3.3. kwant.lattice – Bravais lattices 97


Kwant 1.3.1 documentation

Parameters fam : SiteFamily


the site family which has to be processed. Be sure to delete the previ-
ously processed site families from site_family_data if you want to modify
the cache.
other_vectors : 2d array-like of integers
Bravais lattice vectors used to complement the periods in forming a ba-
sis. The fundamental domain consists of all the lattice sites for which the
zero coefficients corresponding to the symmetry periods in the basis formed
by the symmetry periods and other_vectors. If an insufficient number of
other_vectors is provided to form a basis, the missing ones are selected au-
tomatically.
Raises KeyError
If fam is already stored in site_family_data.
ValueError
If lattice fam is incompatible with given periods.
has_subgroup(other)
in_fd(site)
Tell whether site lies within the fundamental domain.
reversed()
Return a reversed copy of the symmetry.
The resulting symmetry has all the period vectors opposite to the original and an identical
fundamental domain.
subgroup(*generators)
Return the subgroup generated by a sequence of group elements.
Parameters *generators: sequence of int
Each generator must have length self.num_directions.
to_fd(a, b=None)
Map a site or hopping to the fundamental domain.
If b is None, return a site equivalent to a within the fundamental domain. Otherwise, return a
hopping equivalent to (a, b) but where the first element belongs to the fundamental domain.
Equivalent to self.act(-self.which(a), a, b).
which(site)

Attributes

num_directions

kwant.lattice.general

kwant.lattice.general(prim_vecs, basis=None, name=’‘, norbs=None)


Create a Bravais lattice of any dimensionality, with any number of sites.
Parameters prim_vecs : 2d array-like of floats
The primitive vectors of the Bravais lattice
basis : 2d array-like of floats
The coordinates of the basis sites inside the unit cell

98 Chapter 3. Core modules


Kwant 1.3.1 documentation

name : string or sequence of strings


Name of the lattice, or sequence of names of all of the sublattices. If the
name of the lattice is given, the names of sublattices (if any) are obtained
by appending their number to the name of the lattice.
norbs : int or sequence of ints, optional
The number of orbitals per site on the lattice, or a sequence of the number
of orbitals of sites on each of the sublattices.
Returns lattice : either Monatomic or Polyatomic
Resulting lattice.

Notes

This function is largely an alias to the constructors of corresponding lattices.

kwant.lattice.Monatomic

class kwant.lattice.Monatomic(prim_vecs, offset=None, name=’‘, norbs=None)


Bases: kwant.builder.SiteFamily, kwant.lattice.Polyatomic
A Bravais lattice with a single site in the basis.
Instances of this class provide the SiteFamily interface. Site tags (see SiteFamily) are sequences
of integers and describe the lattice coordinates of a site.
Monatomic instances are used as site families on their own or as sublattices of Polyatomic lattices.
Parameters prim_vecs : 2d array-like of floats
Primitive vectors of the Bravais lattice.
offset : vector of floats
Displacement of the lattice origin from the real space coordinates origin.

Attributes

offset (vector) Displacement of the lattice origin from the real space coordinates origin

Methods

closest(pos)
Find the lattice coordinates of the site closest to position pos.
n_closest(pos, n=1)
Find n sites closest to position pos.
Returns sites : numpy array
An array with sites coordinates.
neighbors(n=1, eps=1e-08)
Return n-th nearest neighbor hoppings.
Parameters n : integer
Order of the hoppings to return.
eps : float

3.3. kwant.lattice – Bravais lattices 99


Kwant 1.3.1 documentation

Tolerance relative to the length of the shortest lattice vector for when to
consider lengths to be approximately equal.
Returns hoppings : list of kwant.builder.HopplingKind objects
The n-th nearest neighbor hoppings.

Notes

The hoppings are ordered lexicographically according to sublattice from which they originate,
sublattice on which they end, and their lattice coordinates. Out of the two equivalent hoppings
(a hopping and its reverse) only the lexicographically larger one is returned.
normalize_tag(tag)
pos(tag)
Return the real-space position of the site with a given tag.
shape(function, start)
Return a key for all the lattice sites inside a given shape.
The object returned by this method is primarily meant to be used as a key for indexing
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 : 1d array-like
The real-space 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 Symmetry or 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()
>>> syst = kwant.Builder()
>>> syst[lat.shape(circle, (0, 0))] = 0
>>> syst[lat.neighbors()] = 1

vec(int_vec)
Return the coordinates of a Bravais lattice vector in real space.
Parameters vec : integer vector
Returns output : real vector

100 Chapter 3. Core modules


Kwant 1.3.1 documentation

wire(center, radius)
Return a key for all the lattice sites inside an infinite cylinder.
This method makes it easy to define cylindrical (2d: rectangular) leads that point in any
direction. The object returned by this method is primarily meant to be used as a key for
indexing Builder instances. See example below.
Parameters center : 1d array-like of floats
A point belonging to the axis of the cylinder.
radius : float
The radius of the cylinder.

Notes

The function returned by this method is to be called with a TranslationalSymmetry instance


(or a Builder instance whose symmetry is used then) as sole argument. All the lattice sites
(in the fundamental domain of the symmetry) inside the specified infinite cylinder are yielded.
The direction of the cylinder is determined by the symmetry.

Examples

>>> lat = kwant.lattice.honeycomb()


>>> sym = kwant.TranslationalSymmetry(lat.a.vec((-2, 1)))
>>> lead = kwant.Builder(sym)
>>> lead[lat.wire((0, -5), 5)] = 0
>>> lead[lat.neighbors()] = 1

Attributes

prim_vecs
(sequence of vectors) Primitive vectors
prim_vecs[i]‘ is the i-th primitive basis vector of the lattice displacement of the lattice origin
from the real space coordinates origin.

kwant.lattice.Polyatomic

class kwant.lattice.Polyatomic(prim_vecs, basis, name=’‘, norbs=None)


Bases: object
A Bravais lattice with an arbitrary number of sites in the basis.
Contains Monatomic sublattices. Note that an instance of Polyatomic is not itself a SiteFamily,
only its sublattices are.
Parameters prim_vecs : 2d array-like of floats
The primitive vectors of the Bravais lattice
basis : 2d array-like of floats
The coordinates of the basis sites inside the unit cell.
name : string or sequence of strings, optional
The name of the lattice, or a sequence of the names of all the sublattices.
If the name of the lattice is given, the names of sublattices are obtained by
appending their number to the name of the lattice.

3.3. kwant.lattice – Bravais lattices 101


Kwant 1.3.1 documentation

norbs : int or sequence of ints, optional


The number of orbitals per site on the lattice, or a sequence of the number
of orbitals of sites on each of the sublattices.
Raises ValueError
If dimensionalities do not match.

Methods

neighbors(n=1, eps=1e-08)
Return n-th nearest neighbor hoppings.
Parameters n : integer
Order of the hoppings to return.
eps : float
Tolerance relative to the length of the shortest lattice vector for when to
consider lengths to be approximately equal.
Returns hoppings : list of kwant.builder.HopplingKind objects
The n-th nearest neighbor hoppings.

Notes

The hoppings are ordered lexicographically according to sublattice from which they originate,
sublattice on which they end, and their lattice coordinates. Out of the two equivalent hoppings
(a hopping and its reverse) only the lexicographically larger one is returned.
shape(function, start)
Return a key for all the lattice sites inside a given shape.
The object returned by this method is primarily meant to be used as a key for indexing
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 : 1d array-like
The real-space 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 Symmetry or 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.

102 Chapter 3. Core modules


Kwant 1.3.1 documentation

Examples

>>> def circle(pos):


... x, y = pos
... return x**2 + y**2 < 100
...
>>> lat = kwant.lattice.honeycomb()
>>> syst = kwant.Builder()
>>> syst[lat.shape(circle, (0, 0))] = 0
>>> syst[lat.neighbors()] = 1

vec(int_vec)
Return the coordinates of a Bravais lattice vector in real space.
Parameters vec : integer vector
Returns output : real vector
wire(center, radius)
Return a key for all the lattice sites inside an infinite cylinder.
This method makes it easy to define cylindrical (2d: rectangular) leads that point in any
direction. The object returned by this method is primarily meant to be used as a key for
indexing Builder instances. See example below.
Parameters center : 1d array-like of floats
A point belonging to the axis of the cylinder.
radius : float
The radius of the cylinder.

Notes

The function returned by this method is to be called with a TranslationalSymmetry instance


(or a Builder instance whose symmetry is used then) as sole argument. All the lattice sites
(in the fundamental domain of the symmetry) inside the specified infinite cylinder are yielded.
The direction of the cylinder is determined by the symmetry.

Examples

>>> lat = kwant.lattice.honeycomb()


>>> sym = kwant.TranslationalSymmetry(lat.a.vec((-2, 1)))
>>> lead = kwant.Builder(sym)
>>> lead[lat.wire((0, -5), 5)] = 0
>>> lead[lat.neighbors()] = 1

Attributes

prim_vecs
(sequence of vectors) Primitive vectors
prim_vecs[i]‘ is the i-th primitive basis vector of the lattice displacement of the lattice origin
from the real space coordinates origin.

3.3.2 Library of lattices

3.3. kwant.lattice – Bravais lattices 103


Kwant 1.3.1 documentation

chain([a, name, norbs]) Make a one-dimensional lattice.


square([a, name, norbs]) Make a square lattice.
cubic([a, name, norbs]) Make a cubic lattice.
triangular([a, name, norbs]) Make a triangular lattice.
honeycomb([a, name, norbs]) Make a honeycomb lattice.
kagome([a, name, norbs]) Make a kagome lattice.

kwant.lattice.chain

kwant.lattice.chain(a=1, name=’‘, norbs=None)


Make a one-dimensional lattice.

kwant.lattice.square

kwant.lattice.square(a=1, name=’‘, norbs=None)


Make a square lattice.

kwant.lattice.cubic

kwant.lattice.cubic(a=1, name=’‘, norbs=None)


Make a cubic lattice.

kwant.lattice.triangular

kwant.lattice.triangular(a=1, name=’‘, norbs=None)


Make a triangular lattice.

kwant.lattice.honeycomb

kwant.lattice.honeycomb(a=1, name=’‘, norbs=None)


Make a honeycomb lattice.

kwant.lattice.kagome

kwant.lattice.kagome(a=1, name=’‘, norbs=None)


Make a kagome lattice.

3.4 kwant.plotter – Plotting of systems

3.4.1 Plotting routines

plot(sys[, num_lead_cells, unit, ...]) Plot a system in 2 or 3 dimensions.


map(sys, value[, colorbar, cmap, vmin, ...]) Show interpolated map of a function defined for the
sites of a system.
current(syst, current[, relwidth]) Show an interpolated current defined for the hop-
pings of a system.
bands(sys[, args, momenta, file, show, dpi, ...]) Plot band structure of a translationally invariant 1D
system.
Continued on next page

104 Chapter 3. Core modules


Kwant 1.3.1 documentation

Table 3.10 – continued from previous page


spectrum(syst, x[, y, params, mask, file, ...]) Plot the spectrum of a Hamiltonian as a function of
1 or 2 parameters
streamplot(field, box[, cmap, bgcolor, ...]) Draw streamlines of a flow field in Kwant style

kwant.plotter.plot

kwant.plotter.plot(sys, num_lead_cells=2, unit=’nn’, site_symbol=None, site_size=None,


site_color=None, site_edgecolor=None, site_lw=None, hop_color=None,
hop_lw=None, lead_site_symbol=None, lead_site_size=None,
lead_color=None, lead_site_edgecolor=None, lead_site_lw=None,
lead_hop_lw=None, pos_transform=None, cmap=’gray’, colorbar=True,
file=None, show=True, dpi=None, fig_size=None, ax=None)
Plot a system in 2 or 3 dimensions.
Parameters sys : kwant.builder.Builder or kwant.system.FiniteSystem
A system to be plotted.
num_lead_cells : int
Number of lead copies to be shown with the system.
unit : ‘nn’, ‘pt’, or float
The unit used to specify symbol sizes and linewidths. Possible choices are:
• ‘nn’: unit is the shortest hopping or a typical nearst neighbor dis-
tance in the system if there are no hoppings. This means that symbol
sizes/linewidths will scale as the zoom level of the figure is changed. Very
short distances are discarded before searching for the shortest. This choice
means that the symbols will scale if the figure is zoomed.
• ‘pt’: unit is points (point = 1/72 inch) in figure space. This means that
symbols and linewidths will always be drawn with the same size indepen-
dent of zoom level of the plot.
• float: sizes are given in units of this value in real (system) space, and will
accordingly scale as the plot is zoomed.
The default value is ‘nn’, which allows to ensure that the images neighboring
sites do not overlap.
site_symbol : symbol specification, function, array, or None
Symbol used for representing a site in the plot. Can be specified as
• ‘o’: circle with radius of 1 unit.
• ‘s’: square with inner circle radius of 1 unit.
• ('p', nvert, angle): regular polygon with nvert vertices, rotated by
angle. angle is given in degrees, and angle=0 corresponds to one edge of
the polygon pointing upward. The radius of the inner circle is 1 unit.
• ‘no symbol’: no symbol is plotted.
• ‘S’, (‘P’, nvert, angle): as the lower-case variants described above, but
with an area equal to a circle of radius 1. (Makes the visual size of the
symbol equal to the size of a circle with radius 1).
• matplotlib.path.Path instance.
Instead of a single symbol, different symbols can be specified for differ-
ent sites by passing a function that returns a valid symbol specification
for each site, or by passing an array of symbols specifications (only for
kwant.system.FiniteSystem).

3.4. kwant.plotter – Plotting of systems 105


Kwant 1.3.1 documentation

site_size : number, function, array, or None


Relative (linear) size of the site symbol.
site_color : matplotlib color description, function, array, or None
A color used for plotting a site in the system. If a colormap is used, it should
be a function returning single floats or a one-dimensional array of floats.
site_edgecolor : matplotlib color description, function, array, or None
Color used for plotting the edges of the site symbols. Only valid matplotlib
color descriptions are allowed (and no combination of floats and colormap as
for site_color).
site_lw : number, function, array, or None
Linewidth of the site symbol edges.
hop_color : matplotlib color description or a function
Same as site_color, but for hoppings. A function is passed two sites in this
case. (arrays are not allowed in this case).
hop_lw : number, function, or None
Linewidth of the hoppings.
lead_site_symbol : symbol specification or None
Symbol to be used for the leads. See site_symbol for allowed specifications.
Note that for leads, only constants (i.e. no functions or arrays) are allowed.
If None, then site_symbol is used if it is constant (i.e. no function or array),
the default otherwise. The same holds for the other lead properties below.
lead_site_size : number or None
Relative (linear) size of the lead symbol
lead_color : matplotlib color description or None
For the leads, num_lead_cells copies of the lead unit cell are plotted.
They are plotted in color fading from lead_color to white (alpha values in
lead_color are supported) when moving from the system into the lead. Is
also applied to the hoppings.
lead_site_edgecolor : matplotlib color description or None
Color of the symbol edges (no fading done).
lead_site_lw : number or None
Linewidth of the lead symbols.
lead_hop_lw : number or None
Linewidth of the lead hoppings.
cmap : matplotlib color map or a sequence of two color maps or None
The color map used for sites and optionally hoppings.
pos_transform : function or None
Transformation to be applied to the site position.
colorbar : bool
Whether to show a colorbar if colormap is used. Ignored if ax is provided.
file : string or file object or None
The output file. If None, output will be shown instead.

106 Chapter 3. Core modules


Kwant 1.3.1 documentation

show : bool
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
dpi : float or None
Number of pixels per inch. If not set the matplotlib default is used.
fig_size : tuple or None
Figure size (width, height) in inches. If not set, the default matplotlib value
is used.
ax : matplotlib.axes.Axes instance or None
If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

Notes

•If None is passed for a plot property, a default value depending on the dimension is chosen.
Typically, the default values result in acceptable plots.
•The meaning of “site” depends on whether the system to be plotted is a builder or a low level
system. For builders, a site is a kwant.builder.Site object. For low level systems, a site is an
integer – the site number.
•color and symbol definitions may be tuples, but not lists or arrays. Arrays of values
(linewidths, colors, sizes) may not be tuples.
•The dimensionality of the plot (2D vs 3D) is inferred from the coordinate array. If there are
more than three coordinates, only the first three are used. If there is just one coordinate, the
second one is padded with zeros.
•The system is scaled to fit the smaller dimension of the figure, given its aspect ratio.

kwant.plotter.map

kwant.plotter.map(sys, value, colorbar=True, cmap=None, vmin=None, vmax=None,


a=None, method=’nearest’, oversampling=3, num_lead_cells=0, file=None,
show=True, dpi=None, fig_size=None, ax=None, pos_transform=None,
background=’#e0e0e0’)
Show interpolated map of a function defined for the sites of a system.
Create a pixmap representation of a function of the sites of a system by calling mask_interpolate
and show this pixmap using matplotlib.
Parameters sys : kwant.system.FiniteSystem or kwant.builder.Builder
The system for whose sites value is to be plotted.
value : function or list
Function which takes a site and returns a value if the system is a builder, or
a list of function values for each system site of the finalized system.
colorbar : bool, optional
Whether to show a color bar if numerical data has to be plotted. Defaults
to True. If ax is provided, the colorbar is never plotted.
cmap : matplotlib color map or None

3.4. kwant.plotter – Plotting of systems 107


Kwant 1.3.1 documentation

The color map used for sites and optionally hoppings, if None, matplotlib
default is used.
vmin : float, optional
The lower saturation limit for the colormap; values returned by value which
are smaller than this will saturate
vmax : float, optional
The upper saturation limit for the colormap; valued returned by value which
are larger than this will saturate
a : float, optional
Reference length. If not given, it is determined as a typical nearest neighbor
distance.
method : string, optional
Passed to scipy.interpolate.griddata: “nearest” (default), “linear”, or
“cubic”
oversampling : integer, optional
Number of pixels per reference length. Defaults to 3.
num_lead_cells : integer, optional
number of lead unit cells that should be plotted to indicate the position of
leads. Defaults to 0.
file : string or file object or None
The output file. If None, output will be shown instead.
show : bool
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
ax : matplotlib.axes.Axes instance or None
If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
pos_transform : function or None
Transformation to be applied to the site position.
background : matplotlib color spec
Areas without sites are filled with this color.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

Notes

•When plotting a system on a square lattice and method is “nearest”, it makes sense to set
oversampling to 1. Then, each site will correspond to exactly one pixel.

kwant.plotter.current

kwant.plotter.current(syst, current, relwidth=0.05, **kwargs)


Show an interpolated current defined for the hoppings of a system.

108 Chapter 3. Core modules


Kwant 1.3.1 documentation

The system graph together with current intensities defines a “discrete” current density field where
the current density is non-zero only on the straight lines that connect sites that are coupled by a
hopping term.
To make this vector field easier to visualize and interpret at different length scales, it is smoothed
by convoluting it with the bell-shaped bump function f(r) = max(1 - (2*r / width)**2, 0)**2.
The bump width is determined by the limit and width parameters.
This routine samples the smoothed field on a regular (square or cubic) grid and displays it using
an enhanced variant of matplotlib’s streamplot.
This is a convenience function that is equivalent to streamplot(*interpolate_current(syst,
current, relwidth), **kwargs). The longer form makes it possible to tweak additional options
of interpolate_current.
Parameters syst : kwant.system.FiniteSystem
The system for which to plot the current.
current : sequence of float
Sequence of values defining currents on each hopping of the system. Ordered
in the same way as syst.graph. This typically will be the result of evaluating
a Current operator.
relwidth : float or None
Relative width of the bumps used to generate the field, as a fraction of the
length of the longest side of the bounding box.
**kwargs : various
Keyword args to be passed verbatim to streamplot.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

kwant.plotter.bands

kwant.plotter.bands(sys, args=(), momenta=65, file=None, show=True, dpi=None,


fig_size=None, ax=None, *, params=None)
Plot band structure of a translationally invariant 1D system.
Parameters sys : kwant.system.InfiniteSystem
A system bands of which are to be plotted.
args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutally exclusive
with ‘params’.
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.
file : string or file object or None
The output file. If None, output will be shown instead.
show : bool
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
dpi : float
Number of pixels per inch. If not set the matplotlib default is used.

3.4. kwant.plotter – Plotting of systems 109


Kwant 1.3.1 documentation

fig_size : tuple
Figure size (width, height) in inches. If not set, the default matplotlib value
is used.
ax : matplotlib.axes.Axes instance or None
If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

Notes

See Bands for the calculation of dispersion without plotting.

kwant.plotter.spectrum

kwant.plotter.spectrum(syst, x, y=None, params=None, mask=None, file=None, show=True,


dpi=None, fig_size=None, ax=None)
Plot the spectrum of a Hamiltonian as a function of 1 or 2 parameters
Parameters syst : kwant.system.FiniteSystem or callable
If a function, then it must take named parameters and return the Hamilto-
nian as a dense matrix.
x : pair (name, values)
Parameter to ham that will be varied. Consists of the parameter name, and
a sequence of parameter values.
y : pair (name, values), optional
Used for 3D plots (same as x). If provided, then the cartesian product of the
x values and these values will be used as a grid over which to evaluate the
spectrum.
params : dict, optional
The rest of the parameters to ham, which will be kept constant.
mask : callable, optional
Takes the parameters specified by x and y and returns True if the spectrum
should not be calculated for the given parameter values.
file : string or file object or None
The output file. If None, output will be shown instead.
show : bool
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
dpi : float
Number of pixels per inch. If not set the matplotlib default is used.
fig_size : tuple

110 Chapter 3. Core modules


Kwant 1.3.1 documentation

Figure size (width, height) in inches. If not set, the default matplotlib value
is used.
ax : matplotlib.axes.Axes instance or None
If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

kwant.plotter.streamplot

kwant.plotter.streamplot(field, box, cmap=None, bgcolor=None, linecolor=’k’,


max_linewidth=3, min_linewidth=1, density=0.2222222222222222,
colorbar=True, file=None, show=True, dpi=None, fig_size=None,
ax=None)
Draw streamlines of a flow field in Kwant style
Solid colored streamlines are drawn, superimposed on a color plot of the flow speed that may be
disabled by setting bgcolor. The width of the streamlines is proportional to the flow speed. Lines
that would be thinner than min_linewidth are blended into the background color in order to create
the illusion of arbitrarily thin lines. (This is done because some plot backends like PDF do not
support lines of arbitrary width.)
Internally, this routine uses matplotlib.pyplot.streamplot.
Parameters field : 3d arraylike of float
2d array of 2d vectors.
box : 2-sequence of 2-sequences of float
the extents of field: ((x0, x1), (y0, y1))
cmap : colormap, optional
Colormap for the background color plot. When not set the colormap
“kwant_red” is used by default, unless bgcolor is set.
bgcolor : color definition, optional
The solid color of the background. Mutually exclusive with cmap.
linecolor : color definition
Color of the flow lines.
max_linewidth : float
Width of lines at maximum flow speed.
min_linewidth : float
Minimum width of lines before blending into the background color begins.
density : float
Number of flow lines per point of the field. The default value is cho-
sen to show two lines per default width of the interpolation bump of
interpolate_current.
colorbar : bool
Whether to show a colorbar if a colormap is used. Ignored if ax is provided.
file : string or file object or None
The output file. If None, output will be shown instead.

3.4. kwant.plotter – Plotting of systems 111


Kwant 1.3.1 documentation

show : bool
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
dpi : float or None
Number of pixels per inch. If not set the matplotlib default is used.
fig_size : tuple or None
Figure size (width, height) in inches. If not set, the default matplotlib value
is used.
ax : matplotlib.axes.Axes instance or None
If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.

3.4.2 Helper functions

interpolate_current(syst, current[, ...]) Interpolate currents in a system onto a regular grid.


sys_leads_sites(sys[, num_lead_cells]) Return all the sites of the system and of the leads as
a list.
sys_leads_hoppings(sys[, num_lead_cells]) Return all the hoppings of the system and of the
leads as an iterator.
sys_leads_pos(sys, site_lead_nr) Return an array of positions of sites in a system.
sys_leads_hopping_pos(sys, hop_lead_nr) Return arrays of coordinates of all hoppings in a sys-
tem.
mask_interpolate(coords, values[, a, ...]) Interpolate a scalar function in vicinity of given
points.

kwant.plotter.interpolate_current

kwant.plotter.interpolate_current(syst, current, relwidth=None, abswidth=None, n=9)


Interpolate currents in a system onto a regular grid.
The system graph together with current intensities defines a “discrete” current density field where
the current density is non-zero only on the straight lines that connect sites that are coupled by a
hopping term.
To make this vector field easier to visualize and interpret at different length scales, it is smoothed
by convoluting it with the bell-shaped bump function f(r) = max(1 - (2*r / width)**2, 0)**2.
The bump width is determined by the max_res and width parameters.
This routine samples the smoothed field on a regular (square or cubic) grid.
Parameters syst : A finalized system
The system on which we are going to calculate the field.
current : ‘1D array of float’
Must contain the intensity on each hoppings in the same order that they
appear in syst.graph.
relwidth : float or None
Relative width of the bumps used to generate the field, as a fraction of the
length of the longest side of the bounding box. This argument is only used
if abswidth is not given.

112 Chapter 3. Core modules


Kwant 1.3.1 documentation

abswidth : float or None


Absolute width ot the bumps used to generate the field. Takes precedence
over relwidth. If neither is given, the bump width is set to four times the
length of the shortest hopping.
n : int
Number of points the grid must have over the width of the bump.
Returns field : n-d arraylike of float
n-d array of n-d vectors.
box : sequence of 2-sequences of float
the extents of field: ((x0, x1), (y0, y1), ...)

kwant.plotter.sys_leads_sites

kwant.plotter.sys_leads_sites(sys, num_lead_cells=2)
Return all the sites of the system and of the leads as a list.
Parameters sys : kwant.builder.Builder or kwant.system.System instance
The system, sites of which should be returned.
num_lead_cells : integer
The number of times lead sites from each lead should be returned. This is
useful for showing several unit cells of the lead next to the system.
Returns sites : list of (site, lead_number, copy_number) tuples
A site is a Site instance if the system is not finalized, and an integer other-
wise. For system sites lead_number is None and copy_number is 0, for leads
both are integers.
lead_cells : list of slices
lead_cells[i] gives the position of all the coordinates of lead i within sites.

Notes

Leads are only supported if they are of the same type as the original system, i.e. sites of
BuilderLead leads are returned with an unfinalized system, and sites of system.InfiniteSystem
leads are returned with a finalized system.

kwant.plotter.sys_leads_hoppings

kwant.plotter.sys_leads_hoppings(sys, num_lead_cells=2)
Return all the hoppings of the system and of the leads as an iterator.
Parameters sys : kwant.builder.Builder or kwant.system.System instance
The system, sites of which should be returned.
num_lead_cells : integer
The number of times lead sites from each lead should be returned. This is
useful for showing several unit cells of the lead next to the system.
Returns hoppings : list of (hopping, lead_number, copy_number) tuples

3.4. kwant.plotter – Plotting of systems 113


Kwant 1.3.1 documentation

A site is a Site instance if the system is not finalized, and an integer other-
wise. For system sites lead_number is None and copy_number is 0, for leads
both are integers.
lead_cells : list of slices
lead_cells[i] gives the position of all the coordinates of lead i within hoppings.

Notes

Leads are only supported if they are of the same type as the original system, i.e. hoppings of
BuilderLead leads are returned with an unfinalized system, and hoppings of InfiniteSystem
leads are returned with a finalized system.

kwant.plotter.sys_leads_pos

kwant.plotter.sys_leads_pos(sys, site_lead_nr)
Return an array of positions of sites in a system.
Parameters sys : kwant.builder.Builder or kwant.system.System instance
The system, coordinates of sites of which should be returned.
site_lead_nr : list of (site, leadnr, copynr) tuples
Output of sys_leads_sites applied to the system.
Returns coords : numpy.ndarray of floats
Array of coordinates of the sites.

Notes

This function uses site.pos property to get the position of a builder site and sys.pos(sitenr) for
finalized systems. This function requires that all the positions of all the sites have the same
dimensionality.

kwant.plotter.sys_leads_hopping_pos

kwant.plotter.sys_leads_hopping_pos(sys, hop_lead_nr)
Return arrays of coordinates of all hoppings in a system.
Parameters sys : ~kwant.builder.Builder or ~kwant.system.System instance
The system, coordinates of sites of which should be returned.
hoppings : list of (hopping, leadnr, copynr) tuples
Output of sys_leads_hoppings applied to the system.
Returns coords : (end_site, start_site): tuple of NumPy arrays of floats
Array of coordinates of the hoppings. The first half of coordinates in each
array entry are those of the first site in the hopping, the last half are those
of the second site.

Notes

This function uses site.pos property to get the position of a builder site and sys.pos(sitenr)
for finalized systems. This function requires that all the positions of all the sites have the same
dimensionality.

114 Chapter 3. Core modules


Kwant 1.3.1 documentation

kwant.plotter.mask_interpolate

kwant.plotter.mask_interpolate(coords, values, a=None, method=’nearest’, oversampling=3)


Interpolate a scalar function in vicinity of given points.
Create a masked array corresponding to interpolated values of the function at points lying not
further than a certain distance from the original data points provided.
Parameters coords : np.ndarray
An array with site coordinates.
values : np.ndarray
An array with the values from which the interpolation should be built.
a : float, optional
Reference length. If not given, it is determined as a typical nearest neighbor
distance.
method : string, optional
Passed to scipy.interpolate.griddata: “nearest” (default), “linear”, or
“cubic”
oversampling : integer, optional
Number of pixels per reference length. Defaults to 3.
Returns array : 2d NumPy array
The interpolated values.
min, max : vectors
The real-space coordinates of the two extreme ([0, 0] and [-1, -1]) points of
array.

Notes

•min and max are chosen such that when plotting a system on a square lattice and oversampling
is set to an odd integer, each site will lie exactly at the center of a pixel of the output array.
•When plotting a system on a square lattice and method is “nearest”, it makes sense to set
oversampling to 1. Then, each site will correspond to exactly one pixel in the resulting array.

3.5 kwant.solvers – Library of solvers

3.5.1 Overview

Kwant offers several modules for computing the solutions to quantum transport problems, the so-called
solvers. Each of these solvers may use different internal algorithms and/or depend on different exter-
nal libraries. If the libraries needed by one solver are not installed, trying to import it will raise an
ImportError exception. The Installation instructions list all the libraries that are required or can be
used by Kwant and its solvers.

3.5.2 kwant.solvers.default – The default solver

There is one solver, kwant.solvers.default that is always available. For each Kwant installation it
combines the best functionality of the available solvers into a single module. We recommend to use it
unless there are specific reasons to use another. The following functions are provided.

3.5. kwant.solvers – Library of solvers 115


Kwant 1.3.1 documentation

smatrix(sys[, energy, args, out_leads, ...]) Compute the scattering matrix of a system.
greens_function(sys[, energy, args, ...]) Compute the retarded Green’s function of the sys-
tem between its leads.
wave_function(sys[, energy, args, ...]) Return a callable object for the computation of the
wave function inside the scattering region.
ldos(sys[, energy, args, check_hermiticity, ...]) Calculate the local density of states of a system at a
given energy.

kwant.solvers.default.smatrix

kwant.solvers.default.smatrix(sys, energy=0, args=(), out_leads=None, in_leads=None,


check_hermiticity=True, *, params=None)
Compute the scattering matrix of a system.
Parameters sys : kwant.system.FiniteSystem
Low level system, containing the leads and the Hamiltonian of a scattering
region.
energy : number
Excitation energy at which to solve the scattering problem.
args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
out_leads : sequence of integers or None
Numbers of leads where current or wave function is extracted. None is in-
terpreted as all leads. Default is None and means “all leads”.
in_leads : sequence of integers or None
Numbers of leads in which current or wave function is injected. None is
interpreted as all leads. Default is None and means “all leads”.
check_hermiticity : bool
Check if the Hamiltonian matrices are Hermitian. Enables deduction of
missing transmission coefficients.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns output : SMatrix
See the notes below and SMatrix documentation.

Notes

This function can be used to calculate the conductance and other transport properties of a system.
See the documentation for its output type, SMatrix.
The returned object contains the scattering matrix elements from the in_leads to the out_leads as
well as information about the lead modes.
Both in_leads and out_leads must be sorted and may only contain unique entries.

116 Chapter 3. Core modules


Kwant 1.3.1 documentation

kwant.solvers.default.greens_function

kwant.solvers.default.greens_function(sys, energy=0, args=(), out_leads=None,


in_leads=None, check_hermiticity=True, *,
params=None)
Compute the retarded Green’s function of the system between its leads.
Parameters sys : kwant.system.FiniteSystem
Low level system, containing the leads and the Hamiltonian of a scattering
region.
energy : number
Excitation energy at which to solve the scattering problem.
args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
out_leads : sequence of integers or None
Numbers of leads where current or wave function is extracted. None is in-
terpreted as all leads. Default is None and means “all leads”.
in_leads : sequence of integers or None
Numbers of leads in which current or wave function is injected. None is
interpreted as all leads. Default is None and means “all leads”.
check_hermiticity : bool
Check if the Hamiltonian matrices are Hermitian. Enables deduction of
missing transmission coefficients.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns output : GreensFunction
See the notes below and GreensFunction documentation.

Notes

This function can be used to calculate the conductance and other transport properties of a system.
It is often slower and less stable than the scattering matrix-based calculation executed by smatrix,
and is currently provided mostly for testing purposes and compatibility with RGF code.
It returns an object encapsulating the Green’s function elements between the system sites inter-
facing the leads in in_leads and those interfacing the leads in out_leads. The returned object also
contains a list with self-energies of the leads.
Both in_leads and out_leads must be sorted and may only contain unique entries.

kwant.solvers.default.wave_function

kwant.solvers.default.wave_function(sys, energy=0, args=(), check_hermiticity=True, *,


params=None)
Return a callable object for the computation of the wave function inside the scattering region.
Parameters sys : kwant.system.FiniteSystem
The low level system for which the wave functions are to be calculated.

3.5. kwant.solvers – Library of solvers 117


Kwant 1.3.1 documentation

args : tuple of arguments, or empty tuple


Positional arguments to pass to the function(s) which evaluate the hamilto-
nian matrix elements. Mutually exclusive with ‘params’.
check_hermiticity : bool
Check if the Hamiltonian matrices are Hermitian.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.

Notes

The returned object can be itself called like a function. Given a lead number, it returns a 2d
NumPy array that contains the wave function within the scattering region due to each incoming
mode of the given lead. Index 0 is the mode number, index 1 is the orbital number. The modes
appear in the same order as incoming modes in kwant.physics.modes.

Examples

>>> wf = kwant.solvers.default.wave_function(some_syst, some_energy)


>>> wfs_of_lead_2 = wf(2)

kwant.solvers.default.ldos

kwant.solvers.default.ldos(sys, energy=0, args=(), check_hermiticity=True, *,


params=None)
Calculate the local density of states of a system at a given energy.
Parameters sys : kwant.system.FiniteSystem
Low level system, containing the leads and the Hamiltonian of the scattering
region.
energy : number
Excitation energy at which to solve the scattering problem.
args : tuple of arguments, or empty tuple
Positional arguments to pass to the function(s) which evaluate the hamilto-
nian matrix elements. Mutually exclusive with ‘params’.
check_hermiticity : bool
Check if the Hamiltonian matrices are Hermitian.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns ldos : a NumPy array
Local density of states at each orbital of the system.
smatrix returns an object of the following type:

kwant.solvers.common.SMatrix(data, ...[, ...]) A scattering matrix.

118 Chapter 3. Core modules


Kwant 1.3.1 documentation

kwant.solvers.common.SMatrix

class kwant.solvers.common.SMatrix(data, lead_info, out_leads, in_leads, cur-


rent_conserving=False)
Bases: kwant.solvers.common.BlockResult
A scattering matrix.
Transport properties can be easily accessed using the transmission method (don’t be fooled by
the name, it can also compute reflection, which is just transmission from one lead back into the
same lead.)
SMatrix however also allows for a more direct access to the result: The data stored in SMatrix is
a scattering matrix with respect to lead modes and these modes themselves. The details of this
data can be directly accessed through the instance variables data and lead_info. Subblocks of data
corresponding to particular leads are conveniently obtained by submatrix.
SMatrix also respects the conservation laws present in the lead, such as spin conservation, if
they are declared during system construction. If queried with length-2 sequence the first number
is the number of the lead, and the second number is the index of the corresponding conserved
quantity. For example smatrix.transmission((1, 3), (0, 2)) is transmission from block 2 of
the conserved quantity in lead 0 to the block 3 of the conserved quantity in lead 1.

Attributes

data (NumPy array) a matrix containing all the requested matrix elements of the
scattering matrix.
lead_info (list of data) a list containing kwant.physics.PropagatingModes for each lead.
out_leads, (sequence of integers) indices of the leads where current is extracted (out) or
in_leads injected (in). Only those are listed for which SMatrix contains the calculated
result.

Methods

block_coords(lead_out, lead_in)
Return slices corresponding to the block from lead_in to lead_out.
conductance_matrix()
Return the conductance matrix.
This is the matrix 𝐶 such that 𝐼 = 𝐶𝑉 where 𝐼 and 𝑉 are, respectively, the vectors of currents
and voltages for each lead.
This matrix is useful for calculating non-local resistances. See Section 2.4 of the book by S.
Datta.
in_block_coords(lead_in)
Return a slice with the columns in the block corresponding to lead_in.
num_propagating(lead)
Return the number of propagating modes in the lead.
out_block_coords(lead_out)
Return a slice with the rows in the block corresponding to lead_out.
submatrix(lead_out, lead_in)
Return the matrix elements from lead_in to lead_out.
transmission(lead_out, lead_in)
Return transmission from lead_in to lead_out.

3.5. kwant.solvers – Library of solvers 119


Kwant 1.3.1 documentation

If lead_in or lead_out are a length-2 sequence, the first number is the number of the lead, and
the second number indexes the eigenvalue of the conserved quantity in that lead (e.g. spin) if
it was specified.
The analog of smatrix, greens_function accordingly returns:

kwant.solvers.common.GreensFunction(data, ...) Retarded Green’s function.

kwant.solvers.common.GreensFunction

class kwant.solvers.common.GreensFunction(data, lead_info, out_leads, in_leads, cur-


rent_conserving=False)
Bases: kwant.solvers.common.BlockResult
Retarded Green’s function.
Transport properties can be easily accessed using the transmission method (don’t be fooled by
the name, it can also compute reflection, which is just transmission from one lead back into the
same lead).
GreensFunction however also allows for a more direct access to the result: The data stored in
GreensFunction is the real-space Green’s function. The details of this data can be directly accessed
through the instance variables data and lead_info. Subblocks of data corresponding to particular
leads are conveniently obtained by submatrix.

Attributes

data (NumPy array) a matrix containing all the requested matrix elements of Green’s
function.
lead_info (list of matrices) a list with self-energies of each lead.
out_leads, (sequence of integers) indices of the leads where current is extracted (out) or
in_leads injected (in). Only those are listed for which SMatrix contains the calculated
result.

Methods

block_coords(lead_out, lead_in)
Return slices corresponding to the block from lead_in to lead_out.
conductance_matrix()
Return the conductance matrix.
This is the matrix 𝐶 such that 𝐼 = 𝐶𝑉 where 𝐼 and 𝑉 are, respectively, the vectors of currents
and voltages for each lead.
This matrix is useful for calculating non-local resistances. See Section 2.4 of the book by S.
Datta.
in_block_coords(lead_in)
Return a slice with the columns in the block corresponding to lead_in.
num_propagating(lead)
Return the number of propagating modes in the lead.
out_block_coords(lead_out)
Return a slice with the rows in the block corresponding to lead_out.
submatrix(lead_out, lead_in)
Return the matrix elements from lead_in to lead_out.

120 Chapter 3. Core modules


Kwant 1.3.1 documentation

transmission(lead_out, lead_in)
Return transmission from lead_in to lead_out.
If the option current_conserving has been enabled for this object, this method will deduce
missing transmission values whenever possible.
Current conservation is enabled by default for objects returned by smatrix and
greens_function whenever the Hamiltonian has been verified to be Hermitian (option
check_hermiticity, enabled by default).
Being just a thin wrapper around other solvers, the default solver selectively imports their functionality.
To find out the origin of any function in this module, use Python’s help. For example

>>> help(kwant.solvers.default.ldos)

3.5.3 Other solver modules

Unlike the default one, other solvers have to be imported manually. They provide, whenever possible,
exactly the same interface as the default. Some allow for specific tuning that can improve performance.
The differences to the default solver are listed in the documentation of each module.

kwant.solvers.sparse – Basic sparse matrix solver

This solver uses SciPy’s scipy.sparse.linalg. The interface is identical to that of the default solver.
scipy.sparse.linalg currently uses internally either the direct sparse solver UMFPACK or if that is
not installed, SuperLU. Often, SciPy’s SuperLU will give quite poor performance and you will be warned
if only SuperLU is found. The module variable uses_umfpack can be checked to determine if UMFPACK
is being used.

kwant.solvers.mumps – High performance sparse solver based on MUMPS

This solver uses MUMPS. (Only the sequential, single core version of MUMPS is used.) MUMPS is a
very efficient direct sparse solver that can take advantage of memory beyond 3GiB for the solution of
large problems. Furthermore, it offers a choice of several orderings of the input matrix some of which
can speed up a calculation significantly.
Compared with the default solver, this module adds several options that may be used to fine-tune
performance. Otherwise the interface is identical. These options can be set and queried with the following
functions.
kwant.solvers.mumps.options(self, nrhs=None, ordering=None, sparse_rhs=None)
Modify some options. Return the old options.
Parameters nrhs : number
number of right hand sides that should be solved simultaneously. A value
around 5-10 gives optimal performance on many machines. If memory is an
issue, it can be set to 1, to minimize memory usage (at the cost of slower
performance). Default value is 6.
ordering : string
one of the ordering methods supported by the MUMPS solver (see kwant.
linalg.mumps. The availability of certain orderings depends on the MUMPS
installation.), or ‘kwant_decides’. If ordering=='kwant_decides', the or-
dering that typically gives the best performance is chosen from the available
ones. One can also defer the choice of ordering to MUMPS by specifying
‘auto’, in some cases MUMPS however chooses poorly.

3.5. kwant.solvers – Library of solvers 121


Kwant 1.3.1 documentation

The choice of ordering can significantly influence the performance and


memory impact of the solve phase. Typically the nested dissection order-
ings ‘metis’ and ‘scotch’ are most suited for physical systems. Default is
‘kwant_decides’
sparse_rhs : True or False
whether to use a sparse right hand side in the solve phase of MUMPS. Pre-
liminary tests have not shown a significant performance increase when this
feature is used, but this needs more looking into. Default value is False.
Returns old_options: dict
dictionary containing the previous options.

Notes

Thanks to this method returning the old options as a dictionary it is easy to change some options
temporarily:

>>> saved_options = kwant.solvers.mumps.options(nrhs=12)


>>> some_code()
>>> kwant.solvers.mumps.options(**saved_options)

kwant.solvers.mumps.reset_options(self )
Set the options to default values. Return the old options.

3.5.4 For Kwant experts: detail of the internal structure of a solver

Each solver module (except the default one) contains a class Solver (e.g. kwant.solvers.sparse.
Solver), that actually implements that solver’s functionality. For each module-level function provided
by the solver, there is a correspondent method in the Solver class. The module-level functions are
simply the methods of a hidden Solver instance that is present in each solver module.
The encapsulation in a class allows different solvers to easily share common code. It also makes it
possible to use solvers with different options concurrently. Typically, one does not need this flexibility,
and will not want to bother with the Solver class itself. Instead, one will use the module-level functions
as explained in the previous sections.

3.6 kwant.operator – Operators and Observables

3.6.1 Observables

Density(syst[, onsite, where, ...]) An operator for calculating general densities.


Current(syst[, onsite, where, ...]) An operator for calculating general currents.
Source(syst[, onsite, where, ...]) An operator for calculating general sources.

kwant.operator.Density

class kwant.operator.Density(syst, onsite=1, where=None, check_hermiticity=True, *,


sum=False)
Bases: kwant.operator._LocalOperator
An operator for calculating general densities.
An instance of this class can be called like a function to evaluate the expectation value with a
wavefunction. See the documentation of the __call__ method for more details.

122 Chapter 3. Core modules


Kwant 1.3.1 documentation

Parameters syst : System


onsite : scalar or square matrix or dict or callable
The onsite matrix that defines the operator. If a dict is given, it maps from
site families to square matrices. If a function is given it must take the same
arguments as the onsite Hamiltonian functions of the system.
where : sequence of int or Site, or callable, optional
Where to evaluate the operator. If syst is not a finalized Builder, then this
should be a sequence of integers. If a function is provided, it should take a
single int or Site (if syst is a finalized builder) and return True or False. If
not provided, the operator will be calculated over all sites in the system.
check_hermiticity: bool
Check whether the provided onsite is Hermitian. If it is not Hermitian,
then an error will be raised when the operator is evaluated.
sum : bool, default: False
If True, then calling this operator will return a single scalar.

Notes

In general, if there is a certain “density” (e.g. charge or spin) that is represented by a square matrix
𝑀𝑖 associated with each site 𝑖 then an instance of this class represents the tensor 𝑄𝑖𝛼𝛽 which is
equal to 𝑀𝑖 when 𝛼 and 𝛽 are orbitals on site 𝑖, and zero otherwise.

Methods

act(self, ket, args=(), *, params=None)


Act with the operator on a wavefunction.
For an operator 𝑄𝑖𝛼𝛽 and ket 𝜓𝛽 this computes ∑𝑖𝛽 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters ket : sequence of complex
Wavefunctions defined over all the orbitals of the system.
args : tuple
The extra arguments to the Hamiltonian value functions and the operator
onsite function. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns Array of complex.
bind(self, args=(), *, params=None)
Bind the given arguments to this operator.
Returns a copy of this operator that does not need to be passed extra arguments when
subsequently called or when using the act method.
tocoo(self, args=(), *, params=None)
Convert the operator to coordinate format sparse matrix.
__call__()
Return the matrix elements of the operator.
An operator A can be called like

3.6. kwant.operator – Operators and Observables 123


Kwant 1.3.1 documentation

>>> A(psi)

to compute the expectation value ⟨𝜓| 𝐴 |𝜓⟩, or like

>>> A(phi, psi)

to compute the matrix element ⟨𝜑| 𝐴 |𝜓⟩. Note that these quantities may be vectors (e.g. local
charge or current density).
For an operator 𝑄𝑖𝛼𝛽 , bra 𝜑𝛼 and ket 𝜓𝛽 this computes 𝑞𝑖 = ∑𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 if self.sum is
False, otherwise computes 𝑞 = ∑𝑖𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters bra, ket : sequence of complex
Must have the same length as the number of orbitals in the system. If only
one is provided, both bra and ket are taken as equal.
args : tuple, optional
The arguments to pass to the system. Used to evaluate the onsite elements
and, possibly, the system Hamiltonian. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns float if check_hermiticity is True, and ket is None,
otherwise complex. If this operator was created with sum=True,
then a single value is returned, otherwise an array is returned.

Attributes

check_hermiticity
onsite
sum
syst
where

kwant.operator.Current

class kwant.operator.Current(syst, onsite=1, where=None, check_hermiticity=True, *,


sum=False)
Bases: kwant.operator._LocalOperator
An operator for calculating general currents.
An instance of this class can be called like a function to evaluate the expectation value with a
wavefunction. See the documentation of the __call__ method for more details.
Parameters syst : System
onsite : scalar or square matrix or dict or callable
The onsite matrix that defines the density from which this current is derived.
If a dict is given, it maps from site families to square matrices (scalars are
allowed if the site family has 1 orbital per site). If a function is given it must
take the same arguments as the onsite Hamiltonian functions of the system.
where : sequence of pairs of int or Site, or callable, optional

124 Chapter 3. Core modules


Kwant 1.3.1 documentation

Where to evaluate the operator. If syst is not a finalized Builder, then this
should be a sequence of pairs of integers. If a function is provided, it should
take a pair of integers or a pair of Site (if syst is a finalized builder) and
return True or False. If not provided, the operator will be calculated over
all hoppings in the system.
check_hermiticity : bool
Check whether the provided onsite is Hermitian. If it is not Hermitian,
then an error will be raised when the operator is evaluated.
sum : bool, default: False
If True, then calling this operator will return a single scalar.

Notes

In general, if there is a certain “density” (e.g. charge or spin) that is represented by a square matrix
𝑀𝑖 associated with each site 𝑖 and 𝐻𝑖𝑗 is the hopping Hamiltonian from site 𝑗 to site i, then an
instance of this class represents the tensor 𝐽𝑖𝑗𝛼𝛽 which is equal to 𝑖 [(𝐻𝑖𝑗 )† 𝑀𝑖 − 𝑀𝑖 𝐻𝑖𝑗 ] when 𝛼
and 𝛽 are orbitals on sites 𝑖 and 𝑗 respectively, and zero otherwise.
The tensor 𝐽𝑖𝑗𝛼𝛽 will also be referred to as 𝑄𝑛𝛼𝛽 , where 𝑛 is the index of hopping (𝑖, 𝑗) in where.

Methods

act(self, ket, args=(), *, params=None)


Act with the operator on a wavefunction.
For an operator 𝑄𝑖𝛼𝛽 and ket 𝜓𝛽 this computes ∑𝑖𝛽 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters ket : sequence of complex
Wavefunctions defined over all the orbitals of the system.
args : tuple
The extra arguments to the Hamiltonian value functions and the operator
onsite function. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns Array of complex.
bind(self, args=(), *, params=None)
Bind the given arguments to this operator.
Returns a copy of this operator that does not need to be passed extra arguments when
subsequently called or when using the act method.
__call__()
Return the matrix elements of the operator.
An operator A can be called like

>>> A(psi)

to compute the expectation value ⟨𝜓| 𝐴 |𝜓⟩, or like

>>> A(phi, psi)

3.6. kwant.operator – Operators and Observables 125


Kwant 1.3.1 documentation

to compute the matrix element ⟨𝜑| 𝐴 |𝜓⟩. Note that these quantities may be vectors (e.g. local
charge or current density).
For an operator 𝑄𝑖𝛼𝛽 , bra 𝜑𝛼 and ket 𝜓𝛽 this computes 𝑞𝑖 = ∑𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 if self.sum is
False, otherwise computes 𝑞 = ∑𝑖𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters bra, ket : sequence of complex
Must have the same length as the number of orbitals in the system. If only
one is provided, both bra and ket are taken as equal.
args : tuple, optional
The arguments to pass to the system. Used to evaluate the onsite elements
and, possibly, the system Hamiltonian. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns float if check_hermiticity is True, and ket is None,
otherwise complex. If this operator was created with sum=True,
then a single value is returned, otherwise an array is returned.

Attributes

check_hermiticity
onsite
sum
syst
where

kwant.operator.Source

class kwant.operator.Source(syst, onsite=1, where=None, check_hermiticity=True, *,


sum=False)
Bases: kwant.operator._LocalOperator
An operator for calculating general sources.
An instance of this class can be called like a function to evaluate the expectation value with a
wavefunction. See the documentation of the __call__ method for more details.
Parameters syst : System
onsite : scalar or square matrix or dict or callable
The onsite matrix that defines the density from which this source is defined.
If a dict is given, it maps from site families to square matrices (scalars are
allowed if the site family has 1 orbital per site). If a function is given it must
take the same arguments as the onsite Hamiltonian functions of the system.
where : sequence of int or Site, or callable, optional
Where to evaluate the operator. If syst is not a finalized Builder, then this
should be a sequence of integers. If a function is provided, it should take a
single int or Site (if syst is a finalized builder) and return True or False. If
not provided, the operator will be calculated over all sites in the system.
check_hermiticity : bool

126 Chapter 3. Core modules


Kwant 1.3.1 documentation

Check whether the provided onsite is Hermitian. If it is not Hermitian,


then an error will be raised when the operator is evaluated.
sum : bool, default: False
If True, then calling this operator will return a single scalar.

Notes

An example of a “source” is a spin torque. In general, if there is a certain “density” (e.g. charge
or spin) that is represented by a square matrix 𝑀𝑖 associated with each site 𝑖, and 𝐻𝑖 is the onsite
Hamiltonian on site site i, then an instance of this class represents the tensor 𝑄𝑖𝛼𝛽 which is equal
to (𝐻𝑖 )† 𝑀𝑖 − 𝑀𝑖 𝐻𝑖 when 𝛼 and 𝛽 are orbitals on site 𝑖, and zero otherwise.

Methods

act(self, ket, args=(), *, params=None)


Act with the operator on a wavefunction.
For an operator 𝑄𝑖𝛼𝛽 and ket 𝜓𝛽 this computes ∑𝑖𝛽 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters ket : sequence of complex
Wavefunctions defined over all the orbitals of the system.
args : tuple
The extra arguments to the Hamiltonian value functions and the operator
onsite function. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns Array of complex.
bind(self, args=(), *, params=None)
Bind the given arguments to this operator.
Returns a copy of this operator that does not need to be passed extra arguments when
subsequently called or when using the act method.
__call__()
Return the matrix elements of the operator.
An operator A can be called like

>>> A(psi)

to compute the expectation value ⟨𝜓| 𝐴 |𝜓⟩, or like

>>> A(phi, psi)

to compute the matrix element ⟨𝜑| 𝐴 |𝜓⟩. Note that these quantities may be vectors (e.g. local
charge or current density).
For an operator 𝑄𝑖𝛼𝛽 , bra 𝜑𝛼 and ket 𝜓𝛽 this computes 𝑞𝑖 = ∑𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 if self.sum is
False, otherwise computes 𝑞 = ∑𝑖𝛼𝛽 𝜑∗𝛼 𝑄𝑖𝛼𝛽 𝜓𝛽 .
Parameters bra, ket : sequence of complex
Must have the same length as the number of orbitals in the system. If only
one is provided, both bra and ket are taken as equal.

3.6. kwant.operator – Operators and Observables 127


Kwant 1.3.1 documentation

args : tuple, optional


The arguments to pass to the system. Used to evaluate the onsite elements
and, possibly, the system Hamiltonian. Mutually exclusive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns float if check_hermiticity is True, and ket is None,
otherwise complex. If this operator was created with sum=True,
then a single value is returned, otherwise an array is returned.

Attributes

check_hermiticity
onsite
sum
syst
where

3.7 kwant.physics – Physics-related algorithms

3.7.1 Leads

Bands(sys[, args, params]) Class of callable objects for the computation of en-
ergy bands.
modes(h_cell, h_hop[, tol, stabilization, ...]) Compute the eigendecomposition of a translation op-
erator of a lead.
selfenergy(h_cell, h_hop[, tol]) Compute the self-energy generated by the lead.
two_terminal_shotnoise(smatrix) Compute the shot-noise in a two-terminal setup.
PropagatingModes(wave_functions, velocities, ...) The calculated propagating modes of a lead.
StabilizedModes(vecs, vecslmbdainv, nmodes) Stabilized eigendecomposition of the translation op-
erator.

kwant.physics.Bands

class kwant.physics.Bands(sys, args=(), *, params=None)


Bases: object
Class of callable objects for the computation of energy bands.
Parameters sys : kwant.system.InfiniteSystem
The low level infinite system for which the energies are to be calculated.
args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.

128 Chapter 3. Core modules


Kwant 1.3.1 documentation

Notes

An instance of this class can be called like a function. Given a momentum (currently this must be a
scalar as all infinite systems are quasi-1-d), it returns a NumPy array containing the eigenenergies
of all modes at this momentum

Examples

>>> bands = kwant.physics.Bands(some_syst)


>>> momenta = numpy.linspace(-numpy.pi, numpy.pi, 101)
>>> energies = [bands(k) for k in momenta]
>>> pyplot.plot(momenta, energies)
>>> pyplot.show()

Methods

kwant.physics.modes

kwant.physics.modes(h_cell, h_hop, tol=1000000.0, stabilization=None, *, dis-


crete_symmetry=None, projectors=None, time_reversal=None, par-
ticle_hole=None, chiral=None)
Compute the eigendecomposition of a translation operator of a lead.
Parameters h_cell : numpy array, real or complex, shape (N,N) The unit cell
Hamiltonian of the lead unit cell.
h_hop : numpy array, real or complex, shape (N,M)
The hopping matrix from a lead cell to the one on which self-energy has to
be calculated (and any other hopping in the same direction).
tol : float
Numbers and differences are considered zero when they are smaller than tol
times the machine precision.
stabilization : sequence of 2 booleans or None
Which steps of the eigenvalue prolem stabilization to perform. If the value
is None, then Kwant chooses the fastest (and least stable) algorithm that is
expected to be sufficient. For any other value, Kwant forms the eigenvalue
problem in the basis of the hopping singular values. The first element set
to True forces Kwant to add an anti-Hermitian term to the cell Hamiltonian
before inverting. If it is set to False, the extra term will only be added if
the cell Hamiltonian isn’t invertible. The second element set to True forces
Kwant to solve a generalized eigenvalue problem, and not to reduce it to the
regular one. If it is False, reduction to a regular problem is performed if
possible. Selecting the stabilization manually is mostly necessary for testing
purposes.
particle_hole : sparse or dense square matrix
The unitary part of the particle-hole symmetry operator.
time_reversal : sparse or dense square matrix
The unitary part of the time-reversal symmetry operator.
chiral : sparse or dense square matrix
The chiral symmetry operator.

3.7. kwant.physics – Physics-related algorithms 129


Kwant 1.3.1 documentation

projectors : an iterable of sparse or dense matrices


Projectors that block diagonalize the Hamiltonian in accordance with a con-
servation law.
Returns propagating : PropagatingModes
Contains the array of the wave functions of propagating modes, their mo-
menta, and their velocities. It can be used to identify the gauge in which the
scattering problem is solved.
stabilized : StabilizedModes
A basis of propagating and evanescent modes used by the solvers.

Notes

The propagating modes are sorted according to the longitudinal component of their k-vector, with
incoming modes having k sorted in descending order, and outgoing modes having k sorted in
ascending order. In simple cases where bands do not cross, this ordering corresponds to “lowest
modes first”. In general, however, it is necessary to examine the band structure – something this
function is not doing by design.
Propagating modes with the same momentum are orthogonalized. All the propagating modes are
normalized by current.
This function uses the most stable and efficient algorithm for calculating the mode decomposition
that the Kwant authors are aware about. Its details are to be published.

kwant.physics.selfenergy

kwant.physics.selfenergy(h_cell, h_hop, tol=1000000.0)


Compute the self-energy generated by the lead.
Parameters h_cell : numpy array, real or complex, shape (N,N) The unit cell Hamil-
tonian
of the lead unit cell.
h_hop : numpy array, real or complex, shape (N,M)
The hopping matrix from a lead cell to the one on which self-energy has to
be calculated (and any other hopping in the same direction).
tol : float
Numbers are considered zero when they are smaller than tol times the ma-
chine precision.
Returns Sigma : numpy array, real or complex, shape (M,M)
The computed self-energy. Note that even if h_cell and h_hop are both real,
Sigma will typically be complex. (More precisely, if there is a propagating
mode, Sigma will definitely be complex.)

Notes

For simplicity this function internally calculates the modes first. This may cause a small slowdown,
and can be improved if necessary.

130 Chapter 3. Core modules


Kwant 1.3.1 documentation

kwant.physics.two_terminal_shotnoise

kwant.physics.two_terminal_shotnoise(smatrix)
Compute the shot-noise in a two-terminal setup.
In a two terminal system the shot noise is given by tr((1 - t*t^dagger) * t*t^dagger).
Parameters smatrix : SMatrix instance
A two terminal scattering matrix.
Returns noise : float
Shot noise measured in noise quanta 2 e^3 |V| / pi hbar.

kwant.physics.PropagatingModes

class kwant.physics.PropagatingModes(wave_functions, velocities, momenta)


Bases: object
The calculated propagating modes of a lead.

Notes

The sort order of all the three arrays is identical. The first half of the modes have negative velocity,
the second half have positive velocity. The modes with negative velocity are ordered from larger
to lower momenta, the modes with positive velocity vice versa.
The first dimension of wave_functions corresponds to the orbitals of all the sites in a unit cell, the
second one to the number of the mode. Each mode is normalized to carry unit current. If several
modes have the same momentum and velocity, an arbitrary orthonormal basis in the subspace of
these modes is chosen.
If a conservation law is specified to block diagonalize the Hamiltonian to N blocks, then
block_nmodes[i] is the number of left or right moving propagating modes in conservation law block
i. The ordering of blocks is the same as the ordering of the projectors used to block diagonalize
the Hamiltonian.

Attributes

wave_functions (numpy array) The wave functions of the propagating modes.


momenta (numpy array) Momenta of the modes.
velocities (numpy array) Velocities of the modes.
block_nmodes: list Number of left or right moving propagating modes per conservation
of integers law block of the Hamiltonian.

Methods

kwant.physics.StabilizedModes

class kwant.physics.StabilizedModes(vecs, vecslmbdainv, nmodes, sqrt_hop=None)


Bases: object
Stabilized eigendecomposition of the translation operator.
Due to the lack of Hermiticity of the translation operator, its eigendecomposition is frequently
poorly conditioned. Solvers in Kwant use this stabilized decomposition of the propagating and
evanescent modes in the leads. If the hopping between the unit cells of an infinite system is
invertible, the translation eigenproblem is written in the basis psi_n, h_hop^+ * psi_(n+1),

3.7. kwant.physics – Physics-related algorithms 131


Kwant 1.3.1 documentation

with h_hop the hopping between unit cells. If h_hop is not invertible, and has the singular value
decomposition u s v^+, then the eigenproblem is written in the basis sqrt(s) v^+ psi_n, sqrt(s)
u^+ psi_(n+1). In this basis we calculate the eigenvectors of the propagating modes, and the
Schur vectors (an orthogonal basis) in the space of evanescent modes.
vecs and vecslmbdainv are the first and the second halves of the wave functions. The first nmodes
are eigenmodes moving in the negative direction (hence they are incoming into the system in Kwant
convention), the second nmodes are eigenmodes moving in the positive direction. The remaining
modes are the Schur vectors of the modes evanescent in the positive direction. Propagating modes
with the same eigenvalue are orthogonalized, and all the propagating modes are normalized to
carry unit current. Finally the sqrt_hop attribute is v sqrt(s).

Attributes

vecs (numpy array) Translation eigenvectors.


vecslmb- (numpy array) Translation eigenvectors divided by the corresponding
dainv eigenvalues.
nmodes (int) Number of left-moving (or right-moving) modes.
sqrt_hop (numpy array or None) Part of the SVD of h_hop, or None if the latter is
invertible.

Methods

selfenergy()
Compute the self-energy generated by lead modes.
Returns Sigma : numpy array, real or complex, shape (M,M)
The computed self-energy. Note that even if h_cell and h_hop are both real,
Sigma will typically be complex. (More precisely, if there is a propagating
mode, Sigma will definitely be complex.)

3.7.2 Symmetry

DiscreteSymmetry([projectors, ...]) A collection of discrete symmetries and conservation


laws.

kwant.physics.DiscreteSymmetry

class kwant.physics.DiscreteSymmetry(projectors=None, time_reversal=None, parti-


cle_hole=None, chiral=None)
Bases: object
A collection of discrete symmetries and conservation laws.
Parameters projectors : iterable of rectangular or square sparse matrices
Projectors that block-diagonalize the Hamiltonian.
time_reversal : square sparse matrix
The unitary part of the time-reversal symmetry operator.
particle_hole : square sparse matrix
The unitary part of the particle-hole symmetry operator.
chiral : square sparse matrix
The chiral symmetry operator.

132 Chapter 3. Core modules


Kwant 1.3.1 documentation

Notes

Whenever one or more discrete symmetry is declared in conjunction with a conservation law, the
symmetry operators and projectors must be declared in canonical form. This means that each
block of the Hamiltonian is transformed either to itself by a discrete symmetry or to a single other
block.
More formally, consider a discrete symmetry S. The symmetry projection that maps from block
i to block j of the Hamiltonian with projectors 𝑃𝑖 and 𝑃𝑗 is 𝑆𝑗𝑖 = 𝑃𝑗+ 𝑆𝑃𝑖 . If 𝑆𝑗𝑖 is nonzero, a
symmetry relation exists between blocks i and j. Canonical form means that for each j, the block
𝑆𝑗𝑖 is nonzero at most for one i, while all other blocks vanish.
If the operators are not in canonical form, they can be made so by further splitting the Hamiltonian
into smaller blocks, i.e. by adding more projectors.

Methods

validate(matrix)
Check if a matrix satisfies the discrete symmetries.
Parameters matrix : sparse or dense matrix
If rectangular, it is padded by zeros to be square.
Returns broken_symmetry : string or None
One of “Conservation law”, “Time reversal”, “Particle-hole”, “Chiral”: the
symmetry broken by the matrix. If the matrix breaks more than one sym-
metry, returns only the first failed check.

3.7. kwant.physics – Physics-related algorithms 133


Kwant 1.3.1 documentation

134 Chapter 3. Core modules


CHAPTER

FOUR

OTHER MODULES

The following modules provide functionality for special applications.

4.1 kwant.digest – Random-access random numbers

Random-access random numbers


This module provides routines that given some input compute a “random” output that depends on the
input in a (cryptographically) intractable way.
This turns out to be very useful when one needs to map some irregular objects to random numbers in a
deterministic and reproducible way.
Internally, the md5 hash algorithm is used. The randomness thus generated is good enough to pass the
“dieharder” battery of tests: see the function test of this module.
kwant.digest.uniform(input, salt=’‘)
md5-hash input and salt and map the result to the [0,1) interval.
input must be some object that supports the buffer protocol (i.e. a string or a numpy/tinyarray
array). salt must be a string or a bytes object.
kwant.digest.gauss(input, salt=’‘)
md5-hash input and salt and return the result as a standard normal distributed variable.
input must be some object that supports the buffer protocol (i.e. a string or a numpy/tinyarray
array). salt must be a string or a bytes object.
kwant.digest.test(n=20000)
Test the generator with the dieharder suite generating n**2 samples.
Executing this function may take a very long time.

4.2 kwant.rmt – Random matrix theory Hamiltonians

kwant.rmt.gaussian(n, sym=’A’, v=1.0, rng=None)


Make a n * n random Gaussian Hamiltonian.
Parameters n : int
Size of the Hamiltonian. It should be even for all the classes except A, D,
and AI, and in class CII it should be a multiple of 4.
sym : one of ‘A’, ‘AI’, ‘AII’, ‘AIII’, ‘BDI’, ‘CII’, ‘D’, ‘DIII’, ‘C’, ‘CI’
Altland-Zirnbauer symmetry class of the Hamiltonian.
v : float

135
Kwant 1.3.1 documentation

Variance every degree of freedom of the Hamiltonian. The probaility distri-


bution of the Hamiltonian is P(H) = exp(-Tr(H^2) / 2 v^2).
rng: int or rng (optional)
Seed or random number generator. If no ‘rng’ is provided the random number
generator from numpy will be used.
Returns h : numpy.ndarray
A numpy array drawn from a corresponding Gaussian ensemble.

Notes

The representations of symmetry operators are chosen according to Phys. Rev. B 85, 165409.
Matrix indices are grouped first according to orbital number, then sigma-index, then tau-index.
Chiral (sublattice) symmetry C always reads: H = -tau_z H tau_z.
Time reversal symmetry T reads: AI: H = H^*. BDI: H = tau_z H^* tau_z. CI: H = tau_x
H^* tau_x. AII, CII: H = sigma_y H^* sigma_y. DIII: H = tau_y H^* tau_y.
Particle-hole symmetry reads: C, CI: H = -tau_y H^* tau_y. CII: H = -tau_z sigma_y H^*
tau_z sigma_y. D, BDI: H = -H^*. DIII: H = -tau_x H^* tau_x.
This implementation should be sufficiently efficient for large matrices, since it avoids any matrix
multiplication.
kwant.rmt.circular(n, sym=’A’, charge=None, rng=None)
Make a n * n matrix belonging to a symmetric circular ensemble.
Parameters n : int
Size of the matrix. It should be even for the classes C, CI, CII, AII, DIII
(either T^2 = -1 or P^2 = -1).
sym : one of ‘A’, ‘AI’, ‘AII’, ‘AIII’, ‘BDI’, ‘CII’, ‘D’, ‘DIII’, ‘C’, ‘CI’
Altland-Zirnbauer symmetry class of the matrix.
charge : int or None
Topological invariant of the matrix. Should be one of 1, -1 in symmetry
classes D and DIII, should be from 0 to n in classes AIII and BDI, and
should be from 0 to n / 2 in class CII. If charge is None, it is drawn from a
binomial distribution with p = 1 / 2.
rng: int or rng (optional)
Seed or random number generator. If no ‘rng’ is passed, the random number
generator provided by numpy will be used.
Returns s : numpy.ndarray
A numpy array drawn from a corresponding circular ensemble.

Notes

The representations of symmetry operators are chosen according to Phys. Rev. B 85, 165409,
except class D.
Matrix indices are grouped first according to channel number, then sigma-index.
Chiral (sublattice) symmetry C always reads: s = s^+.
Time reversal symmetry T reads: AI, BDI: r = r^T. CI: r = -sigma_y r^T sigma_y. AII,
DIII: r = -r^T. CII: r = sigma_y r^T sigma_y.

136 Chapter 4. Other modules


Kwant 1.3.1 documentation

Particle-hole symmetry reads: CI: r = -sigma_y r^* sigma_y C, CII: r = sigma_y r^*
sigma_y D, BDI: r = r^*. DIII: -r = r^*.
This function uses QR decomposition to probe symmetric compact groups, as detailed in
arXiv:math-ph/0609050. For a reason as yet unknown, scipy implementation of QR decompo-
sition also works for symplectic matrices.

4.3 kwant.kpm – Kernel Polynomial Method

class kwant.kpm.SpectralDensity(hamiltonian, params=None, operator=None,


num_vectors=10, num_moments=None, en-
ergy_resolution=None, vector_factory=None,
bounds=None, eps=0.05, rng=None)
Bases: object
Calculate the spectral density of an operator.
This class makes use of the kernel polynomial method (KPM), presented in [R1], to obtain the
spectral density 𝜌𝐴 (𝑒), as a function of the energy 𝑒, of some operator 𝐴 that acts on a kwant
system or a Hamiltonian. In general

𝜌𝐴 (𝑒) = 𝜌(𝑒)𝐴(𝑒),
𝐷−1
where 𝜌(𝑒) = ∑𝑘=0 𝛿(𝐸 − 𝐸𝑘 ) is the density of states, and 𝐴(𝑒) is the expectation value of 𝐴 for
all the eigenstates with energy 𝑒.
Parameters hamiltonian : FiniteSystem or matrix Hamiltonian
If a system is passed, it should contain no leads.
params : dict, optional
Additional parameters to pass to the Hamiltonian and operator.
operator : operator, dense matrix, or sparse matrix, optional
Operator for which the spectral density will be evaluated. If it is callable,
the densities at each energy will have the dimension of the result of oper-
ator(bra, ket). If it has a dot method, such as numpy.ndarray and scipy.
sparse.matrices, the densities will be scalars. If no operator is provided,
the density of states is calculated with a faster algorithm.
num_vectors : positive int, default: 10
Number of random vectors for the KPM method.
num_moments : positive int, default: 100
Number of moments, order of the KPM expansion. Mutually exclusive with
‘energy_resolution’.
energy_resolution : positive float, optional
The resolution in energy of the KPM approximation to the spectral density.
Mutually exclusive with ‘num_moments’.
vector_factory : function, optional
The user defined function f(n) generates random vectors of length n that will
be used in the algorithm. If not provided, random phase vectors are used.
The default random vectors are optimal for most cases, see the discussions
in [R1] and [R2].
bounds : pair of floats, optional
Lower and upper bounds for the eigenvalue spectrum of the system. If not
provided, they are computed.

4.3. kwant.kpm – Kernel Polynomial Method 137


Kwant 1.3.1 documentation

eps : positive float, default: 0.05


Parameter to ensure that the rescaled spectrum lies in the interval (-1, 1);
required for stability.
rng : seed, or random number generator, optional
Random number generator used by vector_factory. If not provided,
numpy’s rng will be used; if it is an Integer, it will be used to seed numpy’s
rng, and if it is a random number generator, this is the one used.

Notes

When passing an operator defined in operator, the result of operator(bra, ket) depends on
the attribute sum of such operator. If sum=True, densities will be scalars, that is, total densities
of the system. If sum=False the densities will be arrays of the length of the system, that is, local
densities.

Examples

In the following example, we will obtain the density of states of a graphene sheet, defined as a
honeycomb lattice with first nearest neighbors coupling.
We start by importing kwant and defining a FiniteSystem,

>>> import kwant


...
>>> def circle(pos):
... x, y = pos
... return x**2 + y**2 < 100
...
>>> lat = kwant.lattice.honeycomb()
>>> syst = kwant.Builder()
>>> syst[lat.shape(circle, (0, 0))] = 0
>>> syst[lat.neighbors()] = 1

and after finalizing the system, create an instance of SpectralDensity

>>> fsyst = syst.finalized()


>>> rho = kwant.kpm.SpectralDensity(fsyst)

The energies and densities can be accessed with

>>> energies, densities = rho()

or

>>> energies, densities = rho.energies, rho.densities

Attributes

ener- (array of floats) Array of sampling points with length 2 * num_moments in the range
gies of the spectrum.
densi- (array of floats) Spectral density of the operator evaluated at the energies.
ties
__call__(energy=None)
Return the spectral density evaluated at energy.

138 Chapter 4. Other modules


Kwant 1.3.1 documentation

Parameters energy : float or sequence of float, optional


Returns float, if energy is float, array of float if energy
is a sequence, a tuple (energies, densities) if
energy was not provided.

Notes

If energy is not provided, then the densities are obtained by Fast Fourier Transform of the
Chebyshev moments.
add_moments(num_moments=None, *, energy_resolution=None)
Increase the number of Chebyshev moments.
Parameters num_moments: positive int
The number of Chebyshev moments to add. Mutually exclusive with ‘en-
ergy_resolution’.
energy_resolution: positive float, optional
Features wider than this resolution are visible in the spectral density. Mu-
tually exclusive with ‘num_moments’.
add_vectors(num_vectors)
Increase the number of random vectors.
Parameters num_vectors: positive int
The number of random vectors to add.
integrate(distribution_function=None)
Returns the total spectral density.
Returns the integral over the whole spectrum with an optional distribution function.
distribution_function should be able to take arrays as input. Defined using Gauss-
Chebyshev integration.

4.4 kwant.continuum – Tools for continuum systems

4.4.1 Discretizer

discretize(hamiltonian[, coords, ...]) Construct a tight-binding model from a continuum


Hamiltonian.
discretize_symbolic(hamiltonian[, coords, ...]) Discretize a continuous Hamiltonian into a tight-
binding representation.
build_discretized(tb_hamiltonian, coords, *) Create a template builder from a symbolic tight-
binding Hamiltonian.

kwant.continuum.discretize

kwant.continuum.discretize(hamiltonian, coords=None, *, grid_spacing=1, locals=None)


Construct a tight-binding model from a continuum Hamiltonian.
If necessary, the given Hamiltonian is sympified using kwant.continuum.sympify. It is then
discretized symbolically and turned into a Builder instance that may be used with fill.
This is a convenience function that is equivalent to first calling discretize_symbolic and feeding
its result into build_discretized.

4.4. kwant.continuum – Tools for continuum systems 139


Kwant 1.3.1 documentation

Warning: This function uses eval (because it calls sympy.sympify), and thus should not be
used on unsanitized input.

Parameters hamiltonian : str or SymPy expression


Symbolic representation of a continuous Hamiltonian. It is converted to a
SymPy expression using kwant.continuum.sympify.
coords : sequence of strings, or None (default)
The coordinates for which momentum operators will be treated as differential
operators. May contain only “x”, “y” and “z” and must be sorted. If not
provided, coords will be obtained from the input Hamiltonian by reading the
present coordinates and momentum operators.
grid_spacing : int or float, default: 1
Spacing of the (quadratic or cubic) discretization grid.
locals : dict or None (default)
Additional namespace entries for sympify. May be used to simplify in-
put of matrices or modify input before proceeding further. For example:
locals={'k': 'k_x + I * k_y'} or locals={'sigma_plus': [[0, 2],
[0, 0]]}.
Returns model : Builder
The translationally symmetric builder that corresponds to the provided
Hamiltonian. This builder instance belongs to a subclass of the standard
builder that may be printed to obtain the source code of the value functions.
It also holds the discretization lattice (a Monatomic instance with lattice
constant grid_spacing) in the lattice attribute.

kwant.continuum.discretize_symbolic

kwant.continuum.discretize_symbolic(hamiltonian, coords=None, *, locals=None)


Discretize a continuous Hamiltonian into a tight-binding representation.
If necessary, the given Hamiltonian is sympified using kwant.continuum.sympify. It is then
discretized symbolically.
The two return values may be used directly as the first two arguments for build_discretized.

Warning: This function uses eval (because it calls sympy.sympify), and thus should not be
used on unsanitized input.

Parameters hamiltonian : str or SymPy expression


Symbolic representation of a continuous Hamiltonian. It is converted to a
SymPy expression using kwant.continuum.sympify.
coords : sequence of strings, or None (default)
The coordinates for which momentum operators will be treated as differential
operators. May contain only “x”, “y” and “z” and must be sorted. If not
provided, coords will be obtained from the input Hamiltonian by reading the
present coordinates and momentum operators.
locals : dict or None (default)

140 Chapter 4. Other modules


Kwant 1.3.1 documentation

Additional namespace entries for sympify. May be used to simplify in-


put of matrices or modify input before proceeding further. For example:
locals={'k': 'k_x + I * k_y'} or locals={'sigma_plus': [[0, 2],
[0, 0]]}.
Returns tb_hamiltonian : dict
Keys are tuples of integers; the offsets of the hoppings ((0, 0, 0) for the
onsite). Values are symbolic expressions for the hoppings/onsite.
coords : list of strings
The coordinates that have been discretized.

kwant.continuum.build_discretized

kwant.continuum.build_discretized(tb_hamiltonian, coords, *, grid_spacing=1, locals=None)


Create a template builder from a symbolic tight-binding Hamiltonian.
The provided symbolic tight-binding Hamiltonian is put on a (hyper) square lattice and turned
into Python functions. These functions are used to create a Builder instance that may be used
with fill to construct a system of a desired shape.
The return values of discretize_symbolic may be used directly for the first two arguments of
this function.

Warning: This function uses eval (because it calls sympy.sympify), and thus should not be
used on unsanitized input.

Parameters tb_hamiltonian : dict


Keys must be the offsets of the hoppings, represented by tuples of integers ((0,
0, 0) for onsite). Values must be symbolic expressions for the hoppings/onsite
or expressions that can by sympified with kwant.continuum.sympify.
coords : sequence of strings
The coordinates for which momentum operators will be treated as differential
operators. May contain only “x”, “y” and “z” and must be sorted.
grid_spacing : int or float, default: 1
Spacing of the (quadratic or cubic) discretization grid.
locals : dict, defaults to empty
Additional namespace entries for the calls of sympify on the values of
tb_hamiltonian. May be used to simplify input of matrices or modify in-
put before proceeding further. For example: locals={'k': 'k_x + I *
k_y'} or locals={'sigma_plus': [[0, 2], [0, 0]]}.
Returns model : Builder
The translationally symmetric builder that corresponds to the provided
Hamiltonian. This builder instance belongs to a subclass of the standard
builder that may be printed to obtain the source code of the value functions.
It also holds the discretization lattice (a Monatomic instance with lattice
constant grid_spacing) in the lattice attribute.

4.4.2 Symbolic helpers

4.4. kwant.continuum – Tools for continuum systems 141


Kwant 1.3.1 documentation

sympify(expr[, locals]) Sympify object using special rules for Hamiltonians.


lambdify(expr[, locals]) Return a callable object for computing a continuum
Hamiltonian.

kwant.continuum.sympify

kwant.continuum.sympify(expr, locals=None)
Sympify object using special rules for Hamiltonians.
If ‘expr‘ is already a type that SymPy understands, it will do nothing but return that value. Note
that locals will not be used in this situation.
Otherwise, it is sympified by sympy.sympify with a modified namespace such that
•the position operators “x”, “y” or “z” and momentum operators “k_x”, “k_y”, and “k_z” do
not commute,
•all single-letter identifiers and names of Greek letters (e.g. “pi” or “gamma”) are treated as
symbols,
•“kron” corresponds to sympy.physics.quantum.TensorProduct, and “identity” to sympy.
eye,
•“sigma_0”, “sigma_x”, “sigma_y”, “sigma_z” are the Pauli matrices.
In addition, Python list literals are interpreted as SymPy matrices.

Warning: This function uses eval (because it calls sympy.sympify), and thus should not be
used on unsanitized input.

Parameters expr : str or SymPy expression


Expression to be converted to a SymPy object.
locals : dict or None (default)
Additional entries for the namespace under which expr is sympified. The
keys must be valid Python variable names. The values may be strings, since
they are all are sent through continuum.sympify themselves before use. (Note
that this is a difference to how sympy.sympify behaves.)

Note: When a value of locals is already a SymPy object, it is used as-is, and
the caller is responsible to set the commutativity of its symbols appropriately.
This possible source of errors is demonstrated in the last example below.

Returns result : SymPy object

Examples

>>> sympify('k_x * A(x) * k_x + V(x)')


k_x*A(x)*k_x + V(x) # as valid sympy object

>>> sympify('k_x**2 + V', locals={'V': 'V_0 + V(x)'})


k_x**2 + V(x) + V_0

142 Chapter 4. Other modules


Kwant 1.3.1 documentation

>>> ns = {'sigma_plus': [[0, 2], [0, 0]]}


>>> sympify('k_x**2 * sigma_plus', ns)
Matrix([
[0, 2*k_x**2],
[0, 0]])

>>> sympify('k_x * A(c) * k_x', locals={'c': 'x'})


k_x*A(x)*k_x
>>> sympify('k_x * A(c) * k_x', locals={'c': sympy.Symbol('x')})
A(x)*k_x**2

kwant.continuum.lambdify

kwant.continuum.lambdify(expr, locals=None)
Return a callable object for computing a continuum Hamiltonian.

Warning: This function uses eval (because it calls sympy.sympify), and thus should not be
used on unsanitized input.

If necessary, the given expression is sympified using kwant.continuum.sympify. It is then con-


verted into a callable object.
Parameters expr : str or SymPy expression
Expression to be converted into a callable object
locals : dict or None (default)
Additional definitions for sympify.

4.5 kwant.wraparound – Wrapping around translational symmetries

wraparound(builder[, keep, coordinate_names]) Replace translational symmetries by momentum pa-


rameters.
plot_2d_bands(syst[, k_x, k_y, params, ...]) Plot 2D band structure of a wrapped around system.

4.5.1 kwant.wraparound.wraparound

kwant.wraparound.wraparound(builder, keep=None, *, coordinate_names=(‘x’, ‘y’, ‘z’))


Replace translational symmetries by momentum parameters.
A new Builder instance is returned. By default, each symmetry is replaced by one scalar momentum
parameter that is appended to the already existing arguments of the system. Optionally, one
symmetry may be kept by using the keep argument. The momentum parameters will have names
like ‘k_n’ where the ‘n’ are specified by ‘coordinate_names’.
Parameters builder : Builder
keep : int, optional
Which (if any) translational symmetry to keep.
coordinate_names : sequence of strings, default: (‘x’, ‘y’, ‘z’)
The names of the coordinates along the symmetry directions of ‘builder’.

4.5. kwant.wraparound – Wrapping around translational symmetries 143


Kwant 1.3.1 documentation

Notes

Wraparound is stop-gap functionality until Kwant 2.x which will include support for higher-
dimension translational symmetry in the low-level system format. It will be deprecated in the
2.0 release of Kwant.

4.5.2 kwant.wraparound.plot_2d_bands

kwant.wraparound.plot_2d_bands(syst, k_x=31, k_y=31, params=None,


mask_brillouin_zone=False, extend_bbox=0, file=None,
show=True, dpi=None, fig_size=None, ax=None)
Plot 2D band structure of a wrapped around system.
This function is primarily useful for systems that have translational symmetry vectors that are non-
orthogonal (e.g. graphene). This function will properly plot the band structure in an orthonormal
basis in k-space, as opposed to in the basis of reciprocal lattice vectors (which would produce a
“skewed” Brillouin zone).
If your system has orthogonal lattice vectors, you are probably better off using kwant.plotter.
spectrum.
Parameters syst : kwant.system.FiniteSystem
A 2D system that was finalized from a Builder produced by kwant.
wraparound.wraparound. Note that this must be a finite system; so kwant.
wraparound.wraparound should have been called with keep=None.
k_x, k_y : int or sequence of float, default: 31
Either a number of sampling points, or a sequence of points at which the
band structure is to be evaluated, in units of inverse length.
params : dict, optional
Dictionary of parameter names and their values, not including the momen-
tum parameters.
mask_brillouin_zone : bool, default: False
If True, then the band structure will only be plotted over the first Brillouin
zone. By default the band structure is plotted over a rectangular bounding
box that contains the Brillouin zone.
extend_bbox : float, default: 0
Amount by which to extend the region over which the band structure is
plotted, expressed as a proportion of the Brillouin zone bounding box length.
i.e. extend_bbox=0.1 will extend the region by 10% (in all directions).
file : string or file object, optional
The output file. If None, output will be shown instead.
show : bool, default: False
Whether matplotlib.pyplot.show() is to be called, and the output is to
be shown immediately. Defaults to True.
dpi : float, optional
Number of pixels per inch. If not set the matplotlib default is used.
fig_size : tuple, optional
Figure size (width, height) in inches. If not set, the default matplotlib value
is used.
ax : matplotlib.axes.Axes instance, optional

144 Chapter 4. Other modules


Kwant 1.3.1 documentation

If ax is not None, no new figure is created, but the plot is done within the
existing Axes ax. in this case, file, show, dpi and fig_size are ignored.
Returns fig : matplotlib figure
A figure with the output if ax is not set, else None.
See also:
kwant.plotter.spectrum

Notes

This function produces plots where the units of momentum are inverse length. This is contrary to
kwant.plotter.bands, where the units of momentum are inverse lattice constant.
If the lattice vectors for the symmetry of syst are not orthogonal, then part of the plotted band
structure will be outside the first Brillouin zone (inside the bounding box of the brillouin zone).
Setting mask_brillouin_zone=True will cause the plot to be truncated outside of the first Brillouin
zone.

4.5. kwant.wraparound – Wrapping around translational symmetries 145


Kwant 1.3.1 documentation

146 Chapter 4. Other modules


CHAPTER

FIVE

MODULES MAINLY FOR INTERNAL USE

The following modules contain functionality that is most often used only internally by Kwant itself or
by advanced users.

5.1 kwant.system – Low-level interface of systems

Low-level interface of systems


This module is the binding link between constructing tight-binding systems and doing calculations with
these systems. It defines the interface which any problem-solving algorithm should be able to access,
independently on how the system was constructed. This is achieved by using python abstract base classes
(ABC) – classes, which help to ensure that any derived classes implement the necessary interface.
Any system which is provided to a solver should be derived from the appropriate class in this module,
and every solver can assume that its input corresponds to the interface defined here.

System Abstract general low-level system.


InfiniteSystem Abstract infinite low-level system.
FiniteSystem Abstract finite low-level system, possibly with leads.
PrecalculatedLead([modes, selfenergy]) A general lead defined by its self energy.

5.1.1 kwant.system.System

class kwant.system.System
Bases: object
Abstract general low-level system.

Notes

The sites of the system are indexed by integers ranging from 0 to self.graph.num_nodes - 1.
Optionally, a class derived from System can provide a method pos which is assumed to return the
real-space position of a site given its index.
Due to the ordering semantics of sequences, and the fact that a given first_site can only appear
at most once in site_ranges, site_ranges is ordered according to first_site.
Consecutive elements in site_ranges are not required to have different numbers of orbitals.

147
Kwant 1.3.1 documentation

Attributes

graph (kwant.graph.CGraph) The system graph.


site_ranges
(None or sorted sequence of triples of integers) If provided, encodes ranges of sites that
have the same number of orbitals. Each triple consists of (first_site, norbs,
orb_offset): the first site in the range, the number of orbitals on each site in the
range, and the offset of the first orbital of the first site in the range. In addition, the
final triple should have the form (len(graph.num_nodes), 0, tot_norbs) where
tot_norbs is the total number of orbitals in the system.

Methods

discrete_symmetry(args, *, params=None)
Return the discrete symmetry of the system.
hamiltonian(i, j, *args, params=None)
Return the hamiltonian matrix element for sites i and j.
If i == j, return the on-site Hamiltonian of site i.
if i != j, return the hopping between site i and j.
Hamiltonians may depend (optionally) on positional and keyword arguments
hamiltonian_submatrix(self, args=(), to_sites=None, from_sites=None, sparse=False, re-
turn_norb=False, *, params=None)
Return a submatrix of the system Hamiltonian.
Parameters args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
to_sites : sequence of sites or None (default)
from_sites : sequence of sites or None (default)
sparse : bool
Whether to return a sparse or a dense matrix. Defaults to False.
return_norb : bool
Whether to return arrays of numbers of orbitals. Defaults to False.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns hamiltonian_part : numpy.ndarray or scipy.sparse.coo_matrix
Submatrix of Hamiltonian of the system.
to_norb : array of integers
Numbers of orbitals on each site in to_sites. Only returned when
return_norb is true.
from_norb : array of integers
Numbers of orbitals on each site in from_sites. Only returned when
return_norb is true.

148 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

Notes

The returned submatrix contains all the Hamiltonian matrix elements from from_sites to
to_sites. The default for from_sites and to_sites is None which means to use all sites of
the system in the order in which they appear.

5.1.2 kwant.system.InfiniteSystem

class kwant.system.InfiniteSystem
Bases: kwant.system.System
Abstract infinite low-level system.
An infinite system consists of an infinite series of identical cells. Adjacent cells are connected by
identical inter-cell hoppings.

Notes

The system graph of an infinite systems contains a single cell, as well as the part of the previous
cell which is connected to it. The first cell_size sites form one complete single cell. The remaining
N sites of the graph (N equals graph.num_nodes - cell_size) belong to the previous cell. They
are included so that hoppings between cells can be represented. The N sites of the previous cell
correspond to the first N sites of the fully included cell. When an InfiniteSystem is used as a
lead, N acts also as the number of interface sites to which it must be connected.
The drawing shows three cells of an infinite system. Each cell consists of three sites. Numbers
denote sites which are included into the system graph. Stars denote sites which are not included.
Hoppings are included in the graph if and only if they occur between two sites which are part of
the graph:

* 2 *
... | | | ...
* 0 3
|/|/|
*-1-4

<-- order of cells

The numbering of sites in the drawing is one of the two valid ones for that infinite system. The
other scheme has the numbers of site 0 and 1 exchanged, as well as of site 3 and 4.

Attributes

cell_size (integer) The number of sites in a single cell of the system.

Methods

cell_hamiltonian(args=(), sparse=False, *, params=None)


Hamiltonian of a single cell of the infinite system.
discrete_symmetry(args, *, params=None)
Return the discrete symmetry of the system.
hamiltonian(i, j, *args, params=None)
Return the hamiltonian matrix element for sites i and j.
If i == j, return the on-site Hamiltonian of site i.

5.1. kwant.system – Low-level interface of systems 149


Kwant 1.3.1 documentation

if i != j, return the hopping between site i and j.


Hamiltonians may depend (optionally) on positional and keyword arguments
hamiltonian_submatrix(self, args=(), to_sites=None, from_sites=None, sparse=False, re-
turn_norb=False, *, params=None)
Return a submatrix of the system Hamiltonian.
Parameters args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
to_sites : sequence of sites or None (default)
from_sites : sequence of sites or None (default)
sparse : bool
Whether to return a sparse or a dense matrix. Defaults to False.
return_norb : bool
Whether to return arrays of numbers of orbitals. Defaults to False.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns hamiltonian_part : numpy.ndarray or scipy.sparse.coo_matrix
Submatrix of Hamiltonian of the system.
to_norb : array of integers
Numbers of orbitals on each site in to_sites. Only returned when
return_norb is true.
from_norb : array of integers
Numbers of orbitals on each site in from_sites. Only returned when
return_norb is true.

Notes

The returned submatrix contains all the Hamiltonian matrix elements from from_sites to
to_sites. The default for from_sites and to_sites is None which means to use all sites of
the system in the order in which they appear.
inter_cell_hopping(args=(), sparse=False, *, params=None)
Hopping Hamiltonian between two cells of the infinite system.
modes(energy=0, args=(), *, params=None)
Return mode decomposition of the lead
See documentation of PropagatingModes and StabilizedModes for the return format details.
selfenergy(energy=0, args=(), *, params=None)
Return self-energy of a lead.
The returned matrix has the shape (s, s), where s is sum(len(self.hamiltonian(i, i))
for i in range(self.graph.num_nodes - self.cell_size)).

150 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

5.1.3 kwant.system.FiniteSystem

class kwant.system.FiniteSystem
Bases: kwant.system.System
Abstract finite low-level system, possibly with leads.

Notes

The length of leads must be equal to the length of lead_interfaces.


For lead n, the method leads[n].selfenergy must return a square matrix whose size is sum(len(self.
hamiltonian(site, site)) for site in self.lead_interfaces[n]). The output of leads[n].
modes has to be a tuple of PropagatingModes, StabilizedModes.
Often, the elements of leads will be instances of InfiniteSystem. If this is the case for lead n, the
sites lead_interfaces[n] match the first len(lead_interfaces[n]) sites of the InfiniteSystem.

Attributes

leads (sequence of leads) Each lead has to provide a method selfenergy that has the same
signature as InfiniteSystem.selfenergy (without the self parameter). It may
also provide modes that has the same signature as InfiniteSystem.modes (without
the self parameter).
lead_interfaces
(sequence of sequences of integers) Each sub-sequence contains the indices of the
system sites to which the lead is connected.

Methods

discrete_symmetry(args, *, params=None)
Return the discrete symmetry of the system.
hamiltonian(i, j, *args, params=None)
Return the hamiltonian matrix element for sites i and j.
If i == j, return the on-site Hamiltonian of site i.
if i != j, return the hopping between site i and j.
Hamiltonians may depend (optionally) on positional and keyword arguments
hamiltonian_submatrix(self, args=(), to_sites=None, from_sites=None, sparse=False, re-
turn_norb=False, *, params=None)
Return a submatrix of the system Hamiltonian.
Parameters args : tuple, defaults to empty
Positional arguments to pass to the hamiltonian method. Mutually exclu-
sive with ‘params’.
to_sites : sequence of sites or None (default)
from_sites : sequence of sites or None (default)
sparse : bool
Whether to return a sparse or a dense matrix. Defaults to False.
return_norb : bool
Whether to return arrays of numbers of orbitals. Defaults to False.
params : dict, optional

5.1. kwant.system – Low-level interface of systems 151


Kwant 1.3.1 documentation

Dictionary of parameter names and their values. Mutually exclusive with


‘args’.
Returns hamiltonian_part : numpy.ndarray or scipy.sparse.coo_matrix
Submatrix of Hamiltonian of the system.
to_norb : array of integers
Numbers of orbitals on each site in to_sites. Only returned when
return_norb is true.
from_norb : array of integers
Numbers of orbitals on each site in from_sites. Only returned when
return_norb is true.

Notes

The returned submatrix contains all the Hamiltonian matrix elements from from_sites to
to_sites. The default for from_sites and to_sites is None which means to use all sites of
the system in the order in which they appear.
precalculate(energy=0, args=(), leads=None, what=’modes’, *, params=None)
Precalculate modes or self-energies in the leads.
Construct a copy of the system, with the lead modes precalculated, which may significantly
speed up calculations where only the system is changing.
Parameters energy : float
Energy at which the modes or self-energies have to be evaluated.
args : sequence
Additional parameters required for calculating the Hamiltionians. Mutually
exclusive with ‘params’.
leads : sequence of integers or None
Numbers of the leads to be precalculated. If None, all are precalculated.
what : ‘modes’, ‘selfenergy’, ‘all’
The quantitity to precompute. ‘all’ will compute both modes and self-
energies. Defaults to ‘modes’.
params : dict, optional
Dictionary of parameter names and their values. Mutually exclusive with
‘args’.
Returns syst : FiniteSystem
A copy of the original system with some leads precalculated.

Notes

If the leads are precalculated at certain energy or args values, they might give wrong results
if used to solve the system with different parameter values. Use this function with caution.

152 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

5.1.4 kwant.system.PrecalculatedLead

class kwant.system.PrecalculatedLead(modes=None, selfenergy=None)


Bases: object
A general lead defined by its self energy.
Parameters modes : (kwant.physics.PropagatingModes,
kwant.physics.StabilizedModes)
Modes of the lead.
selfenergy : numpy array
Lead self-energy.

Notes

At least one of modes and selfenergy must be provided.

Methods

modes(energy=0, args=(), *, params=None)


selfenergy(energy=0, args=(), *, params=None)

5.2 kwant.graph – Low-level, efficient directed graphs

Graphs, as handled by this module, consist of nodes (numbered by integers, usually ≥ 0). Pairs of nodes
can be connected by edges (numbered by integers ≥ 0). An edge is described by a pair (tail, head) of
node numbers and is always directed.
The basic workflow is to
1. create an object of type Graph,
2. add edges to it using the methods add_edge and add_edges,
3. create a compressed copy of the graph using the method compressed,
4. and use the thus created object for efficient queries.
Example:

>>> import kwant


>>> g = kwant.graph.Graph()
>>> g.add_edge(0, 1)
0
>>> g.add_edge(0, 2)
1
>>> g = g.compressed()
>>> list(g.out_neighbors(0))
[1, 2]

Node numbers can be assigned freely, but if they are not consecutive integers starting with zero, storage
space is wasted in the compressed graph. Negative node numbers are special and can be allowed optionally
(see further).
Whenever a method returns multiple edges or nodes (via an iterator), they appear in the order in which
the edges associated with them were added to the graph during construction.

5.2. kwant.graph – Low-level, efficient directed graphs 153


Kwant 1.3.1 documentation

Edge IDs are non-negative integers which identify edges unambiguously. They are assigned automatically
when the graph is compressed. The edge IDs of edges with the same tail will occupy a dense interval of
integers. The IDs of edges sharing the same tail will be assigned from lowest to highest in the order in
which these edges had been added.
The method Graph.compressed takes a parameter which determines whether the graph will be one-way
(the default) or two-way. One-way graphs can be queried for the existence of an edge and provide the
nodes to which a node points (=outgoing neighbors). In addition, two-way graphs can be queried for
the nodes which point to a node (=incoming neighbors).
Another parameter of Graph.compressed, edge_nr_translation, determines whether it will be possible
to use the method edge_id of the compressed graph. This method returns the edge ID of an edge given
the edge number that was returned when an edge was added.
Negative node numbers can be allowed for a Graph (parameter allow_negative_nodes of the constructor).
Edges with negative nodes are considered to be dangling: negative nodes can be neighbors of other nodes,
but cannot be queried directly for neighbors. Consequently, “doubly-dangling” edges which connect two
negative nodes do not make sense and are never allowed. The range of values used for the negative node
numbers does not influence the required storage space in any way.
Compressed graphs have the read-only attributes num_nodes and num_edges.

5.2.1 Graph types

Graph An uncompressed graph.


CGraph A compressed graph which can be efficiently queried
for the existence of edges and outgoing neighbors.

kwant.graph.Graph

class kwant.graph.Graph
Bases: object
An uncompressed graph. Used to make compressed graphs. (See CGraph.)

Methods

add_edge()
Add the directed edge (tail, head) to the graph.
Parameters tail : integer
head : integer
Returns edge_nr : integer
The sequential number of the edge. This number can be used to query for
the edge ID of an edge in the compressed graph.
Raises ValueError
If a negative node is added when this has not been allowed explicitly or if an
edge is doubly-dangling.
add_edges()
Add multiple edges in one pass.
Parameters edges : iterable of 2-sequences of integers
The parameter edges must be an iterable of elements which describe the
edges to be added. For each edge-element, edge[0] and edge[1] must give,
respectively, the tail and the head. Valid edges are, for example, a list of

154 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

2-integer-tuples, or an numpy.ndarray of integers with a shape (n, 2). The


latter case is optimized.
Returns first_edge_nr : integer
The sequential number of the first of the added edges. The numbers of
the other added edges are consecutive integers following the number of the
first. Edge numbers can be used to query for the edge ID of an edge in the
compressed graph.
compressed()
Build a CGraph from this graph.
Parameters twoway : boolean (default: False)
If set, it will be possible to query the compressed graph for incoming neigh-
bors.
edge_nr_translation : boolean (default: False)
If set, it will be possible to call the method edge_id.
allow_lost_edges : boolean (default: False)
If set, negative tails are accepted even with one-way compression.
Raises ValueError
When negative tails occur while twoway and allow_lost_edges are both false.

Notes

In a one-way compressed graph, an edge with a negative tail is present only minimally: it
is only possible to query the head of such an edge, given the edge ID. This is why one-
way compression of a graph with a negative tail leads to a ValueError being raised, unless
allow_lost_edges is true.
reserve()
Reserve space for edges.
Parameters capacity : integer
Number of edges for which to reserve space.

Notes

It is not necessary to call this method, but using it can speed up the creation of graphs.
write_dot()
Write a representation of the graph in dot format to file.
That resulting file can be visualized with dot(1) or neato(1) form the graphviz package.

Attributes

num_nodes

kwant.graph.CGraph

class kwant.graph.CGraph
Bases: object

5.2. kwant.graph – Low-level, efficient directed graphs 155


Kwant 1.3.1 documentation

A compressed graph which can be efficiently queried for the existence of edges and outgoing neigh-
bors.
Objects of this class do not initialize the members themselves, but expect that they hold usable
values. A good way to create them is by compressing a Graph.
Iterating over a graph yields a sequence of (tail, head) pairs of all edges. The number of an edge in
this sequence equals its edge ID. The built-in function enumerate can thus be used to easily iterate
over all edges along with their edge IDs.

Methods

all_edge_ids()
Return an iterator over all edge IDs of edges with a given tail and head.
Parameters tail : integer
head : integer
Returns edge_id : integer
Raises NodeDoesNotExist
EdgeDoesNotExistError
DisabledFeatureError
If tail is negative and the graph is not two-way compressed.
edge_id()
Return the edge ID of an edge given its sequential number.
Parameters edge_nr : integer
Returns edge_id : integer
Raises DisabledFeatureError
If edge_nr_translation was not enabled during graph compression.
EdgeDoesNotExistError
first_edge_id()
Return the edge ID of the first edge (tail, head).
Parameters tail : integer
head : integer
Returns edge_id : integer
Raises NodeDoesNotExist
EdgeDoesNotExistError
DisabledFeatureError
If tail is negative and the graph is not two-way compressed.

Notes

This method is useful for graphs where each edge occurs only once.
has_dangling_edges()
has_edge()
Does the graph contain the edge (tail, head)?

156 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

Parameters tail : integer


head : integer
Returns had_edge : boolean
Raises NodeDoesNotExistError
EdgeDoesNotExistError
DisabledFeatureError
If tail is negative and the graph is not two-way compressed.
head()
Return the head of an edge, given its edge ID.
Parameters edge_id : integer
Raises EdgeDoesNotExistError

Notes

This method executes in constant time. It works for all edge IDs, returning both positive and
negative heads.
in_edge_ids()
Return the IDs of incoming edges of a node.
Parameters node : integer
Returns edge_ids : sequence of integers
Raises NodeDoesNotExistError
DisabledFeatureError
If the graph is not two-way compressed.
in_neighbors()
Return the nodes which point to a node.
Parameters node : integer
Returns nodes : sequence of integers
Raises NodeDoesNotExistError
DisabledFeatureError
If the graph is not two-way compressed.
out_edge_ids()
Return the IDs of outgoing edges of node.
Parameters node : integer
Returns edge_ids : sequence of integers
Raises NodeDoesNotExistError
out_neighbors()
Return the nodes a node points to.
Parameters node : integer
Returns nodes : sequence of integers
Raises NodeDoesNotExistError
tail()
Return the tail of an edge, given its edge ID.

5.2. kwant.graph – Low-level, efficient directed graphs 157


Kwant 1.3.1 documentation

Parameters edge_id : integer


Returns tail : integer
If the edge exists and is positive.
None
If the tail is negative.
Raises EdgeDoesNotExistError

Notes

The average performance of this method is O(log num_nodes) for non-negative tails and O(1)
for negative ones.
write_dot()
Write a representation of the graph in dot format to file.
Parameters file : file-like object

Notes

That resulting file can be visualized with dot(1) or neato(1) form the graphviz package.

Attributes

edge_nr_translation
num_edges
num_nodes
num_px_edges
num_xp_edges
twoway

5.2.2 Graph algorithms

slice TODO: write me.


make_undirected undirected_graph(gr) expects a CGraph gr as input,
which is interpreted
remove_duplicates Remove duplicate edges in the CGraph gr (this ap-
plies to the case where there are multiple edges (i,j),
not to having (i,j) and (j,i)).
induced_subgraph Return a subgraph of the CGraph gr by picking all
nodes [0:gr.num_nodes] for which select is True.
print_graph

kwant.graph.slice

kwant.graph.slice()
TODO: write me.

158 Chapter 5. Modules mainly for internal use


Kwant 1.3.1 documentation

kwant.graph.make_undirected

kwant.graph.make_undirected()
undirected_graph(gr) expects a CGraph gr as input, which is interpreted as a directed graph, and
returns a CGraph that is explicitely undirected, i.e. for every edge (i,j) there is also the edge (j,i).
In the process, the function also removes all ‘dangling’ links, i.e. edges to or from negative node
numbers.
If remove_dups == True (default value is True), any duplicates of edges will be removed (this
applies to the case where there are multiple edges (i,j), not to having (i,j) and (j,i)).
The effect of the duplicate edges can be retained if calc_weights == True (default value is False),
in which case a weight array is returned containing the multiplicity of the edges after the graph
has been made undirected.
As a (somewhat drastic but illustrative) example, if make_undirected is applied to a undirected
graph, it will return the same graph again (possibly with the order of edges changed) and a weight
array with 2 everywhere. (Of course, in this case one does not need to call make_undirected ...)
make_undirected() will always return a one-way graph, regardless of whether the input was a two-
way graph or not (NOTE: This restriction could be lifted, if necessary). In addition, the original
edge_ids are lost – the resulting graph will have edge_ids that are not related to the original ones.
(NOTE: there certainly is a relation, but as long as no-one needs it it remains unspecified)

kwant.graph.remove_duplicates

kwant.graph.remove_duplicates()
Remove duplicate edges in the CGraph gr (this applies to the case where there are multiple edges
(i,j), not to having (i,j) and (j,i)). This function modifes the graph in place.
If edge_weights is provided, edge_weights is modified such that the new edge weights are the sum
of the old edge weights if there are duplicate edges.
This function only works on simple graphs (not two-way graphs), and it does not work on graphs
which have a relation between the edge number (given by the order the edges are added) and the
edge_id (given by the order the edges appear in the graph), see the documentation of CGraph.
(Both restrictions could be lifted if necessary.) Furthermore, the function does not support negative
node numbers, i.e. dangling links (the concept of being duplicate is more complicated there.)

kwant.graph.induced_subgraph

kwant.graph.induced_subgraph()
Return a subgraph of the CGraph gr by picking all nodes [0:gr.num_nodes] for which select is
True. select can be either a NumPy array, or a function that takes the node number as input. This
function returns a CGraph as well.
The nodes in the new graph are again numbered sequentially from 0 to num_nodes-1, where
num_nodes is the number of nodes in the subgraph. The numbering is done such that the ordering
of the node numbers in the original and the subgraph are preserved (i.e. if nodes n1 and n2 are
both in the subgraph, and original node number of n1 < original node number of n2, then also
subgraph node number n1 < subgraph node number n2).
If edge_weights is provided, the function also returns the edge weights for the subgraph which are
simply a subset of the original weights.
This function returns a simple graph, regardless of whether the input was a two-way graph or not
(NOTE: This restriction could be lifted, if necessary). Also, the resulting edge_ids are not related
to the original ones in any way (NOTE: There certainly is a relation, but as long no-one needs
it, we do not specify it). Also, negative nodes are discarded (NOTE: this restriction can also be
lifted).

5.2. kwant.graph – Low-level, efficient directed graphs 159


Kwant 1.3.1 documentation

kwant.graph.print_graph

kwant.graph.print_graph()

5.2.3 Other

gint_dtype Data type used for graph nodes and edges

5.3 kwant.linalg – Linear algebra routines

This package wraps some selected LAPACK functionality not available via NumPy and also contains
a Python-wrapper for MUMPS. It also has several algorithms for finding approximately orthonormal
lattice bases. It is meant for internal use by Kwant itself, but of course nothing prevents you from using
it directly.
The documentation of this package is not included here on purpose in order not to add too many things
to this reference. Please consult the source code directly.
• genindex

160 Chapter 5. Modules mainly for internal use


BIBLIOGRAPHY

[R1] Rev. Mod. Phys., Vol. 78, No. 1 (2006).


[R2] Phys. Rev. E 69, 057701 (2004)

161
INDEX

Symbols check_hermiticity (kwant.operator.Current at-


__call__() (kwant.kpm.SpectralDensity method), tribute), 126
138 check_hermiticity (kwant.operator.Density at-
__call__() (kwant.operator.Current method), 125 tribute), 124
__call__() (kwant.operator.Density method), 123 check_hermiticity (kwant.operator.Source at-
__call__() (kwant.operator.Source method), 127 tribute), 128
circular() (in module kwant.rmt), 136
A closest() (kwant.builder.Builder method), 89
closest() (kwant.lattice.Monatomic method), 99
act() (kwant.builder.Symmetry method), 96
compressed() (kwant.graph.Graph method), 155
act() (kwant.lattice.TranslationalSymmetry
conductance_matrix()
method), 97
(kwant.solvers.common.GreensFunction
act() (kwant.operator.Current method), 125
method), 120
act() (kwant.operator.Density method), 123
conductance_matrix()
act() (kwant.operator.Source method), 127
(kwant.solvers.common.SMatrix
add_edge() (kwant.graph.Graph method), 154
method), 119
add_edges() (kwant.graph.Graph method), 154
count() (kwant.builder.HoppingKind method), 92
add_moments() (kwant.kpm.SpectralDensity
count() (kwant.builder.Site method), 91
method), 139
cubic() (in module kwant.lattice), 104
add_site_family() (kwant.lattice.TranslationalSymmetry
Current (class in kwant.operator), 124
method), 97
current() (in module kwant.plotter), 108
add_vectors() (kwant.kpm.SpectralDensity
method), 139
all_edge_ids() (kwant.graph.CGraph method),
D
156 dangling() (kwant.builder.Builder method), 89
attach_lead() (kwant.builder.Builder method), 88 degree() (kwant.builder.Builder method), 89
delta (kwant.builder.HoppingKind attribute), 92
B Density (class in kwant.operator), 122
discrete_symmetry() (kwant.system.FiniteSystem
Bands (class in kwant.physics), 128
method), 151
bands() (in module kwant.plotter), 109
discrete_symmetry()
bind() (kwant.operator.Current method), 125
(kwant.system.InfiniteSystem method),
bind() (kwant.operator.Density method), 123
149
bind() (kwant.operator.Source method), 127
discrete_symmetry() (kwant.system.System
block_coords() (kwant.solvers.common.GreensFunction
method), 148
method), 120
DiscreteSymmetry (class in kwant.physics), 132
block_coords() (kwant.solvers.common.SMatrix
discretize() (in module kwant.continuum), 139
method), 119
discretize_symbolic() (in module
build_discretized() (in module kwant.continuum),
kwant.continuum), 140
141
Builder (class in kwant.builder), 86
BuilderLead (class in kwant.builder), 93
E
edge_id() (kwant.graph.CGraph method), 156
C edge_nr_translation (kwant.graph.CGraph at-
tribute), 158
cell_hamiltonian() (kwant.system.InfiniteSystem
eradicate_dangling() (kwant.builder.Builder
method), 149
method), 89
CGraph (class in kwant.graph), 155
expand() (kwant.builder.Builder method), 89
chain() (in module kwant.lattice), 104

162
Kwant 1.3.1 documentation

F in_block_coords() (kwant.solvers.common.SMatrix
family (kwant.builder.Site attribute), 91 method), 119
family_a (kwant.builder.HoppingKind attribute), in_edge_ids() (kwant.graph.CGraph method), 157
92 in_fd() (kwant.builder.Symmetry method), 96
family_b (kwant.builder.HoppingKind attribute), in_fd() (kwant.lattice.TranslationalSymmetry
92 method), 98
fill() (kwant.builder.Builder method), 89 in_neighbors() (kwant.graph.CGraph method),
finalized() (kwant.builder.Builder method), 90 157
finalized() (kwant.builder.BuilderLead method), 94 index() (kwant.builder.HoppingKind method), 92
finalized() (kwant.builder.Lead method), 97 index() (kwant.builder.Site method), 91
finalized() (kwant.builder.ModesLead method), 94 induced_subgraph() (in module kwant.graph), 159
finalized() (kwant.builder.SelfEnergyLead InfiniteSystem (class in kwant.system), 149
method), 94 integrate() (kwant.kpm.SpectralDensity method),
FiniteSystem (class in kwant.system), 151 139
first_edge_id() (kwant.graph.CGraph method), inter_cell_hopping()
156 (kwant.system.InfiniteSystem method),
150
G interpolate_current() (in module kwant.plotter),
gauss() (in module kwant.digest), 135 112
gaussian() (in module kwant.rmt), 135
general() (in module kwant.lattice), 98
K
Graph (class in kwant.graph), 154 kagome() (in module kwant.lattice), 104
greens_function() (in module kwant (module), 85
kwant.solvers.default), 117 kwant.builder (module), 86
GreensFunction (class in kwant.solvers.common), kwant.continuum (module), 139
120 kwant.digest (module), 135
kwant.graph (module), 153
H kwant.kpm (module), 137
hamiltonian() (kwant.system.FiniteSystem kwant.lattice (module), 97
method), 151 kwant.linalg (module), 160
hamiltonian() (kwant.system.InfiniteSystem kwant.operator (module), 122
method), 149 kwant.physics (module), 128
hamiltonian() (kwant.system.System method), 148 kwant.plotter (module), 104
hamiltonian_submatrix() kwant.rmt (module), 135
(kwant.system.FiniteSystem method), kwant.solvers (module), 118
151 kwant.solvers.default (module), 115
hamiltonian_submatrix() kwant.solvers.mumps (module), 121
(kwant.system.InfiniteSystem method), kwant.solvers.sparse (module), 121
150 kwant.system (module), 147
hamiltonian_submatrix() (kwant.system.System kwant.wraparound (module), 143
method), 148 KwantDeprecationWarning, 85
has_dangling_edges() (kwant.graph.CGraph
method), 156 L
has_edge() (kwant.graph.CGraph method), 156 lambdify() (in module kwant.continuum), 143
has_subgroup() (kwant.builder.Symmetry ldos() (in module kwant.solvers.default), 118
method), 96 Lead (class in kwant.builder), 96
has_subgroup() (kwant.lattice.TranslationalSymmetry
method), 98 M
head() (kwant.graph.CGraph method), 157 make_undirected() (in module kwant.graph), 159
honeycomb() (in module kwant.lattice), 104 map() (in module kwant.plotter), 107
hopping_value_pairs() (kwant.builder.Builder mask_interpolate() (in module kwant.plotter), 115
method), 90 modes() (in module kwant.physics), 129
HoppingKind (class in kwant.builder), 92 modes() (kwant.builder.ModesLead method), 94
hoppings() (kwant.builder.Builder method), 90 modes() (kwant.system.InfiniteSystem method),
150
I modes() (kwant.system.PrecalculatedLead
in_block_coords() (kwant.solvers.common.GreensFunction method), 153
method), 120 ModesLead (class in kwant.builder), 94

Index 163
Kwant 1.3.1 documentation

Monatomic (class in kwant.lattice), 99 print_graph() (in module kwant.graph), 160


PropagatingModes (class in kwant.physics), 131
N
n_closest() (kwant.lattice.Monatomic method), 99 R
neighbors() (kwant.builder.Builder method), 90 remove_duplicates() (in module kwant.graph), 159
neighbors() (kwant.lattice.Monatomic method), 99 reserve() (kwant.graph.Graph method), 155
neighbors() (kwant.lattice.Polyatomic method), reset_options() (in module kwant.solvers.mumps),
102 122
normalize_tag() (kwant.builder.SimpleSiteFamily reversed() (kwant.builder.Builder method), 90
method), 93 reversed() (kwant.lattice.TranslationalSymmetry
normalize_tag() (kwant.builder.SiteFamily method), 98
method), 95
normalize_tag() (kwant.lattice.Monatomic S
method), 100 selfenergy() (in module kwant.physics), 130
num_directions (kwant.builder.Symmetry at- selfenergy() (kwant.builder.ModesLead method),
tribute), 96 94
num_directions (kwant.lattice.TranslationalSymmetry selfenergy() (kwant.builder.SelfEnergyLead
attribute), 98 method), 94
num_edges (kwant.graph.CGraph attribute), 158 selfenergy() (kwant.physics.StabilizedModes
num_nodes (kwant.graph.CGraph attribute), 158 method), 132
num_nodes (kwant.graph.Graph attribute), 155 selfenergy() (kwant.system.InfiniteSystem
num_propagating() (kwant.solvers.common.GreensFunction method), 150
method), 120 selfenergy() (kwant.system.PrecalculatedLead
num_propagating() (kwant.solvers.common.SMatrix method), 153
method), 119 SelfEnergyLead (class in kwant.builder), 94
num_px_edges (kwant.graph.CGraph attribute), shape() (kwant.lattice.Monatomic method), 100
158 shape() (kwant.lattice.Polyatomic method), 102
num_xp_edges (kwant.graph.CGraph attribute), SimpleSiteFamily (class in kwant.builder), 93
158 Site (class in kwant.builder), 91
site_value_pairs() (kwant.builder.Builder
O method), 90
onsite (kwant.operator.Current attribute), 126 SiteFamily (class in kwant.builder), 95
onsite (kwant.operator.Density attribute), 124 sites() (kwant.builder.Builder method), 91
onsite (kwant.operator.Source attribute), 128 slice() (in module kwant.graph), 158
options() (in module kwant.solvers.mumps), 121 SMatrix (class in kwant.solvers.common), 119
out_block_coords() (kwant.solvers.common.GreensFunction
smatrix() (in module kwant.solvers.default), 116
method), 120 Source (class in kwant.operator), 126
out_block_coords() (kwant.solvers.common.SMatrix SpectralDensity (class in kwant.kpm), 137
method), 119 spectrum() (in module kwant.plotter), 110
out_edge_ids() (kwant.graph.CGraph method), square() (in module kwant.lattice), 104
157 StabilizedModes (class in kwant.physics), 131
out_neighbors() (kwant.graph.CGraph method), streamplot() (in module kwant.plotter), 111
157 subgroup() (kwant.builder.Symmetry method), 96
subgroup() (kwant.lattice.TranslationalSymmetry
P method), 98
plot() (in module kwant.plotter), 105 submatrix() (kwant.solvers.common.GreensFunction
plot_2d_bands() (in module kwant.wraparound), method), 120
144 submatrix() (kwant.solvers.common.SMatrix
Polyatomic (class in kwant.lattice), 101 method), 119
pos (kwant.builder.Site attribute), 91 sum (kwant.operator.Current attribute), 126
pos() (kwant.lattice.Monatomic method), 100 sum (kwant.operator.Density attribute), 124
precalculate() (kwant.system.FiniteSystem sum (kwant.operator.Source attribute), 128
method), 152 Symmetry (class in kwant.builder), 95
PrecalculatedLead (class in kwant.system), 153 sympify() (in module kwant.continuum), 142
prim_vecs (kwant.lattice.Monatomic attribute), sys_leads_hopping_pos() (in module
101 kwant.plotter), 114
prim_vecs (kwant.lattice.Polyatomic attribute), sys_leads_hoppings() (in module kwant.plotter),
103 113

164 Index
Kwant 1.3.1 documentation

sys_leads_pos() (in module kwant.plotter), 114


sys_leads_sites() (in module kwant.plotter), 113
syst (kwant.operator.Current attribute), 126
syst (kwant.operator.Density attribute), 124
syst (kwant.operator.Source attribute), 128
System (class in kwant.system), 147

T
tag (kwant.builder.Site attribute), 92
tail() (kwant.graph.CGraph method), 157
test() (in module kwant.digest), 135
to_fd() (kwant.builder.Symmetry method), 96
to_fd() (kwant.lattice.TranslationalSymmetry
method), 98
tocoo() (kwant.operator.Density method), 123
TranslationalSymmetry (class in kwant.lattice), 97
transmission() (kwant.solvers.common.GreensFunction
method), 120
transmission() (kwant.solvers.common.SMatrix
method), 119
triangular() (in module kwant.lattice), 104
two_terminal_shotnoise() (in module
kwant.physics), 131
twoway (kwant.graph.CGraph attribute), 158

U
uniform() (in module kwant.digest), 135
update() (kwant.builder.Builder method), 91
UserCodeError, 85

V
validate() (kwant.physics.DiscreteSymmetry
method), 133
vec() (kwant.lattice.Monatomic method), 100
vec() (kwant.lattice.Polyatomic method), 103

W
wave_function() (in module kwant.solvers.default),
117
where (kwant.operator.Current attribute), 126
where (kwant.operator.Density attribute), 124
where (kwant.operator.Source attribute), 128
which() (kwant.builder.Symmetry method), 96
which() (kwant.lattice.TranslationalSymmetry
method), 98
wire() (kwant.lattice.Monatomic method), 100
wire() (kwant.lattice.Polyatomic method), 103
wraparound() (in module kwant.wraparound), 143
write_dot() (kwant.graph.CGraph method), 158
write_dot() (kwant.graph.Graph method), 155

Index 165

You might also like