diff --git a/doc/source/conf.py b/doc/source/conf.py index 476550f65968ea680de20e0dacbf2d9ba71c81fe..0748681c66658b61315972ac0db2f3a2605adf11 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -215,3 +215,23 @@ autosummary_generate = True autoclass_content = "both" autodoc_default_flags = ['show-inheritance'] + +# -- Teach Sphinx to document bound methods like functions --------------------- +import types +from sphinx.ext import autodoc + +class BoundMethodDocumenter(autodoc.FunctionDocumenter): + objtype = "boundmethod" + directivetype = 'function' + + @classmethod + def can_document_member(cls, member, membername, isattr, parent): + # Return True iff `member` is a bound method. Taken from + # <http://stackoverflow.com/a/1260881>. + return (isinstance(member, types.MethodType) and + member.im_self is not None and + not issubclass(member.im_class, type) and + member.im_class is not types.ClassType) + +def setup(app): + app.add_autodocumenter(BoundMethodDocumenter) diff --git a/doc/source/reference/kwant.rst b/doc/source/reference/kwant.rst index 00ca317e0f1f0ff4d3ea0a0e846ab254b3c9080b..ab901742f94732ffc6ef8ec70f9da99e13abac60 100644 --- a/doc/source/reference/kwant.rst +++ b/doc/source/reference/kwant.rst @@ -33,8 +33,10 @@ From `kwant.plotter` plot +.. currentmodule:: kwant.solvers.default + From ``kwant.solvers.default`` ------------------------------ .. autosummary:: - ~kwant.solvers.common.SparseSolver.solve + solve diff --git a/doc/source/reference/kwant.solvers.common.rst b/doc/source/reference/kwant.solvers.common.rst deleted file mode 100644 index 2d120120128bc959c23dd5672b3f390c6636531f..0000000000000000000000000000000000000000 --- a/doc/source/reference/kwant.solvers.common.rst +++ /dev/null @@ -1,13 +0,0 @@ -:mod:`kwant.solvers.common` -- common functionality used by solvers -=================================================================== - -.. module:: kwant.solvers.common - -This module typically needs not be used directly by the user. It is rather -used by the individual solver modules. - -.. autosummary:: - :toctree: generated/ - - BlockResult - SparseSolver diff --git a/doc/source/reference/kwant.solvers.mumps.rst b/doc/source/reference/kwant.solvers.mumps.rst index de20ccd208a989da0cee9b3cf4c7487fbbe81bbf..3ccc92df1b1b9749022182538361c24c1d744d6c 100644 --- a/doc/source/reference/kwant.solvers.mumps.rst +++ b/doc/source/reference/kwant.solvers.mumps.rst @@ -3,24 +3,18 @@ .. module:: kwant.solvers.mumps -A sparse solver that uses `MUMPS <http://graal.ens-lyon.fr/MUMPS/>`_. (Only -the sequential, single core version is used.) +This solver uses `MUMPS <http://graal.ens-lyon.fr/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. -MUMPS is a very efficient direct sparse solver that can take advantage of -memory beyond 3GB for the solution of large problems. Furthermore, it offers a -choice of several orderings of the input matrix from which can speed up a -calculation significantly. +Compared with the :mod:`default solver <kwant.solvers.default>`, 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. -Compared to the generic sparse solver framework, `mumps` adds the following -control options that may affect performance: +.. autofunction:: options -- `ordering`: a fill-in reducing ordering of the matrix -- `nrhs`: number of right hand sides that should be solved simultaneously -- `sparse_rhs`: whether to use dense or sparse right hand sides - -For more details see `~Solver.options`. - -.. autosummary:: - :toctree: generated/ - - Solver +.. autofunction:: reset_options diff --git a/doc/source/reference/kwant.solvers.rst b/doc/source/reference/kwant.solvers.rst index e18a72402a15adca903bf4b41184f451be94adee..e5b15652a80bec9159ac6db97868a5070f6c2d6f 100644 --- a/doc/source/reference/kwant.solvers.rst +++ b/doc/source/reference/kwant.solvers.rst @@ -1,132 +1,77 @@ :mod:`kwant.solvers` -- Library of solvers ========================================== -Overview of the solver infrastructure -------------------------------------- +Overview +-------- -kwant offers a variety of solvers for computing the solution -to a quantum transport problem. These different solvers may either -depend on different external libraries, or use very different internal -algorithms for doing the actual computation. +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 external libraries. If the +libraries needed by one solver are not installed, trying to import it will +raise an ``ImportError`` exception. The :doc:`Installation instructions +<../install>` list all the libraries that are required or can be used by kwant +and its solvers. -Fortunately, all these different solvers still use the same interface -conventions. Thus, all solvers can be used without explicit knowledge -of the internals. On the other hand, many solvers allow for some -controls that can affect performance. -All of the solver modules implement the following functions: +:mod:`kwant.solvers.default` -- The default solver +-------------------------------------------------- -- `~kwant.solvers.common.SparseSolver.solve`: Compute the Scattering matrix - or Green's function between different leads. Can be used to compute - conductances -- `~kwant.solvers.common.SparseSolver.ldos`: Compute the local density of - states of the system. +.. module:: kwant.solvers.default -For details see the respective function. (You might note that the above links -lead to the documentation of a method in a class, rather than a function -in the solver module. For details, see :ref:`below <details_of_solver>`. -In a nutshell, all of the solver functionality can be -accessed by functions on the module-level; internally they are encapsulated in -a class) +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. -Due to the common interface you can thus write code that allows you to -switch solvers by changing one `import`-line:: +.. autosummary:: + :toctree: generated/ - from kwant.solvers.some_solver import solve + solve + wave_func + ldos - ... +`solve` returns an object of the following type: - smatrix = solve(fsys) - -In addition to the common interface, some solvers allow for additional -control parameters for performance-tuning. In this case they -have a function `options` on the module level. Code could then -look like this:: - - import kwant.solvers.some_solver as solver - - solver.options(...) - - ... - - smatrix - solver.solve(fsys) - - -Summary of solver modules in kwant: ------------------------------------ - -Right now, the following solvers are implemented in kwant: - -- `~kwant.solvers.sparse`: A solver based on solving a sparse linear - system, using the direct sparse solvers provided by SciPy. -- `~kwant.solvers.mumps`: A solver based on solving a sparse linear - system using the direct sparse solver MUMPS. To use it, the MUMPS - library must be installed on the system. This solver typically - gives the best performance of all sparse solvers for a single core. - It allows for various solve options using `~kwant.solvers.mumps.options`. - - -.. _details_of_solver: - -Details of the internal structure of a solver ---------------------------------------------- - -Each solver module implements a class `Solver` (e.g. -`kwant.solvers.sparse.Solver`), with methods implementing the solve -functionality of the solvers. This encapsulation in a class allows to -use solvers with different options concurrently. - -Typically, one however does not need this flexibility, and will not want to -bother with the `Solver` class itself. For this reason, every solver module has -a default instance of the `Solver` class. Its methods are then made available -as functions on the module level. - -In particular, the following:: - - import kwant.solvers.sparse as slv - - ... - - smatrix = slv.solve(sys, energy=...) - dos = slv.ldos(sys, energy=...) - -is equivalent to:: - - import kwant.solvers.sparse as slv - - ... - - smatrix = slv.default_solver.solve(sys, energy=...) - dos = slv.default_solver.ldos(sys, energy=...) - -where ``default_solver`` is an instance of `kwant.solvers.sparse.Solver`. - - -The default solver ------------------- +.. module:: kwant.solvers -Since computing conductance is the most basic task of kwant, the -`solve`-function of one of the solvers is provided via `kwant.solve`. -kwant chooses the solver which it considers best amongst the -available solvers. You can see by calling +.. autosummary:: + :toctree: generated/ ->>> help(kwant.solve) + kwant.solvers.common.BlockResult -from which module it has been imported. +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) -List of solver modules ----------------------- -The modules of the solver package are listed in detail below. Note -that the solvers (with the exception of the module providing -`kwant.solve`) have to be imported explicitly. +Other solver modules +-------------------- -.. module:: kwant.solvers +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. .. toctree:: :maxdepth: 1 kwant.solvers.sparse kwant.solvers.mumps - kwant.solvers.common + +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. diff --git a/doc/source/reference/kwant.solvers.sparse.rst b/doc/source/reference/kwant.solvers.sparse.rst index 00947d84b71900fe5604281ceb81bca1b50f27fa..c320c0e852ad6577846425ba849d5168ca71becc 100644 --- a/doc/source/reference/kwant.solvers.sparse.rst +++ b/doc/source/reference/kwant.solvers.sparse.rst @@ -3,18 +3,13 @@ .. module:: kwant.solvers.sparse -A sparse solver that uses `scipy.sparse.linalg -<http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html>`_. - -SciPy 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. - -`sparse` does not introduce any additional options as compared to the generic -sparse solver framework. - -.. autosummary:: - :toctree: generated/ - - Solver +This solver uses SciPy's `scipy.sparse.linalg +<http://docs.scipy.org/doc/scipy/reference/sparse.linalg.html>`_. The +interface is identical to that of the :mod:`default solver +<kwant.solvers.default>`. + +``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. diff --git a/doc/source/tutorial/tutorial1.rst b/doc/source/tutorial/tutorial1.rst index 837938088e3744db593da1130145fb4812b96a08..11cb9b0e6a535939ad69d8d24c657a6c5170e0ca 100644 --- a/doc/source/tutorial/tutorial1.rst +++ b/doc/source/tutorial/tutorial1.rst @@ -22,15 +22,22 @@ In order to use kwant, we need to import it: Enabling kwant is as easy as this [#]_ ! -The first step is now the definition of the system with scattering region -and leads. For this we make use of the `~kwant.builder.Builder` class -that allows for a convenient way to define the system. For this we need to -create an instance of the `~kwant.builder.Builder` class: +The first step is now the definition of the system with scattering region and +leads. For this we make use of the `~kwant.builder.Builder` type that allows to +define a system in a convenient way. We need to create an instance of it: .. literalinclude:: 1-quantum_wire.py :start-after: #HIDDEN_BEGIN_goiq :end-before: #HIDDEN_END_goiq +Observe that we just accessed `~kwant.builder.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 :doc:`reference documentation +<../reference/index>`. 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 `~kwant.builder.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: @@ -137,12 +144,11 @@ its conductance as a function of energy: :start-after: #HIDDEN_BEGIN_buzn :end-before: #HIDDEN_END_buzn -Currently **CHANGE**, there is only one algorithm implemented to compute the -conductance: :func:`kwant.solve <kwant.solvers.common.SparseSolver.solve>` -which computes the scattering matrix `smatrix` solving a sparse linear system. -`smatrix` itself allows you to directly compute the total -transmission probability from lead 0 to lead 1 as -``smatrix.transmission(1, 0)``. +We use ``kwant.solve`` which is a short name for `kwant.solvers.default.solve` +of the default solver module `kwant.solvers.default`. ``kwant.solve`` 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)``. Finally we can use `matplotlib` to make a plot of the computed data (although writing to file and using an external viewer such as diff --git a/kwant/solvers/common.py b/kwant/solvers/common.py index 7da4ad3cb6faaebe828fe4db49ddce9502ec68b0..ebab8dec99a02abd148d7ea0e21a1ab4cc2af24e 100644 --- a/kwant/solvers/common.py +++ b/kwant/solvers/common.py @@ -22,16 +22,12 @@ class SparseSolver(object): """Solver class for computing physical quantities based on solving a liner system of equations. - `SparseSolver` provides the following functionality: - - - `solve`: Compute a scattering matrix or Green's function - - `ldos`: Compute the local density of states - `SparseSolver` is an abstract base class. It cannot be instantiated as it does not specify the actual linear solve step. In order to be directly - usable, a derived class must implement the method + usable, a derived class must implement the methods - - `solve_linear_sys`, that solves a linear system of equations + - `_factorize` and `_solve_linear_sys`, that solve a linear system of + equations and the following properties: @@ -43,14 +39,25 @@ class SparseSolver(object): in a call to `solve_linear_sys`, when the full solution is computed (i.e. kept_vars covers all entries in the solution). This should be not too big too avoid excessive memory usage, but for some solvers not too small for - performance reasons. Only used for `ldos` in this class. + performance reasons. """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def _factorized(self, a): - """Return a preprocessed version of a matrix for the use with - `solve_linear_sys`.""" + """ + Return a preprocessed version of a matrix for the use with + `solve_linear_sys`. + + Parameters + ---------- + a : a scipy.sparse.coo_matrix sparse matrix. + + Returns + ------- + factorized_a : object + factorized lhs to be used with `_solve_linear_sys`. + """ pass @abc.abstractmethod @@ -59,8 +66,20 @@ class SparseSolver(object): Solve the linar system `a x = b`, returning the part of the result indicated in kept_vars. - `factorized_a` is expected to be the result of `_factorize` for the - matrix a. + Parameters + ---------- + factorized : object + The result of calling `_factorized` for the matrix a. + b : a sequence of matrices. + Sizes of these matrices may be smaller than needed, the missing + entries at the end are padded with zeros. + kept_vars : slice object or sequence of integers + A sequence of numbers of variables to keep in the solution + + Returns + ------- + output : NumPy matrix + Solution to the system of equations. """ pass @@ -73,20 +92,20 @@ class SparseSolver(object): Parameters ---------- sys : kwant.system.FiniteSystem - low level system, containing the leads and the Hamiltonian of a + Low level system, containing the leads and the Hamiltonian of a scattering region. - out_leads : list of integers - numbers of leads where current or wave function is extracted - in_leads : list of integers - numbers of leads in which current or wave function is injected. + out_leads : sequence of integers + Numbers of leads where current or wave function is extracted + in_leads : sequence of integers + Numbers of leads in which current or wave function is injected. energy : number - excitation energy at which to solve the scattering problem. + Excitation energy at which to solve the scattering problem. force_realspace : bool - calculate Green's function between the outermost lead + Calculate Green's function between the outermost lead sites, instead of lead modes. This is almost always more computationally expensive and less stable. check_hermiticity : bool - check if Hamiltonian matrices are in fact Hermitian. + Check if Hamiltonian matrices are in fact Hermitian. Returns ------- @@ -250,28 +269,28 @@ class SparseSolver(object): Parameters ---------- sys : `kwant.system.FiniteSystem` - low level system, containing the leads and the Hamiltonian of a + Low level system, containing the leads and the Hamiltonian of a scattering region. energy : number - excitation energy at which to solve the scattering problem. - out_leads : list of integers or None - numbers of leads where current or wave function is extracted. + Excitation energy at which to solve the scattering problem. + out_leads : sequence of integers or None + Numbers of leads where current or wave function is extracted. None is interpreted as all leads. Default is None. - in_leads : list of integers or None - numbers of leads in which current or wave function is injected. + 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. force_realspace : bool - calculate Green's function between the outermost lead + Calculate Green's function between the outermost lead sites, instead of lead modes. This is almost always more computationally expensive and less stable. check_hermiticity : bool - check if the Hamiltonian matrices are Hermitian. + Check if the Hamiltonian matrices are Hermitian. Returns ------- - output : `BlockResult` - see notes below and `BlockResult` docstring for more - information about the output format. + output : `~kwant.solvers.common.BlockResult` + See the notes below and `~kwant.solvers.common.BlockResult` + documentation. Notes ----- @@ -331,15 +350,15 @@ class SparseSolver(object): Parameters ---------- sys : `kwant.system.FiniteSystem` - low level system, containing the leads and the Hamiltonian of the + Low level system, containing the leads and the Hamiltonian of the scattering region. energy : number - excitation energy at which to solve the scattering problem. + Excitation energy at which to solve the scattering problem. Returns ------- ldos : a NumPy array - local density of states at each orbital of the system. + Local density of states at each orbital of the system. """ for lead in fsys.leads: if not isinstance(lead, system.InfiniteSystem): diff --git a/kwant/solvers/mumps.py b/kwant/solvers/mumps.py index 9b3b04ff900161d5678a45d6f00e7ceda17c28b7..9f18dba310fb4567d7dc2b93de71100810753a29 100644 --- a/kwant/solvers/mumps.py +++ b/kwant/solvers/mumps.py @@ -92,42 +92,11 @@ class Solver(common.SparseSolver): return old_opts def _factorized(self, a): - """ - Factorize a matrix, so it can be used with `_solve_linear_sys`. - - Parameters - ---------- - a : a scipy.sparse.coo_matrix sparse matrix. - - Returns - ------- - factorized_a : object - factorized lhs to be used with `_solve_linear_sys`. - """ inst = mumps.MUMPSContext() inst.factor(a, ordering=self.ordering) return inst, a.shape def _solve_linear_sys(self, factorized_a, b, kept_vars=None): - """ - Solve matrix system of equations a x = b with sparse input, - using MUMPS. - - Parameters - ---------- - factorized_a : object - The result of calling `factorized` for the matrix a. - b : a list of scipy.sparse.csc_matrices. - kept_vars : list of integers - a list of numbers of variables to keep in the solution. - factored : a factorized lhs as returned by a previous call - to `_solve_linear_sys` with the same lhs. - - Returns - ------- - output : NumPy matrix - Solution to the system of equations. - """ inst, a_shape = factorized_a if kept_vars is None: diff --git a/kwant/solvers/sparse.py b/kwant/solvers/sparse.py index 8192870be5ed6dea1062c98c8e537fec1969df98..27ceb565cc523fe92a54004d0870cd6c136cad97 100644 --- a/kwant/solvers/sparse.py +++ b/kwant/solvers/sparse.py @@ -89,41 +89,10 @@ class Solver(common.SparseSolver): nrhs = 1 def _factorized(self, a): - """ - Factorize a matrix, so it can be used with `_solve_linear_sys`. - - Parameters - ---------- - a : a scipy.sparse.coo_matrix sparse matrix. - - Returns - ------- - factorized_a : object - factorized lhs to be used with `_solve_linear_sys`. - """ a = sp.csc_matrix(a) return factorized(a), a.shape def _solve_linear_sys(self, factorized_a, b, kept_vars=None): - """ - Solve matrix system of equations a x = b with sparse input, - using the sparse direct solver provided by SciPy. - - Parameters - ---------- - factorized : object - The result of calling `_factorized` for the matrix a. - b : a list of matrices. - Sizes of these matrices may be smaller than needed, the missing - entries at the end are padded with zeros. - kept_vars : slice object or list of integers - a list of numbers of variables to keep in the solution - - Returns - ------- - output : NumPy matrix - Solution to the system of equations. - """ slv, a_shape = factorized_a if kept_vars is None: