\(\renewcommand{\AA}{\text{Å}}\)
3.4. LAMMPS programming style
The aim of the LAMMPS developers is to use a consistent programming style and naming conventions across the entire code base, as this helps with maintenance, debugging, and understanding the code, both for developers and users. This page provides a list of standard style choices used in LAMMPS. Some of these standards are required, while others are just preferred. Following these conventions will make it much easier to integrate your contribution. If you are uncertain, please ask.
The files pair_lj_cut.h, pair_lj_cut.cpp, utils.h, and utils.cpp may serve as representative examples.
3.4.1. Include files (varied)
Header files that define a new LAMMPS style (i.e. that have a
SomeStyle(some/name,SomeName);
macro in them) should only use the include file for the base class and otherwise use forward declarations and pointers; when interfacing to a library use the PIMPL (pointer to implementation) approach where you have a pointer to a struct that contains all library specific data (and thus requires the library header) but use a forward declaration and define the struct only in the implementation file. This is a strict requirement since this is where type clashes between packages and hard-to-find bugs have regularly manifested in the past.Header files, especially those defining a “style”, should only use the absolute minimum number of include files and must not contain any
using
statements. Typically, that would only be the header for the base class. Instead, any include statements should be put in the corresponding implementation files and forward declarations be used. For implementation files, the “include what you use” principle should be employed. However, there is the notable exception that when thepointers.h
header is included (or the header of one of the classes derived from it), certain headers will always be included and thus do not need to be explicitly specified. These are: mpi.h, cstddef, cstdio, cstdlib, string, utils.h, vector, fmt/format.h, climits, cinttypes. This also means any such file can assume that FILE, NULL, and INT_MAX are defined.Class members variables should not be initialized in the header file, but instead should be initialized either in the initializer list of the constructor or explicitly assigned in the body of the constructor. If the member variable is relevant to the functionality of a class (for example when it stores a value from a command line argument), the member variable declaration is followed by a brief comment explaining its purpose and what its values can be. Class members that are pointers should always be initialized to
nullptr
in the initializer list of the constructor. This reduces clutter in the header and avoids accessing uninitialized pointers, which leads to hard to debug issues, class members are often implicitly initialized toNULL
on the first use (but not after a clear command). Please see the filesreset_atoms_mol.h
andreset_atoms_mol.cpp
as an example.System headers or headers from installed libraries are included with angular brackets (example:
#include <vector>
), while local include files use double quotes (example:#include "atom.h"
)When including system header files from the C library use the C++-style names (
<cstdlib>
or<cstring>
) instead of the C-style names (<stdlib.h>
or<string.h>
)The order of
#include
statements in a filesome_name.cpp
that implements a classSomeName
defined in a header filesome_name.h
should be as follows:#include "some_name.h"
followed by an empty lineLAMMPS include files e.g.
#include "comm.h"
or#include "modify.h"
in alphabetical order followed by an empty lineSystem header files from the C++ or C standard library followed by an empty line
using namespace LAMMPS_NS
or other namespace imports.
3.4.2. Whitespace (preferred)
Source files should not contain TAB characters unless required by the syntax (e.g. in makefiles) and no trailing whitespace. Text files should have Unix-style line endings (LF-only). Git will automatically convert those in both directions when running on Windows; use dos2unix on Linux machines to convert files to Unix-style line endings. The last line of text files include a line ending.
You can check for these issues with the python scripts in the “tools/coding_standard” folder. When run normally with a source file or a source folder as argument, they will list all non-conforming lines. By adding the -f flag to the command line, they will modify the flagged files to try to remove the detected issues.
3.4.3. Placement of braces (strongly preferred)
For new files added to the “src” tree, a clang-format configuration file is provided under the name .clang-format. This file is compatible with clang-format version 8 and later. With that file present, files can be reformatted according to the configuration with a command like: clang-format -i new-file.cpp. Ideally, this is done while writing the code or before a pull request is submitted. Blocks of code where the reformatting from clang-format yields hard-to-read or otherwise undesirable output may be protected with placing a pair // clang-format off and // clang-format on comments around that block.
3.4.4. Miscellaneous standards (varied)
I/O is done via the C-style stdio library and not iostreams.
Do not use so-called “alternative tokens” like
and
,or
,not
and similar, but rather use the corresponding operators&&
,||
, and!
. The alternative tokens are not available by default on all compilers.Output to the screen and the logfile should use the corresponding FILE pointers and only be done on MPI rank 0. Use the
utils::logmesg()
convenience function where possible.Usage of C++11 virtual, override, final keywords: Please follow the C++ Core Guideline C.128. That means, you should only use virtual to declare a new virtual function, override to indicate you are overriding an existing virtual function, and final to prevent any further overriding.
Trivial destructors: Do not write destructors when they are empty and default.
// don't write destructors for A or B like this class A : protected Pointers { public: A(); ~A() override {} }; class B : protected Pointers { public: B(); ~B() override = default; }; // instead, let the compiler create the implicit default destructor by not writing it class A : protected Pointers { public: A(); }; class B : protected Pointers { public: B(); };
Please use clang-format only to reformat files that you have contributed. For header files containing a
SomeStyle(keyword, ClassName)
macros it is required to have this macro embedded with a pair of// clang-format off
,// clang-format on
comments and the line must be terminated with a semicolon (;). Example:#ifdef COMMAND_CLASS // clang-format off CommandStyle(run,Run); // clang-format on #else #ifndef LMP_RUN_H [...]
You may also use
// clang-format on/off
throughout your files to protect individual sections from being reformatted.All files should have 0644 permissions, i.e. writable by the user only and readable by all and no executable permissions. Executable permissions (0755) should only be for shell scripts or python or similar scripts for interpreted script languages.