4.1. LAMMPS source files

The source files of the LAMMPS code are found in two directories of the distribution: src and lib. Most of the code is C++ but there are small numbers of files in several other languages.

The core of the code is located in the src folder and its sub-directories. A sizable number of these files are in the src directory itself, but there are plenty of packages, which can be included or excluded when LAMMPS is built. See the Include packages in build section of the manual for more information about that part of the build process. LAMMPS currently supports building with conventional makefiles and through CMake which differ in how packages are enabled or disabled for a LAMMPS binary. The source files for each package are in all-uppercase sub-directories of the src folder, for example src/MOLECULE or src/USER-MISC. The src/STUBS sub-directory is not a package but contains a dummy MPI library, that is used when building a serial version of the code. The src/MAKE directory contains makefiles with settings and flags for a variety of configuration and machines for the build process with traditional makefiles.

The lib directory contains the source code for several supporting libraries or files with configuration settings to use globally installed libraries, that are required by some of the optional packages. Each sub-directory, like lib/poems or lib/gpu, contains the source files, some of which are in different languages such as Fortran or CUDA. These libraries are linked to during a LAMMPS build, if the corresponding package is installed.

LAMMPS C++ source files almost always come in pairs, such as src/run.cpp (implementation file) and src/run.h (header file). Each pair of files defines a C++ class, for example the LAMMPS_NS::Run class which contains the code invoked by the run command in a LAMMPS input script. As this example illustrates, source file and class names often have a one-to-one correspondence with a command used in a LAMMPS input script. Some source files and classes do not have a corresponding input script command, e.g. src/force.cpp and the LAMMPS_NS::Force class. They are discussed in the next section.

A small number of C++ classes and utility functions are implemented with only a .h file. Examples are the Pointer class or the MathVec functions.

4.2. LAMMPS class topology

Though LAMMPS has a lot of source files and classes, its class topology is relative flat, as outlined in the LAMMPS class topology figure. Each name refers to a class and has a pair of associated source files in the src folder, for example the class LAMMPS_NS::Memory corresponds to the files memory.cpp and memory.h, or the class LAMMPS_NS::AtomVec corresponds to the files atom_vec.cpp and atom_vec.h. Full lines in the figure represent compositing: that is the class to the left holds a pointer to an instance of the class to the right. Dashed lines instead represent inheritance: the class to the right is derived from the class on the left. Classes with a red boundary are not instantiated directly, but they represent the base classes for “styles”. Those “styles” make up the bulk of the LAMMPS code and only a few typical examples are included in the figure for demonstration purposes.

_images/lammps-classes.png

LAMMPS class topology

This figure shows some of the relations of the base classes of the LAMMPS simulation package. Full lines indicate that a class holds an instance of the class it is pointing to; dashed lines point to derived classes that are given as examples of what classes may be instantiated during a LAMMPS run based on the input commands and accessed through the API define by their respective base classes. At the core is the LAMMPS class, which holds pointers to class instances with specific purposes. Those may hold instances of other classes, sometimes directly, or only temporarily, sometimes as derived classes or derived classes or derived classes, which may also hold instances of other classes.

The LAMMPS_NS::LAMMPS class is the topmost class and represents what is referred to an “instance” of LAMMPS. It is a composite holding references to instances of other core classes providing the core functionality of the MD engine in LAMMPS and through them abstractions of the required operations. The constructor of the LAMMPS class will instantiate those instances, process the command line flags, initialize MPI (if not already done) and set up file pointers for input and output. The destructor will shut everything down and free all associated memory. Thus code for the standalone LAMMPS executable in main.cpp simply initializes MPI, instantiates a single instance of LAMMPS, and passes it the command line flags and input script. It deletes the LAMMPS instance after the method reading the input returns and shuts down the MPI environment before it exits the executable.

The LAMMPS_NS::Pointers is not shown in the LAMMPS class topology figure, it holds references to members of the LAMMPS_NS::LAMMPS, so that all classes derived from LAMMPS_NS::Pointers have direct access to those reference. From the class topology all classes with blue boundary are referenced in this class and all classes in the second and third columns, that are not listed as derived classes are instead derived from LAMMPS_NS::Pointers.

Since all storage is encapsulated, the LAMMPS class can also be instantiated multiple times by a calling code, and that can be either simultaneously or consecutively. When running in parallel with MPI, care has to be taken, that suitable communicators are used to not create conflicts between different instances.

The LAMMPS class currently holds instances of 19 classes representing different core functionalities There are a handful of virtual parent classes in LAMMPS that define what LAMMPS calls styles. They are shaded red in the LAMMPS class topology figure. Each of these are parents of a number of child classes that implement the interface defined by the parent class. There are two main categories of these styles: some may only have one instance active at a time (e.g. atom, pair, bond, angle, dihedral, improper, kspace, comm) and there is a dedicated pointer variable in the composite class that manages them. Setups that require a mix of different such styles have to use a hybrid class that manages and forwards calls to the corresponding sub-styles for the designated subset of atoms or data. or the composite class may have lists of class instances, e.g. Modify handles lists of compute and fix styles, while Output handles dumps class instances.

The exception to this scheme are the command style classes. These implement specific commands that can be invoked before, after, or between runs or are commands which launch a simulation. For these an instance of the class is created, its command() method called and then, after completion, the class instance deleted. Examples for this are the create_box, create_atoms, minimize, run, or velocity command styles.

For all those styles certain naming conventions are employed: for the fix nve command the class is called FixNVE and the files are fix_nve.h and fix_nve.cpp. Similarly for fix ave/time we have FixAveTime and fix_ave_time.h and fix_ave_time.cpp. Style names are lower case and without spaces or special characters. A suffix or multiple appended with a forward slash ‘/’ denotes a variant of the corresponding class without the suffix. To connect the style name and the class name, LAMMPS uses macros like the following ATOM_CLASS, PAIR_CLASS, BOND_CLASS, REGION_CLASS, FIX_CLASS, COMPUTE_CLASS, or DUMP_CLASS in the corresponding header file. During compilation files with the pattern style_name.h are created that contain include statements including all headers of all styles of a given type that are currently active (or “installed).

More details on individual classes in the LAMMPS class topology are as follows:

  • The Memory class handles allocation of all large vectors and arrays.

  • The Error class prints all error and warning messages.

  • The Universe class sets up partitions of processors so that multiple simulations can be run, each on a subset of the processors allocated for a run, e.g. by the mpirun command.

  • The Input class reads and processes input input strings and files, stores variables, and invokes commands.

  • As discussed above, command style classes are directly derived from the Pointers class. They provide input script commands that perform one-time operations before/after/between simulations or which invoke a simulation. They are instantiated from within the Input class, invoked, then immediately destructed.

  • The Finish class is instantiated to print statistics to the screen after a simulation is performed, by commands like run and minimize.

  • The Special class walks the bond topology of a molecular system to find first, second, third neighbors of each atom. It is invoked by several commands, like read_data, read_restart, or replicate.

  • The Atom class stores per-atom properties associated with atom styles. More precisely, they are allocated and managed by a class derived from the AtomVec class, and the Atom class simply stores pointers to them. The classes derived from AtomVec represent the different atom styles and they are instantiated through the atom_style command.

  • The Update class holds instances of an integrator and a minimizer class. The Integrate class is a parent style for the Verlet and r-RESPA time integrators, as defined by the run_style command. The Min class is a parent style for various energy minimizers.

  • The Neighbor class builds and stores neighbor lists. The NeighList class stores a single list (for all atoms). A NeighRequest class instance is created by pair, fix, or compute styles when they need a particular kind of neighbor list and use the NeighRequest properties to select the neighbor list settings for the given request. There can be multiple instances of the NeighRequest class and the Neighbor class will try to optimize how they are computed by creating copies or sub-lists where possible.

  • The Comm class performs inter-processor communication, typically of ghost atom information. This usually involves MPI message exchanges with 6 neighboring processors in the 3d logical grid of processors mapped to the simulation box. There are two communication styles enabling different ways to do the domain decomposition. Sometimes the Irregular class is used, when atoms may migrate to arbitrary processors.

  • The Domain class stores the simulation box geometry, as well as geometric Regions and any user definition of a Lattice. The latter are defined by the region and lattice commands in an input script.

  • The Force class computes various forces between atoms. The Pair parent class is for non-bonded or pair-wise forces, which in LAMMPS also includes many-body forces such as the Tersoff 3-body potential if those are computed by walking pairwise neighbor lists. The Bond, Angle, Dihedral, Improper parent classes are styles for bonded interactions within a static molecular topology. The KSpace parent class is for computing long-range Coulombic interactions. One of its child classes, PPPM, uses the FFT3D and Remap classes to redistribute and communicate grid-based information across the parallel processors.

  • The Modify class stores lists of class instances derived from the Fix and Compute base classes.

  • The Group class manipulates groups that atoms are assigned to via the group command. It also has functions to compute various attributes of groups of atoms.

  • The Output class is used to generate 3 kinds of output from a LAMMPS simulation: thermodynamic information printed to the screen and log file, dump file snapshots, and restart files. These correspond to the Thermo, Dump, and WriteRestart classes respectively. The Dump class is a base class with several derived classes implementing various dump style variants.

  • The Timer class logs timing information, output at the end of a run.