Writing Documentation¶
Contents
Documentation Philosophy¶
QDYN’s documentation is organized around four distinct categories.
Examples (learning-oriented tutorials): A lesson illustrating a particular use case of QDYN. Typically a Jupyter notebook walking through a simplified version of a published paper, targeted towards a new user of QDYN. See the section on writing Jupyter Notebook Examples below.
How-tos (goal-oriented guides): A guide on how to accomplish something specific with QDYN, for more experienced users. Typically written as a response to a user’s question. See the section on writing How-Tos below.
Topical overviews (understanding-oriented explanations): An in-depth review of the concepts behind QDYN and how they are implemented. Targeted towards a student learning numerical methods of quantum control. See the section on writing Topical Overviews below.
Reference material (information-oriented descriptions): These are typically auto-generated, e.g. QDYN’s API and config file documentation. Targeted towards QDYN developers. See the sections on Fortran Docstrings and the Config File Documentation below.
Note
Make sure to watch the What Nobody Tells You about Documentation talk that describes the motivation behind these four categories.
See also How the documentation is organized (from a user’s perspective) on the main index page.
Automatic Doc-Generation¶
Running make doc
will use Sphinx to translate input files located in
doc/sources/
to html output in doc/_build/html
. During installation
(make install
), the contents of doc/_build/html
will be copied to the
install location.
Some of the files in doc/sources/
are automatically generated during make
doc
:
For every module, documentation is generated by parsing the source code of that module for lines starting with
!!
(“Fortran Docstrings”). The RST files for this “API” documentation are (temporarily) generated indoc/soures/api/
.Documentation for the different sections of the config file is (temporarily) created in
doc/sources/config/sections/
, via thescripts/generate_config_doc.py
script. Moreover, “reference card” PDF files for the QDYN config are generated indoc/sources/config/refcard/
(via thescripts/generate_refcard.py
script).
The entire process is controlled by the scripts/compile_doc.py
script.
The RestructuredText Syntax (RST) markup language is used both in the static documents
in doc/sources/
and when interpreting the docstrings inside modules.
Bibliographic References¶
The QDYN documentation uses sphinxcontrib-bibtex to manage citations,
emulating citations in LaTeX. All bibliographic data is collected in a bibtex database at doc/sources/refs.bib
.
The entries in this file are rendered in the central References page of the documentation in a format akin to that used in APS journals like Phys. Rev. Lett. The details of this format are defined by the ApsStyle
class in doc/sources/conf.py
.
Citations¶
In any part of the documentation, a reference is then cited as e.g.
:cite:`ReichJCP2012`
which renders as e.g. [23] and links to the corresponding entry on the References page.
In Jupyter notebooks an alternative syntax using <cite>
tags with a
data-cite
attribute is required (see below).
The refs.bib Database¶
All references that are cited anywhere in the QDYN source code or documentation (and only those!) must be included in the bibtex database at doc/sources/refs.bib
.
Warning
Strictly adhere to the citation key format and conventions outlined below!
Use an Author-Journal-Year format for the citation key. That is, the last name of the first author, followed by the initials of the journal in all caps, followed by the 4-digit year, e.g.
KochPRL2003
ReichJCP2012
,GoerzNPJQI2017
. Resolve conflicts by appendinga
,b
, …Be consistent with the journal initials. Check the
refs.bib
file for existing citations with the same journal.Conference contributions or book chapters use the same citation key format as journals, with the initials of the conference name or the book/series title instead of the journal name initials, e.g.
KochICOLS2007
for Ref. [43].For PhD theses, use e.g.
GoerzThesis2015
; for other theses, e.g.BlechMaster2018
,BasilewitschBachelor2013
,ReichDiploma2010
.For books, use an Author-Year format. You may concatenate the names of multiple authors, especially for books that are widely referred to by their author pair, like
NielsenChuang2000
Avoid citing preprints. If you must, you can use e.g.
arxiv1902.11284
as the citation key. Use the@article
class and the full arXiv identifier (arXiv:1902.11284
) for the journal-field. Replace these citations with the published version of the paper as soon as possible.All journal entries must use a macro name in the journal field, e.g.
prl
for “Phys. Rev. Lett.”. These macros are defined at the top of therefs.bib
file. The macro name should generally be the lowercase version of the journal initials used in the citation key. For journals not yet listed inrefs.bib
, define a new appropriate macro inrefs.bib
as well as in thescripts/get_bibtex.py
script (see below).The journal name macros must expand to the standard abbreviated journal name for that journal
All article entries must contain a DOI. (Nearly all articles have a DOI. Find it!)
Make sure that proper nouns in titles are enclosed in braces to preserve their capitalization.
Use unicode for accented characters in titles and author names, e.g.
Mølmer
, notM{\o}lmer
.Theses and other materials that don’t have a DOI must include a Url field.
For journal articles, only include the starting page, not a page range.
Do not include non-relevant fields (
OPT
keys, abstracts, unnecessary URLs) in the entry.
Note
Use the ./scripts/get_bibtex.py
script to generate a proper bibtex entry for a given DOI (or URL containing a DOI), using data from https://search.crossref.org.
get_bibtex.py
(depends on the click and habanero packages)
For example:
$ ./venv/bin/python ./scripts/get_bibtex.py 10.1063/1.3691827
@article{ReichJCP2012,
Author = {Reich, Daniel M. and Ndong, Mamadou and Koch, Christiane P.},
Title = {Monotonically convergent optimization in quantum control using {Krotov}'s method},
Journal = jcp,
Year = {2012},
Doi = {10.1063/1.3691827},
Pages = {104103},
Volume = {136},
Number = {10},
}
This will automatically choose the correct key format, journal macro, protect proper nouns in the title and include all required (and only the required) fields.
See get_bibtex.py --help
for more details.
If the script does not recognize a journal (i.e., there is no macro name in the journal field), edit the script and refs.bib
to define an appropriate macro.
Local reference lists¶
Sometimes it is useful to include a list of references separate from the main References page. This is particularly relevant for documents that must stand on their own outside of the rendered HTML documentation:
Fortran or Python modules should list all relevant references for the implemented numerical methods in their module description.
Examples (Jupyter notebooks) should list the publications that they are derived from, and other key references.
Topical overviews may also include reference lists of key literature.
In all cases, each reference in such local reference lists should be prefixed with a :cite:
command to link the main bibliography, followed by a shortened APS-style reference (Last names of at most two authors, or first author “et al.”, abbreviated journal, volume, page, year). E.g.,
* :cite:`PalaoPRA2003` Palao and Kosloff, Phys. Rev. A 68, 062308 (2003)
* :cite:`ReichJCP2012` Reich *et al*., J. Chem. Phys. 136, 104103 (2012)
which renders as:
In Jupyter notebooks an alternative syntax using <cite>
tags with a
data-cite
attribute is required (see below).
Jupyter Notebook Examples¶
The Examples in the QDYN documentation are tutorials designed to teach users the use of QDYN. These should be written as Jupyter notebooks if possible.
Notebooks should stand on their own: a student trying to follow them would read and run them in the Jupyter web interface. However, they are also automatically converted to RST and included in the documentation via the nbsphinx plugin. Often, an example will be simplified simulation or optimization from a published paper. However, when converting a paper to an example, remember that a scientific paper and a QDYN tutorial differ in their goals and audiences.
The tutorial must work, be repeatable, and show results immediately. Focus only on the steps the user needs to take. Notebooks should run through in at most few minutes on a typical workstation.
The goal is to enable “learning by doing” for a new user of QDYN. Write to the level of a Bachelor student.
Focus on concrete steps, not abstract concepts. Provide the minimum necessary explanation. The example does not need to go into details about either the underlying physics or the numerical methods. Those should be reserved for Topical Overviews.
Markdown formatting¶
Jupyter notebooks are a mix of code cells (usually in Python, but possibly other languages, including shell scripts) and their output, and markdown cells. Markdown is a simple markup languages widely used on the web. However, it does not have all the features of the RestructuredText Syntax used for the other parts of the documentation, especially in regard to cross-referencing. The recommended approach is to keep notebooks mostly self-contained, although the nbsphinx plugin that translates the notebooks into RST files for inclusion in the documentation provides some workarounds for linking to other parts of the documentation.
Images¶
Ideally, images in the notebook should be part of the output of a code cell (e.g., using matplotlib). If this is not possible, it is best to use cell attachments. This ensured that the notebook is self-contained (that is, it can be viewed by itself on https://nbviewer.jupyter.org)
Math¶
Inline math in a Jupyter notebook must be written in LaTeX syntax and be enclosed in dollar signs. The nbsphinx plugin will translate this into RST math directives.
In the translated notebook, the custom latex macros like \ket
and
\Op
that are supported throughout any RST document are automatically
available. However, they will not render when viewing the notebook as
standalone document. To enable these macros, define them via \newcommand
in
inline math inside of a markdown cell. For example:
$\newcommand{ket}[1]{\vert#1\rangle}
\newcommand{Op}[1]{\hat{#1}}$
Define only the macros that are actually used in the notebook. The definitions
must match the custom latex macros in the mathjax_config
setting in
doc/sources/conf.py
. Always use semantic macros, e.g. \ket{\Psi}
instead of \vert \Psi \rangle
!
You can put the macro definitions directly underneath the notebook title: they will not be visible in the rendered notebook. The definitions are available in the rest of the notebook, once defined.
For equations, use standard LaTeX/amsmath equation environments like equation
or
align
. Do not use $$...$$
or \\[...\\]
: these work in the Notebook
environment, but do not translate to RST in the rendered QDYN documentation.
Warning
Always check how the notebook renders both standalone in Jupyter and as part of the QDYN documentation!
The system that nbsphinx proposes for automatic equation numbering is not compatible
with the :label:
and :eqref:
system in RST. Avoid equation numbers in Jupyter
notebooks. If you need to, you may use \tag
to set an explicit equation
label, for example \tag{I}
or \tag{☆}
. You may then reference the
equation inside the same notebook by writing out Eq. (I)
or Eq. (☆)
.
The reference will not be a clickable link. If you need a clickable link, you
could use e.g. Eq. ([I](#mjx-eqn-I))
or Eq. ([☆](#mjx-eqn-☆)
. The
#mjx-eqn-I
and #mjx-eqn-☆
anchor names could also be used to reference
the tagged equation from another document. Since the anchor names are very
hacky (undocumented; Sphinx will not be able to help you with broken links),
avoid such references.
Citations¶
Jupyter notebook markdown cells support a special syntax for bibliographic references in a way that is fully compatible with the system for Bibliographic References in the QDYN documentation.
In a Jupyter notebook markdown cell, write e.g.
Ref. <cite data-cite="RissJPB1993">[RissJPB1993]</cite>
The data-cite
value must be a bibtex key in QDYN’s main refs.bib
file.
The contents of the <cite>
tag is arbitrary; it will be shown in the
standalone notebook but is stripped entirely from the rendering of the notebook as
part of the QDYN documentation. When nbsphinx converts the notebook to RST for
inclusion in the documentation, it replaces the entire <cite>
tag with e.g.
:cite:`RissJPB1993
, generating a link to the main bibliography. The content of the <cite>
tag may be empty, in which
case it will be invisible in the standalone notebook, but produce a citation in
the rendered RST.
It is recommended to collect the references cited in a notebook in a “References” section at the end, e.g.,
## References
* <cite data-cite="RissJPB1993"></cite> Riss and Meyer, J. Phys. B 26, 4503 (1993)
* <cite data-cite="ManolopoulosJCP2002"></cite> Manolopoulos, J. Chem. Phys. 117, 9552 (2002)
* <cite data-cite="BainJPB1974"></cite> Bain *et al*., J. Phys. B 7, 2189 (1974)
* <cite data-cite="BlechMaster2018"></cite> A. Blech, Master’s thesis, Universität Kassel (2018)
This is the same format used for Local reference lists elsewhere in the documentation.
How-Tos¶
How-tos are guides for intermediate to advanced users. They assume the user knows what they want to do, but not how. Unlike Tutorials/Examples, they are oriented towards a particular goal or problem, not towards learning. They provide a series of steps to reach that goal.
A how-to guide may be written alongside a new feature in QDYN: anything that affects the config file should usually have some how-to documentation. Beyond that, a how-to should usually be a response to an actual question. If you have a problem with QDYN that took you some effort to figure out, or someone raised a question on QDYN’s issue tracker, that is an ideal candidate for a how-to guide.
If there are multiple ways to do something, a how-to guide should discuss all of those ways and their relative trade-offs. How-tos may be Jupyter notebooks, but generally, prose in a standalone RST file is preferred. This is because how-tos are generally less “complete” than tutorials: including an entire problem setup and analysis in a how-to may detract from its core message. Be concise. How-tos generally do not contain bibliographic references.
The title for a how-to should start with “How To”.
Topical Overviews¶
Topical overviews are in-depth explanations of overarching concepts. These will often be the most difficult and time-consuming part of the documentation to write. They should be written to the level of a scientific publication, and use citations extensively.
The topics of these overviews can vary widely. For example:
An in-depth discussion of a particular numerical method
A review and comparison of different propagation/optimization methods
An record of design decisions for QDYN, or an explanation of data structures: Why things are implemented the way they are
An analysis of a particular physical system and how QDYN is designed to model it
They are the primary way in which detailed knowledge is communicated to future QDYN developers, as well as a source of background information for users. They should not, however, be required reading for just a basic user of QDYN. They should not take the role of how-to documents.
The topical overviews may be adapted from “methods” thesis chapters (or serve as a draft for such a chapter), from a published review paper, lecture notes, the discussions on a QDYN issue or merge request, or the supplementary material of a paper.
Unlike a published paper or thesis, topical overviews can be continuously revised and adapted, and thus represent a living body of knowledge that keeps up with the continuing development of QDYN. They also fulfill a different role than a scientific publication, in that they do not present novel scientific results, but instead maintain knowledge relevant to the use and development of QDYN.
Topical Overviews may list key references in the format described for
Local reference lists. However, especially for reviews that
contain a large number of citations, it should be sufficient to use the
:cite:
role to link to QDYN’s main References page.
Fortran Docstrings¶
Each module must contain docstrings that document the module and each routine, type, or interface in it, which is rendered in the API. These docstrings start with two exclamation points. Specifically, you should use the format discussed below for the various kinds of objects.
Note
The format of using double-exclamation points and tags like @description
and @param
(see below) are specific to Fortran code. In fact, they are
specific to QDYN, inspired in QDYN’s earliest days from JavaDoc.
Python code (QDYN-pylib) must also have docstrings, but uses the popular “Google Style” format, instead of JavaDoc-inspired tags, see also the notes on the QDYN-pylib documentation. Whether Fortran docstring or Python docstrings, all text is parsed in the RestructuredText (RST) markup language.
Module Documentation¶
Immediately after the beginning of the module, there must be a
description of the module, like this example from the qdyn
module:
!! @description:
!! The :mod:`qdyn` module is the central module of the QDYN library. It
!! collects and exports routines and definitions from all other QDYN
!! modules. Therefore, in any program using the QDYN library it is
!! usually sufficient to import the :mod:`qdyn` module with
!!
!! ::
!!
!! use qdyn
!!
!! For advanced purposes, you can still directly import any other
!! module that is part of the QDYN library.
The module description is a good place to explain the structure of the routines contained in the module and how these relate to other routines in QDYN.
If the module implements numerical methods from a particular paper, it should
explicitly list those references, using a format as in the following example
from the qdyn_krotov_mod
module:
!! @description: Implementation of the Krotov optimization algorithm, both
!! first and second order. Which order is used is decided by the value of
!! :config:`oct:method`, which should be either `krotovpk` (first order), or
!! `krotov2` (2nd order).
!!
!! The Krotov algorithm as implemented here follows the description in
!!
!! * :cite:`ReichJCP2012` Reich et al., J. Chem. Phys. 136, 104103 (2012)
!!
!! The first order algorithm is also described, e.g., in
!!
!! * :cite:`PalaoPRA2003` Palao and Kosloff, Phys. Rev. A 68 062308 (2003)
!! * :cite:`KochPRA2004` Koch et al., Phys Rev. A 70 013402 (2004)
!!
Each reference must start with a :cite:
command to link it to the
corresponding entry in the main bibliography in the HTML documentation,
followed by an abbreviated citation. While this duplicates information already
available in the main bibliography, it served to keep the module self-contained
for developers working with the source code directly.
Descriptions must not contain any headings. If necessary, a rubric may be
used, e.g. for a “References” section, as in this example from the
qdyn_mcwf_mod
module:
!! @description:
!! Implementation of the Monte-Carlo Wave Function (MCWF) method.
!!
!! See :ref:`overview-quantum-jump-method` for a detailed overview.
!!
!! .. rubric:: References
!!
!! * :cite:`DumPRA1992` Dum et al., Phys. Rev. A 45, 4879 (1992)
!! * :cite:`MolmerJOSA1993` Mølmer et al., J. Opt. Soc. Am. B 10, 524 (1993)
!! * :cite:`MolmerQSO1996` Mølmer and Castin, Quantum Semiclass. Opt. 8, 49 (1996)
!! * :cite:`PlenioRMP1998` Plenio and Knight, Rev. Mod. Phys. 70, 101 (1998)
The module description should limit itself to the essential description of the module, be concise (a few paragraphs at most), and not contain tutorials, explanations or how-to guides. It may link to such other parts of the documentation, as in the above example.
Subroutine Documentation¶
All routines (subroutines/functions) must have a documentation block directly before the routine declaration, like in the following example:
!! @description: Read two columns from an ascii file.
!! @param: col1 Array for the first column
!! @param: col2 Array for the second column
!! @param: filename File name
subroutine read_ascii_2col (col1, col2, filename)
real (idp), intent(inout) :: col1(:), col2(:)
character (len=*), intent(in) :: filename
...
Although only public routines are shown in the compiled documentation, both
private and public routines should be documented. As a matter of style, the
@param:
docstrings should consist of the component name, followed by at
least two spaces, and then the description, with all the descriptions lined up
as in the example. The descriptions should start with a capital letter.
Interface Documentation¶
If a module uses overloaded routines, there must be a documentation block right before the interface, giving a description. In order to document the implementations of the interface and their parameters, there are two options:
If (and only if!) all implementations have the same number of parameters and the same parameter names, these parameters should be documented with a
@param
docstrings below the interface description. As the parameter-docstrings do not contain information about intent, shape, and other parameters (all the information normally supplied in a variable declaration), a pseudo-declaration can be given in the documentation on a@paramdef
line. For example, from the documentation ofdelete()
:!! @description: Delete a QDYN-type variable. !! !! The routines combined in this interface delete a variable of the !! corresponding type. It is used as follows: !! !! .. code-block:: fortran !! !! call delete(var, thorough) !! !! @param: var The variable to delete. The type of `var` can be any of !! the ones defined in :mod:`qdyn_def_mod`. !! @param: thorough If given as `.true.` recursively zero out all components !! of `var`. All numbers will be set to zero, logicals to !! `.false.`, and strings to the empty string. !! @paramdef: intent(inout) :: var !! @paramdef: logical, optional, intent(in) :: thorough
For variables that vary only in type between the different implementations (
var
in the example), no type information should be given in@paramdef
; make sure that information about the accepted types is contained elsewhere in the docstring.Warning
The
@paramdef
field must only be used inside the documentation for an interface, never for a function or subroutine!If the implementations of the interface differ in the number of parameters, the interface must only have a
@description
, but no@param
or@paramdef
declarations. Instead, every implementation must also have a documentation block, explaining the parameters. The description given for the implementations is not used, but it is still good style to supply it. For example, from the documentation ofread_ascii()
:!! @description: Read data from a csv file. !! !! The columns in the file are separated by spaces. The data is read into !! arrays of reals, reals, one array per column. There can be up to three !! columns. If there are less columns in the file than you try to read, !! the remaining columns are filled with zeros. interface read_ascii module procedure read_ascii_1col, read_ascii_2col, read_ascii_3col end interface !! @description: Read a single columns from an ascii file. !! @param: col Unallocated array for the column !! @param: filename File name subroutine read_ascii_1col (col, filename) real (idp), allocatable, intent(inout) :: col(:) character (len=*), intent(in) :: filename !...
Warning
If the documentation block of an interface defines any @param
or
@paramdef
fields, the documentation blocks of the actual
implementations will not be used. Conversely, if the interface
documentation block has no @param
or @paramdef
fields, each
actual implementation will be fully rendered as part of the resulting
HTML documentation.
Types Documentation¶
Type definitions also need a documentation block, similar to routines:
!! @description: Information about spatial grid in the config file. !! @param: dim Number of spacial dimensions !! @param: r_min Minimum :math:`r`, per dimension !! @param: r_max Maximum :math:`r`, per dimension !! @param: map Mapping, through dimensions !! @param: maptype Type of mapping (``'diff'``, ``'int'``) !! @param: nr Numer of points, per dimension type grid_pt integer :: dim real(idp), allocatable :: r_min(:) real(idp), allocatable :: r_max(:) logical, allocatable :: map(:) character(len=5) :: maptype integer, allocatable :: nr(:) end type
Docstring Formatting¶
Description docstrings may contain multiple paragraphs of text, code blocks, or
display formulas. However, the docstring must start with a single-line
summary, ending with a period. The summary may be on the same line as the
!! @description:
if it is sufficiently short, as in the example above.
Otherwise, there must be a line break after the initial !! @description:
,
and the summary must be entirely in the second line. The reason for the summary
having to be short is that the summaries are rendered in a tabular overview of
the module they’re defined in, so they must be concise.
The summary must be separated from any subsequent paragraphs by a blank line, e.g.:
!! @description:
!! Complex Discrete Fourier Transform.
!!
!! Returns
!!
!! .. math::
!!
!! X(k) = \sum_{j=0}^{n-1} x(j)
!! \exp(\pm 2 \pi\,i\,j\,k\, / n);
!! \quad 0 \leq k \le n
!!
!!
!! where the sign of the exponent is controlled by the
!! `isign` parameter.
!!
!! Note that the inverse of
!!
!! .. code-block:: fortran
!!
!! call cdft(2*n, -1, a, ip, w)
!!
!! is
!!
!! .. code-block:: fortran
!!
!! call cdft(2*n, 1, a, ip, w)
!! do j = 0, 2 * n - 1
!! a(j) = a(j) / n
!! end do
!!
For parameter docstrings that contain multiple paragraphs, the documentation must be aligned in a column:
!! @param: n ``2*n``: data length, with ``n >= 1`` and ``n`` being a
!! power of 2
!! @param: isgn Sign of exponent
!! @param: a ``a(0:2*n-1)``: input/output data
!!
!! input data::
!!
!! a(2*j) = Re(x(j)),
!! a(2*j+1) = Im(x(j)), 0<=j<n
!!
!! output data::
!!
!! a(2*k) = Re(X(k)),
!! a(2*k+1) = Im(X(k)), 0<=k<n
!!
All docstrings use the RST syntax described below. Most importantly for docstrings:
Put inline code snippets in double backticks. Keywords and constants should be enclosed in single backticks, e.g. write
.true.
as`.true.`
and'diff'
as`'diff'`
.Reference function argument names in single backticks:
... !! @param: from_time_i If given, assume that the state is located at time index !! `from_time_i` in the global time grid !! @param: to_time_i If given, time index at which to stop the !! propagation. When doing backward-propagation, !! `to_time_i` should be smaller than `from_time_i` ...
Warning
QDYN’s Sphinx installation is configured so that single backticks and double backticks both render as code-formatted text. However, they are not semantically equivalent: double-backticks indicate “code”, whereas single backticks are the “default role”, which by convention in Sphinx are used for function arguments. For historical reasons, single and double-backticks are not always used consistently in the QDYN documentation, and the distinction between the two is not strictly enforced. However, all new documentation should try to adhere to the semantic distinction between single and double backticks.
Reference other functions/subroutines/interfaces as e.g.
:func:`prop`
. For types, use e.g.:type:`grid_t`
, and for modules e.g.:mod:`qdyn_prop_mod`
. This links to their documentation (prop()
,grid_t
,qdyn_prop_mod
). Note that only public routines can be referenced.Reference config file sections as e.g.
:config:`prop`
and items within a config file section as e.g.:config:`prop:method`
or:config:`~prop:method`
to suppress “prop” in the output: these examples render asprop
,prop:method
, andmethod
, respectively, linking to the corresponding documentation.Surround inline math with dollar signs (as in LaTeX), e.g.
!! @param: L_psi Array of states :math:`\Op{L}_n \Ket{\Psi}` for all of the !! Lindblad operators :math:`\Op{L}_n`.
There must be no whitespace after the opening dollar sign, and no whitespace before the closing dollar sign.
Warning
The “dollar-math” syntax is a docstring-specific extension (implemented in
scripts/docgen.py
) and not part of the RST standard: $\Op{L}_n$
is
equivalent to the standard math-role (:math:`Op{L}_n$`
).
Within docstrings, dollar-math it is preferred over :math:
, for
conciseness. The dollar-math syntax cannot be used in standalone rst files.
The dollar-math syntax only covers the inline math role. For “display math”
(equations), you must use the RST math-directive, both in docstrings and
in standalone rst files. You cannot use $$...$$
or \[...\]
for
display math.
Config File Documentation¶
The docstrings for types whose names in _pt
are used in two contexts: as
a documentation of a type, e.g. grid_pt
, and for the documentation of
the corresponding grid
section in the config file.
The _pt
types should also define a section @examples
, e.g.:
!! @examples:
!! For OCT on moving grids, you will need to set up one grid for the initial
!! state, and one for the target state::
!!
!! grid: system = initial
!! * dim = 1, r_min = -10, r_max = 10, nr = 128, moveable = true
!!
!! grid: system = target
!! * dim = 1, r_min = 0.078740157480315, r_max = 20.078740157480315, &
!! nr = 128, moveable = true
!!
type grid_pt
character(len=label_l) :: label
integer :: dim
real(idp) :: r_min
...
The content of this section will be included in the HTML describing the
grid
config file section, but not in the rendered documentation of
grid_pt
. Keep these examples short. Their purpose is to show which
config file options typically go together. They should not take the role of
how-tos!
Warning
Generally, docstrings from _pt
types should be written such that they
are equally suitable in both documentation contexts (the type documentation
and the config file section documentation). When this is not possible, the
config file documentation takes precedence. That is, when editing the
documentation for a _pt
type, check that the resulting HTML for the
config file documentation reads well.
RestructuredText Syntax¶
RestructuredText (RST) is a markup language that is specifically designed for writing software documentation. Historically it originates from the Python community and is a core component of the Sphinx documentation generator.
The RST syntax is described in the Sphinx documentation at https://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html (and, in full detail, in the docutils documentation linked therein)
Most of RST’s syntax is relatively straightforward, and well-described in the Sphinx documentation. The remainder of this section fills in some of the more subtle points and QDYN-specific considerations.
See also the RST files in doc/sources
for extensive examples that you
should imitate.
Cross-References (Roles)¶
RST’s greatest strength over other markup languages is its ability for cross-referencing symbols (function names, type components, etc.), via roles. This cross-referencing can be made to work even across different projects, via Intersphinx.
References to Fortran objects¶
The QDYN documentation extends Sphinx with a “Fortran” domain
(doc/sources/_extensions/fortran_domain.py
), which is also the default
domain for all references
(except in QDYN-pylib docstrings).
You should use the following as much as possible throughout the documentation
and within docstrings to reference parts of QDYN:
The
:type:
role for any types defined in QDYN’sdef
module, e.g.:type:`grid_t`
which renders as “grid_t
” to link to thegrid
typeThe
:typef:
role for any fields within types, e.g.:typef:`grid_t%coord_type`
which renders as “grid_t%coord_type
” to refer to thecoord_type
field ofgrid_t
.The
:func:
role for any functions or subroutines defined in QDYN. For example,:func:`prop`
refers to theprop()
function inqdyn_prop_mod
. You may use:subr:
instead of:func:
to distinguish subroutines from functions, but the two roles are equivalent and the distinction is not enforced within the QDYN documentation. Note that only public routines can be referenced in this way.The
:mod:
role for any modules that are part of QDYN, e.g.:mod:`qdyn_grid_mod`
, which renders as “qdyn_grid_mod
” to refer to thegrid
module.
For all of the above, the text of the reference may be modified through the
general :role:`text <target>`
syntax
(Same as Cross-referencing syntax
for the Python domain). For example,
[...] which renders as ":mod:`qdyn_grid_mod`" to refer to the
:mod:`grid <qdyn_grid_mod>` module.
from the rst code of the last bullet point above. There, the reference to
qdyn_grid_mod
is rendered with the text “grid
”.
There is no module-scoping for :type:
, :typef:
, or :func:
: All
routines and types must have unique names across the entiry QDYN library.
Sphinx will then automatically identify which module a routine is defined in.
This is different from :func:
in the Python domain, which may use
references with a fully specified path (including modules/submodules).
Note that there is no way to reference the arguments of a routine. You should use single backticks for argument names, e.g.
[...] the `method` argument of the :func:`prop` routine.
which renders as “[…] the method
argument of the prop()
routine.”
Warning
In Python docstrings for the QDYN-pylib API, references to Fortran
objects must be prefixed with :f
, e.g. f:func:`prop`
to refer to prop()
, see the QDYN-pylib documentation
guidelines
References to Python objects¶
In the main QDYN documentation, that is, any RST file or any Fortran
docstrings, routines in the QDYN-pylib qdyn
package can be referenced
by using roles prefixed with :py
, see “Cross-referencing Python objects”
in the Sphinx documentation:
:py:mod:
to reference a Python module, e.g.:py:mod:`qdyn.pulse`
to referenceqdyn.pulse
.:py:class:
to reference a Python class, e.g.:py:class:`qdyn.pulse.Pulse`
to referenceqdyn.pulse.Pulse
.:py:func:
to reference a Python function, e.g.:py:func:`qdyn.pulse.blackman`
to referenceqdyn.pulse.blackman()
.
You may also reference Python objects from the Python standard library or some
important external Python packages (see the intersphinx_mapping
in ./docs/sources/conf.py
):
:py:class:`str`
to reference the standard-librarystr
.:py:class:`qutip.Qobj`
to referencequtip.Qobj
.:py:func:`krotov.optimize.optimize_pulses`
to referencekrotov.optimize.optimize_pulses()
.
Only within Python docstrings, the :py
prefix is implicit (but, conversely,
references to Fortran objects must have a :f
prefix)
Warning
Use the :f
prefix when referencing Fortran objects from Python
docstrings, and the :py
prefix when referencing Python objects from
Fortran docstrings.
References to the config file¶
The QDYN documentation also includes a Sphinx extensions that defines
a :config:
role for referencing the documentation of QDYN’s config file
(doc/sources/_extensions/config_roles.py
).
You may reference e.g. the grid
section of the config file as
:config:`grid`
. A key within a section may be referenced as e.g.
:config:`grid:coord_type`
, which renders as
“grid:coord_type
” to refer to the coord_type
key in the
grid
section of the config file. To drop the section name from the
rendered reference, prefix the section name with a tilde, e.g.
:config:`~grid:coord_type`
which renders as
“coord_type
”. This serves to distinguish the same key name being
valid in different sections. The :config:
role does not support
the :role:`text <target>`
syntax to change the text of the
rendered label. However, you could use the :ref:
role
(“Cross-referencing arbitrary locations”, see
below) to link the documentation for sections of
the config file, e.g.
Read the :ref:`documentation for the grid section of the config file <confsec-grid>`
which would render as “Read the documentation for the grid section of the config file”
References to other sections¶
To link to arbitrary sections in the documentation, the underlying RST file
must include a reference-label immediately before the section header, as
described in “Cross-referencing arbitrary locations”. If
you want to link to any part of QDYN’s documentation
that does not yet have a label, edit the relevant RST file to add it. Then, use
the :ref:
role to reference it. You can use :ref:`reflabel`
to
insert the section heading that the reflabel
refers to, or
:ref:`text <reflabel>`
to use an arbitrary text (cf. the example
at the end of the “References to the config file” section above.)
Note the extra leading underscore in the definition of reference labels: The
label is defined as e.g. .. _reflabel:
, but is referenced as e.g.
:ref:`reflabel`
.
A possible alternative is to link not to a particular section, but to a
particular rst document, using the :doc:
role. This also
allows to link to the documentation of a module when the use of the :mod:
role is not desirable, e.g.
For example, one module may collect all the routines operating on a
particular :doc:`data type </api/structures/def>`.
Bibliographic references¶
References to the Bibliography are made with the :cite:
role, see Bibliographic References.
Hyperlinks¶
As opposed to internal links, hyperlinks to external websites are rather cumbersome in RST (especially to someone coming from Markdown with its straightforward syntax for links).
The following are all recommended ways to specify links in RST:
With a single-word link text:
See the Sphinx_ documentation .. _Sphinx: https://www.sphinx-doc.org
The link text also serves as a “link label”. The link label definition can be anywhere, e.g. at the end of the section or the end of the document. Note the trailing underscore in the link text, and the leading underscore in the label definition. The syntax is roughly equivalent to Markdown’s “implicit links” (if it wasn’t for those easy-to-forget underscores)
With a multi-word link text:
See the `Sphinx documentation`_ .. _Sphinx documentation: https://www.sphinx-doc.org
The link text must be enclosed in backticks (but no backticks in the label definition). Again, this roughly corresponds to Markdown’s “implicit links”
With an “inline” link:
See the `Sphinx documentation <https://www.sphinx-doc.org>`_
This is for links that only occur once. No label definition is required. This is roughly equivalent to an “inline link” in Markdown (but don’t forget the trailing underscore)
With a direct URL:
See https://www.sphinx-doc.org
The URL will also be the link text. Very straightforward, but rarely appropriate.
With an arbitrary link text and arbitrary link label:
See the `Sphinx documentation <sphinxdocs_>`_ .. _sphinxdocs: https://www.sphinx-doc.org
Note the two underscores: one trailing the link label, and one after the backtick at the end of the link specification. This is closest Markdown’s “reference links”. Use this if the same link occurs multiple time with different link text, or if the link text is more than a few words.
There are even more cumbersome (non-recommended) ways to specify hyperlinks that we won’t get into here. Also, unfortunately RST does not support nested inline-markup. That is (unlike in Markdown), there is no straightforward way to format parts the link text in italics, bold, or as code – cf. the RST Gotchas. A possible workaround is RST’s text replacement feature, but that really pushes the limits of sanity.
Math¶
Sphinx/RST has excellent built-in support for mathematics, using LaTeX-math-syntax.
Inline math is done with the math-role, e.g. :math:`x^2`
will render as “\(x^2\)”.
In docstrings only, you may enclose inline mathematics in dollar signs
($x^2$
) instead of using the math role.
For display math (equations), use the math-directive. You have the option to use equation numbers and references, e.g.:
.. math::
:label: EqSchrödinger
\ii \hbar \frac{\partial}{\partial t} \ket{\Psi(t)} = \Op{H} \ket{\Psi(t)}
The Schrödinger Equation :eq:`EqSchrödinger` describes the time
evolution of a quantum state :math:`\ket{\Psi(t)}`.
This renders as:
If your editor supports it, use a non-breaking space before the :eq:
(<ctrl>-k <space> <space>
in vim, <ctrl>-q 240
in Emacs, corresponding
to ~
in LaTeX).
Equation numbers run consecutively throughout the entire documentation. Thus, you can reference equations on other pages.
The contents of the math directive should be indented with four spaces.
QDYN defines some semantic macros for quantum mechanics in the mathjax_config
setting in doc/sources/conf.py
.
These include:
\ee
for the Euler unit \(\ee\)\ii
for the imaginary unit \(\ii\)\dd
for the differential \(\dd\)\bra{\Psi}
for the \(\bra{\Psi}\) (or\Bra
for a macro that adjusts height)\ket{\Psi}
for the \(\ket{\Psi}\) (or\Ket
for a macro that adjusts height)\Braket{\Psi}{\Psi}
for simple bra-kets \(\Braket{\Psi}{\Psi}\)\Op{H}
for the operator \(\Op{H}\)\norm{\Op{H}}
for the norm \(\norm{\Op{H}}\) (or\Norm
for a macro that adjusts height)\avg{\Op{H}}
for the average/expectation value \(\avg{\Op{H}}\) (or\Avg
for a macro that adjusts height)\Abs{x}
for the absolute value \(\Abs{x}\) (not to be confused with the lower-case\abs
which renders as e.g. \(\abs(x)\))\AbsSq{\ket{x}}
for the absolute-square \(\AbsSq{x}\)\Liouville
for the Liouville symbol \(\Liouville\)\DynMap
for the dynamical map symbol \(\DynMap\)\identity
for the identity \(\identity\)\Complex
for the set of complex numbers \(\Complex\)\Real
for the set of real numbers \(\Real\)\Integer
for the set of natural numbers \(\Integer\)
You may extend these definitions as necessary.
Warning
Use semantic macros wherever possible. Most importantly, do not set
\(\ket{\Psi}\) as \vert \Psi \rangle
or \(\Op{H}\) as \hat{H}
.
You may still use \langle
, \vert
, and \rangle
for bra-ket
expressions that \Braket
cannot express accurately. Make sure to use the
appropriate lower- or upper-case macro for the proper height of delimiters.
In text, usually e.g. \ket
should be used instead of \Ket
.
Code and pre-formatted text¶
Enclose inline code in double backticks, e.g.
``method="cheby"``
, which renders to method="cheby"
.
Longer code snippets use the code-block-directive, which can have syntax highlighting for any language that Pygments understands.
For example,
.. code-block:: fortran
call cdft(2*n, 1, a, ip, w)
do j = 0, 2 * n - 1
a(j) = a(j) / n
end do
renders as:
call cdft(2*n, 1, a, ip, w) do j = 0, 2 * n - 1 a(j) = a(j) / n end do
If no syntax-highlighting or other advanced options are desired, ..
code-block::
can be shortened to ::
. Also, ending a paragraph with ::
,
followed by indented code will replace the double-colon with a single colon and
format the code without syntax highlighting.
The content of the directive should be indented by four spaces relative to the
..code-block::
or ::
(while Fortran code in QDYN is still usually indented
by only two spaces, as in the above example).
Section headers and links¶
The QDYN documentation uses sections (generally the title of one RST document), sub-section , sub-sub-section and (rarely) a 4th-level “paragraph” heading.
These are formatted by underlining with level-specific characters.
.. _my-section-label:
Section
=======
.. _my-sbsection-label:
Subsection
----------
Subsubsection
^^^^^^^^^^^^^
Paragraph Section
"""""""""""""""""
The underline must be at least as long as the text.
“Part-level” (#
underline) or “chapter-level” (*
underline) headings
should not be used. As in the above example, sections (of any level) can have
a section label so that they can be referenced with the :ref:
role.
Docstring @description
texts must not contain any headings. If necessary,
you may instead use a rubric, e.g. for a “References” section on a module
description.
For long RST documents with lots of subheadings (like this very document), it can be useful to insert a local table of contents. This is done with
.. contents:: Contents
:local:
:depth: 2
underneath the main header.
On rare occasions, for linking within a single document, it might be necessary to define a link target to a particular element or paragraph. This can be done with a container directive, e.g.
.. container:: refs-bib-link
:name: refs-bib-link
You may download :download:`refs.bib </refs.bib>`
The container class-name and :name:
should be the same. You can then link to the
container with e.g.
See the `downloadable refs.bib file<#refs-bib-link>`_.
Documentation Checklist¶
The following checklists serve as a guide when adding to or modifying any parts of the documentation.
Docstrings¶
Use the following checklist for the docstrings in the QDYN source code which get rendered into the API documentation. Remember that docstrings are reference material and should be written in a strictly information-oriented style. They target QDYN developers at any level. Only describe (“What?”); explanations (“Why?”) or extended usage discussion (“How?”) should be reserved for other parts of the documentation such as Topical Overviews and How-tos. The API reference documentation is generally not sufficient by itself. It must be augmented by how-to guides, examples, and topical overviews to provide broader context.
Module has a description that contains
The purpose of module
The organization of routines in the module to highlight the most important routines
If appropriate, a local list of references
Other parts of the documentation also cover the functionality implemented in the module. If not, open an issue that a how-to guides/example/topical overview needs to be added.
Every routine, type, or interface in the module is documented (even when private).
For every routine:
Description starts with a summary line that fits on one line (after
!! @description:
or on a new line after!! @description:
)Summary line ends with a period
Summary line is separated from subsequent paragraphs with a blank line
The description is accurate, complete, and understandable to a new user of QDYN, but also concise.
Every parameter in the function has a complete, understandable but concise docstring
All the parameter docstrings are aligned (except for very long parameter names, which may use a “hanging indent”)
All inline math is set with dollar signs and renders correctly in the HTML
All math uses proper domain-specific macros such as
\ket
All references to other parameters are enclosed in single backticks
Values like
.true.
or strings are enclosed in single backticksOther expressions that should be rendered as code are enclosed in double backticks
Any references to other modules, other routines or config file options use the proper role and link correctly in the rendered HTML.
Code-blocks are set correctly with an RST
..code-block::
directive, and use syntax highlighting if appropriate
Check the rendered HTML documentation for the module API
Sphinx reports no errors
All hyperlinks resolve correctly in the rendered HTML
All equations render properly in MathJax
Bibliographic entries link properly to the main References page
The summary table is readable and provides a useable overview
If the docstring is for a
*_pt
data structure, check the Config File reference documentation to ensure that it reads well and that any examples render properly.
How-Tos¶
Use the following checklist when writing how-tos. Remember that how-tos are intended to be goal-oriented: A user knows what they want to do, but not how. How-to guides should be written as RST documents, not Jupyter notebooks. This encourages conciseness: how-to guides (unlike example notebooks) are generally not complete examples, and skip the setup or analysis of an example.
Targets a user with basic familiarity of QDYN and the underlying physics
Written as an RST document
Title starts with “How To”
Solves a particular problem or addresses a specific question or concern (an “FAQ”)
Focuses on achieving a practical goal
Contains a list of steps that need to be followed in order
As short a possible
Does not explain concepts or design decisions. These should be written as topical overviews.
Discusses different options for solving a problem and their relative trade-offs
Provides example code snippets but not full examples
Check the rendered how-to in the HTML documentation to ensure proper formatting.
Examples¶
Use the following checklist when writing example notebooks. Remember that examples are learning-oriented. They should teach a novice user a possible usage of QDYN in a particular context. Ideally, most papers written using QDYN should be worked into a tutorial. However, when writing a tutorial from a published paper or thesis, simplify the example as much as possible to make it more accessible. Examples must be written as a Jupyter notebook to ensure that the example is complete, reproducible, and provides immediate feedback.
Targets a beginner with only basic familiarity of QDYN (the introductory tutorial) and the underlying physics
Written as a Jupyter notebook.
Includes a citation of the paper from which the example is derived
Self-contained: must render correctly on https://nbviewer.jupyter.org
Includes relevant equations, e.g. the system Hamiltonian, using semantic tex macros
As simple and accessible as possible
Uses high-level tools as much as possible, e.g. QuTiP/qdynpylib to set up the problem,
qdyn_proj_traj
andqdyn_optimize
to perform propagation and optimization.Visualizes results with matplotlib
Does not explain anything that is not absolutely necessary to follow the tutorial.
Avoids discussions of alternative approaches as much as possible.
Check the rendered example in the HTML documentation to ensure proper formatting.
Topical Overviews¶
Use the following checklist when writing topical overviews. Remember that topical overviews are understanding-oriented explanations. Topical overviews collect the in-depth knowledge around the development and usage of QDYN. It is intended to transfer knowledge to future generations of students. Compared to a published review paper or thesis, topical overviews are living documents that can keep up with new developments. The QDYN documentation does need many topical overviews, but those that exist should be written to the highest possible standard. The overviews should take a high-level view and strive for completeness. A comparative overview of all propagation methods is preferable to an overview of just one single method. Thus, they will tend to be relatively long and contain sub-sections. Topical overviews can be opinionated. They should capture expert developer experience. They may have a narrative component of how QDYN evolved over time.
Targets a user with a good understanding of QDYN and the underlying physics
Written as an RST document
Contains in-depth explanations of numerical methods, including full derivations, at the level of a published review paper or thesis chapter
Documents design decisions for data structures and methods in QDYN.
Extensively cites existing literature
Avoids examples or usage guidelines. These are better written as example notebooks or how-to guides.
May extend beyond QDYN, e.g. comparing with other tools and methods
Check the rendered HTML documentation to verify that math is rendered correctly and bibliographic references resolve to the References page.