3. Style Guide for OpenMC¶
In order to keep the OpenMC code base consistent in style, this guide specifies a number of rules which should be adhered to when modified existing code or adding new code in OpenMC.
3.1. C++¶
3.1.1. Automatic Formatting¶
To ensure consistent styling with little effort, this project uses clang-format. The repository contains a
.clang-format
file that can be used to automatically apply a consistent
format. The easiest way to use clang-format is to run
tools/dev/install-commit-hooks.sh
to install a post-commit hook that gets
executed each time a commit is made. Note that this script requires that you
already have clang-format installed. In addition, you may want to configure your
editor/IDE to automatically runs clang-format using the .clang-format
file
whenever a file is saved. For example, Visual Studio Code includes
support for running clang-format.
Note
OpenMC’s CI uses clang-format version 15. A different version of clang-format may produce different line changes and as a result fail the CI test.
3.1.2. Miscellaneous¶
Follow the C++ Core Guidelines except when they conflict with another guideline listed here. For convenience, many important guidelines from that list are repeated here.
Conform to the C++17 standard.
Always use C++-style comments (//
) as opposed to C-style (/**/
). (It
is more difficult to comment out a large section of code that uses C-style
comments.)
Do not use C-style casting. Always use the C++-style casts static_cast
,
const_cast
, or reinterpret_cast
. (See ES.49)
3.1.3. Source Files¶
Use a .cpp
suffix for code files and .h
for header files.
Header files should always use include guards with the following style (See SF.8):
#ifndef OPENMC_MODULE_NAME_H
#define OPENMC_MODULE_NAME_H
namespace openmc {
...
content
...
}
#endif // OPENMC_MODULE_NAME_H
Avoid hidden dependencies by always including a related header file first, followed by C/C++ library includes, other library includes, and then local includes. For example:
// foo.cpp
#include "foo.h"
#include <cstddef>
#include <iostream>
#include <vector>
#include "hdf5.h"
#include "pugixml.hpp"
#include "error.h"
#include "random_lcg.h"
3.1.4. Naming¶
Struct and class names should be CamelCase, e.g. HexLattice
.
Functions (including member functions) should be lower-case with underscores,
e.g. get_indices
.
Local variables, global variables, and struct/class member variables should be
lower-case with underscores (e.g., n_cells
) except for physics symbols that
are written differently by convention (e.g., E
for energy). Data members of
classes (but not structs) additionally have trailing underscores (e.g.,
a_class_member_
).
The following conventions are used for variables with short names:
d
stands for “distance”E
stands for “energy”p
stands for “particle”r
stands for “position”rx
stands for “reaction”u
stands for “direction”xs
stands for “cross section”
All classes and non-member functions should be declared within the openmc
namespace. Global variables must be declared in a namespace nested within the
openmc
namespace. The following sub-namespaces are in use:
openmc::data
: Fundamental nuclear data (cross sections, multigroup data, decay constants, etc.)openmc::model
: Variables related to geometry, materials, and talliesopenmc::settings
: Global settings / optionsopenmc::simulation
: Variables used only during a simulation
Accessors and mutators (get and set functions) may be named like
variables. These often correspond to actual member variables, but this is not
required. For example, int count()
and void set_count(int count)
.
Variables declared constexpr or const that have static storage duration (exist
for the duration of the program) should be upper-case with underscores,
e.g., SQRT_PI
.
3.1.5. Documentation¶
Classes, structs, and functions are to be annotated for the Doxygen documentation generation tool. Use the \
form of
Doxygen commands, e.g., \brief
instead of @brief
.
3.2. Python¶
Style for Python code should follow PEP8.
Docstrings for functions and methods should follow numpydoc style.
Python code should work with Python 3.8+.
Use of third-party Python packages should be limited to numpy, scipy, matplotlib, pandas, and h5py. Use of other third-party packages must be implemented as optional dependencies rather than required dependencies.
Prefer pathlib when working with filesystem paths over functions in the os module or other standard-library modules. Functions that accept arguments that represent a filesystem path should work with both strings and Path objects.