Writing Documentation#

User Manual#

The user manual (including the page you are currently reading) is generated with Sphinx using the reStructuredText syntax. Here, you will find some examples that help you write your own documentation entry (take a look at the “page source” to see the code behind the text).

Examples#

Tables of contents are implemented like this:

Notes, warnings, and hints can be included thusly:

Note

This is a note.

Warning

This is a warning.

Hint

This is a hint.

Math and Formulae#

Mathematical expressions can be included like so:

Let \(x \rightarrow \infty\), then

\[\lim_{x \rightarrow \infty} \frac{1}{x} = 0\]

Code snippets and blocks#

Code snippets like std::algorithm or cell_manager are indicated like this. Code blocks can be included like this:

def id(x):
    return x

Python Documentation Bits#

The typical use case of Sphinx is rendering a documentation of Python modules.

.. autoclass:: utopya.multiverse.Multiverse
    :noindex:

Alteratively, use :py:<role>: and a fully qualified module name to refer to the corresponding object in another documentation.

Doxygen Documentation Bits#

Wondering what the class template Cell looks like? Well, here you go:

template<typename Traits>
class Cell : public Utopia::Entity<Cell<Traits>, Traits>#

A cell is a slightly specialized state container.

It can be extended with the use of tags and can be associated with so-called “custom links”. These specializations are carried into the cell by means of the CellTraits struct. A cell is embedded into the CellManager, where the discretization allows assigning a position in space to the cell. The cell itself does not need to know anything about that …

Template Parameters

Traits – Valid Utopia::EntityTraits, describing the type of cell

Public Types

using Self = Cell<Traits>#

The type of this cell.

using State = typename Traits::State#

The type of the state.

Public Functions

inline Cell(const IndexType id, const State initial_state)#

Construct a cell.

The Logging Module#

This is a documentation of the entire Logging module:

group Logging

Utility functions for all logging output based on the spdlog backend.

All output of the simulation backend is intended to be controlled via loggers. Loggers are implemented using spdlog (see https://github.com/gabime/spdlog). Regular output via the standard pipes std::cout and std::cerr is strongly discouraged.

Utopia generates three types of loggers: One logger for Data I/O functions, one for Core (backend) functions, and one for each model instance. The Utopia::Model base class holds a logger instance which should be used for information on the current model. To write log messages from within Data I/O or Core backend functions, the respective logger first has to be retrieved. This is achieved by using spdlog::get (https://github.com/gabime/spdlog/wiki/2.-Creating-loggers). The names for the two loggers are exported within the Utopia namespace. All log levels are handled through the input configuration files.

The Utopia::PseudoParent automatically creates the utility loggers. For executables without Models (like tests), the loggers have to be created explicitly by manually calling Utopia::setup_loggers.

Functions

inline std::shared_ptr<spdlog::logger> init_logger(const std::string name, const spdlog::level::level_enum level, const bool throw_on_exist = true)#

Initialize a logger with a certain name and log level.

If the logger already exists, issue a warning and only set the log level. Optionally, this function can throw an exception.

Parameters
  • name – Name of the logger. This is also the registered logger name.

  • level – Level of the logger. See spdlog::level::level_enum

  • throw_on_exist – Throw an exception if the logger exists

inline void setup_loggers(const spdlog::level::level_enum level_core = spdlog::level::warn, const spdlog::level::level_enum level_data_io = spdlog::level::warn, const spdlog::level::level_enum level_data_mngr = spdlog::level::warn, const std::string &log_pattern = "")#

Set up and register the global loggers and set the global log pattern.

Utopia employs the following global loggers:

  • core: for the Core module

  • data_io: for the Data I/O module in general

  • data_mngr: for the DataIO::DataManager

They can be retrieved with the spdlog::get(name) function, where ‘name’ can be one of the ‘log_’ strings stored in the Utopia namespace.

This function only (re)sets the log levels if the loggers already exist.

Parameters
  • level_core – Log level of the core logger

  • level_data_io – Log level of the data_io logger

  • level_data_mngr – Log level of the data_mngr logger

  • log_pattern – The global log pattern. If empty, a pre-defined log pattern will be set instead of the spdlog default.

Variables

const std::string log_core = "core"#
const std::string log_data_io = "data_io"#
const std::string log_data_mngr = "data_mngr"#

C++ Documentation#

The C++ documentation is created with Doxygen. If you want to contribute to Utopia, you will need to write documentation, too. For this, we provide coding guidelines, as well as the additional information below.

How to write the Doxygen documentation#

Doxygen is a neat and widely used tool to document C++ source code. The documentation is based on docstrings that are attached to the actual source code they should document using the comment syntax of the respective programming language.

Whenever you write a new function, class, and even when you only add a new class member or method, write at least a \brief description, such that this object can later be referred to via the documentation. Notice that you can also add docstrings to a certain object anywhere in the source code, if need be.

Using Doxygen Modules#

Documentations for large code bases quickly become confusing. By default, Doxygen groups documentation pages by class names and namespaces. However, a certain set of classes typically closely interact within one, or even across several, namespaces. For documenting these groupings and interactions, Doxygen implements Modules.

Somewhere in the source code, one may define a module using \defgroup <label> <title>, or \addtogroup <label> together with a set of brackets { ... }. Single objects can be added to an existing group with \ingroup <label>. Modules themselves can be nested, i.e., a module can be grouped into another module.

For documenting modules, we use modules.dox files inside the respective source directory. Doxygen always uses the C++ syntax, therefore all documentation inside these files must have the syntax of a C++ comment.

Python Documentation#

When developing utopya or any other part of the Utopia frontend, you will also have to write documentation of the Python code. For this, please consult and follow the coding guidelines.