From 40396f16915218c9e7c05d005e79df8c761f467f Mon Sep 17 00:00:00 2001
From: Christoph Groth <christoph.groth@cea.fr>
Date: Wed, 28 Nov 2012 14:26:43 +0100
Subject: [PATCH] reorganize solver docs

---
 doc/source/conf.py                            |  20 +++
 doc/source/reference/kwant.rst                |   4 +-
 doc/source/reference/kwant.solvers.common.rst |  13 --
 doc/source/reference/kwant.solvers.mumps.rst  |  30 ++--
 doc/source/reference/kwant.solvers.rst        | 159 ++++++------------
 doc/source/reference/kwant.solvers.sparse.rst |  25 ++-
 doc/source/tutorial/tutorial1.rst             |  26 +--
 kwant/solvers/common.py                       |  87 ++++++----
 kwant/solvers/mumps.py                        |  31 ----
 kwant/solvers/sparse.py                       |  31 ----
 10 files changed, 166 insertions(+), 260 deletions(-)
 delete mode 100644 doc/source/reference/kwant.solvers.common.rst

diff --git a/doc/source/conf.py b/doc/source/conf.py
index 476550f6..0748681c 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 00ca317e..ab901742 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 2d120120..00000000
--- 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 de20ccd2..3ccc92df 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 e18a7240..e5b15652 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 00947d84..c320c0e8 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 83793808..11cb9b0e 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 7da4ad3c..ebab8dec 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 9b3b04ff..9f18dba3 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 8192870b..27ceb565 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:
-- 
GitLab