Project 2 - Modernize legacy code in LAMMPS to use newer internal APIs
Overview and Motivation
Over the last 2-3 years a lot of internal refactoring in LAMMPS has happened (and more is to come). This is related to the desire to benefit more from modern C++ (LAMMPS now requires C++11) where it can help to make code simpler, more effective, more readable and more maintainable.
In part this is needed due to how LAMMPS has evolved since it was started in 1995. It was first written in Fortran 77, then Fortran 90 and then converted to C++ (but actually more to “C with classes”) and we are now gently updating it to C++11. In some cases the data structure layout and flow of control still very much resembles the programming style required for the Fortran versions. This is particularly visible when code accesses (and modifies) internal data structures like lists of class instances maintained by a class. Such accesses and manipulations are contrary to the desire to “encapsulate” implementations from the programming interface and can cause inconsistent behavior (e.g. when new features are added requiring additional operations that legacy code is unaware of).
Unlike the previous transitions this is gradual and we can have transition periods where the legacy and the new APIs can be mixed. Thus we have often multiple variants that can do the same thing but use a different approach.
To modernize the code, we have for example implemented alternate APIs
with a more consistent naming scheme and that can return a pointer (or a
vector of pointers) instead of an index into the internal data
structure/list. Also, we have created custom classes specialized
for parsing text and specifically reading (potential) files.
For complex string operations we depend more on the standard C++
string class and provide a bunch of utility functions. Another
example are functions that need to pass a list of arguments. For
those we have created overloads that just take one long string as
argument (and create the required list internally) where the string
can often be conveniently composed using the std::string
class
and/or the fmt::format()
function.
Tasks
- Replace
Modify::find_fix*()
andModify::find_compute*()
with modernized APIs as described in GitHub Issue #2870. Loops counting the number of styles of the same name can often be converted into a single line. - Improve string operations by converting from C-style strings to C++
style strings. Note that this is not always advisable or requires
additional changes. Text parsers using
strtok()
orstrstr()
or*scanf()
should be rewritten to use tokenizer classes or file reader classes or both. String comparisons the look for style names (e.g. to flag incompatibilities) should be converted to use regex search with utils::strmatch(). Copies can often be done more easily with utils::strdup() - Replace
#define NAME value
withstatic constexpr type NAME = value;
Specifically pair style classes for long-range Coulomb should import the constants in theewald_const.h
header. - Replace iostreams for files with C-style stdio functions (those two
should not be mixed and LAMMPS has chosen to use stdio).
Stringstreams should be replaced with
fmt::format()
or the Tokenizer/ValueTokenizer class. Logging output should useutils::logmesg()
and not explicitly done withfprintf()
.
Examples
Many available APIs and some examples are listed and described in the manual in the Information for Developers section.