1.6.0
Coding guidelines

Table of contents

Configure git

First of all, configure git with your real name and email address, as already described here:

git config --global user.name "Name(s) Surname(s)"
git config --global user.email "my.email@address.com"

Note: the settings above must be formatted properly, i.e. names and surname(s) should start with an uppercase letter and be separated by a (single) space character.

Note: please make sure that these settings are consistent on all computers you are using lifex on.

How to fix Invalid author errors

One of the most common problems experienced by lifex developers is the check indentation job failing for your branch with the following error.

$ scripts/format/check_indentation
Invalid author 'Nickname91' without firstname and lastname

This is because you probably skipped the git configuration steps.

The recommended way to solve the issue consists of:

  • running the git config [...] commands reported above;
  • using git filter-branch command. It allows you to batch-process all commits in your branch with a script. Run the below sample script on your branch (filling in real values for the old and new email and name).

WARNING: the following procedure rewrites the history of your branch, creating new commit objects along the way! Use it with extreme care and only if you're aware of the side effects. Make sure to create a backup of your branch modifications before proceeding.

git filter-branch --force --env-filter '
OLD_NAME="Nickname91"
CORRECT_NAME="Name Surname"
CORRECT_EMAIL="name.surname@polimi.it"
if [ "${GIT_COMMITTER_NAME}" = "${OLD_NAME}" ]
then
export GIT_COMMITTER_NAME="${CORRECT_NAME}
export GIT_COMMITTER_EMAIL="${CORRECT_EMAIL}
fi
if [ "${GIT_AUTHOR_NAME}" = "${OLD_NAME}" ]
then
export GIT_AUTHOR_NAME="${CORRECT_NAME}"
export GIT_AUTHOR_EMAIL="${CORRECT_EMAIL}"
fi
' --tag-name-filter cat

Then the remote branch must be overwritten:

git push --force origin my_branch_name

If that branch is being used on other machines, the usual git pull origin my_branch_name won't work to properly fetch the updates. Run the following commands instead.

git checkout main
git branch -D my_branch_name
git pull
git checkout my_branch_name

Development rules

Here are a few steps to remember before you start to code.

  1. Always keep your branch up-to-date with the main branch by running git pull origin main.
  2. Check periodically for recent relevant changes by refering to the changelog.
  3. Always document the code you write. Don't be rough: a wrong documentation is worse than no documentation at all. Also, provide the proper references.

Run make doc from your build folder to generate the documentation to the doc subdirectory (requires Doxygen and graphviz). Please check that make doc runs without warnings or errors and open /path/to/lifex/build/doc/html/index.html with a web browser to check that the documentation you wrote is typeset and displayed correctly.

  1. Always compile and run your model in debug mode before opening a merge request or an issue.
  2. Always run and/or update the testsuite to ensure that your modifications did not break any previous functionality and are backward-compatible.
  3. Questions? Check the documentation first. Can't find the answer? Before you assume, ask.

Archived branches

Stall branches, i.e. those that are not ready to merge and show no activity within 4 months, will be archived and deleted.

Archived branches can be fetched and inspected with:

# List archived branches in the remote.
git ls-remote origin refs/archive/*
# List archived branches available locally.
git for-each-ref origin refs/archive/*
# Fetch archived branches from the remote.
git fetch origin refs/archive/*:refs/archive/*
# Checkout an archived branch available locally.
git checkout refs/archive/archived_branch_name

Coding conventions

lifex coding rules

  1. Include directives should be added only where strictly needed (either .hpp or .cpp files).
  2. Never use raw pointers (like int *) or the keyword new. For memory handling use std::unique_ptr (with std::make_unique) or std::shared_ptr (with std::make_shared), instead.
  3. Function inputs should be declared as const references, e.g. fun(const type& ...), unless needed otherwise.
  4. Polymorphic base classes should always provide a virtual destructor.
  5. The Core class is implemented to provide a common interface for parameter handling and to some utilities such as MPI communicator, rank and size, a parallel standard output object, a parallel error output object and a timer output. Additionally, the CoreModel class provides a common interface for parameter handling. If your class needs any of such functionalities it should publicly inherit from Core or CoreModel.
  6. All output should be redirected to the lifex::Core::prm_output_directory folder.
  7. Every class inheriting from CoreModel must override the following methods:
    public:
    virtual void
    declare_parameters(ParamHandler &params) const override;
    virtual void
    parse_parameters(ParamHandler &params) override;
    // Not mandatory: the abstract implementation does nothing by default.
    virtual void
    run() override;
    If the class depends on other core models whose parameters have to be exposed externally, such dependencies should be declared as class members (or smart pointers, if they are not default constructable).
  8. The declare_parameters() method should set the verbosity of parameters and sections (as explained in lifex::VerbosityParam and lifex::Core::prm_verbosity_param), e.g.:
    void
    MyClass::declare_parameters(ParamHandler &params) const
    {
    params.enter_subsection_path(prm_subsection_path);
    {
    params.enter_subsection("Very important parameters");
    {
    // ...
    }
    params.leave_subsection();
    params.set_verbosity(VerbosityParam::Standard);
    {
    params.enter_subsection("Less important parameters");
    {
    // ...
    }
    params.leave_subsection();
    }
    params.reset_verbosity();
    params.set_verbosity(VerbosityParam::Full);
    {
    params.enter_subsection("Advanced usage parameters");
    {
    // ...
    }
    params.leave_subsection();
    }
    params.reset_verbosity();
    }
    params.leave_subsection_path();
    }
  9. The parse_parameters() method should parse all parameters declared above, as well as to verify the correctness and meaningfulness of the input parameters (possibly throwing proper exceptions):
    void
    MyClass::parse_parameters(ParamHandler &params) const
    {
    params.parse();
    params.enter_subsection_path(prm_subsection_path);
    {
    // ...
    AssertThrow(!prm_boundary_ids.empty(),
    ExcMessage("List of boundary IDs cannot be left empty.");
    // ...
    AssertThrow(prm_boundary_ids.size() == prm_bcs_type.size(),
    ExcMessage("The list of boundary IDs and of BC types "
    "must have the same length.");
    // ...
    }
    params.leave_subsection_path();
    }
  10. Class members storing the value of parameters read from file should be prefixed with prm_ and enclosed in a Doxygen group named Parameters read from file..
  11. Doxygen comments should start with a @ rather than with a \ (e.g. @param).
  12. Always start the main() function with lifex initialization:
    lifex::lifex_init lifex_initializer(argc, argv, 1);
    Class used to initialize lifex Core functionalities.
    Definition: init.hpp:53
  13. Always start relevant methods within your classes with
    TimerOutput::Scope timer_section(timer_output,
    prm_subsection_path +
    " / What is done here");
    #define timer_output
    Shorthand for dereferenced lifex::Core::timer_output_ptr.
    Definition: core.hpp:161
    This will automaticaly generate timing reports for the code you write.

Install clang-format

clang-format is required to automatically indent and properly format the source files. The corresponding style file is /path/to/lifex/.clang-format.

In order to install clang-format-14.0.0, run the /path/to/lifex/scripts/format/download_clang-format script.

This will download a statically-linked binary of clang-format-14.0.0 and install it under /path/to/lifex/scripts/format/clang-14.0.0/bin.

It is recommended to add the previous folder to your PATH environment variable, e.g. by adding the following line to your ${HOME}/.bashrc file (or equivalent).

export PATH="/path/to/lifex/scripts/format/clang-format-14.0.0/bin:${PATH}"

Note: in case of binary incompatibility with your system, use the /path/to/lifex/scripts/format/compile_clang-format script instead.

lifex coding style

  1. lifex follows the deal.II coding conventions: please read them carefully before coding.
  2. Run /path/to/lifex/scripts/format/static_analysis from lifex source directory before any commit to perform a static analysis of the code, relying upon the cppcheck and cpplint tools.
  3. Run /path/to/lifex/scripts/format/indent_all from lifex source directory before any commit to indent all files (or /path/to/lifex/scripts/format/indent to process only new files or files that have changed since last merge commit). Two equivalent build targets make indent_all and make indent are available.
  4. In order to make sure that the indentation is correct for all of your commits, you might want to setup a pre-commit hook. One way to do so is to run cp ./scripts/format/pre-commit .git/hooks/pre-commit && chmod u+x .git/hooks/pre-commit from your /path/to/lifex directory.

Note: the automatic indentation script makes use of the clang-format package.

When a merge request is open, the copyright notice and its formatting are also checked. Please run /path/to/lifex/scripts/format/update_copyright from lifex source directory to update the copyright notice.

Configure your editor

Use with clang-format

Different plugins and extensions are available to configure your favorite editor for formatting the code you write using clang-format:

  • Emacs:
    1. Download clang-format.el.
    2. Add the following lines to your ~/.emacs file (toggle comments on one of the two define-key lines depending on your needs):
      ;; clang-format.
      (load "/path/to/clang-format.el")
      (require 'cc-mode)
      ;; Uncomment the following line to format the current selection.
      ;; (define-key c-mode-base-map (kbd "<tab>") 'clang-format-region)
      ;; Uncomment the following line to format the current file.
      (define-key c-mode-base-map (kbd "<tab>") 'clang-format-buffer)
    3. Use <TAB> to format the current selection or file.
  • Vim (clang-format.py)
  • Atom
  • Sublime Text:
    1. Install Clang Format via Package Control.
    2. Change user setting of the package (Preferences -> Package Settings -> Clang Format -> Settings - User) as follows:
      {
      "binary": "/path/to/clang-format",
      "style": "File",
      "format_on_save": true
      }
    3. Use <CTRL+ALT+A> to format the current selection or <CTRL+S> to save and format the current file.
  • Eclipse
  • VSCode

Syntax highlight for parameter files

Different plugins and extensions are available to configure your favorite editor for indenting or highlighting deal.II parameter (.prm) files, which are used throughout lifex: